PAPI  5.7.0.0
linux-powercap.c
Go to the documentation of this file.
1 
10 #include <stdio.h>
11 #include <dirent.h>
12 #include <unistd.h>
13 #include <dirent.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #include <stdint.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 
22 /* Headers required by PAPI */
23 #include "papi.h"
24 #include "papi_internal.h"
25 #include "papi_vector.h"
26 #include "papi_memory.h"
27 
28 
29 typedef struct _powercap_register {
30  unsigned int selector;
32 
33 typedef struct _powercap_native_event_entry {
36  char description[PAPI_MAX_STR_LEN];
37  int socket_id;
39  int event_id;
40  int type;
44 
45 typedef struct _powercap_reg_alloc {
48 
51 
52 static int num_events=0;
53 
54 // package events
55 #define PKG_ENERGY 0
56 #define PKG_MAX_ENERGY_RANGE 1
57 #define PKG_MAX_POWER_A 2
58 #define PKG_POWER_LIMIT_A 3
59 #define PKG_TIME_WINDOW_A 4
60 #define PKG_MAX_POWER_B 5
61 #define PKG_POWER_LIMIT_B 6
62 #define PKG_TIME_WINDOW_B 7
63 #define PKG_ENABLED 8
64 #define PKG_NAME 9
65 
66 #define PKG_NUM_EVENTS 10
68 static char *pkg_event_names[PKG_NUM_EVENTS] = {"ENERGY_UJ", "MAX_ENERGY_RANGE_UJ", "MAX_POWER_A_UW", "POWER_LIMIT_A_UW", "TIME_WINDOW_A_US", "MAX_POWER_B_UW", "POWER_LIMIT_B_UW", "TIME_WINDOW_B", "ENABLED", "NAME"};
69 static char *pkg_sys_names[PKG_NUM_EVENTS] = {"energy_uj", "max_energy_range_uj", "constraint_0_max_power_uw", "constraint_0_power_limit_uw", "constraint_0_time_window_us", "constraint_1_max_power_uw", "constraint_1_power_limit_uw", "constraint_1_time_window_us", "enabled", "name"};
70 static mode_t pkg_sys_flags[PKG_NUM_EVENTS] = {O_RDONLY, O_RDONLY, O_RDONLY, O_RDWR, O_RDONLY, O_RDONLY, O_RDWR, O_RDONLY, O_RDONLY, O_RDONLY};
71 
72 
73 // non-package events
74 #define COMPONENT_ENERGY 10
75 #define COMPONENT_MAX_ENERGY_RANGE 11
76 #define COMPONENT_MAX_POWER_A 12
77 #define COMPONENT_POWER_LIMIT_A 13
78 #define COMPONENT_TIME_WINDOW_A 14
79 #define COMPONENT_ENABLED 15
80 #define COMPONENT_NAME 16
81 
82 #define COMPONENT_NUM_EVENTS 7
84 static char *component_event_names[COMPONENT_NUM_EVENTS] = {"ENERGY_UJ", "MAX_ENERGY_RANGE_UJ", "MAX_POWER_A_UW", "POWER_LIMIT_A_UW", "TIME_WINDOW_A_US", "ENABLED", "NAME"};
85 static char *component_sys_names[COMPONENT_NUM_EVENTS] = {"energy_uj", "max_energy_range_uj", "constraint_0_max_power_uw", "constraint_0_power_limit_uw", "constraint_0_time_window_us", "enabled", "name"};
86 static mode_t component_sys_flags[COMPONENT_NUM_EVENTS] = {O_RDONLY, O_RDONLY, O_RDONLY, O_RDWR, O_RDONLY, O_RDONLY, O_RDONLY};
87 
88 #define POWERCAP_MAX_COUNTERS (2 * (PKG_NUM_EVENTS + (3 * COMPONENT_NUM_EVENTS)))
89 
91 
93 
94 typedef struct _powercap_control_state {
96  long long which_counter[POWERCAP_MAX_COUNTERS];
97  long long need_difference[POWERCAP_MAX_COUNTERS];
98  long long lastupdate;
100 
101 typedef struct _powercap_context {
102  long long start_value[POWERCAP_MAX_COUNTERS];
105 
107 
108 /***************************************************************************/
109 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
110 /***************************************************************************/
111 
112 /* Null terminated version of strncpy */
113 static char * _local_strlcpy( char *dst, const char *src, size_t size )
114 {
115  char *retval = strncpy( dst, src, size );
116  if ( size>0 ) dst[size-1] = '\0';
117  return( retval );
118 }
119 
120 static long long read_powercap_value( int index )
121 {
122  int sz = pread(event_fds[index], read_buff, PAPI_MAX_STR_LEN, 0);
123  read_buff[sz] = '\0';
124 
125  return atoll(read_buff);
126 }
127 
128 static int write_powercap_value( int index, long long value )
129 {
130  snprintf(write_buff, sizeof(write_buff), "%lld", value);
131  int sz = pwrite(event_fds[index], write_buff, PAPI_MAX_STR_LEN, 0);
132  if(sz == -1) {
133  perror("Error in pwrite(): ");
134  }
135  return 1;
136 }
137 
138 /************************* PAPI Functions **********************************/
139 
140 /*
141  * This is called whenever a thread is initialized
142  */
144 {
145  ( void ) ctx;
146  return PAPI_OK;
147 }
148 
149 /*
150  * Called when PAPI process is initialized (i.e. PAPI_library_init)
151  */
153 {
154 
155  int num_sockets = -1;
156  int s = -1, e = -1, c = -1;
157 
158  char events_dir[128];
159  char event_path[128];
160 
161  DIR *events;
162 
163  // get hw info
164  const PAPI_hw_info_t *hw_info;
166 
167  // check if intel processor
168  if ( hw_info->vendor!=PAPI_VENDOR_INTEL ) {
169  strncpy(_powercap_vector.cmp_info.disabled_reason, "Not an Intel processor", PAPI_MAX_STR_LEN);
170  return PAPI_ENOSUPP;
171  }
172 
173  // store number of sockets for adding events
174  num_sockets = hw_info->sockets;
175 
176  num_events = 0;
177  for(s = 0; s < num_sockets; s++) {
178 
179  // compose string of a pkg directory path
180  snprintf(events_dir, sizeof(events_dir), "/sys/class/powercap/intel-rapl:%d/", s);
181 
182  // open directory to make sure it exists
183  events = opendir(events_dir);
184 
185  // not a valid pkg/component directory so continue
186  if (events == NULL) { continue; }
187  closedir(events); // opendir has mallocs; so clean up.
188 
189  // loop through pkg events and create powercap event entries
190  for (e = 0; e < PKG_NUM_EVENTS; e++) {
191 
192  // compose string to individual event
193  snprintf(event_path, sizeof(event_path), "%s%s", events_dir, pkg_sys_names[e]);
194  // not a valid pkg event path so continue
195  if (access(event_path, F_OK) == -1) { continue; }
196 
198  //snprintf(powercap_ntv_events[num_events].description, sizeof(powercap_ntv_events[num_events].name), "%s:ZONE%d", pkg_event_names[e], s);
199  //snprintf(powercap_ntv_events[num_events].units, sizeof(powercap_ntv_events[num_events].name), "%s:ZONE%d", pkg_event_names[e], s);
202 
204 
205  event_fds[num_events] = open(event_path, O_SYNC|pkg_sys_flags[e]);
206 
208  int sz = pread(event_fds[num_events], read_buff, PAPI_MAX_STR_LEN, 0);
209  read_buff[sz] = '\0';
210  snprintf(powercap_ntv_events[num_events].description, sizeof(powercap_ntv_events[num_events].description), "%s", read_buff);
211  }
212 
213  num_events++;
214  }
215 
216  // reset component count for each socket
217  c = 0;
218  snprintf(events_dir, sizeof(events_dir), "/sys/class/powercap/intel-rapl:%d:%d/", s, c);
219  while((events = opendir(events_dir)) != NULL) {
220  closedir(events); // opendir has mallocs; so clean up.
221 
222  // loop through pkg events and create powercap event entries
223  for (e = 0; e < COMPONENT_NUM_EVENTS; e++) {
224 
225  // compose string to individual event
226  snprintf(event_path, sizeof(event_path), "%s%s", events_dir, component_sys_names[e]);
227 
228  // not a valid pkg event path so continue
229  if (access(event_path, F_OK) == -1) { continue; }
230 
231  snprintf(powercap_ntv_events[num_events].name, sizeof(powercap_ntv_events[num_events].name), "%s:ZONE%d_SUBZONE%d", component_event_names[e], s, c);
232  //snprintf(powercap_ntv_events[num_events].description, sizeof(powercap_ntv_events[num_events].name), "%s:ZONE%d_SUBZONE%d", component_event_names[e], s, c);
233  //snprintf(powercap_ntv_events[num_events].units, sizeof(powercap_ntv_events[num_events].name), "%s:ZONE%d_SUBZONE%d", component_event_names[e], s, c);
236 
238 
239  event_fds[num_events] = open(event_path, O_SYNC|component_sys_flags[e]);
240 
242  int sz = pread(event_fds[num_events], read_buff, PAPI_MAX_STR_LEN, 0);
243  read_buff[sz] = '\0';
244  snprintf(powercap_ntv_events[num_events].description, sizeof(powercap_ntv_events[num_events].description), "%s", read_buff);
245  }
246 
247  num_events++;
248  }
249 
250  // test for next component
251  c++;
252 
253  // compose string of an pkg directory path
254  snprintf(events_dir, sizeof(events_dir), "/sys/class/powercap/intel-rapl:%d:%d/", s, c);
255  }
256  }
257 
258  /* Export the total number of events available */
262 
263  /* Export the component id */
265 
266  return PAPI_OK;
267 }
268 
269 
270 /*
271  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
272  * functions
273  */
275 {
277  memset( control, 0, sizeof ( _powercap_control_state_t ) );
278 
279 
280  /* if an event is a counter, set its corresponding flag to 1 */
281  int i;
282  for (i = 0; i < num_events; i++) {
283  if ((powercap_ntv_events[i].type == PKG_ENERGY) || (powercap_ntv_events[i].type == COMPONENT_ENERGY)) {
284  control->need_difference[i] = 1;
285  }
286  }
287 
288  return PAPI_OK;
289 }
290 
292 {
293  _powercap_context_t* context = ( _powercap_context_t* ) ctx;
294  (void) ctl;
295 
296  int b;
297  for( b = 0; b < num_events; b++ ) {
298  context->start_value[b]=read_powercap_value(b);
299  }
300 
301  return PAPI_OK;
302 }
303 
305 {
306  (void) ctx;
307  (void) ctl;
308  return PAPI_OK;
309 }
310 
311 /* Shutdown a thread */
312 static int
314 {
315  ( void ) ctx;
316  SUBDBG( "Enter\n" );
317  return PAPI_OK;
318 }
319 
320 
321 static int
323  long long **events, int flags )
324 {
325  SUBDBG("Enter _powercap_read\n");
326 
327  (void) flags;
329  _powercap_context_t* context = ( _powercap_context_t* ) ctx;
330 
331  long long start_val = 0;
332  long long curr_val = 0;
333  int c;
334 
335  for( c = 0; c < num_events; c++ ) {
336  start_val = context->start_value[c];
337  curr_val = read_powercap_value(c);
338 
339  SUBDBG("%d, start value: %lld, current value %lld\n", c, start_val, curr_val);
340 
341  if(start_val) {
342 
343  /* Make sure an event is a counter. */
344  if (control->need_difference[c] == 1) {
345 
346  /* Wraparound. */
347  if(start_val > curr_val) {
348  SUBDBG("Wraparound!\nstart value:\t%lld,\tcurrent value:%lld\n", start_val, curr_val);
349  curr_val += (0x100000000 - start_val);
350  }
351  /* Normal subtraction. */
352  else if (start_val < curr_val) {
353  SUBDBG("Normal subtraction!\nstart value:\t%lld,\tcurrent value:%lld\n", start_val, curr_val);
354  curr_val -= start_val;
355  }
356  SUBDBG("Final value: %lld\n", curr_val);
357 
358  }
359  }
360  control->count[c]=curr_val;
361  }
362 
363  *events = ( ( _powercap_control_state_t* ) ctl )->count;
364 
365  return PAPI_OK;
366 }
367 
368 static int _powercap_write( hwd_context_t * ctx, hwd_control_state_t * ctl, long long *values )
369 {
370  /* write values */
371  ( void ) ctx;
373 
374  int i;
375 
376  for(i=0;i<num_events;i++) {
379  }
380  }
381 
382  return PAPI_OK;
383 }
384 /*
385  * Clean up what was setup in powercap_init_component().
386  */
388 {
389  int i;
390 
391  /* Read counters into expected slot */
392  for(i=0;i<num_events;i++) {
393  close(event_fds[i]);
394  }
395  return PAPI_OK;
396 }
397 
398 /* This function sets various options in the component. The valid
399  * codes being passed in are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN,
400  * PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT
401  */
402 static int
404 {
405  SUBDBG( "Enter: ctx: %p\n", ctx );
406  ( void ) ctx;
407  ( void ) code;
408  ( void ) option;
409 
410  return PAPI_OK;
411 }
412 
413 
415  NativeInfo_t *native, int count,
416  hwd_context_t *ctx )
417 {
418  (void) ctx;
419  int i, index;
420 
422  if (count==0) return PAPI_OK;
423 
424  for( i = 0; i < count; i++ ) {
425  index = native[i].ni_event;
426  control->which_counter[i]=index;
427  native[i].ni_position = i;
428  }
429 
430  return PAPI_OK;
431 
432 }
433 
434 static int _powercap_set_domain( hwd_control_state_t *ctl, int domain )
435 {
436  ( void ) ctl;
437  if ( PAPI_DOM_ALL != domain )
438  return PAPI_EINVAL;
439 
440  return PAPI_OK;
441 }
442 
443 
445 {
446  ( void ) ctx;
447  ( void ) ctl;
448  return PAPI_OK;
449 }
450 
451 /*
452  * Native Event functions
453  */
454 static int _powercap_ntv_enum_events( unsigned int *EventCode, int modifier )
455 {
456  int index;
457  switch ( modifier ) {
458 
459  case PAPI_ENUM_FIRST:
460  *EventCode = 0;
461  return PAPI_OK;
462  case PAPI_ENUM_EVENTS:index = *EventCode;
463  if (index < num_events - 1) {
464  *EventCode = *EventCode + 1;
465  return PAPI_OK;
466  } else {
467  return PAPI_ENOEVNT;
468  }
469 
470  default:return PAPI_EINVAL;
471  }
472 }
473 
474 /*
475  *
476  */
477 static int _powercap_ntv_code_to_name( unsigned int EventCode, char *name, int len )
478 {
479  int index = EventCode & PAPI_NATIVE_AND_MASK;
480 
481  if ( index >= 0 && index < num_events ) {
483  return PAPI_OK;
484  }
485  return PAPI_ENOEVNT;
486 }
487 
488 /*
489  *
490  */
491 static int _powercap_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
492 {
493  int index = EventCode;
494 
495  if ( index < 0 && index >= num_events )
496  return PAPI_ENOEVNT;
497  _local_strlcpy( name, powercap_ntv_events[index].description, len );
498  return PAPI_OK;
499 }
500 
501 static int _powercap_ntv_code_to_info( unsigned int EventCode, PAPI_event_info_t *info )
502 {
503  int index = EventCode;
504 
505  if ( index < 0 || index >= num_events )
506  return PAPI_ENOEVNT;
507 
508  _local_strlcpy( info->symbol, powercap_ntv_events[index].name, sizeof( info->symbol ));
509  _local_strlcpy( info->long_descr, powercap_ntv_events[index].description, sizeof( info->long_descr ) );
510  _local_strlcpy( info->units, powercap_ntv_events[index].units, sizeof( info->units ) );
511 
513  return PAPI_OK;
514 }
515 
516 
518  .cmp_info = { /* (unspecified values are initialized to 0) */
519  .name = "powercap",
520  .short_name = "powercap",
521  .description = "Linux powercap energy measurements",
522  .version = "5.3.0",
523  .default_domain = PAPI_DOM_ALL,
524  .default_granularity = PAPI_GRN_SYS,
525  .available_granularities = PAPI_GRN_SYS,
526  .hardware_intr_sig = PAPI_INT_SIGNAL,
527  .available_domains = PAPI_DOM_ALL,
528  },
529 
530  /* sizes of framework-opaque component-private structures */
531  .size = {
532  .context = sizeof ( _powercap_context_t ),
533  .control_state = sizeof ( _powercap_control_state_t ),
534  .reg_value = sizeof ( _powercap_register_t ),
535  .reg_alloc = sizeof ( _powercap_reg_alloc_t ),
536  },
537  /* function pointers in this component */
538  .init_thread = _powercap_init_thread,
539  .init_component = _powercap_init_component,
540  .init_control_state = _powercap_init_control_state,
541  .update_control_state = _powercap_update_control_state,
542  .start = _powercap_start,
543  .stop = _powercap_stop,
544  .read = _powercap_read,
545  .write = _powercap_write,
546  .shutdown_thread = _powercap_shutdown_thread,
547  .shutdown_component = _powercap_shutdown_component,
548  .ctl = _powercap_ctl,
549 
550  .set_domain = _powercap_set_domain,
551  .reset = _powercap_reset,
552 
553  .ntv_enum_events = _powercap_ntv_enum_events,
554  .ntv_code_to_name = _powercap_ntv_code_to_name,
555  .ntv_code_to_descr = _powercap_ntv_code_to_descr,
556  .ntv_code_to_info = _powercap_ntv_code_to_info,
557 };
#define PAPI_OK
Definition: fpapi.h:105
static char write_buff[PAPI_MAX_STR_LEN]
#define COMPONENT_ENERGY
static char * pkg_event_names[PKG_NUM_EVENTS]
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:637
int close(int fd)
Definition: appio.c:175
#define COMPONENT_MAX_POWER_A
static const char * name
Definition: fork_overflow.c:31
#define PAPI_EINVAL
Definition: fpapi.h:106
Hardware info structure.
Definition: papi.h:781
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:976
#define COMPONENT_TIME_WINDOW_A
static int _powercap_shutdown_thread(hwd_context_t *ctx)
#define COMPONENT_ENABLED
#define PAPI_ENOSUPP
Definition: fpapi.h:123
static int _powercap_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int num_events
static int _powercap_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
static int component_events[COMPONENT_NUM_EVENTS]
static int event_fds[POWERCAP_MAX_COUNTERS]
static char read_buff[PAPI_MAX_STR_LEN]
static mode_t component_sys_flags[COMPONENT_NUM_EVENTS]
#define PAPI_GRN_SYS
Definition: fpapi.h:71
long long start_value[POWERCAP_MAX_COUNTERS]
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
#define PKG_TIME_WINDOW_A
long long which_counter[POWERCAP_MAX_COUNTERS]
int retval
Definition: zero_fork.c:53
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
char name[PAPI_MAX_STR_LEN]
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
static int _powercap_init_control_state(hwd_control_state_t *ctl)
#define COMPONENT_POWER_LIMIT_A
static int write_powercap_value(int index, long long value)
static int _powercap_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
double c
Definition: multiplex.c:22
Return codes and api definitions.
static char * _local_strlcpy(char *dst, const char *src, size_t size)
#define PKG_TIME_WINDOW_B
char events[MAX_EVENTS][BUFSIZ]
char units[PAPI_MIN_STR_LEN]
#define COMPONENT_MAX_ENERGY_RANGE
static int _powercap_shutdown_component(void)
char description[PAPI_MAX_STR_LEN]
#define COMPONENT_NAME
static long long read_powercap_value(int index)
static int cidx
long long count[POWERCAP_MAX_COUNTERS]
#define PKG_ENERGY
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:184
_powercap_register_t ra_bits
static int _powercap_ntv_code_to_name(unsigned int EventCode, char *name, int len)
static int _powercap_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
static char * component_sys_names[COMPONENT_NUM_EVENTS]
#define PKG_ENABLED
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
_powercap_register_t resources
#define PAPI_MIN_STR_LEN
Definition: fpapi.h:41
#define PKG_MAX_ENERGY_RANGE
#define PKG_POWER_LIMIT_A
static int _powercap_init_thread(hwd_context_t *ctx)
unsigned int selector
static int native
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
static int pkg_events[PKG_NUM_EVENTS]
int event_id
static char * component_event_names[COMPONENT_NUM_EVENTS]
#define PKG_NUM_EVENTS
static mode_t pkg_sys_flags[PKG_NUM_EVENTS]
double s
Definition: byte_profile.c:36
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:630
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
int type
static int _powercap_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
#define PKG_NAME
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
PAPI_hw_info_t hw_info
#define PKG_MAX_POWER_B
static int _powercap_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
#define PAPI_VENDOR_INTEL
Definition: papi.h:349
int vendor
Definition: papi.h:788
static int _powercap_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *values)
int component_id
static int _powercap_set_domain(hwd_control_state_t *ctl, int domain)
#define PKG_MAX_POWER_A
#define PAPI_ENOEVNT
Definition: fpapi.h:112
#define PAPI_NATIVE_AND_MASK
papi_vector_t _powercap_vector
int return_type
_powercap_control_state_t state
static int _powercap_ntv_enum_events(unsigned int *EventCode, int modifier)
int socket_id
static _powercap_native_event_entry_t powercap_ntv_events[(2 *(PKG_NUM_EVENTS+(3 *COMPONENT_NUM_EVENTS)))]
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
#define COMPONENT_NUM_EVENTS
static int _powercap_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:28
static int _powercap_reset(hwd_context_t *ctx, 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
long long need_difference[POWERCAP_MAX_COUNTERS]
int sockets
Definition: papi.h:785
static long count
static char * pkg_sys_names[PKG_NUM_EVENTS]
#define POWERCAP_MAX_COUNTERS
static int _powercap_init_component(int cidx)
int i
Definition: fileop.c:140
#define PKG_POWER_LIMIT_B
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
int sz
Definition: fileop.c:80