PAPI 7.1.0.0
Loading...
Searching...
No Matches
papi_internal.c
Go to the documentation of this file.
1/****************************/
2/* THIS IS OPEN SOURCE CODE */
3/****************************/
4
5/*
6* File: papi_internal.c
7*
8* Author: Philip Mucci
9* mucci@cs.utk.edu
10* Mods: dan terpstra
11* terpstra@cs.utk.edu
12* Mods: Min Zhou
13* min@cs.utk.edu
14* Mods: Kevin London
15* london@cs.utk.edu
16* Mods: Per Ekman
17* pek@pdc.kth.se
18* Mods: Haihang You
19* you@cs.utk.edu
20* Mods: Maynard Johnson
21* maynardj@us.ibm.com
22* Mods: Brian Sheely
23* bsheely@eecs.utk.edu
24* Mods: <Gary Mohr>
25* <gary.mohr@bull.com>
26* Mods: <your name here>
27* <your email address>
28*/
29
30#include <stdarg.h>
31#include <stdio.h>
32#include <errno.h>
33#include <string.h>
34#include <ctype.h>
35#include <assert.h>
36
37#include "papi.h"
38#include "papi_internal.h"
39#include "papi_vector.h"
40#include "papi_memory.h"
41#include "sw_multiplex.h"
42#include "extras.h"
43#include "papi_preset.h"
44#include "cpus.h"
45
46#include "papi_common_strings.h"
47
48/* Advanced definitons */
49static int default_debug_handler( int errorCode );
50static long long handle_derived( EventInfo_t * evi, long long *from );
51
52/* Global definitions used by other files */
61
64
65/*****************************/
66/* Native Event Mapping Code */
67/*****************************/
68
69#define NATIVE_EVENT_CHUNKSIZE 1024
70
72 int cidx;
75 char *evt_name;
76};
77
78
79// The following array is indexed by the papi event code (after the native bit has been removed)
81static int num_native_events=0;
82static int num_native_chunks=0;
83
84char **_papi_errlist= NULL;
85static int num_error_chunks = 0;
86
87
88// pointer to event:mask string associated with last enum call to a components
89// will be NULL for non libpfm4 components
90// this is needed because libpfm4 event codes and papi event codes do not contain mask information
91char *papi_event_string = NULL;
92void
93_papi_hwi_set_papi_event_string (const char *event_string) {
94 INTDBG("event_string: %s\n", event_string);
95 if (papi_event_string != NULL) {
96 free (papi_event_string);
97 papi_event_string = NULL;
98 }
99 if (event_string != NULL) {
100 papi_event_string = strdup(event_string);
101 }
102 return;
103}
104char *
106 INTDBG("papi_event_string: %s\n", papi_event_string);
107 return papi_event_string;
108}
109void
111 if (papi_event_string != NULL) {
112 free(papi_event_string);
113 papi_event_string = NULL;
114 }
115 return;
116}
117
118void
119_papi_hwi_set_papi_event_code (unsigned int event_code, int update_flag) {
120 INTDBG("new event_code: %#x, update_flag: %d, previous event_code: %#x\n", event_code, update_flag, _papi_hwi_my_thread->tls_papi_event_code);
121
122 // if call is just to reset and start over, set both flags to show nothing saved yet
123 if (update_flag < 0) {
126 return;
127 }
128
129 // if 0, it is being set prior to calling a component, if >0 it is being changed by the component
131 // save the event code passed in
133 return;
134}
135unsigned int
137 INTDBG("papi_event_code: %#x\n", _papi_hwi_my_thread->tls_papi_event_code);
139}
140/* Get the index into the ESI->NativeInfoArray for the current PAPI event code */
141int
142_papi_hwi_get_ntv_idx (unsigned int papi_evt_code) {
143 INTDBG("ENTER: papi_evt_code: %#x\n", papi_evt_code);
144
145 int result;
146 int event_index;
147
148 if (papi_evt_code == 0) {
149 INTDBG("EXIT: PAPI_ENOEVNT, invalid papi event code\n");
150 return PAPI_ENOEVNT;
151 }
152
153 event_index=papi_evt_code&PAPI_NATIVE_AND_MASK;
154 if ((event_index<0) || (event_index>=num_native_events)) {
155 INTDBG("EXIT: PAPI_ENOEVNT, invalid index into native event array\n");
156 return PAPI_ENOEVNT;
157 }
158
160
161 INTDBG("EXIT: result: %d\n", result);
162 return result;
163}
164
165//
166// Check for the presence of a component name or pmu name in the event string.
167// If found check if it matches this component or one of the pmu's supported by this component.
168//
169// returns true if the event could be for this component and false if it is not for this component.
170// if there is no component or pmu name then it could be for this component and returns true.
171//
172static int
174 INTDBG("ENTER: cidx: %d, event_name: %s\n", cidx, event_name);
175 int i;
176 int component_name = 0;
177 int pmu_name = 0;
178 char *wptr = NULL;
179
180 // if event does not have a component name or pmu name, return to show it could be supported by this component
181 // when component and pmu names are not provided, we just have to call the components to see if they recognize the event
182 //
183
184 // look for component names first
185 if ((wptr = strstr(event_name, ":::")) != NULL) {
186 component_name = 1;
187 } else if ((wptr = strstr(event_name, "::")) != NULL) {
188 pmu_name = 1;
189 } else {
190 INTDBG("EXIT: No Component or PMU name in event string, try this component\n");
191 // need to force all components to be called to find owner of this event
192 // ???? can we assume the default pmu when no component or pmu name is provided ????
193 return 1;
194 }
195
196 // get a temporary copy of the component or pmu name
197 int name_len = wptr - event_name;
198 wptr = strdup(event_name);
199 wptr[name_len] = '\0';
200
201 // if a component name was found, compare it to the component name in the component info structure
202 if (component_name) {
203// INTDBG("component_name: %s\n", _papi_hwd[cidx]->cmp_info.name);
204 if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.name) == 0) {
205 free (wptr);
206 INTDBG("EXIT: Component %s supports this event\n", _papi_hwd[cidx]->cmp_info.name);
207 return 1;
208 }
209 }
210
211 // if a pmu name was found, compare it to the pmu name list if the component info structure (if there is one)
212 if (pmu_name) {
213 for ( i=0 ; i<PAPI_PMU_MAX ; i++) {
214 if (_papi_hwd[cidx]->cmp_info.pmu_names[i] == NULL) {
215 continue;
216 }
217// INTDBG("pmu_name[%d]: %p (%s)\n", i, _papi_hwd[cidx]->cmp_info.pmu_names[i], _papi_hwd[cidx]->cmp_info.pmu_names[i]);
218 if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.pmu_names[i]) == 0) {
219 INTDBG("EXIT: Component %s supports PMU %s and this event\n", _papi_hwd[cidx]->cmp_info.name, wptr);
220 free (wptr);
221 return 1;
222 }
223 }
224 }
225
226 free (wptr);
227 INTDBG("EXIT: Component does not support this event\n");
228 return 0;
229}
230
243int
244_papi_hwi_prefix_component_name( char *component_name, char *event_name, char *out, int out_len)
245{
246 int size1, size2;
247 char temp[out_len];
248
249 size1 = strlen(event_name);
250 size2 = strlen(component_name);
251
252/* sanity checks */
253 if ( size1 == 0 ) {
254 return (PAPI_EBUG); /* hopefully event_name always has length?! */
255 }
256
257 if ( size1 >= out_len )
258 return (PAPI_ENOMEM);
259
260/* Guard against event_name == out */
261 memcpy( temp, event_name, out_len );
262
263/* no component name to prefix */
264 if ( size2 == 0 ) {
265 sprintf(out, "%s%c", temp, '\0' );
266 return (PAPI_OK);
267 }
268
269/* Don't prefix 'cpu' component names for now */
270 if ( strstr(component_name, "pe") ||
271 strstr(component_name, "bgq") ||
272 strstr(component_name, "bgp") ) {
273 sprintf( out, "%s%c", temp, '\0');
274 return (PAPI_OK);
275 }
276
277/* strlen(component_name) + ::: + strlen(event_name) + NULL */
278 if ( size1+size2+3+1 > out_len )
279 return (PAPI_ENOMEM);
280
281 sprintf( out, "%s:::%s%c" , component_name, temp, '\0');
282 return (PAPI_OK);
283}
284
296{
297 const char *start = NULL;
298/* We assume ::: is the seperator
299 * eg:
300 * papi_component:::event_name
301 */
302
303 start = strstr( event_name, ":::" );
304 if ( start != NULL )
305 start+= 3; /* return the actual start of event_name */
306 else
308
309 return (start);
310}
311
312/* find the papi event code (4000xxx) associated with the specified component, native event, and event name */
313static int
314_papi_hwi_find_native_event(int cidx, int event, const char *event_name) {
315 INTDBG("ENTER: cidx: %x, event: %#x, event_name: %s\n", cidx, event, event_name);
316
317 int i;
318
319 // if no event name passed in, it can not be found
320 if (event_name == NULL) {
321 INTDBG("EXIT: PAPI_ENOEVNT\n");
322 return PAPI_ENOEVNT;
323 }
324
325 for(i=0;i<num_native_events;i++) {
326 // if we have have not set up this event name yet, look at next
327 if (_papi_native_events[i].evt_name == NULL) {
328 continue;
329 }
330
331 // is this entry for the correct component and event code
332 if ((_papi_native_events[i].cidx==cidx) &&
334 // if this event name matches what we want, return its papi event code
335 if (strcmp(event_name, _papi_native_events[i].evt_name) == 0) {
336 INTDBG("EXIT: event: %#x, component_event: %#x, ntv_idx: %d, event_name: %s\n",
338 return i|PAPI_NATIVE_MASK;
339 }
340 }
341 }
342
343 INTDBG("EXIT: PAPI_ENOEVNT\n");
344 return PAPI_ENOEVNT;
345}
346
347static int
348_papi_hwi_add_native_event(int cidx, int ntv_event, int ntv_idx, const char *event_name) {
349 INTDBG("ENTER: cidx: %d, ntv_event: %#x, ntv_idx: %d, event_name: %s\n", cidx, ntv_event, ntv_idx, event_name);
350
351 int new_native_event;
352
354
359 sizeof(struct native_event_info));
360 if (_papi_native_events==NULL) {
361 new_native_event=PAPI_ENOMEM;
362 goto native_alloc_early_out;
363 }
364 }
365
369 if (event_name != NULL) {
371 } else {
373 }
374 new_native_event=num_native_events|PAPI_NATIVE_MASK;
375
377
378native_alloc_early_out:
379
381
382 INTDBG("EXIT: new_native_event: %#x, num_native_events: %d\n", new_native_event, num_native_events);
383 return new_native_event;
384}
385
392static int
394{
395 INTDBG("Adding a new Error message |%s|\n", error);
397
400 _papi_errlist= (char **) realloc(_papi_errlist,
402 if (_papi_errlist==NULL) {
404 goto bail;
405 }
406
407 }
408
409 _papi_errlist[_papi_hwi_num_errors] = strdup( error );
410 if ( _papi_errlist[_papi_hwi_num_errors] == NULL )
412
413bail:
415
416 return _papi_hwi_num_errors++;
417}
418
419static void
421{
422 int i;
423
424 if ( _papi_errlist == NULL ||
426 return;
427
428
430 for (i=0; i < _papi_hwi_num_errors; i++ ) {
431 free( _papi_errlist[i]);
432 _papi_errlist[i] = NULL;
433 }
434
435 free( _papi_errlist );
436 _papi_errlist = NULL;
439
441}
442
443static int
445{
446 int i;
447
448 for (i=0; i<_papi_hwi_num_errors; i++) {
449 if ( !strncasecmp( _papi_errlist[i], error, strlen( error ) ) )
450 return i;
451 }
452
453 return (-1);
454}
455
466int _papi_hwi_publish_error( char *error )
467{
468 int error_code = -1;
469
470 if ( (error_code = _papi_hwi_lookup_error( error )) < 0 )
471 error_code = _papi_hwi_add_error(error);
472
473 return (-error_code); /* internally error_code is an index, externally, it should be <= 0 */
474}
475
476
477/* Why are the errors done this way?
478 Should they not be auto-generated the same way the Fortran ones are?
479 --vmw
480*/
481void
483/* we use add error to avoid the cost of lookups, we know the errors are not there yet */
484 /* 0 PAPI_OK */ _papi_hwi_add_error("No error");
485 /* 1 PAPI_EINVAL */ _papi_hwi_add_error("Invalid argument");
486 /* 2 PAPI_ENOMEM */ _papi_hwi_add_error("Insufficient memory");
487 /* 3 PAPI_ESYS */ _papi_hwi_add_error("A System/C library call failed");
488 /* 4 PAPI_ECMP */ _papi_hwi_add_error("Not supported by component");
489 /* 5 PAPI_ECLOST */ _papi_hwi_add_error("Access to the counters was lost or interrupted");
490 /* 6 PAPI_EBUG */ _papi_hwi_add_error("Internal error, please send mail to the developers");
491 /* 7 PAPI_ENOEVNT */ _papi_hwi_add_error("Event does not exist");
492 /* 8 PAPI_ECNFLCT */ _papi_hwi_add_error("Event exists, but cannot be counted due to hardware resource limits");
493 /* 9 PAPI_ENOTRUN */ _papi_hwi_add_error("EventSet is currently not running");
494 /* 10 PAPI_EISRUN */ _papi_hwi_add_error("EventSet is currently counting");
495 /* 11 PAPI_ENOEVST */ _papi_hwi_add_error("No such EventSet available");
496 /* 12 PAPI_ENOTPRESET */_papi_hwi_add_error("Event in argument is not a valid preset");
497 /* 13 PAPI_ENOCNTR */ _papi_hwi_add_error("Hardware does not support performance counters");
498 /* 14 PAPI_EMISC */ _papi_hwi_add_error("Unknown error code");
499 /* 15 PAPI_EPERM */ _papi_hwi_add_error("Permission level does not permit operation");
500 /* 16 PAPI_ENOINIT */ _papi_hwi_add_error("PAPI hasn't been initialized yet");
501 /* 17 PAPI_ENOCMP */ _papi_hwi_add_error("Component Index isn't set");
502 /* 18 PAPI_ENOSUPP */ _papi_hwi_add_error("Not supported");
503 /* 19 PAPI_ENOIMPL */ _papi_hwi_add_error("Not implemented");
504 /* 20 PAPI_EBUF */ _papi_hwi_add_error("Buffer size exceeded");
505 /* 21 PAPI_EINVAL_DOM */_papi_hwi_add_error("EventSet domain is not supported for the operation");
506 /* 22 PAPI_EATTR */ _papi_hwi_add_error("Invalid or missing event attributes");
507 /* 23 PAPI_ECOUNT */ _papi_hwi_add_error("Too many events or attributes");
508 /* 24 PAPI_ECOMBO */ _papi_hwi_add_error("Bad combination of features");
509 /* 25 PAPI_ECMP_DISABLED */_papi_hwi_add_error("Component containing event is disabled");
510 /* 26 PAPI_EDELAY_INIT */ _papi_hwi_add_error("Delayed initialization component");
511 /* 27 PAPI_EMULPASS */ _papi_hwi_add_error("Event exists, but cannot be counted due to multiple passes required by hardware");
512}
513
514int
516{
517 return ( cidx < 0 || cidx >= papi_num_components );
518}
519
520
521int
522_papi_hwi_component_index( int event_code ) {
523 INTDBG("ENTER: event_code: %#x\n", event_code);
524
525 int cidx;
526 int event_index;
527
528 /* currently assume presets are for component 0 only */
529 if (IS_PRESET(event_code)) {
530 INTDBG("EXIT: Event %#x is a PRESET, assigning component %d\n", event_code,0);
531 return 0;
532 }
533
534 /* user defined events are treated like preset events (component 0 only) */
535 if (IS_USER_DEFINED(event_code)) {
536 INTDBG("EXIT: Event %#x is USER DEFINED, assigning component %d\n", event_code,0);
537 return 0;
538 }
539
540 event_index=event_code&PAPI_NATIVE_AND_MASK;
541
542 if ( (event_index < 0) || (event_index>=num_native_events)) {
543 INTDBG("EXIT: Event index %#x is out of range, num_native_events: %d\n", event_index, num_native_events);
544 return PAPI_ENOEVNT;
545 }
546
547 cidx=_papi_native_events[event_index].cidx;
548
549 if ((cidx<0) || (cidx >= papi_num_components)) {
550 INTDBG("EXIT: Component index %#x is out of range, papi_num_components: %d\n", cidx, papi_num_components);
551 return PAPI_ENOCMP;
552 }
553
554 INTDBG("EXIT: Found cidx: %d event_index: %d, event_code: %#x\n", cidx, event_index, event_code);
555 return cidx;
556}
557
558/* Convert an internal component event to a papi event code */
559int
560_papi_hwi_native_to_eventcode(int cidx, int event_code, int ntv_idx, const char *event_name) {
561 INTDBG("Entry: cidx: %d, event: %#x, ntv_idx: %d, event_name: %s\n", cidx, event_code, ntv_idx, event_name);
562
563 int result;
564
567 INTDBG("EXIT: papi_event_code: %#x set by the component\n", result);
568 return result;
569 }
570
572 if (result==PAPI_ENOEVNT) {
573 // Need to create one
575 }
576
577 INTDBG("EXIT: result: %#x\n", result);
578 return result;
579}
580
581/* Convert a native_event code to an internal event code */
582int
584 INTDBG("ENTER: event_code: %#x\n", event_code);
585
586 int result;
587 int event_index;
588
589 event_index=event_code&PAPI_NATIVE_AND_MASK;
590 if ((event_index < 0) || (event_index>=num_native_events)) {
591 INTDBG("EXIT: PAPI_ENOEVNT\n");
592 return PAPI_ENOEVNT;
593 }
594
596
597 INTDBG("EXIT: result: %#x\n", result);
598 return result;
599
600}
601
602
603/*********************/
604/* Utility functions */
605/*********************/
606
607void
608PAPIERROR( char *format, ... )
609{
610 va_list args;
611 if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
612 ( getenv( "PAPI_VERBOSE" ) ) ) {
613 va_start( args, format );
614 fprintf( stderr, "PAPI Error: " );
615 vfprintf( stderr, format, args );
616 fprintf( stderr, "\n" );
617 va_end( args );
618 }
619}
620
621void
622PAPIWARN( char *format, ... )
623{
624 va_list args;
625 if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
626 ( getenv( "PAPI_VERBOSE" ) ) ) {
627 va_start( args, format );
628 fprintf( stderr, "PAPI Warning: " );
629 vfprintf( stderr, format, args );
630 fprintf( stderr, "\n" );
631 va_end( args );
632 }
633}
634
635static int
636default_debug_handler( int errorCode )
637{
638 char str[PAPI_HUGE_STR_LEN];
639
640 if ( errorCode == PAPI_OK )
641 return ( errorCode );
642 if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) {
643 PAPIERROR( "%s %d,%s,Bug! Unknown error code", PAPI_ERROR_CODE_str,
644 errorCode, "" );
645 return ( PAPI_EBUG );
646 }
647
648 switch ( _papi_hwi_error_level ) {
649 case PAPI_VERB_ECONT:
650 case PAPI_VERB_ESTOP:
651 /* gcc 2.96 bug fix, do not change */
652 /* fprintf(stderr,"%s %d: %s: %s\n",PAPI_ERROR_CODE_str,errorCode,_papi_hwi_err[-errorCode].name,_papi_hwi_err[-errorCode].descr); */
653
654 sprintf( str, "%s %d,%s", PAPI_ERROR_CODE_str, errorCode,
655 _papi_errlist[-errorCode] );
656 if ( errorCode == PAPI_ESYS )
657 sprintf( str + strlen( str ), ": %s", strerror( errno ) );
658
659 PAPIERROR( str );
660
662 abort( ); /* patch provided by will cohen of redhat */
663 else
664 return errorCode;
665 break;
666
667 case PAPI_QUIET:
668 default:
669 return errorCode;
670 }
671 return ( PAPI_EBUG ); /* Never get here */
672}
673
674static int
676{
677 /* Allocate and clear the Dynamic Array structure */
678 if ( map->dataSlotArray != NULL )
679 papi_free( map->dataSlotArray );
680 memset( map, 0x00, sizeof ( DynamicArray_t ) );
681
682 /* Allocate space for the EventSetInfo_t pointers */
683
684 map->dataSlotArray =
686 sizeof ( EventSetInfo_t * ) );
687 if ( map->dataSlotArray == NULL ) {
688 return ( PAPI_ENOMEM );
689 }
690 memset( map->dataSlotArray, 0x00,
691 PAPI_INIT_SLOTS * sizeof ( EventSetInfo_t * ) );
694 map->fullSlots = 0;
695
696 return ( PAPI_OK );
697}
698
699static int
701{
702 int number;
703 EventSetInfo_t **n;
704
705 /*realloc existing PAPI_EVENTSET_MAP.dataSlotArray */
706
707 number = DA->totalSlots * 2;
709 ( size_t ) number *
710 sizeof ( EventSetInfo_t * ) );
711 if ( n == NULL )
712 return ( PAPI_ENOMEM );
713
714 /* Need to assign this value, what if realloc moved it? */
715
716 DA->dataSlotArray = n;
717
718 memset( DA->dataSlotArray + DA->totalSlots, 0x00,
719 ( size_t ) DA->totalSlots * sizeof ( EventSetInfo_t * ) );
720
721 DA->totalSlots = number;
722 DA->availSlots = number - DA->fullSlots;
723
724 return ( PAPI_OK );
725}
726
727static int
729{
730 return ( _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs );
731}
732
733
734
735
736
737/*========================================================================*/
738/* This function allocates space for one EventSetInfo_t structure and for */
739/* all of the pointers in this structure. If any malloc in this function */
740/* fails, all memory malloced to the point of failure is freed, and NULL */
741/* is returned. Upon success, a pointer to the EventSetInfo_t data */
742/* structure is returned. */
743/*========================================================================*/
744
745
746static int
748{
749 EventSetInfo_t *ESI;
750
751 ESI = ( EventSetInfo_t * ) papi_calloc( 1, sizeof ( EventSetInfo_t ) );
752 if ( ESI == NULL ) {
753 return PAPI_ENOMEM;
754 }
755
756 *here = ESI;
757
758 return PAPI_OK;
759}
760
761int
763{
764 INTDBG("ENTER: ESI: %p (%d), cidx: %d\n", ESI, ESI->EventSetIndex, cidx);
765 int retval;
766 size_t max_counters;
767 char *ptr;
768 unsigned int i, j;
769
770 /* If component doesn't exist... */
772
773 /* Assigned at create time */
774 ESI->domain.domain = _papi_hwd[cidx]->cmp_info.default_domain;
776 _papi_hwd[cidx]->cmp_info.default_granularity;
777 ESI->CmpIdx = cidx;
778
779 /* ??? */
780 max_counters = ( size_t ) _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
781
782 ESI->ctl_state = (hwd_control_state_t *) papi_calloc( 1, (size_t)
783 _papi_hwd[cidx]->size.control_state );
784 ESI->sw_stop = (long long *) papi_calloc( ( size_t ) max_counters,
785 sizeof ( long long ) );
786 ESI->hw_start = ( long long * ) papi_calloc( ( size_t ) max_counters,
787 sizeof ( long long ) );
788 ESI->EventInfoArray = ( EventInfo_t * ) papi_calloc( (size_t) max_counters,
789 sizeof ( EventInfo_t ) );
790
791 /* allocate room for the native events and for the component-private */
792 /* register structures */
793 /* ugh is there a cleaner way to allocate this? vmw */
794 ESI->NativeInfoArray = ( NativeInfo_t * )
795 papi_calloc( ( size_t ) max_counters, sizeof ( NativeInfo_t ));
796
797 ESI->NativeBits = papi_calloc(( size_t ) max_counters,
798 ( size_t ) _papi_hwd[cidx]->size.reg_value );
799
800 /* NOTE: the next two malloc allocate blocks of memory that are later */
801 /* parcelled into overflow and profile arrays */
802 ESI->overflow.deadline = ( long long * )
803 papi_malloc( ( sizeof ( long long ) +
804 sizeof ( int ) * 3 ) * ( size_t ) max_counters );
805
806 ESI->profile.prof = ( PAPI_sprofil_t ** )
807 papi_malloc( ( sizeof ( PAPI_sprofil_t * ) * ( size_t ) max_counters +
808 ( size_t ) max_counters * sizeof ( int ) * 4 ) );
809
810 /* If any of these allocations failed, free things up and fail */
811
812 if ( ( ESI->ctl_state == NULL ) ||
813 ( ESI->sw_stop == NULL ) ||
814 ( ESI->hw_start == NULL ) ||
815 ( ESI->NativeInfoArray == NULL ) ||
816 ( ESI->NativeBits == NULL ) ||
817 ( ESI->EventInfoArray == NULL ) ||
818 ( ESI->profile.prof == NULL ) ||
819 ( ESI->overflow.deadline == NULL ) ) {
820
821 if ( ESI->sw_stop ) papi_free( ESI->sw_stop );
822 if ( ESI->hw_start ) papi_free( ESI->hw_start );
823 if ( ESI->EventInfoArray ) papi_free( ESI->EventInfoArray );
824 if ( ESI->NativeInfoArray ) papi_free( ESI->NativeInfoArray );
825 if ( ESI->NativeBits ) papi_free( ESI->NativeBits );
826 if ( ESI->ctl_state ) papi_free( ESI->ctl_state );
827 if ( ESI->overflow.deadline ) papi_free( ESI->overflow.deadline );
828 if ( ESI->profile.prof ) papi_free( ESI->profile.prof );
829 papi_free( ESI );
830 return PAPI_ENOMEM;
831 }
832
833
834 /* Carve up the overflow block into separate arrays */
835 ptr = ( char * ) ESI->overflow.deadline;
836 ptr += sizeof ( long long ) * max_counters;
837 ESI->overflow.threshold = ( int * ) ptr;
838 ptr += sizeof ( int ) * max_counters;
839 ESI->overflow.EventIndex = ( int * ) ptr;
840 ptr += sizeof ( int ) * max_counters;
841 ESI->overflow.EventCode = ( int * ) ptr;
842
843 /* Carve up the profile block into separate arrays */
844 ptr = ( char * ) ESI->profile.prof +
845 ( sizeof ( PAPI_sprofil_t * ) * max_counters );
846 ESI->profile.count = ( int * ) ptr;
847 ptr += sizeof ( int ) * max_counters;
848 ESI->profile.threshold = ( int * ) ptr;
849 ptr += sizeof ( int ) * max_counters;
850 ESI->profile.EventIndex = ( int * ) ptr;
851 ptr += sizeof ( int ) * max_counters;
852 ESI->profile.EventCode = ( int * ) ptr;
853
854 /* initialize_EventInfoArray */
855
856 for ( i = 0; i < max_counters; i++ ) {
857 ESI->EventInfoArray[i].event_code=( unsigned int ) PAPI_NULL;
858 ESI->EventInfoArray[i].ops = NULL;
860 for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
861 ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
862 }
863 }
864
865 /* initialize_NativeInfoArray */
866 for( i = 0; i < max_counters; i++ ) {
867 ESI->NativeInfoArray[i].ni_event = -1;
868 ESI->NativeInfoArray[i].ni_position = -1;
869 ESI->NativeInfoArray[i].ni_papi_code = -1;
870 ESI->NativeInfoArray[i].ni_owners = 0;
871 ESI->NativeInfoArray[i].ni_bits = ((unsigned char*)ESI->NativeBits) +
872 (i*_papi_hwd[cidx]->size.reg_value);
873 }
874
875 ESI->NativeCount = 0;
876
877 ESI->state = PAPI_STOPPED;
878
879 /* these used to be init_config */
880 retval = _papi_hwd[cidx]->init_control_state( ESI->ctl_state );
881 retval |= _papi_hwd[cidx]->set_domain( ESI->ctl_state, ESI->domain.domain);
882
883 return retval;
884}
885
886/*========================================================================*/
887/* This function should free memory for one EventSetInfo_t structure. */
888/* The argument list consists of a pointer to the EventSetInfo_t */
889/* structure, *ESI. */
890/* The calling function should check for ESI==NULL. */
891/*========================================================================*/
892
893void
895{
897
898#ifdef DEBUG
899 memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
900#endif
901 papi_free( ESI );
902
903}
904
905static int
907{
909 int i, errorCode;
910
912
913 if ( map->availSlots == 0 ) {
914 errorCode = expand_dynamic_array( map );
915 if ( errorCode < PAPI_OK ) {
917 return ( errorCode );
918 }
919 }
920
921 i = 0;
922 for ( i = 0; i < map->totalSlots; i++ ) {
923 if ( map->dataSlotArray[i] == NULL ) {
924 ESI->master = master;
925 ESI->EventSetIndex = i;
926 map->fullSlots++;
927 map->availSlots--;
928 map->dataSlotArray[i] = ESI;
930 return ( PAPI_OK );
931 }
932 }
933
935 return ( PAPI_EBUG );
936}
937
938int
940{
941 EventSetInfo_t *ESI;
942 int retval;
943
944 /* Is the EventSet already in existence? */
945
946 if ( ( EventSet == NULL ) || ( handle == NULL ) )
947 return PAPI_EINVAL;
948
949 if ( *EventSet != PAPI_NULL )
950 return PAPI_EINVAL;
951
952 /* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
953
954 retval = create_EventSet( &ESI );
955 if ( retval != PAPI_OK )
956 return retval;
957
958 ESI->CmpIdx = -1; /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
959 ESI->state = PAPI_STOPPED;
960
961 /* Add it to the global table */
962
963 retval = add_EventSet( ESI, handle );
964 if ( retval < PAPI_OK ) {
966 return retval ;
967 }
968
969 *EventSet = ESI->EventSetIndex;
970
971 INTDBG( "(%p,%p): new EventSet in slot %d\n",
972 ( void * ) EventSet, handle, *EventSet );
973
974 return retval;
975}
976
977/* This function returns the index of the the next free slot
978 in the EventInfoArray. If EventCode is already in the list,
979 it returns PAPI_ECNFLCT. */
980
981static int
982get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
983{
984 int k;
985 int lowslot = PAPI_ECNFLCT;
986 int limit = EventInfoArrayLength( ESI );
987
988 /* Check for duplicate events and get the lowest empty slot */
989
990 for ( k = 0; k < limit; k++ ) {
991 if ( ESI->EventInfoArray[k].event_code == EventCode )
992 return ( PAPI_ECNFLCT );
993 /*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
994 if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
995 lowslot = k;
996 break;
997 }
998 }
999 return ( lowslot );
1000}
1001
1002/* This function returns the index of the EventCode or error */
1003/* Index to what? The index to everything stored EventCode in the */
1004/* EventSet. */
1005
1006int
1008 unsigned int EventCode )
1009{
1010 int i;
1011 int limit = EventInfoArrayLength( ESI );
1012
1013 for ( i = 0; i < limit; i++ ) {
1014 if ( ESI->EventInfoArray[i].event_code == EventCode ) {
1015 return i;
1016 }
1017 }
1018
1019 return PAPI_EINVAL;
1020}
1021
1022/* This function only removes empty EventSets */
1023
1024int
1026{
1028 int i;
1029
1030 i = ESI->EventSetIndex;
1031
1033
1035
1036 /* do bookkeeping for PAPI_EVENTSET_MAP */
1037
1038 map->dataSlotArray[i] = NULL;
1039 map->availSlots++;
1040 map->fullSlots--;
1041
1043
1044 return PAPI_OK;
1045}
1046
1047
1048/* this function checks if an event is already in an EventSet
1049 Success, return ESI->NativeInfoArray[] index
1050 Fail, return PAPI_ENOEVNT;
1051*/
1052static int
1054{
1055 INTDBG( "ENTER: ESI: %p, papi_event: %#x\n", ESI, papi_event);
1056 int i;
1057
1058 int nevt = _papi_hwi_eventcode_to_native(papi_event);
1059
1060 /* to find the native event from the native events list */
1061 for( i = 0; i < ESI->NativeCount; i++ ) {
1062 if ( nevt == ESI->NativeInfoArray[i].ni_event ) {
1063 // Also need to check papi event code if set because the same event with different masks
1064 // will generate the same libpfm4 event code (what was checked above). But there will be
1065 // different papi events created for it and they need to be handled separately.
1066 if (papi_event == ESI->NativeInfoArray[i].ni_papi_code) {
1067 INTDBG( "EXIT: event: %#x already mapped at index: %d\n", papi_event, i);
1068 return i;
1069 }
1070 }
1071 }
1072 INTDBG( "EXIT: PAPI_ENOEVNT\n");
1073 return PAPI_ENOEVNT;
1074}
1075
1076/* This function goes through the events in an EventSet's EventInfoArray */
1077/* And maps each event (whether native or part of a preset) to */
1078/* an event in the EventSets NativeInfoArray. */
1079
1080/* We need to do this every time a native event is added to or removed */
1081/* from an eventset. */
1082
1083/* It is also called after a update controlstate as the components are */
1084/* allowed to re-arrange the native events to fit hardware constraints. */
1085
1086void
1088{
1089 INTDBG("ENTER: ESI: %p, ESI->EventInfoArray: %p, ESI->NativeInfoArray: %p, ESI->NumberOfEvents: %d, ESI->NativeCount: %d\n", ESI, ESI->EventInfoArray, ESI->NativeInfoArray, ESI->NumberOfEvents, ESI->NativeCount);
1090
1091 int i, event, k, n, preset_index = 0, nevt;
1092 int total_events = ESI->NumberOfEvents;
1093
1094 event = 0;
1095 for( i = 0; i < total_events; i++ ) {
1096
1097 /* find the first event that isn't PAPI_NULL */
1098 /* Is this really necessary? --vmw */
1099 while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
1100 event++;
1101 }
1102
1103 /* If it's a preset */
1104 if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
1105 preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
1106
1107 /* walk all sub-events in the preset */
1108 for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
1109 nevt = _papi_hwi_presets[preset_index].code[k];
1110 if ( nevt == PAPI_NULL ) {
1111 break;
1112 }
1113
1114 INTDBG("Looking for subevent %#x\n",nevt);
1115
1116 /* Match each sub-event to something in the Native List */
1117 for( n = 0; n < ESI->NativeCount; n++ ) {
1118 if ( nevt == ESI->NativeInfoArray[n].ni_papi_code ) {
1119 INTDBG("Found papi event: %#x, &ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_position %d\n",
1120 nevt, n, &(ESI->NativeInfoArray[n]), ESI->NativeInfoArray[n].ni_event, ESI->NativeInfoArray[n].ni_position);
1121 ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
1122 break;
1123 }
1124 }
1125 }
1126 }
1127 /* If it's a native event */
1128 else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
1129 nevt = ( int ) ESI->EventInfoArray[event].event_code;
1130
1131 // get index into native info array for this event
1132 int nidx = event_already_in_eventset( ESI, nevt );
1133 // if not found, then we need to return an error
1134 if (nidx == PAPI_ENOEVNT) {
1135 INTDBG("EXIT: needed event not found\n");
1136 return;
1137 }
1138 ESI->EventInfoArray[event].pos[0] = ESI->NativeInfoArray[nidx].ni_position;
1139 INTDBG("nidx: %d, ni_position: %d\n", nidx, ESI->NativeInfoArray[nidx].ni_position);
1140
1141 }
1142 /* If it's a user-defined event */
1143 else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
1144 preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_UE_AND_MASK;
1145 for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
1146 nevt = user_defined_events[preset_index].code[k];
1147 INTDBG("nevt: %#x, user_defined_events[%d].code[%d]: %#x, code[%d]: %#x\n",
1148 nevt, preset_index, k, user_defined_events[preset_index].code[k], k+1, user_defined_events[preset_index].code[k+1]);
1149
1150 if ( nevt == PAPI_NULL ) break;
1151
1152 /* Match each sub-event to something in the Native List */
1153 for ( n = 0; n < ESI->NativeCount; n++ ) {
1154 // if this is the event we are looking for, set its position and exit inner loop to look for next sub-event
1156 ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
1157 break;
1158 }
1159 }
1160 }
1161 }
1162 event++;
1163 }
1164 INTDBG("EXIT: \n");
1165 return;
1166}
1167
1168
1169static int
1171{
1172 INTDBG("ENTER: ESI: %p, nevt: %#x\n", ESI, nevt);
1173
1174 int i, max_counters;
1175 int cidx;
1176
1178 if (cidx<0) return PAPI_ENOCMP;
1179
1180 max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
1181
1182 /* to find the native event from the native events list */
1183 for( i = 0; i < max_counters; i++ ) {
1184// INTDBG("ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_papi_event_code: %#x, ni_position: %d, ni_owners: %d\n",
1185// i, &(ESI->NativeInfoArray[i]), ESI->NativeInfoArray[i].ni_event, ESI->NativeInfoArray[i].ni_papi_code, ESI->NativeInfoArray[i].ni_position, ESI->NativeInfoArray[i].ni_owners);
1186 if ( nevt == ESI->NativeInfoArray[i].ni_papi_code ) {
1187 ESI->NativeInfoArray[i].ni_owners--;
1188 /* to clean the entry in the nativeInfo array */
1189 if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
1190 ESI->NativeInfoArray[i].ni_event = -1;
1191 ESI->NativeInfoArray[i].ni_position = -1;
1192 ESI->NativeInfoArray[i].ni_papi_code = -1;
1193 ESI->NativeCount--;
1194 }
1195 INTDBG( "EXIT: nevt: %#x, returned: %d\n", nevt, i);
1196 return i;
1197 }
1198 }
1199 INTDBG( "EXIT: returned: -1\n");
1200 return -1;
1201}
1202
1203/* since update_control_state trashes overflow settings, this puts things
1204 back into balance. */
1205static int
1207{
1208 int i, retval = PAPI_OK;
1209
1210 if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
1211 for( i = 0; i < ESI->overflow.event_counter; i++ ) {
1212 retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
1213 ESI->overflow.EventIndex[i],
1214 ESI->overflow.threshold[i] );
1215 if ( retval != PAPI_OK ) {
1216 break;
1217 }
1218 }
1219 }
1220 return retval;
1221}
1222
1223/* this function is called by _papi_hwi_add_event when adding native events
1224 ESI: event set to add the events to
1225 nevnt: pointer to array of native event table indexes to add
1226 size: number of native events to add
1227 out: ???
1228
1229 return: < 0 = error
1230 0 = no new events added
1231 1 = new events added
1232*/
1233static int
1234add_native_events( EventSetInfo_t *ESI, unsigned int *nevt,
1235 int size, EventInfo_t *out )
1236{
1237 INTDBG ("ENTER: ESI: %p, nevt: %p, size: %d, out: %p\n", ESI, nevt, size, out);
1238 int nidx, i, j, added_events = 0;
1239 int retval, retval2;
1240 int max_counters;
1241 hwd_context_t *context;
1242
1243 max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1244
1245 /* Walk through the list of native events, adding them */
1246 for( i = 0; i < size; i++ ) {
1247
1248 /* Check to see if event is already in EventSet */
1249 nidx = event_already_in_eventset( ESI, nevt[i] );
1250
1251 if ( nidx >= 0 ) {
1252 /* Event is already there. Set position */
1253 out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
1254 ESI->NativeInfoArray[nidx].ni_owners++;
1255 continue;
1256 }
1257
1258 /* Event wasn't already there */
1259
1260 if ( ESI->NativeCount == max_counters ) {
1261
1262 /* No more room in counters! */
1263 for( j = 0; j < i; j++ ) {
1264 if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
1265 out->pos[j] = -1;
1266 continue;
1267 }
1268 INTDBG( "should not happen!\n" );
1269 }
1270 INTDBG( "EXIT: counters are full!\n" );
1271 return PAPI_ECOUNT;
1272 }
1273
1274 /* there is an empty slot for the native event; */
1275 /* initialize the native index for the new added event */
1276 INTDBG( "Adding nevt[%d]: %#x, ESI->NativeInfoArray[%d]: %p, Component: %d\n",
1277 i, nevt[i], ESI->NativeCount, &ESI->NativeInfoArray[ESI->NativeCount], ESI->CmpIdx );
1280 ESI->NativeInfoArray[ESI->NativeCount].ni_papi_code = nevt[i];
1281
1282 ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
1283 ESI->NativeCount++;
1284 added_events++;
1285 }
1286
1287 INTDBG("added_events: %d\n", added_events);
1288
1289 /* if we added events we need to tell the component so it */
1290 /* can add them too. */
1291 if ( added_events ) {
1292 /* get the context we should use for this event set */
1293 context = _papi_hwi_get_context( ESI, NULL );
1294
1295 if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
1296
1297 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1298 ESI->NativeInfoArray,
1299 ESI->NativeCount,
1300 context);
1301 if ( retval != PAPI_OK ) {
1302clean:
1303 for( i = 0; i < size; i++ ) {
1304 if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
1305 out->pos[i] = -1;
1306 continue;
1307 }
1308 INTDBG( "should not happen!\n" );
1309 }
1310 /* re-establish the control state after the previous error */
1311 retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state(
1312 ESI->ctl_state,
1313 ESI->NativeInfoArray,
1314 ESI->NativeCount,
1315 context);
1316 if ( retval2 != PAPI_OK ) {
1317 PAPIERROR("update_control_state failed to re-establish working events!" );
1318 INTDBG( "EXIT: update_control_state returned: %d\n", retval2);
1319 return retval2;
1320 }
1321 INTDBG( "EXIT: update_control_state returned: %d\n", retval);
1322 return retval;
1323 }
1324 INTDBG( "EXIT: update_control_state returned: %d, we return: 1 (need remap)\n", retval);
1325 return 1; /* need remap */
1326 } else {
1328 goto clean;
1329 }
1330 }
1331 INTDBG( "EXIT: PAPI_OK\n");
1332 return PAPI_OK;
1333}
1334
1335
1336int
1338{
1339 INTDBG("ENTER: ESI: %p (%d), EventCode: %#x\n", ESI, ESI->EventSetIndex, EventCode);
1340
1341 int i, j, thisindex, remap, retval = PAPI_OK;
1342 int cidx;
1343
1344 /* Sanity check the component */
1345 cidx=_papi_hwi_component_index( EventCode );
1346 if (cidx<0) {
1347 return PAPI_ENOCMP;
1348 }
1349 if (_papi_hwd[cidx]->cmp_info.disabled &&
1350 _papi_hwd[cidx]->cmp_info.disabled != PAPI_EDELAY_INIT) {
1351 return PAPI_ECMP_DISABLED;
1352 }
1353
1354 /* Sanity check that the new EventCode is from the same component */
1355 /* as previous events. */
1356
1357 if ( ESI->CmpIdx < 0 ) {
1358 if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx)) != PAPI_OK ) {
1359 INTDBG("EXIT: Error assigning eventset to component index %d\n", cidx);
1360 return retval;
1361 }
1362 } else {
1363 if ( ESI->CmpIdx != cidx ) {
1364 INTDBG("EXIT: Event is not valid for component index %d\n", cidx);
1365 return PAPI_EINVAL;
1366 }
1367 }
1368
1369 /* Make sure the event is not present and get the next free slot. */
1370 thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1371 if ( thisindex < PAPI_OK ) {
1372 return thisindex;
1373 }
1374
1375 INTDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
1376
1377 /* If it is a software MPX EventSet, add it to the multiplex data structure */
1378 /* and this thread's multiplex list */
1379
1380 if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
1381
1382 /* Handle preset case */
1383 if ( IS_PRESET(EventCode) ) {
1384 int count;
1385 int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
1386
1387 /* Check if it's within the valid range */
1388 if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
1389 return PAPI_EINVAL;
1390 }
1391
1392 /* count the number of native events in this preset */
1393 count = ( int ) _papi_hwi_presets[preset_index].count;
1394
1395 /* Check if event exists */
1396 if ( !count ) {
1397 return PAPI_ENOEVNT;
1398 }
1399
1400 /* check if the native events have been used as overflow events */
1401 /* this is not allowed */
1402 if ( ESI->state & PAPI_OVERFLOWING ) {
1403 for( i = 0; i < count; i++ ) {
1404 for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1405 if ( ESI->overflow.EventCode[j] ==(int)
1406 ( _papi_hwi_presets[preset_index].code[i] ) ) {
1407 return PAPI_ECNFLCT;
1408 }
1409 }
1410 }
1411 }
1412
1413 /* Try to add the preset. */
1414
1415 remap = add_native_events( ESI,
1416 _papi_hwi_presets[preset_index].code,
1417 count, &ESI->EventInfoArray[thisindex] );
1418 if ( remap < 0 ) {
1419 return remap;
1420 }
1421 else {
1422 /* Fill in the EventCode (machine independent) information */
1423 ESI->EventInfoArray[thisindex].event_code =
1424 ( unsigned int ) EventCode;
1425 ESI->EventInfoArray[thisindex].derived =
1426 _papi_hwi_presets[preset_index].derived_int;
1427 ESI->EventInfoArray[thisindex].ops =
1428 _papi_hwi_presets[preset_index].postfix;
1429 ESI->NumberOfEvents++;
1431
1432 }
1433 }
1434 /* Handle adding Native events */
1435 else if ( IS_NATIVE(EventCode) ) {
1436
1437 /* Check if native event exists */
1438 if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
1439 return PAPI_ENOEVNT;
1440 }
1441
1442 /* check if the native events have been used as overflow events */
1443 /* This is not allowed */
1444 if ( ESI->state & PAPI_OVERFLOWING ) {
1445 for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1446 if ( EventCode == ESI->overflow.EventCode[j] ) {
1447 return PAPI_ECNFLCT;
1448 }
1449 }
1450 }
1451
1452 /* Try to add the native event. */
1453
1454 remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
1455 &ESI->EventInfoArray[thisindex] );
1456
1457 if ( remap < 0 ) {
1458 return remap;
1459 } else {
1460
1461 /* Fill in the EventCode (machine independent) information */
1462 ESI->EventInfoArray[thisindex].event_code =
1463 ( unsigned int ) EventCode;
1464 ESI->NumberOfEvents++;
1466
1467 }
1468 } else if ( IS_USER_DEFINED( EventCode ) ) {
1469 int count;
1470 int index = EventCode & PAPI_UE_AND_MASK;
1471
1472 if ( index < 0 || index >= user_defined_events_count )
1473 return ( PAPI_EINVAL );
1474
1475 count = ( int ) user_defined_events[index].count;
1476
1477 for ( i = 0; i < count; i++ ) {
1478 for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
1479 if ( ESI->overflow.EventCode[j] ==
1480 (int)(user_defined_events[index].code[i]) ) {
1481 return ( PAPI_EBUG );
1482 }
1483 }
1484 }
1485
1486 remap = add_native_events( ESI,
1487 user_defined_events[index].code,
1488 count, &ESI->EventInfoArray[thisindex] );
1489
1490 if ( remap < 0 ) {
1491 return remap;
1492 } else {
1493 ESI->EventInfoArray[thisindex].event_code = (unsigned int) EventCode;
1494 ESI->EventInfoArray[thisindex].derived = user_defined_events[index].derived_int;
1495 ESI->EventInfoArray[thisindex].ops = user_defined_events[index].postfix;
1496 ESI->NumberOfEvents++;
1498 }
1499 } else {
1500
1501 /* not Native, Preset, or User events */
1502
1503 return PAPI_EBUG;
1504 }
1505 }
1506 else {
1507
1508 /* Multiplexing is special. See multiplex.c */
1509
1510 retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
1511 ESI->domain.domain,
1512 ESI->granularity.granularity );
1513
1514
1515 if ( retval < PAPI_OK ) {
1516 return retval;
1517 }
1518
1519 /* Relevant (???) */
1520 ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;
1521 ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
1522
1523 ESI->NumberOfEvents++;
1524
1525 /* event is in the EventInfoArray but not mapped to the NativeEvents */
1526 /* this causes issues if you try to set overflow on the event. */
1527 /* in theory this wouldn't matter anyway. */
1528 }
1529
1530 /* reinstate the overflows if any */
1531 retval=update_overflow( ESI );
1532
1533 return retval;
1534}
1535
1536static int
1537remove_native_events( EventSetInfo_t *ESI, int *nevt, int size )
1538{
1539 INTDBG( "Entry: ESI: %p, nevt: %p, size: %d\n", ESI, nevt, size);
1541 hwd_context_t *context;
1542 int i, j, zero = 0, retval;
1543
1544 /* Remove the references to this event from the native events:
1545 for all the metrics in this event,
1546 compare to each native event in this event set,
1547 and decrement owners if they match */
1548 for( i = 0; i < size; i++ ) {
1549 int cevt = _papi_hwi_eventcode_to_native(nevt[i]);
1550// INTDBG( "nevt[%d]: %#x, cevt: %#x\n", i, nevt[i], cevt);
1551 for( j = 0; j < ESI->NativeCount; j++ ) {
1552 if ((native[j].ni_event == cevt) && (native[j].ni_papi_code == nevt[i]) ) {
1553// INTDBG( "native[%d]: %p, ni_papi_code: %#x, ni_event: %#x, ni_position: %d, ni_owners: %d\n",
1554// j, &(native[j]), native[j].ni_papi_code, native[j].ni_event, native[j].ni_position, native[j].ni_owners);
1555 native[j].ni_owners--;
1556 if ( native[j].ni_owners == 0 ) {
1557 zero++;
1558 }
1559 break;
1560 }
1561 }
1562 }
1563
1564 /* Remove any native events from the array if owners dropped to zero.
1565 The NativeInfoArray must be dense, with no empty slots, so if we
1566 remove an element, we must compact the list */
1567 for( i = 0; i < ESI->NativeCount; i++ ) {
1568
1569 if ( native[i].ni_event == -1 ) continue;
1570
1571 if ( native[i].ni_owners == 0 ) {
1572 int copy = 0;
1573 int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
1574 for( j = ESI->NativeCount - 1; j > i; j-- ) {
1575 if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
1576 else {
1577 /* copy j into i */
1578 native[i].ni_event = native[j].ni_event;
1579 native[i].ni_position = native[j].ni_position;
1580 native[i].ni_owners = native[j].ni_owners;
1581 /* copy opaque [j].ni_bits to [i].ni_bits */
1582 memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
1583 /* reset j to initialized state */
1584 native[j].ni_event = -1;
1585 native[j].ni_position = -1;
1586 native[j].ni_owners = 0;
1587 copy++;
1588 break;
1589 }
1590 }
1591
1592 if ( copy == 0 ) {
1593 /* set this structure back to empty state */
1594 /* ni_owners is already 0 and contents of ni_bits doesn't matter */
1595 native[i].ni_event = -1;
1596 native[i].ni_position = -1;
1597 }
1598 }
1599 }
1600
1601 INTDBG( "ESI->NativeCount: %d, zero: %d\n", ESI->NativeCount, zero);
1602
1603 /* to reset hwd_control_state values */
1604 ESI->NativeCount -= zero;
1605
1606 /* If we removed any elements,
1607 clear the now empty slots, reinitialize the index, and update the count.
1608 Then send the info down to the component to update the hwd control structure. */
1609 retval = PAPI_OK;
1610 if ( zero ) {
1611 /* get the context we should use for this event set */
1612 context = _papi_hwi_get_context( ESI, NULL );
1613 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1614 native, ESI->NativeCount, context);
1615 if ( retval == PAPI_OK )
1616 retval = update_overflow( ESI );
1617 }
1618 return ( retval );
1619}
1620
1621int
1623{
1624 int j = 0, retval, thisindex;
1626
1627 thisindex =
1628 _papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1629 if ( thisindex < PAPI_OK )
1630 return ( thisindex );
1631
1632 /* If it is a MPX EventSet, remove it from the multiplex data structure and
1633 this threads multiplex list */
1634
1635 if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1636 retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1637 if ( retval < PAPI_OK )
1638 return ( retval );
1639 } else
1640 /* Remove the events hardware dependent stuff from the EventSet */
1641 {
1642 if ( IS_PRESET(EventCode) ) {
1643 int preset_index = EventCode & PAPI_PRESET_AND_MASK;
1644
1645 /* Check if it's within the valid range */
1646 if ( ( preset_index < 0 ) ||
1647 ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
1648 return PAPI_EINVAL;
1649
1650 /* Check if event exists */
1651 if ( !_papi_hwi_presets[preset_index].count )
1652 return PAPI_ENOEVNT;
1653
1654 /* Remove the preset event. */
1655 for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
1656 j++ );
1657 retval = remove_native_events( ESI, ( int * )_papi_hwi_presets[preset_index].code, j );
1658 if ( retval != PAPI_OK )
1659 return ( retval );
1660 } else if ( IS_NATIVE(EventCode) ) {
1661 /* Check if native event exists */
1662 if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
1663 PAPI_OK )
1664 return PAPI_ENOEVNT;
1665
1666 /* Remove the native event. */
1667 retval = remove_native_events( ESI, &EventCode, 1 );
1668 if ( retval != PAPI_OK )
1669 return ( retval );
1670 } else if ( IS_USER_DEFINED( EventCode ) ) {
1671 int index = EventCode & PAPI_UE_AND_MASK;
1672
1673 if ( (index < 0) || (index >= user_defined_events_count) )
1674 return ( PAPI_EINVAL );
1675
1676 for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
1677 user_defined_events[index].code[j] != 0; j++ ) {
1678 retval = remove_native_events( ESI, ( int * )user_defined_events[index].code, j);
1679
1680 if ( retval != PAPI_OK )
1681 return ( retval );
1682 }
1683 } else
1684 return ( PAPI_ENOEVNT );
1685 }
1686 array = ESI->EventInfoArray;
1687
1688 /* Compact the Event Info Array list if it's not the last event */
1689 /* clear the newly empty slot in the array */
1690 for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
1691 array[thisindex] = array[thisindex + 1];
1692
1693
1694 array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
1695 for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
1696 array[thisindex].pos[j] = PAPI_NULL;
1697 array[thisindex].ops = NULL;
1698 array[thisindex].derived = NOT_DERIVED;
1699 ESI->NumberOfEvents--;
1700
1701 return ( PAPI_OK );
1702}
1703
1704int
1706 long long *values )
1707{
1708 INTDBG("ENTER: context: %p, ESI: %p, values: %p\n", context, ESI, values);
1709 int retval;
1710 long long *dp = NULL;
1711 int i, index;
1712
1713 retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state,
1714 &dp, ESI->state );
1715 if ( retval != PAPI_OK ) {
1716 INTDBG("EXIT: retval: %d\n", retval);
1717 return retval;
1718 }
1719
1720 /* This routine distributes hardware counters to software counters in the
1721 order that they were added. Note that the higher level
1722 EventInfoArray[i] entries may not be contiguous because the user
1723 has the right to remove an event.
1724 But if we do compaction after remove event, this function can be
1725 changed.
1726 */
1727
1728 for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
1729
1730 index = ESI->EventInfoArray[i].pos[0];
1731
1732 if ( index == -1 )
1733 continue;
1734
1735 INTDBG( "ESI->EventInfoArray: %p, pos[%d]: %d, dp[%d]: %lld, derived[%d]: %#x\n", ESI->EventInfoArray, i, index, index, dp[index], i, ESI->EventInfoArray[i].derived );
1736
1737 /* If this is not a derived event */
1738
1739 if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
1740 values[i] = dp[index];
1741 INTDBG( "value: %#llx\n", values[i] );
1742 } else { /* If this is a derived event */
1743 values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
1744#ifdef DEBUG
1745 if ( values[i] < ( long long ) 0 ) {
1746 INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
1747 }
1748 INTDBG( "derived value: %#llx \n", values[i] );
1749#endif
1750 }
1751 }
1752
1753 INTDBG("EXIT: PAPI_OK\n");
1754 return PAPI_OK;
1755}
1756
1757int
1759{
1760 int i, j, num_cntrs, retval;
1761 hwd_context_t *context;
1762 int EventCode;
1764 if ( !_papi_hwi_invalid_cmp( ESI->CmpIdx ) ) {
1765 num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1766
1767 for(i=0;i<num_cntrs;i++) {
1768
1769 EventCode=ESI->EventInfoArray[i].event_code;
1770
1771 /* skip if event not there */
1772 if ( EventCode == PAPI_NULL ) continue;
1773
1774 /* If it is a MPX EventSet, remove it from the multiplex */
1775 /* data structure and this thread's multiplex list */
1776
1777 if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1778 retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1779 if ( retval < PAPI_OK )
1780 return retval;
1781 } else {
1782
1783 native = ESI->NativeInfoArray;
1784
1785 /* clear out ESI->NativeInfoArray */
1786 /* do we really need to do this, seeing as we free() it later? */
1787
1788 for( j = 0; j < ESI->NativeCount; j++ ) {
1789 native[j].ni_event = -1;
1790 native[j].ni_position = -1;
1791 native[j].ni_owners = 0;
1792 /* native[j].ni_bits?? */
1793 }
1794 }
1795
1796 /* do we really need to do this, seeing as we free() it later? */
1797 ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
1798 for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
1799 ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
1800 }
1801 ESI->EventInfoArray[i].ops = NULL;
1803 }
1804
1805 context = _papi_hwi_get_context( ESI, NULL );
1806 /* calling with count of 0 equals a close? */
1807 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1808 NULL, 0, context);
1809 if (retval!=PAPI_OK) {
1810 return retval;
1811 }
1812 }
1813
1814 ESI->CmpIdx = -1;
1815 ESI->NumberOfEvents = 0;
1816 ESI->NativeCount = 0;
1817
1818 if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
1820
1821 if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
1823
1824 if ( ESI->ctl_state )
1825 papi_free( ESI->ctl_state );
1826
1827 if ( ESI->sw_stop )
1828 papi_free( ESI->sw_stop );
1829
1830 if ( ESI->hw_start )
1831 papi_free( ESI->hw_start );
1832
1833 if ( ESI->EventInfoArray )
1834 papi_free( ESI->EventInfoArray );
1835
1836 if ( ESI->NativeInfoArray )
1837 papi_free( ESI->NativeInfoArray );
1838
1839 if ( ESI->NativeBits )
1840 papi_free( ESI->NativeBits );
1841
1842 if ( ESI->overflow.deadline )
1843 papi_free( ESI->overflow.deadline );
1844
1845 if ( ESI->profile.prof )
1846 papi_free( ESI->profile.prof );
1847
1848 ESI->ctl_state = NULL;
1849 ESI->sw_stop = NULL;
1850 ESI->hw_start = NULL;
1851 ESI->EventInfoArray = NULL;
1852 ESI->NativeInfoArray = NULL;
1853 ESI->NativeBits = NULL;
1854
1855 memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
1856 memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
1857 memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
1858 memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
1859 memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
1860 memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
1861 memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
1862 memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
1863
1864 ESI->CpuInfo = NULL;
1865
1866 return PAPI_OK;
1867}
1868
1869int
1871{
1872 int retval, i, j = 0, *mpxlist = NULL;
1873 EventSetInfo_t *ESI = mpx->ESI;
1874 int flags = mpx->flags;
1875
1876 /* If there are any events in the EventSet,
1877 convert them to multiplex events */
1878
1879 if ( ESI->NumberOfEvents ) {
1880
1881 mpxlist =
1882 ( int * ) papi_malloc( sizeof ( int ) *
1883 ( size_t ) ESI->NumberOfEvents );
1884 if ( mpxlist == NULL )
1885 return ( PAPI_ENOMEM );
1886
1887 /* Build the args to MPX_add_events(). */
1888
1889 /* Remember the EventInfoArray can be sparse
1890 and the data can be non-contiguous */
1891
1892 for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
1893 if ( ESI->EventInfoArray[i].event_code !=
1894 ( unsigned int ) PAPI_NULL )
1895 mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
1896
1897 /* Resize the EventInfo_t array */
1898
1899 if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
1900 ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
1901 ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
1902 retval =
1903 MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
1904 ESI->domain.domain,
1905 ESI->granularity.granularity );
1906 if ( retval != PAPI_OK ) {
1907 papi_free( mpxlist );
1908 return ( retval );
1909 }
1910 }
1911
1912 papi_free( mpxlist );
1913 }
1914
1915 /* Update the state before initialization! */
1916
1917 ESI->state |= PAPI_MULTIPLEXING;
1918 if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
1919 ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
1921 ESI->multiplex.ns = ( int ) mpx->ns;
1922
1923 return ( PAPI_OK );
1924}
1925
1926#include "components_config.h"
1927
1928int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
1929
1930/*
1931 * Routine that initializes all available components.
1932 * A component is available if a pointer to its info vector
1933 * appears in the NULL terminated_papi_hwd table.
1934 * Modified to accept an arg: 0=do not init perf_event or
1935 * perf_event_uncore. 1=init ONLY perf_event or perf_event_uncore.
1936 */
1937int
1939{
1940 int retval, is_pe_peu, i = 0;
1941
1943 if ( retval != PAPI_OK ) {
1944 return retval;
1945 }
1946
1947 while ( _papi_hwd[i] ) {
1948 is_pe_peu = 0;
1949 if (strcmp(_papi_hwd[i]->cmp_info.name, "perf_event") == 0) is_pe_peu=1;
1950 if (strcmp(_papi_hwd[i]->cmp_info.name, "perf_event_uncore") == 0) is_pe_peu=1;
1952 if ( retval != PAPI_OK ) {
1953 return retval;
1954 }
1955
1956 /* We can be disabled by user before init */
1957 if (!_papi_hwd[i]->cmp_info.disabled && (PE_OR_PEU == is_pe_peu)) {
1958 retval = _papi_hwd[i]->init_component( i );
1959
1960 /* Do some sanity checking */
1961 if (retval==PAPI_OK) {
1962 if (_papi_hwd[i]->cmp_info.num_cntrs >
1963 _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
1964 fprintf(stderr,"Warning! num_cntrs %d is more than num_mpx_cntrs %d for component %s\n",
1965 _papi_hwd[i]->cmp_info.num_cntrs,
1966 _papi_hwd[i]->cmp_info.num_mpx_cntrs,
1967 _papi_hwd[i]->cmp_info.name);
1968 }
1969
1970 }
1971 }
1972
1973 i++;
1974 }
1975 return PAPI_OK;
1976}
1977
1978/* Machine info struct initialization using defaults */
1979/* See _papi_mdi definition in papi_internal.h */
1980
1981int
1983{
1984
1985 int retval;
1986
1987 memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
1988
1989 memset( _papi_hwi_using_signal,0x0,sizeof( _papi_hwi_using_signal ));
1990
1991 /* Global struct to maintain EventSet mapping */
1993 if ( retval != PAPI_OK ) {
1994 return retval;
1995 }
1996
1997 _papi_hwi_system_info.pid = 0; /* Process identifier */
1998
1999 /* PAPI_hw_info_t struct */
2000 memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
2001 return PAPI_OK;
2002}
2003
2004void
2006{
2007 int i = 0;
2009
2011
2013
2014 for( i = 0; i < num_native_events; i++){
2016 }
2017
2018 free(_papi_native_events);
2019 _papi_native_events = NULL; // In case a new library init is done.
2020 num_native_events=0; // ..
2021 num_native_chunks=0; // ..
2022
2024
2027 0x00, sizeof ( DynamicArray_t ) );
2028
2030
2033 }
2034 memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
2035
2036}
2037
2038
2039
2040void
2041_papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
2042 void *context )
2043{
2044 /* This function is not used and shouldn't be called. */
2045 ( void ) EventSet; /*unused */
2046 ( void ) address; /*unused */
2047 ( void ) overflow_vector; /*unused */
2048 ( void ) context; /*unused */
2049 return;
2050}
2051
2052static long long
2053handle_derived_add( int *position, long long *from )
2054{
2055 int pos, i;
2056 long long retval = 0;
2057
2058 i = 0;
2059 while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
2060 pos = position[i++];
2061 if ( pos == PAPI_NULL )
2062 break;
2063 INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
2064 retval += from[pos];
2065 }
2066 return ( retval );
2067}
2068
2069static long long
2070handle_derived_subtract( int *position, long long *from )
2071{
2072 int pos, i;
2073 long long retval = from[position[0]];
2074
2075 i = 1;
2076 while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
2077 pos = position[i++];
2078 if ( pos == PAPI_NULL )
2079 break;
2080 INTDBG( "Compound event, subtracting pos=%d %lld from %lld\n", pos,
2081 from[pos], retval );
2082 retval -= from[pos];
2083 }
2084 return ( retval );
2085}
2086
2087static long long
2088units_per_second( long long units, long long cycles )
2089{
2090 return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
2091 (long long) 1000000 ) / cycles );
2092}
2093
2094static long long
2095handle_derived_ps( int *position, long long *from )
2096{
2097 return ( units_per_second( from[position[1]], from[position[0]] ) );
2098}
2099static long long
2100handle_derived_add_ps( int *position, long long *from )
2101{
2102 long long tmp = handle_derived_add( position + 1, from );
2103 return ( units_per_second( tmp, from[position[0]] ) );
2104}
2105
2106/* this function implement postfix calculation, it reads in a string where I use:
2107 | as delimiter
2108 N2 indicate No. 2 native event in the derived preset
2109 +, -, *, / as operator
2110 # as MHZ(million hz) got from _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
2111
2112 Haihang (you@cs.utk.edu)
2113*/
2114 static long long
2115 _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
2116 {
2117 char *point = evi->ops, operand[16];
2119 int i, val, top = 0;
2120
2121 INTDBG("ENTER: evi: %p, evi->ops: %p (%s), evi->pos[0]: %d, evi->pos[1]: %d, hw_counter: %p (%lld %lld)\n",
2122 evi, evi->ops, evi->ops, evi->pos[0], evi->pos[1], hw_counter, hw_counter[0], hw_counter[1]);
2123
2124 memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
2125
2126 while ( *point != '\0' ) {
2127 if ( *point == '|' ) { /* consume '|' characters */
2128 point++;
2129 } else if ( *point == 'N' ) { /* to get count for each native event */
2130 point++;
2131 i = 0;
2132 while ( isdigit(*point) ) {
2133 assert(i<16);
2134 operand[i] = *point;
2135 point++;
2136 i++;
2137 }
2138 assert(0<i && i<16);
2139 operand[i] = '\0';
2140 val = atoi( operand );
2141 assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2142 assert( 0 <= val && val < PAPI_EVENTS_IN_DERIVED_EVENT );
2143 stack[top] = ( double ) hw_counter[evi->pos[val]];
2144 top++;
2145 } else if ( *point == '#' ) { /* to get mhz */
2146 point++;
2147 assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2149 top++;
2150 } else if ( isdigit( *point ) ) {
2151 i = 0;
2152 while ( isdigit(*point) ) {
2153 assert(i<16);
2154 operand[i] = *point;
2155 point++;
2156 i++;
2157 }
2158 assert(0<i && i<16);
2159 operand[i] = '\0';
2160 assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2161 stack[top] = atoi( operand );
2162 top++;
2163 } else if ( *point == '+' ) { /* + calculation */
2164 point++;
2165 assert(top >= 2);
2166 stack[top - 2] += stack[top - 1];
2167 top--;
2168 } else if ( *point == '-' ) { /* - calculation */
2169 point++;
2170 assert(top >= 2);
2171 stack[top - 2] -= stack[top - 1];
2172 top--;
2173 } else if ( *point == '*' ) { /* * calculation */
2174 point++;
2175 assert(top >= 2);
2176 stack[top - 2] *= stack[top - 1];
2177 top--;
2178 } else if ( *point == '/' ) { /* / calculation */
2179 point++;
2180 assert(top >= 2);
2181 /* FIXME should handle runtime divide by zero */
2182 stack[top - 2] /= stack[top - 1];
2183 top--;
2184 } else { /* flag an error parsing the preset */
2185 PAPIERROR( "BUG! Unable to parse \"%s\"", evi->ops );
2186 return ( long long ) stack[0];
2187 }
2188 }
2189 assert(top == 1);
2190 INTDBG("EXIT: stack[0]: %lld\n", (long long)stack[0]);
2191 return ( long long ) stack[0];
2192 }
2193
2194static long long
2195handle_derived( EventInfo_t * evi, long long *from )
2196{
2197 INTDBG("ENTER: evi: %p, evi->derived: %d, from: %p\n", evi, evi->derived, from);
2198 switch ( evi->derived ) {
2199 case DERIVED_ADD:
2200 return ( handle_derived_add( evi->pos, from ) );
2201 case DERIVED_ADD_PS:
2202 return ( handle_derived_add_ps( evi->pos, from ) );
2203 case DERIVED_SUB:
2204 return ( handle_derived_subtract( evi->pos, from ) );
2205 case DERIVED_PS:
2206 return ( handle_derived_ps( evi->pos, from ) );
2207 case DERIVED_POSTFIX:
2208 return ( _papi_hwi_postfix_calc( evi, from ) );
2209 case DERIVED_CMPD: /* This type has existed for a long time, but was never implemented.
2210 Probably because its a no-op. However, if it's in a header, it
2211 should be supported. As I found out when I implemented it in
2212 Pentium 4 for testing...dkt */
2213 return ( from[evi->pos[0]] );
2214 default:
2215 PAPIERROR( "BUG! Unknown derived command %d, returning 0", evi->derived );
2216 INTDBG("EXIT: Unknown derived command %d\n", evi->derived);
2217 return ( ( long long ) 0 );
2218 }
2219}
2220
2221
2222/* table matching derived types to derived strings.
2223 used by get_info, encode_event, xml translator
2224*/
2226 {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
2227 {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
2228 {DERIVED_PS, "DERIVED_PS",
2229 "Divide by the cycle counter and convert to seconds"},
2230 {DERIVED_ADD_PS, "DERIVED_ADD_PS",
2231 "Add 2 counters then divide by the cycle counter and xl8 to secs."},
2232 {DERIVED_CMPD, "DERIVED_CMPD",
2233 "Event lives in first counter but takes 2 or more codes"},
2234 {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
2235 {DERIVED_POSTFIX, "DERIVED_POSTFIX",
2236 "Process counters based on specified postfix string"},
2237 {DERIVED_INFIX, "DERIVED_INFIX",
2238 "Process counters based on specified infix string"},
2239 {-1, NULL, NULL}
2240};
2241
2242/* _papi_hwi_derived_type:
2243 Helper routine to extract a derived type from a derived string
2244 returns type value if found, otherwise returns -1
2245*/
2246int
2247_papi_hwi_derived_type( char *tmp, int *code )
2248{
2249 int i = 0;
2250 while ( _papi_hwi_derived[i].name != NULL ) {
2251 if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
2252 *code = _papi_hwi_derived[i].value;
2253 return PAPI_OK;
2254 }
2255 i++;
2256 }
2257 INTDBG( "Invalid derived string %s\n", tmp );
2258 return PAPI_EINVAL;
2259}
2260
2261
2262/* _papi_hwi_derived_string:
2263 Helper routine to extract a derived string from a derived type
2264 copies derived type string into derived if found,
2265 otherwise returns PAPI_EINVAL
2266*/
2267static int
2268_papi_hwi_derived_string( int type, char *derived, int len )
2269{
2270 int j;
2271
2272 for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
2273 if ( _papi_hwi_derived[j].value == type ) {
2274 strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
2275 len );
2276 return PAPI_OK;
2277 }
2278 }
2279 INTDBG( "Invalid derived type %d\n", type );
2280 return PAPI_EINVAL;
2281}
2282
2283
2284/* _papi_hwi_get_preset_event_info:
2285 Assumes EventCode contains a valid preset code.
2286 But defensive programming says check for NULL pointers.
2287 Returns a filled in PAPI_event_info_t structure containing
2288 descriptive strings and values for the specified preset event.
2289*/
2290int
2292{
2293 INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2294
2295 int i = EventCode & PAPI_PRESET_AND_MASK;
2296 unsigned int j;
2297
2298 if ( _papi_hwi_presets[i].symbol ) { /* if the event is in the preset table */
2299 // since we are setting the whole structure to zero the strncpy calls below will
2300 // be leaving NULL terminates strings as long as they copy 1 less byte than the
2301 // buffer size of the field.
2302 memset( info, 0, sizeof ( PAPI_event_info_t ) );
2303
2304 info->event_code = ( unsigned int ) EventCode;
2305 strncpy( info->symbol, _papi_hwi_presets[i].symbol,
2306 sizeof(info->symbol)-1);
2307
2308 if ( _papi_hwi_presets[i].short_descr != NULL )
2309 strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
2310 sizeof ( info->short_descr )-1 );
2311
2312 if ( _papi_hwi_presets[i].long_descr != NULL )
2313 strncpy( info->long_descr, _papi_hwi_presets[i].long_descr,
2314 sizeof ( info->long_descr )-1 );
2315
2317 info->count = _papi_hwi_presets[i].count;
2318
2320 info->derived, sizeof ( info->derived )-1 );
2321
2322 if ( _papi_hwi_presets[i].postfix != NULL )
2323 strncpy( info->postfix, _papi_hwi_presets[i].postfix,
2324 sizeof ( info->postfix )-1 );
2325
2326 for(j=0;j < info->count; j++) {
2327 info->code[j]=_papi_hwi_presets[i].code[j];
2328 strncpy(info->name[j], _papi_hwi_presets[i].name[j],
2329 sizeof(info->name[j])-1);
2330 }
2331
2332 if ( _papi_hwi_presets[i].note != NULL ) {
2333 strncpy( info->note, _papi_hwi_presets[i].note,
2334 sizeof ( info->note )-1 );
2335 }
2336
2337 return PAPI_OK;
2338 } else {
2339 return PAPI_ENOEVNT;
2340 }
2341}
2342
2343
2344/* _papi_hwi_get_user_event_info:
2345 Assumes EventCode contains a valid user event code.
2346 But defensive programming says check for NULL pointers.
2347 Returns a filled in PAPI_event_info_t structure containing
2348 descriptive strings and values for the specified preset event.
2349*/
2350int
2352{
2353 INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2354
2355 unsigned int i = EventCode & PAPI_UE_AND_MASK;
2356 unsigned int j;
2357
2358 // if event code not in valid range, return error
2359 if (i >= PAPI_MAX_USER_EVENTS) {
2360 INTDBG("EXIT: Invalid event index: %d, max value is: %d\n", i, PAPI_MAX_USER_EVENTS - 1);
2361 return( PAPI_ENOEVNT );
2362 }
2363
2364 if ( user_defined_events[i].symbol == NULL) { /* if the event is in the preset table */
2365 INTDBG("EXIT: Event symbol for this event is NULL\n");
2366 return PAPI_ENOEVNT;
2367 }
2368
2369 /* set whole structure to 0 */
2370 memset( info, 0, sizeof ( PAPI_event_info_t ) );
2371
2372 info->event_code = ( unsigned int ) EventCode;
2373 strncpy( info->symbol, user_defined_events[i].symbol,
2374 sizeof(info->symbol)-1);
2375
2376 if ( user_defined_events[i].short_descr != NULL )
2378 sizeof(info->short_descr)-1);
2379
2380 if ( user_defined_events[i].long_descr != NULL )
2381 strncpy( info->long_descr, user_defined_events[i].long_descr,
2382 sizeof(info->long_descr)-1);
2383
2384// info->event_type = user_defined_events[i].event_type;
2386
2388 info->derived, sizeof(info->derived)-1);
2389
2390 if ( user_defined_events[i].postfix != NULL )
2391 strncpy( info->postfix, user_defined_events[i].postfix,
2392 sizeof(info->postfix)-1);
2393
2394 for(j=0;j < info->count; j++) {
2395 info->code[j]=user_defined_events[i].code[j];
2396 INTDBG("info->code[%d]: %#x\n", j, info->code[j]);
2397 strncpy(info->name[j], user_defined_events[i].name[j], sizeof(info->name[j])-1);
2398 }
2399
2400 if ( user_defined_events[i].note != NULL ) {
2401 strncpy( info->note, user_defined_events[i].note, sizeof(info->note)-1);
2402 }
2403
2404 INTDBG("EXIT: PAPI_OK: event_code: %#x, symbol: %s, short_desc: %s, long_desc: %s\n", info->event_code, info->symbol, info->short_descr, info->long_descr);
2405 return PAPI_OK;
2406}
2407
2408
2409/* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
2410 Used to enumerate the entire array, e.g. for native_avail.c */
2411int
2412_papi_hwi_query_native_event( unsigned int EventCode )
2413{
2414 INTDBG("ENTER: EventCode: %#x\n", EventCode);
2415 char name[PAPI_HUGE_STR_LEN]; /* probably overkill, */
2416 /* but should always be big enough */
2417 int cidx;
2418 int nevt_code;
2419
2420 cidx = _papi_hwi_component_index( EventCode );
2421 if (cidx<0) {
2422 INTDBG("EXIT: PAPI_ENOCMP\n");
2423 return PAPI_ENOCMP;
2424 }
2425
2426 // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2427 _papi_hwi_set_papi_event_code(EventCode, 0);
2428
2429 if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2430 INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2431 return nevt_code;
2432 }
2433 int ret = _papi_hwd[cidx]->ntv_code_to_name( (unsigned int)nevt_code, name, sizeof(name));
2434
2435 INTDBG("EXIT: ret: %d\n", ret);
2436 return (ret);
2437}
2438
2439/* Converts an ASCII name into a native event code usable by other routines
2440 Returns code = 0 and PAPI_OK if name not found.
2441 This allows for sparse native event arrays */
2442int
2443_papi_hwi_native_name_to_code( const char *in, int *out )
2444{
2445 INTDBG("ENTER: in: %s, out: %p\n", in, out);
2446
2447 int retval = PAPI_ENOEVNT;
2448 char name[PAPI_HUGE_STR_LEN]; /* make sure it's big enough */
2449
2450 unsigned int i;
2451 int cidx;
2452 char *full_event_name;
2453
2454 if (in == NULL) {
2455 INTDBG("EXIT: PAPI_EINVAL\n");
2456 return PAPI_EINVAL;
2457 }
2458
2459 full_event_name = strdup(in);
2460
2462
2463 // look in each component
2464 for(cidx=0; cidx < papi_num_components; cidx++) {
2465
2466 if (_papi_hwd[cidx]->cmp_info.disabled &&
2467 _papi_hwd[cidx]->cmp_info.disabled != PAPI_EDELAY_INIT)
2468 continue;
2469
2470 // if this component does not support the pmu
2471 // which defines this event, no need to call it
2472 if (is_supported_by_component(cidx, full_event_name) == 0) {
2473 continue;
2474 }
2475
2476 INTDBG("cidx: %d, name: %s, event: %s\n",
2477 cidx, _papi_hwd[cidx]->cmp_info.name, in);
2478
2479 // show that we do not have an event code yet
2480 // (the component may create one and update this info)
2481 // this also clears any values left over from a previous call
2483
2484
2485 // if component has a ntv_name_to_code function, use it to get event code
2486 if (_papi_hwd[cidx]->ntv_name_to_code != NULL) {
2487 // try and get this events event code
2488 retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
2489 if (retval==PAPI_OK) {
2490 *out = _papi_hwi_native_to_eventcode(cidx, *out, -1, in);
2491 free (full_event_name);
2492 INTDBG("EXIT: PAPI_OK event: %s code: %#x\n", in, *out);
2493 return PAPI_OK;
2494 }
2495 } else {
2496 // force the code through the work around
2497 retval = PAPI_ECMP;
2498 }
2499
2500 /* If not implemented, work around */
2501 if ( retval==PAPI_ECMP) {
2502 i = 0;
2503 retval = _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
2504 if (retval != PAPI_OK) {
2505 free (full_event_name);
2506 INTDBG("EXIT: retval: %d\n", retval);
2507 return retval;
2508 }
2509
2510// _papi_hwi_lock( INTERNAL_LOCK );
2511
2512 do {
2513 // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2515 retval = _papi_hwd[cidx]->ntv_code_to_name(i, name, sizeof(name));
2516 /* printf("%#x\nname =|%s|\ninput=|%s|\n", i, name, in); */
2517 if ( retval == PAPI_OK && in != NULL) {
2518 if ( strcasecmp( name, in ) == 0 ) {
2520 free (full_event_name);
2521 INTDBG("EXIT: PAPI_OK, event: %s, code: %#x\n", in, *out);
2522 return PAPI_OK;
2523 }
2525 } else {
2526 *out = 0;
2528 break;
2529 }
2530 } while ( ( _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_EVENTS ) == PAPI_OK ) );
2531
2532// _papi_hwi_unlock( INTERNAL_LOCK );
2533 }
2534 }
2535
2536 free (full_event_name);
2537 INTDBG("EXIT: retval: %d\n", retval);
2538
2539 return retval;
2540}
2541
2542/* Returns event name based on native event code.
2543 Returns NULL if name not found */
2544int
2545_papi_hwi_native_code_to_name( unsigned int EventCode,
2546 char *hwi_name, int len )
2547{
2548 INTDBG("ENTER: EventCode: %#x, hwi_name: %p, len: %d\n", EventCode, hwi_name, len);
2549 int cidx;
2550 int retval;
2551 int nevt_code;
2552
2553 cidx = _papi_hwi_component_index( EventCode );
2554 if (cidx<0) return PAPI_ENOEVNT;
2555
2556 if ( EventCode & PAPI_NATIVE_MASK ) {
2557 // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2558 _papi_hwi_set_papi_event_code(EventCode, 0);
2559
2560 if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2561 INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2562 return nevt_code;
2563 }
2564 if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2565 (unsigned int)nevt_code,
2566 hwi_name, len) ) == PAPI_OK ) {
2567 retval = _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name,
2568 hwi_name, hwi_name, len);
2569 INTDBG("EXIT: retval: %d\n", retval);
2570 return retval;
2571 }
2572 INTDBG("EXIT: retval: %d\n", retval);
2573 return (retval);
2574 }
2575 INTDBG("EXIT: PAPI_ENOEVNT\n");
2576 return PAPI_ENOEVNT;
2577}
2578
2579
2580
2581/* The native event equivalent of PAPI_get_event_info */
2582int
2583_papi_hwi_get_native_event_info( unsigned int EventCode,
2584 PAPI_event_info_t *info )
2585{
2586 INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2587 int retval;
2588 int cidx;
2589 int nevt_code;
2590
2591 cidx = _papi_hwi_component_index( EventCode );
2592 if (cidx<0) return PAPI_ENOCMP;
2593
2594 if (_papi_hwd[cidx]->cmp_info.disabled &&
2595 _papi_hwd[cidx]->cmp_info.disabled != PAPI_EDELAY_INIT)
2596 return PAPI_ENOCMP;
2597
2598 if ( EventCode & PAPI_NATIVE_MASK ) {
2599 // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2600 _papi_hwi_set_papi_event_code(EventCode, 0);
2601
2602 /* clear the event info */
2603 memset( info, 0, sizeof ( PAPI_event_info_t ) );
2604 info->event_code = ( unsigned int ) EventCode;
2605 info->component_index = (unsigned int) cidx;
2606 retval = _papi_hwd[cidx]->ntv_code_to_info(
2607 _papi_hwi_eventcode_to_native(EventCode), info);
2608
2609 /* If component error, it's missing the ntv_code_to_info vector */
2610 /* so we'll have to fake it. */
2611 if ( retval == PAPI_ECMP ) {
2612
2613
2614 INTDBG("missing NTV_CODE_TO_INFO, faking\n");
2615 /* Fill in the info structure */
2616
2617 if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2618 INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2619 return nevt_code;
2620 }
2621 if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2622 (unsigned int)nevt_code,
2623 info->symbol,
2624 sizeof(info->symbol)) ) == PAPI_OK ) {
2625
2626 } else {
2627 INTDBG("EXIT: retval: %d\n", retval);
2628 return retval;
2629 }
2630
2631 if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) <0) {
2632 INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2633 return nevt_code;
2634 }
2635 retval = _papi_hwd[cidx]->ntv_code_to_descr(
2636 (unsigned int)nevt_code,
2637 info->long_descr,
2638 sizeof ( info->long_descr));
2639 if (retval!=PAPI_OK) {
2640 INTDBG("Failed ntv_code_to_descr()\n");
2641 }
2642
2643 }
2645 _papi_hwd[cidx]->cmp_info.short_name,
2646 info->symbol,
2647 info->symbol,
2648 sizeof(info->symbol) );
2649
2650 INTDBG("EXIT: retval: %d\n", retval);
2651 return retval;
2652 }
2653
2654 INTDBG("EXIT: PAPI_ENOEVNT\n");
2655 return PAPI_ENOEVNT;
2656}
2657
2660{
2662 EventSetInfo_t *set;
2663
2664 if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
2665 return ( NULL );
2666
2667 set = map->dataSlotArray[eventset];
2668#ifdef DEBUG
2669 if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
2670 ( set->master->tid != _papi_hwi_thread_id_fn( ) ) )
2671 return ( NULL );
2672#endif
2673
2674 return ( set );
2675}
2676
2677int
2679{
2680 /* Are we multiplexing at all */
2681 if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
2682 return 0;
2683 }
2684
2685 /* Does the component support kernel multiplexing */
2686 if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
2687 /* Have we forced software multiplexing */
2688 if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
2689 return 1;
2690 }
2691 /* Nope, using hardware multiplexing */
2692 return 0;
2693 }
2694
2695 /* We are multiplexing but the component does not support hardware */
2696
2697 return 1;
2698
2699}
2700
2703{
2704 INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
2705 int dirty_ctx;
2706 hwd_context_t *ctx=NULL;
2707
2708 /* assume for now the control state is clean (last updated by this ESI) */
2709 dirty_ctx = 0;
2710
2711 /* get a context pointer based on if we are counting for a thread or for a cpu */
2712 if (ESI->state & PAPI_CPU_ATTACHED) {
2713 /* use cpu context */
2714 ctx = ESI->CpuInfo->context[ESI->CmpIdx];
2715
2716 /* if the user wants to know if the control state was last set by the same event set, tell him */
2717 if (is_dirty != NULL) {
2718 if (ESI->CpuInfo->from_esi != ESI) {
2719 dirty_ctx = 1;
2720 }
2721 *is_dirty = dirty_ctx;
2722 }
2723 ESI->CpuInfo->from_esi = ESI;
2724
2725 } else {
2726
2727 /* use thread context */
2728 ctx = ESI->master->context[ESI->CmpIdx];
2729
2730 /* if the user wants to know if the control state was last set by the same event set, tell him */
2731 if (is_dirty != NULL) {
2732 if (ESI->master->from_esi != ESI) {
2733 dirty_ctx = 1;
2734 }
2735 *is_dirty = dirty_ctx;
2736 }
2737 ESI->master->from_esi = ESI;
2738
2739 }
2740 return( ctx );
2741}
2742
2743static int
2745{
2746 int cidx;
2747
2748 for (cidx = 0; cidx < papi_num_components; ++cidx) {
2749 if (strcmp(_papi_hwd[cidx]->cmp_info.name, name) == 0) {
2750 break;
2751 }
2752 }
2753
2754 return cidx;
2755}
2756
2757int
2758_papi_hwi_enum_dev_type(int enum_modifier, void **handle)
2759{
2762 args.query.enumerate.modifier = enum_modifier;
2763
2764 int cidx = get_component_index("sysdetect");
2765 assert(cidx < papi_num_components);
2766
2767 return _papi_hwd[cidx]->user(0, &args, handle);
2768}
2769
2770int
2772{
2775 args.query.dev_type.handle = handle;
2776 args.query.dev_type.attr = attr;
2777
2778 int cidx = get_component_index("sysdetect");
2779 assert(cidx < papi_num_components);
2780
2781 return _papi_hwd[cidx]->user(0, &args, value);
2782}
2783
2784int
2785_papi_hwi_get_dev_attr(void *handle, int id, PAPI_dev_attr_e attr, void *value)
2786{
2789 args.query.dev.handle = handle;
2790 args.query.dev.id = id;
2791 args.query.dev.attr = attr;
2792
2793 int cidx = get_component_index("sysdetect");
2794 assert(cidx < papi_num_components);
2795
2796 return _papi_hwd[cidx]->user(0, &args, value);
2797}
static papi_handle_t handle
Definition: Gamum.c:21
volatile int result
double tmp
int i
papi_os_vector_t _papi_os_vector
Definition: aix.c:1288
int errno
static long count
Prefixes a component's name to each of its events.
Strip off cmp_name::: from an event name.
struct papi_vectors * _papi_hwd[]
int _papi_hwi_shutdown_cpu(CpuInfo_t *cpu)
Definition: cpus.c:308
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
char * evt_name(evstock *stock, int index)
Definition: eventstock.c:193
int _papi_hwi_using_signal[PAPI_NSIG]
Definition: extras.c:365
#define PAPI_CPU_ATTACH
Definition: f90papi.h:19
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_EBUG
Definition: f90papi.h:176
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_NOT_INITED
Definition: f90papi.h:231
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_NULL
Definition: f90papi.h:78
#define PAPI_QUIET
Definition: f90papi.h:132
#define PAPI_VERB_ECONT
Definition: f90papi.h:164
#define PAPI_ECMP_DISABLED
Definition: f90papi.h:17
#define PAPI_ECNFLCT
Definition: f90papi.h:234
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EDELAY_INIT
Definition: f90papi.h:271
#define PAPI_INIT_SLOTS
Definition: f90papi.h:262
#define PAPI_ECOUNT
Definition: f90papi.h:195
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_PMU_MAX
Definition: f90papi.h:101
#define PAPI_MULTIPLEXING
Definition: f90papi.h:148
#define PAPI_EMISC
Definition: f90papi.h:122
#define PAPI_CPU_ATTACHED
Definition: f90papi.h:96
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_ENOCMP
Definition: f90papi.h:79
#define PAPI_MULTIPLEX_FORCE_SW
Definition: f90papi.h:62
#define PAPI_ECMP
Definition: f90papi.h:214
#define PAPI_OVERFLOWING
Definition: f90papi.h:240
#define PAPI_OVERFLOW_HARDWARE
Definition: f90papi.h:157
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_STOPPED
Definition: f90papi.h:158
#define PAPI_VERB_ESTOP
Definition: f90papi.h:200
#define PAPI_HUGE_STR_LEN
Definition: f90papi.h:120
PAPI_dev_type_attr_e
Definition: papi.h:1049
PAPI_dev_attr_e
Definition: papi.h:1068
static int EventSet
Definition: init_fini.c:8
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
static struct timeval start
uint16_t type
#define PAPI_NATIVE_AND_MASK
#define PAPI_MAX_USER_EVENTS
#define PAPI_PRESET_AND_MASK
#define PAPI_NATIVE_MASK
#define PAPI_MAX_PRESET_EVENTS
#define PAPI_UE_AND_MASK
Return codes and api definitions.
int(* PAPI_debug_handler_t)(int code)
Definition: papi.h:674
#define IS_USER_DEFINED(EventCode)
Definition: papi.h:232
#define IS_NATIVE(EventCode)
Definition: papi.h:230
#define IS_PRESET(EventCode)
Definition: papi.h:231
hwi_presets_t _papi_hwi_presets[PAPI_MAX_PRESET_EVENTS]
#define INTDBG(format, args...)
Definition: papi_debug.h:66
unsigned long int(* _papi_hwi_thread_id_fn)(void)
Definition: threads.c:42
#define ISLEVEL(a)
Definition: papi_debug.h:55
#define DEBUG_THREADS
Definition: papi_debug.h:30
long unsigned int size_t
__gnuc_va_list va_list
FILE * stderr
static void _papi_hwi_cleanup_errors()
int _papi_hwi_enum_dev_type(int enum_modifier, void **handle)
int _papi_hwi_get_user_event_info(int EventCode, PAPI_event_info_t *info)
int init_level
Definition: papi_internal.c:53
static long long handle_derived_ps(int *position, long long *from)
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
int _papi_hwi_get_dev_type_attr(void *handle, PAPI_dev_type_attr_e attr, void *value)
int _papi_hwi_native_to_eventcode(int cidx, int event_code, int ntv_idx, const char *event_name)
int _papi_hwi_add_event(EventSetInfo_t *ESI, int EventCode)
static int expand_dynamic_array(DynamicArray_t *DA)
void _papi_hwi_shutdown_global_internal(void)
int _papi_hwi_get_native_event_info(unsigned int EventCode, PAPI_event_info_t *info)
#define NATIVE_EVENT_CHUNKSIZE
Definition: papi_internal.c:69
static int num_native_events
Definition: papi_internal.c:81
void _papi_hwi_free_EventSet(EventSetInfo_t *ESI)
void _papi_hwi_dummy_handler(int EventSet, void *address, long long overflow_vector, void *context)
static int num_native_chunks
Definition: papi_internal.c:82
static int update_overflow(EventSetInfo_t *ESI)
void PAPIERROR(char *format,...)
THREAD_LOCAL_STORAGE_KEYWORD int _papi_hl_events_running
Definition: papi_internal.c:63
static int remove_native_events(EventSetInfo_t *ESI, int *nevt, int size)
hwi_presets_t user_defined_events[PAPI_MAX_USER_EVENTS]
Definition: papi_internal.c:59
static long long handle_derived_add(int *position, long long *from)
int _papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
int _papi_hwi_native_code_to_name(unsigned int EventCode, char *hwi_name, int len)
void _papi_hwi_init_errors(void)
int _papi_hwi_derived_type(char *tmp, int *code)
static int add_native_fail_clean(EventSetInfo_t *ESI, int nevt)
char * papi_event_string
Definition: papi_internal.c:91
static long long handle_derived_subtract(int *position, long long *from)
int _papi_hwi_eventcode_to_native(int event_code)
int _papi_hwi_errno
Definition: papi_internal.c:57
char * _papi_hwi_get_papi_event_string()
int _papi_hwi_error_level
Definition: papi_internal.c:54
void _papi_hwi_free_papi_event_string()
static int is_supported_by_component(int cidx, char *event_name)
static int _papi_hwi_derived_string(int type, char *derived, int len)
static long long units_per_second(long long units, long long cycles)
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
int _papi_hwi_num_errors
Definition: papi_internal.c:58
int _papi_hwi_lookup_EventCodeIndex(const EventSetInfo_t *ESI, unsigned int EventCode)
int _papi_hwi_init_global(int PE_OR_PEU)
hwd_context_t * _papi_hwi_get_context(EventSetInfo_t *ESI, int *is_dirty)
int _papi_hwi_get_dev_attr(void *handle, int id, PAPI_dev_attr_e attr, void *value)
int _papi_hwi_init_global_internal(void)
PAPI_debug_handler_t _papi_hwi_debug_handler
Definition: papi_internal.c:55
static int add_EventSet(EventSetInfo_t *ESI, ThreadInfo_t *master)
int _papi_hwi_remove_EventSet(EventSetInfo_t *ESI)
int _papi_hwi_native_name_to_code(const char *in, int *out)
int _papi_hwi_create_eventset(int *EventSet, ThreadInfo_t *handle)
int _papi_hwi_component_index(int event_code)
static long long _papi_hwi_postfix_calc(EventInfo_t *evi, long long *hw_counter)
static long long handle_derived_add_ps(int *position, long long *from)
static int num_error_chunks
Definition: papi_internal.c:85
int user_defined_events_count
Definition: papi_internal.c:60
static int event_already_in_eventset(EventSetInfo_t *ESI, int papi_event)
int _papi_hwi_get_preset_event_info(int EventCode, PAPI_event_info_t *info)
static int _papi_hwi_find_native_event(int cidx, int event, const char *event_name)
unsigned int _papi_hwi_get_papi_event_code()
int _papi_hwi_convert_eventset_to_multiplex(_papi_int_multiplex_t *mpx)
static int create_EventSet(EventSetInfo_t **here)
static long long handle_derived(EventInfo_t *evi, long long *from)
void _papi_hwi_set_papi_event_string(const char *event_string)
Definition: papi_internal.c:93
static int default_debug_handler(int errorCode)
static int get_component_index(const char *name)
THREAD_LOCAL_STORAGE_KEYWORD int _papi_rate_events_running
Definition: papi_internal.c:62
static int get_free_EventCodeIndex(const EventSetInfo_t *ESI, unsigned int EventCode)
void PAPIWARN(char *format,...)
int _papi_hwi_read(hwd_context_t *context, EventSetInfo_t *ESI, long long *values)
char ** _papi_errlist
Definition: papi_internal.c:84
int _papi_hwi_assign_eventset(EventSetInfo_t *ESI, int cidx)
int papi_num_components
static int _papi_hwi_lookup_error(char *error)
int _papi_hwi_remove_event(EventSetInfo_t *ESI, int EventCode)
static int _papi_hwi_add_native_event(int cidx, int ntv_event, int ntv_idx, const char *event_name)
static int add_native_events(EventSetInfo_t *ESI, unsigned int *nevt, int size, EventInfo_t *out)
static int EventInfoArrayLength(const EventSetInfo_t *ESI)
int _papi_hwi_invalid_cmp(int cidx)
static int allocate_eventset_map(DynamicArray_t *map)
void _papi_hwi_set_papi_event_code(unsigned int event_code, int update_flag)
static const hwi_describe_t _papi_hwi_derived[]
int _papi_hwi_cleanup_eventset(EventSetInfo_t *ESI)
int _papi_hwi_get_ntv_idx(unsigned int papi_evt_code)
int _papi_hwi_query_native_event(unsigned int EventCode)
static struct native_event_info * _papi_native_events
Definition: papi_internal.c:80
void _papi_hwi_map_events_to_native(EventSetInfo_t *ESI)
#define PAPI_EVENTS_IN_DERIVED_EVENT
#define DERIVED_POSTFIX
Definition: papi_internal.h:74
#define DERIVED_INFIX
Definition: papi_internal.h:75
#define NOT_DERIVED
Definition: papi_internal.h:68
#define INTERNAL_LOCK
Definition: papi_internal.h:85
#define DERIVED_SUB
Definition: papi_internal.h:73
@ PAPI_SYSDETECT_QUERY__DEV_TYPE_ENUM
@ PAPI_SYSDETECT_QUERY__DEV_ATTR
@ PAPI_SYSDETECT_QUERY__DEV_TYPE_ATTR
#define PAPI_ERROR_CODE_str
Definition: papi_internal.h:40
#define DERIVED_PS
Definition: papi_internal.h:70
#define DERIVED_ADD
Definition: papi_internal.h:69
#define DERIVED_ADD_PS
Definition: papi_internal.h:71
#define DERIVED_CMPD
Definition: papi_internal.h:72
static double array[ARRAYSIZE]
Definition: papi_l1_dca.c:23
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_malloc(a)
Definition: papi_memory.h:34
#define papi_realloc(a, b)
Definition: papi_memory.h:36
int _papi_hwi_cleanup_all_presets(void)
Definition: papi_preset.c:114
static char stack[2 *PAPI_HUGE_STR_LEN]
Definition: papi_preset.c:791
int _papi_hwi_innoculate_vector(papi_vector_t *v)
Definition: papi_vector.c:109
int _papi_hwi_innoculate_os_vector(papi_os_vector_t *v)
Definition: papi_vector.c:200
static int native
static int cidx
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
va_end(arg_list)
va_start(arg_list, fmt)
const char * name
Definition: rocs.c:225
int
Definition: sde_internal.h:89
long long int long long
Definition: sde_internal.h:85
EventSetInfo_t ** dataSlotArray
int pos[PAPI_EVENTS_IN_DERIVED_EVENT]
unsigned int event_code
EventSetInheritInfo_t inherit
EventSetMultiplexInfo_t multiplex
EventSetProfileInfo_t profile
long long * sw_stop
struct _ThreadInfo * master
long long * hw_start
EventSetAttachInfo_t attach
hwd_register_t * NativeBits
EventSetCpuInfo_t cpu
struct _CpuInfo * CpuInfo
EventSetGranularityInfo_t granularity
EventInfo_t * EventInfoArray
hwd_control_state_t * ctl_state
NativeInfo_t * NativeInfoArray
EventSetOverflowInfo_t overflow
EventSetDomainInfo_t domain
MPX_EventSet * mpx_evset
Definition: sw_multiplex.h:32
PAPI_sprofil_t ** prof
hwd_register_t * ni_bits
int component_index
Definition: papi.h:968
char name[PAPI_MAX_INFO_TERMS][PAPI_2MAX_STR_LEN]
Definition: papi.h:1003
unsigned int event_type
Definition: papi.h:986
unsigned int count
Definition: papi.h:981
char postfix[PAPI_2MAX_STR_LEN]
Definition: papi.h:992
char note[PAPI_HUGE_STR_LEN]
Definition: papi.h:1007
unsigned int event_code
Definition: papi.h:958
char short_descr[PAPI_MIN_STR_LEN]
Definition: papi.h:961
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:960
char derived[PAPI_MIN_STR_LEN]
Definition: papi.h:989
unsigned int code[PAPI_MAX_INFO_TERMS]
Definition: papi.h:997
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:963
Hardware info structure.
Definition: papi.h:774
int cpu_max_mhz
Definition: papi.h:790
PAPI_address_map_t * map
Definition: papi.h:703
int tls_papi_event_code_changed
Definition: threads.h:37
unsigned int tls_papi_event_code
Definition: threads.h:36
struct _papi_hwi_sysdetect_t::@183::@185 dev_type
PAPI_dev_type_attr_e attr
struct _papi_hwi_sysdetect_t::@183::@186 dev
union _papi_hwi_sysdetect_t::@183 query
struct _papi_hwi_sysdetect_t::@183::@184 enumerate
EventSetInfo_t * ESI
char * symbol
Definition: papi_preset.h:24
unsigned int code[PAPI_MAX_INFO_TERMS]
Definition: papi_preset.h:32
unsigned int count
Definition: papi_preset.h:29
char * postfix
Definition: papi_preset.h:31
unsigned int event_type
Definition: papi_preset.h:30
char * short_descr
Definition: papi_preset.h:25
char * name[PAPI_MAX_INFO_TERMS]
Definition: papi_preset.h:33
char * long_descr
Definition: papi_preset.h:26
DynamicArray_t global_eventset_map
PAPI_hw_info_t hw_info
PAPI_shlib_info_t shlib_info
int mpx_remove_event(MPX_EventSet **mpx_events, int EventCode)
Definition: sw_multiplex.c:418
int MPX_add_events(MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
Definition: sw_multiplex.c:676
int mpx_add_event(MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
Definition: sw_multiplex.c:305
THREAD_LOCAL_STORAGE_KEYWORD ThreadInfo_t * _papi_hwi_my_thread
Definition: threads.c:37
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
#define THREAD_LOCAL_STORAGE_KEYWORD
Definition: threads.h:16
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
int retval
Definition: zero_fork.c:53