PAPI  5.3.0.0
linux-infiniband.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00023 #include <dlfcn.h>
00024 
00025 #include "papi.h"
00026 #include "papi_internal.h"
00027 #include "papi_vector.h"
00028 #include "papi_memory.h"
00029 
00030 #include "linux-infiniband.h"
00031 
00032 void (*_dl_non_dynamic_init)(void) __attribute__((weak));
00033 
00034 /********  CHANGE PROTOTYPES TO DECLARE Infiniband LIBRARY SYMBOLS AS WEAK  **********
00035  *  This is done so that a version of PAPI built with the infiniband component can   *
00036  *  be installed on a system which does not have the infiniband libraries installed. *
00037  *                                                                                   *
00038  *  If this is done without these prototypes, then all papi services on the system   *
00039  *  without the infiniband libraries installed will fail.  The PAPI libraries        *
00040  *  contain references to the infiniband libraries which are not installed.  The     *
00041  *  load of PAPI commands fails because the infiniband library references can not    *
00042  *  be resolved.                                                                     *
00043  *                                                                                   *
00044  *  This also defines pointers to the infiniband library functions that we call.     *
00045  *  These function pointers will be resolved with dlopen/dlsym calls at component    *
00046  *  initialization time.  The component then calls the infiniband library functions  *
00047  *  through these function pointers.                                                 *
00048  *************************************************************************************/
00049 int                 __attribute__((weak)) umad_init              ( void );
00050 int                 __attribute__((weak)) umad_get_cas_names     ( char [][UMAD_CA_NAME_LEN], int  );
00051 int                 __attribute__((weak)) umad_get_ca            ( char *, umad_ca_t * );
00052 void                __attribute__((weak)) mad_decode_field       ( unsigned char *, enum MAD_FIELDS, void *);
00053 struct ibmad_port * __attribute__((weak)) mad_rpc_open_port      ( char *, int, int *, int );
00054 int                 __attribute__((weak)) ib_resolve_self_via    ( ib_portid_t *, int *, ibmad_gid_t *, const struct ibmad_port * );
00055 uint8_t *           __attribute__((weak)) performance_reset_via  ( void *, ib_portid_t *, int, unsigned, unsigned, unsigned, const struct ibmad_port * );
00056 uint8_t *           __attribute__((weak)) pma_query_via          ( void *, ib_portid_t *, int, unsigned, unsigned, const struct ibmad_port * );
00057 
00058 int                  (*umad_initPtr)             ( void );
00059 int                  (*umad_get_cas_namesPtr)    ( char [][UMAD_CA_NAME_LEN], int );
00060 int                  (*umad_get_caPtr)           ( char *, umad_ca_t * );
00061 void                 (*mad_decode_fieldPtr)      ( unsigned char *, enum MAD_FIELDS, void * );
00062 struct ibmad_port *  (*mad_rpc_open_portPtr)     ( char *, int, int *, int );
00063 int                  (*ib_resolve_self_viaPtr)   (ib_portid_t *, int *, ibmad_gid_t *, const struct ibmad_port * );
00064 uint8_t *            (*performance_reset_viaPtr) (void *, ib_portid_t *, int, unsigned, unsigned, unsigned, const struct ibmad_port * );
00065 uint8_t *            (*pma_query_viaPtr)         (void *, ib_portid_t *, int, unsigned, unsigned, const struct ibmad_port * );
00066 
00067 // file handles used to access Infiniband libraries with dlopen
00068 static void* dl1 = NULL;
00069 static void* dl2 = NULL;
00070 
00071 static int linkInfinibandLibraries ();
00072 
00073 papi_vector_t _infiniband_vector;
00074 
00075 
00076 
00077 struct ibmad_port *srcport;
00078 static ib_portid_t portid;
00079 static int ib_timeout = 0;
00080 static int ibportnum = 0;
00081 
00082 static counter_info *subscriptions[INFINIBAND_MAX_COUNTERS];
00083 static int is_initialized = 0;
00084 static int num_counters = 0;
00085 static int is_finalized = 0;
00086 
00087 /* counters are kept in a list */
00088 static counter_info *root_counter = NULL;
00089 /* IB ports found are kept in a list */
00090 static ib_port *root_ib_port = NULL;
00091 static ib_port *active_ib_port = NULL;
00092 
00093 #define infiniband_native_table subscriptions
00094 /* macro to initialize entire structs to 0 */
00095 #define InitStruct(var, type) type var; memset(&var, 0, sizeof(type))
00096 
00097 long long _papi_hwd_infiniband_register_start[INFINIBAND_MAX_COUNTERS];
00098 long long _papi_hwd_infiniband_register[INFINIBAND_MAX_COUNTERS];
00099 
00100 
00101 /*******************************************************************************
00102  ********  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT *********
00103  ******************************************************************************/
00104 
00108 static void
00109 init_ib_counter(  )
00110 {
00111     char names[20][UMAD_CA_NAME_LEN];
00112     int n, i;
00113     char *ca_name;
00114     umad_ca_t ca;
00115     int r;
00116     int portnum;
00117 
00118 //  if ( umad_init(  ) < 0 ) {
00119 //      fprintf( stderr, "can't init UMAD library\n" );
00120 //      exit( 1 );
00121 //  }
00122 
00123     if ( ( n = (*umad_get_cas_namesPtr)( ( void * ) names, UMAD_CA_NAME_LEN ) ) < 0 ) {
00124         fprintf( stderr, "can't list IB device names\n" );
00125         exit( 1 );
00126     }
00127 
00128     for ( i = 0; i < n; i++ ) {
00129         ca_name = names[i];
00130 
00131         if ( ( r = (*umad_get_caPtr)( ca_name, &ca ) ) < 0 ) {
00132             fprintf( stderr, "can't read ca from IB device\n" );
00133             exit( 1 );
00134         }
00135 
00136         if ( !ca.node_type )
00137             continue;
00138 
00139         /* port numbers are '1' based in OFED */
00140         for ( portnum = 1; portnum <= ca.numports; portnum++ )
00141             addIBPort( ca.ca_name, ca.ports[portnum] );
00142     }
00143 }
00144 
00145 
00152 static counter_info *
00153 addCounter( const char *name, const char *desc, const char *unit )
00154 {
00155     counter_info *cntr, *last;
00156 
00157     cntr = ( counter_info * ) malloc( sizeof ( counter_info ) );
00158     if ( cntr == NULL ) {
00159         fprintf( stderr, "can not allocate memory for new counter\n" );
00160         exit( 1 );
00161     }
00162     cntr->name = strdup( name );
00163     cntr->description = strdup( desc );
00164     cntr->unit = strdup( unit );
00165     cntr->value = 0;
00166     cntr->next = NULL;
00167 
00168     if ( root_counter == NULL ) {
00169         root_counter = cntr;
00170     } else {
00171         last = root_counter;
00172         while ( last->next != NULL )
00173             last = last->next;
00174         last->next = cntr;
00175     }
00176 
00177     return cntr;
00178 }
00179 
00180 
00185 static void
00186 addIBPort( const char *ca_name, umad_port_t * port )
00187 {
00188     ib_port *nwif, *last;
00189     char counter_name[512];
00190 
00191     nwif = ( ib_port * ) malloc( sizeof ( ib_port ) );
00192 
00193     if ( nwif == NULL ) {
00194         fprintf( stderr, "can not allocate memory for IB port description\n" );
00195         exit( 1 );
00196     }
00197 
00198     sprintf( counter_name, "%s_%d", ca_name, port->portnum );
00199     nwif->name = strdup( counter_name );
00200 
00201     sprintf( counter_name, "%s_%d_recv", ca_name, port->portnum );
00202     nwif->recv_cntr =
00203         addCounter( counter_name, "bytes received on this IB port", "bytes" );
00204 
00205     sprintf( counter_name, "%s_%d_send", ca_name, port->portnum );
00206     nwif->send_cntr =
00207         addCounter( counter_name, "bytes written to this IB port", "bytes" );
00208 
00209     nwif->port_rate = port->rate;
00210     nwif->is_initialized = 0;
00211     nwif->port_number = port->portnum;
00212     nwif->next = NULL;
00213 
00214     num_counters += 2;
00215 
00216     if ( root_ib_port == NULL ) {
00217         root_ib_port = nwif;
00218     } else {
00219         last = root_ib_port;
00220         while ( last->next != NULL )
00221             last = last->next;
00222         last->next = nwif;
00223     }
00224 }
00225 
00226 
00230 static int
00231 init_ib_port( ib_port * portdata )
00232 {
00233     int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS,
00234         IB_PERFORMANCE_CLASS
00235     };
00236     char *ca = 0;
00237     static uint8_t pc[1024];
00238     int mask = 0xFFFF;
00239 
00240     srcport = (*mad_rpc_open_portPtr)( ca, portdata->port_number, mgmt_classes, 4 );
00241     if ( !srcport ) {
00242         fprintf( stderr, "Failed to open '%s' port '%d'\n", ca,
00243                  portdata->port_number );
00244         exit( 1 );
00245     }
00246 
00247     if ( (*ib_resolve_self_viaPtr)( &portid, &ibportnum, 0, srcport ) < 0 ) {
00248         fprintf( stderr, "can't resolve self port\n" );
00249         exit( 1 );
00250     }
00251 
00252     /* PerfMgt ClassPortInfo is a required attribute */
00253     /* might be redundant, could be left out for fast implementation */
00254     if ( !(*pma_query_viaPtr) ( pc, &portid, ibportnum, ib_timeout, CLASS_PORT_INFO, srcport ) ) {
00255         fprintf( stderr, "classportinfo query\n" );
00256         exit( 1 );
00257     }
00258 
00259     if ( !(*performance_reset_viaPtr) ( pc, &portid, ibportnum, mask, ib_timeout, IB_GSI_PORT_COUNTERS, srcport ) ) {
00260         fprintf( stderr, "perf reset\n" );
00261         exit( 1 );
00262     }
00263 
00264     /* read the initial values */
00265     (*mad_decode_fieldPtr)( pc, IB_PC_XMT_BYTES_F, &portdata->last_send_val );
00266     portdata->sum_send_val = 0;
00267     (*mad_decode_fieldPtr)( pc, IB_PC_RCV_BYTES_F, &portdata->last_recv_val );
00268     portdata->sum_recv_val = 0;
00269 
00270     portdata->is_initialized = 1;
00271 
00272     return 0;
00273 }
00274 
00275 
00279 static int
00280 read_ib_counter(  )
00281 {
00282     uint32_t send_val;
00283     uint32_t recv_val;
00284     uint8_t pc[1024];
00285     /* 32 bit counter FFFFFFFF */
00286     uint32_t max_val = 4294967295;
00287     /* if it is bigger than this -> reset */
00288     uint32_t reset_limit = max_val * 0.7;
00289     int mask = 0xFFFF;
00290 
00291     if ( active_ib_port == NULL )
00292         return 0;
00293 
00294     /* reading cost ~70 mirco secs */
00295     if ( !(*pma_query_viaPtr) ( pc, &portid, ibportnum, ib_timeout, IB_GSI_PORT_COUNTERS, srcport ) ) {
00296         fprintf( stderr, "perfquery\n" );
00297         exit( 1 );
00298     }
00299 
00300     (*mad_decode_fieldPtr)( pc, IB_PC_XMT_BYTES_F, &send_val );
00301     (*mad_decode_fieldPtr)( pc, IB_PC_RCV_BYTES_F, &recv_val );
00302 
00303     /* multiply the numbers read by 4 as the IB port counters are not
00304        counting bytes. they always count 32dwords. see man page of
00305        perfquery for details
00306        internally a uint64_t ia used to sum up the values */
00307     active_ib_port->sum_send_val +=
00308         ( send_val - active_ib_port->last_send_val ) * 4;
00309     active_ib_port->sum_recv_val +=
00310         ( recv_val - active_ib_port->last_recv_val ) * 4;
00311 
00312     active_ib_port->send_cntr->value = active_ib_port->sum_send_val;
00313     active_ib_port->recv_cntr->value = active_ib_port->sum_recv_val;
00314 
00315     if ( send_val > reset_limit || recv_val > reset_limit ) {
00316         /* reset cost ~70 mirco secs */
00317         if ( !(*performance_reset_viaPtr) ( pc, &portid, ibportnum, mask, ib_timeout, IB_GSI_PORT_COUNTERS, srcport ) ) {
00318             fprintf( stderr, "perf reset\n" );
00319             exit( 1 );
00320         }
00321 
00322         (*mad_decode_fieldPtr)( pc, IB_PC_XMT_BYTES_F, &active_ib_port->last_send_val );
00323         (*mad_decode_fieldPtr)( pc, IB_PC_RCV_BYTES_F, &active_ib_port->last_recv_val );
00324     } else {
00325         active_ib_port->last_send_val = send_val;
00326         active_ib_port->last_recv_val = recv_val;
00327     }
00328 
00329     return 0;
00330 }
00331 
00332 
00333 void
00334 host_read_values( long long *data )
00335 {
00336     int loop;
00337 
00338     read_ib_counter(  );
00339 
00340     for ( loop = 0; loop < INFINIBAND_MAX_COUNTERS; loop++ ) {
00341         if ( subscriptions[loop] == NULL )
00342             break;
00343 
00344         data[loop] = subscriptions[loop]->value;
00345     }
00346 }
00347 
00348 
00352 static counter_info *
00353 counterFromName( const char *cntr )
00354 {
00355     int loop = 0;
00356     char tmp[512];
00357     counter_info *local_cntr = root_counter;
00358 
00359     while ( local_cntr != NULL ) {
00360         if ( strcmp( cntr, local_cntr->name ) == 0 )
00361             return local_cntr;
00362 
00363         local_cntr = local_cntr->next;
00364         loop++;
00365     }
00366 
00367     gethostname( tmp, 512 );
00368     fprintf( stderr, "can not find host counter: %s on %s\n", cntr, tmp );
00369     fprintf( stderr, "we only have: " );
00370     local_cntr = root_counter;
00371 
00372     while ( local_cntr != NULL ) {
00373         fprintf( stderr, "'%s' ", local_cntr->name );
00374         local_cntr = local_cntr->next;
00375         loop++;
00376     }
00377 
00378     fprintf( stderr, "\n" );
00379     exit( 1 );
00380     /* never reached */
00381     return 0;
00382 }
00383 
00384 
00388 static uint64_t
00389 host_subscribe( const char *cntr )
00390 {
00391     int loop;
00392     int len;
00393     char tmp_name[512];
00394     ib_port *aktp;
00395 
00396     counter_info *counter = counterFromName( cntr );
00397 
00398     for ( loop = 0; loop < INFINIBAND_MAX_COUNTERS; loop++ ) {
00399         if ( subscriptions[loop] == NULL ) {
00400             subscriptions[loop] = counter;
00401             counter->idx = loop;
00402 
00403             /* we have an IB counter if the name ends with _send or _recv and
00404                the prefix before that is in the ib_port list */
00405             if ( ( len = strlen( cntr ) ) > 5 ) {
00406                 if ( strcmp( &cntr[len - 5], "_recv" ) == 0 ||
00407                      strcmp( &cntr[len - 5], "_send" ) == 0 ) {
00408                     /* look through all IB_counters */
00409                     strncpy( tmp_name, cntr, len - 5 );
00410                     tmp_name[len - 5] = 0;
00411                     aktp = root_ib_port;
00412                     // printf("looking for IB port '%s'\n", tmp_name);
00413                     while ( aktp != NULL ) {
00414                         if ( strcmp( aktp->name, tmp_name ) == 0 ) {
00415                             if ( !aktp->is_initialized ) {
00416                                 init_ib_port( aktp );
00417                                 active_ib_port = aktp;
00418                             }
00419                             return loop + 1;
00420                         }
00421                         /* name does not match, if this counter is
00422                            initialized, we can't have two active IB ports */
00423                         if ( aktp->is_initialized ) {
00424 #if 0   /* not necessary with OFED version >= 1.4 */
00425                             fprintf( stderr,
00426                                      "unable to activate IB port monitoring for more than one port\n" );
00427                             exit( 1 );
00428 #endif
00429                         }
00430                         aktp = aktp->next;
00431                     }
00432                 }
00433             }
00434             return loop + 1;
00435         }
00436     }
00437     fprintf( stderr, "please subscribe only once to each counter\n" );
00438     exit( 1 );
00439     /* never reached */
00440     return 0;
00441 }
00442 
00443 
00447 static string_list *
00448 host_listCounter( int num_counters1 )
00449 {
00450     string_list *list;
00451     counter_info *cntr = root_counter;
00452 
00453     list = malloc( sizeof ( string_list ) );
00454     if ( list == NULL ) {
00455         fprintf( stderr, "unable to allocate memory for new string_list" );
00456         exit( 1 );
00457     }
00458     list->count = 0;
00459     list->data = ( char ** ) malloc( num_counters1 * sizeof ( char * ) );
00460 
00461     if ( list->data == NULL ) {
00462         fprintf( stderr,
00463                  "unable to allocate memory for %d pointers in a new string_list\n",
00464                  num_counters1 );
00465         exit( 1 );
00466     }
00467 
00468     while ( cntr != NULL ) {
00469         list->data[list->count++] = strdup( cntr->name );
00470         cntr = cntr->next;
00471     }
00472 
00473     return list;
00474 }
00475 
00476 
00480 static void
00481 host_finalize(  )
00482 {
00483     counter_info *cntr, *next;
00484 
00485     if ( is_finalized )
00486         return;
00487 
00488     cntr = root_counter;
00489 
00490     while ( cntr != NULL ) {
00491         next = cntr->next;
00492         free( cntr->name );
00493         free( cntr->description );
00494         free( cntr->unit );
00495         free( cntr );
00496         cntr = next;
00497     }
00498 
00499     root_counter = NULL;
00500 
00501     is_finalized = 1;
00502 }
00503 
00504 
00508 static void
00509 host_deleteStringList( string_list * to_delete )
00510 {
00511     int loop;
00512 
00513     if ( to_delete->data != NULL ) {
00514         for ( loop = 0; loop < to_delete->count; loop++ )
00515             free( to_delete->data[loop] );
00516 
00517         free( to_delete->data );
00518     }
00519 
00520     free( to_delete );
00521 }
00522 
00523 
00524 /*****************************************************************************
00525  *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
00526  *****************************************************************************/
00527 
00528 /*
00529  * This is called whenever a thread is initialized
00530  */
00531 int
00532 INFINIBAND_init_thread( hwd_context_t * ctx )
00533 {
00534     string_list *counter_list = NULL;
00535     int i;
00536     int loop;
00537 
00538     /* initialize portid struct of type ib_portid_t to 0 */
00539     InitStruct( portid, ib_portid_t );
00540 
00541     if ( is_initialized )
00542         return PAPI_OK;
00543 
00544     is_initialized = 1;
00545 
00546     init_ib_counter(  );
00547 
00548     for ( loop = 0; loop < INFINIBAND_MAX_COUNTERS; loop++ )
00549         subscriptions[loop] = NULL;
00550 
00551     counter_list = host_listCounter( num_counters );
00552 
00553     for ( i = 0; i < counter_list->count; i++ )
00554         host_subscribe( counter_list->data[i] );
00555 
00556     ( ( INFINIBAND_context_t * ) ctx )->state.ncounter = counter_list->count;
00557 
00558     host_deleteStringList( counter_list );
00559 
00560     return PAPI_OK;
00561 }
00562 
00563 
00564 /* Initialize hardware counters, setup the function vector table
00565  * and get hardware information, this routine is called when the 
00566  * PAPI process is initialized (IE PAPI_library_init)
00567  */
00568 int
00569 INFINIBAND_init_component( int cidx )
00570 {
00571     SUBDBG ("Entry: cidx: %d\n", cidx);
00572     int i;
00573 
00574     /* link in all the infiniband libraries and resolve the symbols we need to use */
00575     if (linkInfinibandLibraries() != PAPI_OK) {
00576         SUBDBG ("Dynamic link of Infiniband libraries failed, component will be disabled.\n");
00577         SUBDBG ("See disable reason in papi_component_avail output for more details.\n");
00578         return (PAPI_ENOSUPP);
00579     }
00580 
00581     /* make sure that the infiniband library finds the kernel module loaded. */
00582     if ( (*umad_initPtr)(  ) < 0 ) {
00583         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Call to initialize umad library failed.",PAPI_MAX_STR_LEN);
00584         return ( PAPI_ENOSUPP );
00585     }
00586 
00587     for ( i = 0; i < INFINIBAND_MAX_COUNTERS; i++ ) {
00588         _papi_hwd_infiniband_register_start[i] = -1;
00589         _papi_hwd_infiniband_register[i] = -1;
00590     }
00591 
00592     /* Export the component id */
00593     _infiniband_vector.cmp_info.CmpIdx = cidx;
00594 
00595     return ( PAPI_OK );
00596 }
00597 
00598 
00599 /*
00600  * Link the necessary Infiniband libraries to use the Infiniband component.  If any of them can not be found, then
00601  * the Infiniband component will just be disabled.  This is done at runtime so that a version of PAPI built
00602  * with the Infiniband component can be installed and used on systems which have the Infiniband libraries installed
00603  * and on systems where these libraries are not installed.
00604  */
00605 static int
00606 linkInfinibandLibraries ()
00607 {
00608     /* Attempt to guess if we were statically linked to libc, if so bail */
00609     if ( _dl_non_dynamic_init != NULL ) {
00610         strncpy(_infiniband_vector.cmp_info.disabled_reason, "The Infiniband component does not support statically linking of libc.", PAPI_MAX_STR_LEN);
00611         return PAPI_ENOSUPP;
00612     }
00613 
00614     /* Need to link in the Infiniband libraries, if not found disable the component */
00615     dl1 = dlopen("libibumad.so", RTLD_NOW | RTLD_GLOBAL);
00616     if (!dl1)
00617     {
00618         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband library libibumad.so not found.",PAPI_MAX_STR_LEN);
00619         return ( PAPI_ENOSUPP );
00620     }
00621     umad_initPtr = dlsym(dl1, "umad_init");
00622     if (dlerror() != NULL)
00623     {
00624         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function umad_init not found.",PAPI_MAX_STR_LEN);
00625         return ( PAPI_ENOSUPP );
00626     }
00627     umad_get_cas_namesPtr = dlsym(dl1, "umad_get_cas_names");
00628     if (dlerror() != NULL)
00629     {
00630         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function umad_get_cas_names not found.",PAPI_MAX_STR_LEN);
00631         return ( PAPI_ENOSUPP );
00632     }
00633     umad_get_caPtr = dlsym(dl1, "umad_get_ca");
00634     if (dlerror() != NULL)
00635     {
00636         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function umad_get_ca not found.",PAPI_MAX_STR_LEN);
00637         return ( PAPI_ENOSUPP );
00638     }
00639 
00640     /* Need to link in the Infiniband libraries, if not found disable the component */
00641     dl2 = dlopen("libibmad.so", RTLD_NOW | RTLD_GLOBAL);
00642     if (!dl2)
00643     {
00644         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband library libibmad.so not found.",PAPI_MAX_STR_LEN);
00645         return ( PAPI_ENOSUPP );
00646     }
00647     mad_decode_fieldPtr = dlsym(dl2, "mad_decode_field");
00648     if (dlerror() != NULL)
00649     {
00650         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function mad_decode_field not found.",PAPI_MAX_STR_LEN);
00651         return ( PAPI_ENOSUPP );
00652     }
00653     mad_rpc_open_portPtr = dlsym(dl2, "mad_rpc_open_port");
00654     if (dlerror() != NULL)
00655     {
00656         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function mad_rpc_open_port not found.",PAPI_MAX_STR_LEN);
00657         return ( PAPI_ENOSUPP );
00658     }
00659     ib_resolve_self_viaPtr = dlsym(dl2, "ib_resolve_self_via");
00660     if (dlerror() != NULL)
00661     {
00662         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function ib_resolve_self_via not found.",PAPI_MAX_STR_LEN);
00663         return ( PAPI_ENOSUPP );
00664     }
00665     performance_reset_viaPtr = dlsym(dl2, "performance_reset_via");
00666     if (dlerror() != NULL)
00667     {
00668         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function performance_reset_via not found.",PAPI_MAX_STR_LEN);
00669         return ( PAPI_ENOSUPP );
00670     }
00671     pma_query_viaPtr = dlsym(dl2, "pma_query_via");
00672     if (dlerror() != NULL)
00673     {
00674         strncpy(_infiniband_vector.cmp_info.disabled_reason, "Infiniband function pma_query_via not found.",PAPI_MAX_STR_LEN);
00675         return ( PAPI_ENOSUPP );
00676     }
00677 
00678     return ( PAPI_OK );
00679 }
00680 
00681 
00682 /*
00683  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00684  * functions
00685  */
00686 int
00687 INFINIBAND_init_control_state( hwd_control_state_t * ctrl )
00688 {
00689     ( void ) ctrl;
00690     return PAPI_OK;
00691 }
00692 
00693 
00694 /*
00695  *
00696  */
00697 int
00698 INFINIBAND_start( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00699 {
00700     ( void ) ctx;
00701     ( void ) ctrl;
00702 
00703     host_read_values( _papi_hwd_infiniband_register_start );
00704 
00705     memcpy( _papi_hwd_infiniband_register, _papi_hwd_infiniband_register_start,
00706             INFINIBAND_MAX_COUNTERS * sizeof ( long long ) );
00707 
00708     return ( PAPI_OK );
00709 }
00710 
00711 
00712 /*
00713  *
00714  */
00715 int
00716 INFINIBAND_stop( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00717 {
00718     int i;
00719     ( void ) ctx;
00720 
00721     host_read_values( _papi_hwd_infiniband_register );
00722 
00723     for ( i = 0; i < ( ( INFINIBAND_context_t * ) ctx )->state.ncounter; i++ ) {
00724         ( ( INFINIBAND_control_state_t * ) ctrl )->counts[i] =
00725             _papi_hwd_infiniband_register[i] -
00726             _papi_hwd_infiniband_register_start[i];
00727     }
00728 
00729     return ( PAPI_OK );
00730 }
00731 
00732 
00733 /*
00734  *
00735  */
00736 int
00737 INFINIBAND_read( hwd_context_t * ctx, hwd_control_state_t * ctrl,
00738                  long_long ** events, int flags )
00739 {
00740     int i;
00741     ( void ) flags;
00742 
00743     host_read_values( _papi_hwd_infiniband_register );
00744 
00745     for ( i = 0; i < ( ( INFINIBAND_context_t * ) ctx )->state.ncounter; i++ ) {
00746         ( ( INFINIBAND_control_state_t * ) ctrl )->counts[i] =
00747             _papi_hwd_infiniband_register[i] -
00748             _papi_hwd_infiniband_register_start[i];
00749     }
00750 
00751     *events = ( ( INFINIBAND_control_state_t * ) ctrl )->counts;
00752     return ( PAPI_OK );
00753 }
00754 
00755 
00756 /*
00757  *
00758  */
00759 int
00760 INFINIBAND_shutdown_thread( hwd_context_t * ctx )
00761 {
00762     ( void ) ctx;
00763     host_finalize(  );
00764     return ( PAPI_OK );
00765 }
00766 
00767 
00768 /*
00769  *
00770  */
00771 int
00772 INFINIBAND_shutdown_component( void )
00773 {
00774     // close the dynamic libraries needed by this component (opened in the init substrate call)
00775     dlclose(dl1);
00776     dlclose(dl2);
00777 
00778     return ( PAPI_OK );
00779 }
00780 
00781 
00782 /* This function sets various options in the component
00783  * The valid codes being passed in are PAPI_SET_DEFDOM,
00784  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00785  */
00786 int
00787 INFINIBAND_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00788 {
00789     ( void ) ctx;
00790     ( void ) code;
00791     ( void ) option;
00792     return ( PAPI_OK );
00793 }
00794 
00795 
00796 //int INFINIBAND_ntv_code_to_bits ( unsigned int EventCode, hwd_register_t * bits );
00797 
00798 
00799 /*
00800  *
00801  */
00802 int
00803 INFINIBAND_update_control_state( hwd_control_state_t * ptr,
00804                                  NativeInfo_t * native, int count,
00805                                  hwd_context_t * ctx )
00806 {
00807     ( void ) ptr;
00808     ( void ) ctx;
00809     int i, index;
00810 
00811     for ( i = 0; i < count; i++ ) {
00812         index = native[i].ni_event;
00813         native[i].ni_position = index;
00814     }
00815 
00816     return ( PAPI_OK );
00817 }
00818 
00819 
00820 /*
00821  * This function has to set the bits needed to count different domains
00822  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00823  * By default return PAPI_EINVAL if none of those are specified
00824  * and PAPI_OK with success
00825  * PAPI_DOM_USER is only user context is counted
00826  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00827  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00828  * PAPI_DOM_ALL   is all of the domains
00829  */
00830 int
00831 INFINIBAND_set_domain( hwd_control_state_t * cntrl, int domain )
00832 {
00833     int found = 0;
00834     ( void ) cntrl;
00835 
00836     if ( PAPI_DOM_USER & domain )
00837         found = 1;
00838 
00839     if ( PAPI_DOM_KERNEL & domain )
00840         found = 1;
00841 
00842     if ( PAPI_DOM_OTHER & domain )
00843         found = 1;
00844 
00845     if ( !found )
00846         return ( PAPI_EINVAL );
00847 
00848     return ( PAPI_OK );
00849 }
00850 
00851 
00852 /*
00853  *
00854  */
00855 int
00856 INFINIBAND_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00857 {
00858     INFINIBAND_start( ctx, ctrl );
00859     return ( PAPI_OK );
00860 }
00861 
00862 
00863 /*
00864  * Native Event functions
00865  */
00866 int
00867 INFINIBAND_ntv_enum_events( unsigned int *EventCode, int modifier )
00868 {
00869     if ( modifier == PAPI_ENUM_FIRST ) {
00870         *EventCode = 0;
00871         return PAPI_OK;
00872     }
00873 
00874     if ( modifier == PAPI_ENUM_EVENTS ) {
00875         int index = *EventCode;
00876 
00877         if ( infiniband_native_table[index + 1] ) {
00878             *EventCode = *EventCode + 1;
00879             return ( PAPI_OK );
00880         } else
00881             return ( PAPI_ENOEVNT );
00882     } else
00883         return ( PAPI_EINVAL );
00884 }
00885 
00886 
00887 /*
00888  *
00889  */
00890 int
00891 INFINIBAND_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00892 {
00893     strncpy( name, infiniband_native_table[EventCode]->name, len );
00894 
00895     return PAPI_OK;
00896 }
00897 
00898 
00899 /*
00900  *
00901  */
00902 int
00903 INFINIBAND_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00904 {
00905     strncpy( name, infiniband_native_table[EventCode]->description, len );
00906 
00907     return PAPI_OK;
00908 }
00909 
00910 
00911 /*
00912  *
00913  */
00914 int
00915 INFINIBAND_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
00916 {
00917     memcpy( ( INFINIBAND_register_t * ) bits,
00918             infiniband_native_table[EventCode],
00919             sizeof ( INFINIBAND_register_t ) );
00920 
00921     return PAPI_OK;
00922 }
00923 
00924 
00925 /*
00926  *
00927  */
00928 papi_vector_t _infiniband_vector = {
00929     .cmp_info = {
00930                  /* default component information (unspecified values are initialized to 0) */
00931                  .name ="infiniband",
00932                  .short_name="infiniband",
00933                  .version = "4.2.1",
00934                  .description = "Infiniband statistics",
00935                  .num_mpx_cntrs = INFINIBAND_MAX_COUNTERS,
00936                  .num_cntrs = INFINIBAND_MAX_COUNTERS,
00937                  .default_domain = PAPI_DOM_USER,
00938                  .available_domains = PAPI_DOM_USER,
00939                  .default_granularity = PAPI_GRN_THR,
00940                  .available_granularities = PAPI_GRN_THR,
00941                  .hardware_intr_sig = PAPI_INT_SIGNAL,
00942 
00943                  /* component specific cmp_info initializations */
00944                  .fast_real_timer = 0,
00945                  .fast_virtual_timer = 0,
00946                  .attach = 0,
00947                  .attach_must_ptrace = 0,
00948                  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00949                  }
00950     ,
00951 
00952     /* sizes of framework-opaque component-private structures */
00953     .size = {
00954              .context = sizeof ( INFINIBAND_context_t ),
00955              .control_state = sizeof ( INFINIBAND_control_state_t ),
00956              .reg_value = sizeof ( INFINIBAND_register_t ),
00957              .reg_alloc = sizeof ( INFINIBAND_reg_alloc_t ),
00958              }
00959     ,
00960     /* function pointers in this component */
00961     .init_thread = INFINIBAND_init_thread,
00962     .init_component = INFINIBAND_init_component,
00963     .init_control_state = INFINIBAND_init_control_state,
00964     .start = INFINIBAND_start,
00965     .stop = INFINIBAND_stop,
00966     .read = INFINIBAND_read,
00967     .shutdown_component = INFINIBAND_shutdown_component,
00968     .shutdown_thread = INFINIBAND_shutdown_thread,
00969     .ctl = INFINIBAND_ctl,
00970 
00971     .update_control_state = INFINIBAND_update_control_state,
00972     .set_domain = INFINIBAND_set_domain,
00973     .reset = INFINIBAND_reset,
00974 
00975     .ntv_enum_events = INFINIBAND_ntv_enum_events,
00976     .ntv_code_to_name = INFINIBAND_ntv_code_to_name,
00977     .ntv_code_to_descr = INFINIBAND_ntv_code_to_descr,
00978     .ntv_code_to_bits = INFINIBAND_ntv_code_to_bits,
00979 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines