PAPI 7.1.0.0
Loading...
Searching...
No Matches
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
70
71/* Synthetic events */
73uint64_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
97static cpc_t *cpc = NULL;
98
99typedef struct __t2_store
100{
101 // Number of counters for a processing unit
102 int npic;
106
108static char **__t2_ntv_events;
109
110// Variables copied from the old component
111static int pid;
112
113// Data types for utility functions
114
115typedef struct __sol_processor_information
116{
117 int total;
118 int clock;
120
121typedef struct __t2_pst_table
122{
124 char *ntv_event[MAX_COUNTERS];
128
129#define SYNTHETIC_EVENTS_SUPPORTED 1
130
131/* This table structure holds all preset events */
133 /* Presets defined by generic_events(3CPC) */
135 {"DC_miss", NULL}, 1, NOT_DERIVED},
137 {"IC_miss", NULL}, 1, NOT_DERIVED},
139 {"L2_imiss", NULL}, 1, NOT_DERIVED},
141 {"DTLB_miss", NULL}, 1, NOT_DERIVED},
143 {"ITLB_miss", NULL}, 1, NOT_DERIVED},
145 {"TLB_miss", NULL}, 1, NOT_DERIVED},
147 {"L2_dmiss_ld", NULL}, 1, NOT_DERIVED},
149 {"Br_taken", NULL}, 1, NOT_DERIVED},
151 {"Instr_cnt", NULL}, 1, NOT_DERIVED},
153 {"Instr_ld", NULL}, 1, NOT_DERIVED},
155 {"Instr_st", NULL}, 1, NOT_DERIVED},
157 {"Br_completed", NULL}, 1, NOT_DERIVED},
158 /* Presets additionally found, should be checked twice */
160 {"Br_taken", NULL}, 1, NOT_DERIVED},
162 {"Instr_FGU_arithmetic", NULL}, 1, NOT_DERIVED},
164 {"Idle_strands", NULL}, 1, NOT_DERIVED},
166 {"Atomics", NULL}, 1, NOT_DERIVED},
168 {"CPU_ifetch_to_PCX", NULL}, 1, NOT_DERIVED},
170 {"CPU_ld_to_PCX", NULL}, 1, NOT_DERIVED},
172 {"CPU_st_to_PCX", NULL}, 1, NOT_DERIVED},
173 /* Derived presets found, should be checked twice */
175 {"IC_miss", "DC_miss"}, 2, DERIVED_ADD},
176 {PAPI_BR_CN,
177 {"Br_completed", "Br_taken"}, 2, DERIVED_ADD},
179 {"Br_completed", "Br_taken"}, 2, DERIVED_SUB},
181 {"Instr_st", "Instr_ld"}, 2, DERIVED_ADD},
182#ifdef SYNTHETIC_EVENTS_SUPPORTED
183 /* This preset does exist in order to support multiplexing */
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
194enum
195{
200#endif
201
202#ifdef SYNTHETIC_EVENTS_SUPPORTED
203typedef 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
230int
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
274int
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
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
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
404void
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
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 */
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;
544 ( info ), &hw, overflow_vector,
545 1, &thread, ESI->CmpIdx );
546 } else {
547 /* This is a software overflow */
548 hw = 0;
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
562static 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
581int
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
653int
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
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",
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
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
729static 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
746int
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 &&
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
771int
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
783int
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 &&
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
821int
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
867int
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
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
949int
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
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
989int
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
1002int
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
1086int
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
1105int
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
1117 // papi_calloc in __cpc_build_ntv_table
1119 // papi_calloc in __cpc_build_pst_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
1135int
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
1192int
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
1210int
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@%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 -
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
1328int
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 vptr_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 =
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 = ( vptr_t ) mapping.pr_vaddr;
1437 cur->data_end =
1438 ( vptr_t ) ( mapping.pr_vaddr + mapping.pr_size );
1439
1440 if ( strcmp
1441 ( cur->name,
1444 cur->data_start;
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 = ( vptr_t ) mapping.pr_vaddr;
1463 cur->text_end =
1464 ( vptr_t ) ( mapping.pr_vaddr + mapping.pr_size );
1465
1466 if ( strcmp
1467 ( cur->name,
1470 cur->text_start;
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__,
1514 SUBDBG( " -> %s: data_start=%#x, data_end=%#x, data_size=%lld\n", __func__,
1519#endif
1520
1521 /* Store the map read and the total count of shlibs found */
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
1544static 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 ) );
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__,
1567#endif
1568 }
1569
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
1597#endif
1598
1599 /* Store the count of events available in central data structure */
1600#ifndef SYNTHETIC_EVENTS_SUPPORTED
1602#else
1605#endif
1606
1607
1608 /* Allocate memory for storing all events found, including the first empty
1609 slot */
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
1640static 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
1655static inline int
1657{
1658 int num_psts, i, j, event_code, pst_events;
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 ) );
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
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
1747static inline int
1749{
1750#ifdef SYNTHETIC_EVENTS_SUPPORTED
1751 const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
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
1821static 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
1862void
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
1880static 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
1906void
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
1928void
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
1953static 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 */
1985static 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
1996static 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
2028static inline psinfo_t *
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
2060static 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
2098uint64_t
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 }
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;
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
2142int
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
2175void
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 ) {
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
2201void
2203{
2204 /* The first index of a synthetic event starts after last native event */
2205 int i = 0;
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 ) {
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
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
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};
double tmp
int i
atomic_p lock[]
Definition: aix.c:25
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:188
off_t lseek(int fd, off_t offset, int whence)
Definition: appio.c:214
int close(int fd)
Definition: appio.c:179
int errno
ssize_t read(int fd, void *buf, size_t count)
Definition: appio.c:229
static long count
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
int _papi_hwi_start_signal(int signal, int need_context, int cidx)
Definition: extras.c:403
int _papi_hwi_stop_signal(int signal)
Definition: extras.c:443
int _papi_hwi_dispatch_overflow_signal(void *papiContext, vptr_t address, int *isHardware, long long overflow_bit, int genOverflowBit, ThreadInfo_t **t, int cidx)
Definition: extras.c:216
#define PAPI_L1_TCR
Definition: f90papi.h:285
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_L2_ICR
Definition: f90papi.h:351
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_MIN_STR_LEN
Definition: f90papi.h:208
#define PAPI_NULL
Definition: f90papi.h:78
#define PAPI_TLB_IM
Definition: f90papi.h:368
#define PAPI_DEFGRN
Definition: f90papi.h:26
#define PAPI_BR_CN
Definition: f90papi.h:304
#define PAPI_GRANUL
Definition: f90papi.h:179
#define PAPI_LST_INS
Definition: f90papi.h:365
#define PAPI_TOT_CYC
Definition: f90papi.h:308
#define PAPI_L1_DCM
Definition: f90papi.h:364
#define PAPI_BR_MSP
Definition: f90papi.h:337
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_BR_PRC
Definition: f90papi.h:371
#define PAPI_BR_INS
Definition: f90papi.h:300
#define PAPI_DOM_SUPERVISOR
Definition: f90papi.h:109
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_FP_INS
Definition: f90papi.h:366
#define PAPI_SR_INS
Definition: f90papi.h:357
#define PAPI_DOMAIN
Definition: f90papi.h:159
#define PAPI_DEF_MPX_NS
Definition: f90papi.h:235
#define PAPI_SYC_INS
Definition: f90papi.h:313
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_L2_TCW
Definition: f90papi.h:299
#define PAPI_ECMP
Definition: f90papi.h:214
#define PAPI_BR_TKN
Definition: f90papi.h:338
#define PAPI_TLB_DM
Definition: f90papi.h:294
#define PAPI_TOT_INS
Definition: f90papi.h:317
#define PAPI_OVERFLOWING
Definition: f90papi.h:240
#define PAPI_L2_LDM
Definition: f90papi.h:330
#define PAPI_TLB_TL
Definition: f90papi.h:387
#define PAPI_RES_STL
Definition: f90papi.h:310
#define PAPI_EBUF
Definition: f90papi.h:253
#define PAPI_L2_ICM
Definition: f90papi.h:311
#define PAPI_L1_ICM
Definition: f90papi.h:392
#define PAPI_DEFDOM
Definition: f90papi.h:188
#define PAPI_L1_TCM
Definition: f90papi.h:347
#define PAPI_GRN_THR
Definition: f90papi.h:265
#define PAPI_HUGE_STR_LEN
Definition: f90papi.h:120
#define PAPI_LD_INS
Definition: f90papi.h:292
#define PAPI_DEF_ITIMER
Definition: papi.h:462
#define PAPI_DEF_ITIMER_NS
Definition: papi.h:463
char events[MAX_EVENTS][BUFSIZ]
static int threshold
void * thread(void *arg)
Definition: kufrin.c:38
#define PAPI_NATIVE_AND_MASK
#define PAPI_NATIVE_MASK
Return codes and api definitions.
#define long_long
Definition: papi.h:559
void * vptr_t
Definition: papi.h:576
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
__sighandler_t signal(int __sig, __sighandler_t __handler) __attribute__((__nothrow__
int sigaction(int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact) __attribute__((__nothrow__
__gnuc_va_list va_list
FILE * stderr
#define PAPI_EVENTS_IN_DERIVED_EVENT
#define NOT_DERIVED
Definition: papi_internal.h:68
#define DERIVED_SUB
Definition: papi_internal.h:73
#define DERIVED_ADD
Definition: papi_internal.h:69
#define PAPI_MAX_LOCK
Definition: papi_lock.h:18
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_strdup(a)
Definition: papi_memory.h:39
int _papi_hwi_setup_all_presets(hwi_search_t *findem, int cidx)
Definition: papi_preset.c:44
static int native
static int cidx
#define MAX_COUNTERS
Definition: perfctr-x86.h:8
static int attach(hwd_control_state_t *ctl, unsigned long tid)
Definition: perfctr.c:248
const char * fmt
Definition: pscanf.h:10
const char FILE * file
Definition: pscanf.h:13
if(file==NULL) goto out
static int total
Definition: rapl_overflow.c:9
const char * name
Definition: rocs.c:225
int _solaris_update_shlib_info(papi_mdi_t *mdi)
long long _solaris_get_real_usec(void)
int _solaris_get_system_info(papi_mdi_t *mdi)
long long _solaris_get_virt_usec(void)
long long _solaris_get_real_cycles(void)
int _solaris_get_dmem_info(PAPI_dmem_info_t *d)
int _niagara2_get_memory_info(PAPI_hw_info_t *hw, int id)
static pstatus_t * __sol_get_proc_status(const pid_t pid)
int _niagara2_init_component(int cidx)
int __int_setup_synthetic_event(int, hwd_control_state_t *, void *)
static void _niagara2_lock_init(void)
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
int _niagara2_set_overflow(EventSetInfo_t *ESI, int EventIndex, int threshold)
vptr_t _etext
#define __CHECK_ERR_NEGV(retval)
static lwpstatus_t * __sol_get_lwp_status(const pid_t pid, const lwpid_t lwpid)
int _niagara2_init_control_state(hwd_control_state_t *ctrl)
static psinfo_t * __sol_get_proc_info(const pid_t pid)
#define __CHECK_ERR_PAPI(retval)
void _niagara2_dispatch_timer(int signal, siginfo_t *si, void *info)
vptr_t _start
void __cpc_error_handler(const char *fn, int subcode, const char *fmt, va_list ap)
vptr_t _end
int _niagara2_update_control_state(hwd_control_state_t *ctrl, NativeInfo_t *native, int count, hwd_context_t *ctx)
@ SYNTHETIC_CYCLES_ELAPSED
@ SYNTHETIC_RETURN_TWO
@ SYNTHETIC_RETURN_ONE
vptr_t _edata
int _niagara2_ntv_enum_events(unsigned int *EventCode, int modifier)
static int __sol_get_itimer_ns(int ns)
int _niagara2_reset(hwd_context_t *ctx, hwd_control_state_t *ctrl)
static cpc_t * cpc
int _niagara2_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
uint64_t __int_get_synthetic_event(int, hwd_control_state_t *, void *)
int _niagara2_start(hwd_context_t *ctx, hwd_control_state_t *ctrl)
static int __cpc_build_pst_table(void)
void __cpc_walk_events_pic_action_count(void *arg, uint_t picno, const char *event)
static int __cpc_build_ntv_table(void)
UTILITY FUNCTIONS FOR ACCESS TO LIBCPC AND SOLARIS /////////////////////////.
int _niagara2_shutdown(hwd_context_t *ctx)
static int __sol_get_processor_clock(void)
enum @188 __int_synthetic_enum
static char ** __t2_ntv_events
#define hwd_context_t
int _niagara2_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len)
void __int_walk_synthetic_events_action_count(void)
static int __cpc_recreate_set(hwd_control_state_t *ctrl)
int _niagara2_update_shlib_info(papi_mdi_t *mdi)
static void * _niagara2_get_overflow_address(void *context)
static int __cpc_enable_sigemt(hwd_control_state_t *ctrl, int position)
static __t2_pst_table_t __t2_table[]
int _niagara2_ntv_code_to_bits(unsigned int EventCode, hwd_register_t *bits)
void __cpc_walk_events_pic_action_store(void *arg, uint_t picno, const char *event)
papi_vector_t _niagara2_vector
int _niagara2_ntv_code_to_descr(unsigned int EventCode, char *ntv_descr, int len)
hwi_search_t * preset_table
int _niagara2_shutdown_global(void)
void __int_walk_synthetic_events_action_store(void)
int _niagara2_set_profile(EventSetInfo_t *ESI, int EventIndex, int threshold)
papi_os_vector_t _papi_os_vector
static int __cpc_domain_translator(const int papi_domain)
int _niagara2_read(hwd_context_t *ctx, hwd_control_state_t *ctrl, long_long **events, int flags)
int _niagara2_stop(hwd_context_t *ctx, hwd_control_state_t *ctrl)
static __t2_store_t __t2_store
static int __cpc_search_ntv_event(char *event_name, int *event_code)
static __int_syn_table_t __int_syn_table[]
static int pid
int _niagara2_set_domain(hwd_control_state_t *ctrl, int domain)
PAPI HWD LAYER RELATED FUNCTIONS ///////////////////////////////////////////.
#define hwd_register_t
#define __CHECK_ERR_NULL(retval)
#define __CHECK_ERR_DFLT(retval)
#define NOT_A_PAPI_HWD_READ
#define EVENT_NOT_SET
#define DEFAULT_CNTR_PRESET
#define CPC_COUNTING_DOMAINS
int niagara2_reg_alloc_t
struct _ThreadInfo * master
hwd_control_state_t * ctl_state
EventSetOverflowInfo_t overflow
get the executable's address space info
Definition: papi.h:684
vptr_t text_start
Definition: papi.h:686
char name[PAPI_HUGE_STR_LEN]
Definition: papi.h:685
vptr_t text_end
Definition: papi.h:687
vptr_t data_end
Definition: papi.h:689
vptr_t data_start
Definition: papi.h:688
int default_granularity
Definition: papi.h:644
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char fullname[PAPI_HUGE_STR_LEN]
Definition: papi.h:697
PAPI_address_map_t address_info
Definition: papi.h:698
char vendor_string[PAPI_MAX_STR_LEN]
Definition: papi.h:782
int totalcpus
Definition: papi.h:780
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:784
int cpu_max_mhz
Definition: papi.h:790
PAPI_address_map_t * map
Definition: papi.h:703
gregset_t gregs
PAPI_exe_info_t exe_info
PAPI_hw_info_t hw_info
PAPI_shlib_info_t shlib_info
int(* get_memory_info)(PAPI_hw_info_t *, int)
Definition: papi_vector.h:69
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
mcontext_t uc_mcontext
inline_static ThreadInfo_t * _papi_hwi_lookup_thread(int custom_tid)
Definition: threads.h:97
_papi_int_domain_t domain
_papi_int_granularity_t granularity
_papi_int_itimer_t itimer
int retval
Definition: zero_fork.c:53