|
PAPI
5.0.1.0
|
00001 00031 /* Headers required by libsensors */ 00032 #include <sensors.h> 00033 #include <error.h> 00034 #include <time.h> 00035 #include <string.h> 00036 00037 /* Headers required by PAPI */ 00038 #include "papi.h" 00039 #include "papi_internal.h" 00040 #include "papi_vector.h" 00041 #include "papi_memory.h" 00042 00043 /************************* DEFINES SECTION *********************************** 00044 *******************************************************************************/ 00045 /* this number assumes that there will never be more events than indicated */ 00046 #define LM_SENSORS_MAX_COUNTERS 512 00047 // time in usecs 00048 #define LM_SENSORS_REFRESHTIME 200000 00049 00051 typedef struct _lmsensors_register 00052 { 00053 /* This is used by the framework.It likes it to be !=0 to do somehting */ 00054 unsigned int selector; 00055 /* These are the only information needed to locate a libsensors event */ 00056 const sensors_chip_name *name; 00057 int subfeat_nr; 00058 } _lmsensors_register_t; 00059 00060 /* 00061 * The following structures mimic the ones used by other components. It is more 00062 * convenient to use them like that as programming with PAPI makes specific 00063 * assumptions for them. 00064 */ 00065 00067 typedef struct _lmsensors_native_event_entry 00068 { 00069 _lmsensors_register_t resources; 00070 char name[PAPI_MAX_STR_LEN]; 00071 char description[PAPI_MAX_STR_LEN]; 00072 unsigned int count; 00073 } _lmsensors_native_event_entry_t; 00074 00075 00076 typedef struct _lmsensors_reg_alloc 00077 { 00078 _lmsensors_register_t ra_bits; 00079 } _lmsensors_reg_alloc_t; 00080 00081 00082 typedef struct _lmsensors_control_state 00083 { 00084 long_long counts[LM_SENSORS_MAX_COUNTERS]; // used for caching 00085 long_long lastupdate; 00086 } _lmsensors_control_state_t; 00087 00088 00089 typedef struct _lmsensors_context 00090 { 00091 _lmsensors_control_state_t state; 00092 } _lmsensors_context_t; 00093 00094 00095 00096 /************************* GLOBALS SECTION *********************************** 00097 *******************************************************************************/ 00098 /* This table contains the LM_SENSORS native events */ 00099 static _lmsensors_native_event_entry_t *lm_sensors_native_table; 00100 /* number of events in the table*/ 00101 static int num_events = 0; 00102 00103 00104 00105 papi_vector_t _lmsensors_vector; 00106 00107 /****************************************************************************** 00108 ******** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ******** 00109 *****************************************************************************/ 00110 /* 00111 * Counts number of events available in this system 00112 */ 00113 static unsigned 00114 detectSensors( void ) 00115 { 00116 unsigned id = 0; 00117 int chip_nr = 0; 00118 const sensors_chip_name *chip_name; 00119 00120 /* Loop through all the chips, features, subfeatures found */ 00121 while ( ( chip_name = 00122 sensors_get_detected_chips( NULL, &chip_nr ) ) != NULL ) { 00123 int a = 0, b; 00124 const sensors_feature *feature; 00125 00126 while ( ( feature = sensors_get_features( chip_name, &a ) ) ) { 00127 b = 0; 00128 while ( ( sensors_get_all_subfeatures( chip_name, feature, 00129 &b ) ) ) { 00130 id++; 00131 } 00132 } 00133 } 00134 00135 return id; 00136 } 00137 00138 00139 /* 00140 * Create the native events for particulare component (!= 0) 00141 */ 00142 static unsigned 00143 createNativeEvents( void ) 00144 { 00145 unsigned id = 0; 00146 unsigned int count = 0; 00147 00148 int chip_nr = 0; 00149 const sensors_chip_name *chip_name; 00150 00151 /* component name and description */ 00152 strcpy( _lmsensors_vector.cmp_info.short_name, "LM_SENSORS" ); 00153 strcpy( _lmsensors_vector.cmp_info.description, 00154 "lm-sensors provides tools for monitoring the hardware health" ); 00155 00156 00157 /* Loop through all the chips found */ 00158 while ( ( chip_name = 00159 sensors_get_detected_chips( NULL, &chip_nr ) ) != NULL ) { 00160 int a, b; 00161 const sensors_feature *feature; 00162 const sensors_subfeature *sub; 00163 char chipnamestring[PAPI_MIN_STR_LEN]; 00164 00165 // lm_sensors_native_table[id].count = 0; 00166 00167 /* get chip name from its internal representation */ 00168 sensors_snprintf_chip_name( chipnamestring, 00169 PAPI_MIN_STR_LEN, chip_name ); 00170 00171 a = 0; 00172 00173 /* Loop through all the features found */ 00174 while ( ( feature = sensors_get_features( chip_name, &a ) ) ) { 00175 char *featurelabel; 00176 00177 if ( !( featurelabel = sensors_get_label( chip_name, feature ))) { 00178 fprintf( stderr, "ERROR: Can't get label of feature %s!\n", 00179 feature->name ); 00180 continue; 00181 } 00182 00183 b = 0; 00184 00185 /* Loop through all the subfeatures found */ 00186 while ((sub=sensors_get_all_subfeatures(chip_name,feature,&b))) { 00187 00188 count = 0; 00189 00190 /* Save native event data */ 00191 sprintf( lm_sensors_native_table[id].name, "%s.%s.%s.%s", 00192 _lmsensors_vector.cmp_info.short_name, 00193 chipnamestring, featurelabel, sub->name ); 00194 00195 strncpy( lm_sensors_native_table[id].description, 00196 lm_sensors_native_table[id].name, PAPI_MAX_STR_LEN ); 00197 00198 /* The selector has to be !=0 . Starts with 1 */ 00199 lm_sensors_native_table[id].resources.selector = id + 1; 00200 00201 /* Save the actual references to this event */ 00202 lm_sensors_native_table[id].resources.name = chip_name; 00203 lm_sensors_native_table[id].resources.subfeat_nr = sub->number; 00204 00205 count = sub->number; 00206 00207 /* increment the table index counter */ 00208 id++; 00209 } 00210 00211 // lm_sensors_native_table[id].count = count + 1; 00212 free( featurelabel ); 00213 } 00214 } 00215 00216 /* Return the number of events created */ 00217 return id; 00218 } 00219 00220 /* 00221 * Returns the value of the event with index 'i' in lm_sensors_native_table 00222 * This value is scaled by 1000 to cope with the lack to return decimal numbers 00223 * with PAPI 00224 */ 00225 00226 static long_long 00227 getEventValue( unsigned event_id ) 00228 { 00229 double value; 00230 int res; 00231 00232 res = sensors_get_value( lm_sensors_native_table[event_id].resources.name, 00233 lm_sensors_native_table[event_id].resources. 00234 subfeat_nr, &value ); 00235 00236 if ( res < 0 ) { 00237 fprintf( stderr, "libsensors(): Could not read event #%d!\n", 00238 event_id ); 00239 return -1; 00240 } 00241 00242 return ( ( long_long ) ( value * 1000 ) ); 00243 } 00244 00245 00246 /***************************************************************************** 00247 ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS ************* 00248 *****************************************************************************/ 00249 00250 /* 00251 * This is called whenever a thread is initialized 00252 */ 00253 int 00254 _lmsensors_init_thread( hwd_context_t *ctx ) 00255 { 00256 ( void ) ctx; 00257 return PAPI_OK; 00258 } 00259 00260 00261 /* Initialize hardware counters, setup the function vector table 00262 * and get hardware information, this routine is called when the 00263 * PAPI process is initialized (IE PAPI_library_init) 00264 */ 00265 int 00266 _lmsensors_init_component( int cidx ) 00267 { 00268 int res; 00269 (void) cidx; 00270 00271 /* Initialize libsensors library */ 00272 if ( ( res = sensors_init( NULL ) ) != 0 ) { 00273 strncpy(_lmsensors_vector.cmp_info.disabled_reason, 00274 "Cannot enable libsensors",PAPI_MAX_STR_LEN); 00275 return res; 00276 } 00277 00278 /* Create dyanmic events table */ 00279 num_events = detectSensors( ); 00280 SUBDBG("Found %d sensors\n",num_events); 00281 00282 if ( ( lm_sensors_native_table = 00283 calloc( num_events, sizeof ( _lmsensors_native_event_entry_t ))) 00284 == NULL ) { 00285 strncpy(_lmsensors_vector.cmp_info.disabled_reason, 00286 "Could not malloc room",PAPI_MAX_STR_LEN); 00287 return PAPI_ENOMEM; 00288 } 00289 00290 if ( ( unsigned ) num_events != createNativeEvents( ) ) { 00291 strncpy(_lmsensors_vector.cmp_info.disabled_reason, 00292 "LM_SENSOR number mismatch",PAPI_MAX_STR_LEN); 00293 return PAPI_ECMP; 00294 } 00295 00296 _lmsensors_vector.cmp_info.num_native_events=num_events; 00297 _lmsensors_vector.cmp_info.num_cntrs=num_events; 00298 00299 return PAPI_OK; 00300 } 00301 00302 00303 /* 00304 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00305 * functions 00306 */ 00307 int 00308 _lmsensors_init_control_state( hwd_control_state_t *ctl ) 00309 { 00310 int i; 00311 00312 for ( i = 0; i < num_events; i++ ) 00313 ( ( _lmsensors_control_state_t * ) ctl )->counts[i] = 00314 getEventValue( i ); 00315 00316 ( ( _lmsensors_control_state_t * ) ctl )->lastupdate = 00317 PAPI_get_real_usec( ); 00318 return PAPI_OK; 00319 } 00320 00321 00322 /* 00323 * 00324 */ 00325 int 00326 _lmsensors_start( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00327 { 00328 ( void ) ctx; 00329 ( void ) ctl; 00330 00331 return PAPI_OK; 00332 } 00333 00334 00335 /* 00336 * 00337 */ 00338 int 00339 _lmsensors_stop( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00340 { 00341 ( void ) ctx; 00342 ( void ) ctl; 00343 00344 return PAPI_OK; 00345 } 00346 00347 00348 /* 00349 * 00350 */ 00351 int 00352 _lmsensors_read( hwd_context_t *ctx, hwd_control_state_t *ctl, 00353 long_long ** events, int flags ) 00354 { 00355 ( void ) ctx; 00356 ( void ) flags; 00357 long long start = PAPI_get_real_usec( ); 00358 int i; 00359 00360 _lmsensors_control_state_t *control=(_lmsensors_control_state_t *)ctl; 00361 00362 if ( start - control->lastupdate > 200000 ) { // cache refresh 00363 00364 for ( i = 0; i < num_events; i++ ) { 00365 control->counts[i] = getEventValue( i ); 00366 } 00367 control->lastupdate = PAPI_get_real_usec( ); 00368 } 00369 00370 *events = control->counts; 00371 return PAPI_OK; 00372 } 00373 00374 00375 int 00376 _lmsensors_shutdown_component( void ) 00377 { 00378 00379 /* Call the libsensors cleaning function before leaving */ 00380 sensors_cleanup( ); 00381 00382 return PAPI_OK; 00383 } 00384 00385 int 00386 _lmsensors_shutdown_thread( hwd_context_t *ctx ) 00387 { 00388 ( void ) ctx; 00389 00390 return PAPI_OK; 00391 } 00392 00393 00394 00395 /* This function sets various options in the component 00396 * The valid codes being passed in are PAPI_SET_DEFDOM, 00397 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00398 */ 00399 int 00400 _lmsensors_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option ) 00401 { 00402 ( void ) ctx; 00403 ( void ) code; 00404 ( void ) option; 00405 return PAPI_OK; 00406 } 00407 00408 00409 int 00410 _lmsensors_update_control_state( hwd_control_state_t *ctl, 00411 NativeInfo_t * native, 00412 int count, 00413 hwd_context_t *ctx ) 00414 { 00415 int i, index; 00416 ( void ) ctx; 00417 ( void ) ctl; 00418 00419 for ( i = 0; i < count; i++ ) { 00420 index = native[i].ni_event; 00421 native[i].ni_position = 00422 lm_sensors_native_table[index].resources.selector - 1; 00423 } 00424 return PAPI_OK; 00425 } 00426 00427 00428 /* 00429 * This function has to set the bits needed to count different domains 00430 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00431 * By default return PAPI_EINVAL if none of those are specified 00432 * and PAPI_OK with success 00433 * PAPI_DOM_USER is only user context is counted 00434 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00435 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00436 * PAPI_DOM_ALL is all of the domains 00437 */ 00438 int 00439 _lmsensors_set_domain( hwd_control_state_t *ctl, int domain ) 00440 { 00441 int found = 0; 00442 ( void ) ctl; 00443 00444 if ( PAPI_DOM_USER & domain ) 00445 found = 1; 00446 00447 if ( PAPI_DOM_KERNEL & domain ) 00448 found = 1; 00449 00450 if ( PAPI_DOM_OTHER & domain ) 00451 found = 1; 00452 00453 if ( !found ) 00454 return ( PAPI_EINVAL ); 00455 00456 return ( PAPI_OK ); 00457 } 00458 00459 00460 /* 00461 * 00462 */ 00463 int 00464 _lmsensors_reset( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00465 { 00466 ( void ) ctx; 00467 ( void ) ctl; 00468 return PAPI_OK; 00469 } 00470 00471 00472 /* 00473 * Native Event functions 00474 */ 00475 int 00476 _lmsensors_ntv_enum_events( unsigned int *EventCode, int modifier ) 00477 { 00478 00479 switch ( modifier ) { 00480 case PAPI_ENUM_FIRST: 00481 *EventCode = 0; 00482 00483 return PAPI_OK; 00484 break; 00485 00486 case PAPI_ENUM_EVENTS: 00487 { 00488 int index = *EventCode; 00489 00490 if ( index < num_events - 1 ) { 00491 *EventCode = *EventCode + 1; 00492 return PAPI_OK; 00493 } else 00494 return PAPI_ENOEVNT; 00495 00496 break; 00497 } 00498 default: 00499 return PAPI_EINVAL; 00500 } 00501 return PAPI_EINVAL; 00502 } 00503 00504 /* 00505 * 00506 */ 00507 int 00508 _lmsensors_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00509 { 00510 int index = EventCode; 00511 00512 if (index>=0 && index<num_events) { 00513 strncpy( name, lm_sensors_native_table[index].name, len ); 00514 } 00515 00516 return PAPI_OK; 00517 } 00518 00519 /* 00520 * 00521 */ 00522 int 00523 _lmsensors_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00524 { 00525 int index = EventCode; 00526 00527 if (index>=0 && index<num_events) { 00528 strncpy( name, lm_sensors_native_table[index].description, len ); 00529 } 00530 return PAPI_OK; 00531 } 00532 00533 00534 00535 /* 00536 * 00537 */ 00538 papi_vector_t _lmsensors_vector = { 00539 .cmp_info = { 00540 /* component information (unspecified values are initialized to 0) */ 00541 .name = "lmsensors", 00542 .short_name = "lmsensors", 00543 .version = "5.0", 00544 .description = "Linux LMsensor statistics", 00545 .num_mpx_cntrs = LM_SENSORS_MAX_COUNTERS, 00546 .num_cntrs = LM_SENSORS_MAX_COUNTERS, 00547 .default_domain = PAPI_DOM_USER, 00548 //.available_domains = PAPI_DOM_USER, 00549 .default_granularity = PAPI_GRN_THR, 00550 .available_granularities = PAPI_GRN_THR, 00551 .hardware_intr_sig = PAPI_INT_SIGNAL, 00552 00553 /* component specific cmp_info initializations */ 00554 .fast_real_timer = 0, 00555 .fast_virtual_timer = 0, 00556 .attach = 0, 00557 .attach_must_ptrace = 0, 00558 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00559 }, 00560 00561 /* sizes of framework-opaque component-private structures */ 00562 .size = { 00563 .context = sizeof ( _lmsensors_context_t ), 00564 .control_state = sizeof ( _lmsensors_control_state_t ), 00565 .reg_value = sizeof ( _lmsensors_register_t ), 00566 .reg_alloc = sizeof ( _lmsensors_reg_alloc_t ), 00567 }, 00568 /* function pointers in this component */ 00569 .init_thread = _lmsensors_init_thread, 00570 .init_component = _lmsensors_init_component, 00571 .init_control_state = _lmsensors_init_control_state, 00572 .start = _lmsensors_start, 00573 .stop = _lmsensors_stop, 00574 .read = _lmsensors_read, 00575 .shutdown_thread = _lmsensors_shutdown_thread, 00576 .shutdown_component = _lmsensors_shutdown_component, 00577 .ctl = _lmsensors_ctl, 00578 .update_control_state = _lmsensors_update_control_state, 00579 .set_domain = _lmsensors_set_domain, 00580 .reset = _lmsensors_reset, 00581 00582 .ntv_enum_events = _lmsensors_ntv_enum_events, 00583 .ntv_code_to_name = _lmsensors_ntv_code_to_name, 00584 .ntv_code_to_descr = _lmsensors_ntv_code_to_descr, 00585 };