PAPI 7.1.0.0
Loading...
Searching...
No Matches
sde_lib.c File Reference

This is the main implementation of the functionality needed to support SDEs in third party libraries. More...

Include dependency graph for sde_lib.c:

Go to the source code of this file.

Macros

#define DLSYM_CHECK(name)
 
#define _SDE_MODIFIER_COUNT   6
 
#define _SDE_CMP_MIN   0
 
#define _SDE_CMP_MAX   1
 

Functions

static long long sdei_compute_q1 (void *param)
 
static long long sdei_compute_med (void *param)
 
static long long sdei_compute_q3 (void *param)
 
static long long sdei_compute_min (void *param)
 
static long long sdei_compute_max (void *param)
 
static long long sdei_compute_quantile (void *param, int percent)
 
static long long sdei_compute_edge (void *param, int which_edge)
 
int papi_sde_compare_long_long (const void *p1, const void *p2)
 
int papi_sde_compare_int (const void *p1, const void *p2)
 
int papi_sde_compare_double (const void *p1, const void *p2)
 
int papi_sde_compare_float (const void *p1, const void *p2)
 
 __attribute__ ((__common__))
 
int sdei_set_timer_for_overflow (void)
 
static void obtain_papi_symbols (void)
 
papi_handle_t papi_sde_init (const char *name_of_library)
 
int papi_sde_disable (papi_handle_t handle)
 
int papi_sde_enable (papi_handle_t handle)
 
int papi_sde_shutdown (papi_handle_t handle)
 
int papi_sde_register_counter (papi_handle_t handle, const char *event_name, int cntr_mode, int cntr_type, void *counter)
 
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)
 
int papi_sde_unregister_counter (papi_handle_t handle, const char *event_name)
 
int papi_sde_describe_counter (void *handle, const char *event_name, const char *event_description)
 
int papi_sde_add_counter_to_group (papi_handle_t handle, const char *event_name, const char *group_name, uint32_t group_flags)
 
int papi_sde_create_counter (papi_handle_t handle, const char *event_name, int cntr_mode, void **cntr_handle)
 
int papi_sde_inc_counter (papi_handle_t cntr_handle, long long int increment)
 
int papi_sde_create_counting_set (papi_handle_t handle, const char *cset_name, void **cset_handle)
 
int papi_sde_counting_set_remove (void *cset_handle, size_t hashable_size, const void *element, uint32_t type_id)
 
int papi_sde_counting_set_insert (void *cset_handle, size_t element_size, size_t hashable_size, const void *element, uint32_t type_id)
 
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)
 
int papi_sde_record (void *record_handle, size_t typesize, const void *value)
 
int papi_sde_reset_recorder (void *record_handle)
 
int papi_sde_reset_counter (void *cntr_handle)
 
void * papi_sde_get_counter_handle (void *handle, const char *event_name)
 

Variables

papisde_control_t * _papisde_global_control = NULL
 
int papi_sde_version = PAPI_SDE_VERSION
 
pthread_mutex_t _sde_hwd_lock_data
 

Detailed Description

Author
Anthony Danalis adana.nosp@m.lis@.nosp@m.icl.u.nosp@m.tk.e.nosp@m.du

Definition in file sde_lib.c.

Macro Definition Documentation

◆ _SDE_CMP_MAX

#define _SDE_CMP_MAX   1

Definition at line 1096 of file sde_lib.c.

◆ _SDE_CMP_MIN

#define _SDE_CMP_MIN   0

Definition at line 1095 of file sde_lib.c.

◆ _SDE_MODIFIER_COUNT

#define _SDE_MODIFIER_COUNT   6

◆ DLSYM_CHECK

#define DLSYM_CHECK (   name)
Value:
do { \
if ( NULL != (err=dlerror()) ) { \
name##_ptr = NULL; \
SDEDBG("obtain_papi_symbols(): Unable to load symbol %s: %s\n", #name, err);\
return; \
} \
} while (0)
const char * name
Definition: rocs.c:225

Definition at line 14 of file sde_lib.c.

Function Documentation

◆ __attribute__()

__attribute__ ( (__common__)  )

Definition at line 50 of file sde_lib.c.

54 {
56 (*papi_sde_check_overflow_status_ptr)(cntr_uniq_id, latest);
57}
void(* papi_sde_check_overflow_status_ptr)(uint32_t cntr_id, long long int value)
Definition: sde.c:21

◆ obtain_papi_symbols()

static void obtain_papi_symbols ( void  )
inlinestatic

Definition at line 72 of file sde_lib.c.

72 {
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}
static papi_handle_t handle
Definition: Gamum.c:21
int(* papi_sde_set_timer_for_overflow_ptr)(void)
Definition: sde.c:22
void papi_sde_check_overflow_status(unsigned int cntr_uniq_id, long long int latest)
int papi_sde_set_timer_for_overflow(void)
#define DLSYM_CHECK(name)
Definition: sde_lib.c:14
#define SDEDBG(format, args...)
Definition: sde_lib.h:58
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_add_counter_to_group()

int papi_sde_add_counter_to_group ( papi_handle_t  handle,
const char *  event_name,
const char *  group_name,
uint32_t  group_flags 
)

This function adds an event counter to a group. A group is created automatically the first time a counter is added to it.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]group_name– (const char *) name of the group.
[in]group_flags– (uint32_t) one of PAPI_SDE_SUM, PAPI_SDE_MAX, PAPI_SDE_MIN to define how the members of the group will be used to compute the group's value.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 449 of file sde_lib.c.

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}
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
papisde_control_t * _papisde_global_control
Definition: sde_lib.c:37
#define SDE_EINVAL
Definition: sde_lib.h:40
static void SDE_ERROR(const char *format,...)
Definition: sde_lib.h:60
#define SDE_OK
Definition: sde_lib.h:39
uint32_t ht_hash_name(const char *str)
void ht_insert(papisde_list_entry_t *hash_table, int ht_key, sde_counter_t *sde_counter)
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)
@ CNTR_CLASS_GROUP
@ CNTR_CLASS_PLACEHOLDER
int sdei_inc_ref_count(sde_counter_t *counter)
Definition: sde_lib_misc.c:236
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
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_compare_double()

int papi_sde_compare_double ( const void *  p1,
const void *  p2 
)

Definition at line 1074 of file sde_lib.c.

1074 {
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}

◆ papi_sde_compare_float()

int papi_sde_compare_float ( const void *  p1,
const void *  p2 
)

Definition at line 1085 of file sde_lib.c.

1085 {
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}

◆ papi_sde_compare_int()

int papi_sde_compare_int ( const void *  p1,
const void *  p2 
)

Definition at line 1063 of file sde_lib.c.

1063 {
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}

◆ papi_sde_compare_long_long()

int papi_sde_compare_long_long ( const void *  p1,
const void *  p2 
)

Definition at line 1052 of file sde_lib.c.

1052 {
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}
Here is the caller graph for this function:

◆ papi_sde_counting_set_insert()

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 at line 766 of file sde_lib.c.

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}
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)
#define IS_CNTR_CSET(_CNT)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_counting_set_remove()

int papi_sde_counting_set_remove ( void *  cset_handle,
size_t  hashable_size,
const void *  element,
uint32_t  type_id 
)

Definition at line 737 of file sde_lib.c.

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}
int cset_remove_elem(cset_hash_table_t *hash_ptr, size_t hashable_size, const void *element, uint32_t type_id)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_create_counter()

int papi_sde_create_counter ( papi_handle_t  handle,
const char *  event_name,
int  cntr_mode,
void **  cntr_handle 
)

This function creates a counter whose memory is allocated and managed by libsde, in contrast with papi_sde_register_counter(), which works with counters that are managed by the user library that is calling this function. This counter can only by modified via the functions papi_sde_inc_counter() and papi_sde_reset_counter(). This has two benefits over a counter which lives inside the user library and is modified directly by that library: A) Our counter and the modifying API is guaranteed to be thread safe. B) Since libsde knows about each change in the value of the counter, overflowing is accurate. However, this approach has higher overhead than executing "my_cntr += value" inside a user library.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]event_name– (const char *) name of the event.
[in]cntr_mode– (int) the mode of the counter (one of: PAPI_SDE_RO, PAPI_SDE_RW and one of: PAPI_SDE_DELTA, PAPI_SDE_INSTANT).
[out]cntr_handle– address of a pointer in which libsde will store a handle to the newly created counter.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 576 of file sde_lib.c.

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}
static void * cntr_handle
Definition: Gamum.c:22
#define PAPI_SDE_long_long
Definition: sde_lib.h:28
#define SDE_ECMP
Definition: sde_lib.h:42
@ CNTR_CLASS_CREATED
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
cntr_class_basic_t cntr_basic
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_create_counting_set()

int papi_sde_create_counting_set ( papi_handle_t  handle,
const char *  cset_name,
void **  cset_handle 
)

Definition at line 682 of file sde_lib.c.

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}
#define SDE_ENOMEM
Definition: sde_lib.h:41
#define PAPI_SDE_RO
Definition: sde_lib.h:23
#define PAPI_SDE_DELTA
Definition: sde_lib.h:25
@ CNTR_CLASS_CSET
cset_hash_table_t * data
cntr_class_cset_t cntr_cset
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_create_recorder()

int papi_sde_create_recorder ( papi_handle_t  handle,
const char *  event_name,
size_t  typesize,
int(*)(const void *p1, const void *p2)  cmpr_func_ptr,
void **  record_handle 
)

Definition at line 794 of file sde_lib.c.

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}
int i
long long int long long
Definition: sde_internal.h:85
static long long sdei_compute_q3(void *param)
Definition: sde_lib.c:1257
static long long sdei_compute_max(void *param)
Definition: sde_lib.c:1263
static long long sdei_compute_min(void *param)
Definition: sde_lib.c:1260
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
#define PAPI_SDE_INSTANT
Definition: sde_lib.h:26
#define EXP_CONTAINER_MIN_SIZE
@ CNTR_CLASS_CB
@ CNTR_CLASS_REGISTERED
@ CNTR_CLASS_RECORDER
papi_sde_fptr_t callback
recorder_data_t * data
cntr_class_recorder_t cntr_recorder
cntr_class_callback_t cntr_cb
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_describe_counter()

int papi_sde_describe_counter ( void *  handle,
const char *  event_name,
const char *  event_description 
)

This function optionally replaces an event's default description with a description provided by the library developer within the SDE data structure attached to the handle.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]event_name– (const char *) name of the event.
[in]event_description– (const char *) description of the event.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 398 of file sde_lib.c.

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}
Here is the call graph for this function:

◆ papi_sde_disable()

int papi_sde_disable ( papi_handle_t  handle)

This function disables SDE activity for a specific library, or for all libraries that use SDEs until papi_sde_enable() is called.

Parameters
[in]handle– (papi_handle_t) opaque pointer to sde structure for a specific library. If NULL then SDEs will be disabled at a global level.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 161 of file sde_lib.c.

161 {
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}
Here is the call graph for this function:

◆ papi_sde_enable()

int papi_sde_enable ( papi_handle_t  handle)

This function enables SDE activity for a specific library, or for all libraries that use SDEs.

Parameters
[in]handle– (papi_handle_t) opaque pointer to sde structure for a specific library. If NULL then SDEs will be enabled at a global level. Note that if SDEs for a specific library have been explicitly disabled, then they must be explicitly enabled passing that libary's handle. Calling papi_sde_enabled(NULL) will only enable SDEs at the global level. It will not recursivelly enable SDEs for individual libraries.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 189 of file sde_lib.c.

189 {
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}
Here is the call graph for this function:

◆ papi_sde_get_counter_handle()

void * papi_sde_get_counter_handle ( void *  handle,
const char *  event_name 
)

This function finds the handle associated with a created counter, or a recorder, given the library handle and the event name.

Parameters
[in]handle– (void *) pointer to sde structure for an individual library
[in]event_name– name of the event

Definition at line 1016 of file sde_lib.c.

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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_inc_counter()

int papi_sde_inc_counter ( papi_handle_t  cntr_handle,
long long int  increment 
)

Definition at line 637 of file sde_lib.c.

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}
#define IS_CNTR_CREATED(_CNT)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_init()

papi_handle_t papi_sde_init ( const char *  name_of_library)

This function initializes SDE internal data-structures for an individual software library and returns an opaque handle to these structures.

Parameters
[in]name_of_library– (const char *) library name.
[out]sde_handle– (papi_handle_t) opaque pointer to sde structure for initialized library.

Definition at line 119 of file sde_lib.c.

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}
double tmp
static void obtain_papi_symbols(void)
Definition: sde_lib.c:72
int _sde_be_verbose
Definition: sde_lib_misc.c:19
int _sde_debug
Definition: sde_lib_misc.c:20
papi_handle_t do_sde_init(const char *name_of_library, papisde_control_t *gctl)
Definition: sde_lib_misc.c:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_record()

int papi_sde_record ( void *  record_handle,
size_t  typesize,
const void *  value 
)

Definition at line 909 of file sde_lib.c.

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}
int exp_container_insert_element(recorder_data_t *exp_container, size_t typesize, const void *value)
#define IS_CNTR_RECORDER(_CNT)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_register_counter()

int papi_sde_register_counter ( papi_handle_t  handle,
const char *  event_name,
int  cntr_mode,
int  cntr_type,
void *  counter 
)

This function registers an event name and counter within the SDE data structure attached to the handle. A default description for an event is synthesized from the library name and the event name when they are registered.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]event_name– (const char *) name of the event.
[in]cntr_mode– (int) the mode of the counter (one of: PAPI_SDE_RO, PAPI_SDE_RW and one of: PAPI_SDE_DELTA, PAPI_SDE_INSTANT).
[in]cntr_type– (int) the type of the counter (PAPI_SDE_long_long, PAPI_SDE_int, PAPI_SDE_double, PAPI_SDE_float).
[in]counter– pointer to a variable that stores the value for the event.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 276 of file sde_lib.c.

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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_register_counter_cb()

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 
)

This function registers an event name and (caller provided) callback function within the SDE data structure attached to the handle. A default description for an event is synthesized from the library name and the event name when they are registered.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]event_name– (const char *) name of the event.
[in]cntr_mode– (int) the mode of the counter (one of: PAPI_SDE_RO, PAPI_SDE_RW and one of: PAPI_SDE_DELTA, PAPI_SDE_INSTANT).
[in]cntr_type– (int) the type of the counter (PAPI_SDE_long_long, PAPI_SDE_int, PAPI_SDE_double, PAPI_SDE_float).
[in]fp_counter– pointer to a callback function that SDE will call when PAPI_read/stop/accum is called.
[in]param– (void *) opaque parameter that will be passed to the callback function every time it's called.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 312 of file sde_lib.c.

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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_reset_counter()

int papi_sde_reset_counter ( void *  cntr_handle)

Definition at line 973 of file sde_lib.c.

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}
Here is the call graph for this function:

◆ papi_sde_reset_recorder()

int papi_sde_reset_recorder ( void *  record_handle)

Definition at line 940 of file sde_lib.c.

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}
Here is the call graph for this function:

◆ papi_sde_shutdown()

int papi_sde_shutdown ( papi_handle_t  handle)

This function frees all SDE internal data-structures for an individual software library including all memory allocated by the counters of that library.

Parameters
[in]handle– (papi_handle_t) opaque pointer to sde structure for initialized library.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 212 of file sde_lib.c.

212 {
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}
int ht_to_array(papisde_list_entry_t *hash_table, sde_counter_t **rslt_array)
int sdei_delete_counter(papisde_library_desc_t *lib_handle, const char *name)
Definition: sde_lib_misc.c:260
Here is the call graph for this function:
Here is the caller graph for this function:

◆ papi_sde_unregister_counter()

int papi_sde_unregister_counter ( papi_handle_t  handle,
const char *  event_name 
)

This function unregisters (removes) an event name and counter from the SDE data structures.

Parameters
[in]handle– pointer (of opaque type papi_handle_t) to sde structure for an individual library.
[in]event_name– (const char *) name of the event that is being unregistered.
[out]--(int) the return value is SDE_OK on success, or an error code on failure.

Definition at line 342 of file sde_lib.c.

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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_edge()

static long long sdei_compute_edge ( void *  param,
int  which_edge 
)
inlinestatic

Definition at line 1101 of file sde_lib.c.

1101 {
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}
int
Definition: sde_internal.h:89
#define _SDE_CMP_MAX
Definition: sde_lib.c:1096
#define _SDE_CMP_MIN
Definition: sde_lib.c:1095
#define EXP_CONTAINER_ENTRIES
Here is the caller graph for this function:

◆ sdei_compute_max()

static long long sdei_compute_max ( void *  param)
static

Definition at line 1263 of file sde_lib.c.

1263 {
1264 return sdei_compute_edge(param, _SDE_CMP_MAX);
1265}
static long long sdei_compute_edge(void *param, int which_edge)
Definition: sde_lib.c:1101
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_med()

static long long sdei_compute_med ( void *  param)
static

Definition at line 1254 of file sde_lib.c.

1254 {
1255 return sdei_compute_quantile(param, 50);
1256}
static long long sdei_compute_quantile(void *param, int percent)
Definition: sde_lib.c:1194
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_min()

static long long sdei_compute_min ( void *  param)
static

Definition at line 1260 of file sde_lib.c.

1260 {
1261 return sdei_compute_edge(param, _SDE_CMP_MIN);
1262}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_q1()

static long long sdei_compute_q1 ( void *  param)
static

Definition at line 1251 of file sde_lib.c.

1251 {
1252 return sdei_compute_quantile(param, 25);
1253}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_q3()

static long long sdei_compute_q3 ( void *  param)
static

Definition at line 1257 of file sde_lib.c.

1257 {
1258 return sdei_compute_quantile(param, 75);
1259}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_compute_quantile()

static long long sdei_compute_quantile ( void *  param,
int  percent 
)
inlinestatic

Definition at line 1194 of file sde_lib.c.

1194 {
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}
void exp_container_to_contiguous(recorder_data_t *exp_container, void *cont_buffer)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sdei_set_timer_for_overflow()

int sdei_set_timer_for_overflow ( void  )
inline

Definition at line 60 of file sde_lib.c.

60 {
63 return -1;
64}
Here is the caller graph for this function:

Variable Documentation

◆ _papisde_global_control

papisde_control_t* _papisde_global_control = NULL

This global variable points to the head of the control state list

Definition at line 37 of file sde_lib.c.

◆ _sde_hwd_lock_data

pthread_mutex_t _sde_hwd_lock_data

Definition at line 43 of file sde_lib.c.

◆ papi_sde_version

int papi_sde_version = PAPI_SDE_VERSION

Definition at line 38 of file sde_lib.c.