PAPI  5.7.0.0
linux-lmsensors.c
Go to the documentation of this file.
1 
31 /* Headers required by libsensors */
32 #include <sensors.h>
33 #include <error.h>
34 #include <time.h>
35 #include <string.h>
36 #include <dlfcn.h>
37 
38 /* Headers required by PAPI */
39 #include "papi.h"
40 #include "papi_internal.h"
41 #include "papi_vector.h"
42 #include "papi_memory.h"
43 
44 /************************* DEFINES SECTION ***********************************
45  *******************************************************************************/
46 // time in usecs
47 #define LM_SENSORS_REFRESHTIME 200000
48 
50 typedef struct _lmsensors_register
51 {
52  /* This is used by the framework.It likes it to be !=0 to do somehting */
53  unsigned int selector;
54  /* These are the only information needed to locate a libsensors event */
55  const sensors_chip_name *name;
58 
59 /*
60  * The following structures mimic the ones used by other components. It is more
61  * convenient to use them like that as programming with PAPI makes specific
62  * assumptions for them.
63  */
64 
66 typedef struct _lmsensors_native_event_entry
67 {
70  char description[PAPI_MAX_STR_LEN];
71  unsigned int count;
73 
74 
75 typedef struct _lmsensors_reg_alloc
76 {
79 
80 
81 typedef struct _lmsensors_control_state
82 {
85 
86 
87 typedef struct _lmsensors_context
88 {
91 
92 
93 
94 /************************* GLOBALS SECTION ***********************************
95  *******************************************************************************/
96 /* This table contains the LM_SENSORS native events */
98 /* number of events in the table*/
99 static int num_events = 0;
100 static long_long *cached_counts = NULL; // used for caching readings
101 
102 
103 static int (*sensors_initPtr)(FILE *input);
104 static void (*sensors_cleanupPtr)(void);
105 static int (*sensors_snprintf_chip_namePtr)(char *str, size_t size,
106  const sensors_chip_name *chip);
107 static char *(*sensors_get_labelPtr)(const sensors_chip_name *name, const sensors_feature *feature);
108 static int (*sensors_get_valuePtr)(const sensors_chip_name *name, int subfeat_nr,
109  double *value);
110 static const sensors_chip_name *(*sensors_get_detected_chipsPtr)(const sensors_chip_name
111  *match, int *nr);
112 static const sensors_feature *(*sensors_get_featuresPtr)(const sensors_chip_name *name, int *nr);
113 static const sensors_subfeature *(*sensors_get_all_subfeaturesPtr)(const sensors_chip_name *name,
114  const sensors_feature *feature, int *nr);
115 
116 // file handles used to access lmsensors libraries with dlopen
117 static void* dl1 = NULL;
118 
119 static int link_lmsensors_libraries ();
120 
122 
123 /******************************************************************************
124  ******** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ********
125  *****************************************************************************/
126 /*
127  * Counts number of events available in this system
128  */
129 static unsigned
131 {
132  unsigned id = 0;
133  int chip_nr = 0;
134  const sensors_chip_name *chip_name;
135 
136  /* Loop through all the chips, features, subfeatures found */
137  while ( ( chip_name =
138  sensors_get_detected_chipsPtr( NULL, &chip_nr ) ) != NULL ) {
139  int a = 0, b;
140  const sensors_feature *feature;
141 
142  while ( ( feature = sensors_get_featuresPtr( chip_name, &a ) ) ) {
143  b = 0;
144  while ( ( sensors_get_all_subfeaturesPtr( chip_name, feature,
145  &b ) ) ) {
146  id++;
147  }
148  }
149  }
150 
151  return id;
152 }
153 
154 
155 /*
156  * Create the native events for particulare component (!= 0)
157  */
158 static unsigned
160 {
161  unsigned id = 0;
162  unsigned int count;
163  (void) count; // Ignore not used warnings.
164 
165  int chip_nr = 0;
166  const sensors_chip_name *chip_name;
167 
168  /* component name and description */
169  strcpy( _lmsensors_vector.cmp_info.short_name, "lm_sensors" );
171  "lm-sensors provides tools for monitoring the hardware health" );
172 
173 
174  /* Loop through all the chips found */
175  while ( ( chip_name =
176  sensors_get_detected_chipsPtr( NULL, &chip_nr ) ) != NULL ) {
177  int a, b;
178  const sensors_feature *feature;
179  const sensors_subfeature *sub;
180  char chipnamestring[PAPI_MIN_STR_LEN];
181 
182  // lm_sensors_native_table[id].count = 0;
183 
184  /* get chip name from its internal representation */
185  sensors_snprintf_chip_namePtr( chipnamestring,
186  PAPI_MIN_STR_LEN, chip_name );
187 
188  a = 0;
189 
190  /* Loop through all the features found */
191  while ( ( feature = sensors_get_featuresPtr( chip_name, &a ) ) ) {
192  char *featurelabel;
193 
194  if ( !( featurelabel = sensors_get_labelPtr( chip_name, feature ))) {
195  fprintf( stderr, "ERROR: Can't get label of feature %s!\n",
196  feature->name );
197  continue;
198  }
199 
200  b = 0;
201 
202  /* Loop through all the subfeatures found */
203  while ((sub=sensors_get_all_subfeaturesPtr(chip_name,feature,&b))) {
204 
205  count = 0;
206 
207  /* Save native event data */
208  sprintf( lm_sensors_native_table[id].name, "%s.%s.%s",
209  chipnamestring, featurelabel, sub->name );
210 
211  strncpy( lm_sensors_native_table[id].description,
214 
215  /* The selector has to be !=0 . Starts with 1 */
217 
218  /* Save the actual references to this event */
219  lm_sensors_native_table[id].resources.name = chip_name;
220  lm_sensors_native_table[id].resources.subfeat_nr = sub->number;
221 
222  count = sub->number;
223 
224  /* increment the table index counter */
225  id++;
226  }
227 
228  // lm_sensors_native_table[id].count = count + 1;
229  free( featurelabel );
230  }
231  }
232 
233  /* Return the number of events created */
234  return id;
235 }
236 
237 /*
238  * Returns the value of the event with index 'i' in lm_sensors_native_table
239  * This value is scaled by 1000 to cope with the lack to return decimal numbers
240  * with PAPI
241  */
242 
243 static long_long
244 getEventValue( unsigned event_id )
245 {
246  double value;
247  int res;
248 
249  res = sensors_get_valuePtr( lm_sensors_native_table[event_id].resources.name,
251  subfeat_nr, &value );
252 
253  if ( res < 0 ) {
254  fprintf( stderr, "libsensors(): Could not read event #%d!\n",
255  event_id );
256  return -1;
257  }
258 
259  return ( ( long_long ) ( value * 1000 ) );
260 }
261 
262 
263 /*****************************************************************************
264  ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *************
265  *****************************************************************************/
266 
267 /*
268  * This is called whenever a thread is initialized
269  */
270 static int
272 {
273  ( void ) ctx;
274  return PAPI_OK;
275 }
276 
277 
278 /* Initialize hardware counters, setup the function vector table
279  * and get hardware information, this routine is called when the
280  * PAPI process is initialized (IE PAPI_library_init)
281  */
282 static int
284 {
285  int res;
286  (void) cidx;
287 
288  /* link in all the lmsensor libraries and resolve the symbols we need to use */
290  SUBDBG ("Dynamic link of lmsensors libraries failed, component will be disabled.\n");
291  SUBDBG ("See disable reason in papi_component_avail output for more details.\n");
292  return (PAPI_ENOSUPP);
293  }
294 
295  /* Initialize libsensors library */
296  if ( ( res = sensors_initPtr( NULL ) ) != 0 ) {
298  "Cannot enable libsensors",PAPI_MAX_STR_LEN);
299  return res;
300  }
301 
302  /* Create dyanmic events table */
304  SUBDBG("Found %d sensors\n",num_events);
305 
308 
309  if ( ( lm_sensors_native_table =
310  calloc( num_events, sizeof ( _lmsensors_native_event_entry_t )))
311  == NULL ) {
313  "Could not malloc room",PAPI_MAX_STR_LEN);
314  return PAPI_ENOMEM;
315  }
316 
317  cached_counts = (long long*) calloc(num_events, sizeof(long long));
318 
319  if (cached_counts == NULL) {
321  "Could not malloc room",PAPI_MAX_STR_LEN);
324  return PAPI_ENOMEM;
325  }
326 
327  if ( ( unsigned ) num_events != createNativeEvents( ) ) {
329  "LM_SENSOR number mismatch",PAPI_MAX_STR_LEN);
330  free(cached_counts);
331  cached_counts = NULL;
334  return PAPI_ECMP;
335  }
336 
339 
340  return PAPI_OK;
341 }
342 
343 /*
344  * Link the necessary lmsensors libraries to use the lmsensors
345  * component. If any of them can not be found, then the lmsensors
346  * component will just be disabled. This is done at runtime so that a
347  * version of PAPI built with the Infiniband component can be
348  * installed and used on systems which have the lmsensors libraries
349  * installed and on systems where these libraries are not installed.
350  */
351 static int
353 {
354  /* Need to link in the lmsensors libraries, if not found disable the component */
355  dl1 = dlopen("libsensors.so", RTLD_NOW | RTLD_GLOBAL);
356  if (!dl1)
357  {
359  "lmsensors library libsensors.so not found.",PAPI_MAX_STR_LEN);
360  return ( PAPI_ENOSUPP );
361  }
362  sensors_initPtr = dlsym(dl1, "sensors_init");
363  if (dlerror() != NULL)
364  {
366  "lmsensor function sensors_init.",PAPI_MAX_STR_LEN);
367  return ( PAPI_ENOSUPP );
368  }
369  sensors_cleanupPtr = dlsym(dl1, "sensors_cleanup");
370  if (dlerror() != NULL)
371  {
373  "lmsensor function sensors_cleanup.",PAPI_MAX_STR_LEN);
374  return ( PAPI_ENOSUPP );
375  }
376  sensors_snprintf_chip_namePtr = dlsym(dl1, "sensors_snprintf_chip_name");
377  if (dlerror() != NULL)
378  {
380  "lmsensor function sensors_snprintf_chip_name.",PAPI_MAX_STR_LEN);
381  return ( PAPI_ENOSUPP );
382  }
383  sensors_get_labelPtr = dlsym(dl1, "sensors_get_label");
384  if (dlerror() != NULL)
385  {
387  "lmsensor function sensors_get_label.",PAPI_MAX_STR_LEN);
388  return ( PAPI_ENOSUPP );
389  }
390  sensors_get_valuePtr = dlsym(dl1, "sensors_get_value");
391  if (dlerror() != NULL)
392  {
394  "lmsensor function sensors_get_value.",PAPI_MAX_STR_LEN);
395  return ( PAPI_ENOSUPP );
396  }
397  sensors_get_detected_chipsPtr = dlsym(dl1, "sensors_get_detected_chips");
398  if (dlerror() != NULL)
399  {
401  "lmsensor function sensors_get_detected_chips.",PAPI_MAX_STR_LEN);
402  return ( PAPI_ENOSUPP );
403  }
404  sensors_get_featuresPtr = dlsym(dl1, "sensors_get_features");
405  if (dlerror() != NULL)
406  {
408  "lmsensor function sensors_get_features.",PAPI_MAX_STR_LEN);
409  return ( PAPI_ENOSUPP );
410  }
411  sensors_get_all_subfeaturesPtr = dlsym(dl1, "sensors_get_all_subfeatures");
412  if (dlerror() != NULL)
413  {
415  "lmsensor function sensors_get_all_subfeatures.",PAPI_MAX_STR_LEN);
416  return ( PAPI_ENOSUPP );
417  }
418 
419  return ( PAPI_OK );
420 }
421 
422 /*
423  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
424  * functions
425  */
426 static int
428 {
429  int i;
430 
431  for ( i = 0; i < num_events; i++ )
433 
434  ( ( _lmsensors_control_state_t * ) ctl )->lastupdate =
436  return PAPI_OK;
437 }
438 
439 
440 /*
441  *
442  */
443 static int
445 {
446  ( void ) ctx;
447  ( void ) ctl;
448 
449  return PAPI_OK;
450 }
451 
452 
453 /*
454  *
455  */
456 static int
458 {
459  ( void ) ctx;
460  ( void ) ctl;
461 
462  return PAPI_OK;
463 }
464 
465 
466 /*
467  *
468  */
469 static int
471  long_long ** events, int flags )
472 {
473  ( void ) ctx;
474  ( void ) flags;
475  long long start = PAPI_get_real_usec( );
476  int i;
477 
479 
480  if ( start - control->lastupdate > 200000 ) { // cache refresh
481 
482  for ( i = 0; i < num_events; i++ ) {
484  }
485  control->lastupdate = PAPI_get_real_usec( );
486  }
487 
489  return PAPI_OK;
490 }
491 
492 
493 static int
495 {
496  if (cached_counts) {
497  free(cached_counts);
498  cached_counts = NULL;
499  }
500 
501  /* Call the libsensors cleaning function before leaving */
503 
507  }
508 
509  return PAPI_OK;
510 }
511 
512 static int
514 {
515  ( void ) ctx;
516 
517  return PAPI_OK;
518 }
519 
520 
521 
522 /* This function sets various options in the component
523  * The valid codes being passed in are PAPI_SET_DEFDOM,
524  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
525  */
526 static int
528 {
529  ( void ) ctx;
530  ( void ) code;
531  ( void ) option;
532  return PAPI_OK;
533 }
534 
535 
536 static int
538  NativeInfo_t * native,
539  int count,
540  hwd_context_t *ctx )
541 {
542  int i, index;
543  ( void ) ctx;
544  ( void ) ctl;
545 
546  for ( i = 0; i < count; i++ ) {
547  index = native[i].ni_event;
548  native[i].ni_position =
550  }
551  return PAPI_OK;
552 }
553 
554 
555 /*
556  * As I understand it, all data reported by these interfaces will be system wide
557  */
558 static int
560 {
561  (void) ctl;
562  if ( PAPI_DOM_ALL != domain )
563  return ( PAPI_EINVAL );
564 
565  return ( PAPI_OK );
566 }
567 
568 
569 /*
570  *
571  */
572 static int
574 {
575  ( void ) ctx;
576  ( void ) ctl;
577  return PAPI_OK;
578 }
579 
580 
581 /*
582  * Native Event functions
583  */
584 static int
585 _lmsensors_ntv_enum_events( unsigned int *EventCode, int modifier )
586 {
587 
588  switch ( modifier ) {
589  case PAPI_ENUM_FIRST:
590  *EventCode = 0;
591 
592  return PAPI_OK;
593  break;
594 
595  case PAPI_ENUM_EVENTS:
596  {
597  int index = *EventCode;
598 
599  if ( index < num_events - 1 ) {
600  *EventCode = *EventCode + 1;
601  return PAPI_OK;
602  } else
603  return PAPI_ENOEVNT;
604 
605  break;
606  }
607  default:
608  return PAPI_EINVAL;
609  }
610  return PAPI_EINVAL;
611 }
612 
613 /*
614  *
615  */
616 static int
617 _lmsensors_ntv_code_to_name( unsigned int EventCode, char *name, int len )
618 {
619  int index = EventCode;
620 
621  if (index>=0 && index<num_events) {
622  strncpy( name, lm_sensors_native_table[index].name, len );
623  }
624 
625  return PAPI_OK;
626 }
627 
628 /*
629  *
630  */
631 static int
632 _lmsensors_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
633 {
634  int index = EventCode;
635 
636  if (index>=0 && index<num_events) {
637  strncpy( name, lm_sensors_native_table[index].description, len );
638  }
639  return PAPI_OK;
640 }
641 
642 
643 
644 /*
645  *
646  */
648  .cmp_info = {
649  /* component information (unspecified values are initialized to 0) */
650  .name = "lmsensors",
651  .short_name = "lmsensors",
652  .version = "5.0",
653  .description = "Linux LMsensor statistics",
654  .num_mpx_cntrs = 0,
655  .num_cntrs = 0,
656  .default_domain = PAPI_DOM_ALL,
657  .default_granularity = PAPI_GRN_SYS,
658  .available_granularities = PAPI_GRN_SYS,
659  .hardware_intr_sig = PAPI_INT_SIGNAL,
660 
661  /* component specific cmp_info initializations */
662  .fast_real_timer = 0,
663  .fast_virtual_timer = 0,
664  .attach = 0,
665  .attach_must_ptrace = 0,
666  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
667  },
668 
669  /* sizes of framework-opaque component-private structures */
670  .size = {
671  .context = sizeof ( _lmsensors_context_t ),
672  .control_state = sizeof ( _lmsensors_control_state_t ),
673  .reg_value = sizeof ( _lmsensors_register_t ),
674  .reg_alloc = sizeof ( _lmsensors_reg_alloc_t ),
675  },
676  /* function pointers in this component */
677  .init_thread = _lmsensors_init_thread,
678  .init_component = _lmsensors_init_component,
679  .init_control_state = _lmsensors_init_control_state,
680  .start = _lmsensors_start,
681  .stop = _lmsensors_stop,
682  .read = _lmsensors_read,
683  .shutdown_thread = _lmsensors_shutdown_thread,
684  .shutdown_component = _lmsensors_shutdown_component,
685  .ctl = _lmsensors_ctl,
686  .update_control_state = _lmsensors_update_control_state,
687  .set_domain = _lmsensors_set_domain,
688  .reset = _lmsensors_reset,
689 
690  .ntv_enum_events = _lmsensors_ntv_enum_events,
691  .ntv_code_to_name = _lmsensors_ntv_code_to_name,
692  .ntv_code_to_descr = _lmsensors_ntv_code_to_descr,
693 };
#define PAPI_OK
Definition: fpapi.h:105
static void(* sensors_cleanupPtr)(void)
static int _lmsensors_init_component(int cidx)
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:637
#define PAPI_ENOMEM
Definition: fpapi.h:107
static const char * name
Definition: fork_overflow.c:31
static long_long * cached_counts
static int _lmsensors_ntv_code_to_name(unsigned int EventCode, char *name, int len)
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
#define PAPI_EINVAL
Definition: fpapi.h:106
static int _lmsensors_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _lmsensors_shutdown_thread(hwd_context_t *ctx)
static int(* sensors_get_valuePtr)(const sensors_chip_name *name, int subfeat_nr, double *value)
#define PAPI_ENOSUPP
Definition: fpapi.h:123
char description[PAPI_MAX_STR_LEN]
static int _lmsensors_init_thread(hwd_context_t *ctx)
static const sensors_feature *(* sensors_get_featuresPtr)(const sensors_chip_name *name, int *nr)
unsigned int count
static unsigned createNativeEvents(void)
#define PAPI_GRN_SYS
Definition: fpapi.h:71
static int _lmsensors_shutdown_component(void)
static struct timeval start
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
static int _lmsensors_set_domain(hwd_control_state_t *ctl, int domain)
char short_name[PAPI_MIN_STR_LEN]
Definition: papi.h:631
Return codes and api definitions.
char events[MAX_EVENTS][BUFSIZ]
#define PAPI_ECMP
Definition: fpapi.h:109
static int num_events
static int _lmsensors_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
static char *(* sensors_get_labelPtr)(const sensors_chip_name *name, const sensors_feature *feature)
static int cidx
static unsigned detectSensors(void)
static long_long getEventValue(unsigned event_id)
static const sensors_subfeature *(* sensors_get_all_subfeaturesPtr)(const sensors_chip_name *name, const sensors_feature *feature, int *nr)
static int _lmsensors_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
#define PAPI_DOM_USER
Definition: fpapi.h:21
#define PAPI_MIN_STR_LEN
Definition: fpapi.h:41
static int native
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
static _lmsensors_native_event_entry_t * lm_sensors_native_table
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:630
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static int _lmsensors_ntv_enum_events(unsigned int *EventCode, int modifier)
char name[PAPI_MAX_STR_LEN]
static const sensors_chip_name *(* sensors_get_detected_chipsPtr)(const sensors_chip_name *match, int *nr)
static int _lmsensors_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
static int(* sensors_snprintf_chip_namePtr)(char *str, size_t size, const sensors_chip_name *chip)
long long PAPI_get_real_usec(void)
Definition: papi.c:6264
#define PAPI_ENOEVNT
Definition: fpapi.h:112
#define long_long
Definition: papi.h:553
static int(* sensors_initPtr)(FILE *input)
_lmsensors_control_state_t state
char description[PAPI_MAX_STR_LEN]
Definition: papi.h:633
static int _lmsensors_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int _lmsensors_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
static void * dl1
papi_vector_t _lmsensors_vector
const sensors_chip_name * name
static int _lmsensors_init_control_state(hwd_control_state_t *ctl)
#define PAPI_DOM_ALL
Definition: fpapi.h:25
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
_lmsensors_register_t resources
static int link_lmsensors_libraries()
static long count
static int _lmsensors_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long_long **events, int flags)
static double a[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:38
int i
Definition: fileop.c:140
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
_lmsensors_register_t ra_bits