|
PAPI
5.3.0.0
|
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 };