PAPI  5.0.1.0
linux-lmsensors.c
Go to the documentation of this file.
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 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines