|
PAPI
5.0.1.0
|
00001 /* This file handles the OS dependent part of the POWER5 and POWER6 architectures. 00002 It supports both AIX 4 and AIX 5. The switch between AIX 4 and 5 is driven by the 00003 system defined value _AIX_VERSION_510. 00004 Other routines also include minor conditionally compiled differences. 00005 */ 00006 00007 #include <sys/utsname.h> 00008 00009 #include "papi.h" 00010 #include "papi_internal.h" 00011 #include "papi_lock.h" 00012 00013 #include "papi_memory.h" 00014 00015 #include "extras.h" 00016 00017 #include "aix.h" 00018 #include "papi_vector.h" 00019 00020 /* Advance declarations */ 00021 papi_vector_t _aix_vector; 00022 00023 /* Locking variables */ 00024 volatile int lock_var[PAPI_MAX_LOCK] = { 0 }; 00025 atomic_p lock[PAPI_MAX_LOCK]; 00026 00027 /* 00028 some heap information, start_of_text, start_of_data ..... 00029 ref: http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/genprogc/sys_mem_alloc.htm#HDRA9E4A4C9921SYLV 00030 */ 00031 #define START_OF_TEXT &_text 00032 #define END_OF_TEXT &_etext 00033 #define START_OF_DATA &_data 00034 #define END_OF_DATA &_edata 00035 #define START_OF_BSS &_edata 00036 #define END_OF_BSS &_end 00037 00038 static int maxgroups = 0; 00039 struct utsname AixVer; 00040 00041 native_event_entry_t native_table[PAPI_MAX_NATIVE_EVENTS]; 00042 00043 hwd_pminfo_t pminfo; 00044 pm_groups_info_t pmgroups; 00045 native_event_entry_t native_table[PAPI_MAX_NATIVE_EVENTS]; 00046 PPC64_native_map_t native_name_map[PAPI_MAX_NATIVE_EVENTS]; 00047 hwd_groups_t group_map[MAX_GROUPS] = { 0 }; 00048 00049 /* to initialize the native_table */ 00050 void 00051 aix_initialize_native_table( ) 00052 { 00053 int i, j; 00054 00055 memset( native_table, 0, 00056 PAPI_MAX_NATIVE_EVENTS * sizeof ( native_event_entry_t ) ); 00057 memset( native_name_map, 0, 00058 PAPI_MAX_NATIVE_EVENTS * sizeof ( PPC64_native_map_t ) ); 00059 for ( i = 0; i < PAPI_MAX_NATIVE_EVENTS; i++ ) { 00060 native_name_map[i].index = -1; 00061 for ( j = 0; j < MAX_COUNTERS; j++ ) 00062 native_table[i].resources.counter_cmd[j] = -1; 00063 } 00064 } 00065 00066 /* to setup native_table group value */ 00067 static void 00068 aix_ppc64_setup_gps( int total ) 00069 { 00070 int i, j, gnum; 00071 00072 for ( i = 0; i < total; i++ ) { 00073 for ( j = 0; j < MAX_COUNTERS; j++ ) { 00074 /* native_table[i].resources.rgg[j]=-1; */ 00075 if ( native_table[i].resources.selector & ( 1 << j ) ) { 00076 for ( gnum = 0; gnum < pmgroups.maxgroups; gnum++ ) { 00077 if ( native_table[i].resources.counter_cmd[j] == 00078 pmgroups.event_groups[gnum].events[j] ) { 00079 /* could use gnum instead of pmgroups.event_groups[gnum].group_id */ 00080 native_table[i].resources.group[pmgroups. 00081 event_groups[gnum]. 00082 group_id / 32] |= 00083 1 << ( pmgroups.event_groups[gnum].group_id % 32 ); 00084 } 00085 } 00086 } 00087 } 00088 } 00089 00090 for ( gnum = 0; gnum < pmgroups.maxgroups; gnum++ ) { 00091 for ( i = 0; i < MAX_COUNTERS; i++ ) { 00092 /*group_map[gnum].counter_cmd[i] = pmgroups.event_groups[gnum].events[i]; */ 00093 if (pmgroups.event_groups[gnum].group_id >=MAX_GROUPS) { 00094 fprintf(stderr,"ERROR, group number trying to go past MAX GROUPS\n"); 00095 continue; 00096 } 00097 00098 group_map[pmgroups.event_groups[gnum].group_id].counter_cmd[i] = 00099 pmgroups.event_groups[gnum].events[i]; 00100 } 00101 } 00102 } 00103 00104 /* to setup native_table values, and return number of entries */ 00105 int 00106 aix_ppc64_setup_native_table( ) 00107 { 00108 hwd_pmevents_t *wevp; 00109 hwd_pminfo_t *info; 00110 int pmc, ev, i, j, index; 00111 00112 info = &pminfo; 00113 index = 0; 00114 aix_initialize_native_table( ); 00115 for ( pmc = 0; pmc < info->maxpmcs; pmc++ ) { 00116 wevp = info->list_events[pmc]; 00117 for ( ev = 0; ev < info->maxevents[pmc]; ev++, wevp++ ) { 00118 for ( i = 0; i < index; i++ ) { 00119 if ( strcmp( wevp->short_name, native_table[i].name ) == 0 ) { 00120 native_table[i].resources.selector |= 1 << pmc; 00121 native_table[i].resources.counter_cmd[pmc] = wevp->event_id; 00122 break; 00123 } 00124 } 00125 if ( i == index ) { 00126 /*native_table[i].index=i; */ 00127 native_table[i].resources.selector |= 1 << pmc; 00128 native_table[i].resources.counter_cmd[pmc] = wevp->event_id; 00129 native_table[i].name = wevp->short_name; 00130 native_table[i].description = wevp->description; 00131 native_name_map[i].name = native_table[i].name; 00132 native_name_map[i].index = i; 00133 index++; 00134 } 00135 } 00136 } 00137 aix_ppc64_setup_gps( index ); 00138 00139 return index; 00140 } 00141 00142 /* Reports the elements of the hwd_register_t struct as an array of names and a matching array of values. 00143 Maximum string length is name_len; Maximum number of values is count. 00144 */ 00145 static void 00146 copy_value( unsigned int val, char *nam, char *names, unsigned int *values, 00147 int len ) 00148 { 00149 *values = val; 00150 strncpy( names, nam, len ); 00151 names[len - 1] = '\0'; 00152 } 00153 00154 00155 /* this function recusively does Modified Bipartite Graph counter allocation 00156 success return 1 00157 fail return 0 00158 */ 00159 static int 00160 do_counter_allocation( ppc64_reg_alloc_t * event_list, int size ) 00161 { 00162 int i, j, group = -1; 00163 unsigned int map[GROUP_INTS]; 00164 00165 for ( i = 0; i < GROUP_INTS; i++ ) 00166 map[i] = event_list[0].ra_group[i]; 00167 00168 for ( i = 1; i < size; i++ ) { 00169 for ( j = 0; j < GROUP_INTS; j++ ) 00170 map[j] &= event_list[i].ra_group[j]; 00171 } 00172 00173 for ( i = 0; i < GROUP_INTS; i++ ) { 00174 if ( map[i] ) { 00175 group = ffs( map[i] ) - 1 + i * 32; 00176 break; 00177 } 00178 } 00179 00180 if ( group < 0 ) 00181 return group; /* allocation fail */ 00182 else { 00183 for ( i = 0; i < size; i++ ) { 00184 for ( j = 0; j < MAX_COUNTERS; j++ ) { 00185 if ( event_list[i].ra_counter_cmd[j] >= 0 00186 && event_list[i].ra_counter_cmd[j] == 00187 group_map[group].counter_cmd[j] ) 00188 event_list[i].ra_position = j; 00189 } 00190 } 00191 return group; 00192 } 00193 } 00194 00195 00196 /* this function will be called when there are counters available 00197 success return 1 00198 fail return 0 00199 */ 00200 int 00201 _aix_allocate_registers( EventSetInfo_t * ESI ) 00202 { 00203 hwd_control_state_t *this_state = ESI->ctl_state; 00204 unsigned char selector; 00205 int i, j, natNum, index; 00206 ppc64_reg_alloc_t event_list[MAX_COUNTERS]; 00207 int position, group; 00208 00209 00210 /* not yet successfully mapped, but have enough slots for events */ 00211 00212 /* Initialize the local structure needed 00213 for counter allocation and optimization. */ 00214 natNum = ESI->NativeCount; 00215 for ( i = 0; i < natNum; i++ ) { 00216 /* CAUTION: Since this is in the hardware layer, it's ok 00217 to access the native table directly, but in general this is a bad idea */ 00218 event_list[i].ra_position = -1; 00219 /* calculate native event rank, which is number of counters it can live on, this is power3 specific */ 00220 for ( j = 0; j < MAX_COUNTERS; j++ ) { 00221 if ( ( index = 00222 native_name_map[ESI->NativeInfoArray[i]. 00223 ni_event & PAPI_NATIVE_AND_MASK].index ) < 00224 0 ) 00225 return PAPI_ECNFLCT; 00226 event_list[i].ra_counter_cmd[j] = 00227 native_table[index].resources.counter_cmd[j]; 00228 } 00229 for ( j = 0; j < GROUP_INTS; j++ ) { 00230 if ( ( index = 00231 native_name_map[ESI->NativeInfoArray[i]. 00232 ni_event & PAPI_NATIVE_AND_MASK].index ) < 00233 0 ) 00234 return PAPI_ECNFLCT; 00235 event_list[i].ra_group[j] = native_table[index].resources.group[j]; 00236 } 00237 /*event_list[i].ra_mod = -1; */ 00238 } 00239 00240 if ( ( group = do_counter_allocation( event_list, natNum ) ) >= 0 ) { /* successfully mapped */ 00241 /* copy counter allocations info back into NativeInfoArray */ 00242 this_state->group_id = group; 00243 for ( i = 0; i < natNum; i++ ) 00244 ESI->NativeInfoArray[i].ni_position = event_list[i].ra_position; 00245 /* update the control structure based on the NativeInfoArray */ 00246 /*_papi_hwd_update_control_state(this_state, ESI->NativeInfoArray, natNum);*/ 00247 return PAPI_OK; 00248 } else { 00249 return PAPI_ECNFLCT; 00250 } 00251 } 00252 00253 int 00254 _aix_init_control_state( hwd_control_state_t * ptr ) 00255 { 00256 int i; 00257 00258 for ( i = 0; i < _aix_vector.cmp_info.num_cntrs; i++ ) { 00259 ptr->counter_cmd.events[i] = COUNT_NOTHING; 00260 } 00261 ptr->counter_cmd.mode.b.is_group = 1; 00262 00263 _aix_vector.set_domain( ptr, _aix_vector.cmp_info.default_domain ); 00264 _aix_set_granularity( ptr, _aix_vector.cmp_info.default_granularity ); 00265 /*setup_native_table(); */ 00266 return ( PAPI_OK ); 00267 } 00268 00269 00270 /* This function updates the control structure with whatever resources are allocated 00271 for all the native events in the native info structure array. */ 00272 int 00273 _aix_update_control_state( hwd_control_state_t * this_state, 00274 NativeInfo_t * native, int count, 00275 hwd_context_t * context ) 00276 { 00277 00278 this_state->counter_cmd.events[0] = this_state->group_id; 00279 return PAPI_OK; 00280 } 00281 00282 00283 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 00284 /* The following is for any POWER hardware */ 00285 00286 /* Trims trailing blank space and line endings from a string (in place). 00287 Returns pointer to start address */ 00288 static char * 00289 trim_string( char *in ) 00290 { 00291 int len, i = 0; 00292 char *start = in; 00293 00294 if ( in == NULL ) 00295 return ( in ); 00296 len = strlen( in ); 00297 if ( len == 0 ) 00298 return ( in ); 00299 /* Trim right */ 00300 i = strlen( start ) - 1; 00301 while ( i >= 0 ) { 00302 if ( isblank( start[i] ) || ( start[i] == '\r' ) || 00303 ( start[i] == '\n' ) ) 00304 start[i] = '\0'; 00305 else 00306 break; 00307 i--; 00308 } 00309 return ( start ); 00310 } 00311 00312 00313 /* Routines to support an opaque native event table */ 00314 int 00315 _aix_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len ) 00316 { 00317 if ( ( EventCode & PAPI_NATIVE_AND_MASK ) >= 00318 _aix_vector.cmp_info.num_native_events ) 00319 return ( PAPI_ENOEVNT ); 00320 strncpy( ntv_name, 00321 native_name_map[EventCode & PAPI_NATIVE_AND_MASK].name, len ); 00322 trim_string( ntv_name ); 00323 if ( strlen( native_name_map[EventCode & PAPI_NATIVE_AND_MASK].name ) > 00324 len - 1 ) 00325 return ( PAPI_EBUF ); 00326 return ( PAPI_OK ); 00327 } 00328 00329 int 00330 _aix_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len ) 00331 { 00332 if ( ( EventCode & PAPI_NATIVE_AND_MASK ) >= 00333 _aix_vector.cmp_info.num_native_events ) 00334 return ( PAPI_ENOEVNT ); 00335 strncpy( ntv_descr, 00336 native_table[native_name_map[EventCode & PAPI_NATIVE_AND_MASK]. 00337 index].description, len ); 00338 trim_string( ntv_descr ); 00339 if ( strlen 00340 ( native_table 00341 [native_name_map[EventCode & PAPI_NATIVE_AND_MASK].index]. 00342 description ) > len - 1 ) 00343 return ( PAPI_EBUF ); 00344 return ( PAPI_OK ); 00345 } 00346 00347 int 00348 _aix_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits ) 00349 { 00350 bits = &native_table[EventCode & PAPI_NATIVE_AND_MASK].resources; /* it is not right, different type */ 00351 return ( PAPI_OK ); 00352 } 00353 00354 /* this function return the next native event code. 00355 modifier = PAPI_ENUM_FIRST returns first native event code 00356 modifier = PAPI_ENUM_EVENTS returns next native event code 00357 modifier = PAPI_NTV_ENUM_GROUPS return groups in which this 00358 native event lives, in bits 16 - 23 of event code 00359 terminating with PAPI_ENOEVNT at the end of the list. 00360 function return value: 00361 PAPI_OK successful, event code is valid 00362 PAPI_EINVAL bad modifier 00363 PAPI_ENOEVNT end of list or fail, event code is invalid 00364 */ 00365 int 00366 _aix_ntv_enum_events( unsigned int *EventCode, int modifier ) 00367 { 00368 if ( modifier == PAPI_ENUM_FIRST ) { 00369 *EventCode = PAPI_NATIVE_MASK; 00370 return ( PAPI_OK ); 00371 } 00372 if ( modifier == PAPI_ENUM_EVENTS ) { 00373 int index = *EventCode & PAPI_NATIVE_AND_MASK; 00374 00375 if ( native_table[index + 1].resources.selector ) { 00376 *EventCode = *EventCode + 1; 00377 return ( PAPI_OK ); 00378 } else 00379 return ( PAPI_ENOEVNT ); 00380 } else if ( modifier == PAPI_NTV_ENUM_GROUPS ) { 00381 #if defined(_POWER5) || defined(_POWER6) 00382 unsigned int group = 00383 ( *EventCode & PAPI_NTV_GROUP_AND_MASK ) >> PAPI_NTV_GROUP_SHIFT; 00384 int index = *EventCode & 0x000000FF; 00385 int i; 00386 unsigned int tmpg; 00387 00388 *EventCode = *EventCode & ( ~PAPI_NTV_GROUP_SHIFT ); 00389 for ( i = 0; i < GROUP_INTS; i++ ) { 00390 tmpg = native_table[index].resources.group[i]; 00391 if ( group != 0 ) { 00392 while ( ( ffs( tmpg ) + i * 32 ) <= group && tmpg != 0 ) 00393 tmpg = tmpg ^ ( 1 << ( ffs( tmpg ) - 1 ) ); 00394 } 00395 if ( tmpg != 0 ) { 00396 group = ffs( tmpg ) + i * 32; 00397 *EventCode = *EventCode | ( group << PAPI_NTV_GROUP_SHIFT ); 00398 return ( PAPI_OK ); 00399 } 00400 } 00401 #endif 00402 return ( PAPI_ENOEVNT ); 00403 } else 00404 return ( PAPI_EINVAL ); 00405 } 00406 00407 static void 00408 set_config( hwd_control_state_t * ptr, int arg1, int arg2 ) 00409 { 00410 ptr->counter_cmd.events[arg1] = arg2; 00411 } 00412 00413 static void 00414 unset_config( hwd_control_state_t * ptr, int arg1 ) 00415 { 00416 ptr->counter_cmd.events[arg1] = 0; 00417 } 00418 00419 int 00420 init_domain( ) 00421 { 00422 int domain = 0; 00423 00424 domain = PAPI_DOM_USER | PAPI_DOM_KERNEL | PAPI_DOM_OTHER; 00425 #ifdef PM_INITIALIZE 00426 #ifdef _AIXVERSION_510 00427 if ( pminfo.proc_feature.b.hypervisor ) { 00428 domain |= PAPI_DOM_SUPERVISOR; 00429 } 00430 #endif 00431 #endif 00432 return ( domain ); 00433 } 00434 00435 static int 00436 _aix_set_domain( hwd_control_state_t * this_state, int domain ) 00437 { 00438 pm_mode_t *mode = &( this_state->counter_cmd.mode ); 00439 int did = 0; 00440 00441 mode->b.user = 0; 00442 mode->b.kernel = 0; 00443 if ( domain & PAPI_DOM_USER ) { 00444 did++; 00445 mode->b.user = 1; 00446 } 00447 if ( domain & PAPI_DOM_KERNEL ) { 00448 did++; 00449 mode->b.kernel = 1; 00450 } 00451 #ifdef PM_INITIALIZE 00452 #ifdef _AIXVERSION_510 00453 if ( ( domain & PAPI_DOM_SUPERVISOR ) && pminfo.proc_feature.b.hypervisor ) { 00454 did++; 00455 mode->b.hypervisor = 1; 00456 } 00457 #endif 00458 #endif 00459 if ( did ) 00460 return ( PAPI_OK ); 00461 else 00462 return ( PAPI_EINVAL ); 00463 /* 00464 switch (domain) 00465 { 00466 case PAPI_DOM_USER: 00467 mode->b.user = 1; 00468 mode->b.kernel = 0; 00469 break; 00470 case PAPI_DOM_KERNEL: 00471 mode->b.user = 0; 00472 mode->b.kernel = 1; 00473 break; 00474 case PAPI_DOM_ALL: 00475 mode->b.user = 1; 00476 mode->b.kernel = 1; 00477 break; 00478 default: 00479 return(PAPI_EINVAL); 00480 } 00481 return(PAPI_OK); 00482 */ 00483 } 00484 00485 int 00486 _aix_set_granularity( hwd_control_state_t * this_state, int domain ) 00487 { 00488 pm_mode_t *mode = &( this_state->counter_cmd.mode ); 00489 00490 switch ( domain ) { 00491 case PAPI_GRN_THR: 00492 mode->b.process = 0; 00493 mode->b.proctree = 0; 00494 break; 00495 /* case PAPI_GRN_PROC: 00496 mode->b.process = 1; 00497 mode->b.proctree = 0; 00498 break; 00499 case PAPI_GRN_PROCG: 00500 mode->b.process = 0; 00501 mode->b.proctree = 1; 00502 break; */ 00503 default: 00504 return ( PAPI_EINVAL ); 00505 } 00506 return ( PAPI_OK ); 00507 } 00508 00509 static int 00510 set_default_domain( EventSetInfo_t * zero, int domain ) 00511 { 00512 hwd_control_state_t *current_state = zero->ctl_state; 00513 return ( _aix_set_domain( current_state, domain ) ); 00514 } 00515 00516 static int 00517 set_default_granularity( EventSetInfo_t * zero, int granularity ) 00518 { 00519 hwd_control_state_t *current_state = zero->ctl_state; 00520 return ( _aix_set_granularity( current_state, granularity ) ); 00521 } 00522 00523 /* Initialize the system-specific settings */ 00524 /* Machine info structure. -1 is unused. */ 00525 int 00526 _aix_mdi_init( ) 00527 { 00528 int retval; 00529 00530 if ( ( retval = uname( &AixVer ) ) < 0 ) 00531 return ( PAPI_ESYS ); 00532 if ( AixVer.version[0] == '4' ) { 00533 _papi_hwi_system_info.exe_info.address_info.text_start = 00534 ( caddr_t ) START_OF_TEXT; 00535 _papi_hwi_system_info.exe_info.address_info.text_end = 00536 ( caddr_t ) END_OF_TEXT; 00537 _papi_hwi_system_info.exe_info.address_info.data_start = 00538 ( caddr_t ) START_OF_DATA; 00539 _papi_hwi_system_info.exe_info.address_info.data_end = 00540 ( caddr_t ) END_OF_DATA; 00541 _papi_hwi_system_info.exe_info.address_info.bss_start = 00542 ( caddr_t ) START_OF_BSS; 00543 _papi_hwi_system_info.exe_info.address_info.bss_end = 00544 ( caddr_t ) END_OF_BSS; 00545 } else { 00546 _aix_update_shlib_info( &_papi_hwi_system_info ); 00547 } 00548 00549 /* _papi_hwi_system_info.supports_64bit_counters = 1; 00550 _papi_hwi_system_info.supports_real_usec = 1; 00551 _papi_hwi_system_info.sub_info.fast_real_timer = 1; 00552 _papi_hwi_system_info.sub_info->available_domains = init_domain();*/ 00553 00554 00555 return ( PAPI_OK ); 00556 } 00557 00558 00559 static int 00560 _aix_get_system_info( papi_mdi_t *mdi ) 00561 { 00562 int retval; 00563 /* pm_info_t pminfo; */ 00564 struct procsinfo psi = { 0 }; 00565 pid_t pid; 00566 char maxargs[PAPI_HUGE_STR_LEN]; 00567 char pname[PAPI_HUGE_STR_LEN]; 00568 00569 pid = getpid( ); 00570 if ( pid == -1 ) 00571 return ( PAPI_ESYS ); 00572 _papi_hwi_system_info.pid = pid; 00573 psi.pi_pid = pid; 00574 retval = getargs( &psi, sizeof ( psi ), maxargs, PAPI_HUGE_STR_LEN ); 00575 if ( retval == -1 ) 00576 return ( PAPI_ESYS ); 00577 00578 if ( realpath( maxargs, pname ) ) 00579 strncpy( _papi_hwi_system_info.exe_info.fullname, pname, 00580 PAPI_HUGE_STR_LEN ); 00581 else 00582 strncpy( _papi_hwi_system_info.exe_info.fullname, maxargs, 00583 PAPI_HUGE_STR_LEN ); 00584 00585 strcpy( _papi_hwi_system_info.exe_info.address_info.name, 00586 basename( maxargs ) ); 00587 00588 #ifdef _POWER7 00589 /* we pass PM_POWER7 for the same reasons as below (power6 case) */ 00590 retval = pm_initialize( PM_INIT_FLAGS , &pminfo, &pmgroups, PM_POWER7); 00591 #elif defined(_POWER6) 00592 /* problem with pm_initialize(): it cannot be called multiple times with 00593 PM_CURRENT; use instead the actual proc type - here PM_POWER6 - 00594 and multiple invocations are no longer a problem */ 00595 retval = pm_initialize( PM_INIT_FLAGS, &pminfo, &pmgroups, PM_POWER6 ); 00596 #else 00597 #ifdef _AIXVERSION_510 00598 #ifdef PM_INITIALIZE 00599 SUBDBG( "Calling AIX 5 version of pm_initialize...\n" ); 00600 /*#if defined(_POWER5) 00601 retval = pm_initialize(PM_INIT_FLAGS, &pminfo, &pmgroups, PM_POWER5); 00602 #endif*/ 00603 retval = pm_initialize( PM_INIT_FLAGS, &pminfo, &pmgroups, PM_CURRENT ); 00604 #else 00605 SUBDBG( "Calling AIX 5 version of pm_init...\n" ); 00606 retval = pm_init( PM_INIT_FLAGS, &pminfo, &pmgroups ); 00607 #endif 00608 00609 #else 00610 SUBDBG( "Calling AIX 4 version of pm_init...\n" ); 00611 retval = pm_init( PM_INIT_FLAGS, &pminfo ); 00612 #endif 00613 #endif 00614 SUBDBG( "...Back from pm_init\n" ); 00615 00616 if ( retval > 0 ) 00617 return ( retval ); 00618 00619 _aix_mdi_init( ); 00620 00621 _papi_hwi_system_info.hw_info.nnodes = 1; 00622 _papi_hwi_system_info.hw_info.ncpu = _system_configuration.ncpus; 00623 _papi_hwi_system_info.hw_info.totalcpus = 00624 _papi_hwi_system_info.hw_info.ncpu * 00625 _papi_hwi_system_info.hw_info.nnodes; 00626 _papi_hwi_system_info.hw_info.vendor = -1; 00627 strcpy( _papi_hwi_system_info.hw_info.vendor_string, "IBM" ); 00628 _papi_hwi_system_info.hw_info.model = _system_configuration.implementation; 00629 strcpy( _papi_hwi_system_info.hw_info.model_string, pminfo.proc_name ); 00630 _papi_hwi_system_info.hw_info.revision = 00631 ( float ) _system_configuration.version; 00632 _papi_hwi_system_info.hw_info.mhz = ( float ) ( pm_cycles( ) / 1000000.0 ); 00633 _papi_hwi_system_info.hw_info.cpu_max_mhz=_papi_hwi_system_info.hw_info.mhz; 00634 _papi_hwi_system_info.hw_info.cpu_min_mhz=_papi_hwi_system_info.hw_info.mhz; 00635 00636 /* _papi_hwi_system_info.num_gp_cntrs = pminfo.maxpmcs;*/ 00637 _aix_vector.cmp_info.num_cntrs = pminfo.maxpmcs; 00638 _aix_vector.cmp_info.num_mpx_cntrs = MAX_MPX_COUNTERS; // pminfo.maxpmcs, 00639 00640 _aix_vector.cmp_info.available_granularities = PAPI_GRN_THR; 00641 /* This field doesn't appear to exist in the PAPI 3.0 structure 00642 _papi_hwi_system_info.cpunum = mycpu(); 00643 */ 00644 _aix_vector.cmp_info.available_domains = init_domain( ); 00645 return PAPI_OK; 00646 } 00647 00648 /* Low level functions, should not handle errors, just return codes. */ 00649 00650 /* At init time, the higher level library should always allocate and 00651 reserve EventSet zero. */ 00652 00653 long long 00654 _aix_get_real_usec( void ) 00655 { 00656 timebasestruct_t t; 00657 long long retval; 00658 00659 read_real_time( &t, TIMEBASE_SZ ); 00660 time_base_to_time( &t, TIMEBASE_SZ ); 00661 retval = ( t.tb_high * 1000000 ) + t.tb_low / 1000; 00662 return ( retval ); 00663 } 00664 00665 long long 00666 _aix_get_real_cycles( void ) 00667 { 00668 return ( _aix_get_real_usec( ) * 00669 ( long long ) _papi_hwi_system_info.hw_info.cpu_max_mhz ); 00670 } 00671 00672 long long 00673 _aix_get_virt_usec( void ) 00674 { 00675 long long retval; 00676 struct tms buffer; 00677 00678 times( &buffer ); 00679 SUBDBG( "user %d system %d\n", ( int ) buffer.tms_utime, 00680 ( int ) buffer.tms_stime ); 00681 retval = 00682 ( long long ) ( ( buffer.tms_utime + buffer.tms_stime ) * 00683 ( 1000000 / CLK_TCK ) ); 00684 return ( retval ); 00685 } 00686 00687 static void 00688 _aix_lock_init( void ) 00689 { 00690 int i; 00691 for ( i = 0; i < PAPI_MAX_LOCK; i++ ) 00692 lock[i] = ( int * ) ( lock_var + i ); 00693 } 00694 00695 int 00696 _aix_shutdown_thread( hwd_context_t * ctx ) 00697 { 00698 return ( PAPI_OK ); 00699 } 00700 00701 int 00702 _aix_init_component( int cidx ) 00703 { 00704 int retval = PAPI_OK, procidx; 00705 00706 /* Fill in what we can of the papi_system_info. */ 00707 retval = _papi_os_vector.get_system_info( &_papi_hwi_system_info ); 00708 if ( retval ) 00709 return ( retval ); 00710 00711 /* Setup memory info */ 00712 retval = _papi_os_vector.get_memory_info( &_papi_hwi_system_info.hw_info, 0 ); 00713 if ( retval ) 00714 return ( retval ); 00715 00716 SUBDBG( "Found %d %s %s CPUs at %d Mhz.\n", 00717 _papi_hwi_system_info.hw_info.totalcpus, 00718 _papi_hwi_system_info.hw_info.vendor_string, 00719 _papi_hwi_system_info.hw_info.model_string, 00720 _papi_hwi_system_info.hw_info.cpu_max_mhz ); 00721 00722 _aix_vector.cmp_info.CmpIdx = cidx; 00723 _aix_vector.cmp_info.num_native_events = aix_ppc64_setup_native_table( ); 00724 00725 procidx = pm_get_procindex( ); 00726 switch ( procidx ) { 00727 case PM_POWER5: 00728 _papi_load_preset_table( "POWER5", 0, cidx ); 00729 break; 00730 case PM_POWER5_II: 00731 _papi_load_preset_table( "POWER5+", 0, cidx ); 00732 break; 00733 case PM_POWER6: 00734 _papi_load_preset_table( "POWER6", 0, cidx ); 00735 break; 00736 case PM_PowerPC970: 00737 _papi_load_preset_table( "PPC970", 0, cidx ); 00738 break; 00739 case PM_POWER7: 00740 _papi_load_preset_table( "POWER7", 0, cidx ); 00741 break; 00742 default: 00743 fprintf( stderr, "%s is not supported!\n", pminfo.proc_name ); 00744 return PAPI_ENOIMPL; 00745 } 00746 00747 _aix_lock_init( ); 00748 00749 return ( retval ); 00750 } 00751 00752 00753 int 00754 _aix_init_thread( hwd_context_t * context ) 00755 { 00756 int retval; 00757 /* Initialize our global control state. */ 00758 00759 _aix_init_control_state( &context->cntrl ); 00760 } 00761 00762 /* Go from highest counter to lowest counter. Why? Because there are usually 00763 more counters on #1, so we try the least probable first. */ 00764 00765 static int 00766 get_avail_hwcntr_bits( int cntr_avail_bits ) 00767 { 00768 int tmp = 0, i = 1 << ( POWER_MAX_COUNTERS - 1 ); 00769 00770 while ( i ) { 00771 tmp = i & cntr_avail_bits; 00772 if ( tmp ) 00773 return ( tmp ); 00774 i = i >> 1; 00775 } 00776 return ( 0 ); 00777 } 00778 00779 static void 00780 set_hwcntr_codes( int selector, unsigned char *from, int *to ) 00781 { 00782 int useme, i; 00783 00784 for ( i = 0; i < _aix_vector.cmp_info.num_cntrs; i++ ) { 00785 useme = ( 1 << i ) & selector; 00786 if ( useme ) { 00787 to[i] = from[i]; 00788 } 00789 } 00790 } 00791 00792 00793 #ifdef DEBUG 00794 void 00795 dump_cmd( pm_prog_t * t ) 00796 { 00797 SUBDBG( "mode.b.threshold %d\n", t->mode.b.threshold ); 00798 SUBDBG( "mode.b.spare %d\n", t->mode.b.spare ); 00799 SUBDBG( "mode.b.process %d\n", t->mode.b.process ); 00800 SUBDBG( "mode.b.kernel %d\n", t->mode.b.kernel ); 00801 SUBDBG( "mode.b.user %d\n", t->mode.b.user ); 00802 SUBDBG( "mode.b.count %d\n", t->mode.b.count ); 00803 SUBDBG( "mode.b.proctree %d\n", t->mode.b.proctree ); 00804 SUBDBG( "events[0] %d\n", t->events[0] ); 00805 SUBDBG( "events[1] %d\n", t->events[1] ); 00806 SUBDBG( "events[2] %d\n", t->events[2] ); 00807 SUBDBG( "events[3] %d\n", t->events[3] ); 00808 SUBDBG( "events[4] %d\n", t->events[4] ); 00809 SUBDBG( "events[5] %d\n", t->events[5] ); 00810 SUBDBG( "events[6] %d\n", t->events[6] ); 00811 SUBDBG( "events[7] %d\n", t->events[7] ); 00812 SUBDBG( "reserved %d\n", t->reserved ); 00813 } 00814 00815 void 00816 dump_data( long long *vals ) 00817 { 00818 int i; 00819 00820 for ( i = 0; i < MAX_COUNTERS; i++ ) { 00821 SUBDBG( "counter[%d] = %lld\n", i, vals[i] ); 00822 } 00823 } 00824 #endif 00825 00826 int 00827 _aix_reset( hwd_context_t * ESI, hwd_control_state_t * zero ) 00828 { 00829 int retval = pm_reset_data_mythread( ); 00830 if ( retval > 0 ) { 00831 if ( _papi_hwi_error_level != PAPI_QUIET ) 00832 pm_error( "PAPI Error: pm_reset_data_mythread", retval ); 00833 return ( retval ); 00834 } 00835 return ( PAPI_OK ); 00836 } 00837 00838 00839 int 00840 _aix_read( hwd_context_t * ctx, hwd_control_state_t * spc, 00841 long long **vals, int flags ) 00842 { 00843 int retval; 00844 00845 retval = pm_get_data_mythread( &spc->state ); 00846 if ( retval > 0 ) { 00847 if ( _papi_hwi_error_level != PAPI_QUIET ) 00848 pm_error( "PAPI Error: pm_get_data_mythread", retval ); 00849 return ( retval ); 00850 } 00851 00852 *vals = spc->state.accu; 00853 00854 #ifdef DEBUG 00855 if ( ISLEVEL( DEBUG_SUBSTRATE ) ) 00856 dump_data( *vals ); 00857 #endif 00858 00859 return ( PAPI_OK ); 00860 } 00861 00862 static int 00863 round_requested_ns( int ns ) 00864 { 00865 if ( ns <= _papi_os_info.itimer_res_ns ) { 00866 return _papi_os_info.itimer_res_ns; 00867 } else { 00868 int leftover_ns = ns % _papi_os_info.itimer_res_ns; 00869 return ( ns - leftover_ns + _papi_os_info.itimer_res_ns ); 00870 } 00871 } 00872 00873 int 00874 _aix_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option ) 00875 { 00876 switch ( code ) { 00877 /* I don't understand what it means to set the default domain 00878 case PAPI_DEFDOM: 00879 return(set_default_domain(zero, option->domain.domain)); 00880 */ 00881 case PAPI_DOMAIN: 00882 return ( _aix_set_domain 00883 ( option->domain.ESI->ctl_state, option->domain.domain ) ); 00884 /* I don't understand what it means to set the default granularity 00885 case PAPI_DEFGRN: 00886 return(set_default_granularity(zero, option->granularity.granularity)); 00887 */ 00888 case PAPI_GRANUL: 00889 return ( _aix_set_granularity 00890 ( option->domain.ESI->ctl_state, 00891 option->granularity.granularity ) ); 00892 #if 0 00893 case PAPI_INHERIT: 00894 return ( set_inherit( option->inherit.inherit ) ); 00895 #endif 00896 case PAPI_DEF_ITIMER: 00897 { 00898 /* flags are currently ignored, eventually the flags will be able 00899 to specify whether or not we use POSIX itimers (clock_gettimer) */ 00900 if ( ( option->itimer.itimer_num == ITIMER_REAL ) && 00901 ( option->itimer.itimer_sig != SIGALRM ) ) 00902 return PAPI_EINVAL; 00903 if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) && 00904 ( option->itimer.itimer_sig != SIGVTALRM ) ) 00905 return PAPI_EINVAL; 00906 if ( ( option->itimer.itimer_num == ITIMER_PROF ) && 00907 ( option->itimer.itimer_sig != SIGPROF ) ) 00908 return PAPI_EINVAL; 00909 if ( option->itimer.ns > 0 ) 00910 option->itimer.ns = round_requested_ns( option->itimer.ns ); 00911 /* At this point, we assume the user knows what he or 00912 she is doing, they maybe doing something arch specific */ 00913 return PAPI_OK; 00914 } 00915 case PAPI_DEF_MPX_NS: 00916 { 00917 option->multiplex.ns = round_requested_ns( option->multiplex.ns ); 00918 return ( PAPI_OK ); 00919 } 00920 case PAPI_DEF_ITIMER_NS: 00921 { 00922 option->itimer.ns = round_requested_ns( option->itimer.ns ); 00923 return ( PAPI_OK ); 00924 } 00925 default: 00926 return ( PAPI_ENOSUPP ); 00927 } 00928 } 00929 00930 void 00931 _aix_dispatch_timer( int signal, siginfo_t * si, void *i ) 00932 { 00933 _papi_hwi_context_t ctx; 00934 ThreadInfo_t *t = NULL; 00935 caddr_t address; 00936 00937 ctx.si = si; 00938 ctx.ucontext = ( hwd_ucontext_t * ) i; 00939 00940 address = ( caddr_t ) GET_OVERFLOW_ADDRESS( ( &ctx ) ); 00941 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, NULL, 0, 0, 00942 &t, _aix_vector.cmp_info.CmpIdx ); 00943 } 00944 00945 int 00946 _aix_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) 00947 { 00948 hwd_control_state_t *this_state = ESI->ctl_state; 00949 00950 return ( PAPI_OK ); 00951 } 00952 00953 void * 00954 _aix_get_overflow_address( void *context ) 00955 { 00956 void *location; 00957 struct sigcontext *info = ( struct sigcontext * ) context; 00958 location = ( void * ) info->sc_jmpbuf.jmp_context.iar; 00959 00960 return ( location ); 00961 } 00962 00963 00964 /* Copy the current control_state into the new thread context */ 00965 /*int _papi_hwd_start(EventSetInfo_t *ESI, EventSetInfo_t *zero)*/ 00966 int 00967 _aix_start( hwd_context_t * ctx, hwd_control_state_t * cntrl ) 00968 { 00969 int i, retval; 00970 hwd_control_state_t *current_state = &ctx->cntrl; 00971 00972 /* If we are nested, merge the global counter structure 00973 with the current eventset */ 00974 00975 SUBDBG( "Start\n" ); 00976 00977 /* Copy the global counter structure to the current eventset */ 00978 00979 SUBDBG( "Copying states\n" ); 00980 memcpy( current_state, cntrl, sizeof ( hwd_control_state_t ) ); 00981 00982 retval = pm_set_program_mythread( ¤t_state->counter_cmd ); 00983 if ( retval > 0 ) { 00984 if ( retval == 13 ) { 00985 retval = pm_delete_program_mythread( ); 00986 if ( retval > 0 ) { 00987 if ( _papi_hwi_error_level != PAPI_QUIET ) 00988 pm_error( "PAPI Error: pm_delete_program_mythread", 00989 retval ); 00990 return ( retval ); 00991 } 00992 retval = pm_set_program_mythread( ¤t_state->counter_cmd ); 00993 if ( retval > 0 ) { 00994 if ( _papi_hwi_error_level != PAPI_QUIET ) 00995 pm_error( "PAPI Error: pm_set_program_mythread", retval ); 00996 return ( retval ); 00997 } 00998 } else { 00999 if ( _papi_hwi_error_level != PAPI_QUIET ) 01000 pm_error( "PAPI Error: pm_set_program_mythread", retval ); 01001 return ( retval ); 01002 } 01003 } 01004 01005 /* Set up the new merged control structure */ 01006 01007 #if 0 01008 dump_cmd( ¤t_state->counter_cmd ); 01009 #endif 01010 01011 /* Start the counters */ 01012 01013 retval = pm_start_mythread( ); 01014 if ( retval > 0 ) { 01015 if ( _papi_hwi_error_level != PAPI_QUIET ) 01016 pm_error( "pm_start_mythread()", retval ); 01017 return ( retval ); 01018 } 01019 01020 return ( PAPI_OK ); 01021 } 01022 01023 int 01024 _aix_stop( hwd_context_t * ctx, hwd_control_state_t * cntrl ) 01025 { 01026 int retval; 01027 01028 retval = pm_stop_mythread( ); 01029 if ( retval > 0 ) { 01030 if ( _papi_hwi_error_level != PAPI_QUIET ) 01031 pm_error( "pm_stop_mythread()", retval ); 01032 return ( retval ); 01033 } 01034 01035 retval = pm_delete_program_mythread( ); 01036 if ( retval > 0 ) { 01037 if ( _papi_hwi_error_level != PAPI_QUIET ) 01038 pm_error( "pm_delete_program_mythread()", retval ); 01039 return ( retval ); 01040 } 01041 01042 return ( PAPI_OK ); 01043 } 01044 01045 int 01046 _aix_update_shlib_info( papi_mdi_t *mdi ) 01047 { 01048 #if ( ( defined( _AIXVERSION_510) || defined(_AIXVERSION_520))) 01049 struct ma_msg_s 01050 { 01051 long flag; 01052 char *name; 01053 } ma_msgs[] = { 01054 { 01055 MA_MAINEXEC, "MAINEXEC"}, { 01056 MA_KERNTEXT, "KERNTEXT"}, { 01057 MA_READ, "READ"}, { 01058 MA_WRITE, "WRITE"}, { 01059 MA_EXEC, "EXEC"}, { 01060 MA_SHARED, "SHARED"}, { 01061 MA_BREAK, "BREAK"}, { 01062 MA_STACK, "STACK"},}; 01063 01064 char fname[80], name[PAPI_HUGE_STR_LEN]; 01065 prmap_t newp; 01066 int count, t_index, retval, i, j, not_first_flag_bit; 01067 FILE *map_f; 01068 void *vaddr; 01069 prmap_t *tmp1 = NULL; 01070 PAPI_address_map_t *tmp2 = NULL; 01071 01072 sprintf( fname, "/proc/%d/map", getpid( ) ); 01073 map_f = fopen( fname, "r" ); 01074 if ( !map_f ) { 01075 PAPIERROR( "fopen(%s) returned < 0", fname ); 01076 return ( PAPI_OK ); 01077 } 01078 01079 /* count the entries we need */ 01080 count = 0; 01081 t_index = 0; 01082 while ( ( retval = fread( &newp, sizeof ( prmap_t ), 1, map_f ) ) > 0 ) { 01083 if ( newp.pr_pathoff > 0 && newp.pr_mapname[0] != '\0' ) { 01084 if ( newp.pr_mflags & MA_STACK ) 01085 continue; 01086 01087 count++; 01088 SUBDBG( "count=%d offset=%ld map=%s\n", count, 01089 newp.pr_pathoff, newp.pr_mapname ); 01090 01091 if ( ( newp.pr_mflags & MA_READ ) && ( newp.pr_mflags & MA_EXEC ) ) 01092 t_index++; 01093 } 01094 } 01095 rewind( map_f ); 01096 tmp1 = ( prmap_t * ) papi_calloc( ( count + 1 ), sizeof ( prmap_t ) ); 01097 if ( tmp1 == NULL ) 01098 return ( PAPI_ENOMEM ); 01099 01100 tmp2 = 01101 ( PAPI_address_map_t * ) papi_calloc( t_index, 01102 sizeof ( PAPI_address_map_t ) ); 01103 if ( tmp2 == NULL ) 01104 return ( PAPI_ENOMEM ); 01105 01106 i = 0; 01107 t_index = -1; 01108 while ( ( retval = fread( &tmp1[i], sizeof ( prmap_t ), 1, map_f ) ) > 0 ) { 01109 if ( tmp1[i].pr_pathoff > 0 && tmp1[i].pr_mapname[0] != '\0' ) 01110 if ( !( tmp1[i].pr_mflags & MA_STACK ) ) 01111 i++; 01112 } 01113 for ( i = 0; i < count; i++ ) { 01114 char c; 01115 int cc = 0; 01116 01117 retval = fseek( map_f, tmp1[i].pr_pathoff, SEEK_SET ); 01118 if ( retval != 0 ) 01119 return ( PAPI_ESYS ); 01120 while ( fscanf( map_f, "%c", &c ) != EOF ) { 01121 name[cc] = c; 01122 /* how many char are hold in /proc/xxxx/map */ 01123 cc++; 01124 if ( c == '\0' ) 01125 break; 01126 } 01127 01128 01129 /* currently /proc/xxxx/map file holds only 33 char per line (incl NULL char); 01130 * if executable name > 32 char, compare first 32 char only */ 01131 if ( strncmp( _papi_hwi_system_info.exe_info.address_info.name, 01132 basename( name ), cc - 1 ) == 0 ) { 01133 if ( strlen( _papi_hwi_system_info.exe_info.address_info.name ) != 01134 cc - 1 ) 01135 PAPIERROR 01136 ( "executable name too long (%d char). Match of first %d char only", 01137 strlen( _papi_hwi_system_info.exe_info.address_info. 01138 name ), cc - 1 ); 01139 01140 if ( tmp1[i].pr_mflags & MA_READ ) { 01141 if ( tmp1[i].pr_mflags & MA_EXEC ) { 01142 _papi_hwi_system_info.exe_info.address_info. 01143 text_start = ( caddr_t ) tmp1[i].pr_vaddr; 01144 _papi_hwi_system_info.exe_info.address_info. 01145 text_end = 01146 ( caddr_t ) ( tmp1[i].pr_vaddr + tmp1[i].pr_size ); 01147 } else if ( tmp1[i].pr_mflags & MA_WRITE ) { 01148 _papi_hwi_system_info.exe_info.address_info. 01149 data_start = ( caddr_t ) tmp1[i].pr_vaddr; 01150 _papi_hwi_system_info.exe_info.address_info. 01151 data_end = 01152 ( caddr_t ) ( tmp1[i].pr_vaddr + tmp1[i].pr_size ); 01153 } 01154 } 01155 01156 } else { 01157 if ( ( _papi_hwi_system_info.exe_info.address_info.text_start == 0 ) 01158 && ( _papi_hwi_system_info.exe_info.address_info.text_end == 01159 0 ) && 01160 ( _papi_hwi_system_info.exe_info.address_info.data_start == 0 ) 01161 && ( _papi_hwi_system_info.exe_info.address_info.data_end == 01162 0 ) ) 01163 PAPIERROR( "executable name not recognized" ); 01164 01165 if ( tmp1[i].pr_mflags & MA_READ ) { 01166 if ( tmp1[i].pr_mflags & MA_EXEC ) { 01167 t_index++; 01168 tmp2[t_index].text_start = ( caddr_t ) tmp1[i].pr_vaddr; 01169 tmp2[t_index].text_end = 01170 ( caddr_t ) ( tmp1[i].pr_vaddr + tmp1[i].pr_size ); 01171 strncpy( tmp2[t_index].name, name, PAPI_MAX_STR_LEN ); 01172 } else if ( tmp1[i].pr_mflags & MA_WRITE ) { 01173 tmp2[t_index].data_start = ( caddr_t ) tmp1[i].pr_vaddr; 01174 tmp2[t_index].data_end = 01175 ( caddr_t ) ( tmp1[i].pr_vaddr + tmp1[i].pr_size ); 01176 } 01177 } 01178 01179 } 01180 } 01181 fclose( map_f ); 01182 01183 if ( _papi_hwi_system_info.shlib_info.map ) 01184 papi_free( _papi_hwi_system_info.shlib_info.map ); 01185 _papi_hwi_system_info.shlib_info.map = tmp2; 01186 _papi_hwi_system_info.shlib_info.count = t_index + 1; 01187 papi_free( tmp1 ); 01188 01189 return PAPI_OK; 01190 #else 01191 return PAPI_ENOIMPL; 01192 #endif 01193 } 01194 01195 int 01196 _aix_ntv_name_to_code( char *name, unsigned int *evtcode ) 01197 { 01198 int i; 01199 01200 for ( i = 0; i < PAPI_MAX_NATIVE_EVENTS; i++ ) 01201 if ( strcmp( name, native_name_map[i].name ) == 0 ) { 01202 *evtcode = native_name_map[i].index | PAPI_NATIVE_MASK; 01203 return PAPI_OK; 01204 } 01205 01206 return PAPI_ENOEVNT; 01207 } 01208 01209 01210 PAPI_os_info_t _papi_os_info; 01211 01212 int 01213 _papi_hwi_init_os(void) { 01214 01215 struct utsname uname_buffer; 01216 01217 uname(&uname_buffer); 01218 01219 strncpy(_papi_os_info.name,uname_buffer.sysname,PAPI_MAX_STR_LEN); 01220 01221 strncpy(_papi_os_info.version,uname_buffer.release,PAPI_MAX_STR_LEN); 01222 01223 _papi_os_info.itimer_sig = PAPI_INT_MPX_SIGNAL; 01224 _papi_os_info.itimer_num = PAPI_INT_ITIMER; 01225 _papi_os_info.itimer_res_ns = 1; 01226 _papi_os_info.itimer_ns = 1000 * PAPI_INT_MPX_DEF_US; 01227 01228 return PAPI_OK; 01229 01230 } 01231 01232 01233 papi_vector_t _aix_vector = { 01234 .cmp_info = { 01235 /* default component information (unspecified values are initialized to 0) */ 01236 01237 .name = "aix", 01238 .description = "AIX pmapi CPU counters", 01239 .default_domain = PAPI_DOM_USER, 01240 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 01241 .default_granularity = PAPI_GRN_THR, 01242 .available_granularities = PAPI_GRN_THR, 01243 .hardware_intr_sig = PAPI_INT_SIGNAL, 01244 01245 /* component specific cmp_info initializations */ 01246 .fast_real_timer = 1, 01247 .fast_virtual_timer = 1, 01248 .attach = 1, 01249 .attach_must_ptrace = 1, 01250 .cntr_umasks = 1, 01251 } 01252 , 01253 01254 /* sizes of framework-opaque component-private structures 01255 these are remapped in pmapi_ppc64.h, ppc64_events.h */ 01256 .size = { 01257 .context = sizeof ( hwd_context_t ), 01258 .control_state = sizeof ( hwd_control_state_t ), 01259 .reg_value = sizeof ( hwd_register_t ), 01260 .reg_alloc = sizeof ( hwd_reg_alloc_t ), 01261 } 01262 , 01263 01264 /* function pointers in this component */ 01265 .init_control_state = _aix_init_control_state, 01266 .start = _aix_start, 01267 .stop = _aix_stop, 01268 .read = _aix_read, 01269 .allocate_registers = _aix_allocate_registers, 01270 .update_control_state = _aix_update_control_state, 01271 .set_domain = _aix_set_domain, 01272 .reset = _aix_reset, 01273 .set_overflow = _aix_set_overflow, 01274 /* .stop_profiling = _aix_stop_profiling, */ 01275 .ntv_enum_events = _aix_ntv_enum_events, 01276 .ntv_name_to_code = _aix_ntv_name_to_code, 01277 .ntv_code_to_name = _aix_ntv_code_to_name, 01278 .ntv_code_to_descr = _aix_ntv_code_to_descr, 01279 .ntv_code_to_bits = _aix_ntv_code_to_bits, 01280 01281 .init_component = _aix_init_component, 01282 .ctl = _aix_ctl, 01283 .dispatch_timer = _aix_dispatch_timer, 01284 .init_thread = _aix_init_thread, 01285 .shutdown_thread = _aix_shutdown_thread, 01286 }; 01287 01288 papi_os_vector_t _papi_os_vector = { 01289 .get_memory_info = _aix_get_memory_info, 01290 .get_dmem_info = _aix_get_dmem_info, 01291 .get_real_usec = _aix_get_real_usec, 01292 .get_real_cycles = _aix_get_real_cycles, 01293 .get_virt_usec = _aix_get_virt_usec, 01294 .update_shlib_info = _aix_update_shlib_info, 01295 .get_system_info = _aix_get_system_info, 01296 };