PAPI 7.1.0.0
Loading...
Searching...
No Matches
linux-pcp.c
Go to the documentation of this file.
1//-----------------------------------------------------------------------------
2//-----------------------------------------------------------------------------
3// This file contains the functions needed to interface PAPI with PCP, the
4// Performance Co-Pilot package. A manual for pmXXX commands is online at
5// https://pcp.io/man/
6// Performance: As tested on the ICL Saturn system, round-trip communications
7// with the PCP Daemon cost us 8-10ms, so every pm___ call is a stall. We have
8// to create our event list when initialized, but we can do that with some
9// 'batch' reads to minimize overhead.
10//-----------------------------------------------------------------------------
11//-----------------------------------------------------------------------------
12// #define DEBUG /* To enable SUBDBG messages */
13// see also _papi_hwi_debug = DEBUG_SUBSTRATE; below, to enable xxxDBG macros.
14
15#include <unistd.h>
16#include <errno.h>
17#include <dirent.h>
18#include <fcntl.h>
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <limits.h>
23#include <ctype.h>
24#include <math.h>
25#include <sys/time.h>
26
27// Headers required by PAPI.
28#include "papi.h"
29#include "papi_internal.h"
30#include "papi_vector.h"
31#include "papi_memory.h"
32#include "papi_debug.h" // for FUNC macro in error messages, keep even if we have no xxxDBG messages.
33#include <dlfcn.h> // Dynamic lib routines; especially dlsym to get func ptrs.
34
35#ifndef FUNC /* Not defined if not DEBUG... */
36#define FUNC __func__ /* force it. */
37#endif
38
39// Event Name filters, used in init_component for the routine pmTraversePMNS(). Differs by system.
40//#define AGENT_NAME "xfs" /* Saturn PCP. */
41//#define AGENT_NAME "mem" /* Saturn PCP. */
42 #define AGENT_NAME "perfevent" /* Power9 PCP. */
43//#define AGENT_NAME "" /* Get it all! */
44
45/* To remove redefined warnings */
46#undef PACKAGE_BUGREPORT
47#undef PACKAGE_TARNAME
48#undef PACKAGE_NAME
49#undef PACKAGE_STRING
50#undef PACKAGE_VERSION
51
52// PCP include directory (defaults to /usr/include/pcp; see README for PAPI_PCP_INC.)
53#include <pmapi.h> // See https://pcp.io/man/man3/pmapi.3.html for routines.
54#include <impl.h> // also a PCP file.
55
56#define PM_OPTFLAG_EXIT (1<<5)
57#define PM_CONTEXT_UNDEF -1
58#define PM_CONTEXT_HOST 1
59#define PM_CONTEXT_ARCHIVE 2
60#define PM_CONTEXT_LOCAL 3
61
62// The following macro follows if a string function has an error. It should
63// never happen; but it is necessary to prevent compiler warnings. We print
64// something just in case there is programmer error in invoking the function.
65#define HANDLE_STRING_ERROR {fprintf(stderr,"%s:%i unexpected string function error.\n",__FILE__,__LINE__); exit(-1);}
66
67//-----------------------------------------------------------------------------
68// Union to convert pointers and avoid warnings. Plug in one, pull out the other.
69//-----------------------------------------------------------------------------
70typedef union
71{
72 void *vPtr;
73 int *iPtr;
74 unsigned int *uiPtr;
75 long *lPtr;
76 long long *llPtr;
77 unsigned long long *ullPtr;
78 float *fPtr;
79 double *dPtr;
80 char *cPtr;
82
83typedef union
84{
85 long long ll;
86 unsigned long long ull;
87 double d;
88 void *vp;
89 unsigned char ch[8];
91
92//-----------------------------------------------------------------------------
93// Structure to store private information on each Event.
94//-----------------------------------------------------------------------------
95typedef struct _pcp_register
96{
97 unsigned int selector; // indexed from 1, index of counter slot, but 0 means none.
99
100
101//-----------------------------------------------------------------------------
102// WARNING: Do NOT expect pointers into the pcp_event_info[] array to remain
103// valid during processing; the list is realloc() to make room and this can
104// i_nvalidate the pointer. (Hard won knowledge).
105//-----------------------------------------------------------------------------
106typedef struct _pcp_event_info // an array of these is populated by our pcp create event routine.
107{
108 char name[PAPI_MAX_STR_LEN]; // name (we never copy more than PAPI_MAX_STR_LEN-1, so always z-terminated).
109 pmID pmid; // PCP's unique id (gets only base name).
110 pmDesc desc; // Description (not text, just var type etc). desc.pmid = PM_ID_NULL if not read yet.
111 int valfmt; // Value format from Fetch (PM_VAL_INSITU, PM_VAL_DPTR [dynamic], PM_VAL_SPTR [static]
112 int valType; // Type of value (PM_TYPE_[32,U32,64,U64,FLOAT,DOUBLE,STRING).
113 char domainDesc[PAPI_MAX_STR_LEN]; // Domain description if not null.
114 int numVal; // number of values in array.
115 int idx; // idx into vlist array.
116 unsigned long long zeroValue; // Value that counts as zero.
118
119
120//-----------------------------------------------------------------------------
121// This structure is used when doing register allocation it possibly is not
122// necessary when there are no register constraints.
123//-----------------------------------------------------------------------------
124typedef struct _pcp_reg_alloc
125{
128
129
130//-----------------------------------------------------------------------------
131// Holds control flags. There's one of these per event-set. Use this to hold
132// data specific to the EventSet. We hold for each event the index into the
133// pcp_event_info[] array, and a corresponding value; they must grow in
134// lockstep; to be NULL together or [maxAllocated] together. We cannot create a
135// structure to make that automatic; we need to point to an array of long long
136// values alone after a read.
137//-----------------------------------------------------------------------------
138
139typedef struct _pcp_control_state
140{
141 int numEvents; // The number of events we have.
142 int maxAllocated; // The most ever allocated.
143 int *pcpIndex; // array of indices into pcp_event_info[].
144 unsigned long long *pcpValue; // corresponding value read.
146
147
148//-----------------------------------------------------------------------------
149// Holds per-thread information. We don't have any.
150//-----------------------------------------------------------------------------
151typedef struct _pcp_context
152{
153 int initDone; // does nothing.
155
156//-----------------------------------------------------------------------------
157// Our hash table entry. We use a hash table to help lookup event names. Each
158// entry contains an index into the pcp_event_info table, and a chain pointer
159// to the next hash entry if the same hash results for several event names.
160// See the routines addNameHash(), freeNameHash(), findNameHash().
161//-----------------------------------------------------------------------------
162typedef struct _pcp_hash // hash table entry.'
163{
164 int idx; // The entry that matches this hash.
165 void *next; // next entry that matches this hash, or NULL.
167
168//-----------------------------------------------------------------------------
169// We cache our domains to save costly reads from the daemon, using a table of
170// this structure per entry. The domain id is not a counter, but there haven't
171// been many of them, so we do a sequential search of the table.
172//-----------------------------------------------------------------------------
173typedef struct
174{
175 pmInDom domainId; // The id.
176 int numInstances; // size of the arrays below.
177 int *instances; // the instances. cleanup must free(instances).
178 char **names; // The names. cleanup (must free(names).
180
181
182papi_vector_t _pcp_vector; // What we expose to PAPI, routine ptrs and other values.
183
184
185// -------------------------- GLOBAL SECTION ---------------------------------
186
187 int _papi_hwi_debug = DEBUG_SUBSTRATE; // Bit flags to enable xxxDBG; SUBDBG for Substrate. Overrides weak global in papi.c.
188static int sEventInfoSize=0; // total size of pcp_event_info.
189static int sEventInfoBlock = ((8*1024) / sizeof(_pcp_event_info_t)); // add about 8K at a time.
190static _pcp_event_info_t * pcp_event_info = NULL; // our array of created pcp events.
191static int sEventCount = 0; // count of events seen by pmTraversePMNS().
192static int ctxHandle = -1; // context handle. (-1 is invalid).
193static char *cachedGetInDom(pmInDom indom, int inst); // cache all reads of pcp_pmGetInDom, to save time.
194#define HASH_SIZE 512 /* very roughly in the range of total events. full Saturn test, had ~ 11,000 events.*/
195static _pcp_hash_t sNameHash[HASH_SIZE]; // hash table into pcp_event_info by event name.
196
197#define COUNT_ROUTINES 1 /* Change to zero to stop counting. */
198#if (COUNT_ROUTINES == 1)
199enum {
200ctr_pcp_init_thread, // counter 0
201ctr_pcp_init_component, // counter 1
202ctr_pcp_init_control_state, // counter 2
203ctr_pcp_start, // counter 3
204ctr_pcp_stop, // counter 4
205ctr_pcp_read, // counter 5
206ctr_pcp_shutdown_thread, // counter 6
207ctr_pcp_shutdown_component, // counter 7
208ctr_pcp_ctl, // counter 8
209ctr_pcp_update_control_state, // counter 9
210ctr_pcp_set_domain, // counter 10
211ctr_pcp_reset, // counter 11
212ctr_pcp_ntv_enum_events, // counter 12
213ctr_pcp_ntv_name_to_code, // counter 13
214ctr_pcp_ntv_code_to_name, // counter 14
215ctr_pcp_ntv_code_to_descr, // counter 15
216ctr_pcp_ntv_code_to_info}; // counter 16
217
218static int cnt[ctr_pcp_ntv_code_to_info+1] = {0}; // counters for the following macro.
219
220#define mRtnCnt(funcname) \
221 if (COUNT_ROUTINES) { /* Note if (0) optimized out completely even if -O0. */ \
222 cnt[ctr##funcname]++; /* Increment counter. */ \
223 if (cnt[ctr##funcname] == 1) /* If first time entering a new function, report it. */ \
224 _prog_fprintf(stderr, "Entered " TOSTRING(funcname) "\n"); \
225 }
226#else /* If COUNT_ROUTINES != 1, */
227#define mRtnCnt(funcname) /* .. make macro do nothing. */
228#endif /* if/else for COUNT_ROUTINES handled. */
229
230//--------------------------------------------------------------------
231// Timing of routines and blocks. Typical usage;
232// _time_gettimeofday(&t1, NULL); // starting point.
233// ... some code to execute ...
234// _time_gettimeofday(&t2, NULL); // finished timing.
235// _time_fprintf(stderr, "routine took %li uS.\n", // report time.
236// (mConvertUsec(t2)-mConvertUsec(t1)));
237//--------------------------------------------------------------------
238static struct timeval t1, t2; // used in timing routines to measure performance.
239#define mConvertUsec(timeval_) \
240 (timeval_.tv_sec*1000000+timeval_.tv_usec) /* avoid typos. */
241
242#define _prog_fprintf if (0) fprintf /* change to 1 to enable printing of progress debug messages. */
243#define _time_fprintf if (0) fprintf /* change to 1 to enable printing of performance timings. */
244#define _time_gettimeofday if (0) gettimeofday /* change to 1 to enable gettimeofday for performance timings. */
245
246
247// file handle used to access pcp library with dlopen
248static void *dl1 = NULL;
249
250// string macro defined within Rules.pcp
251static char pcp_main[]=PAPI_PCP_MAIN;
252
253//-----------------------------------------------------------------------------
254// Using weak symbols (global declared without a value, so it defers to any
255// other global declared in another file WITH a value) allows PAPI to be built
256// with the component, but PAPI can still be installed in a system without the
257// required library.
258//-----------------------------------------------------------------------------
259
260void (*_dl_non_dynamic_init)(void) __attribute__((weak)); // declare a weak dynamic-library init routine pointer.
261
262// ------------------------ LINK DYNAMIC LIBRARIES ---------------------------
263// Function pointers for the PCP lib; begin with pm (performance monitor).
264// Commented out functions are ones we do not use; so we don't waste space.
265static int (*pmLookupName_ptr) (int numpid, char **namelist,pmID *pmidlist);
266static char* (*pmErrStr_ptr) (int code);
267static int (*pmTraversePMNS_ptr) (const char *name, void(*func)(const char *));
268static void (*pmFreeResult_ptr) (pmResult *result);
269static int (*pmNewContext_ptr) (int type, const char *name);
270static int (*pmDestroyContext_ptr) (int handle);
271static int (*pmFetch_ptr) (int numpid, pmID *pmidlist, pmResult **result);
272static int (*pmLookupDesc_ptr) (pmID pmid, pmDesc *desc);
273static int (*pmGetInDom_ptr) (pmInDom indom, int **instlist, char ***namelist);
274static int (*pmLookupText_ptr) (pmID pmid, int level, char **buffer);
275static char * (*pmUnitsStr_r_ptr) (const pmUnits *pu, char *buf, int buflen);
276
277// -------------------- LOCAL WRAPPERS FOR LIB FUNCTIONS ---------------------
278static int pcp_pmLookupName (int numpid, char **namelist, pmID *pmidlist)
279 { return ((*pmLookupName_ptr) (numpid, namelist, pmidlist)); }
280
281static char* pcp_pmErrStr (int code)
282 { return ((*pmErrStr_ptr) (code)); }
283
284static int pcp_pmTraversePMNS (const char *name, void(*func)(const char *))
285 { return ((*pmTraversePMNS_ptr) (name, func)); }
286
287static void pcp_pmFreeResult (pmResult *result)
288 {(*pmFreeResult_ptr) (result); return;}
289
290static int pcp_pmNewContext (int type, const char *name)
291 { return ((*pmNewContext_ptr) (type,name)); }
292
294 { return ((*pmDestroyContext_ptr) (handle));}
295
296static int pcp_pmFetch (int numpid, pmID *pmidlist, pmResult **result)
297 { return ((*pmFetch_ptr) (numpid,pmidlist,result)); }
298
299static int pcp_pmLookupDesc (pmID pmid, pmDesc *desc)
300 { return ((*pmLookupDesc_ptr) (pmid,desc)); }
301
302static int pcp_pmGetInDom (pmInDom indom, int **instlist, char ***namelist)
303 { return ((*pmGetInDom_ptr) (indom,instlist,namelist)); }
304
305static int pcp_pmLookupText(pmID pmid, int level, char **buffer)
306 { return ((*pmLookupText_ptr) (pmid, level, buffer)); }
307
308static char* pcp_pmUnitsStr_r (const pmUnits *pu, char *buf, int buflen)
309 {return ((*pmUnitsStr_r_ptr) (pu, buf, buflen)); }
310
311
312//-----------------------------------------------------------------------------
313// stringHash: returns unsigned long value for hashed string. See djb2, Dan
314// Bernstein, http://www.cse.yorku.ca/~oz/hash.html Empirically a fast well
315// distributed hash, not theoretically explained. On a test system with 1857
316// events, this gets about a 65% density in a 2000 element table; 35% of slots
317// have dups; max dups was 4.
318//-----------------------------------------------------------------------------
319
320static unsigned int stringHash(char *str, unsigned int tableSize)
321{
322 unsigned long hash = 5381; // seed value.
323 int c;
324 while ((c = (*str++))) { // ends when c == 0.
325 hash = ((hash << 5) + hash) + c; // hash * 33 + c.
326 }
327
328 return (hash % tableSize); // compute index and exit.
329} // end function.
330
331
332//-----------------------------------------------------------------------------
333// addNameHash: Given a string, hash it, and add to sNameHash[].
334//-----------------------------------------------------------------------------
335
336static unsigned int addNameHash(char *key, int idx)
337{
338 unsigned int slot = stringHash(key, HASH_SIZE); // compute hash code.
339 if (sNameHash[slot].idx < 0) { // If not occupied,
340 sNameHash[slot].idx = idx; // ..Now it is.
341 return(slot); // and we are done.
342 }
343
344 // slot was occupied (collision).
345 _pcp_hash_t *newGuy = calloc(1, sizeof(_pcp_hash_t)); // make a new entry.
346 newGuy->idx = sNameHash[slot].idx; // copy the idx sitting in table.
347 newGuy->next = sNameHash[slot].next; // copy the chain pointer.
348 sNameHash[slot].idx = idx; // this one goes into table.
349 sNameHash[slot].next = (void*) newGuy; // and chains to that new guy.
350 return(slot); // and we are done.
351} // end routine.
352
353
354//-----------------------------------------------------------------------------
355// freeNameHash: delete any allocated for collisions.
356//-----------------------------------------------------------------------------
357
358static void freeNameHash(void)
359{
360 int i;
361 for (i=0; i<HASH_SIZE; i++) { // loop through table.
362 void *next = sNameHash[i].next; // Get any pointer.
363 while (next != NULL) { // follow the chain.
364 void *tofree = next; // remember what we have to free.
365 next = ((_pcp_hash_t*) next)->next; // follow the chain.
366 free(tofree); // free the one we are standing on.
367 }
368 }
369} // end routine.
370
371
372//-----------------------------------------------------------------------------
373// findNameHash: Returns the idx into pcp_event_info, or -1 if not found.
374// avg over 1857 lookups, Saturn [Intel XEON 2.0GHz) was 120ns per lookup.
375//-----------------------------------------------------------------------------
376
377static int findNameHash(char *key)
378{
379 int idx;
380 unsigned int slot = stringHash(key, HASH_SIZE); // compute hash code.
381 idx = sNameHash[slot].idx; // get the index.
382 if (idx < 0) return(-1); // No good slot for it.
383 if (strcmp(key, pcp_event_info[idx].name) == 0) { // If we found it straight away,
384 return(idx); // .. quick return.
385 }
386
387 _pcp_hash_t *next = (_pcp_hash_t*) sNameHash[slot].next; // get the next guy.
388
389 while (next != NULL) { // follow the chain.
390 idx = next->idx; // .. get the idx.
391 if (strcmp(key, pcp_event_info[idx].name) == 0) { // If we found a match,
392 return(idx); // .. return with answer.
393 }
394
395 next = next->next; // get the next guy in the link.
396 } // end chain follow for collisions.
397
398 return(-1); // did not find it.
399} // end routine.
400
401
402//-----------------------------------------------------------------------------
403// Get all needed function pointers from the Dynamic Link Library.
404//-----------------------------------------------------------------------------
405
406// Simplify routine below; relies on ptr names being same as func tags.
407#define STRINGIFY(x) #x
408#define TOSTRING(x) STRINGIFY(x)
409#define mGet_DL_FPtr(Name) \
410 Name##_ptr = dlsym(dl1, TOSTRING(Name)); \
411 if (dlerror() != NULL) { /* If we had an error, */ \
412 int strErr=snprintf(_pcp_vector.cmp_info.disabled_reason, PAPI_HUGE_STR_LEN, \
413 "PCP library function %s not found in lib.", TOSTRING(Name)); \
414 _pcp_vector.cmp_info.disabled_reason[PAPI_HUGE_STR_LEN-1]=0; \
415 if (strErr > PAPI_HUGE_STR_LEN) HANDLE_STRING_ERROR; \
416 return(PAPI_ENOSUPP); \
417 } /* end of macro. */
418
420{
421 if ( _dl_non_dynamic_init != NULL ) { // If weak var present, statically linked insted of dynamic.
422 char *strCpy=strncpy( _pcp_vector.cmp_info.disabled_reason, "The pcp component REQUIRES dynamic linking capabilities.", PAPI_HUGE_STR_LEN);
424 if (strCpy == NULL) HANDLE_STRING_ERROR;
425 return PAPI_ENOSUPP; // EXIT not supported.
426 }
427
428 char path_name[1024];
429 char *pcp_root = getenv("PAPI_PCP_ROOT");
430
431 dl1 = NULL;
432 // Step 1: Process override if given.
433 if (strlen(pcp_main) > 0) { // If override given, it has to work.
434 dl1 = dlopen(pcp_main, RTLD_NOW | RTLD_GLOBAL); // Try to open that path.
435 if (dl1 == NULL) {
436 int strErr=snprintf(_pcp_vector.cmp_info.disabled_reason, PAPI_HUGE_STR_LEN, "PAPI_PCP_MAIN override '%s' given in Rules.pcp not found.", pcp_main);
439 return(PAPI_ENOSUPP); // Override given but not found.
440 }
441 }
442
443 // Step 2: Try system paths, will work with Spack, LD_LIBRARY_PATH, default paths.
444 if (dl1 == NULL) { // No override,
445 dl1 = dlopen("libpcp.so", RTLD_NOW | RTLD_GLOBAL); // Try system paths.
446 }
447
448 // Step 3: Try the explicit install default.
449 if (dl1 == NULL && pcp_root != NULL) { // if root given, try it.
450 int strErr=snprintf(path_name, 1024, "%s/lib64/libpcp.so", pcp_root); // PAPI Root check.
451 path_name[1024-1]=0;
453 dl1 = dlopen(path_name, RTLD_NOW | RTLD_GLOBAL); // Try to open that path.
454 }
455
456 // Check for failure.
457 if (dl1 == NULL) {
458 int strErr=snprintf(_pcp_vector.cmp_info.disabled_reason, PAPI_HUGE_STR_LEN, "libpcp.so not found.");
461 return(PAPI_ENOSUPP);
462 }
463
464 // We have dl1.
465
466//-----------------------------------------------------------------------------
467// Collect pointers for routines in shared library. All below will abort this
468// routine with PAPI_ENOSUPP, if the routine is not found in the dynamic
469// library.
470//-----------------------------------------------------------------------------
471
472 mGet_DL_FPtr(pmLookupName);
473 mGet_DL_FPtr(pmErrStr);
474 mGet_DL_FPtr(pmTraversePMNS);
475 mGet_DL_FPtr(pmFreeResult);
476 mGet_DL_FPtr(pmNewContext);
477 mGet_DL_FPtr(pmDestroyContext);
478 mGet_DL_FPtr(pmFetch);
479 mGet_DL_FPtr(pmLookupDesc);
480 mGet_DL_FPtr(pmGetInDom);
481 mGet_DL_FPtr(pmLookupText);
482 mGet_DL_FPtr(pmUnitsStr_r);
483 return PAPI_OK; // If we get here, all above succeeded.
484} // end routine.
485
486
487//-----------------------------------------------------------------------------
488// qsort comparison routine, for pcp_event_info.
489//-----------------------------------------------------------------------------
490static int qsPMID(const void *arg1, const void* arg2)
491{
494
495 if (p1->pmid < p2->pmid) return (-1); // 1 comes before 2.
496 if (p1->pmid > p2->pmid) return ( 1); // 1 comes after 2.
497 if (p1->idx < p2->idx ) return (-1); // same pmid, try idx into vlist.
498 if (p1->idx > p2->idx ) return ( 1); // 1 comes after 2.
499 return (strcmp(p1->name, p2->name)); // sort by name if same PMID and idx.
500} // end routine.
501
502
503//-----------------------------------------------------------------------------
504// cbPopulateNameOnly: This is a callback routine, called by pmTraversePMNS. That
505// routine iterates through the PM name space and calls this routine once per
506// name. We increment sEventCount as we go, this will be the final count of valid
507// array entries. sEventInfoSize will be >= sEventCount.
508// WARNING: May realloc() pcp_event_info[], invalidating pointers into it.
509//-----------------------------------------------------------------------------
510
511static void cbPopulateNameOnly(const char *name)
512{
513 if (sEventCount >= sEventInfoSize) { // If we must realloc,
514 sEventInfoSize += sEventInfoBlock; // .. Add another page.
515 pcp_event_info = realloc(pcp_event_info, // .. do realloc.
516 sEventInfoSize*sizeof(_pcp_event_info_t)); // ..
517 memset(&pcp_event_info[sEventCount], 0, // .. clear to zeros.
518 sEventInfoBlock*sizeof(_pcp_event_info_t)); // ..
519 }
520
521 strncpy(pcp_event_info[sEventCount].name, name, PAPI_MAX_STR_LEN-1); // copy name.
522 sEventCount++; // increment our count of events.
523} // end routine.
524
525
526//-----------------------------------------------------------------------------
527// makeQualifiedEvent: Create a new event as a copy of the old, plus a tag at
528// the end. This appends to the pcp_event_info[] array, which may be realloced
529// (which CAN invalidate any pointers into it).
530//-----------------------------------------------------------------------------
531
532static void makeQualifiedEvent(int baseEvent, int idx, char *qualifier)
533{
534 int prevSize;
535 if (sEventCount >= sEventInfoSize) { // If we must realloc,
536 prevSize = sEventInfoSize;
537 sEventInfoSize += sEventInfoBlock; // .. Add another block.
538 pcp_event_info = realloc(pcp_event_info, // .. attempt reallocation.
539 sEventInfoSize*sizeof(_pcp_event_info_t)); // .. ..
540 if (pcp_event_info == NULL) { // If realloc failed, report it.
541 fprintf(stderr, "%s:%i:%s realloc denied; "
542 "pcp_event_info=%p at size=%i.\n",
543 __FILE__, __LINE__, __func__,
545 exit(-1);
546 } // end if realloc failed.
547
548 memset(&pcp_event_info[prevSize], 0, // .. clear the new block to zeros..
549 sEventInfoBlock*sizeof(_pcp_event_info_t)); // ..
550 } // end if realloc needed.
551
552 pcp_event_info[sEventCount] = pcp_event_info[baseEvent]; // copy the structure.
553 pcp_event_info[sEventCount].numVal = 1; // Just one value.
554 pcp_event_info[sEventCount].idx = idx; // Set the right index.
555 pcp_event_info[sEventCount].zeroValue = 0; // Set the base value.
556 int slen = strlen(pcp_event_info[sEventCount].name); // get length of user name.
557 char *c = qualifier; // point at qualifier.
558 pcp_event_info[sEventCount].name[slen++] = ':'; // place a colon.
559
560 while ( (*c) != 0 && slen < PAPI_MAX_STR_LEN-1) { // .. appending qualifier,
561 char v=*c++; // .. what we intend to append, point at next.
562 // your chance to invalidate any chars, right here!
563 pcp_event_info[sEventCount].name[slen++] = v; // .. add to name, inc slen.
564 }
565
566 pcp_event_info[sEventCount].name[slen] = 0; // ensure z-terminator.
567 sEventCount++; // increment our count of events.
568} // end routine.
569
570
571//-----------------------------------------------------------------------------
572// Helper; reads the description if it has not already been read for a given
573// index. Presumes pmid is already present.
574//-----------------------------------------------------------------------------
575
576static void getPMDesc(int pcpIdx) { // Reads the variable descriptor.
577 int ret;
578 if (pcp_event_info[pcpIdx].pmid == PM_ID_NULL) return; // Already have it.
579 ret = pcp_pmLookupDesc(pcp_event_info[pcpIdx].pmid, // Get the event descriptor.
580 &pcp_event_info[pcpIdx].desc); // .. into the table; will set desc.pmid to not null.
581 if (ret == PM_ERR_PMID) { // If we failed for PMID,
582 fprintf(stderr, "%s:%i:%s Invalid PMID.\n",
583 __FILE__, __LINE__, __func__);
584 exit(-1);
585 } // end if realloc failed.
586
587 if (ret == PM_ERR_NOAGENT) { // If we failed for agent,
588 fprintf(stderr, "%s:%i:%s PMDA Agent not available to respond..\n",
589 __FILE__, __LINE__, __func__);
590 exit(-1);
591 } // end if realloc failed.
592
593 if (ret != 0) { // Unknown error,
594 fprintf(stderr, "%s:%i:%s Unknown error code ret=%i.\n",
595 __FILE__, __LINE__, __func__, ret);
596 exit(-1);
597 } // end if realloc failed.
598
599 pcp_event_info[pcpIdx].valType = pcp_event_info[pcpIdx].desc.type; // Always copy type over.
600 return; // No error.
601} // END code.
602
603
604//-----------------------------------------------------------------------------
605// We cache all domains we read; to save the round-trip cost to the daemon;
606// on Saturn Test 8ms (too much delay invoked over thousands of events).
607// Use inst = -1 to free all malloced memory.
608// WARNING: realloc() cachedDomains[] can relocate the entire cache in memory,
609// INVALIDATING ALL POINTERS into it, causing segfaults or anomolous results.
610//-----------------------------------------------------------------------------
611
612static char *cachedGetInDom(pmInDom indom, int inst)
613{
614 static int domains=0; // None cached to begin.
615 static _pcp_domain_cache_t* cachedDomains = NULL; // Empty pointer.
616 int i, domIdx;
617
618 if (inst == -1) { // If we are shutting down,
619 if (cachedDomains == NULL) return(NULL); // exit if we never built an array.
620 for (i=0; i<domains; i++) { // for every one cached,
621 free(cachedDomains[i].instances); // .. free malloced memory.
622 free(cachedDomains[i].names); // .. free malloced memory.
623 }
624
625 free(cachedDomains); // discard our table.
626 domains = 0; // reset.
627 cachedDomains = NULL; // never free twice.
628 return(NULL); // exit.
629 } // end if shutting down.
630
631 // Check if we have it already.
632 for (i=0; i<domains; i++) {
633 if (indom == cachedDomains[i].domainId) break; // Exit loop if found.
634 }
635
636 domIdx = i; // The domain index.
637 if (i == domains) { // If not found; make a new one and read it.
638 domains++; // .. add one to count.
639
640 if (domains == 1) { // for first domain,
641 cachedDomains = malloc(sizeof(_pcp_domain_cache_t)); // ..malloc.
642 } else { // for subsequent domains,
643 cachedDomains = realloc(cachedDomains,
644 domains*sizeof(_pcp_domain_cache_t)); // realloc, retain first.
645 }
646
647 if (cachedDomains == NULL) { // If we failed malloc/realloc,
648 fprintf(stderr, "%s:%i:%s malloc/realloc denied for "
649 "cachedDomains; size=%i.\n",
650 __FILE__, __LINE__, __func__, domains);
651 exit(-1);
652 } // end if realloc failed.
653
654 cachedDomains[domIdx].domainId = indom; // .. The domain we are getting.
655 cachedDomains[domIdx].numInstances = pcp_pmGetInDom(indom,
656 &cachedDomains[domIdx].instances, // .. store pointer lists in struct too.
657 &cachedDomains[domIdx].names); // ..
658 for (i=0; i<cachedDomains[domIdx].numInstances; i++) { // DEBUG, vet the strings.
659 if (cachedDomains[domIdx].names[i] == NULL ||
660 strlen(cachedDomains[domIdx].names[i]) == 0 ||
661 strlen(cachedDomains[domIdx].names[i]) >= PAPI_MAX_STR_LEN) {
662 fprintf(stderr, "%s:%i:%s ERROR: cachedGetInDom: domain=%u, domIdx=%i, name idx %i invalid string.\n",
663 __FILE__, __LINE__, FUNC, indom, domIdx, i);
664 exit(-1);
665 } // end if domain string is nonsense.
666 }
667 } // end if we need to cache a new domain.
668
669 // We got the domain index, Now we can try to look up the
670 // instance name.
671
672 for (i=0; i < cachedDomains[domIdx].numInstances; i++) { // look through all instances.
673 if (cachedDomains[domIdx].instances[i] == inst) // .. If found,
674 return cachedDomains[domIdx].names[i]; // .. .. return matching name.
675 } // end search for inst.
676
677 fprintf(stderr, "%s:%i:%s ERROR: cachedGetInDom: domain=%u, domIdx=%i, numInstances=%i, failed to find inst=%i.\n",
678 __FILE__, __LINE__, FUNC, indom, domIdx, cachedDomains[domIdx].numInstances, inst);
679 exit(-1); // Cannot continue; should not have happened.
680
681 return NULL; // Code cannot be reached. Couldn't find it.
682} // end routine.
683
684
685//-----------------------------------------------------------------------------
686// Helper routine, returns a ull value from a value set pointer. Automatically
687// does conversions from 32 bit to 64 bit (int32, uint32, fp32).
688//-----------------------------------------------------------------------------
689static unsigned long long getULLValue(pmValueSet *vset, int value_index)
690{
691 unsigned long long value; // our return value.
692 convert_64_t convert; // union for conversion.
693 uPointer_t myPtr; // a union helper to avoid warnings.
694
695 if (vset->valfmt == PM_VAL_INSITU) { // If the value format is in situ; a 32 bit value.
696 convert.ll = vset->vlist[value_index].value.lval; // .. we can just collect the value immediately.
697 value = convert.ull; // ..
698 } else { // If it is either static or dynamic alloc table,
699 pmValueBlock *pmvb = vset->vlist[value_index].value.pval; // .. value given is a pointer to value block.
700 myPtr.cPtr = pmvb->vbuf; // .. use cPtr because vbuf defined as char[1] in pmValueBlock.
701 switch (pmvb->vtype) { // Note we restricted the types in init; these cases should agree.
702 case PM_TYPE_32: // 32-bit signed integer
703 convert.ll = myPtr.iPtr[0];
704 value = convert.ull;
705 break;
706
707 case PM_TYPE_U32: // 32-bit unsigned integer
708 value = myPtr.uiPtr[0];
709 break;
710
711 case PM_TYPE_64: // 64-bit signed integer
712 convert.ll = myPtr.llPtr[0];
713 value = convert.ull;
714 break;
715
716 case PM_TYPE_U64: // 64-bit unsigned integer
717 value = myPtr.ullPtr[0];
718 break;
719
720 case PM_TYPE_FLOAT: // 32-bit floating point
721 convert.d = myPtr.fPtr[0]; // convert first.
722 value = convert.ull;
723 break;
724
725 case PM_TYPE_DOUBLE: // 64-bit floating point
726 convert.d = myPtr.dPtr[0];
727 value = convert.ull;
728 break;
729
730 case PM_TYPE_STRING: // array of char
731 convert.vp = myPtr.cPtr;
732 value = convert.ull;
733 break;
734
735 default:
736 fprintf(stderr, "%s:%i pmValueBlock (from PCP) contains an unrecognized value type=%i.\n",
737 __FILE__, __LINE__, pmvb->vtype);
738 convert.ll = -1; // A flag besides zero
739 value = convert.ull;
740 } // end switch on type.
741 } // if pmValueBlock value.
742
743 return(value); // exit with result.
744} // end routine.
745
746
747//----------------------------------------------------------------------------
748// Helper routine to subtract zero value from an event value. Although we
749// store an unsigned long long value for both our zero value and a read-in
750// value, it can be recast to signed or double. So zeroing on those must be
751// done in the type intended, and we have to recast to do it. Note that 32
752// bit signed int or float were saved and cast as 64 bit int or double,
753// respectively.
754//
755// There are three types of 'semantics' in a description; only one is a
756// counter; the other two are instantaneous values. We do not subtract a
757// zero reference value from instantaneous values.
758// PM_SEM_COUNTER // cumulative counter (monotonic increasing)
759// PM_SEM_INSTANT // instantaneous value, continuous domain
760// PM_SEM_DISCRETE // instantaneous value, discrete domain
761//----------------------------------------------------------------------------
762
763static void subZero(_pcp_control_state_t *myCtl, int event)
764{
765 int k = myCtl->pcpIndex[event]; // get pcp_event_info[] index.
766 if (pcp_event_info[k].desc.sem != PM_SEM_COUNTER) return; // Don't subtract from instantaneous values.
767
768 convert_64_t zero, rawval;
769 rawval.ull = myCtl->pcpValue[event]; // collect the raw value.
770 zero.ull = pcp_event_info[k].zeroValue; // collect the zero (base) value.
771 switch (pcp_event_info[k].valType) { // Note we restricted the types in init; these cases should agree.
772 case PM_TYPE_32: // 32 bit was converted to long long.
773 case PM_TYPE_64: // long long.
774 rawval.ll -= zero.ll; // converted.
775 break;
776
777 case PM_TYPE_U32: // 32-bit was converted to 64 bit.
778 case PM_TYPE_U64: // 64-bit unsigned integer
779 rawval.ull -= zero.ull; // converted.
780 break;
781
782 case PM_TYPE_FLOAT: // 32-bit was converted to double.
783 case PM_TYPE_DOUBLE: // 64-bit floating point
784 rawval.d -= zero.d; // converted.
785 break;
786
787 case PM_TYPE_STRING: // array of char, do nothing for pointer.
788 break;
789
790 default:
791 fprintf(stderr, "%s:%i pcp_event_info[%s] contains an unrecognized value type=%i.\n",
792 __FILE__, __LINE__, pcp_event_info[k].name, pcp_event_info[k].valType);
793 exit(-1); // Quit, this shouldn't happen; something needs updating.
794 break;
795 } // end switch on type.
796
797 myCtl->pcpValue[event] = rawval.ull; // The adjusted value.
798} // end routine.
799
800
801//-----------------------------------------------------------------------------
802// Helper routine for _pcp_ntv_code_to_descr to retrieve pm event text (a
803// description of the event) given a pcp_event_info[] index.
804// There are two options, a PM_TEXT_ONELINE is a single line description and
805// PM_TEXT_HELP is a longer help description. The PAPI code that calls this
806// stores the description in PAPI_event_info_t->long_descr[PAPI_HUGE_STR_LEN];
807// currently 1024 characters. So we use the PM_TEXT_HELP version.
808//
809// pcpIdx MUST BE pre-validated as in range [0, sEventCount-1].
810// *helpText may be allocated; caller must free(helpText).
811// RETURNS PAPI_OK or PAPI error.
812// NOTE: There is also a pmLookupInDomText() that returns a description of a
813// domain; if you want that, you need a pmInDom and a very similar routine.
814//-----------------------------------------------------------------------------
815static int getHelpText(unsigned int pcpIdx, char **helpText)
816{
817 char *p;
818 int ret;
819 char errMsg[]="Help Text is not available for this event."; // for an error we have seen.
820
821 pmID myPMID = pcp_event_info[pcpIdx].pmid; // collect the pmid.
822 ret = pcp_pmLookupText(myPMID, PM_TEXT_HELP, helpText); // collect a line of text, routine mallocs helpText.
823 if (ret != 0) { // If larger help is not available, Try oneline.
824 if (*helpText != NULL) free(*helpText); // .. Free anything allocated.
825 *helpText = NULL; // .. start it as null.
826 ret = pcp_pmLookupText(myPMID, PM_TEXT_ONELINE, helpText); // .. collect a line of text, routine mallocs helpText.
827 }
828
829 if (ret == PM_ERR_TEXT) { // If not available,
830 *helpText = strdup(errMsg); // duplicate this error message.
831 } else if (ret != 0) { // If PCP has any other error, report and exit.
832 fprintf(stderr, "%s:%i:%s pmLookupText failed; return=%s.\n",
833 __FILE__, __LINE__, FUNC, pcp_pmErrStr(ret));
834 return PAPI_EATTR; // .. invalid or missing event attribute.
835 }
836
837 // Replace all /n with '|'.
838 for (p=(*helpText); p[0] != 0; p++) { // loop through string routine allocated,
839 if (p[0] == '\n') p[0] = '|'; // .. If we found a \n, replace with '|'.
840 } // end scan for \n.
841
842 return PAPI_OK; // Presumably all went well.
843} // end routine.
844
845
846//----------------------------------------------------------------------------
847//----------------------------------------------------------------------------
848// PAPI FUNCTIONS.
849//----------------------------------------------------------------------------
850//----------------------------------------------------------------------------
851
852//----------------------------------------------------------------------------
853// _pcp_init_component is called when PAPI is initialized (during
854// PAPI_library_init). The argument is the component index.
855//---------------------------------------------------------------------------
856static int _pcp_init_component(int cidx)
857{
858 int retval = PAPI_OK;
859 char *reason = _papi_hwd[cidx]->cmp_info.disabled_reason; // For error messages.
860 int rLen = PAPI_HUGE_STR_LEN; // Most I will print.
861 reason[rLen-1]=0; // last resort terminator.
862
863 mRtnCnt(_pcp_init_component); // count the routine.
864 #define hostnameLen 512 /* constant used multiple times. */
865 char hostname[hostnameLen]; // host name.
866 int ret;
867
869 if ( ret != PAPI_OK ) { // Failure to get lib.
871 goto fn_fail;
872 }
873
874 ret = gethostname(hostname, hostnameLen); // Try to get the host hame.
875 if (ret != 0) { // If we can't get the hostname,
876 int strErr=snprintf(reason, rLen, "Failed system call, gethostname() "
877 "returned %i.", ret);
878 reason[rLen-1]=0;
879 if (strErr > rLen) HANDLE_STRING_ERROR;
881 goto fn_fail;
882 }
883 #undef hostnameLen /* done with it. */
884
885 _prog_fprintf(stderr, "%s:%i retrieved hostname='%s'\n", __FILE__, __LINE__, hostname); // show progress.
886
887 ctxHandle = pcp_pmNewContext(PM_CONTEXT_HOST, "local:"); // Set the new context to local host.
888 if (ctxHandle < 0) {
889 int strErr=snprintf(reason, rLen, "Cannot connect to PM Daemon on \"%s\".\n "
890 "(Is the Performance Co-Pilot running?)\n", hostname);
891 reason[rLen-1]=0;
892 if (strErr > rLen) SUBDBG("%s:%i Warning! Error's 'reason' string truncated:\n%s\n",__FILE__,__LINE__,reason);
894 goto fn_fail;
895 }
896
897 _prog_fprintf(stderr, "%s:%i Found ctxHandle=%i\n", __FILE__, __LINE__, ctxHandle); // show progress.
898
899 sEventInfoSize = sEventInfoBlock; // first allocation.
901 calloc(sEventInfoSize, sizeof(_pcp_event_info_t)); // Make room for all events.
902 if (pcp_event_info == NULL) {
904 "Could not allocate %lu bytes of memory for pcp_event_info.", sEventInfoSize*sizeof(_pcp_event_info_t));
905 _pcp_vector.cmp_info.disabled_reason[PAPI_HUGE_STR_LEN-1]=0; // force null termination.
908 goto fn_fail;
909 }
910
911 sEventCount = 0; // begin at zero.
912 _time_gettimeofday(&t1, NULL);
913 ret = pcp_pmTraversePMNS(AGENT_NAME, cbPopulateNameOnly); // Timed on Saturn [Intel Xeon 2.0GHz]; typical 9ms, range 8.5-10.5ms.
914 if (ret < 0) { // Failure...
915 int strErr=snprintf(reason, rLen, "pmTraversePMNS failed; ret=%i [%s]\n",
916 ret, pcp_pmErrStr(ret));
917 if (ret == PM_ERR_NAME) { // We know what this one is,
918 strErr=snprintf(reason, rLen, "pmTraversePMNS ret=PM_ERR_NAME: "
919 "Occurs if event filter '%s' unknown to PCP Daemon.\n", AGENT_NAME);
920 }
921 reason[rLen-1]=0;
922 if (strErr >rLen) HANDLE_STRING_ERROR;
924 goto fn_fail;
925 }
926
927 _time_gettimeofday(&t2, NULL);
928 _time_fprintf(stderr, "pmTraversePMNS PopulateNameOnly took %li uS.\n",
930 _time_fprintf(stderr, "Final sEventCount=%i, sEventInfoSize=%i, "
931 "sEventInfoBlock=%i.\n",
933
934 if (sEventCount < 1) { // Failure...
935 int strErr=snprintf(reason, rLen, "pmTraversePMNS returned zero events "
936 "for AGENT=\"%s\".\n", AGENT_NAME);
937 reason[rLen-1]=0;
938 if (strErr >rLen) HANDLE_STRING_ERROR;
940 goto fn_fail;
941 }
942
943 int i,j,k;
944 char **allNames=calloc(sEventCount, sizeof(char*)); // Make an array for all names.
945 for (i=0; i<sEventCount; i++) { // ..
946 allNames[i] = pcp_event_info[i].name; // copy pointer into array.
947 } // end for each event.
948
949 pmID *allPMID=calloc(sEventCount, sizeof(pmID)); // Make an array for results.
950 if (allPMID == NULL) { // If we failed,
951 snprintf(reason, rLen, "memory alloc denied for allPMID; "
952 "size=%i.\n", sEventCount);
953 int strErr=snprintf(reason, rLen, "Could not allocate %lu bytes of memory for allPMID.", sEventCount*sizeof(pmID));
954 free(allNames);
955 if (strErr > rLen) HANDLE_STRING_ERROR;
957 goto fn_fail;
958 } // end if calloc failed.
959
960 //----------------------------------------------------------------
961 // Unlike Saturn, on the Power9 we get an 'IPC protocol failure'
962 // if we try to read more than 946 names at a time. This is some
963 // limitation on a communication packet size. On our test system
964 // Power9; the maximum number we can read is 946. To allow leeway
965 // for other possible values; we read in blocks of 256.
966 //----------------------------------------------------------------
967 #define LNBLOCK 256 /* Power9 gets IPC errors if read block is too large. */
968 k = (__LINE__)-1; // where LNBLOCK is defined.
969
970 _time_gettimeofday(&t1, NULL);
971
972 i=0; // Starting index for allPMID.
973 while (i<sEventCount) { // read in blocks of LNBLOCK.
974 j = sEventCount-i; // .. presume we can read the rest.
975 if (j > LNBLOCK) j=LNBLOCK; // .. reduce if we cannot.
976 ret = pcp_pmLookupName(j, allNames+i, allPMID+i); // .. Get a block of PMIDs for a block of names.
977 if (ret < 0) { // .. Failure...
978 int strErr=snprintf(reason, rLen, "pmLookupName for %i names failed; ret=%i [%s].\n",
979 sEventCount, ret, pcp_pmErrStr(ret));
980 reason[rLen-1]=0;
981 if (strErr > rLen) HANDLE_STRING_ERROR;
982
983 if (ret == PM_ERR_IPC) { // .. If we know it, rewrite.
984 strErr=snprintf(reason, rLen, "pmLookupName ret=PM_ERR_IPC: one known cause is a readblock too large; reduce LNBLOCK (%s:%i).\n",
985 __FILE__,k);
986 reason[rLen-1]=0;
987 if (strErr > rLen) HANDLE_STRING_ERROR;
989 goto fn_fail;
990 }
991
993 goto fn_fail;
994 }
995
996 i+=j; // .. Adjust the pointer forward by what we read.
997 } // end while to read names in chunks, and avoid IPC error.
998 #undef LNBLOCK /* Discard constant; no further use. */
999
1000 _time_gettimeofday(&t2, NULL);
1001 _time_fprintf(stderr, "pmLookupName for all took %li uS, ret=%i.\n",
1002 (mConvertUsec(t2)-mConvertUsec(t1)), ret );
1003
1004 for (i=0; i<sEventCount; i++) pcp_event_info[i].pmid = allPMID[i]; // copy all the pmid over to array.
1005
1006 pmResult *allFetch = NULL; // result of pmFetch.
1007 _time_gettimeofday(&t1, NULL);
1008 ret = pcp_pmFetch(sEventCount, allPMID, &allFetch); // Fetch (read) all the events.
1009 _time_gettimeofday(&t2, NULL);
1010 if (ret != 0) {
1011 int strErr=snprintf(reason, rLen, "pcp_pmFetch failed, retcode=%d.", ret);
1012 reason[rLen-1]=0;
1013 if (strErr > rLen) HANDLE_STRING_ERROR;
1015 goto fn_fail;
1016 }
1017
1018 _time_fprintf(stderr, "pmFetch for all took %li uS, for %i events; ret=%i.\n",
1020
1021 //-------------------------------------------------------------------
1022 // In processing fetches, if we find a multi-valued event, we need
1023 // to force an event for every value (PAPI only returns 1 value per
1024 // event; not an array). In experiments thus far, all multi-valued
1025 // events have had domain descriptor names; so we just concat with
1026 // the name and make a new Event. We use a helper for that,
1027 // afterward we set the number of values in the original 'base name'
1028 // to zero; so it will be deleted by the cleanup routine.
1029 //-------------------------------------------------------------------
1030
1031 _time_gettimeofday(&t1, NULL); // time this index explosion.
1032 int origEventCount = sEventCount; // sEventCount may change in below routine.
1033
1034 for (i=0; i<origEventCount; i++) { // process all the fetch results.
1035 pcp_event_info[i].desc.pmid = PM_ID_NULL; // This indicates the description is NOT loaded yet.
1036 pmValueSet *vset = allFetch->vset[i]; // get the result for event[i].
1037
1038 // On Saturn test system, never saw this happen.
1039 if (vset == NULL) { // .. should not happen. leave numVal=0 for deletion.
1040 fprintf(stderr, "%s:%i vset=NULL for name='%s'\n",
1041 __FILE__, __LINE__, pcp_event_info[i].name);
1042 continue; // .. next in loop.
1043 }
1044
1045 pcp_event_info[i].numVal = vset->numval; // Show we have a value.
1046 if (vset->numval == 0) { // If the value is zero,
1047// _prog_fprintf(stderr, "%s:%i Discarding, no values for event '%s'.\n", __FILE__, __LINE__, pcp_event_info[i].name);
1048 continue; // If no values, leave numVal = 0 for deletion. (We do see this in tests).
1049 }
1050
1051 pcp_event_info[i].valfmt = vset->valfmt; // Get the value format. (INSITU or not).
1052 getPMDesc(i); // Get the value descriptor.
1053 unsigned long long ullval= (long long) -1; // debug stuff.
1054 convert_64_t convert;
1055
1056 if (vset->valfmt != PM_VAL_INSITU) { // If not in situ, must get the type.
1057 pmValue *pmval = &vset->vlist[0]; // .. Get the first value.
1058 pmValueBlock *pB = pmval->value.pval; // .. get it.
1059 if (pcp_event_info[i].valType != pB->vtype) {
1060 int strErr=snprintf(reason, rLen, "Unexpected value type fetched for %s. %i vs %i. Possible version incompatibiity.\n",
1061 pcp_event_info[i].name, pcp_event_info[i].valType, pB->vtype);
1062 reason[rLen-1]=0;
1063 if( strErr > rLen) HANDLE_STRING_ERROR;
1065 goto fn_fail;
1066 }
1067
1068// pcp_event_info[i].valType = pB->vtype; // .. get the type.
1069 ullval = getULLValue(vset, 0); // .. get the first value.
1070
1071 switch(pB->vtype) { // PCP's variable type; an int flag.
1072 case PM_TYPE_32: // 32-bit signed integer
1073 _prog_fprintf(stderr, "type I32, desc.sem=%i, event '%s'=", pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1074 break;
1075 case PM_TYPE_U32: // 32-bit unsigned integer
1076 _prog_fprintf(stderr, "type U32, desc.sem=%i, event '%s'=", pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1077 break;
1078 case PM_TYPE_FLOAT: // 32-bit floating point
1079 _prog_fprintf(stderr, "type F32, desc.sem=%i, event '%s'=", pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1080 break; // END CASE.
1081
1082 case PM_TYPE_64: // 64-bit signed integer
1083 convert.ull = ullval;
1084 _prog_fprintf(stderr, "type I64, desc.sem=%i, event '%s'= (ll) %lli =", pcp_event_info[i].desc.sem, pcp_event_info[i].name, convert.ll);
1085 break;
1086 case PM_TYPE_U64: // 64-bit unsigned integer
1087 _prog_fprintf(stderr, "type U64, desc.sem=%i, event '%s'= (ull) %llu =", pcp_event_info[i].desc.sem, pcp_event_info[i].name, convert.ull);
1088 break;
1089 case PM_TYPE_DOUBLE: // 64-bit floating point
1090 convert.ull = ullval;
1091 _prog_fprintf(stderr, "type U64, desc.sem=%i, event '%s'= (double) %f =", pcp_event_info[i].desc.sem, pcp_event_info[i].name, convert.d);
1092 break; // END CASE.
1093
1094 // IF YOU want to return string values, this is a place
1095 // to change; currently all string-valued events are
1096 // rejected. But, pB->vbuf is the string value. I would
1097 // copy it into a new pcp_event_info[] field; it would
1098 // need to be malloc'd here and free'd at component
1099 // shutdown. Also PAPI would need a new way to accept a
1100 // char* or void*.
1101
1102 case PM_TYPE_STRING: // pB->vbuf is char* to string value.
1103 _prog_fprintf(stderr, "%s:%i Discarding PM_TYPE_STRING event, desc.sem=%i, event '%s'=", __FILE__, __LINE__, pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1104 pcp_event_info[i].numVal = 0; // .. .. set numVal = 0 for deletion.
1105 break;
1106
1107 default: // If we don't recognize the type,
1108 _prog_fprintf(stderr, "%s:%i Dsicarding PM_UNKNOWN_TYPE event, desc.sem=%i, event '%s'=", __FILE__, __LINE__, pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1109 pcp_event_info[i].numVal = 0; // .. set numVal = 0 for deletion.
1110 break;
1111 } // end switch.
1112 } // If not In Situ.
1113 else {
1114 _prog_fprintf(stderr, "type IST, desc.sem=%i, event '%s'=", pcp_event_info[i].desc.sem, pcp_event_info[i].name);
1115 }
1116
1117 convert.ull = ullval;
1118 _prog_fprintf(stderr, "%02X%02X%02X%02X %02X%02X%02X%02X\n", convert.ch[0], convert.ch[1], convert.ch[2], convert.ch[3], convert.ch[4], convert.ch[5], convert.ch[6], convert.ch[7]);
1119 // Lookup description takes time; so we only do it for
1120 // multi-valued events here. For other events, we will do it
1121 // as needed for EventInfo filling.
1122
1123 if (pcp_event_info[i].numVal > 1) { // If a domain qualifier is possible;
1124 getPMDesc(i); // .. Get the event descriptor.
1125 _prog_fprintf(stderr, "Event %s has %i values, indom=%i.\n", pcp_event_info[i].name, pcp_event_info[i].numVal, pcp_event_info[i].desc.indom);
1126 if (pcp_event_info[i].desc.indom != PM_INDOM_NULL) { // .. If we have a non-null domain,
1127 for (j=0; j<vset->numval; j++) { // .. for every value present,
1128 pmValue *pmval = &vset->vlist[j]; // .. .. get that guy.
1129
1130 char *dname = cachedGetInDom( // .. .. read from cached domains (and populate it when needed).
1131 pcp_event_info[i].desc.indom,
1132 pmval->inst); // .. .. get the name. Not malloced so don't free dName.
1133
1134 makeQualifiedEvent(i, j, dname); // .. .. helper routine; may realloc pcp_event_info[], change sEventCount.
1135 } // end value list.
1136
1137 pcp_event_info[i].numVal = 0; // .. let the base event be discarded.
1138 } // end if we have a domain.
1139 } // end if multiple valued.
1140 } // end for each event.
1141
1142 // Trim the fat! We get rid of everything with numVal == 0.
1143 // We do that by compaction; moving valid entries to backfill
1144 // invalid ones.
1145
1146 j=0; // first destination.
1147 for (i=0; i<sEventCount; i++) { // loop thorugh all old and new.
1148 if (pcp_event_info[i].numVal > 0) { // If we have a valid entry,
1149 if (i != j) pcp_event_info[j] = pcp_event_info[i]; // move if it isn't already there.
1150 j++; // count one moved; new count of valid ones.
1151 }
1152 }
1153
1154 sEventCount = j; // this is our new count.
1155 pcp_event_info = realloc(pcp_event_info, // release any extra memory.
1156 sEventCount*sizeof(_pcp_event_info_t)); // ..
1157 if (pcp_event_info == NULL) {
1158 int strErr=snprintf(reason, rLen,
1159 "Could not reallocate %lu bytes of memory for pcp_event_info.", sEventCount*sizeof(_pcp_event_info_t));
1160 reason[rLen-1]=0; // force null termination.
1161 if (strErr > rLen) HANDLE_STRING_ERROR;
1163 goto fn_fail;
1164 } // end if realloc failed.
1165
1166 qsort(pcp_event_info, sEventCount, // sort by PMID, idx, name.
1167 sizeof(_pcp_event_info_t), qsPMID); // ..
1168
1169 _time_gettimeofday(&t2, NULL); // done with index explosion.
1170 _time_fprintf(stderr, "indexedExplosion for all took %li uS.\n",
1172
1173 for (i=0; i<HASH_SIZE; i++) { // init hash table.
1174 sNameHash[i].idx = -1; // unused entry.
1175 sNameHash[i].next = NULL; // ..
1176 }
1177
1178 unsigned int myHash;
1179 for (i=0; i<sEventCount; i++) {
1180 myHash = addNameHash(pcp_event_info[i].name, i); // Point this hash to this entry.
1181 }
1182
1183 //-----------------------------------------------------------------------------------------------------------------------
1184 // *************************************** DEBUG REPORT OF INFORMATION DISCOVERED ***************************************
1185 //-----------------------------------------------------------------------------------------------------------------------
1186 // We use -O2, but even in -O0, if(0){...} is completely removed from code. It costs us nothing to leave this code in.
1187 if (0) { // change to 1 to enable debug report.
1188 unsigned int current, prev=0;
1189 printf("count, hash, name, pmid, value[idx]\n");
1190 for (i=0; i<sEventCount; i++) {
1191 myHash = stringHash(pcp_event_info[i].name, HASH_SIZE); // Get the hash value.
1192 current = pcp_event_info[i].pmid;
1193 if (prev > 0 && current != (prev+1) && current != prev) // print separators.
1194 printf("----,----,----,----\n");
1195 printf("%i, %u, \"%s\", 0x%08X, %i\n", i, myHash, // quote name, may contain \,/,comma, etc.
1197 pcp_event_info[i].pmid,
1198 pcp_event_info[i].idx);
1199 prev=current; // for finding pmid skips.
1200 }
1201
1202 // Test hashing.
1203 int hashErr = 0;
1204 _time_gettimeofday(&t1, NULL);
1205 for (i=0; i<sEventCount; i++) {
1206 int f = findNameHash(pcp_event_info[i].name); // Try to find this name.
1207 if (f != i) hashErr++;
1208 }
1209
1210 _time_gettimeofday(&t2, NULL);
1211
1212 _time_fprintf(stderr, "HashLookup avg uS: %3.6f\n", ((double) (mConvertUsec(t2)-mConvertUsec(t1)) )/((double) sEventCount) );
1213 _time_fprintf(stderr, "Hash Errors: %i of %i.\n", hashErr, sEventCount);
1214
1215 } // END DEBUG REPORT.
1216 //-----------------------------------------------------------------------------------------------------------------------
1217 // *************************************** END DEBUG REPORT INFORMATION DISCOVERED **************************************
1218 //-----------------------------------------------------------------------------------------------------------------------
1219
1220 free(allNames); // Locals allocations not needed anymore.
1221 free(allPMID); // .. the pmIDs we read.
1222 pcp_pmFreeResult(allFetch); // .. release the results we fetched.
1223
1224// For PCP, we can read any number of events at once
1225// in a single event set. Set vector elements for PAPI.
1226
1227 _pcp_vector.cmp_info.num_native_events = sEventCount; // Setup our pcp vector.
1230 _pcp_vector.cmp_info.CmpIdx = cidx; // export the component ID.
1231
1232 fn_exit:
1233 _papi_hwd[cidx]->cmp_info.disabled = retval;
1234 return retval;
1235 fn_fail:
1236 goto fn_exit;
1237} // end routine.
1238
1239
1240//----------------------------------------------------------------------------
1241//----------------------------------------------------------------------------
1242// Control of counters (Reading/Writing/Starting/Stopping/Setup) functions.
1243//----------------------------------------------------------------------------
1244//----------------------------------------------------------------------------
1245
1246//----------------------------------------------------------------------------
1247// Init vars in pcp_context.
1248// This is called immediately after _pcp_init_component.
1249//----------------------------------------------------------------------------
1251{
1252 mRtnCnt(_pcp_init_thread); // count this function.
1253 _pcp_context_t* myCtx = (_pcp_context_t*) ctx; // recast.
1254 myCtx->initDone = 1; // Nothing else to do for init.
1255 return PAPI_OK;
1256} // end routine.
1257
1258
1259//----------------------------------------------------------------------------
1260// The control_state is our internal description of an event set.
1261//----------------------------------------------------------------------------
1263{
1264 mRtnCnt(_pcp_init_control_state); // count this function.
1265 _pcp_control_state_t* control = ( _pcp_control_state_t* ) ctl;
1266 // contents: _pcp_control_state state at this writing:
1267 // contents of state:
1268 // int numEvents; // The number of events we have.
1269 // int maxAllocated; // the current entries in pcpIndex.
1270 // int *pcpIndex; // array of indices into pcp_event_info[].
1271 // long long *values; // Values read from our PCP events.
1272
1273 memset(control, 0, sizeof(_pcp_control_state_t)); // zero it.
1274
1275 return PAPI_OK;
1276} // end routine.
1277
1278
1279//---------------------------------------------------------------------------------------------
1280// update_control_state: PAPI calls this when it adds or removes events
1281// from its EventState; so we can do our component-specific things. The
1282// hwd_control_state_t* is a void pointer, we recast to
1283// _pcp_control_state_t* to get whatever is CURRENTLY in there. We only
1284// need to update that, for now we just re-init it. HOWEVER, we may be
1285// discarding counters we set to counting.
1286// This is called.
1287
1288// NOTE: This code allocates pcpIndex[] in the control and never frees
1289// it. However, the PAPI code in destroying the eventSet calls this
1290// with a zero count; so we free() it then, without reallocating. Also,
1291// the values[] array
1292
1293// NOTE: Also, PAPI *may* call more than once with a zero count on the
1294// control. If you free pcpIndex, set it to NULL, so you don't try to
1295// free it again.
1296
1297// Content of NativeInfo_t:
1298// int ni_event; // native (libpfm4) event code; always non-zero unless empty
1299// int ni_papi_code; // papi event code value returned to papi applications
1300// int ni_position; // counter array position where this native event lives
1301// int ni_owners; // specifies how many owners share this native event
1302// hwd_register_t *ni_bits; // Component defined resources used by this native event
1303//---------------------------------------------------------------------------------------------
1304
1306 hwd_control_state_t *ctl, // Our internal info about events in an event set.
1307 NativeInfo_t *native, // NativeInfoArray in papi.
1308 int count, // NativeCount in papi.
1309 hwd_context_t *ctx) // context, we don't use it.
1310{
1311 mRtnCnt(_pcp_update_control_state); // count this function.
1312 int i, index = 0;
1313 ( void ) ctx;
1314
1315 _pcp_control_state_t* MyCtl = ( _pcp_control_state_t* ) ctl; // Recast ctl.
1316
1317 MyCtl->numEvents = count; // remember how many there are.
1318 if (count == 0) { // If we are deleting a set,
1319 if (MyCtl->pcpIndex != NULL) { // If we have space allocated,
1320 free(MyCtl->pcpIndex); // .. discard it,
1321 free(MyCtl->pcpValue); // .. and values.
1322 MyCtl->pcpIndex = NULL; // .. never free it again.
1323 MyCtl->pcpValue = NULL; // .. never free it again.
1324 }
1325
1326 MyCtl->maxAllocated = 0; // .. no longer tracking max.
1327 return PAPI_OK; // .. get out.
1328 }
1329
1330 // henceforth, count != 0.
1331 #define BlockSize 64 /* constant used multiple times. */
1332 int newalloc = ((count/BlockSize)*BlockSize+BlockSize); // .. pick next up multiple of BlockSize.
1333 #undef BlockSize /*prevent bugs if same name used elsewhere.*/
1334
1335 if (MyCtl->pcpIndex != NULL) { // If I have a previous list of variables,
1336 if (count > MyCtl->maxAllocated) { // .. If I will need more room,
1337 MyCtl->pcpIndex = realloc(MyCtl->pcpIndex, // .. .. reallocate to make more room.
1338 newalloc*sizeof(int)); // .. .. ..
1339 MyCtl->pcpValue = realloc(MyCtl->pcpValue, // .. .. reallocate to make more room.
1340 newalloc*sizeof(unsigned long long));// .. .. ..
1341 MyCtl->maxAllocated = newalloc; // .. .. remember what we've got.
1342 }
1343 } else { // If NULL then I have no previous set,
1344 MyCtl->maxAllocated = newalloc; // .. pick next up multiple of BlockSize.
1345 MyCtl->pcpIndex = // .. make room for 'count' indices,
1346 calloc(MyCtl->maxAllocated, sizeof(int)); // ..
1347 MyCtl->pcpValue = // .. make room for 'count' values.
1348 calloc(MyCtl->maxAllocated, sizeof(unsigned long long)); // ..
1349 }
1350
1351 if (MyCtl->pcpIndex == NULL) { // If malloc failed,
1352 return PAPI_ENOMEM; // .. out of memory.
1353 } // end if malloc failed.
1354
1355 //------------------------------------------------------------------
1356 // pcpIndex alloc managed, now process all events passed in.
1357 // pcpIndex[i] holds the event pcp_event_info[] index for
1358 // EventSet[i], and we populate the caller's ni_position for
1359 // EventSet[i] with the index into pcpIndex[].
1360 //------------------------------------------------------------------
1361
1362 for (i=0; i<count; i++) { // for each event passed in,
1363 index = native[i].ni_event & PAPI_NATIVE_AND_MASK; // get index.
1364 if (index < 0 || index >= sEventCount) { // if something is wrong,
1365 return PAPI_ENOEVNT; // no such event.
1366 } // end if index invalid.
1367
1368 MyCtl->pcpIndex[i]=index; // remember the index.
1369 MyCtl->pcpValue[i]=0; // clear the value.
1370 native[i].ni_position = i; // Tell PAPI about its location (doesn't matter to us), we have no restrictions on position.
1371 getPMDesc(index); // Any time an event is added, ensure we have its variable descriptor.
1372 } // end for each event listed.
1373
1374 return PAPI_OK;
1375} // end routine.
1376
1377
1378//---------------------------------------------------------------------
1379// Helper routine, for reset and read, does the work of reading all
1380// current raw values in an EventSet (hwd_control_state).
1381//
1382// 1) Does not subtract zeroValue; returns raw read in ULL format.
1383// 2) Does not change pcp_event_info[] in any way.
1384// 3) stores values in _pcp_control_state.pcpValue[] for each event.
1385// 4) Returns with 'results' malloc'd by PCP, nest mallocs, SO:
1386// 5) if (results != NULL) pcp_pmFreeResults(results);
1387// 6) must check on 5 EVEN IF THERE WAS AN ERROR.
1388//
1389// RETURNS PAPI error code, or PAPI_OK.
1390//---------------------------------------------------------------------
1391
1392static int PCP_ReadList(hwd_control_state_t *ctl, // the event set.
1393 pmResult **results) // results from pmFetch, caller must pmFreeResult(results).
1394{
1395 int i, j, ret;
1397 *results = NULL; // Nothing allocated.
1398 if (myCtl->numEvents < 1) return PAPI_ENOEVNT; // No events to start.
1399 int nPMID = 0; // To count number of **unique** PMIDs.
1400
1401 pmID *allPMID=malloc((myCtl->numEvents)*sizeof(pmID)); // Make maximum possible room.
1402
1403 // We build a list of all *unique* PMIDs. Because PMID can return
1404 // an array of N values for a single event (e.g. one per CPU), we
1405 // 'explode' such events into N events for PAPI, which can only
1406 // return 1 value per event. Thus PAPI could add several to an
1407 // EventSet that all have the same PMID (PCP's ID). We only need
1408 // to read those once, our pcp_event_info[] contains the index
1409 // for each exploded event into the array returned for that PMID.
1410
1411 allPMID[nPMID++] = pcp_event_info[myCtl->pcpIndex[0]].pmid; // Move the first, increment total so far.
1412
1413 for (i=1; i<myCtl->numEvents; i++) { // For every event in the event set,
1414 int myIdx = myCtl->pcpIndex[i]; // .. Get pcp_event_info[] index of the event,
1415 pmID myPMID = pcp_event_info[myIdx].pmid; // .. get the PMID for that event,
1416 for (j=0; j<nPMID; j++) { // .. Search the unique PMID list for a match.
1417 if (myPMID == allPMID[j]) break; // .. .. found it. break out.
1418 }
1419
1420 if (j == nPMID) { // full loop ==> myPMID was not found in list,
1421 allPMID[nPMID++] = myPMID; // .. store the unique pmid in list, inc count.
1422 }
1423 } // done building list of unique pmid.
1424
1425 // nPMID is # of unique PMID, now ready to read all the pmid needed.
1426 pmResult *allFetch = NULL; // result of pmFetch.
1427 ret = pcp_pmFetch(nPMID, allPMID, &allFetch); // Fetch them all.
1428 *results = allFetch; // For either success or failure.
1429
1430 if( ret != PAPI_OK) { // If fetch failed ..
1431 fprintf(stderr, "%s:%i:%s pcp_pmFetch failed, return=%s.\n",
1432 __FILE__, __LINE__, FUNC, PAPI_strerror(ret)); // .. report error.
1433 if (allPMID != NULL) free(allPMID); // .. no memory leak.
1434 allPMID = NULL; // .. prevent future use.
1435 return(ret); // .. exit with that error.
1436 }
1437
1438 // For each unique PMID we just read, we must map it to the event
1439 // sets, which may contain multiple entries with that same PMID.
1440 // This is because PCP returns arrays, and PAPI does not, so each
1441 // of our names translates to a PMID + an index.
1442
1443 for (i=0; i<nPMID; i++) { // process all the fetch results.
1444 pmValueSet *vset = allFetch->vset[i]; // get the result for event[i].
1445 pmID myPMID = allPMID[i]; // get the pmid from this read.
1446
1447 // Now we must search for any events with this pmid, and get
1448 // the corresponding value (may be more than one, since we
1449 // treat each idx as its own value).
1450
1451 for (j=0; j<myCtl->numEvents; j++) { // for each event,
1452 int myPCPIdx = myCtl->pcpIndex[j]; // .. get my pcp_event_info[] index.
1453 pmID thisPMID = pcp_event_info[myPCPIdx].pmid; // .. collect its pmid.
1454 if (thisPMID == myPMID) { // .. If this result services that event,
1455 int myArrayIdx = pcp_event_info[myPCPIdx].idx; // .. .. get array index within result array, for result value list.
1456 myCtl->pcpValue[j] = getULLValue(vset, myArrayIdx); // .. .. translate as needed, put back into pcpValue array.
1457 } // end if counter was found for this PMID.
1458 } // end loop through all events in this event set.
1459 } // end for each pmID read.
1460
1461 if (allPMID != NULL) free(allPMID); // Done with this work area; no memory leak.
1462 return PAPI_OK; // All done.
1463} // end routine.
1464
1465
1466//----------------------------------------------------------------------------
1467// Reset counters.
1468//---------------------------------------------------------------------------
1470{
1471 mRtnCnt(_pcp_reset); // count this function.
1472 ( void ) ctx; // avoid unused var warning.
1473 int i, k, ret;
1474 unsigned long long aValue;
1475
1476 pmResult *allFetch; // vars to be allocated by call.
1477 _pcp_control_state_t* myCtl = ( _pcp_control_state_t* ) ctl; // make a shortcut.
1478
1479 ret = PCP_ReadList(ctl, &allFetch); // Read the list of events we were given.
1480 if (ret != PAPI_OK) { // If that failed,
1481 fprintf(stderr, "%s:%i:%s PCP_ReadList failed, return=%s.\n",
1482 __FILE__, __LINE__, FUNC, PAPI_strerror(ret)); // report error.
1483 if (allFetch != NULL) pcp_pmFreeResult(allFetch); // free if it was allocated.
1484 return(ret); // exit with that error.
1485 }
1486
1487 // We have all the results; the values read have been extracted
1488 // and stored the control state. Now set them as the zeroValue
1489 // in each pcp_event_info[].
1490
1491 for (i=0; i<myCtl->numEvents; i++) { // for each event,
1492 k = myCtl->pcpIndex[i]; // .. get pcp_event_info[] index.
1493 aValue = myCtl->pcpValue[i]; // .. get the value for that event.
1494 pcp_event_info[k].zeroValue = aValue; // .. reset the counter.
1495 } // end loop through all events in this event set.
1496
1497 // That is all we do; reset the zeroValue to the current value.
1498 // For efficiency we do not check if it is a counter, instantaneous
1499 // or discrete value; that is done in subZero.
1500 pcp_pmFreeResult(allFetch); // .. Clean up.
1501 return PAPI_OK;
1502} // end routine.
1503
1504
1505//---------------------------------------------------------------------
1506// Start counters. We just reset the counters; read them and set
1507// zeroValue on each.
1508//---------------------------------------------------------------------
1509
1511{
1512 mRtnCnt(_pcp_start); // count this function.
1513 _pcp_reset(ctx, ctl); // Just reset counters.
1514 return PAPI_OK;
1515} // end routine.
1516
1517
1518//---------------------------------------------------------------------
1519// read several pcp values.
1520// This is triggered by PAPI_read( int EventSet, long long *values).
1521// However, the **events that we see is NOT the *values which is an
1522// array done by the application (or caller of PAPI_read). Instead,
1523// we must give *event the address of an array of our values.
1524// The eventSet is represented by ctx and ctl, for us ctx is empty.
1525// The flags are a copy of PAPI's EventSetInfo_t.state, including
1526// PAPI_RUNNING, PAPI_STOPPED and other flags. We ignore that here.
1527//---------------------------------------------------------------------
1528
1529static int _pcp_read(hwd_context_t *ctx, // unused.
1530 hwd_control_state_t *ctl, // contains pmIDs in event set.
1531 long long **events, // for our returns.
1532 int flags) // unused; EventSetInfo_t.state.
1533{
1534 mRtnCnt(_pcp_read); // count this function.
1535 (void) ctx; // avoid unused var warning.
1536 (void) flags; // ..
1537
1538 _pcp_control_state_t* myCtl = ( _pcp_control_state_t* ) ctl; // make a shortcut.
1539 int i, ret;
1540 pmResult *allFetch; // vars to be allocated by call.
1541 if (events == NULL) {
1542 fprintf(stderr, "%s:%i:%s 'events' is null.\n",
1543 __FILE__, __LINE__, FUNC); // report error.
1544 return(PAPI_EINVAL); // invalid argument.
1545 }
1546
1547 ret = PCP_ReadList(ctl, &allFetch); // Read the list of events we were given.
1548 if (ret != PAPI_OK) { // If that failed,
1549 fprintf(stderr, "%s:%i:%s PCP_ReadList failed, return=%s.\n",
1550 __FILE__, __LINE__, FUNC, PAPI_strerror(ret)); // report error.
1551 return(ret); // exit with that error.
1552 }
1553
1554 // We have all the results and values extracted from them.
1555 // Now subtract zero value from them.
1556
1557 for (i=0; i<myCtl->numEvents; i++) { // for each event,
1558 subZero(myCtl, i); // .. subtract zero value in proper type. [TONY DON"T COMMENT OUT, JUST DEBUG]
1559 } // end loop through all events in this event set.
1560
1561 // Done, point the caller to our results list.
1562 *events = (long long *) myCtl->pcpValue; // pointer the caller needs.
1563 pcp_pmFreeResult(allFetch); // Clean up.
1564 return PAPI_OK; // exit, all okay.
1565} // end routine.
1566
1567
1568//---------------------------------------------------------------------
1569// stop counters. (does nothing).
1570//---------------------------------------------------------------------
1572{
1573 mRtnCnt(_pcp_stop); // count this function.
1574 (void) ctx; // avoid var unused warning.
1575 (void) ctl; // avoid var unused warning.
1576 return PAPI_OK;
1577} // end routine.
1578
1579
1580//---------------------------------------------------------------------
1581// shutdown thread. (does nothing).
1582//---------------------------------------------------------------------
1584{
1585 mRtnCnt(_pcp_shutdown_thread); // count this function.
1586 ( void ) ctx; // avoid var unused warning.
1587
1588 return PAPI_OK;
1589} // end routine.
1590
1591
1592//---------------------------------------------------------------------
1593// shutdown PCP component. (frees allocs).
1594//---------------------------------------------------------------------
1596{
1597 int i;
1598 mRtnCnt(_pcp_shutdown_component); // count this function.
1599 pcp_pmDestroyContext(ctxHandle); // context handle; fails to free malloced memory, says valgrind.
1600 ctxHandle = -1; // reset to prevent reuse.
1601 free(pcp_event_info); pcp_event_info=NULL; // then pcp_event_info, reset.
1602 freeNameHash(); // free sNameHash. resets itself.
1603 cachedGetInDom(PM_INDOM_NULL, -1); // -1 for inst == free its local static mallocs.
1604 sEventCount = 0; // clear number of events.
1605
1606 for (i=0; i<=ctr_pcp_ntv_code_to_info; i++)
1607 _prog_fprintf(stderr, "routine counter %i = %i.\n", i, cnt[i]);
1608
1609 return PAPI_OK;
1610} // end routine.
1611
1612
1613//---------------------------------------------------------------------
1614// This function sets options in the component.
1615// The valid codes being passed in are PAPI_DEFDOM, PAPI_DOMAIN,
1616// PAPI_DEFGRN, PAPI_GRANUL and PAPI_INHERIT.
1617
1618// _papi_int_option_t:
1619// _papi_int_overflow_t overflow;
1620// _papi_int_profile_t profile;
1621// _papi_int_domain_t domain; // PAPI_SET_DEFDOM, PAPI_SET_DOMAIN
1622// _papi_int_attach_t attach;
1623// _papi_int_cpu_t cpu;
1624// _papi_int_multiplex_t multiplex;
1625// _papi_int_itimer_t itimer;
1626// _papi_int_inherit_t inherit; // PAPI_SET_INHERIT
1627// _papi_int_granularity_t granularity; // PAPI_SET_DEFGRN, PAPI_SET_GRANUL
1628// _papi_int_addr_range_t address_range;
1629//---------------------------------------------------------------------
1630
1631static int _pcp_ctl (hwd_context_t *ctx, int code, _papi_int_option_t *option)
1632{
1633 mRtnCnt(_pcp_ctl); // count this function.
1634 ( void ) ctx; // avoid var unused warning.
1635 ( void ) code; // avoid var unused warning.
1636 ( void ) option; // avoid var unused warning.
1637
1638 switch (code) {
1639 case PAPI_DEFDOM:
1640 SUBDBG("PAPI_DEFDOM, option.domain=0x%08X\n", (unsigned int) option->domain.domain);
1641 break;
1642
1643 case PAPI_DOMAIN:
1644 SUBDBG("PAPI_DOMAIN, option.domain=0x%08X\n", (unsigned int) option->domain.domain);
1645 break;
1646
1647 case PAPI_DEFGRN:
1648 SUBDBG("PAPI_DEFGRN, option.granularity=0x%08X\n", (unsigned int) option->granularity.granularity);
1649 break;
1650
1651 case PAPI_GRANUL:
1652 SUBDBG("PAPI_GRANUL, option.granularity=0x%08X\n", (unsigned int) option->granularity.granularity);
1653 break;
1654
1655 case PAPI_INHERIT:
1656 SUBDBG("PAPI_INHERIT, option.inherit=0x%08X\n", (unsigned int) option->inherit.inherit);
1657 break;
1658
1659 default:
1660 fprintf(stderr, "%s:%i:%s CODE 0x%08x IS INVALID "
1661 "OR UNRECOGNIZED.\n", __FILE__, __LINE__, FUNC, code);
1662 return PAPI_EINVAL; // Invalid code.
1663 break;
1664 } // end switch by code.
1665
1666 return PAPI_OK;
1667} // end routine.
1668
1669
1670//----------------------------------------------------------------------------
1671// This function has to set the bits needed to count different domains.
1672// PAPI_DOM_USER : only user context is counted
1673// PAPI_DOM_KERNEL : only the Kernel/OS context is counted
1674// PAPI_DOM_OTHER : Exception/transient mode (like user TLB misses)
1675// PAPI_DOM_ALL : all of the domains, THE ONLY ONE WE ACCEPT!
1676// All other domains result in an invalid value.
1677//----------------------------------------------------------------------------
1678static int _pcp_set_domain(hwd_control_state_t *ctl, int domain)
1679{
1680 mRtnCnt(_pcp_set_domain); // count this function.
1681 (void) ctl; // avoid var unused warning.
1682 if ( PAPI_DOM_ALL != domain ) return PAPI_EINVAL; // Reject if not this one.
1683 return PAPI_OK; // Otherwise, OK, nothing to do.
1684} // end routine.
1685
1686
1687//----------------------------------------------------------------------------
1688//----------------------------------------------------------------------------
1689// NATIVE EVENT ROUTINES.
1690//----------------------------------------------------------------------------
1691//----------------------------------------------------------------------------
1692
1693//----------------------------------------------------------------------------
1694// Enumerate events. PAPI_NTV_ENUM_UMASKS has nothing to do; we don't have
1695// qualifying masks or options on any of our events.
1696//----------------------------------------------------------------------------
1697
1698static int _pcp_ntv_enum_events(unsigned int *EventCode, int modifier)
1699{
1700 mRtnCnt(_pcp_ntv_enum_events); // count this function.
1701 int idx;
1702
1703 switch (modifier) { // modifier is type of enum operation desired.
1704 case PAPI_ENUM_FIRST: // Returns event code of first event created.
1705 EventCode[0] = 0; // Return 0 as event code after a start.
1706 return PAPI_OK; // EXIT.
1707 break; // END CASE.
1708
1709 // return EventCode of next available event.
1710 case PAPI_ENUM_EVENTS: // enum base events (which is all events).
1711 idx = EventCode[0] & PAPI_NATIVE_AND_MASK; // Take off any hi order flag bits.
1712 if ((++idx) >= sEventCount) return PAPI_ENOEVNT; // If we reach an invalid idx for pcp_event_info[], exit. Does nothing to EventCode.
1713 EventCode[0] = idx | PAPI_NATIVE_MASK; // If index was valid, we return it.
1714 return PAPI_OK; // And exit.
1715 break; // END CASE.
1716
1717 case PAPI_NTV_ENUM_UMASKS: // Note we HAVE no qualifiers or masks.
1718 return PAPI_ENOEVNT; // There are no qualifiers to list.
1719
1720 default: // If we don't understand the modifier,
1721 return PAPI_ENOEVNT; // .. Presets or other stuff, just say we have none.
1722 break; // END CASE.
1723 } // end switch(modifier).
1724
1725 return PAPI_EBUG; // Dummy return; should have exited from inside switch.
1726} // end routine.
1727
1728
1729//----------------------------------------------------------------------------
1730// Given a string, find the name in the pcp_event_info[] array.
1731//---------------------------------------------------------------------------
1732static int _pcp_ntv_name_to_code(const char *name, unsigned int *event_code)
1733{
1734 mRtnCnt(_pcp_ntv_name_to_code); // count this function.
1735
1736 if (name == NULL || strlen(name)<1) { // Invalid name argument.
1737 fprintf(stderr, "%s:%i:%s Invalid name.\n", // .. report it.
1738 __FILE__, __LINE__, FUNC);
1739 return PAPI_EINVAL; // .. Invalid argument.
1740 }
1741
1742 if (event_code == NULL) { // Invalid event_code pointer.
1743 fprintf(stderr, "%s:%i:%s event_code is not a valid pointer.\n", // .. report it.
1744 __FILE__, __LINE__, FUNC);
1745 return PAPI_EINVAL; // .. Invalid argument.
1746 }
1747
1748 int idx = findNameHash((char*) name); // Use our hash to find it.
1749 if (idx < 0) { // If we failed,
1750 fprintf(stderr, "%s:%i:%s Failed to find name='%s', hash=%i.\n", // .. report it.
1751 __FILE__, __LINE__, FUNC, name,
1752 stringHash((char*) name, HASH_SIZE)); // ..
1753 return PAPI_EINVAL; // .. Invalid argument.
1754 }
1755
1756 *event_code = idx; // return with the index we found.
1757 return PAPI_OK;
1758} // end routine.
1759
1760
1761//----------------------------------------------------------------------------
1762// Collect the name of the event from the EventCode, given here as our index
1763// into pcp_event_info[]. We must fit it into name[len].
1764//----------------------------------------------------------------------------
1765static int _pcp_ntv_code_to_name(unsigned int pcpIdx, char *name, int len)
1766{
1767 mRtnCnt(_pcp_ntv_code_to_name); // count this function.
1768
1769 pcpIdx &= PAPI_NATIVE_AND_MASK; // We can be called with the NATIVE bit set.
1770 if (pcpIdx >= (unsigned int) sEventCount) { // out of range?
1771 fprintf(stderr, "%s:%i:%s called with out-of-range pcpIdx=%u.\n",
1772 __FILE__, __LINE__, FUNC, pcpIdx);
1773 return PAPI_EINVAL; // exit with error.
1774 }
1775
1776 if (len < 1) { // If length is ridiculous,
1777 fprintf(stderr, "%s:%i:%s called with out-of-range descr len=%i.\n",
1778 __FILE__, __LINE__, FUNC, len);
1779 return PAPI_EINVAL; // exit with error.
1780 }
1781
1782 strncpy(name, pcp_event_info[pcpIdx].name, len); // just copy the name.
1783 name[len-1]=0; // force z-termination.
1784
1785 return PAPI_OK;
1786} // end routine.
1787
1788
1789//----------------------------------------------------------------------------
1790// Collect the text description of the EventCode; which is our index into our
1791// pcp_event_info[] array. We must fit it into descr[len].
1792//---------------------------------------------------------------------------
1793
1794static int _pcp_ntv_code_to_descr(unsigned int pcpIdx, char *descr, int len)
1795{
1796 mRtnCnt(_pcp_ntv_code_to_descr); // count this function.
1797
1798 pcpIdx &= PAPI_NATIVE_AND_MASK; // We might be called with the NATIVE bit set.
1799 if (pcpIdx >= (unsigned int) sEventCount) { // out of range?
1800 fprintf(stderr, "%s:%i:%s called with out-of-range pcpIdx=%u.\n",
1801 __FILE__, __LINE__, FUNC, pcpIdx);
1802 return PAPI_EINVAL; // exit with error.
1803 }
1804
1805 if (len < 1) { // If length is ridiculous,
1806 fprintf(stderr, "%s:%i:%s called with out-of-range descr len=%i.\n",
1807 __FILE__, __LINE__, FUNC, len);
1808 return PAPI_EINVAL; // exit with error.
1809 }
1810
1811 char *helpText = NULL; // pointer to receive the result.
1812 int ret = getHelpText(pcpIdx, &helpText); // get it.
1813 if (ret != PAPI_OK) { // If there is any error,
1814 if (helpText != NULL) free(helpText); // .. no memory leak.
1815 fprintf(stderr, "%s:%i:%s failed getHelpText; it returned %s.\n",
1816 __FILE__, __LINE__, FUNC, PAPI_strerror(ret));
1817 return ret; // exit with whatever PAPI error routine had.
1818 }
1819
1820 strncpy(descr, helpText, len); // copy it over.
1821 descr[len-1] = 0; // force a z-terminator.
1822 free(helpText); // release text alloc by pm routine.
1823 return PAPI_OK; // EXIT, all good.
1824} // end routine.
1825
1826
1827//---------------------------------------------------------------------
1828// Fill in the PAPI_event_info_t vars. This is not a required
1829// function for a component, not all fields require filling in.
1830// Components that implement this feature generally complete the
1831// following fields:
1832
1833// char symbol[PAPI_HUGE_STR_LEN]; // (1024 char, name of the event),
1834// char long_descr[PAPI_HUGE_STR_LEN]; // (1024 char, can be a paragraph);
1835// char units[PAPI_MIN_STR_LEN]; // (64 chars, unit of measurement);
1836// int data_type; // data type returned by PAPI.
1837//
1838// data_type is PAPI_DATATYPE_INT64, PAPI_DATATYPE_UINT64,
1839// PAPI_DATATYPE_FP64, PAPI_DATATYPE_BIT64.
1840// We translate all values into INT64, UINT64, or FP64.
1841//
1842// timescope; // Counter or instantaneous.
1843// PAPI_TIMESCOPE_SINCE_START // Data is cumulative from start.
1844// PAPI_TIMESCOPE_POINT // Data is an instantaneous value.
1845//---------------------------------------------------------------------
1846
1847static int _pcp_ntv_code_to_info(unsigned int pcpIdx, PAPI_event_info_t *info)
1848{
1849 mRtnCnt(_pcp_ntv_code_to_info); // count this function.
1850 int len, ret;
1851
1852 pcpIdx &= PAPI_NATIVE_AND_MASK; // remove any high order bits.
1853 if (pcpIdx >= (unsigned int) sEventCount) { // out of range?
1854 fprintf(stderr, "%s:%i:%s called with out-of-range pcpIdx=%u.\n",
1855 __FILE__, __LINE__, FUNC, pcpIdx);
1856 return PAPI_EINVAL; // exit with error.
1857 }
1858
1859 len=sizeof(info->symbol); // get length.
1860 strncpy(info->symbol, pcp_event_info[pcpIdx].name, len); // Copy.
1861 info->symbol[len-1] = 0; // force z-terminator.
1862
1863 len=sizeof(info->long_descr); // get length.
1864 ret = _pcp_ntv_code_to_descr(pcpIdx, info->long_descr, len); // copy to info.
1865 if (ret != PAPI_OK) return(ret); // return on failure. _pcp_ntv_code_to_descr already printed error.
1866
1867 // Units resides in pmDesc; we need to get it if we don't already
1868 // have it (multi-valued events got it during init).
1869
1870 getPMDesc(pcpIdx); // get the description.
1871
1872 char unitStr[64];
1873 // This routine has been timed over 19600 trials on Saturn;
1874 // it requires an average of 2 uS. No daemon comm needed.
1875
1876 pcp_pmUnitsStr_r(&pcp_event_info[pcpIdx].desc.units, unitStr, 64); // Construct the unit string; needs at least 60 char.
1877 if ( strlen(unitStr) == 0) {
1878 sprintf(unitStr, "fraction"); // Only ever seen for 'dutycycle' events.
1879
1880 // Following is for debug purposes.
1881 if (0) { // Alternatively, show the details of the PCP units descriptor.
1882 sprintf(unitStr, "[%u, %i, %u, %u, %i, %i, %i]",
1883 pcp_event_info[pcpIdx].desc.units.pad,
1884 pcp_event_info[pcpIdx].desc.units.scaleCount,
1885 pcp_event_info[pcpIdx].desc.units.scaleTime,
1886 pcp_event_info[pcpIdx].desc.units.scaleSpace,
1887 pcp_event_info[pcpIdx].desc.units.dimCount,
1888 pcp_event_info[pcpIdx].desc.units.dimTime,
1889 pcp_event_info[pcpIdx].desc.units.dimSpace
1890 );
1891 }
1892 }
1893
1894 len = sizeof(info->units); // length of destination.
1895 strncpy( info->units, unitStr, len); // copy it over.
1896 info->units[len-1] = 0; // ensure a z-terminator.
1897
1898 switch (pcp_event_info[pcpIdx].valType) { // Translate this to a papi value.
1899
1900 case PM_TYPE_32: // 32 bit was converted to long long.
1901 case PM_TYPE_64: // long long.
1902 info->data_type = PAPI_DATATYPE_INT64; // What papi needs.
1903 break; // END CASE.
1904
1905 case PM_TYPE_U32: // 32-bit was converted to 64 bit.
1906 case PM_TYPE_U64: // 64-bit unsigned integer
1907 case PM_TYPE_STRING: // array of char pointer.
1908 info->data_type = PAPI_DATATYPE_UINT64; // What papi needs.
1909 break; // END CASE.
1910
1911 case PM_TYPE_FLOAT: // 32-bit was converted to double.
1912 case PM_TYPE_DOUBLE: // 64-bit floating point
1913 info->data_type = PAPI_DATATYPE_FP64; // What papi needs.
1914 break; // END CASE.
1915 };
1916
1917 if (pcp_event_info[pcpIdx].desc.sem == PM_SEM_COUNTER) { // If we have a counter,
1918 info->timescope = PAPI_TIMESCOPE_SINCE_START; // .. normal stuff.
1919 } else { // An instantaneous value.
1920 info->timescope = PAPI_TIMESCOPE_POINT; // .. What PAPI calls that.
1921 }
1922
1923 return PAPI_OK; // exit.
1924} // end routine.
1925
1926//----------------------------------------------------------------------------
1927//----------------------------------------------------------------------------
1928// PCP Vector definition.
1929//---------------------------------------------------------------------------
1930//----------------------------------------------------------------------------
1931
1933 .cmp_info = { /* (unspecified values are initialized to 0) */
1934 .name = "pcp",
1935 .short_name = "pcp",
1936 .description = "Performance Co-Pilot",
1937 .version = "5.6.1",
1938 .default_domain = PAPI_DOM_ALL,
1939 .default_granularity = PAPI_GRN_SYS,
1940 .available_granularities = PAPI_GRN_SYS,
1941 .hardware_intr_sig = PAPI_INT_SIGNAL,
1942 .available_domains = PAPI_DOM_ALL,
1943 },
1944
1945 /* sizes of framework-opaque component-private structures */
1946 .size = {
1947 .context = sizeof ( _pcp_context_t ),
1948 .control_state = sizeof ( _pcp_control_state_t ),
1949 .reg_value = sizeof ( _pcp_register_t ),
1950 .reg_alloc = sizeof ( _pcp_reg_alloc_t ),
1951 },
1952
1953 /* function pointers in this component */
1954 .init_thread = _pcp_init_thread,
1955 .init_component = _pcp_init_component,
1956 .init_control_state = _pcp_init_control_state,
1957 .start = _pcp_start,
1958 .stop = _pcp_stop,
1959 .read = _pcp_read,
1960 .shutdown_thread = _pcp_shutdown_thread,
1961 .shutdown_component = _pcp_shutdown_component,
1962 .ctl = _pcp_ctl,
1963
1964 .update_control_state= _pcp_update_control_state,
1965 .set_domain = _pcp_set_domain,
1966 .reset = _pcp_reset,
1967
1968 .ntv_enum_events = _pcp_ntv_enum_events,
1969 .ntv_name_to_code = _pcp_ntv_name_to_code,
1970 .ntv_code_to_name = _pcp_ntv_code_to_name,
1971 .ntv_code_to_descr = _pcp_ntv_code_to_descr,
1972 .ntv_code_to_info = _pcp_ntv_code_to_info,
1973}; // end pcp_vector.
static papi_handle_t handle
Definition: Gamum.c:21
volatile int result
int i
const char * names[NUM_EVENTS]
static long count
Returns a string describing the PAPI error code.
struct papi_vectors * _papi_hwd[]
double f(double a)
Definition: cpi.c:23
volatile int buf[CACHE_FLUSH_BUFFER_SIZE_INTS]
Definition: do_loops.c:12
volatile double t1
#define PAPI_TIMESCOPE_POINT
Definition: f90papi.h:63
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_EBUG
Definition: f90papi.h:176
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_DEFGRN
Definition: f90papi.h:26
#define PAPI_GRANUL
Definition: f90papi.h:179
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_DATATYPE_FP64
Definition: f90papi.h:171
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_DATATYPE_UINT64
Definition: f90papi.h:278
#define PAPI_DOMAIN
Definition: f90papi.h:159
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_INHERIT
Definition: f90papi.h:76
#define PAPI_NTV_ENUM_UMASKS
Definition: f90papi.h:66
#define PAPI_TIMESCOPE_SINCE_START
Definition: f90papi.h:124
#define PAPI_GRN_SYS
Definition: f90papi.h:43
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_EATTR
Definition: f90papi.h:97
#define PAPI_EBUF
Definition: f90papi.h:253
#define PAPI_ENOIMPL
Definition: f90papi.h:219
#define PAPI_DATATYPE_INT64
Definition: f90papi.h:227
#define PAPI_DEFDOM
Definition: f90papi.h:188
#define PAPI_HUGE_STR_LEN
Definition: f90papi.h:120
#define PAPI_DOM_ALL
Definition: f90papi.h:261
char events[MAX_EVENTS][BUFSIZ]
static pthread_key_t key
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
static int _pcp_ntv_name_to_code(const char *name, unsigned int *event_code)
Definition: linux-pcp.c:1732
static unsigned long long getULLValue(pmValueSet *vset, int value_index)
Definition: linux-pcp.c:689
static int _local_linkDynamicLibraries(void)
Definition: linux-pcp.c:419
#define mConvertUsec(timeval_)
Definition: linux-pcp.c:239
#define _time_gettimeofday
Definition: linux-pcp.c:244
static int pcp_pmLookupDesc(pmID pmid, pmDesc *desc)
Definition: linux-pcp.c:299
static int _pcp_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: linux-pcp.c:1529
static unsigned int stringHash(char *str, unsigned int tableSize)
Definition: linux-pcp.c:320
static void pcp_pmFreeResult(pmResult *result)
Definition: linux-pcp.c:287
static int getHelpText(unsigned int pcpIdx, char **helpText)
Definition: linux-pcp.c:815
#define FUNC
Definition: linux-pcp.c:36
static int _pcp_shutdown_component(void)
Definition: linux-pcp.c:1595
static int _pcp_shutdown_thread(hwd_context_t *ctx)
Definition: linux-pcp.c:1583
static char * pcp_pmErrStr(int code)
Definition: linux-pcp.c:281
static int _pcp_init_thread(hwd_context_t *ctx)
Definition: linux-pcp.c:1250
#define LNBLOCK
#define _prog_fprintf
Definition: linux-pcp.c:242
static char pcp_main[]
Definition: linux-pcp.c:251
static int ctxHandle
Definition: linux-pcp.c:192
static int sEventInfoBlock
Definition: linux-pcp.c:189
static int _pcp_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: linux-pcp.c:1631
static void * dl1
Definition: linux-pcp.c:248
#define AGENT_NAME
Definition: linux-pcp.c:42
static void makeQualifiedEvent(int baseEvent, int idx, char *qualifier)
Definition: linux-pcp.c:532
static int _pcp_init_component(int cidx)
Definition: linux-pcp.c:856
int _papi_hwi_debug
Definition: linux-pcp.c:187
static int _pcp_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-pcp.c:1510
static void subZero(_pcp_control_state_t *myCtl, int event)
Definition: linux-pcp.c:763
static int pcp_pmDestroyContext(int handle)
Definition: linux-pcp.c:293
static int sEventCount
Definition: linux-pcp.c:191
static void cbPopulateNameOnly(const char *name)
Definition: linux-pcp.c:511
static int _pcp_ntv_code_to_name(unsigned int pcpIdx, char *name, int len)
Definition: linux-pcp.c:1765
static int _pcp_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-pcp.c:1571
static int pcp_pmTraversePMNS(const char *name, void(*func)(const char *))
Definition: linux-pcp.c:284
static int _pcp_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: linux-pcp.c:1698
#define BlockSize
#define hostnameLen
static int _pcp_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-pcp.c:1469
#define PM_CONTEXT_HOST
Definition: linux-pcp.c:58
#define _time_fprintf
Definition: linux-pcp.c:243
static int _pcp_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: linux-pcp.c:1305
static int pcp_pmGetInDom(pmInDom indom, int **instlist, char ***namelist)
Definition: linux-pcp.c:302
static _pcp_hash_t sNameHash[HASH_SIZE]
Definition: linux-pcp.c:195
static unsigned int addNameHash(char *key, int idx)
Definition: linux-pcp.c:336
static int findNameHash(char *key)
Definition: linux-pcp.c:377
static int sEventInfoSize
Definition: linux-pcp.c:188
static _pcp_event_info_t * pcp_event_info
Definition: linux-pcp.c:190
void(* _dl_non_dynamic_init)(void)
Definition: linux-pcp.c:260
static int _pcp_ntv_code_to_descr(unsigned int pcpIdx, char *descr, int len)
Definition: linux-pcp.c:1794
static int pcp_pmLookupText(pmID pmid, int level, char **buffer)
Definition: linux-pcp.c:305
static struct timeval t1 t2
Definition: linux-pcp.c:238
static char * pcp_pmUnitsStr_r(const pmUnits *pu, char *buf, int buflen)
Definition: linux-pcp.c:308
static int _pcp_init_control_state(hwd_control_state_t *ctl)
Definition: linux-pcp.c:1262
static int PCP_ReadList(hwd_control_state_t *ctl, pmResult **results)
Definition: linux-pcp.c:1392
#define HASH_SIZE
Definition: linux-pcp.c:194
static void freeNameHash(void)
Definition: linux-pcp.c:358
static int pcp_pmNewContext(int type, const char *name)
Definition: linux-pcp.c:290
static int _pcp_set_domain(hwd_control_state_t *ctl, int domain)
Definition: linux-pcp.c:1678
static void getPMDesc(int pcpIdx)
Definition: linux-pcp.c:576
static int qsPMID(const void *arg1, const void *arg2)
Definition: linux-pcp.c:490
static int pcp_pmFetch(int numpid, pmID *pmidlist, pmResult **result)
Definition: linux-pcp.c:296
#define mGet_DL_FPtr(Name)
Definition: linux-pcp.c:409
static char * cachedGetInDom(pmInDom indom, int inst)
Definition: linux-pcp.c:612
#define mRtnCnt(funcname)
Definition: linux-pcp.c:227
static int _pcp_ntv_code_to_info(unsigned int pcpIdx, PAPI_event_info_t *info)
Definition: linux-pcp.c:1847
#define HANDLE_STRING_ERROR
Definition: linux-pcp.c:65
papi_vector_t _pcp_vector
Definition: linux-pcp.c:182
uint16_t type
unsigned long AO_t __attribute__((__aligned__(4)))
Definition: m68k.h:21
#define PAPI_NATIVE_AND_MASK
#define PAPI_NATIVE_MASK
Return codes and api definitions.
#define DEBUG_SUBSTRATE
Definition: papi_debug.h:27
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
FILE * stderr
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
static int native
static int cidx
const char * name
Definition: rocs.c:225
int
Definition: sde_internal.h:89
long long int long long
Definition: sde_internal.h:85
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:969
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:960
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:963
unsigned long long * pcpValue
Definition: linux-pcp.c:144
char name[PAPI_MAX_STR_LEN]
Definition: linux-pcp.c:108
unsigned long long zeroValue
Definition: linux-pcp.c:116
void * next
Definition: linux-pcp.c:165
_pcp_register_t ra_bits
Definition: linux-pcp.c:126
unsigned int selector
Definition: linux-pcp.c:97
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
_papi_int_domain_t domain
_papi_int_granularity_t granularity
_papi_int_inherit_t inherit
unsigned long long ull
Definition: benchSANVML.c:138
unsigned char ch[8]
Definition: benchSANVML.c:141
long long ll
Definition: benchSANVML.c:137
unsigned long long * ullPtr
Definition: benchSANVML.c:129
char * cPtr
Definition: benchSANVML.c:132
int * iPtr
Definition: benchSANVML.c:125
float * fPtr
Definition: benchSANVML.c:130
double * dPtr
Definition: benchSANVML.c:131
long long * llPtr
Definition: benchSANVML.c:128
unsigned int * uiPtr
Definition: benchSANVML.c:126
char * descr
int retval
Definition: zero_fork.c:53