PAPI  5.3.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
solaris-niagara2.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * >>>>>> "Development of a PAPI Backend for the Sun Niagara 2 Processor" <<<<<<
3  * -----------------------------------------------------------------------------
4  *
5  * Fabian Gorsler <fabian.gorsler@smail.inf.h-bonn-rhein-sieg.de>
6  *
7  * Hochschule Bonn-Rhein-Sieg, Sankt Augustin, Germany
8  * University of Applied Sciences
9  *
10  * -----------------------------------------------------------------------------
11  *
12  * File: solaris-niagara2.c
13  * Author: fg215045
14  *
15  * Description: This source file is the implementation of a PAPI
16  * component for the Sun Niagara 2 processor (aka UltraSPARC T2)
17  * running on Solaris 10 with libcpc 2.
18  * The machine for implementing this component was courtesy of RWTH
19  * Aachen University, Germany. Thanks to the HPC-Team at RWTH!
20  *
21  * Conventions used:
22  * - __cpc_*: Functions, variables, etc. related to libcpc handling
23  * - __sol_*: Functions, variables, etc. related to Solaris handling
24  * - __int_*: Functions, variables, etc. related to extensions of libcpc
25  * - _niagara*: Functions, variables, etc. needed by PAPI hardware dependent
26  * layer, i.e. the component itself
27  *
28  *
29  * ***** Feel free to convert this header to the PAPI default *****
30  *
31  * -----------------------------------------------------------------------------
32  * Created on April 23, 2009, 7:31 PM
33  ******************************************************************************/
34 
35 #include "papi.h"
36 #include "papi_internal.h"
37 #include "papi_vector.h"
38 #include "solaris-niagara2.h"
39 #include "papi_memory.h"
40 
41 #include <libcpc.h>
42 #include <procfs.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <strings.h>
50 #include <sys/lwp.h>
51 #include <limits.h>
52 #include <sys/processor.h>
53 #include <sys/types.h>
54 #include <sys/time.h>
55 #include <stdarg.h>
56 #include <libgen.h>
57 #include <ucontext.h>
58 #include <sys/regset.h>
59 #include <sys/utsname.h>
60 
61 #include "solaris-common.h"
62 #include "solaris-memory.h"
63 
64 #define hwd_control_state_t _niagara2_control_state_t
65 #define hwd_context_t _niagara2_context_t
66 #define hwd_register_t _niagara2_register_t
67 
68 extern caddr_t _start, _end, _etext, _edata;
70 
71 /* Synthetic events */
73 uint64_t __int_get_synthetic_event( int, hwd_control_state_t *, void * );
76 
77 /* Simple error handlers for convenience */
78 #define __CHECK_ERR_DFLT(retval) \
79  if(retval != 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
80 
81 #define __CHECK_ERR_NULL(retval) \
82  if(retval == NULL){ SUBDBG("RETVAL: NULL\n"); return PAPI_ECMP;}
83 
84 #define __CHECK_ERR_PAPI(retval) \
85  if(retval != PAPI_OK){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
86 
87 #define __CHECK_ERR_INVA(retval) \
88  if(retval != 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_EINVAL;}
89 
90 #define __CHECK_ERR_NEGV(retval) \
91  if(retval < 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
92 
93 // PAPI defined variables
95 
96 // The instance of libcpc
97 static cpc_t *cpc = NULL;
98 
99 typedef struct __t2_store
100 {
101  // Number of counters for a processing unit
102  int npic;
105 } __t2_store_t;
106 
108 static char **__t2_ntv_events;
109 
110 // Variables copied from the old component
111 static int pid;
112 
113 // Data types for utility functions
114 
115 typedef struct __sol_processor_information
116 {
117  int total;
118  int clock;
120 
121 typedef struct __t2_pst_table
122 {
123  int papi_pst;
124  char *ntv_event[MAX_COUNTERS];
125  int ntv_ctrs;
128 
129 #define SYNTHETIC_EVENTS_SUPPORTED 1
130 
131 /* This table structure holds all preset events */
133  /* Presets defined by generic_events(3CPC) */
134  {PAPI_L1_DCM,
135  {"DC_miss", NULL}, 1, NOT_DERIVED},
136  {PAPI_L1_ICM,
137  {"IC_miss", NULL}, 1, NOT_DERIVED},
138  {PAPI_L2_ICM,
139  {"L2_imiss", NULL}, 1, NOT_DERIVED},
140  {PAPI_TLB_DM,
141  {"DTLB_miss", NULL}, 1, NOT_DERIVED},
142  {PAPI_TLB_IM,
143  {"ITLB_miss", NULL}, 1, NOT_DERIVED},
144  {PAPI_TLB_TL,
145  {"TLB_miss", NULL}, 1, NOT_DERIVED},
146  {PAPI_L2_LDM,
147  {"L2_dmiss_ld", NULL}, 1, NOT_DERIVED},
148  {PAPI_BR_TKN,
149  {"Br_taken", NULL}, 1, NOT_DERIVED},
150  {PAPI_TOT_INS,
151  {"Instr_cnt", NULL}, 1, NOT_DERIVED},
152  {PAPI_LD_INS,
153  {"Instr_ld", NULL}, 1, NOT_DERIVED},
154  {PAPI_SR_INS,
155  {"Instr_st", NULL}, 1, NOT_DERIVED},
156  {PAPI_BR_INS,
157  {"Br_completed", NULL}, 1, NOT_DERIVED},
158  /* Presets additionally found, should be checked twice */
159  {PAPI_BR_MSP,
160  {"Br_taken", NULL}, 1, NOT_DERIVED},
161  {PAPI_FP_INS,
162  {"Instr_FGU_arithmetic", NULL}, 1, NOT_DERIVED},
163  {PAPI_RES_STL,
164  {"Idle_strands", NULL}, 1, NOT_DERIVED},
165  {PAPI_SYC_INS,
166  {"Atomics", NULL}, 1, NOT_DERIVED},
167  {PAPI_L2_ICR,
168  {"CPU_ifetch_to_PCX", NULL}, 1, NOT_DERIVED},
169  {PAPI_L1_TCR,
170  {"CPU_ld_to_PCX", NULL}, 1, NOT_DERIVED},
171  {PAPI_L2_TCW,
172  {"CPU_st_to_PCX", NULL}, 1, NOT_DERIVED},
173  /* Derived presets found, should be checked twice */
174  {PAPI_L1_TCM,
175  {"IC_miss", "DC_miss"}, 2, DERIVED_ADD},
176  {PAPI_BR_CN,
177  {"Br_completed", "Br_taken"}, 2, DERIVED_ADD},
178  {PAPI_BR_PRC,
179  {"Br_completed", "Br_taken"}, 2, DERIVED_SUB},
180  {PAPI_LST_INS,
181  {"Instr_st", "Instr_ld"}, 2, DERIVED_ADD},
182 #ifdef SYNTHETIC_EVENTS_SUPPORTED
183  /* This preset does exist in order to support multiplexing */
184  {PAPI_TOT_CYC,
185  {"_syn_cycles_elapsed", "DC_miss"}, 1, NOT_DERIVED},
186 #endif
187  {0,
188  {NULL, NULL}, 0, 0},
189 };
190 
192 
193 #ifdef SYNTHETIC_EVENTS_SUPPORTED
194 enum
195 {
200 #endif
201 
202 #ifdef SYNTHETIC_EVENTS_SUPPORTED
203 typedef struct __int_synthetic_table
204 {
205  int code;
206  char *name;
208 #endif
209 
210 #ifdef SYNTHETIC_EVENTS_SUPPORTED
212  {SYNTHETIC_CYCLES_ELAPSED, "_syn_cycles_elapsed"},
213  {SYNTHETIC_RETURN_ONE, "_syn_return_one"},
214  {SYNTHETIC_RETURN_TWO, "_syn_return_two"},
215  {-1, NULL},
216 };
217 #endif
218 
222 
223 /* DESCRIPTION:
224  * -----------------------------------------------------------------------------
225  * Functions in this section are related to the PAPI hardware dependend layer,
226  * also known as "HWD". In this case the HWD layer is the interface from PAPI
227  * to libcpc 2/Solaris 10.
228  ******************************************************************************/
229 
230 int
232 {
233  int i;
234 
235 #ifdef DEBUG
236  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
237  __LINE__ );
238 #endif
239 
240  /* Clean and set the new flag for each counter */
241 
242  for ( i = 0; i < MAX_COUNTERS; i++ ) {
243 #ifdef DEBUG
244  SUBDBG( " -> %s: Setting flags for PIC#%d, old value: %p\n",
245  __func__, i, ctrl->flags[i] );
246 #endif
247 
248  ctrl->flags[i] &= ~( CPC_COUNTING_DOMAINS );
249 
250 #ifdef DEBUG
251  SUBDBG( " -> %s: +++ cleaned value: %p\n",
252  __func__, ctrl->flags[i] );
253 #endif
254 
255  ctrl->flags[i] |= __cpc_domain_translator( domain );
256 
257 #ifdef DEBUG
258  SUBDBG( " -> %s: +++ new value: %p\n",
259  __func__, ctrl->flags[i] );
260 #endif
261  }
262 
263  /* Recreate the set */
265 
266 #ifdef DEBUG
267  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
268  __LINE__ );
269 #endif
270 
271  return PAPI_OK;
272 }
273 
274 int
275 _niagara2_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
276 {
277 #ifdef DEBUG
278  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
279  __LINE__ );
280  SUBDBG( " -> %s: Option #%d requested\n", __func__, code );
281 #endif
282 
283  /* Only these options are handled which are handled in PAPI_set_opt, as many
284  of the left out options are not settable, like PAPI_MAX_CPUS. */
285 
286  switch ( code ) {
287  case PAPI_DEFDOM:
288  /* From papi.h: Domain for all new eventsets. Takes non-NULL option
289  pointer. */
290 
291  _niagara2_vector.cmp_info.default_domain = option->domain.domain;
292 
293  return PAPI_OK;
294  case PAPI_DOMAIN:
295  /* From papi.h: Domain for an eventset */
296 
297  return _niagara2_set_domain( ctx, option->domain.domain );
298  case PAPI_DEFGRN:
299  /* From papi.h: Granularity for all new eventsets */
300 
301  _niagara2_vector.cmp_info.default_granularity =
302  option->granularity.granularity;
303 
304  return PAPI_OK;
305  case PAPI_GRANUL:
306  /* From papi.h: Granularity for an eventset */
307 
308  /* Only supported granularity is PAPI_GRN_THREAD */
309 
310  return PAPI_OK;
311  case PAPI_DEF_MPX_NS:
312  /* From papi.h: Multiplexing/overflowing interval in ns, same as
313  PAPI_DEF_ITIMER_NS */
314 
315  /* From the old component */
316  option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
317 
318 #ifdef DEBUG
319  SUBDBG( " -> %s: PAPI_DEF_MPX_NS, option->itimer.ns=%d\n",
320  __func__, option->itimer.ns );
321 #endif
322 
323  return PAPI_OK;
324  case PAPI_DEF_ITIMER: // IN THE OLD COMPONENT // USED
325  /* From papi.h: Option to set the type of itimer used in both software
326  multiplexing, overflowing and profiling */
327 
328  /* These tests are taken from the old component. For Solaris 10 the
329  same rules apply as documented in getitimer(2). */
330 
331  if ( ( option->itimer.itimer_num == ITIMER_REAL ) &&
332  ( option->itimer.itimer_sig != SIGALRM ) ) {
333 #ifdef DEBUG
334  SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_REAL needs SIGALRM\n",
335  __func__ );
336 #endif
337 
338  return PAPI_EINVAL;
339  }
340 
341 
342  if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) &&
343  ( option->itimer.itimer_sig != SIGVTALRM ) ) {
344 #ifdef DEBUG
345  SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_VIRTUAL needs SIGVTALRM\n",
346  __func__ );
347 #endif
348 
349  return PAPI_EINVAL;
350  }
351 
352 
353  if ( ( option->itimer.itimer_num == ITIMER_PROF ) &&
354  ( option->itimer.itimer_sig != SIGPROF ) ) {
355 #ifdef DEBUG
356  SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_PROF needs SIGPROF\n",
357  __func__ );
358 #endif
359 
360  return PAPI_EINVAL;
361  }
362 
363 
364  /* As in the old component defined, timer values below 0 are NOT
365  filtered out, but timer values greater than 0 are rounded, either to
366  a value which is at least itimer_res_ns or padded to a multiple of
367  itimer_res_ns. */
368 
369  if ( option->itimer.ns > 0 ) {
370  option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
371 
372 #ifdef DEBUG
373  SUBDBG( " -> %s: PAPI_DEF_ITIMER, option->itimer.ns=%d\n",
374  __func__, option->itimer.ns );
375 #endif
376  }
377 
378  return PAPI_OK;
379  case PAPI_DEF_ITIMER_NS: // IN THE OLD COMPONENT // USED
380  /* From papi.h: Multiplexing/overflowing interval in ns, same as
381  PAPI_DEF_MPX_NS */
382 
383  /* From the old component */
384  option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
385 
386 #ifdef DEBUG
387  SUBDBG( " -> %s: PAPI_DEF_ITIMER_NS, option->itimer.ns=%d\n",
388  __func__, option->itimer.ns );
389 #endif
390 
391  return PAPI_OK;
392  }
393 
394 #ifdef DEBUG
395  SUBDBG( " -> %s: Option not found\n", __func__ );
396  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
397  __LINE__ );
398 #endif
399 
400  /* This place should never be reached */
401  return PAPI_EINVAL;
402 }
403 
404 void
405 _niagara2_dispatch_timer( int signal, siginfo_t * si, void *info )
406 {
407  EventSetInfo_t *ESI = NULL;
408  ThreadInfo_t *thread = NULL;
409  int overflow_vector = 0;
410  hwd_control_state_t *ctrl = NULL;
411  long_long results[MAX_COUNTERS];
412  int i;
413  // Hint from perf_events.c
414  int cidx = _niagara2_vector.cmp_info.CmpIdx;
415 
416 
417 #ifdef DEBUG
418  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
419  __LINE__ );
420  SUBDBG( " -> %s: Overflow handler called by signal #%d\n", __func__,
421  signal );
422 #endif
423 
424  /* From the old component */
425  thread = _papi_hwi_lookup_thread( 0 );
426  ESI = ( EventSetInfo_t * ) thread->running_eventset[cidx];
427 
428  /* From the old component, modified */
429  //
430  if ( ESI == NULL || ESI->master != thread || ESI->ctl_state == NULL ||
431  ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
432 #ifdef DEBUG
433  SUBDBG( " -> %s: Problems with ESI, not necessarily serious\n",
434  __func__ );
435 
436  if ( ESI == NULL ) {
437  SUBDBG( " -> %s: +++ ESI is NULL\n", __func__ );
438  }
439 
440  if ( ESI->master != thread ) {
441  SUBDBG( " -> %s: +++ Thread mismatch, ESI->master=%#x thread=%#x\n",
442  __func__, ESI->master, thread );
443  }
444 
445  if ( ESI->ctl_state == NULL ) {
446  SUBDBG( " -> %s: +++ Counter state invalid\n", __func__ );
447  }
448 
449  if ( ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
450  SUBDBG
451  ( " -> %s: +++ Overflow flag missing, ESI->overflow.flags=%#x\n",
452  __func__, ESI->overflow.flags );
453  }
454 #endif
455 
456  return;
457  }
458 #ifdef DEBUG
459  printf( " -> %s: Preconditions valid, trying to read counters\n",
460  __func__ );
461 #endif
462 
463  ctrl = ESI->ctl_state;
464 
465  if ( _niagara2_read
466  ( ctrl, ctrl, ( long_long ** ) & results, NOT_A_PAPI_HWD_READ )
467  != PAPI_OK ) {
468  /* Failure */
469 
470 #ifdef DEBUG
471  printf( "%s: Failed to read counters\n", __func__ );
472 #endif
473 
474  return;
475  } else {
476  /* Success */
477 
478 #ifdef DEBUG
479  SUBDBG( " -> %s: Counters read\n", __func__ );
480 #endif
481 
482  /* Iterate over all available counters in order to detect which counter
483  overflowed (counter value should be 0 if an hw overflow happened),
484  store the position in the overflow_vector, calculte the offset and
485  shift (value range signed long long vs. unsigned long long). */
486  for ( i = 0; i < ctrl->count; i++ ) {
487  if ( results[i] >= 0 ) {
488 #ifdef DEBUG
489  SUBDBG( " -> %s: Overflow detected at PIC #%d\n", __func__, i );
490 #endif
491 
492  /* Set the bit in the overflow_vector */
493  overflow_vector = overflow_vector | ( 1 << i );
494 
495  /* hoose which method to use depending on the overflow signal. */
496  if ( signal == SIGEMT ) {
497  /* Store the counter value, but only if we have a real *
498  hardware overflow counting with libcpc/SIGEMT. */
499  ctrl->preset[i] = UINT64_MAX - ctrl->threshold[i];
500  ctrl->hangover[i] += ctrl->threshold[i];
501  } else {
502  /* Push the value back, this time PAPI does the work. This is
503  software overflow handling. */
504  cpc_request_preset( cpc, ctrl->idx[i], ctrl->result[i] );
505  }
506  } else {
507 #ifdef DEBUG
508  SUBDBG( " -> %s: No overflow detected at PIC #%d, value=%ld\n",
509  __func__, i, results[i] );
510 #endif
511 
512  /* Save the results read from the counter as we can not store the
513  temporary value in hardware or libcpc. */
514  if ( signal == SIGEMT ) {
515  ctrl->preset[i] += results[i];
516  ctrl->hangover[i] = results[i];
517  }
518  }
519  }
520 
521 #ifdef DEBUG
522  SUBDBG( " -> %s: Restarting set to push values back\n", __func__ );
523 #endif
524 
525  /* Push all values back to the counter as preset */
526  cpc_set_restart( cpc, ctrl->set );
527  }
528 
529 #ifdef DEBUG
530  SUBDBG( " -> %s: Passing overflow to PAPI with overflow_vector=%p\n",
531  __func__, overflow_vector );
532 #endif
533 
534  {
535  /* hw is used as pointer in the dispatching routine of PAPI and might be
536  changed. For safety it is not a pseudo pointer to NULL. */
537  int hw;
538 
539  if ( signal == SIGEMT ) {
540  /* This is a hardware overflow */
541  hw = 1;
542  _papi_hwi_dispatch_overflow_signal( ctrl, ( caddr_t )
544  ( info ), &hw, overflow_vector,
545  1, &thread, ESI->CmpIdx );
546  } else {
547  /* This is a software overflow */
548  hw = 0;
549  _papi_hwi_dispatch_overflow_signal( ctrl, ( caddr_t )
551  ( info ), &hw, overflow_vector,
552  1, &thread, ESI->CmpIdx );
553  }
554  }
555 
556 #ifdef DEBUG
557  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
558  __LINE__ );
559 #endif
560 }
561 
562 static inline void *
564 {
565  ucontext_t *ctx = ( ucontext_t * ) context;
566 
567 #ifdef DEBUG
568  SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
569  __LINE__ );
570 #endif
571 
572  return ( void * ) ctx->uc_mcontext.gregs[REG_PC];
573 }
574 
575 
581 int
583 {
584  int i;
585 
586 #ifdef DEBUG
587  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
588  __LINE__ );
589 #endif
590 
591  // cpc_seterrhndlr(cpc, myapp_errfn);
592 
593  /* Clear the buffer */
594  if ( ctrl->counter_buffer != NULL ) {
595 #ifdef DEBUG
596  SUBDBG( " -> %s: Cleaning buffer\n", __func__ );
597 #endif
598 
599  cpc_buf_destroy( cpc, ctrl->counter_buffer );
600  ctrl->counter_buffer = NULL;
601  }
602 
603  /* Clear the set */
604  if ( ctrl->set != NULL ) {
605 #ifdef DEBUG
606  SUBDBG( " -> %s: Cleaning set\n", __func__ );
607 #endif
608 
609  cpc_set_destroy( cpc, ctrl->set );
610  ctrl->set = NULL;
611  }
612 
613  /* Indicate this idx has no request associated, this counter is unused. */
614  for ( i = 0; i < MAX_COUNTERS; i++ ) {
615 #ifdef DEBUG
616  SUBDBG( " -> %s: Cleaning counter state #%d\n", __func__, i );
617 #endif
618 
619  /* Indicate missing setup values */
620  ctrl->idx[i] = EVENT_NOT_SET;
621  ctrl->code[i].event_code = EVENT_NOT_SET;
622 
623  /* No flags yet set, this is for overflow and binding */
624  ctrl->flags[i] = 0;
625 
626  /* Preset value for counting results */
627  ctrl->preset[i] = DEFAULT_CNTR_PRESET;
628 
629  /* Needed for overflow handling, will be set later */
630  ctrl->threshold[i] = 0;
631  ctrl->hangover[i] = 0;
632 
633 #ifdef SYNTHETIC_EVENTS_SUPPORTED
634  ctrl->syn_hangover[i] = 0;
635 #endif
636  }
637 
638  /* No counters active in this set */
639  ctrl->count = 0;
640 
641 #ifdef SYNTHETIC_EVENTS_SUPPORTED
642  ctrl->syn_count = 0;
643 #endif
644 
645 #ifdef DEBUG
646  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
647  __LINE__ );
648 #endif
649 
650  return PAPI_OK;
651 }
652 
653 int
655 {
656 #ifdef DEBUG
657  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
658  __LINE__ );
659 #endif
660 
661  /* Create an instance of libcpc */
662 #ifdef DEBUG
663  SUBDBG( " -> %s: Trying to initalize libcpc\n", __func__ );
664 #endif
665  cpc = cpc_open( CPC_VER_CURRENT );
667 
668 #ifdef DEBUG
669  SUBDBG( " -> %s: Registering libcpc error handler\n", __func__ );
670 #endif
671  cpc_seterrhndlr( cpc, __cpc_error_handler );
672 
673 #ifdef DEBUG
674  SUBDBG( " -> %s: Detecting supported PICs", __func__ );
675 #endif
676  __t2_store.npic = cpc_npic( cpc );
677 
678 #ifdef DEBUG
679  SUBDBG( " -> %s: Storing component index, cidx=%d\n", __func__, cidx );
680 #endif
681  _niagara2_vector.cmp_info.CmpIdx = cidx;
682 
683 #ifdef DEBUG
684  SUBDBG( " -> %s: Gathering system information for PAPI\n", __func__ );
685 #endif
686  /* Store system info in central data structure */
687  __CHECK_ERR_PAPI( _niagara2_get_system_info( &_papi_hwi_system_info ) );
688 
689 #ifdef DEBUG
690  SUBDBG( " -> %s: Initializing locks\n", __func__ );
691 #endif
692  /* Set up the lock after initialization */
694 
695  // Copied from the old component, _papi_init_component()
696  SUBDBG( "Found %d %s %s CPUs at %d Mhz.\n",
697  _papi_hwi_system_info.hw_info.totalcpus,
698  _papi_hwi_system_info.hw_info.vendor_string,
699  _papi_hwi_system_info.hw_info.model_string,
700  _papi_hwi_system_info.hw_info.cpu_max_mhz );
701 
702  /* Build native event table */
703 #ifdef DEBUG
704  SUBDBG( " -> %s: Building native event table\n", __func__ );
705 #endif
707 
708  /* Build preset event table */
709 #ifdef DEBUG
710  SUBDBG( " -> %s: Building PAPI preset table\n", __func__ );
711 #endif
713 
714  /* Register presets and finish event related setup */
715 #ifdef DEBUG
716  SUBDBG( " -> %s: Registering presets in PAPI\n", __func__ );
717 #endif
718  __CHECK_ERR_PAPI( _papi_hwi_setup_all_presets( preset_table, NULL ) );
719 
720 #ifdef DEBUG
721  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
722  __LINE__ );
723 #endif
724 
725  /* Everything is ok */
726  return PAPI_OK;
727 }
728 
729 static void
731 {
732 #ifdef DEBUG
733  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
734  __LINE__ );
735 #endif
736 
737  /* Copied from old component, lock_init() */
738  memset( lock, 0x0, sizeof ( rwlock_t ) * PAPI_MAX_LOCK );
739 
740 #ifdef DEBUG
741  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
742  __LINE__ );
743 #endif
744 }
745 
746 int
747 _niagara2_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
748 {
749  int event_code = EventCode & PAPI_NATIVE_AND_MASK;
750 
751 #ifdef DEBUG
752  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
753  __LINE__ );
754 #endif
755 
756  if ( event_code >= 0 &&
757  event_code <= _niagara2_vector.cmp_info.num_native_events ) {
758  return PAPI_ENOEVNT;
759  }
760 
761  bits->event_code = event_code;
762 
763 #ifdef DEBUG
764  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
765  __LINE__ );
766 #endif
767 
768  return PAPI_OK;
769 }
770 
771 int
772 _niagara2_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len )
773 {
774 #ifdef DEBUG
775  SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
776  __LINE__ );
777 #endif
778 
779  /* libcpc offers no descriptions, just a link to the reference manual */
780  return _niagara2_ntv_code_to_name( EventCode, ntv_descr, len );
781 }
782 
783 int
784 _niagara2_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len )
785 {
786  int event_code = EventCode & PAPI_NATIVE_AND_MASK;
787 
788 #ifdef DEBUG
789  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
790  __LINE__ );
791 #endif
792 
793  if ( event_code >= 0 &&
794  event_code <= _niagara2_vector.cmp_info.num_native_events ) {
795  strlcpy( ntv_name, __t2_ntv_events[event_code], len );
796 
797  if ( strlen( __t2_ntv_events[event_code] ) > len - 1 ) {
798 #ifdef DEBUG
799  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
800  __LINE__ );
801 #endif
802 
803  /* It's not a real error, but at least a hint */
804  return PAPI_EBUF;
805  }
806 #ifdef DEBUG
807  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
808  __LINE__ );
809 #endif
810 
811  return PAPI_OK;
812  }
813 #ifdef DEBUG
814  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
815  __LINE__ );
816 #endif
817 
818  return PAPI_ENOEVNT;
819 }
820 
821 int
822 _niagara2_ntv_enum_events( unsigned int *EventCode, int modifier )
823 {
824  /* This code is very similar to the code from the old component. */
825 
826  int event_code = *EventCode & PAPI_NATIVE_AND_MASK;
827 
828 #ifdef DEBUG
829  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
830  __LINE__ );
831 #endif
832 
833  if ( modifier == PAPI_ENUM_FIRST ) {
834  *EventCode = PAPI_NATIVE_MASK + 1;
835 
836 #ifdef DEBUG
837  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
838  __LINE__ );
839 #endif
840 
841  return PAPI_OK;
842  }
843 
844  /* The table needs to be shifted by one position (starting index 1), as PAPI
845  expects native event codes not to be 0 (papi_internal.c:744). */
846 
847  if ( event_code >= 1 &&
848  event_code <= _niagara2_vector.cmp_info.num_native_events - 1 ) {
849  *EventCode = *EventCode + 1;
850 
851 #ifdef DEBUG
852  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
853  __LINE__ );
854 #endif
855 
856  return PAPI_OK;
857  }
858 #ifdef DEBUG
859  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
860  __LINE__ );
861 #endif
862 
863  // If nothing found report an error
864  return PAPI_ENOEVNT;
865 }
866 
867 int
869  long_long ** events, int flags )
870 {
871  int i;
872 
873 #ifdef DEBUG
874  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
875  __LINE__ );
876  SUBDBG( " -> %s: called with flags=%p\n", __func__, flags );
877 #endif
878 
879  /* Take a new sample from the PIC to the buffer */
880  __CHECK_ERR_DFLT( cpc_set_sample( cpc, ctrl->set, ctrl->counter_buffer ) );
881 
882  /* Copy the buffer values from all active counters */
883  for ( i = 0; i < ctrl->count; i++ ) {
884  /* Retrieve the counting results of libcpc */
885  __CHECK_ERR_DFLT( cpc_buf_get( cpc, ctrl->counter_buffer, ctrl->idx[i],
886  &ctrl->result[i] ) );
887 
888  /* As libcpc uses uint64_t and PAPI uses int64_t, we need to normalize
889  the result back to a value that PAPI can handle, otherwise the result
890  is not usable as its in the negative range of int64_t and the result
891  becomes useless for PAPI. */
892  if ( ctrl->threshold[i] > 0 ) {
893 #ifdef DEBUG
894  SUBDBG( " -> %s: Normalizing result on PIC#%d to %lld\n",
895  __func__, i, ctrl->result[i] );
896 #endif /* DEBUG */
897 
898  /* This shifts the retrieved value back to the PAPI value range */
899  ctrl->result[i] = ctrl->result[i] -
900  ( UINT64_MAX - ctrl->threshold[i] ) - 1;
901 
902  /* Needed if called internally if a PIC didn't really overflow, but
903  was programmed in the same set. */
904  if ( flags != NOT_A_PAPI_HWD_READ ) {
905  ctrl->result[i] = ctrl->hangover[i];
906  }
907 #ifdef DEBUG
908  SUBDBG( " -> %s: Overflow scaling on PIC#%d:\n", __func__, i );
909  SUBDBG( " -> %s: +++ ctrl->result[%d]=%llu\n",
910  __func__, i, ctrl->result[i] );
911  SUBDBG( " -> %s: +++ ctrl->threshold[%d]=%lld\n",
912  __func__, i, ctrl->threshold[i] );
913  SUBDBG( " -> %s: +++ ctrl->hangover[%d]=%lld\n",
914  __func__, i, ctrl->hangover[i] );
915 #endif
916  }
917 #ifdef DEBUG
918  SUBDBG( " -> %s: +++ ctrl->result[%d]=%llu\n",
919  __func__, i, ctrl->result[i] );
920 #endif
921  }
922 
923 #ifdef SYNTHETIC_EVENTS_SUPPORTED
924  {
925  int i;
926  const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
927  - __t2_store.syn_evt_count;
928 
929  for ( i = 0; i < ctrl->count; i++ ) {
930  if ( ctrl->code[i].event_code >= syn_barrier ) {
931  ctrl->result[i] =
932  __int_get_synthetic_event( ctrl->code[i].event_code
933  - syn_barrier, ctrl, &i );
934  }
935  }
936  }
937 #endif
938 
939  /* Pass the address of the results back to the calling function */
940  *events = ( long_long * ) & ctrl->result[0];
941 
942 #ifdef DEBUG
943  SUBDBG( "LEAVING: %s\n", "_papi_read" );
944 #endif
945 
946  return PAPI_OK;
947 }
948 
949 int
951 {
952 #ifdef DEBUG
953  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
954  __LINE__ );
955 #endif
956 
957  /* This does a restart of the whole set, setting the internal counters back
958  to the value passed as preset of the last call of cpc_set_add_request or
959  cpc_request_preset. */
960  cpc_set_restart( cpc, ctrl->set );
961 
962 #ifdef SYNTHETIC_EVENTS_SUPPORTED
963  {
964  const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
965  - __t2_store.syn_evt_count;
966  int i;
967 
968  if ( ctrl->syn_count > 0 ) {
969  for ( i = 0; i < MAX_COUNTERS; i++ ) {
970  if ( ctrl->code[i].event_code >= syn_barrier ) {
971 
972  ctrl->syn_hangover[i] +=
973  __int_get_synthetic_event( ctrl->code[i].event_code -
974  syn_barrier, ctrl, &i );
975  }
976  }
977  }
978  }
979 #endif
980 
981 #ifdef DEBUG
982  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
983  __LINE__ );
984 #endif
985 
986  return PAPI_OK;
987 }
988 
989 int
990 _niagara2_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold )
991 {
992  /* Seems not to be used. */
993 
994 #ifdef DEBUG
995  SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
996  __LINE__ );
997 #endif
998 
999  return PAPI_ENOSUPP;
1000 }
1001 
1002 int
1003 _niagara2_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
1004 {
1005  hwd_control_state_t *ctrl = ESI->ctl_state;
1006  struct sigaction sigact;
1007 
1008 #ifdef DEBUG
1009  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1010  __LINE__ );
1011  SUBDBG( " -> %s: Overflow handling for %#x on PIC#%d requested\n",
1012  __func__, ctrl, EventIndex );
1013  SUBDBG( " -> %s: ESI->overflow.flags=%#x\n\n", __func__, ctrl,
1014  ESI->overflow.flags );
1015 #endif
1016 
1017  /* If threshold > 0, then activate hardware overflow handling, otherwise
1018  disable it. */
1019  if ( threshold > 0 ) {
1020 #ifdef DEBUG
1021  SUBDBG( " -> %s: Activating overflow handling\n", __func__ );
1022 #endif
1023 
1024  ctrl->preset[EventIndex] = UINT64_MAX - threshold;
1025  ctrl->threshold[EventIndex] = threshold;
1026 
1027  /* If SIGEMT is not yet enabled, enable it. In libcpc this means to re-
1028  recreate the used set. In order not to break PAPI operations only the
1029  event referred by EventIndex will be updated to use SIGEMT. */
1030  if ( !( ctrl->flags[EventIndex] & CPC_OVF_NOTIFY_EMT ) ) {
1031 #ifdef DEBUG
1032  SUBDBG( " -> %s: Need to activate SIGEMT on PIC %d\n",
1033  __func__, EventIndex );
1034 #endif
1035 
1036  /* Enable overflow handling */
1037  if ( __cpc_enable_sigemt( ctrl, EventIndex ) != PAPI_OK ) {
1038 #ifdef DEBUG
1039  SUBDBG( " -> %s: Activating SIGEMT failed for PIC %d\n",
1040  __func__, EventIndex );
1041 #endif
1042 
1043  return PAPI_ESYS;
1044  }
1045  }
1046 #ifdef DEBUG
1047  SUBDBG( " -> %s: SIGEMT activated, will install signal handler\n",
1048  __func__ );
1049 #endif
1050 
1051  // FIXME: Not really sure that this construct is working
1052  return _papi_hwi_start_signal( SIGEMT, 1, 0 );
1053 
1054  } else {
1055 #ifdef DEBUG
1056  SUBDBG( " -> %s: Disabling overflow handling\n", __func__ );
1057 #endif
1058 
1059  /* Resetting values which were used for overflow handling */
1060  ctrl->preset[EventIndex] = DEFAULT_CNTR_PRESET;
1061  ctrl->flags[EventIndex] &= ~( CPC_OVF_NOTIFY_EMT );
1062  ctrl->threshold[EventIndex] = 0;
1063  ctrl->hangover[EventIndex] = 0;
1064 
1065 #ifdef DEBUG
1066  SUBDBG( " -> %s:ctrl->preset[%d]=%d, ctrl->flags[%d]=%p\n",
1067  __func__, EventIndex, ctrl->preset[EventIndex],
1068  EventIndex, ctrl->flags[EventIndex] );
1069 #endif
1070 
1071  /* Recreate the undelying set and disable the signal handler */
1074  }
1075 
1076 
1077 
1078 #ifdef DEBUG
1079  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1080  __LINE__ );
1081 #endif
1082 
1083  return PAPI_OK;
1084 }
1085 
1086 int
1088 {
1089 #ifdef DEBUG
1090  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1091  __LINE__ );
1092 #endif
1093 
1094  cpc_buf_destroy( cpc, ctx->counter_buffer );
1095  cpc_set_destroy( cpc, ctx->set );
1096 
1097 #ifdef DEBUG
1098  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1099  __LINE__ );
1100 #endif
1101 
1102  return PAPI_OK;
1103 }
1104 
1105 int
1107 {
1108 #ifdef DEBUG
1109  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1110  __LINE__ );
1111 #endif
1112 
1113  /* Free allocated memory */
1114 
1115  // papi_calloc in __cpc_build_ntv_table
1116  papi_free( __t2_store.pic_ntv_count );
1117  // papi_calloc in __cpc_build_ntv_table
1119  // papi_calloc in __cpc_build_pst_table
1120  papi_free( preset_table );
1121 
1122  /* Shutdown libcpc */
1123 
1124  // cpc_open in _papi_init_component
1125  cpc_close( cpc );
1126 
1127 #ifdef DEBUG
1128  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1129  __LINE__ );
1130 #endif
1131 
1132  return PAPI_OK;
1133 }
1134 
1135 int
1137 {
1138  int retval;
1139 
1140 #ifdef DEBUG
1141  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1142  __LINE__ );
1143  SUBDBG( " -> %s: Starting EventSet %p\n", __func__, ctrl );
1144 #endif
1145 
1146 
1147 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1148  {
1149 #ifdef DEBUG
1150  SUBDBG( " -> %s: Event count: ctrl->count=%d, ctrl->syn_count=%d\n",
1151  __func__, ctrl->count, ctrl->syn_count );
1152 #endif
1153 
1154  if ( ctrl->count > 0 && ctrl->count == ctrl->syn_count ) {
1155  ctrl->idx[0] = cpc_set_add_request( cpc, ctrl->set, "Instr_cnt",
1156  ctrl->preset[0], ctrl->flags[0],
1157  0, NULL );
1158  ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
1159  }
1160  }
1161 #endif
1162 
1163 #ifdef DEBUG
1164  {
1165  int i;
1166 
1167  for ( i = 0; i < MAX_COUNTERS; i++ ) {
1168  SUBDBG( " -> %s: Flags for PIC#%d: ctrl->flags[%d]=%d\n", __func__,
1169  i, i, ctrl->flags[i] );
1170  }
1171  }
1172 #endif
1173 
1174  __CHECK_ERR_DFLT( cpc_bind_curlwp( cpc, ctrl->set, CPC_BIND_LWP_INHERIT ) );
1175 
1176  /* Ensure the set is working properly */
1177  retval = cpc_set_sample( cpc, ctrl->set, ctrl->counter_buffer );
1178 
1179  if ( retval != 0 ) {
1180  printf( "%s: cpc_set_sample failed, return=%d, errno=%d\n",
1181  __func__, retval, errno );
1182  return PAPI_ECMP;
1183  }
1184 #ifdef DEBUG
1185  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1186  __LINE__ );
1187 #endif
1188 
1189  return PAPI_OK;
1190 }
1191 
1192 int
1194 {
1195 #ifdef DEBUG
1196  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1197  __LINE__ );
1198 #endif
1199 
1200  __CHECK_ERR_DFLT( cpc_unbind( cpc, ctrl->set ) );
1201 
1202 #ifdef DEBUG
1203  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1204  __LINE__ );
1205 #endif
1206 
1207  return PAPI_OK;
1208 }
1209 
1210 int
1212  NativeInfo_t * native, int count,
1213  hwd_context_t * ctx )
1214 {
1215  int i;
1216 
1217 #ifdef DEBUG
1218  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1219  __LINE__ );
1220 #endif
1221 
1222  /* Delete everything as we can't change an existing set */
1223  if ( ctrl->counter_buffer != NULL ) {
1224  __CHECK_ERR_DFLT( cpc_buf_destroy( cpc, ctrl->counter_buffer ) );
1225  }
1226 
1227  if ( ctrl->set != NULL ) {
1228  __CHECK_ERR_DFLT( cpc_set_destroy( cpc, ctrl->set ) );
1229  }
1230 
1231  for ( i = 0; i < MAX_COUNTERS; i++ ) {
1232  ctrl->idx[i] = EVENT_NOT_SET;
1233  }
1234 
1235  /* New setup */
1236 
1237  ctrl->set = cpc_set_create( cpc );
1238  __CHECK_ERR_NULL( ctrl->set );
1239 
1240  ctrl->count = count;
1241  ctrl->syn_count = 0;
1242 
1243  for ( i = 0; i < count; i++ ) {
1244  /* Store the active event */
1245  ctrl->code[i].event_code = native[i].ni_event & PAPI_NATIVE_AND_MASK;
1246 
1247  ctrl->flags[i] = __cpc_domain_translator( PAPI_DOM_USER );
1248  ctrl->preset[i] = DEFAULT_CNTR_PRESET;
1249 
1250 #ifdef DEBUG
1251  SUBDBG
1252  ( " -> %s: EventSet@0x%p/PIC#%d - ntv request >>%s<< (%d), flags=%#x\n",
1253  __func__, ctrl, i, __t2_ntv_events[ctrl->code[i].event_code],
1254  ctrl->code[i].event_code, ctrl->flags[i] );
1255 #endif
1256 
1257  /* Store the counter position (???) */
1258  native[i].ni_position = i;
1259 
1260 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1261  {
1262  int syn_code = ctrl->code[i].event_code -
1263  ( _niagara2_vector.cmp_info.num_native_events
1264  - __t2_store.syn_evt_count ) - 1;
1265 
1266  /* Check if the event code is bigger than the CPC provided events. */
1267  if ( syn_code >= 0 ) {
1268 #ifdef DEBUG
1269  SUBDBG
1270  ( " -> %s: Adding synthetic event %#x (%s) on position %d\n",
1271  __func__, native[i].ni_event,
1272  __t2_ntv_events[ctrl->code[i].event_code], i );
1273 #endif
1274 
1275  /* Call the setup routine */
1276  __int_setup_synthetic_event( syn_code, ctrl, NULL );
1277 
1278  /* Clean the hangover count as this event is new */
1279  ctrl->syn_hangover[i] = 0;
1280 
1281  /* Register this event as being synthetic, as an event set only
1282  based on synthetic events can not be actived through libcpc */
1283  ctrl->syn_count++;
1284 
1285  /* Jump to next iteration */
1286  continue;
1287  }
1288  }
1289 #endif
1290 
1291 #ifdef DEBUG
1292  SUBDBG( " -> %s: Adding native event %#x (%s) on position %d\n",
1293  __func__, native[i].ni_event,
1294  __t2_ntv_events[ctrl->code[i].event_code], i );
1295 #endif
1296 
1297  /* Pass the event as request to libcpc */
1298  ctrl->idx[i] = cpc_set_add_request( cpc, ctrl->set,
1299  __t2_ntv_events[ctrl->code[i].
1300  event_code],
1301  ctrl->preset[i], ctrl->flags[i], 0,
1302  NULL );
1303  __CHECK_ERR_NEGV( ctrl->idx[i] );
1304  }
1305 
1306 #ifdef DEBUG
1307  if ( i == 0 ) {
1308  SUBDBG( " -> %s: nothing added\n", __func__ );
1309  }
1310 #endif
1311 
1312  ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
1313  __CHECK_ERR_NULL( ctrl->counter_buffer );
1314 
1315  /* Finished the new setup */
1316 
1317  /* Linking to context (same data type by typedef!) */
1318  ctx = ctrl;
1319 
1320 #ifdef DEBUG
1321  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1322  __LINE__ );
1323 #endif
1324 
1325  return PAPI_OK;
1326 }
1327 
1328 int
1330 {
1331  char *file = "/proc/self/map";
1332  char *resolve_pattern = "/proc/self/path/%s";
1333 
1334  char lastobject[PRMAPSZ];
1335  char link[PAPI_HUGE_STR_LEN];
1336  char path[PAPI_HUGE_STR_LEN];
1337 
1338  prmap_t mapping;
1339 
1340  int fd, count = 0, total = 0, position = -1, first = 1;
1341  caddr_t t_min, t_max, d_min, d_max;
1342 
1343  PAPI_address_map_t *pam, *cur;
1344 
1345 #ifdef DEBUG
1346  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1347  __LINE__ );
1348 #endif
1349 
1350  fd = open( file, O_RDONLY );
1351 
1352  if ( fd == -1 ) {
1353  return PAPI_ESYS;
1354  }
1355 
1356  memset( lastobject, 0, PRMAPSZ );
1357 
1358 #ifdef DEBUG
1359  SUBDBG( " -> %s: Preprocessing memory maps from procfs\n", __func__ );
1360 #endif
1361 
1362  /* Search through the list of mappings in order to identify a) how many
1363  mappings are available and b) how many unique mappings are available. */
1364  while ( read( fd, &mapping, sizeof ( prmap_t ) ) > 0 ) {
1365 #ifdef DEBUG
1366  SUBDBG( " -> %s: Found a new memory map entry\n", __func__ );
1367 #endif
1368  /* Another entry found, just the total count of entries. */
1369  total++;
1370 
1371  /* Is the mapping accessible and not anonymous? */
1372  if ( mapping.pr_mflags & ( MA_READ | MA_WRITE | MA_EXEC ) &&
1373  !( mapping.pr_mflags & MA_ANON ) ) {
1374  /* Test if a new library has been found. If a new library has been
1375  found a new entry needs to be counted. */
1376  if ( strcmp( lastobject, mapping.pr_mapname ) != 0 ) {
1377  strncpy( lastobject, mapping.pr_mapname, PRMAPSZ );
1378  count++;
1379 
1380 #ifdef DEBUG
1381  SUBDBG( " -> %s: Memory mapping entry valid for %s\n", __func__,
1382  mapping.pr_mapname );
1383 #endif
1384  }
1385  }
1386  }
1387 #ifdef DEBUG
1388  SUBDBG( " -> %s: Preprocessing done, starting to analyze\n", __func__ );
1389 #endif
1390 
1391 
1392  /* Start from the beginning, now fill in the found mappings */
1393  if ( lseek( fd, 0, SEEK_SET ) == -1 ) {
1394  return PAPI_ESYS;
1395  }
1396 
1397  memset( lastobject, 0, PRMAPSZ );
1398 
1399  /* Allocate memory */
1400  pam =
1401  ( PAPI_address_map_t * ) papi_calloc( count,
1402  sizeof ( PAPI_address_map_t ) );
1403 
1404  while ( read( fd, &mapping, sizeof ( prmap_t ) ) > 0 ) {
1405 
1406  if ( mapping.pr_mflags & MA_ANON ) {
1407 #ifdef DEBUG
1408  SUBDBG
1409  ( " -> %s: Anonymous mapping (MA_ANON) found for %s, skipping\n",
1410  __func__, mapping.pr_mapname );
1411 #endif
1412  continue;
1413  }
1414 
1415  /* Check for a new entry */
1416  if ( strcmp( mapping.pr_mapname, lastobject ) != 0 ) {
1417 #ifdef DEBUG
1418  SUBDBG( " -> %s: Analyzing mapping for %s\n", __func__,
1419  mapping.pr_mapname );
1420 #endif
1421  cur = &( pam[++position] );
1422  strncpy( lastobject, mapping.pr_mapname, PRMAPSZ );
1423  snprintf( link, PAPI_HUGE_STR_LEN, resolve_pattern, lastobject );
1424  memset( path, 0, PAPI_HUGE_STR_LEN );
1425  readlink( link, path, PAPI_HUGE_STR_LEN );
1426  strncpy( cur->name, path, PAPI_HUGE_STR_LEN );
1427 #ifdef DEBUG
1428  SUBDBG( " -> %s: Resolved name for %s: %s\n", __func__,
1429  mapping.pr_mapname, cur->name );
1430 #endif
1431  }
1432 
1433  if ( mapping.pr_mflags & MA_READ ) {
1434  /* Data (MA_WRITE) or text (MA_READ) segment? */
1435  if ( mapping.pr_mflags & MA_WRITE ) {
1436  cur->data_start = ( caddr_t ) mapping.pr_vaddr;
1437  cur->data_end =
1438  ( caddr_t ) ( mapping.pr_vaddr + mapping.pr_size );
1439 
1440  if ( strcmp
1441  ( cur->name,
1442  _papi_hwi_system_info.exe_info.fullname ) == 0 ) {
1443  _papi_hwi_system_info.exe_info.address_info.data_start =
1444  cur->data_start;
1445  _papi_hwi_system_info.exe_info.address_info.data_end =
1446  cur->data_end;
1447  }
1448 
1449  if ( first )
1450  d_min = cur->data_start;
1451  if ( first )
1452  d_max = cur->data_end;
1453 
1454  if ( cur->data_start < d_min ) {
1455  d_min = cur->data_start;
1456  }
1457 
1458  if ( cur->data_end > d_max ) {
1459  d_max = cur->data_end;
1460  }
1461  } else if ( mapping.pr_mflags & MA_EXEC ) {
1462  cur->text_start = ( caddr_t ) mapping.pr_vaddr;
1463  cur->text_end =
1464  ( caddr_t ) ( mapping.pr_vaddr + mapping.pr_size );
1465 
1466  if ( strcmp
1467  ( cur->name,
1468  _papi_hwi_system_info.exe_info.fullname ) == 0 ) {
1469  _papi_hwi_system_info.exe_info.address_info.text_start =
1470  cur->text_start;
1471  _papi_hwi_system_info.exe_info.address_info.text_end =
1472  cur->text_end;
1473  }
1474 
1475  if ( first )
1476  t_min = cur->text_start;
1477  if ( first )
1478  t_max = cur->text_end;
1479 
1480  if ( cur->text_start < t_min ) {
1481  t_min = cur->text_start;
1482  }
1483 
1484  if ( cur->text_end > t_max ) {
1485  t_max = cur->text_end;
1486  }
1487  }
1488  }
1489 
1490  first = 0;
1491  }
1492 
1493  close( fd );
1494 
1495  /* During the walk of shared objects the upper and lower bound of the
1496  segments could be discovered. The bounds are stored in the PAPI info
1497  structure. The information is important for the profiling functions of
1498  PAPI. */
1499 
1500 /* This variant would pass the addresses of all text and data segments
1501  _papi_hwi_system_info.exe_info.address_info.text_start = t_min;
1502  _papi_hwi_system_info.exe_info.address_info.text_end = t_max;
1503  _papi_hwi_system_info.exe_info.address_info.data_start = d_min;
1504  _papi_hwi_system_info.exe_info.address_info.data_end = d_max;
1505 */
1506 
1507 #ifdef DEBUG
1508  SUBDBG( " -> %s: Analysis of memory maps done, results:\n", __func__ );
1509  SUBDBG( " -> %s: text_start=%#x, text_end=%#x, text_size=%lld\n", __func__,
1510  _papi_hwi_system_info.exe_info.address_info.text_start,
1511  _papi_hwi_system_info.exe_info.address_info.text_end,
1512  _papi_hwi_system_info.exe_info.address_info.text_end
1513  - _papi_hwi_system_info.exe_info.address_info.text_start );
1514  SUBDBG( " -> %s: data_start=%#x, data_end=%#x, data_size=%lld\n", __func__,
1515  _papi_hwi_system_info.exe_info.address_info.data_start,
1516  _papi_hwi_system_info.exe_info.address_info.data_end,
1517  _papi_hwi_system_info.exe_info.address_info.data_end
1518  - _papi_hwi_system_info.exe_info.address_info.data_start );
1519 #endif
1520 
1521  /* Store the map read and the total count of shlibs found */
1522  _papi_hwi_system_info.shlib_info.map = pam;
1523  _papi_hwi_system_info.shlib_info.count = count;
1524 
1525 #ifdef DEBUG
1526  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1527  __LINE__ );
1528 #endif
1529 
1530  return PAPI_OK;
1531 }
1532 
1533 
1537 
1538 /* DESCRIPTION:
1539  * -----------------------------------------------------------------------------
1540  * The following functions are for accessing libcpc 2 and Solaris related stuff
1541  * needed for PAPI.
1542  ******************************************************************************/
1543 
1544 static inline int
1546 {
1547  int i, tmp;
1548 
1549 #ifdef DEBUG
1550  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1551  __LINE__ );
1552 #endif
1553 
1554  __t2_store.pic_ntv_count = papi_calloc( __t2_store.npic, sizeof ( int ) );
1555  __CHECK_ERR_NULL( __t2_store.pic_ntv_count );
1556 
1557 #ifdef DEBUG
1558  SUBDBG( " -> %s: Checking PICs for functionality\n", __func__ );
1559 #endif
1560 
1561  for ( i = 0; i < __t2_store.npic; i++ ) {
1562  cpc_walk_events_pic( cpc, i, NULL, __cpc_walk_events_pic_action_count );
1563 
1564 #ifdef DEBUG
1565  SUBDBG( " -> %s: Found %d events on PIC#%d\n", __func__,
1566  __t2_store.pic_ntv_count[i], i );
1567 #endif
1568  }
1569 
1570  tmp = __t2_store.pic_ntv_count[0];
1571 
1572  /* There should be at least one counter... */
1573  if ( tmp == 0 ) {
1574 #ifdef DEBUG
1575  SUBDBG( " -> %s: PIC#0 has 0 events\n", __func__ );
1576 #endif
1577 
1578  return PAPI_ECMP;
1579  }
1580 
1581  /* Check if all PICs have the same number of counters */
1582  for ( i = 0; i < __t2_store.npic; i++ ) {
1583  if ( __t2_store.pic_ntv_count[i] != tmp ) {
1584 #ifdef DEBUG
1585  SUBDBG( " -> %s: PIC#%d has %d events, should have %d\n",
1586  __func__, i, __t2_store.pic_ntv_count[i], tmp );
1587 #endif
1588 
1589  return PAPI_ECMP;
1590  }
1591  }
1592 
1593  /* Count synthetic events which add functionality to libcpc */
1594 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1595  __t2_store.syn_evt_count = 0;
1597 #endif
1598 
1599  /* Store the count of events available in central data structure */
1600 #ifndef SYNTHETIC_EVENTS_SUPPORTED
1601  _niagara2_vector.cmp_info.num_native_events = __t2_store.pic_ntv_count[0];
1602 #else
1603  _niagara2_vector.cmp_info.num_native_events =
1604  __t2_store.pic_ntv_count[0] + __t2_store.syn_evt_count;
1605 #endif
1606 
1607 
1608  /* Allocate memory for storing all events found, including the first empty
1609  slot */
1610  __t2_ntv_events =
1611  papi_calloc( _niagara2_vector.cmp_info.num_native_events + 1,
1612  sizeof ( char * ) );
1613 
1614  __t2_ntv_events[0] = "THIS IS A BUG!";
1615 
1616  tmp = 1;
1617  cpc_walk_events_pic( cpc, 0, ( void * ) &tmp,
1619 
1620 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1622 #endif
1623 
1624 #ifdef DEBUG
1625  for ( i = 1; i < __t2_store.pic_ntv_count[0]; i++ ) {
1626  SUBDBG( " -> %s: Event #%d: %s\n", __func__, i, __t2_ntv_events[i] );
1627  }
1628 #endif
1629 
1630 #ifdef DEBUG
1631  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1632  __LINE__ );
1633 #endif
1634 
1635  return PAPI_OK;
1636 }
1637 
1638 /* Return event code for event_name */
1639 
1640 static inline int
1641 __cpc_search_ntv_event( char *event_name, int *event_code )
1642 {
1643  int i;
1644 
1645  for ( i = 0; i < _niagara2_vector.cmp_info.num_native_events; i++ ) {
1646  if ( strcmp( event_name, __t2_ntv_events[i] ) == 0 ) {
1647  *event_code = i;
1648  return PAPI_OK;
1649  }
1650  }
1651 
1652  return PAPI_ENOEVNT;
1653 }
1654 
1655 static inline int
1657 {
1658  int num_psts, i, j, event_code, pst_events;
1659  hwi_search_t tmp;
1660 
1661 #ifdef DEBUG
1662  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1663  __LINE__ );
1664 #endif
1665 
1666  num_psts = 0;
1667 
1668  while ( __t2_table[num_psts].papi_pst != 0 ) {
1669  num_psts++;
1670  }
1671 
1672 #ifdef DEBUG
1673  SUBDBG( " -> %s: Found %d presets\n", __func__, num_psts );
1674 #endif
1675 
1676  preset_table = papi_calloc( num_psts + 1, sizeof ( hwi_search_t ) );
1677  __CHECK_ERR_NULL( preset_table );
1678 
1679  pst_events = 0;
1680 
1681  for ( i = 0; i < num_psts; i++ ) {
1682  memset( &tmp, PAPI_NULL, sizeof ( tmp ) );
1683 
1684  /* Mark counters as unused. If they are needed, they will be overwritten
1685  later. See papi_preset.c:51 for more details. */
1686  for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
1687  tmp.data.native[j] = PAPI_NULL;
1688  }
1689 
1690  tmp.event_code = __t2_table[i].papi_pst;
1691  tmp.data.derived = __t2_table[i].ntv_opcode;
1692  tmp.data.operation[0] = '\0';
1693 
1694  switch ( __t2_table[i].ntv_opcode ) {
1695  case DERIVED_ADD:
1696  tmp.data.operation[0] = '+';
1697  break;
1698  case DERIVED_SUB:
1699  tmp.data.operation[0] = '-';
1700  break;
1701  }
1702 
1703  for ( j = 0; j < __t2_table[i].ntv_ctrs; j++ ) {
1705  ( __t2_table[i].ntv_event[j], &event_code )
1706  >= PAPI_OK ) {
1707  tmp.data.native[j] = event_code;
1708  } else {
1709  continue;
1710  }
1711  }
1712 
1713 #ifdef DEBUG
1714  SUBDBG( " -> %s: pst row %d - event_code=%d\n",
1715  __func__, i, tmp.event_code );
1716  SUBDBG( " -> %s: pst row %d - data.derived=%d, data.operation=%c\n",
1717  __func__, i, tmp.data.derived, tmp.data.operation[0] );
1718  SUBDBG( " -> %s: pst row %d - native event codes:\n", __func__, i );
1719  {
1720  int d_i;
1721 
1722  for ( d_i = 0; d_i < PAPI_EVENTS_IN_DERIVED_EVENT; d_i++ ) {
1723  SUBDBG( " -> %s: pst row %d - +++ data.native[%d]=%d\n",
1724  __func__, i, d_i, tmp.data.native[d_i] );
1725  }
1726  }
1727 #endif
1728 
1729  memcpy( &preset_table[i], &tmp, sizeof ( tmp ) );
1730 
1731  pst_events++;
1732  }
1733 
1734  // Check!
1735  memset( &preset_table[num_psts], 0, sizeof ( hwi_search_t ) );
1736 
1737  _niagara2_vector.cmp_info.num_preset_events = pst_events;
1738 
1739 #ifdef DEBUG
1740  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1741  __LINE__ );
1742 #endif
1743 
1744  return PAPI_OK;
1745 }
1746 
1747 static inline int
1749 {
1750 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1751  const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
1752  - __t2_store.syn_evt_count;
1753 #endif
1754 
1755  int i;
1756 
1757 #ifdef DEBUG
1758  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1759  __LINE__ );
1760 #endif
1761 
1762  /* Destroy the old buffer and the old set if they exist, we need to do a full
1763  recreate as changing flags or events through libcpc is not possible */
1764  if ( ctrl->counter_buffer != NULL ) {
1765  __CHECK_ERR_DFLT( cpc_buf_destroy( cpc, ctrl->counter_buffer ) );
1766  }
1767 
1768  if ( ctrl->set != NULL ) {
1769  __CHECK_ERR_DFLT( cpc_set_destroy( cpc, ctrl->set ) );
1770  }
1771 
1772  /* Create a new set */
1773  ctrl->set = cpc_set_create( cpc );
1774  __CHECK_ERR_NULL( ctrl->set );
1775 
1776  for ( i = 0; i < ctrl->count; i++ ) {
1777 #ifdef DEBUG
1778  SUBDBG( " -> %s: Adding native event %#x (%s) on position %d\n",
1779  __func__, ctrl->code[i].event_code,
1780  __t2_ntv_events[ctrl->code[i].event_code], i );
1781  SUBDBG( " -> %s: Event setup: ctrl->code[%d].event_code=%#x\n",
1782  __func__, i, ctrl->code[i].event_code );
1783  SUBDBG( " -> %s: Event setup: ctrl->preset[%d]=%d\n",
1784  __func__, i, ctrl->preset[i] );
1785  SUBDBG( " -> %s: Event setup: ctrl->flags[%d]=%#x\n",
1786  __func__, i, ctrl->flags[i] );
1787 #endif
1788 
1789 #ifdef SYNTHETIC_EVENTS_SUPPORTED
1790  /* Ensure that synthetic events are skipped */
1791  if ( ctrl->code[i].event_code >= syn_barrier ) {
1792 #ifdef DEBUG
1793  SUBDBG( " -> %s: Skipping counter %d, synthetic event found\n",
1794  __func__, i );
1795 #endif
1796 
1797  /* Next iteration */
1798  continue;
1799  }
1800 #endif
1801 
1802  ctrl->idx[i] = cpc_set_add_request( cpc, ctrl->set,
1803  __t2_ntv_events[ctrl->code[i].
1804  event_code],
1805  ctrl->preset[i], ctrl->flags[i], 0,
1806  NULL );
1807  __CHECK_ERR_NEGV( ctrl->idx[i] );
1808  }
1809 
1810  ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
1811  __CHECK_ERR_NULL( ctrl->counter_buffer );
1812 
1813 #ifdef DEBUG
1814  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1815  __LINE__ );
1816 #endif
1817 
1818  return PAPI_OK;
1819 }
1820 
1821 static inline int
1822 __cpc_domain_translator( const int papi_domain )
1823 {
1824  int domain = 0;
1825 
1826 #ifdef DEBUG
1827  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1828  __LINE__ );
1829  SUBDBG( " -> %s: papi_domain=%d requested\n", __func__, papi_domain );
1830 #endif
1831 
1832  if ( papi_domain & PAPI_DOM_USER ) {
1833 #ifdef DEBUG
1834  SUBDBG( " -> %s: Domain PAPI_DOM_USER/CPC_COUNT_USER selected\n",
1835  __func__ );
1836 #endif
1837  domain |= CPC_COUNT_USER;
1838  }
1839 
1840  if ( papi_domain & PAPI_DOM_KERNEL ) {
1841 #ifdef DEBUG
1842  SUBDBG( " -> %s: Domain PAPI_DOM_KERNEL/CPC_COUNT_SYSTEM selected\n",
1843  __func__ );
1844 #endif
1845  domain |= CPC_COUNT_SYSTEM;
1846  }
1847 
1848  if ( papi_domain & PAPI_DOM_SUPERVISOR ) {
1849 #ifdef DEBUG
1850  SUBDBG( " -> %s: Domain PAPI_DOM_SUPERVISOR/CPC_COUNT_HV selected\n",
1851  __func__ );
1852 #endif
1853  domain |= CPC_COUNT_HV;
1854  }
1855 #ifdef DEBUG
1856  SUBDBG( " -> %s: domain=%d\n", __func__, domain );
1857 #endif
1858 
1859  return domain;
1860 }
1861 
1862 void
1863 __cpc_error_handler( const char *fn, int subcode, const char *fmt, va_list ap )
1864 {
1865 #ifdef DEBUG
1866  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1867  __LINE__ );
1868 #endif
1869 
1870  /* From the libcpc manpages */
1871  fprintf( stderr, "ERROR - libcpc error handler in %s() called!\n", fn );
1872  vfprintf( stderr, fmt, ap );
1873 
1874 #ifdef DEBUG
1875  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1876  __LINE__ );
1877 #endif
1878 }
1879 
1880 static inline int
1882 {
1883 #ifdef DEBUG
1884  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1885  __LINE__ );
1886 #endif
1887 
1888  if ( position >= MAX_COUNTERS ) {
1889 #ifdef DEBUG
1890  SUBDBG( " -> %s: Position of the counter does not exist\n", __func__ );
1891 #endif
1892 
1893  return PAPI_EINVAL;
1894  }
1895 
1896  ctrl->flags[position] = ctrl->flags[position] | CPC_OVF_NOTIFY_EMT;
1897 
1898 #ifdef DEBUG
1899  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1900  __LINE__ );
1901 #endif
1902 
1903  return __cpc_recreate_set( ctrl );
1904 }
1905 
1906 void
1907 __cpc_walk_events_pic_action_count( void *arg, uint_t picno, const char *event )
1908 {
1909 #ifdef DEBUG
1910  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1911  __LINE__ );
1912 #endif
1913 
1914  __t2_store.pic_ntv_count[picno]++;
1915 
1916 #ifdef DEBUG
1917  SUBDBG
1918  ( " -> %s: Found one native event on PIC#%d (now totally %d events)\n",
1919  __func__, picno, __t2_store.pic_ntv_count[picno] );
1920 #endif
1921 
1922 #ifdef DEBUG
1923  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1924  __LINE__ );
1925 #endif
1926 }
1927 
1928 void
1929 __cpc_walk_events_pic_action_store( void *arg, uint_t picno, const char *event )
1930 {
1931  int *tmp = ( int * ) arg;
1932 
1933 #ifdef DEBUG
1934  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1935  __LINE__ );
1936 #endif
1937 
1938  __t2_ntv_events[*tmp] = papi_strdup( event );
1939 
1940 #ifdef DEBUG
1941  SUBDBG( " -> %s: Native event >>%s<< registered\n",
1942  __func__, __t2_ntv_events[*tmp] );
1943 #endif
1944 
1945  *tmp = *tmp + 1;
1946 
1947 #ifdef DEBUG
1948  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1949  __LINE__ );
1950 #endif
1951 }
1952 
1953 static inline int
1955 {
1956  processor_info_t pinfo;
1957 
1958 #ifdef DEBUG
1959  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1960  __LINE__ );
1961 #endif
1962 
1963  // Fetch information from the first processor in the system
1964  if ( processor_info( getcpuid( ), &pinfo ) == 0 ) {
1965 
1966 #ifdef DEBUG
1967  SUBDBG( " -> %s: Clock at %d MHz\n", __func__, pinfo.pi_clock );
1968 #endif
1969 
1970  return pinfo.pi_clock;
1971  }
1972 #ifdef DEBUG
1973  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
1974  __LINE__ );
1975 #endif
1976 
1977  return PAPI_ESYS;
1978 }
1979 
1980 /* This function either increases the ns supplied to itimer_res_ns or pads it up
1981  * to a multiple of itimer_res_ns if the value is bigger than itimer_res_ns.
1982  *
1983  * The source is taken from the old component.
1984  */
1985 static inline int
1987 {
1988  if ( ns < _papi_os_info.itimer_res_ns ) {
1990  } else {
1991  int leftover_ns = ns % _papi_os_info.itimer_res_ns;
1992  return ns + leftover_ns;
1993  }
1994 }
1995 
1996 static inline lwpstatus_t *
1997 __sol_get_lwp_status( const pid_t pid, const lwpid_t lwpid )
1998 {
1999  char *pattern = "/proc/%d/lwp/%d/lwpstatus";
2000  char filename[PAPI_MIN_STR_LEN];
2001  int fd;
2002  static lwpstatus_t lwp;
2003 
2004 #ifdef DEBUG
2005  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2006  __LINE__ );
2007 #endif
2008 
2009  memset( &lwp, 0, sizeof ( lwp ) );
2010  snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid, lwpid );
2011 
2012  fd = open( filename, O_RDONLY );
2013  if ( fd == -1 )
2014  return NULL;
2015 
2016  read( fd, ( void * ) &lwp, sizeof ( lwp ) );
2017 
2018  close( fd );
2019 
2020 #ifdef DEBUG
2021  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2022  __LINE__ );
2023 #endif
2024 
2025  return &lwp;
2026 }
2027 
2028 static inline psinfo_t *
2029 __sol_get_proc_info( const pid_t pid )
2030 {
2031  char *pattern = "/proc/%d/psinfo";
2032  char filename[PAPI_MIN_STR_LEN];
2033  int fd;
2034  static psinfo_t proc;
2035 
2036 #ifdef DEBUG
2037  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2038  __LINE__ );
2039 #endif
2040 
2041  memset( &proc, 0, sizeof ( proc ) );
2042  snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid );
2043 
2044  fd = open( filename, O_RDONLY );
2045  if ( fd == -1 )
2046  return NULL;
2047 
2048  read( fd, ( void * ) &proc, sizeof ( proc ) );
2049 
2050  close( fd );
2051 
2052 #ifdef DEBUG
2053  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2054  __LINE__ );
2055 #endif
2056 
2057  return &proc;
2058 }
2059 
2060 static inline pstatus_t *
2062 {
2063  char *pattern = "/proc/%d/status";
2064  char filename[PAPI_MIN_STR_LEN];
2065  int fd;
2066  static pstatus_t proc;
2067 
2068 #ifdef DEBUG
2069  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2070  __LINE__ );
2071 #endif
2072 
2073  memset( &proc, 0, sizeof ( proc ) );
2074  snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid );
2075 
2076  fd = open( filename, O_RDONLY );
2077  if ( fd == -1 )
2078  return NULL;
2079 
2080  read( fd, ( void * ) &proc, sizeof ( proc ) );
2081 
2082  close( fd );
2083 
2084 #ifdef DEBUG
2085  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2086  __LINE__ );
2087 #endif
2088 
2089  return &proc;
2090 }
2091 
2092 /* This function handles synthetic events and returns their result. Synthetic
2093  * events are events retrieved from outside of libcpc, e.g. all events which
2094  * can not be retrieved using cpc_set_add_request/cpc_buf_get. */
2095 
2096 #ifdef SYNTHETIC_EVENTS_SUPPORTED
2097 
2098 uint64_t
2099 __int_get_synthetic_event( int code, hwd_control_state_t * ctrl, void *arg )
2100 {
2101 #ifdef DEBUG
2102  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2103  __LINE__ );
2104 #endif
2105 
2106  switch ( code ) {
2108  /* Return the count of ticks this set was bound. If a reset of the set
2109  has been executed the last count will be subtracted. */
2110  {
2111  int *i = ( int * ) arg;
2112  return cpc_buf_tick( cpc,
2113  ctrl->counter_buffer ) - ctrl->syn_hangover[*i];
2114  }
2115  case SYNTHETIC_RETURN_ONE:
2116  // The name says it - only for testing purposes.
2117 #ifdef DEBUG
2118  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2119  __LINE__ );
2120 #endif
2121  return 1;
2122  case SYNTHETIC_RETURN_TWO:
2123  // The name says it - only for testing purposes.
2124 #ifdef DEBUG
2125  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2126  __LINE__ );
2127 #endif
2128  return 2;
2129  default:
2130 
2131 #ifdef DEBUG
2132  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2133  __LINE__ );
2134 #endif
2135  return PAPI_EINVAL;
2136  }
2137 }
2138 #endif
2139 
2140 #ifdef SYNTHETIC_EVENTS_SUPPORTED
2141 
2142 int
2143 __int_setup_synthetic_event( int code, hwd_control_state_t * ctrl, void *arg )
2144 {
2145 #ifdef DEBUG
2146  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2147  __LINE__ );
2148 #endif
2149 
2150  switch ( code ) {
2152 
2153 #ifdef DEBUG
2154  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2155  __LINE__ );
2156 #endif
2157  return PAPI_OK;
2158  default:
2159 
2160 #ifdef DEBUG
2161  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2162  __LINE__ );
2163 #endif
2164  return PAPI_EINVAL;
2165  }
2166 #ifdef DEBUG
2167  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2168  __LINE__ );
2169 #endif
2170 }
2171 #endif
2172 
2173 #ifdef SYNTHETIC_EVENTS_SUPPORTED
2174 
2175 void
2177 {
2178  int i = 0;
2179 
2180 #ifdef DEBUG
2181  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2182  __LINE__ );
2183 #endif
2184 
2185  /* Count all synthetic events in __int_syn_table, the last event is marked
2186  with an event code of -1. */
2187  while ( __int_syn_table[i].code != -1 ) {
2188  __t2_store.syn_evt_count++;
2189  i++;
2190  }
2191 
2192 #ifdef DEBUG
2193  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2194  __LINE__ );
2195 #endif
2196 }
2197 #endif
2198 
2199 #ifdef SYNTHETIC_EVENTS_SUPPORTED
2200 
2201 void
2203 {
2204  /* The first index of a synthetic event starts after last native event */
2205  int i = 0;
2206  int offset = _niagara2_vector.cmp_info.num_native_events + 1 -
2207  __t2_store.syn_evt_count;
2208 
2209 #ifdef DEBUG
2210  SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2211  __LINE__ );
2212 #endif
2213 
2214  while ( i < __t2_store.syn_evt_count ) {
2215  __t2_ntv_events[i + offset] = papi_strdup( __int_syn_table[i].name );
2216  i++;
2217  }
2218 
2219 #ifdef DEBUG
2220  SUBDBG( "LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
2221  __LINE__ );
2222 #endif
2223 }
2224 #endif
2225 
2226 
2227 papi_vector_t _niagara2_vector = {
2228 /************* COMPONENT CAPABILITIES/INFORMATION/ETC ************************/
2229  .cmp_info = {
2230  .name = "solaris-niagara2",
2231  .description = "Solaris Counters",
2232  .num_cntrs = MAX_COUNTERS,
2233  .num_mpx_cntrs = MAX_COUNTERS,
2234  .default_domain = PAPI_DOM_USER,
2235  .available_domains = ( PAPI_DOM_USER | PAPI_DOM_KERNEL
2236  | PAPI_DOM_SUPERVISOR ),
2237  .default_granularity = PAPI_GRN_THR,
2238  .available_granularities = PAPI_GRN_THR,
2239  .fast_real_timer = 1,
2240  .fast_virtual_timer = 1,
2241  .attach = 1,
2242  .attach_must_ptrace = 1,
2243  .hardware_intr = 1,
2244  .hardware_intr_sig = SIGEMT,
2245  .precise_intr = 1,
2246  }
2247  ,
2248 /************* COMPONENT DATA STRUCTURE SIZES ********************************/
2249  .size = {
2250  .context = sizeof ( hwd_context_t ),
2251  .control_state = sizeof ( hwd_control_state_t ),
2252  .reg_value = sizeof ( hwd_register_t ),
2253  .reg_alloc = sizeof ( niagara2_reg_alloc_t ),
2254  }
2255  ,
2256 /************* COMPONENT INTERFACE FUNCTIONS *********************************/
2257  .init_control_state = _niagara2_init_control_state,
2258  .start = _niagara2_start,
2259  .stop = _niagara2_stop,
2260  .read = _niagara2_read,
2261  .write = NULL, /* NOT IMPLEMENTED */
2262  .shutdown_thread = _niagara2_shutdown,
2263  .shutdown_component = _niagara2_shutdown_global,
2264  .ctl = _niagara2_ctl,
2265  .update_control_state = _niagara2_update_control_state,
2266  .set_domain = _niagara2_set_domain,
2267  .reset = _niagara2_reset,
2268  .set_overflow = _niagara2_set_overflow,
2269  .set_profile = _niagara2_set_profile,
2270  .stop_profiling = NULL, /* NOT IMPLEMENTED */
2271  .ntv_enum_events = _niagara2_ntv_enum_events,
2272  .ntv_name_to_code = NULL, /* NOT IMPLEMENTED */
2273  .ntv_code_to_name = _niagara2_ntv_code_to_name,
2274  .ntv_code_to_descr = _niagara2_ntv_code_to_descr,
2275  .ntv_code_to_bits = _niagara2_ntv_code_to_bits,
2276  .init_component = _niagara2_init_component,
2277  .dispatch_timer = _niagara2_dispatch_timer,
2278 };
2279 
2282  .get_dmem_info = _solaris_get_dmem_info,
2283 
2284  .get_real_usec = _solaris_get_real_usec,
2285  .get_real_cycles = _solaris_get_real_cycles,
2286  .get_virt_usec = _solaris_get_virt_usec,
2287  .update_shlib_info = _solaris_update_shlib_info,
2288  .get_system_info = _solaris_get_system_info,
2289 };
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:23
char name[PAPI_HUGE_STR_LEN]
Definition: papi.h:691
#define PAPI_TLB_TL
Definition: fpapi.h:157
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:625
int _niagara2_get_memory_info(PAPI_hw_info_t *hw, int id)
#define PAPI_HUGE_STR_LEN
Definition: fpapi.h:42
ssize_t read(int fd, void *buf, size_t count)
Definition: appio.c:225
memset(eventId, 0, size)
#define PAPI_TLB_IM
Definition: fpapi.h:156
#define PAPI_NATIVE_MASK
#define DERIVED_SUB
Definition: papi_internal.h:74
int errno
#define PAPI_LD_INS
Definition: fpapi.h:188
int close(int fd)
Definition: appio.c:175
static int __cpc_search_ntv_event(char *event_name, int *event_code)
int _solaris_update_shlib_info(papi_mdi_t *mdi)
#define PAPI_EVENTS_IN_DERIVED_EVENT
Definition: genpapifdef.c:39
_etext
long long _solaris_get_virt_usec(void)
#define PAPI_L2_TCW
Definition: fpapi.h:230
long long _solaris_get_real_cycles(void)
long long flags
Definition: iozone.c:12330
#define PAPI_DEF_ITIMER_NS
Definition: papi.h:453
#define PAPI_NULL
Definition: fpapi.h:13
static int __cpc_build_ntv_table(void)
UTILITY FUNCTIONS FOR ACCESS TO LIBCPC AND SOLARIS /////////////////////////.
#define papi_free(a)
Definition: papi_memory.h:35
#define PAPI_L1_ICM
Definition: fpapi.h:136
unsigned int event_code
Definition: papi_preset.h:14
static psinfo_t * __sol_get_proc_info(const pid_t pid)
caddr_t text_end
Definition: papi.h:693
static void _niagara2_lock_init(void)
#define PAPI_RES_STL
Definition: fpapi.h:192
static __int_syn_table_t __int_syn_table[]
int _niagara2_read(hwd_context_t *ctx, hwd_control_state_t *ctrl, long_long **events, int flags)
#define PAPI_MIN_STR_LEN
Definition: fpapi.h:41
void __cpc_error_handler(const char *fn, int subcode, const char *fmt, va_list ap)
#define EVENT_NOT_SET
int default_granularity
Definition: papi.h:641
#define PAPI_L1_TCM
Definition: fpapi.h:141
#define PAPI_ENOEVNT
Definition: fpapi.h:112
#define PAPI_TOT_INS
Definition: fpapi.h:185
hwi_search_t * preset_table
int ns
Definition: iozone.c:20358
off64_t offset
Definition: iozone.c:1279
off_t lseek(int fd, off_t offset, int whence)
Definition: appio.c:210
#define __CHECK_ERR_DFLT(retval)
int fd
Definition: iozone.c:1291
static cpc_t * cpc
#define MAX_COUNTERS
Definition: perfctr-x86.h:8
device[deviceId] domain[domainId] event
Definition: linux-cuda.c:306
void __cpc_walk_events_pic_action_count(void *arg, uint_t picno, const char *event)
#define PAPI_TLB_DM
Definition: fpapi.h:155
enum @8 __int_synthetic_enum
return PAPI_OK
Definition: linux-nvml.c:458
int count
Definition: iozone.c:22422
int _niagara2_stop(hwd_context_t *ctx, hwd_control_state_t *ctrl)
#define papi_strdup(a)
Definition: papi_memory.h:39
char filename[MAXNAMESIZE]
Definition: iozone.c:1360
#define PAPI_LST_INS
Definition: fpapi.h:195
#define DERIVED_ADD
Definition: papi_internal.h:70
PAPI_exe_info_t exe_info
int _niagara2_init_component(int cidx)
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
return PAPI_EINVAL
Definition: linux-nvml.c:408
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
int _niagara2_update_shlib_info(papi_mdi_t *mdi)
static lwpstatus_t * __sol_get_lwp_status(const pid_t pid, const lwpid_t lwpid)
#define printf
Definition: papi_test.h:125
int _niagara2_update_control_state(hwd_control_state_t *ctrl, NativeInfo_t *native, int count, hwd_context_t *ctx)
#define PAPI_OVERFLOWING
Definition: fpapi.h:33
_end
PAPI_shlib_info_t shlib_info
Return codes and api definitions.
#define PAPI_MAX_LOCK
Definition: papi_lock.h:18
int niagara2_reg_alloc_t
#define PAPI_BR_INS
Definition: fpapi.h:190
_papi_int_itimer_t itimer
void __int_walk_synthetic_events_action_count(void)
int _niagara2_shutdown(hwd_context_t *ctx)
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:184
papi_os_vector_t _papi_os_vector
Definition: aix.c:1288
int _papi_hwi_setup_all_presets(hwi_search_t *findem, int cidx)
Definition: papi_preset.c:37
int i
Definition: fileop.c:140
#define PAPI_ENOSUPP
Definition: fpapi.h:123
EventSetOverflowInfo_t overflow
int _niagara2_ntv_code_to_bits(unsigned int EventCode, hwd_register_t *bits)
long long _solaris_get_real_usec(void)
#define PAPI_SYC_INS
Definition: fpapi.h:196
#define PAPI_TOT_CYC
Definition: fpapi.h:194
_edata
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
int _niagara2_ntv_code_to_descr(unsigned int EventCode, char *ntv_descr, int len)
#define PAPI_SR_INS
Definition: fpapi.h:189
struct _ThreadInfo * master
int _niagara2_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
static __t2_store_t __t2_store
int _niagara2_set_overflow(EventSetInfo_t *ESI, int EventIndex, int threshold)
#define PAPI_DOM_SUPERVISOR
Definition: fpapi.h:24
int _niagara2_set_domain(hwd_control_state_t *ctrl, int domain)
PAPI HWD LAYER RELATED FUNCTIONS ///////////////////////////////////////////.
static pstatus_t * __sol_get_proc_status(const pid_t pid)
#define __CHECK_ERR_NEGV(retval)
static int pid
#define __CHECK_ERR_NULL(retval)
static int __cpc_build_pst_table(void)
#define NOT_DERIVED
Definition: papi_internal.h:69
#define PAPI_BR_PRC
Definition: fpapi.h:182
char *long long size
Definition: iozone.c:12023
#define __CHECK_ERR_PAPI(retval)
static int cidx
Definition: event_info.c:40
caddr_t text_start
Definition: papi.h:692
#define hwd_context_t
#define PAPI_ECMP
Definition: fpapi.h:109
PAPI_address_map_t address_info
Definition: papi.h:704
static int __cpc_domain_translator(const int papi_domain)
#define PAPI_BR_CN
Definition: fpapi.h:178
static int native
Definition: event_info.c:39
static int __cpc_recreate_set(hwd_control_state_t *ctrl)
get the executable&#39;s address space info
Definition: papi.h:690
void * thread(void *arg)
Definition: kufrin.c:31
int native[PAPI_EVENTS_IN_DERIVED_EVENT]
Definition: papi_preset.h:16
#define PAPI_DEFDOM
Definition: fpapi.h:49
#define NOT_A_PAPI_HWD_READ
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
_papi_int_granularity_t granularity
static void * _niagara2_get_overflow_address(void *context)
static char ** __t2_ntv_events
int _papi_hwi_start_signal(int signal, int need_context, int cidx)
Definition: extras.c:401
void _niagara2_dispatch_timer(int signal, siginfo_t *si, void *info)
caddr_t _start
int __int_setup_synthetic_event(int, hwd_control_state_t *, void *)
#define PAPI_DOMAIN
Definition: fpapi.h:50
char events[MAX_EVENTS][BUFSIZ]
static int __sol_get_processor_clock(void)
int _niagara2_set_profile(EventSetInfo_t *ESI, int EventIndex, int threshold)
#define PAPI_BR_MSP
Definition: fpapi.h:181
#define PAPI_DEFGRN
Definition: fpapi.h:51
char operation[PAPI_2MAX_STR_LEN]
Definition: papi_preset.h:17
int _papi_hwi_stop_signal(int signal)
Definition: extras.c:441
#define PAPI_FP_INS
Definition: fpapi.h:187
#define PAPI_GRANUL
Definition: fpapi.h:52
int _niagara2_shutdown_global(void)
#define PAPI_DEF_MPX_NS
Definition: fpapi.h:53
atomic_p lock[]
Definition: aix.c:25
static __t2_pst_table_t __t2_table[]
#define PAPI_ESYS
Definition: fpapi.h:108
#define PAPI_BR_TKN
Definition: fpapi.h:179
int threshold
char vendor_string[PAPI_MAX_STR_LEN]
Definition: papi.h:783
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:57
PAPI_hw_info_t hw_info
again struct sockaddr sizeof(struct sockaddr_in))
caddr_t data_start
Definition: papi.h:694
int _niagara2_reset(hwd_context_t *ctx, hwd_control_state_t *ctrl)
#define PAPI_L1_DCM
Definition: fpapi.h:135
#define PAPI_DEF_ITIMER
Definition: papi.h:452
EventSetInfo_t ** running_eventset
Definition: threads.h:30
int _solaris_get_system_info(papi_mdi_t *mdi)
char * name
Definition: iozone.c:23648
static int total
Definition: rapl_overflow.c:5
void __cpc_walk_events_pic_action_store(void *arg, uint_t picno, const char *event)
PAPI_address_map_t * map
Definition: papi.h:709
static int __cpc_enable_sigemt(hwd_control_state_t *ctrl, int position)
#define DEFAULT_CNTR_PRESET
int _niagara2_start(hwd_context_t *ctx, hwd_control_state_t *ctrl)
int cpu_max_mhz
Definition: papi.h:791
#define long_long
Definition: papi.h:549
inline_static ThreadInfo_t * _papi_hwi_lookup_thread(int custom_tid)
Definition: threads.h:92
#define PAPI_EBUF
Definition: fpapi.h:125
#define PAPI_NATIVE_AND_MASK
caddr_t data_end
Definition: papi.h:695
papi_vector_t _niagara2_vector
#define PAPI_L1_TCR
Definition: fpapi.h:226
int _niagara2_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len)
int totalcpus
Definition: papi.h:781
_papi_int_domain_t domain
int _niagara2_ntv_enum_events(unsigned int *EventCode, int modifier)
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:785
char fullname[PAPI_HUGE_STR_LEN]
Definition: papi.h:703
int _solaris_get_dmem_info(PAPI_dmem_info_t *d)
static int attach(hwd_control_state_t *ctl, unsigned long tid)
Definition: perfctr.c:242
#define PAPI_L2_ICM
Definition: fpapi.h:138
static int __sol_get_itimer_ns(int ns)
int _niagara2_init_control_state(hwd_control_state_t *ctrl)
#define PAPI_DOM_USER
Definition: fpapi.h:21
int _papi_hwi_dispatch_overflow_signal(void *papiContext, caddr_t address, int *isHardware, long long overflow_bit, int genOverflowBit, ThreadInfo_t **t, int cidx)
Definition: extras.c:214
hwd_control_state_t * ctl_state
long j
Definition: iozone.c:19135
#define PAPI_L2_ICR
Definition: fpapi.h:215
uint64_t __int_get_synthetic_event(int, hwd_control_state_t *, void *)
ssize_t retval
Definition: libasync.c:338
long long tmp
Definition: iozone.c:12031
int(* get_memory_info)(PAPI_hw_info_t *, int)
Definition: papi_vector.h:69
#define PAPI_L2_LDM
Definition: fpapi.h:160
void __int_walk_synthetic_events_action_store(void)
#define CPC_COUNTING_DOMAINS
#define hwd_register_t
#define PAPI_GRN_THR
Definition: fpapi.h:67
signal(SIGINT, signal_handler)
if(gettimeofday(&tp,(struct timezone *) NULL)==-1) perror("gettimeofday")
#define papi_calloc(a, b)
Definition: papi_memory.h:37
unsigned int pattern
Definition: iozone.c:1531