PAPI  5.6.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
perf_event_uncore.c
Go to the documentation of this file.
1 /*
2 * File: perf_event_uncore.c
3 *
4 * Author: Vince Weaver
5 * vincent.weaver@maine.edu
6 * Mods: Gary Mohr
7 * gary.mohr@bull.com
8 * Modified the perf_event_uncore component to use PFM_OS_PERF_EVENT_EXT mode in libpfm4.
9 * This adds several new event masks, including cpu=, u=, and k= which give the user
10 * the ability to set cpu number to use or control the domain (user, kernel, or both)
11 * in which the counter should be incremented. These are event masks so it is now
12 * possible to have multiple events in the same event set that count activity from
13 * differennt cpu's or count activity in different domains.
14 */
15 
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <signal.h>
21 #include <syscall.h>
22 #include <sys/utsname.h>
23 #include <sys/mman.h>
24 #include <sys/ioctl.h>
25 
26 /* PAPI-specific includes */
27 #include "papi.h"
28 #include "papi_memory.h"
29 #include "papi_internal.h"
30 #include "papi_vector.h"
31 #include "extras.h"
32 
33 /* libpfm4 includes */
34 #include "papi_libpfm4_events.h"
36 #include "perfmon/pfmlib.h"
37 #include PEINCLUDE
38 
39 /* Linux-specific includes */
40 #include "mb.h"
41 #include "linux-memory.h"
42 #include "linux-timer.h"
43 #include "linux-common.h"
44 #include "linux-context.h"
45 
47 
48 /* Forward declaration */
50 
51 /* Globals */
53 static int our_cidx;
54 //int
55 //_peu_libpfm4_get_cidx() {
56 // return our_cidx;
57 //}
58 
59 /* Defines for ctx->state */
60 #define PERF_EVENTS_OPENED 0x01
61 #define PERF_EVENTS_RUNNING 0x02
62 
63 static int _peu_set_domain( hwd_control_state_t *ctl, int domain);
64 
65 
66 
67 /******************************************************************/
68 /******** Kernel Version Dependent Routines **********************/
69 /******************************************************************/
70 
71 /* The read format on perf_event varies based on various flags that */
72 /* are passed into it. This helper avoids copying this logic */
73 /* multiple places. */
74 static unsigned int
75 get_read_format( unsigned int multiplex,
76  unsigned int inherit,
77  int format_group )
78 {
79  unsigned int format = 0;
80 
81  /* if we need read format options for multiplexing, add them now */
82  if (multiplex) {
83  format |= PERF_FORMAT_TOTAL_TIME_ENABLED;
84  format |= PERF_FORMAT_TOTAL_TIME_RUNNING;
85  }
86 
87  /* If we are not using inherit, add the group read options */
88  if (!inherit) {
89  if (format_group) {
90  format |= PERF_FORMAT_GROUP;
91  }
92  }
93 
94  SUBDBG("multiplex: %d, inherit: %d, group_leader: %d, format: %#x\n",
95  multiplex, inherit, format_group, format);
96 
97  return format;
98 }
99 
100 /*****************************************************************/
101 /********* End Kernel-version Dependent Routines ****************/
102 /*****************************************************************/
103 
104 /********************************************************************/
105 /* Low-level perf_event calls */
106 /********************************************************************/
107 
108 /* In case headers aren't new enough to have __NR_perf_event_open */
109 #ifndef __NR_perf_event_open
110 
111 #ifdef __powerpc__
112 #define __NR_perf_event_open 319
113 #elif defined(__x86_64__)
114 #define __NR_perf_event_open 298
115 #elif defined(__i386__)
116 #define __NR_perf_event_open 336
117 #elif defined(__arm__) 366+0x900000
118 #define __NR_perf_event_open
119 #endif
120 
121 #endif
122 
123 static long
124 sys_perf_event_open( struct perf_event_attr *hw_event, pid_t pid, int cpu,
125  int group_fd, unsigned long flags )
126 {
127  int ret;
128 
129  SUBDBG("sys_perf_event_open(hw_event: %p, pid: %d, cpu: %d, group_fd: %d, flags: %lx\n",hw_event,pid,cpu,group_fd,flags);
130  SUBDBG(" type: %d\n",hw_event->type);
131  SUBDBG(" size: %d\n",hw_event->size);
132  SUBDBG(" config: %#"PRIx64" (%"PRIu64")\n",hw_event->config,
133  hw_event->config);
134  SUBDBG(" sample_period: %"PRIu64"\n",hw_event->sample_period);
135  SUBDBG(" sample_type: %"PRIu64"\n",hw_event->sample_type);
136  SUBDBG(" read_format: %"PRIu64"\n",hw_event->read_format);
137  SUBDBG(" disabled: %d\n",hw_event->disabled);
138  SUBDBG(" inherit: %d\n",hw_event->inherit);
139  SUBDBG(" pinned: %d\n",hw_event->pinned);
140  SUBDBG(" exclusive: %d\n",hw_event->exclusive);
141  SUBDBG(" exclude_user: %d\n",hw_event->exclude_user);
142  SUBDBG(" exclude_kernel: %d\n",hw_event->exclude_kernel);
143  SUBDBG(" exclude_hv: %d\n",hw_event->exclude_hv);
144  SUBDBG(" exclude_idle: %d\n",hw_event->exclude_idle);
145  SUBDBG(" mmap: %d\n",hw_event->mmap);
146  SUBDBG(" comm: %d\n",hw_event->comm);
147  SUBDBG(" freq: %d\n",hw_event->freq);
148  SUBDBG(" inherit_stat: %d\n",hw_event->inherit_stat);
149  SUBDBG(" enable_on_exec: %d\n",hw_event->enable_on_exec);
150  SUBDBG(" task: %d\n",hw_event->task);
151  SUBDBG(" watermark: %d\n",hw_event->watermark);
152  SUBDBG(" precise_ip: %d\n",hw_event->precise_ip);
153  SUBDBG(" mmap_data: %d\n",hw_event->mmap_data);
154  SUBDBG(" sample_id_all: %d\n",hw_event->sample_id_all);
155  SUBDBG(" exclude_host: %d\n",hw_event->exclude_host);
156  SUBDBG(" exclude_guest: %d\n",hw_event->exclude_guest);
157  SUBDBG(" exclude_callchain_kernel: %d\n",hw_event->exclude_callchain_kernel);
158  SUBDBG(" exclude_callchain_user: %d\n",hw_event->exclude_callchain_user);
159  SUBDBG(" wakeup_watermark: %d\n",hw_event->wakeup_watermark);
160  SUBDBG(" bp_type: %d\n",hw_event->bp_type);
161  SUBDBG(" config1: %#lx (%lu)\n",hw_event->config1,hw_event->config1);
162  SUBDBG(" config2: %#lx (%lu)\n",hw_event->config2,hw_event->config2);
163  SUBDBG(" branch_sample_type: %lu\n",hw_event->branch_sample_type);
164  SUBDBG(" sample_regs_user: %lu\n",hw_event->sample_regs_user);
165  SUBDBG(" sample_stack_user: %d\n",hw_event->sample_stack_user);
166 
167  ret = syscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags );
168  SUBDBG("Returned %d %d %s\n",ret,
169  ret<0?errno:0,
170  ret<0?strerror(errno):" ");
171  return ret;
172 }
173 
174 
175 static int map_perf_event_errors_to_papi(int perf_event_error) {
176 
177  int ret;
178 
179  /* These mappings are approximate.
180  EINVAL in particular can mean lots of different things */
181  switch(perf_event_error) {
182  case EPERM:
183  case EACCES:
184  ret = PAPI_EPERM;
185  break;
186  case ENODEV:
187  case EOPNOTSUPP:
188  ret = PAPI_ENOSUPP;
189  break;
190  case ENOENT:
191  ret = PAPI_ENOEVNT;
192  break;
193  case ENOSYS:
194  case EAGAIN:
195  case EBUSY:
196  case E2BIG:
197  ret = PAPI_ESYS;
198  break;
199  case ENOMEM:
200  ret = PAPI_ENOMEM;
201  break;
202  case EINVAL:
203  default:
204  ret = PAPI_EINVAL;
205  break;
206  }
207  return ret;
208 }
209 
210 /* Maximum size we ever expect to read from a perf_event fd */
211 /* (this is the number of 64-bit values) */
212 /* We use this to size the read buffers */
213 /* The three is for event count, time_enabled, time_running */
214 /* and the counter term is count value and count id for each */
215 /* possible counter value. */
216 #define READ_BUFFER_SIZE (3 + (2 * PERF_EVENT_MAX_MPX_COUNTERS))
217 
218 
219 
220 /* KERNEL_CHECKS_SCHEDUABILITY_UPON_OPEN is a work-around for kernel arch */
221 /* implementations (e.g. x86 before 2.6.33) which don't do a static event */
222 /* scheduability check in sys_perf_event_open. It is also needed if the */
223 /* kernel is stealing an event, such as when NMI watchdog is enabled. */
224 
225 static int
227 {
228  SUBDBG("ENTER: ctx: %p, ctl: %p\n", ctx, ctl);
229  int retval = 0, cnt = -1;
230  ( void ) ctx; /*unused */
231  long long papi_pe_buffer[READ_BUFFER_SIZE];
232  int i;
233 
234  /* If the kernel isn't tracking scheduability right */
235  /* Then we need to start/stop/read to force the event */
236  /* to be scheduled and see if an error condition happens. */
237 
238  /* start all events */
239  for( i = 0; i < ctl->num_events; i++) {
240  retval = ioctl( ctl->events[i].event_fd, PERF_EVENT_IOC_ENABLE, NULL );
241  if (retval == -1) {
242  SUBDBG("EXIT: Enable failed event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
243  return PAPI_ESYS;
244  }
245  }
246 
247  /* stop all events */
248  for( i = 0; i < ctl->num_events; i++) {
249  retval = ioctl(ctl->events[i].event_fd, PERF_EVENT_IOC_DISABLE, NULL );
250  if (retval == -1) {
251  SUBDBG("EXIT: Disable failed: event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
252  return PAPI_ESYS;
253  }
254  }
255 
256  /* See if a read of each event returns results */
257  for( i = 0; i < ctl->num_events; i++) {
258  cnt = read( ctl->events[i].event_fd, papi_pe_buffer, sizeof(papi_pe_buffer));
259  if ( cnt == -1 ) {
260  SUBDBG( "EXIT: read failed: event index: %d, num_events: %d, return PAPI_ESYS. Should never happen.\n", i, ctl->num_events);
261  return PAPI_ESYS;
262  }
263 
264  if ( cnt == 0 ) {
265  /* We read 0 bytes if we could not schedule the event */
266  /* The kernel should have detected this at open */
267  /* but various bugs (including NMI watchdog) */
268  /* result in this behavior */
269 
270  SUBDBG( "EXIT: read returned 0: event index: %d, num_events: %d, return PAPI_ECNFLCT.\n", i, ctl->num_events);
271  return PAPI_ECNFLCT;
272  }
273  }
274 
275  /* Reset all of the counters (opened so far) back to zero */
276  /* from the above brief enable/disable call pair. */
277 
278  /* We have to reset all events because reset of group leader */
279  /* does not reset all. */
280  /* we assume that the events are being added one by one and that */
281  /* we do not need to reset higher events (doing so may reset ones */
282  /* that have not been initialized yet. */
283 
284  /* Note... PERF_EVENT_IOC_RESET does not reset time running */
285  /* info if multiplexing, so we should avoid coming here if */
286  /* we are multiplexing the event. */
287  for( i = 0; i < ctl->num_events; i++) {
288  retval=ioctl( ctl->events[i].event_fd, PERF_EVENT_IOC_RESET, NULL );
289  if (retval == -1) {
290  SUBDBG("EXIT: Reset failed: event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
291  return PAPI_ESYS;
292  }
293  }
294  SUBDBG("EXIT: return PAPI_OK\n");
295  return PAPI_OK;
296 }
297 
298 
299 /* Open all events in the control state */
300 static int
302 {
303 
304  int i, ret = PAPI_OK;
305  long pid;
306 
307  if (ctl->granularity==PAPI_GRN_SYS) {
308  pid = -1;
309  }
310  else {
311  pid = ctl->tid;
312  }
313 
314  for( i = 0; i < ctl->num_events; i++ ) {
315 
316  ctl->events[i].event_opened=0;
317 
318  /* set up the attr structure. We don't set up all fields here */
319  /* as some have already been set up previously. */
320 
321 /*
322  * The following code controls how the uncore component interfaces with the
323  * kernel for uncore events. The code inside the ifdef will use grouping of
324  * uncore events which can make the cost of reading the results more efficient.
325  * The problem with it is that the uncore component supports 20 different uncore
326  * PMU's. The kernel requires that all events in a group must be for the same PMU.
327  * This means that with grouping enabled papi applications can count events on only
328  * one of the 20 PMU's during a run.
329  *
330  * The code inside the else clause treats each event in the event set as
331  * independent. When running in this mode the kernel allows the papi multiple
332  * uncore PMU's at the same time.
333  *
334  * Example:
335  * An application wants to measure all the L3 cache write requests.
336  * The event to do this is part of a cbox pmu (there are 8 cbox pmu's).
337  * When built with the code in the ifdef, the application would have to be
338  * run 8 times and count write requests from one pmu at a time.
339  * When built with the code in the else, the write requests in all 8 cbox
340  * pmu's could be counted in the same run.
341  *
342  */
343 // #define GROUPIT 1 // remove the comment on this line to force event grouping
344 #ifdef GROUPIT
345  /* group leader (event 0) is special */
346  /* If we're multiplexed, everyone is a group leader */
347  if (( i == 0 ) || (ctl->multiplexed)) {
348  ctl->events[i].attr.pinned = !ctl->multiplexed;
349  ctl->events[i].attr.disabled = 1;
350  ctl->events[i].group_leader_fd=-1;
351  ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed,
352  ctl->inherit,
353  !ctl->multiplexed );
354  } else {
355  ctl->events[i].attr.pinned=0;
356  ctl->events[i].attr.disabled = 0;
357  ctl->events[i].group_leader_fd=ctl->events[0].event_fd,
358  ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed,
359  ctl->inherit,
360  0 );
361  }
362 #else
363  ctl->events[i].attr.pinned = !ctl->multiplexed;
364  ctl->events[i].attr.disabled = 1;
365  ctl->inherit = 1;
366  ctl->events[i].group_leader_fd=-1;
367  ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed, ctl->inherit, 0 );
368 #endif
369 
370 
371  /* try to open */
372  ctl->events[i].event_fd = sys_perf_event_open( &ctl->events[i].attr,
373  pid,
374  ctl->events[i].cpu,
375  ctl->events[i].group_leader_fd,
376  0 /* flags */
377  );
378 
379  /* Try to match Linux errors to PAPI errors */
380  if ( ctl->events[i].event_fd == -1 ) {
381  SUBDBG("sys_perf_event_open returned error on event #%d."
382  " Error: %s\n",
383  i, strerror( errno ) );
385 
386  goto open_peu_cleanup;
387  }
388 
389  SUBDBG ("sys_perf_event_open: tid: %ld, cpu_num: %d,"
390  " group_leader/fd: %d, event_fd: %d,"
391  " read_format: %"PRIu64"\n",
392  pid, ctl->events[i].cpu, ctl->events[i].group_leader_fd,
393  ctl->events[i].event_fd, ctl->events[i].attr.read_format);
394 
395  ctl->events[i].event_opened=1;
396  }
397 
398 
399  /* in many situations the kernel will indicate we opened fine */
400  /* yet things will fail later. So we need to double check */
401  /* we actually can use the events we've set up. */
402 
403  /* This is not necessary if we are multiplexing, and in fact */
404  /* we cannot do this properly if multiplexed because */
405  /* PERF_EVENT_IOC_RESET does not reset the time running info */
406  if (!ctl->multiplexed) {
407  ret = check_scheduability( ctx, ctl);
408 
409  if ( ret != PAPI_OK ) {
410  /* the last event did open, so we need to bump the counter */
411  /* before doing the cleanup */
412  i++;
413  goto open_peu_cleanup;
414  }
415  }
416 
417  /* Now that we've successfully opened all of the events, do whatever */
418  /* "tune-up" is needed to attach the mmap'd buffers, signal handlers, */
419  /* and so on. */
420  for ( i = 0; i < ctl->num_events; i++ ) {
421 
422  /* No sampling if uncore */
423  ctl->events[i].mmap_buf = NULL;
424  }
425 
426  /* Set num_evts only if completely successful */
427  ctx->state |= PERF_EVENTS_OPENED;
428 
429  return PAPI_OK;
430 
431 open_peu_cleanup:
432  /* We encountered an error, close up the fds we successfully opened. */
433  /* We go backward in an attempt to close group leaders last, although */
434  /* That's probably not strictly necessary. */
435  while ( i > 0 ) {
436  i--;
437  if (ctl->events[i].event_fd>=0) {
438  close( ctl->events[i].event_fd );
439  ctl->events[i].event_opened=0;
440  }
441  }
442 
443  return ret;
444 }
445 
446 /* Close all of the opened events */
447 static int
449 {
450  int i;
451  int num_closed=0;
452  int events_not_opened=0;
453 
454  /* should this be a more serious error? */
455  if ( ctx->state & PERF_EVENTS_RUNNING ) {
456  SUBDBG("Closing without stopping first\n");
457  }
458 
459  /* Close child events first */
460  for( i=0; i<ctl->num_events; i++ ) {
461 
462  if (ctl->events[i].event_opened) {
463 
464  if (ctl->events[i].group_leader_fd!=-1) {
465  if ( ctl->events[i].mmap_buf ) {
466  if ( munmap ( ctl->events[i].mmap_buf,
467  ctl->events[i].nr_mmap_pages * getpagesize() ) ) {
468  PAPIERROR( "munmap of fd = %d returned error: %s",
469  ctl->events[i].event_fd, strerror( errno ) );
470  return PAPI_ESYS;
471  }
472  }
473 
474  if ( close( ctl->events[i].event_fd ) ) {
475  PAPIERROR( "close of fd = %d returned error: %s",
476  ctl->events[i].event_fd, strerror( errno ) );
477  return PAPI_ESYS;
478  } else {
479  num_closed++;
480  }
481  ctl->events[i].event_opened=0;
482  }
483  }
484  else {
485  events_not_opened++;
486  }
487  }
488 
489  /* Close the group leaders last */
490  for( i=0; i<ctl->num_events; i++ ) {
491 
492  if (ctl->events[i].event_opened) {
493 
494  if (ctl->events[i].group_leader_fd==-1) {
495  if ( ctl->events[i].mmap_buf ) {
496  if ( munmap ( ctl->events[i].mmap_buf,
497  ctl->events[i].nr_mmap_pages * getpagesize() ) ) {
498  PAPIERROR( "munmap of fd = %d returned error: %s",
499  ctl->events[i].event_fd, strerror( errno ) );
500  return PAPI_ESYS;
501  }
502  }
503 
504 
505  if ( close( ctl->events[i].event_fd ) ) {
506  PAPIERROR( "close of fd = %d returned error: %s",
507  ctl->events[i].event_fd, strerror( errno ) );
508  return PAPI_ESYS;
509  } else {
510  num_closed++;
511  }
512  ctl->events[i].event_opened=0;
513  }
514  }
515  }
516 
517 
518  if (ctl->num_events!=num_closed) {
519  if (ctl->num_events!=(num_closed+events_not_opened)) {
520  PAPIERROR("Didn't close all events: "
521  "Closed %d Not Opened: %d Expected %d\n",
522  num_closed,events_not_opened,ctl->num_events);
523  return PAPI_EBUG;
524  }
525  }
526 
527  ctl->num_events=0;
528 
529  ctx->state &= ~PERF_EVENTS_OPENED;
530 
531  return PAPI_OK;
532 }
533 
534 
535 
536 
537 /********************************************************************/
538 /* Component Interface */
539 /********************************************************************/
540 
541 
542 
543 /* Initialize a thread */
544 static int
546 {
547 
548  pe_context_t *pe_ctx = ( pe_context_t *) hwd_ctx;
549 
550  /* clear the context structure and mark as initialized */
551  memset( pe_ctx, 0, sizeof ( pe_context_t ) );
552  pe_ctx->initialized=1;
553 
555  pe_ctx->cidx=our_cidx;
556 
557  return PAPI_OK;
558 }
559 
560 /* Initialize a new control state */
561 static int
563 {
564  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
565 
566  /* clear the contents */
567  memset( pe_ctl, 0, sizeof ( pe_control_t ) );
568 
569  /* Set the default domain */
570  _peu_set_domain( ctl, _perf_event_uncore_vector.cmp_info.default_domain );
571 
572  /* Set the default granularity */
573  pe_ctl->granularity=_perf_event_uncore_vector.cmp_info.default_granularity;
574 
575  pe_ctl->cidx=our_cidx;
576 
577  /* Set cpu number in the control block to show events */
578  /* are not tied to specific cpu */
579  pe_ctl->cpu = -1;
580  return PAPI_OK;
581 }
582 
583 
584 
585 /* Initialize the perf_event uncore component */
586 static int
588 {
589 
590  int retval;
591  int paranoid_level;
592 
593  FILE *fff;
594 
595  our_cidx=cidx;
596 
597  /* The is the official way to detect if perf_event support exists */
598  /* The file is called perf_counter_paranoid on 2.6.31 */
599  /* currently we are lazy and do not support 2.6.31 kernels */
600 
601  fff=fopen("/proc/sys/kernel/perf_event_paranoid","r");
602  if (fff==NULL) {
603  strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
604  "perf_event support not detected",PAPI_MAX_STR_LEN);
605  return PAPI_ENOCMP;
606  }
607  retval=fscanf(fff,"%d",&paranoid_level);
608  if (retval!=1) fprintf(stderr,"Error reading paranoid level\n");
609  fclose(fff);
610 
611 
612  /* Run the libpfm4-specific setup */
613 
614  retval = _papi_libpfm4_init(_papi_hwd[cidx]);
615  if (retval) {
616  strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
617  "Error initializing libpfm4",PAPI_MAX_STR_LEN);
618  return PAPI_ENOCMP;
619  }
620 
621 
622  /* Run the uncore specific libpfm4 setup */
623 
624  retval = _peu_libpfm4_init(_papi_hwd[cidx], our_cidx,
627  if (retval) {
628  strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
629  "Error setting up libpfm4",PAPI_MAX_STR_LEN);
630  return PAPI_ENOCMP;
631  }
632 
633  /* Check if no uncore events found */
634 
635  if (_papi_hwd[cidx]->cmp_info.num_native_events==0) {
636  strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
637  "No uncore PMUs or events found",PAPI_MAX_STR_LEN);
638  return PAPI_ENOCMP;
639  }
640 
641  /* Check if we have enough permissions for uncore */
642 
643  /* 2 means no kernel measurements allowed */
644  /* 1 means normal counter access */
645  /* 0 means you can access CPU-specific data */
646  /* -1 means no restrictions */
647 
648  if ((paranoid_level>0) && (getuid()!=0)) {
649  strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
650  "Insufficient permissions for uncore access. Set /proc/sys/kernel/perf_event_paranoid to 0 or run as root.",
652  return PAPI_ENOCMP;
653  }
654 
655  return PAPI_OK;
656 
657 }
658 
659 /* Shutdown the perf_event component */
660 static int
662 
663  /* deallocate our event table */
664  _pe_libpfm4_shutdown(&_perf_event_uncore_vector,
666 
667  /* Shutdown libpfm4 */
668  _papi_libpfm4_shutdown(&_perf_event_uncore_vector);
669 
670  return PAPI_OK;
671 }
672 
673 /* This function clears the current contents of the control structure and
674  updates it with whatever resources are allocated for all the native events
675  in the native info structure array. */
676 
677 int
680  int count, hwd_context_t *ctx )
681 {
682  int i;
683  int j;
684  int ret;
685  int skipped_events=0;
686  struct native_event_t *ntv_evt;
687  pe_context_t *pe_ctx = ( pe_context_t *) ctx;
688  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
689 
690  /* close all of the existing fds and start over again */
691  /* In theory we could have finer-grained control and know if */
692  /* things were changed, but it's easier to tear things down and rebuild. */
693  close_pe_events( pe_ctx, pe_ctl );
694 
695  /* Calling with count==0 should be OK, it's how things are deallocated */
696  /* when an eventset is destroyed. */
697  if ( count == 0 ) {
698  SUBDBG( "Called with count == 0\n" );
699  return PAPI_OK;
700  }
701 
702  /* set up all the events */
703  for( i = 0; i < count; i++ ) {
704  if ( native ) {
705  // get the native event pointer used for this papi event
706  int ntv_idx = _papi_hwi_get_ntv_idx((unsigned)(native[i].ni_papi_code));
707  if (ntv_idx < -1) {
708  SUBDBG("papi_event_code: %#x known by papi but not by the component\n", native[i].ni_papi_code);
709  continue;
710  }
711  // if native index is -1, then we have an event without a mask and need to find the right native index to use
712  if (ntv_idx == -1) {
713  // find the native event index we want by matching for the right papi event code
714  for (j=0 ; j<pe_ctx->event_table->num_native_events ; j++) {
715  if (pe_ctx->event_table->native_events[j].papi_event_code == native[i].ni_papi_code) {
716  ntv_idx = j;
717  }
718  }
719  }
720 
721  // if native index is still negative, we did not find event we wanted so just return error
722  if (ntv_idx < 0) {
723  SUBDBG("papi_event_code: %#x not found in native event tables\n", native[i].ni_papi_code);
724  continue;
725  }
726 
727  // this native index is positive so there was a mask with the event, the ntv_idx identifies which native event to use
728  ntv_evt = (struct native_event_t *)(&(pe_ctx->event_table->native_events[ntv_idx]));
729 
730  SUBDBG("ntv_evt: %p\n", ntv_evt);
731 
732  SUBDBG("i: %d, pe_ctx->event_table->num_native_events: %d\n", i, pe_ctx->event_table->num_native_events);
733 
734  // Move this events hardware config values and other attributes to the perf_events attribute structure
735  memcpy (&pe_ctl->events[i].attr, &ntv_evt->attr, sizeof(perf_event_attr_t));
736 
737  // may need to update the attribute structure with information from event set level domain settings (values set by PAPI_set_domain)
738  // only done if the event mask which controls each counting domain was not provided
739 
740  // get pointer to allocated name, will be NULL when adding preset events to event set
741  char *aName = ntv_evt->allocated_name;
742  if ((aName == NULL) || (strstr(aName, ":u=") == NULL)) {
743  SUBDBG("set exclude_user attribute from eventset level domain flags, encode: %d, eventset: %d\n", pe_ctl->events[i].attr.exclude_user, !(pe_ctl->domain & PAPI_DOM_USER));
744  pe_ctl->events[i].attr.exclude_user = !(pe_ctl->domain & PAPI_DOM_USER);
745  }
746  if ((aName == NULL) || (strstr(aName, ":k=") == NULL)) {
747  SUBDBG("set exclude_kernel attribute from eventset level domain flags, encode: %d, eventset: %d\n", pe_ctl->events[i].attr.exclude_kernel, !(pe_ctl->domain & PAPI_DOM_KERNEL));
748  pe_ctl->events[i].attr.exclude_kernel = !(pe_ctl->domain & PAPI_DOM_KERNEL);
749  }
750 
751  // set the cpu number provided with an event mask if there was one (will be -1 if mask not provided)
752  pe_ctl->events[i].cpu = ntv_evt->cpu;
753  // if cpu event mask not provided, then set the cpu to use to what may have been set on call to PAPI_set_opt (will still be -1 if not called)
754  if (pe_ctl->events[i].cpu == -1) {
755  pe_ctl->events[i].cpu = pe_ctl->cpu;
756  }
757  } else {
758  // This case happens when called from _pe_set_overflow and _pe_ctl
759  // Those callers put things directly into the pe_ctl structure so it is already set for the open call
760  }
761 
762  // Copy the inherit flag into the attribute block that will be passed to the kernel
763  pe_ctl->events[i].attr.inherit = pe_ctl->inherit;
764 
765  /* Set the position in the native structure */
766  /* We just set up events linearly */
767  if ( native ) {
768  native[i].ni_position = i;
769  SUBDBG( "&native[%d]: %p, ni_papi_code: %#x, ni_event: %#x, ni_position: %d, ni_owners: %d\n",
770  i, &(native[i]), native[i].ni_papi_code, native[i].ni_event, native[i].ni_position, native[i].ni_owners);
771  }
772  }
773 
774  if (count <= skipped_events) {
775  SUBDBG("EXIT: No events to count, they all contained invalid umasks\n");
776  return PAPI_ENOEVNT;
777  }
778 
779  pe_ctl->num_events = count - skipped_events;
780 
781  /* actuall open the events */
782  /* (why is this a separate function?) */
783  ret = open_pe_events( pe_ctx, pe_ctl );
784  if ( ret != PAPI_OK ) {
785  SUBDBG("open_pe_events failed\n");
786  /* Restore values ? */
787  return ret;
788  }
789 
790  SUBDBG( "EXIT: PAPI_OK\n" );
791  return PAPI_OK;
792 }
793 
794 /********************************************************************/
795 /********************************************************************/
796 /* Start with functions that are exported via the module interface */
797 /********************************************************************/
798 /********************************************************************/
799 
800 
801 /* set the domain. perf_events allows per-event control of this, papi allows it to be set at the event level or at the event set level. */
802 /* this will set the event set level domain values but they only get used if no event level domain mask (u= or k=) was specified. */
803 static int
805 {
806  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
807 
808  SUBDBG("old control domain %d, new domain %d\n",
809  pe_ctl->domain,domain);
810 
811  pe_ctl->domain = domain;
812  return PAPI_OK;
813 }
814 
815 /* Shutdown a thread */
816 static int
818 {
819  pe_context_t *pe_ctx = ( pe_context_t *) ctx;
820 
821  pe_ctx->initialized=0;
822 
823  return PAPI_OK;
824 }
825 
826 
827 /* reset the hardware counters */
828 /* Note: PAPI_reset() does not necessarily call this */
829 /* unless the events are actually running. */
830 static int
832 {
833  int i, ret;
834  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
835 
836  ( void ) ctx; /*unused */
837 
838  /* We need to reset all of the events, not just the group leaders */
839  for( i = 0; i < pe_ctl->num_events; i++ ) {
840  ret = ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_RESET, NULL );
841  if ( ret == -1 ) {
842  PAPIERROR("ioctl(%d, PERF_EVENT_IOC_RESET, NULL) "
843  "returned error, Linux says: %s",
844  pe_ctl->events[i].event_fd, strerror( errno ) );
845  return PAPI_ESYS;
846  }
847  }
848 
849  return PAPI_OK;
850 }
851 
852 
853 /* write (set) the hardware counters */
854 /* Current we do not support this. */
855 static int
857  long long *from )
858 {
859  ( void ) ctx; /*unused */
860  ( void ) ctl; /*unused */
861  ( void ) from; /*unused */
862  /*
863  * Counters cannot be written. Do we need to virtualize the
864  * counters so that they can be written, or perhaps modify code so that
865  * they can be written? FIXME ?
866  */
867 
868  return PAPI_ENOSUPP;
869 }
870 
871 /*
872  * perf_event provides a complicated read interface.
873  * the info returned by read() varies depending on whether
874  * you have PERF_FORMAT_GROUP, PERF_FORMAT_TOTAL_TIME_ENABLED,
875  * PERF_FORMAT_TOTAL_TIME_RUNNING, or PERF_FORMAT_ID set
876  *
877  * To simplify things we just always ask for everything. This might
878  * lead to overhead when reading more than we need, but it makes the
879  * read code a lot simpler than the original implementation we had here.
880  *
881  * For more info on the layout see include/linux/perf_event.h
882  *
883  */
884 
885 static int
887  long long **events, int flags )
888 {
889  SUBDBG("ENTER: ctx: %p, ctl: %p, events: %p, flags: %#x\n", ctx, ctl, events, flags);
890 
891  ( void ) flags; /*unused */
892  int i, ret = -1;
893  /* pe_context_t *pe_ctx = ( pe_context_t *) ctx; */
894  (void) ctx; /*unused*/
895  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
896  long long papi_pe_buffer[READ_BUFFER_SIZE];
897  long long tot_time_running, tot_time_enabled, scale;
898 
899  /* Handle case where we are multiplexing */
900  if (pe_ctl->multiplexed) {
901 
902  /* currently we handle multiplexing by having individual events */
903  /* so we read from each in turn. */
904 
905  for ( i = 0; i < pe_ctl->num_events; i++ ) {
906 
907  ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer,
908  sizeof ( papi_pe_buffer ) );
909  if ( ret == -1 ) {
910  PAPIERROR("read returned an error: ", strerror( errno ));
911  SUBDBG("EXIT: PAPI_ESYS\n");
912  return PAPI_ESYS;
913  }
914 
915  /* We should read 3 64-bit values from the counter */
916  if (ret<(signed)(3*sizeof(long long))) {
917  PAPIERROR("Error! short read!\n");
918  SUBDBG("EXIT: PAPI_ESYS\n");
919  return PAPI_ESYS;
920  }
921 
922  SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
923  pe_ctl->events[i].event_fd,
924  (long)pe_ctl->tid, pe_ctl->events[i].cpu, ret);
925  SUBDBG("read: %lld %lld %lld\n",papi_pe_buffer[0],
926  papi_pe_buffer[1],papi_pe_buffer[2]);
927 
928  tot_time_enabled = papi_pe_buffer[1];
929  tot_time_running = papi_pe_buffer[2];
930 
931  SUBDBG("count[%d] = (papi_pe_buffer[%d] %lld * "
932  "tot_time_enabled %lld) / tot_time_running %lld\n",
933  i, 0,papi_pe_buffer[0],
934  tot_time_enabled,tot_time_running);
935 
936  if (tot_time_running == tot_time_enabled) {
937  /* No scaling needed */
938  pe_ctl->counts[i] = papi_pe_buffer[0];
939  } else if (tot_time_running && tot_time_enabled) {
940  /* Scale factor of 100 to avoid overflows when computing */
941  /*enabled/running */
942 
943  scale = (tot_time_enabled * 100LL) / tot_time_running;
944  scale = scale * papi_pe_buffer[0];
945  scale = scale / 100LL;
946  pe_ctl->counts[i] = scale;
947  } else {
948  /* This should not happen, but Phil reports it sometime does. */
949  SUBDBG("perf_event kernel bug(?) count, enabled, "
950  "running: %lld, %lld, %lld\n",
951  papi_pe_buffer[0],tot_time_enabled,
952  tot_time_running);
953 
954  pe_ctl->counts[i] = papi_pe_buffer[0];
955  }
956  }
957  }
958 
959  /* Handle cases where we cannot use FORMAT GROUP */
960  else if (pe_ctl->inherit) {
961 
962  /* we must read each counter individually */
963  for ( i = 0; i < pe_ctl->num_events; i++ ) {
964 
965  ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer,
966  sizeof ( papi_pe_buffer ) );
967  if ( ret == -1 ) {
968  PAPIERROR("read returned an error: ", strerror( errno ));
969  SUBDBG("EXIT: PAPI_ESYS\n");
970  return PAPI_ESYS;
971  }
972 
973  /* we should read one 64-bit value from each counter */
974  if (ret!=sizeof(long long)) {
975  PAPIERROR("Error! short read!\n");
976  PAPIERROR("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
977  pe_ctl->events[i].event_fd,
978  (long)pe_ctl->tid, pe_ctl->events[i].cpu, ret);
979  SUBDBG("EXIT: PAPI_ESYS\n");
980  return PAPI_ESYS;
981  }
982 
983  SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
984  pe_ctl->events[i].event_fd, (long)pe_ctl->tid,
985  pe_ctl->events[i].cpu, ret);
986  SUBDBG("read: %lld\n",papi_pe_buffer[0]);
987 
988  pe_ctl->counts[i] = papi_pe_buffer[0];
989  }
990  }
991 
992 
993  /* Handle cases where we are using FORMAT_GROUP */
994  /* We assume only one group leader, in position 0 */
995 
996  else {
997  if (pe_ctl->events[0].group_leader_fd!=-1) {
998  PAPIERROR("Was expecting group leader!\n");
999  }
1000 
1001  ret = read( pe_ctl->events[0].event_fd, papi_pe_buffer,
1002  sizeof ( papi_pe_buffer ) );
1003 
1004  if ( ret == -1 ) {
1005  PAPIERROR("read returned an error: ", strerror( errno ));
1006  SUBDBG("EXIT: PAPI_ESYS\n");
1007  return PAPI_ESYS;
1008  }
1009 
1010  /* we read 1 64-bit value (number of events) then */
1011  /* num_events more 64-bit values that hold the counts */
1012  if (ret<(signed)((1+pe_ctl->num_events)*sizeof(long long))) {
1013  PAPIERROR("Error! short read!\n");
1014  SUBDBG("EXIT: PAPI_ESYS\n");
1015  return PAPI_ESYS;
1016  }
1017 
1018  SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
1019  pe_ctl->events[0].event_fd,
1020  (long)pe_ctl->tid, pe_ctl->events[0].cpu, ret);
1021  {
1022  int j;
1023  for(j=0;j<ret/8;j++) {
1024  SUBDBG("read %d: %lld\n",j,papi_pe_buffer[j]);
1025  }
1026  }
1027 
1028  /* Make sure the kernel agrees with how many events we have */
1029  if (papi_pe_buffer[0]!=pe_ctl->num_events) {
1030  PAPIERROR("Error! Wrong number of events!\n");
1031  SUBDBG("EXIT: PAPI_ESYS\n");
1032  return PAPI_ESYS;
1033  }
1034 
1035  /* put the count values in their proper location */
1036  for(i=0;i<pe_ctl->num_events;i++) {
1037  pe_ctl->counts[i] = papi_pe_buffer[1+i];
1038  }
1039  }
1040 
1041  /* point PAPI to the values we read */
1042  *events = pe_ctl->counts;
1043 
1044  SUBDBG("EXIT: PAPI_OK\n");
1045  return PAPI_OK;
1046 }
1047 
1048 /* Start counting events */
1049 static int
1051 {
1052  int ret;
1053  int i;
1054  int did_something = 0;
1055  pe_context_t *pe_ctx = ( pe_context_t *) ctx;
1056  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
1057 
1058  /* Reset the counters first. Is this necessary? */
1059  ret = _peu_reset( pe_ctx, pe_ctl );
1060  if ( ret ) {
1061  return ret;
1062  }
1063 
1064  /* Enable all of the group leaders */
1065  /* All group leaders have a group_leader_fd of -1 */
1066  for( i = 0; i < pe_ctl->num_events; i++ ) {
1067  if (pe_ctl->events[i].group_leader_fd == -1) {
1068  SUBDBG("ioctl(enable): fd: %d\n", pe_ctl->events[i].event_fd);
1069  ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_ENABLE, NULL) ;
1070 
1071  /* ioctls always return -1 on failure */
1072  if (ret == -1) {
1073  PAPIERROR("ioctl(PERF_EVENT_IOC_ENABLE) failed.\n");
1074  return PAPI_ESYS;
1075  }
1076 
1077  did_something++;
1078  }
1079  }
1080 
1081  if (!did_something) {
1082  PAPIERROR("Did not enable any counters.\n");
1083  return PAPI_EBUG;
1084  }
1085 
1086  pe_ctx->state |= PERF_EVENTS_RUNNING;
1087 
1088  return PAPI_OK;
1089 
1090 }
1091 
1092 /* Stop all of the counters */
1093 static int
1095 {
1096 
1097  int ret;
1098  int i;
1099  pe_context_t *pe_ctx = ( pe_context_t *) ctx;
1100  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
1101 
1102  /* Just disable the group leaders */
1103  for ( i = 0; i < pe_ctl->num_events; i++ ) {
1104  if ( pe_ctl->events[i].group_leader_fd == -1 ) {
1105  ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_DISABLE, NULL);
1106  if ( ret == -1 ) {
1107  PAPIERROR( "ioctl(%d, PERF_EVENT_IOC_DISABLE, NULL) "
1108  "returned error, Linux says: %s",
1109  pe_ctl->events[i].event_fd, strerror( errno ) );
1110  return PAPI_EBUG;
1111  }
1112  }
1113  }
1114 
1115  pe_ctx->state &= ~PERF_EVENTS_RUNNING;
1116 
1117  return PAPI_OK;
1118 }
1119 
1120 /* Set various options on a control state */
1121 static int
1122 _peu_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
1123 {
1124  int ret;
1125  pe_context_t *pe_ctx = ( pe_context_t *) ctx;
1126  pe_control_t *pe_ctl = NULL;
1127 
1128  switch ( code ) {
1129  case PAPI_MULTIPLEX:
1130  pe_ctl = ( pe_control_t * ) ( option->multiplex.ESI->ctl_state );
1131 
1132  pe_ctl->multiplexed = 1;
1133  ret = _peu_update_control_state( pe_ctl, NULL,
1134  pe_ctl->num_events, pe_ctx );
1135  if (ret != PAPI_OK) {
1136  pe_ctl->multiplexed = 0;
1137  }
1138  return ret;
1139 
1140  case PAPI_ATTACH:
1141  pe_ctl = ( pe_control_t * ) ( option->attach.ESI->ctl_state );
1142 
1143  pe_ctl->tid = option->attach.tid;
1144 
1145  /* If events have been already been added, something may */
1146  /* have been done to the kernel, so update */
1147  ret =_peu_update_control_state( pe_ctl, NULL,
1148  pe_ctl->num_events, pe_ctx);
1149 
1150  return ret;
1151 
1152  case PAPI_DETACH:
1153  pe_ctl = ( pe_control_t *) ( option->attach.ESI->ctl_state );
1154 
1155  pe_ctl->tid = 0;
1156  return PAPI_OK;
1157 
1158  case PAPI_CPU_ATTACH:
1159  pe_ctl = ( pe_control_t *) ( option->cpu.ESI->ctl_state );
1160 
1161  /* this tells the kernel not to count for a thread */
1162  /* should we warn if we try to set both? perf_event */
1163  /* will reject it. */
1164  pe_ctl->tid = -1;
1165 
1166  pe_ctl->cpu = option->cpu.cpu_num;
1167 
1168  return PAPI_OK;
1169 
1170  case PAPI_DOMAIN:
1171  pe_ctl = ( pe_control_t *) ( option->domain.ESI->ctl_state );
1172 
1173  /* looks like we are allowed, so set event set level counting domains */
1174  pe_ctl->domain = option->domain.domain;
1175  return PAPI_OK;
1176 
1177  case PAPI_GRANUL:
1178  pe_ctl = (pe_control_t *) ( option->granularity.ESI->ctl_state );
1179 
1180  /* FIXME: we really don't support this yet */
1181 
1182  switch ( option->granularity.granularity ) {
1183  case PAPI_GRN_PROCG:
1184  case PAPI_GRN_SYS_CPU:
1185  case PAPI_GRN_PROC:
1186  return PAPI_ECMP;
1187 
1188  /* Currently we only support thread and CPU granularity */
1189  case PAPI_GRN_SYS:
1190  pe_ctl->granularity=PAPI_GRN_SYS;
1191  break;
1192 
1193  case PAPI_GRN_THR:
1194  pe_ctl->granularity=PAPI_GRN_THR;
1195  break;
1196 
1197 
1198  default:
1199  return PAPI_EINVAL;
1200  }
1201  return PAPI_OK;
1202 
1203  case PAPI_INHERIT:
1204  pe_ctl = (pe_control_t *) ( option->inherit.ESI->ctl_state );
1205 
1206  if (option->inherit.inherit) {
1207  /* children will inherit counters */
1208  pe_ctl->inherit = 1;
1209  } else {
1210  /* children won't inherit counters */
1211  pe_ctl->inherit = 0;
1212  }
1213  return PAPI_OK;
1214 
1215  case PAPI_DATA_ADDRESS:
1216  return PAPI_ENOSUPP;
1217 
1218  case PAPI_INSTR_ADDRESS:
1219  return PAPI_ENOSUPP;
1220 
1221  case PAPI_DEF_ITIMER:
1222  return PAPI_ENOSUPP;
1223 
1224  case PAPI_DEF_MPX_NS:
1225  return PAPI_ENOSUPP;
1226 
1227  case PAPI_DEF_ITIMER_NS:
1228  return PAPI_ENOSUPP;
1229 
1230  default:
1231  return PAPI_ENOSUPP;
1232  }
1233 }
1234 
1235 
1236 static int
1237 _peu_ntv_enum_events( unsigned int *PapiEventCode, int modifier )
1238 {
1239 
1240  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
1241 
1242 
1243  return _pe_libpfm4_ntv_enum_events(PapiEventCode, modifier, our_cidx,
1245 }
1246 
1247 static int
1248 _peu_ntv_name_to_code( const char *name, unsigned int *event_code) {
1249 
1250  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
1251 
1252  return _pe_libpfm4_ntv_name_to_code(name,event_code, our_cidx,
1254 }
1255 
1256 static int
1257 _peu_ntv_code_to_name(unsigned int EventCode,
1258  char *ntv_name, int len) {
1259 
1260  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
1261 
1262  return _pe_libpfm4_ntv_code_to_name(EventCode,
1263  ntv_name, len,
1265 }
1266 
1267 static int
1268 _peu_ntv_code_to_descr( unsigned int EventCode,
1269  char *ntv_descr, int len) {
1270 
1271  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
1272 
1273  return _pe_libpfm4_ntv_code_to_descr(EventCode,ntv_descr,len,
1275 }
1276 
1277 static int
1278 _peu_ntv_code_to_info(unsigned int EventCode,
1279  PAPI_event_info_t *info) {
1280 
1281  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
1282 
1283  return _pe_libpfm4_ntv_code_to_info(EventCode, info,
1285 }
1286 
1287 /* Our component vector */
1288 
1289 papi_vector_t _perf_event_uncore_vector = {
1290  .cmp_info = {
1291  /* component information (unspecified values initialized to 0) */
1292  .name = "perf_event_uncore",
1293  .short_name = "peu",
1294  .version = "5.0",
1295  .description = "Linux perf_event CPU uncore and northbridge",
1296 
1297  .default_domain = PAPI_DOM_ALL,
1298  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL | PAPI_DOM_SUPERVISOR,
1299  .default_granularity = PAPI_GRN_SYS,
1300  .available_granularities = PAPI_GRN_SYS,
1301 
1302  .num_mpx_cntrs = PERF_EVENT_MAX_MPX_COUNTERS,
1303 
1304  /* component specific cmp_info initializations */
1305  .fast_virtual_timer = 0,
1306  .attach = 1,
1307  .attach_must_ptrace = 1,
1308  .cpu = 1,
1309  .inherit = 1,
1310  .cntr_umasks = 1,
1311 
1312  },
1313 
1314  /* sizes of framework-opaque component-private structures */
1315  .size = {
1316  .context = sizeof ( pe_context_t ),
1317  .control_state = sizeof ( pe_control_t ),
1318  .reg_value = sizeof ( int ),
1319  .reg_alloc = sizeof ( int ),
1320  },
1321 
1322  /* function pointers in this component */
1323  .init_component = _peu_init_component,
1324  .shutdown_component = _peu_shutdown_component,
1325  .init_thread = _peu_init_thread,
1326  .init_control_state = _peu_init_control_state,
1327  .start = _peu_start,
1328  .stop = _peu_stop,
1329  .read = _peu_read,
1330  .shutdown_thread = _peu_shutdown_thread,
1331  .ctl = _peu_ctl,
1332  .update_control_state = _peu_update_control_state,
1333  .set_domain = _peu_set_domain,
1334  .reset = _peu_reset,
1335  .write = _peu_write,
1336 
1337  /* from counter name mapper */
1338  .ntv_enum_events = _peu_ntv_enum_events,
1339  .ntv_name_to_code = _peu_ntv_name_to_code,
1340  .ntv_code_to_name = _peu_ntv_code_to_name,
1341  .ntv_code_to_descr = _peu_ntv_code_to_descr,
1342  .ntv_code_to_info = _peu_ntv_code_to_info,
1343 };
1344 
1345 
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:629
i inherit inherit
#define PAPI_ENOEVNT
Definition: papi.h:260
static int our_cidx
ssize_t read(int fd, void *buf, size_t count)
Definition: appio.c:225
static int open_pe_events(pe_context_t *ctx, pe_control_t *ctl)
long long counts[PERF_EVENT_MAX_MPX_COUNTERS]
int _papi_hwi_get_ntv_idx(unsigned int papi_evt_code)
_papi_int_inherit_t inherit
int errno
int close(int fd)
Definition: appio.c:175
static int _peu_init_thread(hwd_context_t *hwd_ctx)
#define PAPI_CPU_ATTACH
Definition: papi.h:457
#define PERF_EVENT_MAX_MPX_COUNTERS
Definition: perf_event_lib.h:5
EventSetInfo_t * ESI
struct native_event_t * native_events
unsigned int granularity
long long flags
Definition: iozone.c:12330
#define PAPI_DEF_ITIMER_NS
Definition: papi.h:455
EventSetInfo_t * ESI
int _papi_libpfm4_init(papi_vector_t *my_vector)
static int _peu_shutdown_thread(hwd_context_t *ctx)
static int _peu_ntv_code_to_descr(unsigned int EventCode, char *ntv_descr, int len)
static int map_perf_event_errors_to_papi(int perf_event_error)
#define PAPI_INSTR_ADDRESS
Definition: papi.h:453
#define PAPI_DEF_MPX_NS
Definition: papi.h:436
cpu
Definition: iozone.c:3872
int default_granularity
Definition: papi.h:645
#define PAPI_ENOSUPP
Definition: papi.h:271
static int _peu_shutdown_component(void)
#define PAPI_DATA_ADDRESS
Definition: papi.h:452
#define PAPI_DOM_KERNEL
Definition: papi.h:300
papi_vector_t _perf_event_uncore_vector
EventSetInfo_t * ESI
#define PAPI_DOM_ALL
Definition: papi.h:303
#define PERF_EVENTS_OPENED
static int _peu_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *from)
pe_event_info_t events[PERF_EVENT_MAX_MPX_COUNTERS]
int _pe_libpfm4_ntv_enum_events(unsigned int *PapiEventCode, int modifier, int cidx, struct native_event_table_t *event_table)
static int close_pe_events(pe_context_t *ctx, pe_control_t *ctl)
int _pe_libpfm4_ntv_name_to_code(const char *name, unsigned int *event_code, int cidx, struct native_event_table_t *event_table)
#define PAPI_EBUG
Definition: papi.h:259
return PAPI_OK
Definition: linux-nvml.c:497
int count
Definition: iozone.c:22422
fclose(thread_wqfd)
static int _peu_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
#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
#define PAPI_EPERM
Definition: papi.h:268
static int _peu_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
papi_vector_t * _papi_hwd[]
#define PAPI_INHERIT
Definition: papi.h:458
Return codes and api definitions.
uint32_t nr_mmap_pages
FILE * fff[MAX_EVENTS]
static int check_scheduability(pe_context_t *ctx, pe_control_t *ctl)
unsigned int domain
char events[MAX_EVENTS][BUFSIZ]
int multiplex(void)
Definition: multiplex.c:35
_papi_int_attach_t attach
long long ret
Definition: iozone.c:1346
static int _peu_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
unsigned long tid
int _pe_libpfm4_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len, struct native_event_table_t *event_table)
static int cidx
_papi_int_cpu_t cpu
int i
Definition: fileop.c:140
struct native_event_table_t uncore_native_event_table
static int pid
static int _peu_init_control_state(hwd_control_state_t *ctl)
#define PAPI_ESYS
Definition: papi.h:255
static int _peu_init_component(int cidx)
#define PAPI_GRANUL
Definition: papi.h:435
static int native
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
_papi_int_granularity_t granularity
#define PAPI_ECNFLCT
Definition: papi.h:261
EventSetInfo_t * ESI
#define PAPI_DETACH
Definition: papi.h:429
void PAPIERROR(char *format,...)
unsigned int multiplexed
#define PAPI_ATTACH
Definition: papi.h:447
#define PAPI_ECMP
Definition: papi.h:256
struct native_event_table_t * event_table
#define PAPI_MULTIPLEX
Definition: papi.h:431
#define PAPI_GRN_THR
Definition: papi.h:362
int _papi_libpfm4_shutdown(papi_vector_t *my_vector)
int _peu_libpfm4_init(papi_vector_t *my_vector, int cidx, struct native_event_table_t *event_table, int pmu_type)
EventSetInfo_t * ESI
static int _peu_ntv_name_to_code(const char *name, unsigned int *event_code)
#define PAPI_GRN_SYS_CPU
Definition: papi.h:367
_papi_int_multiplex_t multiplex
#define PERF_EVENTS_RUNNING
#define PAPI_ENOMEM
Definition: papi.h:254
again struct sockaddr sizeof(struct sockaddr_in))
int _pe_libpfm4_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info, struct native_event_table_t *event_table)
#define PAPI_ENOCMP
Definition: papi.h:270
#define PAPI_DOMAIN
Definition: papi.h:433
int _pe_libpfm4_ntv_code_to_descr(unsigned int EventCode, char *ntv_descr, int len, struct native_event_table_t *event_table)
static int _peu_ntv_enum_events(unsigned int *PapiEventCode, int modifier)
unsigned int cpu_num
#define PMU_TYPE_UNCORE
int _pe_libpfm4_shutdown(papi_vector_t *my_vector, struct native_event_table_t *event_table)
static int _peu_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len)
#define PAPI_DEF_ITIMER
Definition: papi.h:454
char * name
Definition: iozone.c:23648
perf_event_attr_t attr
static int _peu_set_domain(hwd_control_state_t *ctl, int domain)
struct perf_event_attr attr
int
Definition: iozone.c:18528
static unsigned int get_read_format(unsigned int multiplex, unsigned int inherit, int format_group)
unsigned int inherit
static int _peu_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
#define PAPI_MAX_STR_LEN
Definition: papi.h:465
_papi_int_domain_t domain
static long sys_perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)
#define PAPI_GRN_PROCG
Definition: papi.h:365
#define READ_BUFFER_SIZE
#define PAPI_DOM_SUPERVISOR
Definition: papi.h:302
EventSetInfo_t * ESI
#define PAPI_GRN_SYS
Definition: papi.h:366
hwd_control_state_t * ctl_state
int _peu_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int _peu_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
long j
Definition: iozone.c:19135
ssize_t retval
Definition: libasync.c:338
static int _peu_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
#define PAPI_GRN_PROC
Definition: papi.h:364