PAPI  5.6.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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);
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 
164  int chip_nr = 0;
165  const sensors_chip_name *chip_name;
166 
167  /* component name and description */
168  strcpy( _lmsensors_vector.cmp_info.short_name, "lm_sensors" );
169  strcpy( _lmsensors_vector.cmp_info.description,
170  "lm-sensors provides tools for monitoring the hardware health" );
171 
172 
173  /* Loop through all the chips found */
174  while ( ( chip_name =
175  sensors_get_detected_chipsPtr( NULL, &chip_nr ) ) != NULL ) {
176  int a, b;
177  const sensors_feature *feature;
178  const sensors_subfeature *sub;
179  char chipnamestring[PAPI_MIN_STR_LEN];
180 
181  // lm_sensors_native_table[id].count = 0;
182 
183  /* get chip name from its internal representation */
184  sensors_snprintf_chip_namePtr( chipnamestring,
185  PAPI_MIN_STR_LEN, chip_name );
186 
187  a = 0;
188 
189  /* Loop through all the features found */
190  while ( ( feature = sensors_get_featuresPtr( chip_name, &a ) ) ) {
191  char *featurelabel;
192 
193  if ( !( featurelabel = sensors_get_labelPtr( chip_name, feature ))) {
194  fprintf( stderr, "ERROR: Can't get label of feature %s!\n",
195  feature->name );
196  continue;
197  }
198 
199  b = 0;
200 
201  /* Loop through all the subfeatures found */
202  while ((sub=sensors_get_all_subfeaturesPtr(chip_name,feature,&b))) {
203 
204  count = 0;
205 
206  /* Save native event data */
207  sprintf( lm_sensors_native_table[id].name, "%s.%s.%s",
208  chipnamestring, featurelabel, sub->name );
209 
210  strncpy( lm_sensors_native_table[id].description,
211  lm_sensors_native_table[id].name, PAPI_MAX_STR_LEN );
212  lm_sensors_native_table[id].description[PAPI_MAX_STR_LEN-1] = '\0';
213 
214  /* The selector has to be !=0 . Starts with 1 */
215  lm_sensors_native_table[id].resources.selector = id + 1;
216 
217  /* Save the actual references to this event */
218  lm_sensors_native_table[id].resources.name = chip_name;
219  lm_sensors_native_table[id].resources.subfeat_nr = sub->number;
220 
221  count = sub->number;
222 
223  /* increment the table index counter */
224  id++;
225  }
226 
227  // lm_sensors_native_table[id].count = count + 1;
228  free( featurelabel );
229  }
230  }
231 
232  /* Return the number of events created */
233  return id;
234 }
235 
236 /*
237  * Returns the value of the event with index 'i' in lm_sensors_native_table
238  * This value is scaled by 1000 to cope with the lack to return decimal numbers
239  * with PAPI
240  */
241 
242 static long_long
243 getEventValue( unsigned event_id )
244 {
245  double value;
246  int res;
247 
248  res = sensors_get_valuePtr( lm_sensors_native_table[event_id].resources.name,
249  lm_sensors_native_table[event_id].resources.
250  subfeat_nr, &value );
251 
252  if ( res < 0 ) {
253  fprintf( stderr, "libsensors(): Could not read event #%d!\n",
254  event_id );
255  return -1;
256  }
257 
258  return ( ( long_long ) ( value * 1000 ) );
259 }
260 
261 
262 /*****************************************************************************
263  ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *************
264  *****************************************************************************/
265 
266 /*
267  * This is called whenever a thread is initialized
268  */
269 static int
271 {
272  ( void ) ctx;
273  return PAPI_OK;
274 }
275 
276 
277 /* Initialize hardware counters, setup the function vector table
278  * and get hardware information, this routine is called when the
279  * PAPI process is initialized (IE PAPI_library_init)
280  */
281 static int
283 {
284  int res;
285  (void) cidx;
286 
287  /* link in all the lmsensor libraries and resolve the symbols we need to use */
289  SUBDBG ("Dynamic link of lmsensors libraries failed, component will be disabled.\n");
290  SUBDBG ("See disable reason in papi_component_avail output for more details.\n");
291  return (PAPI_ENOSUPP);
292  }
293 
294  /* Initialize libsensors library */
295  if ( ( res = sensors_initPtr( NULL ) ) != 0 ) {
296  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
297  "Cannot enable libsensors",PAPI_MAX_STR_LEN);
298  return res;
299  }
300 
301  /* Create dyanmic events table */
303  SUBDBG("Found %d sensors\n",num_events);
304 
305  _lmsensors_vector.cmp_info.num_mpx_cntrs = num_events;
306  _lmsensors_vector.cmp_info.num_cntrs = num_events;
307 
308  if ( ( lm_sensors_native_table =
309  calloc( num_events, sizeof ( _lmsensors_native_event_entry_t )))
310  == NULL ) {
311  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
312  "Could not malloc room",PAPI_MAX_STR_LEN);
313  return PAPI_ENOMEM;
314  }
315 
316  cached_counts = (long long*) calloc(num_events, sizeof(long long));
317 
318  if (cached_counts == NULL) {
319  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
320  "Could not malloc room",PAPI_MAX_STR_LEN);
321  return PAPI_ENOMEM;
322  }
323 
324  if ( ( unsigned ) num_events != createNativeEvents( ) ) {
325  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
326  "LM_SENSOR number mismatch",PAPI_MAX_STR_LEN);
327  return PAPI_ECMP;
328  }
329 
330  _lmsensors_vector.cmp_info.num_native_events=num_events;
331  _lmsensors_vector.cmp_info.num_cntrs=num_events;
332 
333  return PAPI_OK;
334 }
335 
336 /*
337  * Link the necessary lmsensors libraries to use the lmsensors
338  * component. If any of them can not be found, then the lmsensors
339  * component will just be disabled. This is done at runtime so that a
340  * version of PAPI built with the Infiniband component can be
341  * installed and used on systems which have the lmsensors libraries
342  * installed and on systems where these libraries are not installed.
343  */
344 static int
346 {
347  /* Need to link in the lmsensors libraries, if not found disable the component */
348  dl1 = dlopen("libsensors.so", RTLD_NOW | RTLD_GLOBAL);
349  if (!dl1)
350  {
351  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
352  "lmsensors library libsensors.so not found.",PAPI_MAX_STR_LEN);
353  return ( PAPI_ENOSUPP );
354  }
355  sensors_initPtr = dlsym(dl1, "sensors_init");
356  if (dlerror() != NULL)
357  {
358  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
359  "lmsensor function sensors_init.",PAPI_MAX_STR_LEN);
360  return ( PAPI_ENOSUPP );
361  }
362  sensors_cleanupPtr = dlsym(dl1, "sensors_cleanup");
363  if (dlerror() != NULL)
364  {
365  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
366  "lmsensor function sensors_cleanup.",PAPI_MAX_STR_LEN);
367  return ( PAPI_ENOSUPP );
368  }
369  sensors_snprintf_chip_namePtr = dlsym(dl1, "sensors_snprintf_chip_name");
370  if (dlerror() != NULL)
371  {
372  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
373  "lmsensor function sensors_snprintf_chip_name.",PAPI_MAX_STR_LEN);
374  return ( PAPI_ENOSUPP );
375  }
376  sensors_get_labelPtr = dlsym(dl1, "sensors_get_label");
377  if (dlerror() != NULL)
378  {
379  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
380  "lmsensor function sensors_get_label.",PAPI_MAX_STR_LEN);
381  return ( PAPI_ENOSUPP );
382  }
383  sensors_get_valuePtr = dlsym(dl1, "sensors_get_value");
384  if (dlerror() != NULL)
385  {
386  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
387  "lmsensor function sensors_get_value.",PAPI_MAX_STR_LEN);
388  return ( PAPI_ENOSUPP );
389  }
390  sensors_get_detected_chipsPtr = dlsym(dl1, "sensors_get_detected_chips");
391  if (dlerror() != NULL)
392  {
393  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
394  "lmsensor function sensors_get_detected_chips.",PAPI_MAX_STR_LEN);
395  return ( PAPI_ENOSUPP );
396  }
397  sensors_get_featuresPtr = dlsym(dl1, "sensors_get_features");
398  if (dlerror() != NULL)
399  {
400  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
401  "lmsensor function sensors_get_features.",PAPI_MAX_STR_LEN);
402  return ( PAPI_ENOSUPP );
403  }
404  sensors_get_all_subfeaturesPtr = dlsym(dl1, "sensors_get_all_subfeatures");
405  if (dlerror() != NULL)
406  {
407  strncpy(_lmsensors_vector.cmp_info.disabled_reason,
408  "lmsensor function sensors_get_all_subfeatures.",PAPI_MAX_STR_LEN);
409  return ( PAPI_ENOSUPP );
410  }
411 
412  return ( PAPI_OK );
413 }
414 
415 /*
416  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
417  * functions
418  */
419 static int
421 {
422  int i;
423 
424  for ( i = 0; i < num_events; i++ )
425  cached_counts[i] = getEventValue( i );
426 
427  ( ( _lmsensors_control_state_t * ) ctl )->lastupdate =
429  return PAPI_OK;
430 }
431 
432 
433 /*
434  *
435  */
436 static int
438 {
439  ( void ) ctx;
440  ( void ) ctl;
441 
442  return PAPI_OK;
443 }
444 
445 
446 /*
447  *
448  */
449 static int
451 {
452  ( void ) ctx;
453  ( void ) ctl;
454 
455  return PAPI_OK;
456 }
457 
458 
459 /*
460  *
461  */
462 static int
464  long_long ** events, int flags )
465 {
466  ( void ) ctx;
467  ( void ) flags;
468  long long start = PAPI_get_real_usec( );
469  int i;
470 
472 
473  if ( start - control->lastupdate > 200000 ) { // cache refresh
474 
475  for ( i = 0; i < num_events; i++ ) {
476  cached_counts[i] = getEventValue( i );
477  }
478  control->lastupdate = PAPI_get_real_usec( );
479  }
480 
481  *events = cached_counts;
482  return PAPI_OK;
483 }
484 
485 
486 static int
488 {
489  if (cached_counts)
491 
492  /* Call the libsensors cleaning function before leaving */
494 
495  return PAPI_OK;
496 }
497 
498 static int
500 {
501  ( void ) ctx;
502 
503  return PAPI_OK;
504 }
505 
506 
507 
508 /* This function sets various options in the component
509  * The valid codes being passed in are PAPI_SET_DEFDOM,
510  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
511  */
512 static int
514 {
515  ( void ) ctx;
516  ( void ) code;
517  ( void ) option;
518  return PAPI_OK;
519 }
520 
521 
522 static int
524  NativeInfo_t * native,
525  int count,
526  hwd_context_t *ctx )
527 {
528  int i, index;
529  ( void ) ctx;
530  ( void ) ctl;
531 
532  for ( i = 0; i < count; i++ ) {
533  index = native[i].ni_event;
534  native[i].ni_position =
535  lm_sensors_native_table[index].resources.selector - 1;
536  }
537  return PAPI_OK;
538 }
539 
540 
541 /*
542  * As I understand it, all data reported by these interfaces will be system wide
543  */
544 static int
546 {
547  (void) ctl;
548  if ( PAPI_DOM_ALL != domain )
549  return ( PAPI_EINVAL );
550 
551  return ( PAPI_OK );
552 }
553 
554 
555 /*
556  *
557  */
558 static int
560 {
561  ( void ) ctx;
562  ( void ) ctl;
563  return PAPI_OK;
564 }
565 
566 
567 /*
568  * Native Event functions
569  */
570 static int
571 _lmsensors_ntv_enum_events( unsigned int *EventCode, int modifier )
572 {
573 
574  switch ( modifier ) {
575  case PAPI_ENUM_FIRST:
576  *EventCode = 0;
577 
578  return PAPI_OK;
579  break;
580 
581  case PAPI_ENUM_EVENTS:
582  {
583  int index = *EventCode;
584 
585  if ( index < num_events - 1 ) {
586  *EventCode = *EventCode + 1;
587  return PAPI_OK;
588  } else
589  return PAPI_ENOEVNT;
590 
591  break;
592  }
593  default:
594  return PAPI_EINVAL;
595  }
596  return PAPI_EINVAL;
597 }
598 
599 /*
600  *
601  */
602 static int
603 _lmsensors_ntv_code_to_name( unsigned int EventCode, char *name, int len )
604 {
605  int index = EventCode;
606 
607  if (index>=0 && index<num_events) {
608  strncpy( name, lm_sensors_native_table[index].name, len );
609  }
610 
611  return PAPI_OK;
612 }
613 
614 /*
615  *
616  */
617 static int
618 _lmsensors_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
619 {
620  int index = EventCode;
621 
622  if (index>=0 && index<num_events) {
623  strncpy( name, lm_sensors_native_table[index].description, len );
624  }
625  return PAPI_OK;
626 }
627 
628 
629 
630 /*
631  *
632  */
633 papi_vector_t _lmsensors_vector = {
634  .cmp_info = {
635  /* component information (unspecified values are initialized to 0) */
636  .name = "lmsensors",
637  .short_name = "lmsensors",
638  .version = "5.0",
639  .description = "Linux LMsensor statistics",
640  .num_mpx_cntrs = 0,
641  .num_cntrs = 0,
642  .default_domain = PAPI_DOM_ALL,
643  .default_granularity = PAPI_GRN_SYS,
644  .available_granularities = PAPI_GRN_SYS,
645  .hardware_intr_sig = PAPI_INT_SIGNAL,
646 
647  /* component specific cmp_info initializations */
648  .fast_real_timer = 0,
649  .fast_virtual_timer = 0,
650  .attach = 0,
651  .attach_must_ptrace = 0,
652  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
653  },
654 
655  /* sizes of framework-opaque component-private structures */
656  .size = {
657  .context = sizeof ( _lmsensors_context_t ),
658  .control_state = sizeof ( _lmsensors_control_state_t ),
659  .reg_value = sizeof ( _lmsensors_register_t ),
660  .reg_alloc = sizeof ( _lmsensors_reg_alloc_t ),
661  },
662  /* function pointers in this component */
663  .init_thread = _lmsensors_init_thread,
664  .init_component = _lmsensors_init_component,
665  .init_control_state = _lmsensors_init_control_state,
666  .start = _lmsensors_start,
667  .stop = _lmsensors_stop,
668  .read = _lmsensors_read,
669  .shutdown_thread = _lmsensors_shutdown_thread,
670  .shutdown_component = _lmsensors_shutdown_component,
671  .ctl = _lmsensors_ctl,
672  .update_control_state = _lmsensors_update_control_state,
673  .set_domain = _lmsensors_set_domain,
674  .reset = _lmsensors_reset,
675 
676  .ntv_enum_events = _lmsensors_ntv_enum_events,
677  .ntv_code_to_name = _lmsensors_ntv_code_to_name,
678  .ntv_code_to_descr = _lmsensors_ntv_code_to_descr,
679 };
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:629
#define PAPI_ENOEVNT
Definition: papi.h:260
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
static int _lmsensors_init_component(int cidx)
static long_long * cached_counts
static int _lmsensors_ntv_code_to_name(unsigned int EventCode, char *name, int len)
static int _lmsensors_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
long long flags
Definition: iozone.c:12330
static int _lmsensors_shutdown_thread(hwd_context_t *ctx)
char description[PAPI_MAX_STR_LEN]
start
Definition: iozone.c:22736
#define PAPI_ENOSUPP
Definition: papi.h:271
static int _lmsensors_init_thread(hwd_context_t *ctx)
unsigned int count
#define PAPI_DOM_KERNEL
Definition: papi.h:300
static unsigned createNativeEvents(void)
#define PAPI_DOM_ALL
Definition: papi.h:303
static int _lmsensors_shutdown_component(void)
return PAPI_OK
Definition: linux-nvml.c:497
int count
Definition: iozone.c:22422
#define PAPI_DOM_USER
Definition: papi.h:298
void
Definition: iozone.c:18627
return PAPI_EINVAL
Definition: linux-nvml.c:436
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
char short_name[PAPI_MIN_STR_LEN]
Definition: papi.h:630
static int _lmsensors_set_domain(hwd_control_state_t *ctl, int domain)
static const sensors_subfeature *(* sensors_get_all_subfeaturesPtr)(const sensors_chip_name *name, const sensors_feature *feature, int *nr)
void double value
Definition: iozone.c:18781
Return codes and api definitions.
static void(* sensors_cleanupPtr)(void)
char events[MAX_EVENTS][BUFSIZ]
static int num_events
static int _lmsensors_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
static int cidx
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:636
static unsigned detectSensors(void)
static long_long getEventValue(unsigned event_id)
int i
Definition: fileop.c:140
static int _lmsensors_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
char *long long size
Definition: iozone.c:12023
free(dummyfile[xx])
static int native
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
static int(* sensors_get_valuePtr)(const sensors_chip_name *name, int subfeat_nr, double *value)
#define PAPI_ECMP
Definition: papi.h:256
static _lmsensors_native_event_entry_t * lm_sensors_native_table
char description[PAPI_MAX_STR_LEN]
Definition: papi.h:632
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static int(* sensors_snprintf_chip_namePtr)(char *str, size_t size, const sensors_chip_name *chip)
#define PAPI_ENOMEM
Definition: papi.h:254
static int _lmsensors_ntv_enum_events(unsigned int *EventCode, int modifier)
static char *(* sensors_get_labelPtr)(const sensors_chip_name *name, const sensors_feature *feature)
char name[PAPI_MAX_STR_LEN]
strcpy(filename, default_filename)
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)
long long PAPI_get_real_usec(void)
Definition: papi.c:6264
char * name
Definition: iozone.c:23648
int
Definition: iozone.c:18528
#define PAPI_MIN_STR_LEN
Definition: papi.h:464
#define long_long
Definition: papi.h:552
_lmsensors_control_state_t state
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
#define PAPI_MAX_STR_LEN
Definition: papi.h:465
papi_vector_t _lmsensors_vector
static const sensors_feature *(* sensors_get_featuresPtr)(const sensors_chip_name *name, int *nr)
#define PAPI_GRN_SYS
Definition: papi.h:366
const sensors_chip_name * name
static int _lmsensors_init_control_state(hwd_control_state_t *ctl)
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
_lmsensors_register_t resources
static int link_lmsensors_libraries()
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
_lmsensors_register_t ra_bits
static int(* sensors_initPtr)(FILE *input)