|
PAPI
5.0.1.0
|
00001 /****************************/ 00002 /* THIS IS OPEN SOURCE CODE */ 00003 /****************************/ 00004 00020 #include "papi.h" 00021 #include "papi_internal.h" 00022 #include "papi_lock.h" 00023 #include "papi_memory.h" 00024 #include "extras.h" 00025 00026 #include "linux-bgq.h" 00027 00028 #include "papi_vector.h" 00029 #include "error.h" 00030 00031 /* 00032 * BG/Q specific 'stuff' 00033 */ 00034 #include <ucontext.h> 00035 #include <stdlib.h> 00036 #include <signal.h> 00037 #include <sys/time.h> 00038 #include <errno.h> 00039 #include <stdio.h> 00040 #include <string.h> 00041 #include <sys/utsname.h> 00042 #include "spi/include/upci/upci.h" 00043 #ifdef DEBUG_BGQ 00044 #include <inttypes.h> 00045 #endif 00046 00047 // BG/Q macros 00048 #define get_cycles GetTimeBase 00049 00050 // BG/Q external structures/functions/stuff 00051 #if 1 00052 UPC_Lock_t thdLocks[PAPI_MAX_LOCK]; 00053 #else 00054 pthread_mutex_t thdLocks[PAPI_MAX_LOCK]; 00055 #endif 00056 00057 /* Defined in papi_data.c */ 00058 //extern papi_mdi_t _papi_hwi_system_info; 00059 00060 papi_vector_t _bgq_vectors; 00061 PAPI_os_info_t _papi_os_info; 00062 00063 #define OPCODE_EVENT_CHUNK 8 00064 static int allocated_opcode_events = 0; 00065 static int num_opcode_events = 0; 00066 00067 struct bgq_generic_events_t { 00068 int idx; 00069 int eventId; 00070 char mask[PAPI_MIN_STR_LEN]; 00071 char opcode[PAPI_MIN_STR_LEN]; 00072 uint64_t opcode_mask; 00073 }; 00074 00075 static struct bgq_generic_events_t *GenericEvent; 00076 00077 /* Defined in linux-bgq-memory.c */ 00078 extern int _bgq_get_memory_info( PAPI_hw_info_t * pHwInfo, int pCPU_Type ); 00079 extern int _bgq_get_dmem_info( PAPI_dmem_info_t * pDmemInfo ); 00080 00081 00082 /******************************************************************************* 00083 ******** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ********** 00084 ******************************************************************************/ 00085 00086 00087 /* 00088 * Lock 00089 */ 00090 void 00091 _papi_hwd_lock( int lock ) 00092 { 00093 #ifdef DEBUG_BGQ 00094 printf( _AT_ " _papi_hwd_lock %d\n", lock); 00095 #endif 00096 assert( lock < PAPI_MAX_LOCK ); 00097 #if 1 00098 UPC_Lock( &thdLocks[lock] ); 00099 #else 00100 pthread_mutex_lock( &thdLocks[lock] ); 00101 #endif 00102 00103 #ifdef DEBUG_BGQ 00104 printf( _AT_ " _papi_hwd_lock got lock %d\n", lock ); 00105 #endif 00106 00107 return; 00108 } 00109 00110 /* 00111 * Unlock 00112 */ 00113 void 00114 _papi_hwd_unlock( int lock ) 00115 { 00116 #ifdef DEBUG_BGQ 00117 printf( _AT_ " _papi_hwd_unlock %d\n", lock ); 00118 #endif 00119 assert( lock < PAPI_MAX_LOCK ); 00120 #if 1 00121 UPC_Unlock( &thdLocks[lock] ); 00122 #else 00123 pthread_mutex_unlock( &thdLocks[lock] ); 00124 #endif 00125 00126 return; 00127 } 00128 00129 00130 /* 00131 * Get System Information 00132 * 00133 * Initialize system information structure 00134 */ 00135 int 00136 _bgq_get_system_info( papi_mdi_t *mdi ) 00137 { 00138 #ifdef DEBUG_BGQ 00139 printf( "_bgq_get_system_info\n" ); 00140 #endif 00141 00142 //( void ) mdi; 00143 Personality_t personality; 00144 int retval; 00145 00146 /* Hardware info */ 00147 retval = Kernel_GetPersonality( &personality, sizeof( Personality_t ) ); 00148 if ( retval ) { 00149 fprintf( stdout, "Kernel_GetPersonality returned %d (sys error=%d).\n" 00150 "\t%s\n", retval, errno, strerror( errno ) ); 00151 return PAPI_ESYS; 00152 } 00153 00154 /* Returns the number of processors that are associated with the currently 00155 * running process */ 00156 _papi_hwi_system_info.hw_info.ncpu = Kernel_ProcessorCount( ); 00157 // TODO: HJ Those values need to be fixed 00158 _papi_hwi_system_info.hw_info.nnodes = Kernel_ProcessCount( ); 00159 _papi_hwi_system_info.hw_info.totalcpus = _papi_hwi_system_info.hw_info.ncpu; 00160 00161 _papi_hwi_system_info.hw_info.cpu_max_mhz = personality.Kernel_Config.FreqMHz; 00162 _papi_hwi_system_info.hw_info.cpu_min_mhz = personality.Kernel_Config.FreqMHz; 00163 00164 _papi_hwi_system_info.hw_info.mhz = ( float ) personality.Kernel_Config.FreqMHz; 00165 SUBDBG( "_bgq_get_system_info: Detected MHZ is %f\n", 00166 _papi_hwi_system_info.hw_info.mhz ); 00167 00168 return ( PAPI_OK ); 00169 } 00170 00171 00172 /* 00173 * Initialize Control State 00174 * 00175 */ 00176 int 00177 _bgq_init_control_state( hwd_control_state_t * ptr ) 00178 { 00179 #ifdef DEBUG_BGQ 00180 printf( "_bgq_init_control_state\n" ); 00181 #endif 00182 00183 ptr->EventGroup = Bgpm_CreateEventSet(); 00184 CHECK_BGPM_ERROR( ptr->EventGroup, "Bgpm_CreateEventSet" ); 00185 00186 // initialize multiplexing flag to OFF (0) 00187 ptr->muxOn = 0; 00188 // initialized BGPM eventGroup flag to NOT applied yet (0) 00189 ptr->bgpm_eventset_applied = 0; 00190 00191 return PAPI_OK; 00192 } 00193 00194 00195 /* 00196 * Set Domain 00197 */ 00198 int 00199 _bgq_set_domain( hwd_control_state_t * cntrl, int domain ) 00200 { 00201 #ifdef DEBUG_BGQ 00202 printf( "_bgq_set_domain\n" ); 00203 #endif 00204 int found = 0; 00205 ( void ) cntrl; 00206 00207 if ( PAPI_DOM_USER & domain ) 00208 found = 1; 00209 00210 if ( PAPI_DOM_KERNEL & domain ) 00211 found = 1; 00212 00213 if ( PAPI_DOM_OTHER & domain ) 00214 found = 1; 00215 00216 if ( !found ) 00217 return ( PAPI_EINVAL ); 00218 00219 return ( PAPI_OK ); 00220 } 00221 00222 /* 00223 * PAPI Initialization 00224 * This is called whenever a thread is initialized 00225 */ 00226 int 00227 _bgq_init( hwd_context_t * ctx ) 00228 { 00229 #ifdef DEBUG_BGQ 00230 printf( "_bgq_init\n" ); 00231 #endif 00232 ( void ) ctx; 00233 int retval; 00234 00235 #ifdef DEBUG_BGPM 00236 Bgpm_PrintOnError(1); 00237 Bgpm_ExitOnError(0); 00238 #else 00239 Bgpm_PrintOnError(0); 00240 // avoid bgpm default of exiting when error occurs - caller will check return code instead. 00241 Bgpm_ExitOnError(0); 00242 #endif 00243 00244 retval = Bgpm_Init( BGPM_MODE_SWDISTRIB ); 00245 CHECK_BGPM_ERROR( retval, "Bgpm_Init" ); 00246 00247 //_common_initBgpm(); 00248 00249 return PAPI_OK; 00250 } 00251 00252 00253 int 00254 _bgq_multiplex( hwd_control_state_t * bgq_state ) 00255 { 00256 int retval; 00257 uint64_t bgpm_period; 00258 double Sec, Hz; 00259 00260 #ifdef DEBUG_BGQ 00261 printf("_bgq_multiplex BEGIN: Num of Events = %d (vs %d)\n", Bgpm_NumEvents( bgq_state->EventGroup ), bgq_state->count ); 00262 #endif 00263 00264 // convert Mhz to Hz ( = cycles / sec ) 00265 Hz = (double) _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000 * 1000; 00266 // convert PAPI multiplex period (in ns) to BGPM period (in cycles) 00267 Sec = (double) _papi_os_info.itimer_ns / ( 1000 * 1000 * 1000 ); 00268 bgpm_period = Hz * Sec; 00269 00270 // if EventGroup is not empty -- which is required by BGPM before 00271 // we can call SetMultiplex() -- then drain the events from the 00272 // BGPM EventGroup, turn on multiplex flag, and rebuild BGPM EventGroup. 00273 if ( 0 < bgq_state->count ) { 00274 // Delete and re-create BGPM eventset 00275 _common_deleteRecreate( &bgq_state->EventGroup ); 00276 00277 // turn on multiplex for BGPM 00278 retval = Bgpm_SetMultiplex( bgq_state->EventGroup, bgpm_period, BGPM_NORMAL ); 00279 CHECK_BGPM_ERROR( retval, "Bgpm_SetMultiplex" ); 00280 00281 // rebuild BGPM EventGroup 00282 _common_rebuildEventgroup( bgq_state->count, 00283 bgq_state->EventGroup_local, 00284 &bgq_state->EventGroup ); 00285 } 00286 else { 00287 // need to pass either BGPM_NORMAL or BGPM_NOTNORMAL 00288 // BGPM_NORMAL: numbers reported by Bgpm_ReadEvent() are normalized 00289 // to the maximum time spent in a multiplexed group 00290 retval = Bgpm_SetMultiplex( bgq_state->EventGroup, bgpm_period, BGPM_NORMAL ); 00291 CHECK_BGPM_ERROR( retval, "Bgpm_SetMultiplex" ); 00292 } 00293 00294 #ifdef DEBUG_BGQ 00295 printf("_bgq_multiplex END: Num of Events = %d (vs %d) --- retval = %d\n", 00296 Bgpm_NumEvents( bgq_state->EventGroup ), bgq_state->count, retval ); 00297 #endif 00298 00299 return ( retval ); 00300 } 00301 00302 00303 00304 00305 00306 /* 00307 * Register Allocation 00308 * 00309 */ 00310 int 00311 _bgq_allocate_registers( EventSetInfo_t * ESI ) 00312 { 00313 #ifdef DEBUG_BGQ 00314 printf("_bgq_allocate_registers\n"); 00315 #endif 00316 int i, natNum; 00317 int xEventId; 00318 00319 /* 00320 * Start monitoring the events... 00321 */ 00322 natNum = ESI->NativeCount; 00323 00324 for ( i = 0; i < natNum; i++ ) { 00325 xEventId = ( ESI->NativeInfoArray[i].ni_event & PAPI_NATIVE_AND_MASK ) + 1; 00326 ESI->NativeInfoArray[i].ni_position = i; 00327 } 00328 00329 return PAPI_OK; 00330 } 00331 00332 00333 /* 00334 * PAPI Cleanup Eventset 00335 * 00336 * Destroy and re-create the BGPM / Punit EventSet 00337 */ 00338 int 00339 _bgq_cleanup_eventset( hwd_control_state_t * ctrl ) 00340 { 00341 #ifdef DEBUG_BGQ 00342 printf( "_bgq_cleanup_eventset\n" ); 00343 #endif 00344 00345 // set multiplexing flag to OFF (0) 00346 ctrl->muxOn = 0; 00347 // set BGPM eventGroup flag back to NOT applied yet (0) 00348 ctrl->bgpm_eventset_applied = 0; 00349 00350 return ( PAPI_OK ); 00351 } 00352 00353 00354 /* 00355 * Update Control State 00356 * 00357 * This function clears the current contents of the control 00358 * structure and updates it with whatever resources are allocated 00359 * for all the native events in the native info structure array. 00360 */ 00361 int 00362 _bgq_update_control_state( hwd_control_state_t * ptr, 00363 NativeInfo_t * native, int count, 00364 hwd_context_t * ctx ) 00365 { 00366 #ifdef DEBUG_BGQ 00367 printf( _AT_ " _bgq_update_control_state: count = %d, EventGroup=%d\n", count, ptr->EventGroup ); 00368 #endif 00369 ( void ) ctx; 00370 int i, j, index, retval; 00371 unsigned evtIdx; 00372 00373 // Delete and re-create BGPM eventset 00374 _common_deleteRecreate( &ptr->EventGroup ); 00375 00376 #ifdef DEBUG_BGQ 00377 printf( _AT_ " _bgq_update_control_state: EventGroup=%d, muxOn = %d\n", ptr->EventGroup, ptr->muxOn ); 00378 #endif 00379 00380 // add the events to the eventset 00381 for ( i = 0; i < count; i++ ) { 00382 index = ( native[i].ni_event & PAPI_NATIVE_AND_MASK ) + 1; 00383 00384 ptr->EventGroup_local[i] = index; 00385 00386 // we found an opcode event 00387 if ( index > BGQ_PUNIT_MAX_COUNTERS ) { 00388 for( j = 0; j < num_opcode_events; j++ ) { 00389 #ifdef DEBUG_BGQ 00390 printf(_AT_ " _bgq_update_control_state: %d out of %d OPCODES\n", 00391 j, num_opcode_events ); 00392 #endif 00393 #ifdef DEBUG_BGQ 00394 printf(_AT_ " _bgq_update_control_state: j's idx = %d, index = %d\n", 00395 GenericEvent[j].idx, index ); 00396 #endif 00397 if ( GenericEvent[j].idx == ( index - 1) ) { 00398 /* Add events to the BGPM eventGroup */ 00399 retval = Bgpm_AddEvent( ptr->EventGroup, GenericEvent[j].eventId ); 00400 CHECK_BGPM_ERROR( retval, "Bgpm_AddEvent" ); 00401 #ifdef DEBUG_BGQ 00402 printf(_AT_ " _bgq_update_control_state: ADD event: i = %d, eventId = %d\n", i, GenericEvent[j].eventId ); 00403 #endif 00404 00405 evtIdx = Bgpm_GetEventIndex( ptr->EventGroup, 00406 GenericEvent[j].eventId, 00407 i ); 00408 #ifdef DEBUG_BGQ 00409 printf(_AT_ " _bgq_update_control_state: evtIdx in EventGroup = %d\n", 00410 evtIdx ); 00411 #endif 00412 if ( 0 == strcmp( GenericEvent[j].mask, "PEVT_INST_XU_GRP_MASK" ) ) { 00413 retval = Bgpm_SetXuGrpMask( ptr->EventGroup, 00414 evtIdx, 00415 GenericEvent[j].opcode_mask ); 00416 CHECK_BGPM_ERROR( retval, "Bgpm_SetXuGrpMask" ); 00417 #ifdef DEBUG_BGQ 00418 printf(_AT_ " _bgq_update_control_state: it's PEVT_INST_XU_GRP_MASK\n" ); 00419 #endif 00420 } else if ( 0 == strcmp( GenericEvent[j].mask, "PEVT_INST_QFPU_GRP_MASK" ) ) { 00421 retval = Bgpm_SetQfpuGrpMask( ptr->EventGroup, 00422 evtIdx, 00423 GenericEvent[j].opcode_mask ); 00424 CHECK_BGPM_ERROR( retval, "Bgpm_SetQfpuGrpMask" ); 00425 #ifdef DEBUG_BGQ 00426 printf(_AT_ " _bgq_update_control_state: it's PEVT_INST_QFPU_GRP_MASK\n" ); 00427 #endif 00428 } 00429 } 00430 } 00431 } 00432 else { 00433 #ifdef DEBUG_BGQ 00434 printf(_AT_ " _bgq_update_control_state: no OPCODE\n" ); 00435 #endif 00436 00437 /* Add events to the BGPM eventGroup */ 00438 retval = Bgpm_AddEvent( ptr->EventGroup, index ); 00439 CHECK_BGPM_ERROR( retval, "Bgpm_AddEvent" ); 00440 #ifdef DEBUG_BGQ 00441 printf(_AT_ " _bgq_update_control_state: ADD event: i = %d, index = %d\n", i, index ); 00442 #endif 00443 00444 } 00445 } 00446 00447 // store how many events we added to an EventSet 00448 ptr->count = count; 00449 00450 // if muxOn and EventGroup is not empty -- which is required by BGPM before 00451 // we can call SetMultiplex() -- then drain the events from the 00452 // BGPM EventGroup, turn on multiplex flag, and rebuild BGPM EventGroup. 00453 if ( 1 == ptr->muxOn ) 00454 retval = _bgq_multiplex( ptr ); 00455 00456 return ( PAPI_OK ); 00457 } 00458 00459 00460 00461 /* 00462 * PAPI Start 00463 */ 00464 int 00465 _bgq_start( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00466 { 00467 #ifdef DEBUG_BGQ 00468 printf( "BEGIN _bgq_start\n" ); 00469 #endif 00470 ( void ) ctx; 00471 int retval; 00472 00473 retval = Bgpm_Apply( ptr->EventGroup ); 00474 CHECK_BGPM_ERROR( retval, "Bgpm_Apply" ); 00475 00476 // set flag to 1: BGPM eventGroup HAS BEEN applied 00477 ptr->bgpm_eventset_applied = 1; 00478 00479 #ifdef DEBUG_BGQ 00480 int i; 00481 int numEvts = Bgpm_NumEvents( ptr->EventGroup ); 00482 for ( i = 0; i < numEvts; i++ ) { 00483 printf("%d = %s\n", i, Bgpm_GetEventLabel( ptr->EventGroup, i) ); 00484 } 00485 #endif 00486 00487 /* Bgpm_Apply() does an implicit reset; 00488 hence no need to use Bgpm_ResetStart */ 00489 retval = Bgpm_Start( ptr->EventGroup ); 00490 CHECK_BGPM_ERROR( retval, "Bgpm_Start" ); 00491 00492 return ( PAPI_OK ); 00493 } 00494 00495 /* 00496 * PAPI Stop 00497 */ 00498 int 00499 _bgq_stop( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00500 { 00501 #ifdef DEBUG_BGQ 00502 printf( "BEGIN _bgq_stop\n" ); 00503 #endif 00504 ( void ) ctx; 00505 int retval; 00506 00507 retval = Bgpm_Stop( ptr->EventGroup ); 00508 CHECK_BGPM_ERROR( retval, "Bgpm_Stop" ); 00509 00510 return ( PAPI_OK ); 00511 } 00512 00513 /* 00514 * PAPI Read Counters 00515 * 00516 * Read the counters into local storage 00517 */ 00518 int 00519 _bgq_read( hwd_context_t * ctx, hwd_control_state_t * ptr, 00520 long_long ** dp, int flags ) 00521 { 00522 #ifdef DEBUG_BGQ 00523 printf( "_bgq_read\n" ); 00524 #endif 00525 ( void ) ctx; 00526 ( void ) flags; 00527 int i, numEvts; 00528 00529 numEvts = Bgpm_NumEvents( ptr->EventGroup ); 00530 if ( numEvts == 0 ) { 00531 #ifdef DEBUG_BGPM 00532 printf ("Error: ret value is %d for BGPM API function Bgpm_NumEvents.\n", numEvts ); 00533 //return ( EXIT_FAILURE ); 00534 #endif 00535 } 00536 00537 for ( i = 0; i < numEvts; i++ ) 00538 ptr->counters[i] = _common_getEventValue( i, ptr->EventGroup ); 00539 00540 *dp = ptr->counters; 00541 00542 return ( PAPI_OK ); 00543 } 00544 00545 /* 00546 * PAPI Reset 00547 * 00548 * Zero the counter values 00549 */ 00550 int 00551 _bgq_reset( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00552 { 00553 #ifdef DEBUG_BGQ 00554 printf( "_bgq_reset\n" ); 00555 #endif 00556 ( void ) ctx; 00557 int retval; 00558 00559 /* we can't simply call Bgpm_Reset() since PAPI doesn't have the 00560 restriction that an EventSet has to be stopped before resetting is 00561 possible. However, BGPM does have this restriction. 00562 Hence we need to stop, reset and start */ 00563 retval = Bgpm_Stop( ptr->EventGroup ); 00564 CHECK_BGPM_ERROR( retval, "Bgpm_Stop" ); 00565 00566 retval = Bgpm_ResetStart( ptr->EventGroup ); 00567 CHECK_BGPM_ERROR( retval, "Bgpm_ResetStart" ); 00568 00569 return ( PAPI_OK ); 00570 } 00571 00572 00573 /* 00574 * PAPI Shutdown 00575 * 00576 * This routine is for shutting down threads, 00577 * including the master thread. 00578 * Effectively a no-op, same as BG/L/P... 00579 */ 00580 int 00581 _bgq_shutdown( hwd_context_t * ctx ) 00582 { 00583 #ifdef DEBUG_BGQ 00584 printf( "_bgq_shutdown\n" ); 00585 #endif 00586 ( void ) ctx; 00587 int retval; 00588 00589 /* Disable BGPM library */ 00590 retval = Bgpm_Disable(); 00591 CHECK_BGPM_ERROR( retval, "Bgpm_Disable" ); 00592 00593 return ( PAPI_OK ); 00594 00595 } 00596 00597 /* 00598 * PAPI Write 00599 * 00600 * Write counter values 00601 * NOTE: Could possible support, but signal error as BG/L/P does... 00602 */ 00603 int 00604 _bgq_write( hwd_context_t * ctx, hwd_control_state_t * cntrl, long_long * from ) 00605 { 00606 #ifdef DEBUG_BGQ 00607 printf( "_bgq_write\n" ); 00608 #endif 00609 ( void ) ctx; 00610 ( void ) cntrl; 00611 ( void ) from; 00612 00613 return PAPI_ECMP; 00614 } 00615 00616 /* 00617 * Dispatch Timer 00618 * 00619 * NOT the same as BG/L/P where we simply return 00620 * This function is used when hardware overflows are working or when 00621 * software overflows are forced 00622 */ 00623 void 00624 _bgq_dispatch_timer( int signal, hwd_siginfo_t * info, void *uc ) 00625 { 00626 #ifdef DEBUG_BGQ 00627 printf("BEGIN _bgq_dispatch_timer\n"); 00628 #endif 00629 00630 return; 00631 } 00632 00633 00634 00635 /* 00636 * user_signal_handler 00637 * 00638 * This function is used when hardware overflows are working or when 00639 * software overflows are forced 00640 */ 00641 void 00642 user_signal_handler( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext ) 00643 { 00644 #ifdef DEBUG_BGQ 00645 printf( "user_signal_handler start\n" ); 00646 #endif 00647 00648 int retval, i; 00649 int isHardware = 1; 00650 int cidx = _bgq_vectors.cmp_info.CmpIdx; 00651 long_long overflow_bit = 0; 00652 caddr_t address1; 00653 _papi_hwi_context_t ctx; 00654 ctx.ucontext = ( hwd_ucontext_t * ) pContext; 00655 ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 ); 00656 00657 //printf(_AT_ " thread = %p\n", thread); // <<<<<<<<<<<<<<<<<< 00658 00659 EventSetInfo_t *ESI; 00660 ESI = thread->running_eventset[cidx]; 00661 // Get the indices of all events which have overflowed. 00662 unsigned ovfIdxs[BGPM_MAX_OVERFLOW_EVENTS]; 00663 unsigned len = BGPM_MAX_OVERFLOW_EVENTS; 00664 00665 retval = Bgpm_GetOverflowEventIndices( hEvtSet, ovfVector, ovfIdxs, &len ); 00666 00667 if ( retval < 0 ) { 00668 #ifdef DEBUG_BGPM 00669 printf ( "Error: ret value is %d for BGPM API function Bgpm_GetOverflowEventIndices.\n", 00670 retval ); 00671 #endif 00672 return; 00673 } 00674 00675 if ( thread == NULL ) { 00676 PAPIERROR( "thread == NULL in user_signal_handler!" ); 00677 return; 00678 } 00679 00680 if ( ESI == NULL ) { 00681 PAPIERROR( "ESI == NULL in user_signal_handler!"); 00682 return; 00683 } 00684 00685 if ( ESI->overflow.flags == 0 ) { 00686 PAPIERROR( "ESI->overflow.flags == 0 in user_signal_handler!"); 00687 return; 00688 } 00689 00690 for ( i = 0; i < len; i++ ) { 00691 uint64_t hProf; 00692 Bgpm_GetEventUser1( hEvtSet, ovfIdxs[i], &hProf ); 00693 if ( hProf ) { 00694 overflow_bit ^= 1 << ovfIdxs[i]; 00695 break; 00696 } 00697 00698 } 00699 00700 if ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) { 00701 #ifdef DEBUG_BGQ 00702 printf("OVERFLOW_SOFTWARE\n"); 00703 #endif 00704 address1 = GET_OVERFLOW_ADDRESS( ctx ); 00705 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, NULL, 0, 0, &thread, cidx ); 00706 return; 00707 } 00708 else if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) { 00709 #ifdef DEBUG_BGQ 00710 printf("OVERFLOW_HARDWARE\n"); 00711 #endif 00712 address1 = GET_OVERFLOW_ADDRESS( ctx ); 00713 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, &isHardware, overflow_bit, 0, &thread, cidx ); 00714 } 00715 else { 00716 #ifdef DEBUG_BGQ 00717 printf("OVERFLOW_NONE\n"); 00718 #endif 00719 PAPIERROR( "ESI->overflow.flags is set to something other than PAPI_OVERFLOW_HARDWARE or PAPI_OVERFLOW_FORCE_SW (%x)", thread->running_eventset[cidx]->overflow.flags); 00720 } 00721 } 00722 00723 00724 /* 00725 * Set Overflow 00726 * 00727 * This is commented out in BG/L/P - need to explore and complete... 00728 * However, with true 64-bit counters in BG/Q and all counters for PAPI 00729 * always starting from a true zero (we don't allow write...), the possibility 00730 * for overflow is remote at best... 00731 */ 00732 int 00733 _bgq_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) 00734 { 00735 #ifdef DEBUG_BGQ 00736 printf("BEGIN _bgq_set_overflow\n"); 00737 #endif 00738 hwd_control_state_t * this_state = ( hwd_control_state_t * ) ESI->ctl_state; 00739 int retval; 00740 int evt_idx; 00741 uint64_t threshold_for_bgpm; 00742 00743 /* 00744 * In case an BGPM eventGroup HAS BEEN applied or attached before 00745 * overflow is set, delete the eventGroup and create an new empty one, 00746 * and rebuild as it was prior to deletion 00747 */ 00748 #ifdef DEBUG_BGQ 00749 printf( "_bgq_set_overflow: bgpm_eventset_applied = %d\n", 00750 this_state->bgpm_eventset_applied ); 00751 #endif 00752 if ( 1 == this_state->bgpm_eventset_applied ) { 00753 _common_deleteRecreate( &this_state->EventGroup ); 00754 _common_rebuildEventgroup( this_state->count, 00755 this_state->EventGroup_local, 00756 &this_state->EventGroup ); 00757 00758 /* set BGPM eventGroup flag back to NOT applied yet (0) 00759 * because the eventGroup has been recreated from scratch */ 00760 this_state->bgpm_eventset_applied = 0; 00761 } 00762 00763 /* convert threadhold value assigned by PAPI user to value that is 00764 * programmed into the counter. This value is required by Bgpm_SetOverflow() */ 00765 threshold_for_bgpm = BGPM_PERIOD2THRES( threshold ); 00766 00767 evt_idx = ESI->EventInfoArray[EventIndex].pos[0]; 00768 //evt_id = ( ESI->NativeInfoArray[EventIndex].ni_event & PAPI_NATIVE_AND_MASK ) + 1; 00769 SUBDBG( "Hardware counter %d (vs %d) used in overflow, threshold %d\n", 00770 evt_idx, EventIndex, threshold ); 00771 #ifdef DEBUG_BGQ 00772 printf( "Hardware counter %d (vs %d) used in overflow, threshold %d\n", 00773 evt_idx, EventIndex, threshold ); 00774 #endif 00775 /* If this counter isn't set to overflow, it's an error */ 00776 if ( threshold == 0 ) { 00777 /* Remove the signal handler */ 00778 retval = _papi_hwi_stop_signal( _bgq_vectors.cmp_info.hardware_intr_sig ); 00779 if ( retval != PAPI_OK ) 00780 return ( retval ); 00781 } 00782 else { 00783 #ifdef DEBUG_BGQ 00784 printf( "_bgq_set_overflow: Enable the signal handler\n" ); 00785 #endif 00786 /* Enable the signal handler */ 00787 retval = _papi_hwi_start_signal( _bgq_vectors.cmp_info.hardware_intr_sig, 00788 NEED_CONTEXT, 00789 _bgq_vectors.cmp_info.CmpIdx ); 00790 if ( retval != PAPI_OK ) 00791 return ( retval ); 00792 00793 retval = Bgpm_SetOverflow( this_state->EventGroup, 00794 evt_idx, 00795 threshold_for_bgpm ); 00796 00797 CHECK_BGPM_ERROR( retval, "Bgpm_SetOverflow" ); 00798 00799 retval = Bgpm_SetEventUser1( this_state->EventGroup, 00800 evt_idx, 00801 1024 ); 00802 CHECK_BGPM_ERROR( retval, "Bgpm_SetEventUser1" ); 00803 00804 /* user signal handler for overflow case */ 00805 retval = Bgpm_SetOverflowHandler( this_state->EventGroup, user_signal_handler ); 00806 CHECK_BGPM_ERROR( retval, "Bgpm_SetOverflowHandler" ); 00807 } 00808 00809 return ( PAPI_OK ); 00810 } 00811 00812 00813 /* 00814 * Set Profile 00815 * 00816 * Same as for BG/L/P, routine not used and returns error 00817 */ 00818 int 00819 _bgq_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold ) 00820 { 00821 #ifdef DEBUG_BGQ 00822 printf("BEGIN _bgq_set_profile\n"); 00823 #endif 00824 00825 ( void ) ESI; 00826 ( void ) EventIndex; 00827 ( void ) threshold; 00828 00829 return PAPI_ECMP; 00830 } 00831 00832 /* 00833 * Stop Profiling 00834 * 00835 * Same as for BG/L/P... 00836 */ 00837 int 00838 _bgq_stop_profiling( ThreadInfo_t * master, EventSetInfo_t * ESI ) 00839 { 00840 #ifdef DEBUG_BGQ 00841 printf("BEGIN _bgq_stop_profiling\n"); 00842 #endif 00843 00844 ( void ) master; 00845 ( void ) ESI; 00846 00847 return ( PAPI_OK ); 00848 } 00849 00850 /* 00851 * PAPI Control 00852 * 00853 * Same as for BG/L/P - initialize the domain 00854 */ 00855 int 00856 _bgq_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option ) 00857 { 00858 #ifdef DEBUG_BGQ 00859 printf( "_bgq_ctl\n" ); 00860 #endif 00861 00862 int retval; 00863 00864 switch ( code ) { 00865 case PAPI_MULTIPLEX: 00866 { 00867 hwd_control_state_t * bgq_state = ( ( hwd_control_state_t * ) option->multiplex.ESI->ctl_state ); 00868 bgq_state->muxOn = 1; 00869 retval = _bgq_multiplex( bgq_state ); 00870 return ( retval ); 00871 } 00872 default: 00873 return ( PAPI_OK ); 00874 } 00875 } 00876 00877 /* 00878 * Get Real Micro-seconds 00879 */ 00880 long long 00881 _bgq_get_real_usec( void ) 00882 { 00883 #ifdef DEBUG_BGQ 00884 printf( "_bgq_get_real_usec\n" ); 00885 #endif 00886 00887 /* 00888 * NOTE: _papi_hwi_system_info.hw_info.mhz is really a representation of unit of time per cycle. 00889 * On BG/P, it's value is 8.5e-4. Therefore, to get cycles per sec, we have to multiply 00890 * by 1.0e12. To then convert to usec, we have to divide by 1.0e-3. 00891 */ 00892 return ( ( long long ) ( ( ( float ) get_cycles( ) ) / 00893 ( ( _papi_hwi_system_info.hw_info.cpu_max_mhz ) ) ) ); 00894 00895 } 00896 00897 /* 00898 * Get Real Cycles 00899 * 00900 * Same for BG/L/P, using native function... 00901 */ 00902 long long 00903 _bgq_get_real_cycles( void ) 00904 { 00905 #ifdef DEBUG_BGQ 00906 printf( "_bgq_get_real_cycles\n" ); 00907 #endif 00908 00909 return ( ( long long ) get_cycles( ) ); 00910 00911 } 00912 00913 /* 00914 * Get Virtual Micro-seconds 00915 * 00916 * Same calc as for BG/L/P, returns real usec... 00917 */ 00918 long long 00919 _bgq_get_virt_usec( void ) 00920 { 00921 #ifdef DEBUG_BGQ 00922 printf( "_bgq_get_virt_usec\n" ); 00923 #endif 00924 00925 return _bgq_get_real_usec( ); 00926 } 00927 00928 /* 00929 * Get Virtual Cycles 00930 * 00931 * Same calc as for BG/L/P, returns real cycles... 00932 */ 00933 long long 00934 _bgq_get_virt_cycles( void ) 00935 { 00936 #ifdef DEBUG_BGQ 00937 printf( "_bgq_get_virt_cycles\n" ); 00938 #endif 00939 00940 return _bgq_get_real_cycles( ); 00941 } 00942 00943 /* 00944 * Component setup and shutdown 00945 * 00946 * Initialize hardware counters, setup the function vector table 00947 * and get hardware information, this routine is called when the 00948 * PAPI process is initialized (IE PAPI_library_init) 00949 */ 00950 int 00951 _bgq_init_component( int cidx ) 00952 { 00953 #ifdef DEBUG_BGQ 00954 printf("_bgq_init_substrate\n"); 00955 //printf("_bgq_init_substrate: 1. BGPM_INITIALIZED = %d \n", BGPM_INITIALIZED); 00956 #endif 00957 int retval; 00958 int i; 00959 00960 /* allocate the opcode event structure */ 00961 GenericEvent = calloc( OPCODE_EVENT_CHUNK, sizeof( struct bgq_generic_events_t ) ); 00962 if ( NULL == GenericEvent ) { 00963 return PAPI_ENOMEM; 00964 } 00965 00966 /* init opcode event stuff */ 00967 allocated_opcode_events = OPCODE_EVENT_CHUNK; 00968 num_opcode_events = 0; 00969 00970 _bgq_vectors.cmp_info.CmpIdx = cidx; 00971 00972 /* 00973 * Fill in what we can of the papi_system_info 00974 */ 00975 SUBDBG( "Before _bgq_get_system_info()...\n" ); 00976 retval = _bgq_get_system_info( &_papi_hwi_system_info ); 00977 SUBDBG( "After _bgq_get_system_info(), retval=%d...\n", retval ); 00978 if ( retval != PAPI_OK ) 00979 return ( retval ); 00980 00981 /* 00982 * Setup memory info 00983 */ 00984 00985 SUBDBG( "Before _bgq_get_memory_info...\n" ); 00986 retval = _bgq_get_memory_info( &_papi_hwi_system_info.hw_info, 00987 ( int ) _papi_hwi_system_info.hw_info. 00988 model ); 00989 SUBDBG( "After _bgq_get_memory_info, retval=%d...\n", retval ); 00990 if ( retval ) 00991 return ( retval ); 00992 #if 1 00993 /* Setup Locks */ 00994 for ( i = 0; i < PAPI_MAX_LOCK; i++ ) 00995 thdLocks[i] = 0; // MUTEX_OPEN 00996 #else 00997 for( i = 0; i < PAPI_MAX_LOCK; i++ ) { 00998 pthread_mutex_init( &thdLocks[i], NULL ); 00999 } 01000 #endif 01001 01002 /* Setup presets */ 01003 retval = _papi_load_preset_table( "BGQ", 0, cidx ); 01004 if ( retval ) { 01005 return retval; 01006 } 01007 01008 01009 return ( PAPI_OK ); 01010 } 01011 01012 01013 /*************************************/ 01014 /* CODE TO SUPPORT OPAQUE NATIVE MAP */ 01015 /*************************************/ 01016 01017 /* 01018 * Event Name to Native Code 01019 */ 01020 int 01021 _bgq_ntv_name_to_code( char *name, unsigned int *event_code ) 01022 { 01023 #ifdef DEBUG_BGQ 01024 printf( "_bgq_ntv_name_to_code\n" ); 01025 #endif 01026 int ret; 01027 #ifdef DEBUG_BGQ 01028 printf( "name = ===%s===\n", name ); 01029 #endif 01030 01031 /* Treat events differently if BGPM Opcodes are used */ 01032 /* Opcode group selection values are "OR"ed together to create a desired 01033 mask of instruction group events to accumulate in the same counter */ 01034 if ( 0 == strncmp( name, "PEVT_INST_XU_GRP_MASK", strlen( "PEVT_INST_XU_GRP_MASK" ) ) || 01035 0 == strncmp( name, "PEVT_INST_QFPU_GRP_MASK", strlen( "PEVT_INST_QFPU_GRP_MASK" ) ) ) { 01036 01037 char *pcolon; 01038 pcolon = strchr( name, ':' ); 01039 01040 // Found colon separator 01041 if ( pcolon != NULL ) { 01042 int mask_len = pcolon - name; 01043 strncpy( GenericEvent[num_opcode_events].mask, name, mask_len ); 01044 strncpy( GenericEvent[num_opcode_events].opcode, pcolon+1, strlen(name) - 1 - mask_len ); 01045 /* opcode_mask needs to be 'uint64_t', 01046 hence we use strtoull() which returns an 'unsigned long long int' */ 01047 GenericEvent[num_opcode_events].opcode_mask = strtoull( GenericEvent[num_opcode_events].opcode, (char **)NULL, 16 ); 01048 GenericEvent[num_opcode_events].idx = OPCODE_BUF + num_opcode_events; 01049 /* Return event id matching the generic XU/QFPU event string */ 01050 GenericEvent[num_opcode_events].eventId = Bgpm_GetEventIdFromLabel( GenericEvent[num_opcode_events].mask ); 01051 if ( GenericEvent[num_opcode_events].eventId <= 0 ) { 01052 #ifdef DEBUG_BGPM 01053 printf ("Error: ret value is %d for BGPM API function '%s'.\n", 01054 ret, "Bgpm_GetEventIdFromLabel" ); 01055 #endif 01056 return PAPI_ENOEVNT; 01057 } 01058 01059 *event_code = GenericEvent[num_opcode_events].idx; 01060 01061 num_opcode_events++; 01062 01063 /* If there are too many opcode events than allocated, then allocate more room */ 01064 if( num_opcode_events >= allocated_opcode_events ) { 01065 01066 SUBDBG("Allocating more room for BGPM opcode events (%d %ld)\n", 01067 ( allocated_opcode_events + NATIVE_OPCODE_CHUNK ), 01068 ( long )sizeof( struct bgq_generic_events_t ) * 01069 ( allocated_opcode_events + NATIVE_OPCODE_CHUNK ) ); 01070 01071 GenericEvent = realloc( GenericEvent, sizeof( struct bgq_generic_events_t ) * 01072 ( allocated_opcode_events + OPCODE_EVENT_CHUNK ) ); 01073 if ( NULL == GenericEvent ) { 01074 return PAPI_ENOMEM; 01075 } 01076 allocated_opcode_events += OPCODE_EVENT_CHUNK; 01077 } 01078 } 01079 else { 01080 SUBDBG( "Error: Found a generic BGPM event mask without opcode string\n" ); 01081 return PAPI_ENOEVNT; 01082 } 01083 01084 01085 #ifdef DEBUG_BGQ 01086 printf(_AT_ " _bgq_ntv_name_to_code: GenericEvent no. %d: \n", num_opcode_events-1 ); 01087 printf( "idx = %d\n", GenericEvent[num_opcode_events-1].idx); 01088 printf( "eventId = %d\n", GenericEvent[num_opcode_events-1].eventId); 01089 printf( "mask = %s\n", GenericEvent[num_opcode_events-1].mask); 01090 printf( "opcode = %s\n", GenericEvent[num_opcode_events-1].opcode); 01091 printf( "opcode_mask = %" PRIX64 " (%" PRIu64 ")\n", GenericEvent[num_opcode_events-1].opcode_mask, 01092 GenericEvent[num_opcode_events-1].opcode_mask ); 01093 #endif 01094 } 01095 else { 01096 /* Return event id matching a given event label string */ 01097 ret = Bgpm_GetEventIdFromLabel ( name ); 01098 01099 if ( ret <= 0 ) { 01100 #ifdef DEBUG_BGPM 01101 printf ("Error: ret value is %d for BGPM API function '%s'.\n", 01102 ret, "Bgpm_GetEventIdFromLabel" ); 01103 #endif 01104 return PAPI_ENOEVNT; 01105 } 01106 else if ( ret > BGQ_PUNIT_MAX_COUNTERS ) // not a PUnit event 01107 return PAPI_ENOEVNT; 01108 else 01109 *event_code = ( ret - 1 ); 01110 } 01111 01112 return PAPI_OK; 01113 } 01114 01115 01116 /* 01117 * Native Code to Event Name 01118 * 01119 * Given a native event code, returns the short text label 01120 */ 01121 int 01122 _bgq_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 01123 { 01124 #ifdef DEBUG_BGQ 01125 printf( "_bgq_ntv_code_to_name\n" ); 01126 #endif 01127 int index = ( EventCode & PAPI_NATIVE_AND_MASK ) + 1; 01128 01129 if ( index >= MAX_COUNTERS ) 01130 return PAPI_ENOEVNT; 01131 01132 strncpy( name, Bgpm_GetEventIdLabel( index ), len ); 01133 01134 if ( name == NULL ) { 01135 #ifdef DEBUG_BGPM 01136 printf ("Error: ret value is NULL for BGPM API function Bgpm_GetEventIdLabel.\n" ); 01137 #endif 01138 return PAPI_ENOEVNT; 01139 } 01140 #ifdef DEBUG_BGQ 01141 printf( "name = ===%s===\n", name ); 01142 #endif 01143 01144 return ( PAPI_OK ); 01145 } 01146 01147 /* 01148 * Native Code to Event Description 01149 * 01150 * Given a native event code, returns the longer native event description 01151 */ 01152 int 01153 _bgq_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 01154 { 01155 #ifdef DEBUG_BGQ 01156 printf( "_bgq_ntv_code_to_descr\n" ); 01157 #endif 01158 int retval; 01159 int index = ( EventCode & PAPI_NATIVE_AND_MASK ) + 1; 01160 01161 retval = Bgpm_GetLongDesc( index, name, &len ); 01162 CHECK_BGPM_ERROR( retval, "Bgpm_GetLongDesc" ); 01163 01164 return ( PAPI_OK ); 01165 } 01166 01167 /* 01168 * Native Code to Bit Configuration 01169 * 01170 * Given a native event code, assigns the native event's 01171 * information to a given pointer. 01172 * NOTE: The info must be COPIED to location addressed by 01173 * the provided pointer, not just referenced! 01174 * NOTE: For BG/Q, the bit configuration is not needed, 01175 * as the native SPI is used to configure events. 01176 */ 01177 int 01178 _bgq_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits ) 01179 { 01180 #ifdef DEBUG_BGQ 01181 printf( "_bgq_ntv_code_to_bits\n" ); 01182 #endif 01183 01184 ( void ) EventCode; 01185 ( void ) bits; 01186 01187 return ( PAPI_OK ); 01188 } 01189 01190 /* 01191 * Native ENUM Events 01192 * 01193 */ 01194 int 01195 _bgq_ntv_enum_events( unsigned int *EventCode, int modifier ) 01196 { 01197 #ifdef DEBUG_BGQ 01198 printf( "_bgq_ntv_enum_events\n" ); 01199 #endif 01200 01201 switch ( modifier ) { 01202 case PAPI_ENUM_FIRST: 01203 *EventCode = PAPI_NATIVE_MASK; 01204 01205 return ( PAPI_OK ); 01206 break; 01207 01208 case PAPI_ENUM_EVENTS: 01209 { 01210 int index = ( *EventCode & PAPI_NATIVE_AND_MASK ) + 1; 01211 01212 if ( index < BGQ_PUNIT_MAX_COUNTERS ) { 01213 *EventCode = *EventCode + 1; 01214 return ( PAPI_OK ); 01215 } else 01216 return ( PAPI_ENOEVNT ); 01217 01218 break; 01219 } 01220 default: 01221 return ( PAPI_EINVAL ); 01222 } 01223 01224 return ( PAPI_EINVAL ); 01225 } 01226 01227 01228 int 01229 _papi_hwi_init_os(void) { 01230 01231 struct utsname uname_buffer; 01232 01233 /* Get the kernel info */ 01234 uname(&uname_buffer); 01235 01236 strncpy(_papi_os_info.name,uname_buffer.sysname,PAPI_MAX_STR_LEN); 01237 01238 strncpy(_papi_os_info.version,uname_buffer.release,PAPI_MAX_STR_LEN); 01239 01240 _papi_os_info.itimer_sig = PAPI_INT_MPX_SIGNAL; 01241 _papi_os_info.itimer_num = PAPI_INT_ITIMER; 01242 _papi_os_info.itimer_res_ns = 1; 01243 01244 return PAPI_OK; 01245 } 01246 01247 01248 /* 01249 * PAPI Vector Table for BG/Q 01250 */ 01251 papi_vector_t _bgq_vectors = { 01252 .cmp_info = { 01253 /* Default component information (unspecified values are initialized to 0) */ 01254 .name = "linux-bgq", 01255 .short_name = "bgq", 01256 .description = "Blue Gene/Q component", 01257 .num_cntrs = BGQ_PUNIT_MAX_COUNTERS, 01258 .num_mpx_cntrs = BGQ_PUNIT_MAX_COUNTERS, 01259 .default_domain = PAPI_DOM_USER, 01260 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 01261 .default_granularity = PAPI_GRN_THR, 01262 .available_granularities = PAPI_GRN_THR, 01263 .hardware_intr_sig = PAPI_INT_SIGNAL, 01264 .hardware_intr = 1, 01265 .kernel_multiplex = 1, 01266 01267 /* component specific cmp_info initializations */ 01268 .fast_real_timer = 1, 01269 .fast_virtual_timer = 0, 01270 } 01271 , 01272 01273 /* Sizes of framework-opaque component-private structures */ 01274 .size = { 01275 .context = sizeof ( hwd_context_t ), 01276 .control_state = sizeof ( hwd_control_state_t ), 01277 .reg_value = sizeof ( hwd_register_t ), 01278 .reg_alloc = sizeof ( hwd_reg_alloc_t ), 01279 } 01280 , 01281 /* Function pointers in this component */ 01282 // .get_overflow_address = 01283 .start = _bgq_start, 01284 .stop = _bgq_stop, 01285 .read = _bgq_read, 01286 .reset = _bgq_reset, 01287 .write = _bgq_write, 01288 .stop_profiling = _bgq_stop_profiling, 01289 .init_component = _bgq_init_component, 01290 .init_thread = _bgq_init, 01291 .init_control_state = _bgq_init_control_state, 01292 .update_control_state = _bgq_update_control_state, 01293 .ctl = _bgq_ctl, 01294 .set_overflow = _bgq_set_overflow, 01295 //.dispatch_timer = _bgq_dispatch_timer, 01296 .set_profile = _bgq_set_profile, 01297 .set_domain = _bgq_set_domain, 01298 .ntv_enum_events = _bgq_ntv_enum_events, 01299 .ntv_name_to_code = _bgq_ntv_name_to_code, 01300 .ntv_code_to_name = _bgq_ntv_code_to_name, 01301 .ntv_code_to_descr = _bgq_ntv_code_to_descr, 01302 .ntv_code_to_bits = _bgq_ntv_code_to_bits, 01303 .allocate_registers = _bgq_allocate_registers, 01304 .cleanup_eventset = _bgq_cleanup_eventset, 01305 .shutdown_thread = _bgq_shutdown 01306 // .shutdown_global = 01307 // .user = 01308 }; 01309 01310 papi_os_vector_t _papi_os_vector = { 01311 .get_memory_info = _bgq_get_memory_info, 01312 .get_dmem_info = _bgq_get_dmem_info, 01313 .get_real_cycles = _bgq_get_real_cycles, 01314 .get_real_usec = _bgq_get_real_usec, 01315 .get_virt_cycles = _bgq_get_virt_cycles, 01316 .get_virt_usec = _bgq_get_virt_usec, 01317 .get_system_info = _bgq_get_system_info 01318 };