PAPI 7.1.0.0
Loading...
Searching...
No Matches
sde_lib.c
Go to the documentation of this file.
1
11#include "sde_lib_internal.h"
12#include "sde_lib_lock.h"
13
14#define DLSYM_CHECK(name) \
15 do { \
16 if ( NULL != (err=dlerror()) ) { \
17 name##_ptr = NULL; \
18 SDEDBG("obtain_papi_symbols(): Unable to load symbol %s: %s\n", #name, err);\
19 return; \
20 } \
21 } while (0)
22
23static long long sdei_compute_q1(void *param);
24static long long sdei_compute_med(void *param);
25static long long sdei_compute_q3(void *param);
26static long long sdei_compute_min(void *param);
27static long long sdei_compute_max(void *param);
28static inline long long sdei_compute_quantile(void *param, int percent);
29static inline long long sdei_compute_edge(void *param, int which_edge);
30
31int papi_sde_compare_long_long(const void *p1, const void *p2);
32int papi_sde_compare_int(const void *p1, const void *p2);
33int papi_sde_compare_double(const void *p1, const void *p2);
34int papi_sde_compare_float(const void *p1, const void *p2);
35
37papisde_control_t *_papisde_global_control = NULL;
39
40#if defined(USE_LIBAO_ATOMICS)
42#else //defined(USE_LIBAO_ATOMICS)
44#endif //defined(USE_LIBAO_ATOMICS)
45
46/*******************************************************************************/
47/* Function pointers magic for functions that we expect to access from libpapi */
48/*******************************************************************************/
49
50__attribute__((__common__)) void (*papi_sde_check_overflow_status_ptr)(uint32_t cntr_id, long long int value);
52
53static inline void
54sdei_check_overflow_status(uint32_t cntr_uniq_id, long long int latest){
56 (*papi_sde_check_overflow_status_ptr)(cntr_uniq_id, latest);
57}
58
59inline int
63 return -1;
64}
65
66/*
67 The folling function will look for symbols from libpapi.so. If the application
68 that linked against libsde has used the static PAPI library (libpapi.a)
69 then dlsym will fail to find them, but the __attribute__((__common__)) should
70 do the trick.
71*/
72static inline void obtain_papi_symbols(void){
73 char *err;
74 int dlsym_err = 0;
75
76 // In case of static linking the function pointers will be automatically set
77 // by the linker and the dlopen()/dlsym() would fail at runtime, so we want to
78 // check if the linker has done its magic first.
81 ){
82 return;
83 }
84
85 (void)dlerror(); // Clear the internal string so we can diagnose errors later on.
86
87 void *handle = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
88 if( NULL != (err = dlerror()) ){
89 SDEDBG("obtain_papi_symbols(): %s\n",err);
90 dlsym_err = 1;
91 return;
92 }
93
94 // We need this function to inform the SDE component in libpapi about the value of created counters.
95 papi_sde_check_overflow_status_ptr = dlsym(handle, "papi_sde_check_overflow_status");
97
98 papi_sde_set_timer_for_overflow_ptr = dlsym(handle, "papi_sde_set_timer_for_overflow");
100
101 if( !dlsym_err ){
102 SDEDBG("obtain_papi_symbols(): All symbols from libpapi.so have been successfully acquired.\n");
103 }
104
105 return;
106}
107
108
109/*************************************************************************/
110/* API Functions for libraries. */
111/*************************************************************************/
112
119papi_sde_init(const char *name_of_library)
120{
121 papisde_library_desc_t *tmp_lib;
122
123 papisde_control_t *gctl = sdei_get_global_struct();
124 if(gctl->disabled)
125 return NULL;
126
127 // We have to emulate PAPI's SUBDBG to get the same behavior
128 _sde_be_verbose = (NULL != getenv("PAPI_VERBOSE"));
129 char *tmp= getenv("PAPI_DEBUG");
130 if( (NULL != tmp) && (0 != strlen(tmp)) && (strstr(tmp, "SUBSTRATE") || strstr(tmp, "ALL")) ){
131 _sde_debug = 1;
132 }
133
134 SDEDBG("Registering library: '%s'\n", name_of_library);
135
137
138 // Lock before we read and/or modify the global structures.
139 sde_lock();
140
141 // Put the actual work in a different function so we call it from other
142 // places. We have to do this because we cannot call
143 // papi_sde_init() from places in the code which already call
144 // lock()/unlock(), or we will end up with deadlocks.
145 tmp_lib = (papisde_library_desc_t *)do_sde_init(name_of_library, gctl);
146
147 sde_unlock();
148
149 SDEDBG("Library '%s' has been registered.\n",name_of_library);
150
151 return tmp_lib;
152}
153
160int
162
163 sde_lock();
164 papisde_control_t *gctl = sdei_get_global_struct();
165
166 // If the caller did not specify a library, then disable all SDEs.
167 if( NULL == handle ){
168 gctl->disabled = 1;
169 }else{
170 // else disable the specified library.
171 papisde_library_desc_t *lib_handle = (papisde_library_desc_t *) handle;
172 lib_handle->disabled = 1;
173 }
174 sde_unlock();
175 return SDE_OK;
176}
177
188int
190
191 sde_lock();
192 papisde_control_t *gctl = sdei_get_global_struct();
193
194 // If the caller did not specify a library, then disable all SDEs.
195 if( NULL == handle ){
196 gctl->disabled = 0;
197 }else{
198 // else disable the specified library.
199 papisde_library_desc_t *lib_handle = (papisde_library_desc_t *) handle;
200 lib_handle->disabled = 0;
201 }
202 sde_unlock();
203 return SDE_OK;
204}
205
211int
213 papisde_library_desc_t *lib_handle, *tmp_lib, *next_lib, *prev_lib;
214 int i;
215
216 lib_handle = (papisde_library_desc_t *) handle;
217 papisde_control_t *gctl = _papisde_global_control;
218 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
219 return SDE_OK;
220
221 SDEDBG("papi_sde_shutdown(): for library '%s'.\n", lib_handle->libraryName);
222
223 sde_lock();
224
225 sde_counter_t *all_lib_counters;
226 int item_cnt = ht_to_array(lib_handle->lib_counters, &all_lib_counters);
227
228 for(i=0; i<item_cnt; i++){
229 char *cntr_name = all_lib_counters[i].name;
230 sdei_delete_counter(lib_handle, cntr_name);
231 }
232
233 // We don't need the serialized array any more. Besides, the pointers inside
234 // its elements have _not_ been copied, so they are junk by now, since we
235 // deleted the counters.
236 free(all_lib_counters);
237
238 // Keep the `gctl` struct consistent
239 // 1. If the lib head is this one, just set to next (could be NULL)
240 // 2. Otherwise, find the prev_lib and set prev_lib->next = next_lib
241 next_lib = lib_handle->next;
242 if (gctl->lib_list_head == lib_handle) {
243 gctl->lib_list_head = next_lib;
244 } else {
245 prev_lib = NULL;
246 tmp_lib = gctl->lib_list_head;
247 while (tmp_lib != lib_handle && tmp_lib != NULL)
248 {
249 prev_lib = tmp_lib;
250 tmp_lib = tmp_lib->next;
251 }
252 if (prev_lib != NULL) {
253 prev_lib->next = next_lib;
254 }
255 }
256
257 free(lib_handle->libraryName);
258 free(lib_handle);
259
260 sde_unlock();
261 return SDE_OK;
262}
263
264
275int
276papi_sde_register_counter( papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, void *counter )
277{
278 papisde_library_desc_t *lib_handle;
279 int ret_val = SDE_OK;
280 cntr_class_specific_t cntr_union;
281
282 if( NULL != event_name )
283 SDEDBG("Prepaing to register counter: '%s'.\n", event_name);
284
285 lib_handle = (papisde_library_desc_t *) handle;
286 papisde_control_t *gctl = _papisde_global_control;
287 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
288 return SDE_OK;
289
290 cntr_union.cntr_basic.data = counter;
291
292 sde_lock();
293 ret_val = sdei_setup_counter_internals( lib_handle, event_name, cntr_mode, cntr_type, CNTR_CLASS_REGISTERED, cntr_union );
294 sde_unlock();
295
296 return ret_val;
297}
298
311int
312papi_sde_register_counter_cb( papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, papi_sde_fptr_t callback, void *param )
313{
314 papisde_library_desc_t *lib_handle;
315 int ret_val = SDE_OK;
316 cntr_class_specific_t cntr_union;
317
318 if( NULL != event_name )
319 SDEDBG("Prepaing to register fp_counter: '%s'.\n", event_name);
320
321 lib_handle = (papisde_library_desc_t *) handle;
322 papisde_control_t *gctl = _papisde_global_control;
323 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
324 return SDE_OK;
325
326 cntr_union.cntr_cb.callback = callback;
327 cntr_union.cntr_cb.param = param;
328
329 sde_lock();
330 ret_val = sdei_setup_counter_internals( lib_handle, event_name, cntr_mode, cntr_type, CNTR_CLASS_CB, cntr_union );
331 sde_unlock();
332
333 return ret_val;
334}
335
341int
343{
344 papisde_library_desc_t *lib_handle;
345 int error;
346 char *full_event_name;
347 int ret_val;
348
349 SDEDBG("Preparing to unregister counter: '%s'.\n",event_name);
350
351 lib_handle = (papisde_library_desc_t *) handle;
352 papisde_control_t *gctl = _papisde_global_control;
353 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
354 return SDE_OK;
355
356 if( NULL == lib_handle->libraryName ){
357 SDE_ERROR("papi_sde_unregister_counter(): 'handle' is clobbered. Unable to unregister counter.");
358 return SDE_EINVAL;
359 }
360
361 size_t str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
362 full_event_name = (char *)malloc(str_len*sizeof(char));
363 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
364
365 SDEDBG("Unregistering counter: '%s' from SDE library: %s.\n", full_event_name, lib_handle->libraryName);
366
367 // After this point we will be modifying data structures, so we need to acquire a lock.
368 // This function has multiple exist points. If you add more, make sure you unlock before each one of them.
369 sde_lock();
370
371 error = sdei_delete_counter( lib_handle, full_event_name );
372 // Check if we found a registered counter, or if it never existed.
373 if( error ){
374 SDE_ERROR("Counter '%s' has not been registered by library '%s'.", full_event_name, lib_handle->libraryName);
375 free(full_event_name);
376 ret_val = SDE_EINVAL;
377 goto fn_exit;
378 }
379
380 // We will not use the name beyond this point
381 free(full_event_name);
382 ret_val = SDE_OK;
383fn_exit:
384 sde_unlock();
385 return ret_val;
386}
387
388
397int
398papi_sde_describe_counter( void *handle, const char *event_name, const char *event_description )
399{
400 sde_counter_t *tmp_item;
401 papisde_library_desc_t *lib_handle;
402 char *full_event_name;
403 int ret_val;
404
405 lib_handle = (papisde_library_desc_t *) handle;
406 papisde_control_t *gctl = _papisde_global_control;
407 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
408 return SDE_OK;
409
410 if( NULL == lib_handle->libraryName ){
411 SDE_ERROR("papi_sde_describe_counter(): 'handle' is clobbered. Unable to add description for counter.");
412 return SDE_EINVAL;
413 }
414
415 size_t str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
416 full_event_name = (char *)malloc(str_len*sizeof(char));
417 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
418
419 // After this point we will be modifying data structures, so we need to acquire a lock.
420 // This function has multiple exist points. If you add more, make sure you unlock before each one of them.
421 sde_lock();
422
423 tmp_item = ht_lookup_by_name(lib_handle->lib_counters, full_event_name);
424 if( NULL != tmp_item ){
425 tmp_item->description = strdup(event_description);
426 free(full_event_name);
427 ret_val = SDE_OK;
428 goto fn_exit;
429 }
430 SDEDBG("papi_sde_describe_counter() Event: '%s' is not registered in SDE library: '%s'\n", full_event_name, lib_handle->libraryName);
431 // We will not use the name beyond this point
432 free(full_event_name);
433 ret_val = SDE_EINVAL;
434fn_exit:
435 sde_unlock();
436 return ret_val;
437}
438
439
440
448int
449papi_sde_add_counter_to_group(papi_handle_t handle, const char *event_name, const char *group_name, uint32_t group_flags)
450{
451 papisde_library_desc_t *lib_handle;
452 sde_counter_t *tmp_item, *tmp_group;
453 uint32_t cntr_group_uniq_id;
454 char *full_event_name, *full_group_name;
455 int ret_val;
456
457 lib_handle = (papisde_library_desc_t *) handle;
458 papisde_control_t *gctl = _papisde_global_control;
459 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
460 return SDE_OK;
461
462 SDEDBG("Adding counter: %s into group %s\n",event_name, group_name);
463
464 if( NULL == lib_handle->libraryName ){
465 SDE_ERROR("papi_sde_add_counter_to_group(): 'handle' is clobbered. Unable to add counter to group.");
466 return SDE_EINVAL;
467 }
468
469 size_t str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
470 full_event_name = (char *)malloc(str_len*sizeof(char));
471 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
472
473 // After this point we will be modifying data structures, so we need to acquire a lock.
474 // This function has multiple exist points. If you add more, make sure you unlock before each one of them.
475 sde_lock();
476
477 // Check to make sure that the event is already registered. This is not the place to create a placeholder.
478 tmp_item = ht_lookup_by_name(lib_handle->lib_counters, full_event_name);
479 if( NULL == tmp_item ){
480 SDE_ERROR("papi_sde_add_counter_to_group(): Unable to find counter: '%s'.",full_event_name);
481 free(full_event_name);
482 ret_val = SDE_EINVAL;
483 goto fn_exit;
484 }
485
486 // We will not use the name beyond this point
487 free(full_event_name);
488
489 str_len = strlen(lib_handle->libraryName)+strlen(group_name)+2+1; // +2 for "::" and +1 for '\0'
490 full_group_name = (char *)malloc(str_len*sizeof(char));
491 snprintf(full_group_name, str_len, "%s::%s", lib_handle->libraryName, group_name);
492
493 // Check to see if the group exists already. Otherwise we need to create it.
494 tmp_group = ht_lookup_by_name(lib_handle->lib_counters, full_group_name);
495 if( NULL == tmp_group ){
496
497 papisde_control_t *gctl = sdei_get_global_struct();
498
499 // We use the current number of registered events as the uniq id of the counter group, and we
500 // increment it because counter groups are treated as real counters by the outside world.
501 // They are first class citizens.
502 cntr_group_uniq_id = gctl->num_reg_events++;
503 gctl->num_live_events++;
504
505 SDEDBG("%s line %d: Unique ID for new counter group = %d\n", __FILE__, __LINE__, cntr_group_uniq_id);
506
507 tmp_group = (sde_counter_t *)calloc(1, sizeof(sde_counter_t));
508 tmp_group->cntr_class = CNTR_CLASS_GROUP;
509 tmp_group->glb_uniq_id = cntr_group_uniq_id;
510 // copy the name because we will free the malloced space further down in this function.
511 tmp_group->name = strdup(full_group_name);
512 // make a copy here, because we will free() the 'name' and the 'description' separately.
513 tmp_group->description = strdup( full_group_name );
514 tmp_group->which_lib = lib_handle;
515 tmp_group->u.cntr_group.group_flags = group_flags;
516
517 (void)ht_insert(lib_handle->lib_counters, ht_hash_name(full_group_name), tmp_group);
518 (void)ht_insert(gctl->all_reg_counters, ht_hash_id(cntr_group_uniq_id), tmp_group);
519
520 }else{
521 if( NULL == tmp_group->u.cntr_group.group_head ){
522 if( CNTR_CLASS_PLACEHOLDER == tmp_group->cntr_class ){
523 tmp_group->cntr_class = CNTR_CLASS_GROUP;
524 }else{
525 SDE_ERROR("papi_sde_add_counter_to_group(): Found an empty counter group: '%s'. This might indicate that a cleanup routine is not doing its job.", group_name);
526 }
527
528 }
529
530 // make sure the caller is not trying to change the flags of the group after it has been created.
531 if( tmp_group->u.cntr_group.group_flags != group_flags ){
532 SDE_ERROR("papi_sde_add_counter_to_group(): Attempting to add counter '%s' to counter group '%s' with incompatible group flags.", event_name, group_name);
533 free(full_group_name);
534 ret_val = SDE_EINVAL;
535 goto fn_exit;
536 }
537 }
538
539 // Add the new counter to the group's head.
540 papisde_list_entry_t *new_head = (papisde_list_entry_t *)calloc(1, sizeof(papisde_list_entry_t));
541 new_head->item = tmp_item;
542 new_head->next = tmp_group->u.cntr_group.group_head;
543 tmp_group->u.cntr_group.group_head = new_head;
544 if( SDE_OK != sdei_inc_ref_count(tmp_item) ){
545 SDE_ERROR("papi_sde_add_counter_to_group(): Error while adding counter '%s' to counter group: '%s'.", tmp_item->name, group_name);
546 }
547
548 free(full_group_name);
549 ret_val = SDE_OK;
550fn_exit:
551 sde_unlock();
552 return ret_val;
553}
554
575int
577{
578 int ret_val;
579 long long int *counter_data;
580 char *full_event_name;
581 papisde_library_desc_t *lib_handle;
582 sde_counter_t *cntr;
583 cntr_class_specific_t cntr_union;
584
585 lib_handle = (papisde_library_desc_t *) handle;
586 papisde_control_t *gctl = _papisde_global_control;
587 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
588 return SDE_OK;
589
590 if( NULL != event_name )
591 SDEDBG("Preparing to create counter: '%s'.\n", event_name);
592
593 sde_lock();
594
595 if( NULL == lib_handle->libraryName ){
596 SDE_ERROR("papi_sde_create_counter(): 'handle' is clobbered. Unable to create counter.");
597 return SDE_EINVAL;
598 }
599
600 SDEDBG("Adding created counter: '%s' with mode: '%d' in SDE library: %s.\n", event_name, cntr_mode, lib_handle->libraryName);
601
602 // Created counters use memory allocated by libsde, not the user library.
603 counter_data = (long long int *)calloc(1, sizeof(long long int));
604 cntr_union.cntr_basic.data = counter_data;
605
606 ret_val = sdei_setup_counter_internals( lib_handle, event_name, cntr_mode, PAPI_SDE_long_long, CNTR_CLASS_CREATED, cntr_union );
607 if( SDE_OK != ret_val ){
608 goto fn_exit;
609 }
610
611 size_t str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
612 full_event_name = (char *)malloc(str_len*sizeof(char));
613 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
614
615 cntr = ht_lookup_by_name(lib_handle->lib_counters, full_event_name);
616 if(NULL == cntr) {
617 SDEDBG("Logging counter '%s' not properly inserted in SDE library '%s'\n", full_event_name, lib_handle->libraryName);
618 free(full_event_name);
619 ret_val = SDE_ECMP;
620 goto fn_exit;
621 }
622
623 if( NULL != cntr_handle ){
624 *(sde_counter_t **)cntr_handle = cntr;
625 }
626
627 free(full_event_name);
628 ret_val = SDE_OK;
629fn_exit:
630 sde_unlock();
631 return ret_val;
632}
633
634
635// The following function works only for counters created using papi_sde_create_counter().
636int
638{
639 long long int *ptr;
640 sde_counter_t *tmp_cntr;
641 int ret_val;
642
643 tmp_cntr = (sde_counter_t *)cntr_handle;
644 papisde_control_t *gctl = _papisde_global_control;
645 if( (NULL==tmp_cntr) || (NULL==tmp_cntr->which_lib) || tmp_cntr->which_lib->disabled || (NULL==gctl) || gctl->disabled)
646 return SDE_OK;
647
648 sde_lock();
649
650 if( !IS_CNTR_CREATED(tmp_cntr) || (NULL == tmp_cntr->u.cntr_basic.data) ){
651 SDE_ERROR("papi_sde_inc_counter(): 'cntr_handle' is clobbered. Unable to modify value of counter.");
652 ret_val = SDE_EINVAL;
653 goto fn_exit;
654 }
655
656 if( PAPI_SDE_long_long != tmp_cntr->cntr_type ){
657 SDE_ERROR("papi_sde_inc_counter(): Counter is not of type \"long long int\" and cannot be modified using this function.");
658 ret_val = SDE_EINVAL;
659 goto fn_exit;
660 }
661
662 SDEDBG("Preparing to increment counter: '%s::%s' by %lld.\n", tmp_cntr->which_lib->libraryName, tmp_cntr->name, increment);
663
664 ptr = tmp_cntr->u.cntr_basic.data;
665 *ptr += increment;
666
667 sdei_check_overflow_status(tmp_cntr->glb_uniq_id, *ptr);
668
669 ret_val = SDE_OK;
670fn_exit:
671 sde_unlock();
672 return ret_val;
673}
674
675/*
676 @param[in] handle -- pointer (of opaque type papi_handle_t) to sde structure for an individual library.
677 @param[in] cset_name -- (const char *) name of the counting set.
678 @param[out] cset_handle -- address of a pointer in which libsde will store a handle to the newly created counting set.
679 @param[out] -- (int) the return value is SDE_OK on success, or an error code on failure.
680*/
681int
682papi_sde_create_counting_set( papi_handle_t handle, const char *cset_name, void **cset_handle )
683{
684 int ret_val;
685 sde_counter_t *tmp_cset_handle;
686 char *full_cset_name;
687 papisde_library_desc_t *lib_handle;
688 cntr_class_specific_t cntr_union;
689
690 SDEDBG("papi_sde_create_counting_set()\n");
691
692 lib_handle = (papisde_library_desc_t *) handle;
693 papisde_control_t *gctl = _papisde_global_control;
694 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
695 return SDE_OK;
696
697 if( NULL != cset_name )
698 SDEDBG("Preparing to create counting set: '%s'.\n", cset_name);
699
700 if( NULL == lib_handle->libraryName ){
701 SDE_ERROR("papi_sde_create_counting_set(): 'handle' is clobbered. Unable to create counting set.");
702 return SDE_EINVAL;
703 }
704
705 SDEDBG("Adding counting set: '%s' in SDE library: %s.\n", cset_name, lib_handle->libraryName);
706
707 // Allocate the structure for the hash table.
708 cntr_union.cntr_cset.data = (cset_hash_table_t *)calloc(1,sizeof(cset_hash_table_t));
709 if( NULL == cntr_union.cntr_cset.data )
710 return SDE_ENOMEM;
711
712 ret_val = sdei_setup_counter_internals( lib_handle, cset_name, PAPI_SDE_DELTA|PAPI_SDE_RO, PAPI_SDE_long_long, CNTR_CLASS_CSET, cntr_union );
713 if( SDE_OK != ret_val )
714 return ret_val;
715
716 size_t str_len = strlen(lib_handle->libraryName)+strlen(cset_name)+2+1; // +2 for "::" and +1 for '\0'
717 full_cset_name = (char *)malloc(str_len*sizeof(char));
718 snprintf(full_cset_name, str_len, "%s::%s", lib_handle->libraryName, cset_name);
719
720 tmp_cset_handle = ht_lookup_by_name(lib_handle->lib_counters, full_cset_name);
721 if(NULL == tmp_cset_handle) {
722 SDEDBG("Recorder '%s' not properly inserted in SDE library '%s'\n", full_cset_name, lib_handle->libraryName);
723 free(full_cset_name);
724 return SDE_ECMP;
725 }
726
727 if( NULL != cset_handle ){
728 *(sde_counter_t **)cset_handle = tmp_cset_handle;
729 }
730
731 free(full_cset_name);
732
733 return SDE_OK;
734}
735
736int
737papi_sde_counting_set_remove( void *cset_handle, size_t hashable_size, const void *element, uint32_t type_id)
738{
739 sde_counter_t *tmp_cset;
740 int ret_val = SDE_OK;
741
742 tmp_cset = (sde_counter_t *)cset_handle;
743 papisde_control_t *gctl = _papisde_global_control;
744 if( (NULL==tmp_cset) || (NULL==tmp_cset->which_lib) || tmp_cset->which_lib->disabled || (NULL==gctl) || gctl->disabled)
745 return SDE_OK;
746
747 sde_lock();
748
749 if( !IS_CNTR_CSET(tmp_cset) || (NULL == tmp_cset->u.cntr_cset.data) ){
750 SDE_ERROR("papi_sde_counting_set_remove(): Counting set is clobbered. Unable to remove element.");
751 ret_val = SDE_EINVAL;
752 goto fn_exit;
753 }
754
755 SDEDBG("Preparing to remove element from counting set: '%s::%s'.\n", tmp_cset->which_lib->libraryName, tmp_cset->name);
756 ret_val = cset_remove_elem(tmp_cset->u.cntr_cset.data, hashable_size, element, type_id);
757
758fn_exit:
759 sde_unlock();
760 return ret_val;
761}
762
763
764
765int
766papi_sde_counting_set_insert( void *cset_handle, size_t element_size, size_t hashable_size, const void *element, uint32_t type_id)
767{
768 sde_counter_t *tmp_cset;
769 int ret_val = SDE_OK;
770
771 tmp_cset = (sde_counter_t *)cset_handle;
772 papisde_control_t *gctl = _papisde_global_control;
773 if( (NULL==tmp_cset) || (NULL==tmp_cset->which_lib) || tmp_cset->which_lib->disabled || (NULL==gctl) || gctl->disabled)
774 return SDE_OK;
775
776 sde_lock();
777
778 if( !IS_CNTR_CSET(tmp_cset) || (NULL == tmp_cset->u.cntr_cset.data) ){
779 SDE_ERROR("papi_sde_counting_set_insert(): Counting set is clobbered. Unable to insert element.");
780 ret_val = SDE_EINVAL;
781 goto fn_exit;
782 }
783
784 SDEDBG("Preparing to insert element in counting set: '%s::%s'.\n", tmp_cset->which_lib->libraryName, tmp_cset->name);
785 ret_val = cset_insert_elem(tmp_cset->u.cntr_cset.data, element_size, hashable_size, element, type_id);
786
787fn_exit:
788 sde_unlock();
789 return ret_val;
790}
791
792
793int
794papi_sde_create_recorder( papi_handle_t handle, const char *event_name, size_t typesize, int (*cmpr_func_ptr)(const void *p1, const void *p2), void **record_handle )
795{
796 int ret_val, i;
797 sde_counter_t *tmp_rec_handle;
798 cntr_class_specific_t aux_cntr_union;
799 char *aux_event_name;
800 size_t str_len;
801 char *full_event_name;
802 cntr_class_specific_t cntr_union;
803#define _SDE_MODIFIER_COUNT 6
804 const char *modifiers[_SDE_MODIFIER_COUNT] = {":CNT",":MIN",":Q1",":MED",":Q3",":MAX"};
805 // Add a NULL pointer for symmetry with the 'modifiers' vector, since the modifier ':CNT' does not have a function pointer.
807
808 papisde_library_desc_t *lib_handle = (papisde_library_desc_t *)handle;
809 papisde_control_t *gctl = _papisde_global_control;
810 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
811 return SDE_OK;
812
813 sde_lock();
814
815 if( NULL == lib_handle->libraryName ){
816 SDE_ERROR("papi_sde_create_recorder(): 'handle' is clobbered. Unable to create recorder.");
817 ret_val = SDE_EINVAL;
818 goto fn_exit;
819 }
820
821 SDEDBG("Preparing to create recorder: '%s' with typesize: '%d' in SDE library: %s.\n", event_name, (int)typesize, lib_handle->libraryName);
822
823 // Allocate the "Exponential Storage" structure for the recorder data and meta-data.
824 cntr_union.cntr_recorder.data = (recorder_data_t *)calloc(1,sizeof(recorder_data_t));
825 // Allocate the first chunk of recorder data.
826 cntr_union.cntr_recorder.data->ptr_array[0] = malloc(EXP_CONTAINER_MIN_SIZE*typesize);
827 cntr_union.cntr_recorder.data->total_entries = EXP_CONTAINER_MIN_SIZE;
828 cntr_union.cntr_recorder.data->typesize = typesize;
829 cntr_union.cntr_recorder.data->used_entries = 0;
830
832 if( SDE_OK != ret_val )
833 return ret_val;
834
835 str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
836 full_event_name = (char *)malloc(str_len*sizeof(char));
837 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
838
839 tmp_rec_handle = ht_lookup_by_name(lib_handle->lib_counters, full_event_name);
840 if(NULL == tmp_rec_handle) {
841 SDEDBG("Recorder '%s' not properly inserted in SDE library '%s'\n", full_event_name, lib_handle->libraryName);
842 free(full_event_name);
843 ret_val = SDE_ECMP;
844 goto fn_exit;
845 }
846
847 // We will not use the name beyond this point
848 free(full_event_name);
849
850 if( NULL != record_handle ){
851 *(sde_counter_t **)record_handle = tmp_rec_handle;
852 }
853
854 // At this point we are done creating the recorder and we will create the additional events which will appear as modifiers of the recorder.
855 str_len = 0;
856 for(i=0; i<_SDE_MODIFIER_COUNT; i++){
857 size_t tmp_len = strlen(modifiers[i]);
858 if( tmp_len > str_len )
859 str_len = tmp_len;
860 }
861 str_len += strlen(event_name)+1;
862 aux_event_name = (char *)calloc(str_len, sizeof(char));
863
864 snprintf(aux_event_name, str_len, "%s%s", event_name, modifiers[0]);
865 SDEDBG("papi_sde_create_recorder(): Preparing to register aux counter: '%s' in SDE library: %s.\n", aux_event_name, lib_handle->libraryName);
866
867 // The field that holds the number of used entries in the recorder structure will become the counter of the new auxiliary event.
868 aux_cntr_union.cntr_basic.data = &(tmp_rec_handle->u.cntr_recorder.data->used_entries);
869 ret_val = sdei_setup_counter_internals( lib_handle, (const char *)aux_event_name, PAPI_SDE_INSTANT|PAPI_SDE_RO, PAPI_SDE_long_long, CNTR_CLASS_REGISTERED, aux_cntr_union );
870 if( SDE_OK != ret_val ){
871 SDEDBG("papi_sde_create_recorder(): Registration of aux counter: '%s' in SDE library: %s FAILED.\n", aux_event_name, lib_handle->libraryName);
872 free(aux_event_name);
873 goto fn_exit;
874 }
875
876 // If the caller passed NULL as the function pointer, then they do _not_ want the quantiles. Otherwise, create them.
877 if( NULL != cmpr_func_ptr ){
878 for(i=1; i<_SDE_MODIFIER_COUNT; i++){
879 sde_sorting_params_t *sorting_params;
880
881 sorting_params = (sde_sorting_params_t *)malloc(sizeof(sde_sorting_params_t)); // This will be free()-ed by papi_sde_unregister_counter()
882 sorting_params->recording = tmp_rec_handle;
883 sorting_params->cmpr_func_ptr = cmpr_func_ptr;
884
885 snprintf(aux_event_name, str_len, "%s%s", event_name, modifiers[i]);
886
887 SDEDBG("papi_sde_create_recorder(): Preparing to register aux fp counter: '%s' in SDE library: %s.\n", aux_event_name, lib_handle->libraryName);
888 // clear the previous entries;
889 memset(&aux_cntr_union, 0, sizeof(aux_cntr_union));
890 aux_cntr_union.cntr_cb.callback = func_ptr_vec[i];
891 aux_cntr_union.cntr_cb.param = sorting_params;
892 ret_val = sdei_setup_counter_internals(lib_handle, (const char *)aux_event_name, PAPI_SDE_RO|PAPI_SDE_INSTANT, PAPI_SDE_long_long, CNTR_CLASS_CB, aux_cntr_union );
893 if( SDE_OK != ret_val ){
894 SDEDBG("papi_sde_create_recorder(): Registration of aux counter: '%s' in SDE library: %s FAILED.\n", aux_event_name, lib_handle->libraryName);
895 free(aux_event_name);
896 goto fn_exit;
897 }
898 }
899 }
900
901 free(aux_event_name);
902 ret_val = SDE_OK;
903fn_exit:
904 sde_unlock();
905 return ret_val;
906}
907
908int
909papi_sde_record( void *record_handle, size_t typesize, const void *value)
910{
911 sde_counter_t *tmp_rcrd;
912 int ret_val;
913
914 tmp_rcrd = (sde_counter_t *)record_handle;
915 papisde_control_t *gctl = _papisde_global_control;
916 if( (NULL==tmp_rcrd) || (NULL==tmp_rcrd->which_lib) || tmp_rcrd->which_lib->disabled || (NULL==gctl) || gctl->disabled)
917 return SDE_OK;
918
919 SDEDBG("Preparing to record value of size %lu at address: %p\n",typesize, value);
920
921 sde_lock();
922
923 if( !IS_CNTR_RECORDER(tmp_rcrd) || (NULL == tmp_rcrd->u.cntr_recorder.data) ){
924 SDE_ERROR("papi_sde_record(): 'record_handle' is clobbered. Unable to record value.");
925 ret_val = SDE_EINVAL;
926 goto fn_exit;
927 }
928
929 ret_val = exp_container_insert_element(tmp_rcrd->u.cntr_recorder.data, typesize, value);
930
931fn_exit:
932 sde_unlock();
933 return ret_val;
934}
935
936
937// This function neither frees the allocated, nor does it zero it. It only resets the counter of used entries so that
938// the allocated space can be resused (and overwritten) by future calls to record().
939int
940papi_sde_reset_recorder( void *record_handle )
941{
942 sde_counter_t *tmp_rcrdr;
943 int ret_val;
944
945 tmp_rcrdr = (sde_counter_t *)record_handle;
946 papisde_control_t *gctl = _papisde_global_control;
947 if( (NULL==tmp_rcrdr) || (NULL==tmp_rcrdr->which_lib) || tmp_rcrdr->which_lib->disabled || (NULL==gctl) || gctl->disabled)
948 return SDE_OK;
949
950 sde_lock();
951
952 if( !IS_CNTR_RECORDER(tmp_rcrdr) || NULL == tmp_rcrdr->u.cntr_recorder.data ){
953 SDE_ERROR("papi_sde_reset_recorder(): 'record_handle' is clobbered. Unable to reset recorder.");
954 ret_val = SDE_EINVAL;
955 goto fn_exit;
956 }
957
958 // NOTE: do _not_ free the chunks and do _not_ reset "cntr_recorder.data->total_entries"
959 tmp_rcrdr->u.cntr_recorder.data->used_entries = 0;
960 free( tmp_rcrdr->u.cntr_recorder.data->sorted_buffer );
961 tmp_rcrdr->u.cntr_recorder.data->sorted_buffer = NULL;
962 tmp_rcrdr->u.cntr_recorder.data->sorted_entries = 0;
963
964 ret_val = SDE_OK;
965fn_exit:
966 sde_unlock();
967 return ret_val;
968}
969
970
971// The following function works only for counters created using papi_sde_create_counter().
972int
974{
975 long long int *ptr;
976 sde_counter_t *tmp_cntr;
977 int ret_val;
978
979 tmp_cntr = (sde_counter_t *)cntr_handle;
980 papisde_control_t *gctl = _papisde_global_control;
981 if( (NULL==tmp_cntr) || (NULL==tmp_cntr->which_lib) || tmp_cntr->which_lib->disabled || (NULL==gctl) || gctl->disabled)
982 return SDE_OK;
983
984 sde_lock();
985
986 if( !IS_CNTR_CREATED(tmp_cntr) ){
987 SDE_ERROR("papi_sde_reset_counter(): Counter is not created by PAPI, so it cannot be reset.");
988 ret_val = SDE_EINVAL;
989 goto fn_exit;
990 }
991
992 ptr = (long long int *)(tmp_cntr->u.cntr_basic.data);
993
994 if( NULL == ptr ){
995 SDE_ERROR("papi_sde_reset_counter(): Counter structure is clobbered. Unable to reset value of counter.");
996 ret_val = SDE_EINVAL;
997 goto fn_exit;
998 }
999
1000 *ptr = 0; // Reset the counter.
1001
1002 ret_val = SDE_OK;
1003fn_exit:
1004 sde_unlock();
1005 return ret_val;
1006}
1007
1008
1015void
1017{
1018 sde_counter_t *counter_handle;
1019 papisde_library_desc_t *lib_handle;
1020 char *full_event_name;
1021
1022 lib_handle = (papisde_library_desc_t *) handle;
1023 papisde_control_t *gctl = _papisde_global_control;
1024 if( (NULL==lib_handle) || lib_handle->disabled || (NULL==gctl) || gctl->disabled)
1025 return NULL;
1026
1027 if( NULL == lib_handle->libraryName ){
1028 SDE_ERROR("papi_sde_get_counter_handle(): 'handle' is clobbered.");
1029 return NULL;
1030 }
1031
1032 size_t str_len = strlen(lib_handle->libraryName)+strlen(event_name)+2+1; // +2 for "::" and +1 for '\0'
1033 full_event_name = (char *)malloc(str_len*sizeof(char));
1034 snprintf(full_event_name, str_len, "%s::%s", lib_handle->libraryName, event_name);
1035
1036 // After this point we will be accessing shared data structures, so we need to acquire a lock.
1037 sde_lock();
1038 counter_handle = ht_lookup_by_name(lib_handle->lib_counters, full_event_name);
1039 sde_unlock();
1040
1041 free(full_event_name);
1042
1043 return counter_handle;
1044}
1045
1046
1047/*************************************************************************/
1048/* Utility Functions. */
1049/*************************************************************************/
1050
1051int
1052papi_sde_compare_long_long(const void *p1, const void *p2){
1053 long long n1, n2;
1054 n1 = *(long long *)p1;
1055 n2 = *(long long *)p2;
1056
1057 if( n1 < n2 ) return -1;
1058 if( n1 > n2 ) return 1;
1059 return 0;
1060}
1061
1062int
1063papi_sde_compare_int(const void *p1, const void *p2){
1064 int n1, n2;
1065 n1 = *(int *)p1;
1066 n2 = *(int *)p2;
1067
1068 if( n1 < n2 ) return -1;
1069 if( n1 > n2 ) return 1;
1070 return 0;
1071}
1072
1073int
1074papi_sde_compare_double(const void *p1, const void *p2){
1075 double n1, n2;
1076 n1 = *(double *)p1;
1077 n2 = *(double *)p2;
1078
1079 if( n1 < n2 ) return -1;
1080 if( n1 > n2 ) return 1;
1081 return 0;
1082}
1083
1084int
1085papi_sde_compare_float(const void *p1, const void *p2){
1086 float n1, n2;
1087 n1 = *(float *)p1;
1088 n2 = *(float *)p2;
1089
1090 if( n1 < n2 ) return -1;
1091 if( n1 > n2 ) return 1;
1092 return 0;
1093}
1094
1095#define _SDE_CMP_MIN 0
1096#define _SDE_CMP_MAX 1
1097
1098// This function returns a "long long" which contains a pointer to the
1099// data element that corresponds to the edge (min/max), so that it works
1100// for all types of data, not only integers.
1101static inline long long sdei_compute_edge(void *param, int which_edge){
1102 void *edge = NULL, *edge_copy;
1103 long long elem_cnt;
1104 long long current_size, cumul_size = 0;
1105 void *src;
1106 int i, chunk;
1107 size_t typesize;
1108 sde_counter_t *rcrd;
1109 int (*cmpr_func_ptr)(const void *p1, const void *p2);
1110
1111
1112 rcrd = ((sde_sorting_params_t *)param)->recording;
1113 elem_cnt = rcrd->u.cntr_recorder.data->used_entries;
1114 typesize = rcrd->u.cntr_recorder.data->typesize;
1115
1116 cmpr_func_ptr = ((sde_sorting_params_t *)param)->cmpr_func_ptr;
1117
1118 // The return value is supposed to be a pointer to the correct element, therefore zero
1119 // is a NULL pointer, which should tell the caller that there was a problem.
1120 if( (0 == elem_cnt) || (NULL == cmpr_func_ptr) )
1121 return 0;
1122
1123 // If there is a sorted (contiguous) buffer, but it's stale, we need to free it.
1124 // The value of elem_cnt (rcrd->u.cntr_recorder.data->used_entries) can
1125 // only increase, or be reset to zero, but when it is reset to zero
1126 // (by papi_sde_reset_recorder()) the buffer will be freed (by the same function).
1127 if( (NULL != rcrd->u.cntr_recorder.data->sorted_buffer) &&
1128 (rcrd->u.cntr_recorder.data->sorted_entries < elem_cnt) ){
1129
1130 free( rcrd->u.cntr_recorder.data->sorted_buffer );
1131 rcrd->u.cntr_recorder.data->sorted_buffer = NULL;
1132 rcrd->u.cntr_recorder.data->sorted_entries = 0;
1133 }
1134
1135 // Check if a sorted contiguous buffer is already there. If there is, return
1136 // the first or last element (for MIN, or MAX respectively).
1137 if( NULL != rcrd->u.cntr_recorder.data->sorted_buffer ){
1138 if( _SDE_CMP_MIN == which_edge )
1139 edge = rcrd->u.cntr_recorder.data->sorted_buffer;
1140 if( _SDE_CMP_MAX == which_edge )
1141 edge = (char *)(rcrd->u.cntr_recorder.data->sorted_buffer) + (elem_cnt-1)*typesize;
1142 }else{
1143 // Make "edge" point to the beginning of the first chunk.
1144 edge = rcrd->u.cntr_recorder.data->ptr_array[0];
1145 if ( NULL == edge )
1146 return 0;
1147
1148 cumul_size = 0;
1149 for(chunk=0; chunk<EXP_CONTAINER_ENTRIES; chunk++){
1150 current_size = ((long long)1<<chunk) * EXP_CONTAINER_MIN_SIZE;
1151 src = rcrd->u.cntr_recorder.data->ptr_array[chunk];
1152
1153 for(i=0; (i < (elem_cnt-cumul_size)) && (i < current_size); i++){
1154 void *next_elem = (char *)src + i*typesize;
1155 int rslt = cmpr_func_ptr(next_elem, edge);
1156
1157 // If the new element is smaller than the current min and we are looking for the min, then keep it.
1158 if( (rslt < 0) && (_SDE_CMP_MIN == which_edge) )
1159 edge = next_elem;
1160 // If the new element is larger than the current max and we are looking for the max, then keep it.
1161 if( (rslt > 0) && (_SDE_CMP_MAX == which_edge) )
1162 edge = next_elem;
1163 }
1164
1165 cumul_size += current_size;
1166
1167 if( cumul_size >= elem_cnt )
1168 break;
1169 }
1170 }
1171
1172 // We might free the sorted_buffer (when it becomes stale), so we can't return "edge".
1173 // Therefore, we allocate fresh space for the resulting element and copy it there.
1174 // Since we do not know when the user will use this pointer, we will not be able
1175 // to free it, so it is the responibility of the user (who calls PAPI_read()) to
1176 // free this memory.
1177 edge_copy = malloc( 1 * typesize);
1178 memcpy(edge_copy, edge, 1 * typesize);
1179
1180 // A pointer is guaranteed to fit inside a long long, so cast it and return a long long.
1181 return (long long)edge_copy;
1182}
1183
1184
1185
1186// This function returns a "long long" which contains a pointer to the
1187// data element that corresponds to the edge (min/max), so that it works
1188// for all types of data, not only integers.
1189
1190// NOTE: This function allocates memory for one element and returns a pointer
1191// to this memory. Since we do not know when the user will use this pointer, we
1192// can not free it, so it is the responibility of the user
1193// (the code that calls PAPI_read()) to free this memory.
1194static inline long long sdei_compute_quantile(void *param, int percent){
1195 long long quantile, elem_cnt;
1196 void *result_data;
1197 size_t typesize;
1198 sde_counter_t *rcrd;
1199 int (*cmpr_func_ptr)(const void *p1, const void *p2);
1200
1201 rcrd = ((sde_sorting_params_t *)param)->recording;
1202 elem_cnt = rcrd->u.cntr_recorder.data->used_entries;
1203 typesize = rcrd->u.cntr_recorder.data->typesize;
1204
1205 cmpr_func_ptr = ((sde_sorting_params_t *)param)->cmpr_func_ptr;
1206
1207 // The return value is supposed to be a pointer to the correct element, therefore zero
1208 // is a NULL pointer, which should tell the caller that there was a problem.
1209 if( (0 == elem_cnt) || (NULL == cmpr_func_ptr) )
1210 return 0;
1211
1212 // If there is a sorted (contiguous) buffer, but it's stale, we need to free it.
1213 // The value of elem_cnt (rcrd->u.cntr_recorder.data->used_entries) can
1214 // only increase, or be reset to zero, but when it is reset to zero
1215 // (by papi_sde_reset_recorder()) the buffer will be freed (by the same function).
1216 if( (NULL != rcrd->u.cntr_recorder.data->sorted_buffer) &&
1217 (rcrd->u.cntr_recorder.data->sorted_entries < elem_cnt) ){
1218
1219 free( rcrd->u.cntr_recorder.data->sorted_buffer );
1220 rcrd->u.cntr_recorder.data->sorted_buffer = NULL;
1221 rcrd->u.cntr_recorder.data->sorted_entries = 0;
1222 }
1223
1224 // Check if a sorted buffer is already there. If there isn't, allocate one.
1225 if( NULL == rcrd->u.cntr_recorder.data->sorted_buffer ){
1226 rcrd->u.cntr_recorder.data->sorted_buffer = malloc(elem_cnt * typesize);
1227 exp_container_to_contiguous(rcrd->u.cntr_recorder.data, rcrd->u.cntr_recorder.data->sorted_buffer);
1228 // We set this field so we can test later to see if the allocated buffer is stale.
1229 rcrd->u.cntr_recorder.data->sorted_entries = elem_cnt;
1230 }
1231 void *sorted_buffer = rcrd->u.cntr_recorder.data->sorted_buffer;
1232
1233 qsort(sorted_buffer, elem_cnt, typesize, cmpr_func_ptr);
1234 void *tmp_ptr = (char *)sorted_buffer + typesize*((elem_cnt*percent)/100);
1235
1236 // We might free the sorted_buffer (when it becomes stale), so we can't return "tmp_ptr".
1237 // Therefore, we allocate fresh space for the resulting element and copy it there.
1238 // Since we do not know when the user will use this pointer, we will not be able
1239 // to free it, so it is the responibility of the user (who calls PAPI_read()) to
1240 // free this memory.
1241 result_data = malloc(typesize);
1242 memcpy(result_data, tmp_ptr, typesize);
1243
1244 // convert the pointer into a long long so we can return it.
1245 quantile = (long long)result_data;
1246
1247 return quantile;
1248}
1249
1250
1251static long long sdei_compute_q1(void *param){
1252 return sdei_compute_quantile(param, 25);
1253}
1254static long long sdei_compute_med(void *param){
1255 return sdei_compute_quantile(param, 50);
1256}
1257static long long sdei_compute_q3(void *param){
1258 return sdei_compute_quantile(param, 75);
1259}
1260static long long sdei_compute_min(void *param){
1261 return sdei_compute_edge(param, _SDE_CMP_MIN);
1262}
1263static long long sdei_compute_max(void *param){
1264 return sdei_compute_edge(param, _SDE_CMP_MAX);
1265}
1266
1267
static void * cntr_handle
Definition: Gamum.c:22
static papi_handle_t handle
Definition: Gamum.c:21
double tmp
int i
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
#define AO_TS_t
Definition: gcc/hppa.h:39
unsigned long AO_t __attribute__((__aligned__(4)))
Definition: m68k.h:21
void(* papi_sde_check_overflow_status_ptr)(uint32_t cntr_id, long long int value)
Definition: sde.c:21
int(* papi_sde_set_timer_for_overflow_ptr)(void)
Definition: sde.c:22
int
Definition: sde_internal.h:89
void papi_sde_check_overflow_status(unsigned int cntr_uniq_id, long long int latest)
int papi_sde_set_timer_for_overflow(void)
long long int long long
Definition: sde_internal.h:85
int papi_sde_compare_int(const void *p1, const void *p2)
Definition: sde_lib.c:1063
static long long sdei_compute_edge(void *param, int which_edge)
Definition: sde_lib.c:1101
static long long sdei_compute_quantile(void *param, int percent)
Definition: sde_lib.c:1194
papi_handle_t papi_sde_init(const char *name_of_library)
Definition: sde_lib.c:119
int papi_sde_version
Definition: sde_lib.c:38
int papi_sde_disable(papi_handle_t handle)
Definition: sde_lib.c:161
papisde_control_t * _papisde_global_control
Definition: sde_lib.c:37
static long long sdei_compute_q3(void *param)
Definition: sde_lib.c:1257
int papi_sde_reset_recorder(void *record_handle)
Definition: sde_lib.c:940
static long long sdei_compute_max(void *param)
Definition: sde_lib.c:1263
int papi_sde_unregister_counter(papi_handle_t handle, const char *event_name)
Definition: sde_lib.c:342
#define _SDE_CMP_MAX
Definition: sde_lib.c:1096
int papi_sde_enable(papi_handle_t handle)
Definition: sde_lib.c:189
int papi_sde_counting_set_remove(void *cset_handle, size_t hashable_size, const void *element, uint32_t type_id)
Definition: sde_lib.c:737
int papi_sde_counting_set_insert(void *cset_handle, size_t element_size, size_t hashable_size, const void *element, uint32_t type_id)
Definition: sde_lib.c:766
int papi_sde_compare_long_long(const void *p1, const void *p2)
Definition: sde_lib.c:1052
static long long sdei_compute_min(void *param)
Definition: sde_lib.c:1260
int papi_sde_create_recorder(papi_handle_t handle, const char *event_name, size_t typesize, int(*cmpr_func_ptr)(const void *p1, const void *p2), void **record_handle)
Definition: sde_lib.c:794
pthread_mutex_t _sde_hwd_lock_data
Definition: sde_lib.c:43
void * papi_sde_get_counter_handle(void *handle, const char *event_name)
Definition: sde_lib.c:1016
int papi_sde_register_counter(papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, void *counter)
Definition: sde_lib.c:276
int papi_sde_compare_float(const void *p1, const void *p2)
Definition: sde_lib.c:1085
int sdei_set_timer_for_overflow(void)
Definition: sde_lib.c:60
int papi_sde_reset_counter(void *cntr_handle)
Definition: sde_lib.c:973
static void obtain_papi_symbols(void)
Definition: sde_lib.c:72
int papi_sde_shutdown(papi_handle_t handle)
Definition: sde_lib.c:212
int papi_sde_compare_double(const void *p1, const void *p2)
Definition: sde_lib.c:1074
int papi_sde_inc_counter(papi_handle_t cntr_handle, long long int increment)
Definition: sde_lib.c:637
int papi_sde_add_counter_to_group(papi_handle_t handle, const char *event_name, const char *group_name, uint32_t group_flags)
Definition: sde_lib.c:449
int papi_sde_record(void *record_handle, size_t typesize, const void *value)
Definition: sde_lib.c:909
static long long sdei_compute_q1(void *param)
Definition: sde_lib.c:1251
#define _SDE_MODIFIER_COUNT
static long long sdei_compute_med(void *param)
Definition: sde_lib.c:1254
int papi_sde_create_counting_set(papi_handle_t handle, const char *cset_name, void **cset_handle)
Definition: sde_lib.c:682
int papi_sde_register_counter_cb(papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, papi_sde_fptr_t callback, void *param)
Definition: sde_lib.c:312
int papi_sde_create_counter(papi_handle_t handle, const char *event_name, int cntr_mode, void **cntr_handle)
Definition: sde_lib.c:576
int papi_sde_describe_counter(void *handle, const char *event_name, const char *event_description)
Definition: sde_lib.c:398
#define _SDE_CMP_MIN
Definition: sde_lib.c:1095
#define DLSYM_CHECK(name)
Definition: sde_lib.c:14
#define SDE_ENOMEM
Definition: sde_lib.h:41
void * papi_handle_t
Definition: sde_lib.h:100
int _sde_be_verbose
Definition: sde_lib_misc.c:19
#define PAPI_SDE_VERSION
Definition: sde_lib.h:21
#define PAPI_SDE_long_long
Definition: sde_lib.h:28
#define SDE_ECMP
Definition: sde_lib.h:42
#define PAPI_SDE_RO
Definition: sde_lib.h:23
#define SDE_EINVAL
Definition: sde_lib.h:40
static void SDE_ERROR(const char *format,...)
Definition: sde_lib.h:60
#define PAPI_SDE_INSTANT
Definition: sde_lib.h:26
int _sde_debug
Definition: sde_lib_misc.c:20
#define SDEDBG(format, args...)
Definition: sde_lib.h:58
#define SDE_OK
Definition: sde_lib.h:39
long long int(* papi_sde_fptr_t)(void *)
Definition: sde_lib.h:98
#define PAPI_SDE_DELTA
Definition: sde_lib.h:25
int cset_insert_elem(cset_hash_table_t *hash_ptr, size_t element_size, size_t hashable_size, const void *element, uint32_t type_id)
uint32_t ht_hash_name(const char *str)
void exp_container_to_contiguous(recorder_data_t *exp_container, void *cont_buffer)
void ht_insert(papisde_list_entry_t *hash_table, int ht_key, sde_counter_t *sde_counter)
int ht_to_array(papisde_list_entry_t *hash_table, sde_counter_t **rslt_array)
int exp_container_insert_element(recorder_data_t *exp_container, size_t typesize, const void *value)
int cset_remove_elem(cset_hash_table_t *hash_ptr, size_t hashable_size, const void *element, uint32_t type_id)
sde_counter_t * ht_lookup_by_name(papisde_list_entry_t *hash_table, const char *name)
uint32_t ht_hash_id(uint32_t uniq_id)
#define IS_CNTR_CSET(_CNT)
#define EXP_CONTAINER_MIN_SIZE
@ CNTR_CLASS_GROUP
@ CNTR_CLASS_CREATED
@ CNTR_CLASS_CSET
@ CNTR_CLASS_CB
@ CNTR_CLASS_PLACEHOLDER
@ CNTR_CLASS_REGISTERED
@ CNTR_CLASS_RECORDER
int sdei_setup_counter_internals(papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, enum CNTR_CLASS cntr_class, cntr_class_specific_t cntr_union)
Definition: sde_lib_misc.c:156
#define IS_CNTR_RECORDER(_CNT)
papi_handle_t do_sde_init(const char *name_of_library, papisde_control_t *gctl)
Definition: sde_lib_misc.c:91
int sdei_inc_ref_count(sde_counter_t *counter)
Definition: sde_lib_misc.c:236
int sdei_delete_counter(papisde_library_desc_t *lib_handle, const char *name)
Definition: sde_lib_misc.c:260
#define EXP_CONTAINER_ENTRIES
#define IS_CNTR_CREATED(_CNT)
papisde_control_t * sdei_get_global_struct(void)
Definition: sde_lib_misc.c:34
#define sde_lock()
Definition: sde_lib_lock.h:24
#define sde_unlock(lck)
Definition: sde_lib_lock.h:29
papi_sde_fptr_t callback
cset_hash_table_t * data
recorder_data_t * data
cntr_class_recorder_t cntr_recorder
cntr_class_cset_t cntr_cset
cntr_class_callback_t cntr_cb
cntr_class_basic_t cntr_basic