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

This is the component for supporting Software Defined Events (SDE). It provides an interface for libraries, runtimes, and other software layers to export events to other software layers through PAPI. More...

Include dependency graph for sde.c:

Go to the source code of this file.

Macros

#define DLSYM_CHECK(name)
 

Functions

static int sde_load_sde_ti (void)
 
static int _sde_init_component (int cidx)
 
static int _sde_init_thread (hwd_context_t *ctx)
 
static int _sde_init_control_state (hwd_control_state_t *ctl)
 
static int _sde_update_control_state (hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
 
static int _sde_start (hwd_context_t *ctx, hwd_control_state_t *ctl)
 
static int _sde_stop (hwd_context_t *ctx, hwd_control_state_t *ctl)
 
static int _sde_read (hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
 
static int _sde_write (hwd_context_t *ctx, hwd_control_state_t *ctl, long long *values)
 
static int _sde_reset (hwd_context_t *ctx, hwd_control_state_t *ctl)
 
static int _sde_shutdown_component (void)
 
static int _sde_shutdown_thread (hwd_context_t *ctx)
 
static int _sde_ctl (hwd_context_t *ctx, int code, _papi_int_option_t *option)
 
static int _sde_set_domain (hwd_control_state_t *cntrl, int domain)
 
static int _sde_ntv_enum_events (unsigned int *EventCode, int modifier)
 
static int _sde_ntv_code_to_name (unsigned int EventCode, char *name, int len)
 
static int _sde_ntv_code_to_descr (unsigned int EventCode, char *descr, int len)
 
static int _sde_ntv_name_to_code (const char *event_name, unsigned int *event_code)
 
static int _sde_set_overflow (EventSetInfo_t *ESI, int EventIndex, int threshold)
 
static int do_set_timer_for_overflow (sde_control_state_t *sde_ctl)
 
static int sde_arm_timer (sde_control_state_t *sde_ctl)
 
void _sde_dispatch_timer (int n, hwd_siginfo_t *info, void *uc)
 
static void invoke_user_handler (uint32_t cntr_uniq_id)
 
void __attribute__ ((visibility("default")))
 

Variables

papi_vector_t _sde_vector
 
int _sde_component_lock
 
void(* papi_sde_check_overflow_status_ptr )(uint32_t cntr_id, long long int value) = &papi_sde_check_overflow_status
 
int(* papi_sde_set_timer_for_overflow_ptr )(void) = &papi_sde_set_timer_for_overflow
 

Detailed Description

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

Definition in file sde.c.

Macro Definition Documentation

◆ DLSYM_CHECK

#define DLSYM_CHECK (   name)
Value:
do { \
if ( NULL != (err=dlerror()) ) { \
int strErr=snprintf(_sde_vector.cmp_info.disabled_reason, \
"Function '%s' not found in any dynamic lib", \
#name); \
if (strErr > PAPI_MAX_STR_LEN) \
SUBDBG("Unexpected snprintf error.\n"); \
name##_ptr = NULL; \
SUBDBG("sde_load_sde_ti(): Unable to load symbol %s: %s\n", #name, err);\
return ( PAPI_ECMP ); \
} \
} while (0)
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_ECMP
Definition: f90papi.h:214
const char * name
Definition: rocs.c:225
papi_vector_t _sde_vector
Definition: sde.c:17
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20

Definition at line 24 of file sde.c.

Function Documentation

◆ __attribute__()

void __attribute__ ( (visibility("default"))  )

Definition at line 934 of file sde.c.

935 {
936 EventSetInfo_t *ESI;
937 int cidx, i, index_in_ESI;
939 sde_control_state_t *sde_ctl;
940
943 if( NULL == thread )
944 return;
945
946 ESI = thread->running_eventset[cidx];
947 // Check if there is a running event set and it has some events set to overflow
948 if( (NULL == ESI) || !(ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE) )
949 return;
950
951 sde_ctl = ( sde_control_state_t * ) ESI->ctl_state;
952 int event_counter = ESI->overflow.event_counter;
953
954 // Check all the events that are set to overflow
955 index_in_ESI = -1;
956 for (i = 0; i < event_counter; i++ ) {
957 int papi_index = ESI->overflow.EventIndex[i];
958 uint32_t uniq_id = sde_ctl->which_counter[papi_index];
959 // If the created counter that we are incrementing corresponds to
960 // an event that was set to overflow, read the deadline and threshold.
961 if( uniq_id == cntr_uniq_id ){
962 index_in_ESI = i;
963 break;
964 }
965 }
966
967 if( index_in_ESI >= 0 ){
968 long long deadline, threshold;
969 deadline = ESI->overflow.deadline[index_in_ESI];
970 threshold = ESI->overflow.threshold[index_in_ESI];
971
972 // If the current value has exceeded the deadline then
973 // invoke the user handler and update the deadline.
974 if( latest > deadline ){
975 // We adjust the deadline in a way that it remains a multiple of threshold
976 // so we don't create an additive error.
977 ESI->overflow.deadline[index_in_ESI] = threshold*(latest/threshold) + threshold;
978 invoke_user_handler(cntr_uniq_id);
979 }
980 }
981
982 return;
983}
int i
#define PAPI_OVERFLOW_HARDWARE
Definition: f90papi.h:157
static int threshold
void * thread(void *arg)
Definition: kufrin.c:38
static int cidx
static void invoke_user_handler(uint32_t cntr_uniq_id)
Definition: sde.c:884
hwd_control_state_t * ctl_state
EventSetOverflowInfo_t overflow
uint32_t which_counter[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:40
inline_static ThreadInfo_t * _papi_hwi_lookup_thread(int custom_tid)
Definition: threads.h:97
Here is the call graph for this function:

◆ _sde_ctl()

static int _sde_ctl ( hwd_context_t ctx,
int  code,
_papi_int_option_t option 
)
static

This function sets various options in the component

Parameters
[in]ctx– hardware context
[in]codevalid are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT
[in]option– options to be set

Definition at line 415 of file sde.c.

416{
417
418 (void) ctx;
419 (void) code;
420 (void) option;
421
422 SUBDBG( "sde_ctl...\n" );
423
424 return PAPI_OK;
425}
#define PAPI_OK
Definition: f90papi.h:73
#define SUBDBG(format, args...)
Definition: papi_debug.h:64

◆ _sde_dispatch_timer()

void _sde_dispatch_timer ( int  n,
hwd_siginfo_t info,
void *  uc 
)

Definition at line 721 of file sde.c.

721 {
722
723 _papi_hwi_context_t hw_context;
724 vptr_t address;
726 int i, cidx, retval, isHardware, slow_down, speed_up;
727 int found_registered_counters, period_has_changed = 0;
728 EventSetInfo_t *ESI;
729 struct itimerspec its;
730 long long overflow_vector = 0;
731 sde_control_state_t *sde_ctl;
732
733 (void) n;
734
735 SUBDBG("SDE timer expired. Dispatching (papi internal) overflow handler\n");
736
739
740 ESI = thread->running_eventset[cidx];
741 // This holds only the number of events in the eventset that are set to overflow.
742 int event_counter = ESI->overflow.event_counter;
743 sde_ctl = ( sde_control_state_t * ) ESI->ctl_state;
744
745 retval = _papi_hwi_read( thread->context[cidx], ESI, ESI->sw_stop );
746 if ( retval < PAPI_OK )
747 return;
748
749 slow_down = 0;
750 speed_up = 0;
751 found_registered_counters = 0;
752 // Reset the deadline of counters which have exceeded the current deadline
753 // and check if we need to slow down the frequency of the timer.
754 for ( i = 0; i < event_counter; i++ ) {
755 int papi_index = ESI->overflow.EventIndex[i];
756 long long deadline, threshold, latest, previous, diff;
757
758 uint32_t counter_uniq_id = sde_ctl->which_counter[papi_index];
759 if( !sde_ti_is_simple_counter_ptr( counter_uniq_id ) )
760 continue;
761
762 found_registered_counters = 1;
763
764 latest = ESI->sw_stop[papi_index];
765 deadline = ESI->overflow.deadline[i];
767
768 // Find the increment from the previous measurement.
769 previous = sde_ctl->previous_value[papi_index];
770
771 // NOTE: The following code assumes that the counters are "long long". No other
772 // NOTE: type will work correctly.
773 diff = latest-previous;
774
775 // If it's too small we need to slow down the timer, it it's
776 // too large we need to speed up the timer.
777 if( 30*diff < threshold ){
778 slow_down = 1; // I.e., grow the sampling period
779 }else if( 10*diff > threshold ){
780 speed_up = 1; // I.e., shrink the sampling period
781 }
782
783 // Update the "previous" measurement to be the latest one.
784 sde_ctl->previous_value[papi_index] = latest;
785
786 // If this counter has exceeded the deadline, add it in the vector.
787 if ( latest >= deadline ) {
788 // pos[0] holds the first among the native events that compose the given event. If it is a derived event,
789 // then it might be made up of multiple native events, but this is a CPU component concept. The SDE component
790 // does not have derived events (the groups are first class citizens, they don't have multiple pos[] entries).
791 int pos = ESI->EventInfoArray[papi_index].pos[0];
792 SUBDBG ( "Event at index %d (and pos %d) has value %lld which exceeds deadline %lld (threshold %lld, accuracy %.2lf)\n",
793 papi_index, pos, latest, deadline, threshold, 100.0*(double)(latest-deadline)/(double)threshold);
794
795 overflow_vector ^= ( long long ) 1 << pos;
796 // We adjust the deadline in a way that it remains a multiple of threshold so we don't create an additive error.
797 ESI->overflow.deadline[i] = threshold*(latest/threshold) + threshold;
798 }
799 }
800
801 if( !found_registered_counters && sde_ctl->has_timer ){
802 struct itimerspec zero_time;
803 memset(&zero_time, 0, sizeof(struct itimerspec));
804 if (timer_settime(sde_ctl->timerid, 0, &zero_time, NULL) == -1){
805 PAPIERROR("timer_settime");
806 timer_delete(sde_ctl->timerid);
807 sde_ctl->has_timer = 0;
808 return;
809 }
810 goto no_change_in_period;
811 }
812
813 // Since we potentially check multiple counters in the loop above, both conditions could be true (for different counter).
814 // In this case, we give speed_up priority.
815 if( speed_up )
816 slow_down = 0;
817
818 // If neither was set, there is nothing to do here.
819 if( !speed_up && !slow_down )
820 goto no_change_in_period;
821
822 if( !sde_ctl->has_timer )
823 goto no_change_in_period;
824
825 // Get the current value of the timer.
826 if( timer_gettime(sde_ctl->timerid, &its) == -1){
827 PAPIERROR("timer_gettime() failed. Timer will not be modified.\n");
828 goto no_change_in_period;
829 }
830
831 period_has_changed = 0;
832 // We only reduce the period if it is above 131.6us, so it never drops below 100us.
833 if( speed_up && (its.it_interval.tv_nsec > 131607) ){
834 double new_val = (double)its.it_interval.tv_nsec;
835 new_val /= 1.31607; // sqrt(sqrt(3)) = 1.316074
836 its.it_value.tv_nsec = (int)new_val;
837 its.it_interval.tv_nsec = its.it_value.tv_nsec;
838 period_has_changed = 1;
839 SUBDBG ("Timer will be sped up to %ld ns\n", its.it_value.tv_nsec);
840 }
841
842 // We only increase the period if it is below 75.9ms, so it never grows above 100ms.
843 if( slow_down && (its.it_interval.tv_nsec < 75983800) ){
844 double new_val = (double)its.it_interval.tv_nsec;
845 new_val *= 1.31607; // sqrt(sqrt(3)) = 1.316074
846 its.it_value.tv_nsec = (int)new_val;
847 its.it_interval.tv_nsec = its.it_value.tv_nsec;
848 period_has_changed = 1;
849 SUBDBG ("Timer will be slowed down to %ld ns\n", its.it_value.tv_nsec);
850 }
851
852 if( !period_has_changed )
853 goto no_change_in_period;
854
855 if (timer_settime(sde_ctl->timerid, 0, &its, NULL) == -1){
856 PAPIERROR("timer_settime() failed when modifying PAPI internal timer. This might have broken overflow support for this eventset.\n");
857 goto no_change_in_period;
858 }
859
860no_change_in_period:
861
862 // If none of the events exceeded their deadline, there is nothing else to do.
863 if( 0 == overflow_vector ){
864 return;
865 }
866
867 if ( (NULL== thread) || (NULL == thread->running_eventset[cidx]) || (0 == thread->running_eventset[cidx]->overflow.flags) ){
868 PAPIERROR( "_sde_dispatch_timer(): 'Can not access overflow flags'");
869 return;
870 }
871
872 hw_context.si = info;
873 hw_context.ucontext = ( hwd_ucontext_t * ) uc;
874
875 address = GET_OVERFLOW_ADDRESS( hw_context );
876
877 int genOverflowBit = 0;
878
879 _papi_hwi_dispatch_overflow_signal( ( void * ) &hw_context, address, &isHardware, overflow_vector, genOverflowBit, &thread, cidx );
880
881 return;
882}
#define GET_OVERFLOW_ADDRESS(ctx)
Definition: aix-context.h:12
int _papi_hwi_dispatch_overflow_signal(void *papiContext, vptr_t address, int *isHardware, long long overflow_bit, int genOverflowBit, ThreadInfo_t **t, int cidx)
Definition: extras.c:216
void * vptr_t
Definition: papi.h:576
void PAPIERROR(char *format,...)
int _papi_hwi_read(hwd_context_t *context, EventSetInfo_t *ESI, long long *values)
long long int long long
Definition: sde_internal.h:85
int pos[PAPI_EVENTS_IN_DERIVED_EVENT]
long long * sw_stop
EventInfo_t * EventInfoArray
hwd_siginfo_t * si
hwd_ucontext_t * ucontext
long long previous_value[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:42
int retval
Definition: zero_fork.c:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _sde_init_component()

static int _sde_init_component ( int  cidx)
static

Definition at line 117 of file sde.c.

118{
119 int ret_val = PAPI_OK;
120 SUBDBG("_sde_init_component...\n");
121
125
126 ret_val = sde_load_sde_ti();
127 if( PAPI_OK != ret_val ){
128 _sde_vector.cmp_info.disabled = ret_val;
129 int expect = snprintf(_sde_vector.cmp_info.disabled_reason,
130 PAPI_MAX_STR_LEN, "libsde API not found. No SDEs exist in this executable.");
131 if (expect > PAPI_MAX_STR_LEN) {
132 SUBDBG("disabled_reason truncated");
133 }
134 }
135
136 return ret_val;
137}
#define PAPI_NUM_LOCK
Definition: f90papi.h:80
#define NUM_INNER_LOCK
Definition: papi_lock.h:17
int _sde_component_lock
Definition: sde.c:18
static int sde_load_sde_ti(void)
Definition: sde.c:46
Here is the call graph for this function:

◆ _sde_init_control_state()

static int _sde_init_control_state ( hwd_control_state_t ctl)
static

Setup a counter control state. In general a control state holds the hardware info for an EventSet.

Definition at line 158 of file sde.c.

159{
160 SUBDBG( "sde_init_control_state... %p\n", ctl );
161
162 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
163 memset( sde_ctl, 0, sizeof ( sde_control_state_t ) );
164
165 return PAPI_OK;
166}

◆ _sde_init_thread()

static int _sde_init_thread ( hwd_context_t ctx)
static

This is called whenever a thread is initialized

Definition at line 143 of file sde.c.

144{
145 (void)ctx;
146 SUBDBG( "_sde_init_thread %p...\n", ctx );
147 return PAPI_OK;
148}

◆ _sde_ntv_code_to_descr()

static int _sde_ntv_code_to_descr ( unsigned int  EventCode,
char *  descr,
int  len 
)
static

Takes a native event code and passes back the event description

Parameters
EventCodeis the native event code
descris a pointer for the description to be copied to
lenis the size of the descr string

Definition at line 579 of file sde.c.

580{
581 int ret_val = PAPI_OK;
582 unsigned int code = EventCode & PAPI_NATIVE_AND_MASK;
583
584 SUBDBG("_sde_ntv_code_to_descr %u\n", code);
585
587
588 char *ev_descr = sde_ti_get_event_description_ptr((uint32_t)code);
589 if( NULL == ev_descr ){
590 ret_val = PAPI_ENOEVNT;
591 goto fnct_exit;
592 }
593 SUBDBG("Event (code = %d) description: %s\n", code, ev_descr);
594
595 (void)strncpy( descr, ev_descr, len );
596 descr[len-1] = '\0';
597
598fnct_exit:
600 return ret_val;
601}
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_NATIVE_AND_MASK
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
char * descr
Here is the call graph for this function:

◆ _sde_ntv_code_to_name()

static int _sde_ntv_code_to_name ( unsigned int  EventCode,
char *  name,
int  len 
)
static

Takes a native event code and passes back the name

Parameters
EventCodeis the native event code
nameis a pointer for the name to be copied to
lenis the size of the name string

Definition at line 550 of file sde.c.

551{
552 int ret_val = PAPI_OK;
553 unsigned int code = EventCode & PAPI_NATIVE_AND_MASK;
554
555 SUBDBG("_sde_ntv_code_to_name %u\n", code);
556
558
559 char *ev_name = sde_ti_get_event_name_ptr((uint32_t)code);
560 if( NULL == ev_name ){
561 ret_val = PAPI_ENOEVNT;
562 goto fnct_exit;
563 }
564 SUBDBG("Event name = %s (code = %d)\n", ev_name, code);
565 (void)strncpy( name, ev_name, len );
566 name[len-1] = '\0';
567
568fnct_exit:
570 return ret_val;
571}
Here is the call graph for this function:

◆ _sde_ntv_enum_events()

static int _sde_ntv_enum_events ( unsigned int EventCode,
int  modifier 
)
static

Enumerate Native Events

Parameters
EventCodeis the event of interest
modifieris one of PAPI_ENUM_FIRST, PAPI_ENUM_EVENTS If your component has attribute masks then these need to be handled here as well.

Definition at line 479 of file sde.c.

480{
481 unsigned int curr_code, next_code, num_reg_events;
482 int ret_val = PAPI_OK;
483
484 SUBDBG("_sde_ntv_enum_events begin\n\tEventCode=%u modifier=%d\n", *EventCode, modifier);
485
486 switch ( modifier ) {
487
488 /* return EventCode of first event */
489 case PAPI_ENUM_FIRST:
490 /* return the first event that we support */
491 if( sde_ti_get_num_reg_events_ptr() <= 0 ){
492 ret_val = PAPI_ENOEVNT;
493 break;
494 }
495 *EventCode = 0;
496 ret_val = PAPI_OK;
497 break;
498
499 /* return EventCode of next available event */
500 case PAPI_ENUM_EVENTS:
501 curr_code = *EventCode & PAPI_NATIVE_AND_MASK;
502
503 // Lock before we read num_reg_events and the hash-tables.
505
506 num_reg_events = (unsigned int)sde_ti_get_num_reg_events_ptr();
507 if( curr_code >= num_reg_events-1 ){
508 ret_val = PAPI_ENOEVNT;
509 goto unlock;
510 }
511
512 /*
513 * We have to check the events which follow the current one, because unregistering
514 * will create sparcity in the global SDE table, so we can't just return the next
515 * index.
516 */
517 next_code = curr_code;
518 do{
519 next_code++;
520 char *ev_name = sde_ti_get_event_name_ptr((uint32_t)next_code);
521 if( NULL != ev_name ){
522 *EventCode = next_code;
523 SUBDBG("Event name = %s (code = %d)\n", ev_name, next_code);
524 ret_val = PAPI_OK;
525 goto unlock;
526 }
527 }while(next_code < num_reg_events);
528
529 // If we make it here it means that we didn't find the event.
530 ret_val = PAPI_EINVAL;
531
532unlock:
534 break;
535
536 default:
537 ret_val = PAPI_EINVAL;
538 break;
539 }
540
541 return ret_val;
542}
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_EINVAL
Definition: f90papi.h:115
int
Definition: sde_internal.h:89
Here is the call graph for this function:

◆ _sde_ntv_name_to_code()

static int _sde_ntv_name_to_code ( const char *  event_name,
unsigned int event_code 
)
static

Takes a native event name and passes back the code

Parameters
event_name– a pointer for the name to be copied to
event_code– the native event code

Definition at line 608 of file sde.c.

609{
610 int ret_val;
611
612 SUBDBG( "_sde_ntv_name_to_code(%s)\n", event_name );
613
614 ret_val = sde_ti_name_to_code_ptr(event_name, (uint32_t *)event_code);
615
616 return ret_val;
617}
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29

◆ _sde_read()

static int _sde_read ( hwd_context_t ctx,
hwd_control_state_t ctl,
long long **  events,
int  flags 
)
static

Triggered by PAPI_read()

Definition at line 300 of file sde.c.

301{
302 int i;
303 int ret_val = PAPI_OK;
304 (void) flags;
305 (void) ctx;
306
307 SUBDBG( "_sde_read... %p %d\n", ctx, flags );
308 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
309
311 for( i = 0; i < sde_ctl->num_events; i++ ) {
312 uint32_t counter_uniq_id = sde_ctl->which_counter[i];
313 ret_val = sde_ti_read_counter_ptr( counter_uniq_id, &(sde_ctl->counter[i]) );
314 if( PAPI_OK != ret_val ){
315 PAPIERROR("_sde_read(): Error when reading event at index %d.\n",i);
316 goto fnct_exit;
317 }
318
319 }
320 *events = sde_ctl->counter;
321
322fnct_exit:
324 return ret_val;
325}
char events[MAX_EVENTS][BUFSIZ]
long long counter[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:41
Here is the call graph for this function:

◆ _sde_reset()

static int _sde_reset ( hwd_context_t ctx,
hwd_control_state_t ctl 
)
static

Triggered by PAPI_reset() but only if the EventSet is currently running

Definition at line 360 of file sde.c.

361{
362 int i, ret_val=PAPI_OK;
363 (void) ctx;
364
365 SUBDBG( "_sde_reset ctx=%p ctrl=%p...\n", ctx, ctl );
366 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
367
369 for( i = 0; i < sde_ctl->num_events; i++ ) {
370 uint32_t counter_uniq_id = sde_ctl->which_counter[i];
371 ret_val = sde_ti_reset_counter_ptr( counter_uniq_id );
372 if( PAPI_OK != ret_val ){
373 PAPIERROR("_sde_reset(): Error when reseting event at index %d.\n",i);
374 goto fnct_exit;
375 }
376
377 }
378
379fnct_exit:
381 return ret_val;
382}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _sde_set_domain()

static int _sde_set_domain ( hwd_control_state_t cntrl,
int  domain 
)
static

This function has to set the bits needed to count different domains In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER By default return PAPI_EINVAL if none of those are specified and PAPI_OK with success PAPI_DOM_USER is only user context is counted PAPI_DOM_KERNEL is only the Kernel/OS context is counted PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) PAPI_DOM_ALL is all of the domains

Definition at line 437 of file sde.c.

438{
439 (void) cntrl;
440
441 int found = 0;
442 SUBDBG( "sde_set_domain...\n" );
443
444 if ( PAPI_DOM_USER & domain ) {
445 SUBDBG( " PAPI_DOM_USER\n" );
446 found = 1;
447 }
448 if ( PAPI_DOM_KERNEL & domain ) {
449 SUBDBG( " PAPI_DOM_KERNEL\n" );
450 found = 1;
451 }
452 if ( PAPI_DOM_OTHER & domain ) {
453 SUBDBG( " PAPI_DOM_OTHER\n" );
454 found = 1;
455 }
456 if ( PAPI_DOM_ALL & domain ) {
457 SUBDBG( " PAPI_DOM_ALL\n" );
458 found = 1;
459 }
460 if ( !found )
461 return ( PAPI_EINVAL );
462
463 return PAPI_OK;
464}
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_DOM_OTHER
Definition: f90papi.h:21
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_DOM_ALL
Definition: f90papi.h:261

◆ _sde_set_overflow()

static int _sde_set_overflow ( EventSetInfo_t ESI,
int  EventIndex,
int  threshold 
)
static

Definition at line 621 of file sde.c.

621 {
622
623 (void)ESI;
624 (void)EventIndex;
625 (void)threshold;
626
627 SUBDBG("_sde_set_overflow(%d, %d).\n",EventIndex, threshold);
628
630
631 // pos[0] holds the first among the native events that compose the given event. If it is a derived event,
632 // then it might be made up of multiple native events, but this is a CPU component concept. The SDE component
633 // does not have derived events (the groups are first class citizens, they don't have multiple pos[] entries).
634 int pos = ESI->EventInfoArray[EventIndex].pos[0];
635 uint32_t counter_uniq_id = sde_ctl->which_counter[pos];
636
637 // If we still don't know what type the counter is, then we are _not_ in r[1-3] so we can't create a timer here,
638 // but we still have to tell the calling tool/app that there was no error, because the timer will be set in the future.
639 int ret_val = sde_ti_set_counter_overflow_ptr(counter_uniq_id, threshold);
640 if( PAPI_OK >= ret_val ){
641 return ret_val;
642 }
643
644 // A threshold of zero indicates that overflowing is not needed anymore.
645 if( 0 == threshold ){
646 // If we had a timer (if the counter was created we wouldn't have one) then delete it.
647 if( sde_ctl->has_timer )
648 timer_delete(sde_ctl->timerid);
649 sde_ctl->has_timer = 0;
650 }else{
651 // If we are here we are in r[1-3] so we can create the timer
652 return do_set_timer_for_overflow(sde_ctl);
653 }
654
655 return PAPI_OK;
656}
static int do_set_timer_for_overflow(sde_control_state_t *sde_ctl)
Definition: sde.c:662
Here is the call graph for this function:

◆ _sde_shutdown_component()

static int _sde_shutdown_component ( void  )
static

Triggered by PAPI_shutdown()

Definition at line 386 of file sde.c.

387{
388 SUBDBG( "sde_shutdown_component...\n" );
389 return sde_ti_shutdown_ptr();
390}

◆ _sde_shutdown_thread()

static int _sde_shutdown_thread ( hwd_context_t ctx)
static

Called at thread shutdown

Definition at line 394 of file sde.c.

395{
396
397 (void) ctx;
398
399 SUBDBG( "sde_shutdown_thread... %p\n", ctx );
400
401 /* Last chance to clean up thread */
402
403 return PAPI_OK;
404}

◆ _sde_start()

static int _sde_start ( hwd_context_t ctx,
hwd_control_state_t ctl 
)
static

Triggered by PAPI_start()

Definition at line 207 of file sde.c.

208{
209 int ret_val = PAPI_OK;
211 int cidx;
212 struct itimerspec its;
213 ( void ) ctx;
214 ( void ) ctl;
215
216 SUBDBG( "%p %p...\n", ctx, ctl );
217
218 ret_val = _sde_reset(ctx, ctl);
219
220 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
221
222 its.it_value.tv_sec = 0;
223 // We will start the timer at 100us because we adjust its period in _sde_dispatch_timer()
224 // if the counter is not growing fast enough, or growing too slowly.
225 its.it_value.tv_nsec = 100*1000; // 100us
226 its.it_interval.tv_sec = its.it_value.tv_sec;
227 its.it_interval.tv_nsec = its.it_value.tv_nsec;
228
231
232 if ( (NULL != thread) && (NULL != thread->running_eventset[cidx]) && (thread->running_eventset[cidx]->overflow.flags & PAPI_OVERFLOW_HARDWARE) ) {
233 if( !(sde_ctl->has_timer) ){
234 // No registered counters went through r[1-3]
235 int i;
237 for( i = 0; i < sde_ctl->num_events; i++ ) {
238 if( sde_ti_is_counter_set_to_overflow_ptr(sde_ctl->which_counter[i]) ){
239 // Registered counters went through r4
240 if( PAPI_OK == do_set_timer_for_overflow(sde_ctl) )
241 break;
242 }
243 }
245 }
246
247 // r[1-4]
248 if( sde_ctl->has_timer ){
249 SUBDBG( "starting SDE internal timer for emulating HARDWARE overflowing\n");
250 if (timer_settime(sde_ctl->timerid, 0, &its, NULL) == -1){
251 PAPIERROR("timer_settime");
252 timer_delete(sde_ctl->timerid);
253 sde_ctl->has_timer = 0;
254 return PAPI_ECMP;
255 }
256 }
257 }
258
259 return ret_val;
260}
static int _sde_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: sde.c:360
Here is the call graph for this function:

◆ _sde_stop()

static int _sde_stop ( hwd_context_t ctx,
hwd_control_state_t ctl 
)
static

Triggered by PAPI_stop()

Definition at line 265 of file sde.c.

266{
267
268 (void) ctx;
269 (void) ctl;
271 int cidx;
272 struct itimerspec zero_time;
273
274 SUBDBG( "sde_stop %p %p...\n", ctx, ctl );
275 /* anything that would need to be done at counter stop time */
276
277 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
278
281
282 if ( (NULL != thread) && (NULL != thread->running_eventset[cidx]) && (thread->running_eventset[cidx]->overflow.flags & PAPI_OVERFLOW_HARDWARE) ) {
283 if( sde_ctl->has_timer ){
284 SUBDBG( "stopping SDE internal timer\n");
285 memset(&zero_time, 0, sizeof(struct itimerspec));
286 if (timer_settime(sde_ctl->timerid, 0, &zero_time, NULL) == -1){
287 PAPIERROR("timer_settime");
288 timer_delete(sde_ctl->timerid);
289 sde_ctl->has_timer = 0;
290 return PAPI_ECMP;
291 }
292 }
293 }
294
295 return PAPI_OK;
296}
Here is the call graph for this function:

◆ _sde_update_control_state()

static int _sde_update_control_state ( hwd_control_state_t ctl,
NativeInfo_t native,
int  count,
hwd_context_t ctx 
)
static

Triggered by eventset operations like add or remove

Definition at line 171 of file sde.c.

175{
176
177 (void) ctx;
178 int i, index;
179
180 SUBDBG( "_sde_update_control_state %p %p...\n", ctl, ctx );
181
182 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
183
184 for( i = 0; i < count; i++ ) {
185 index = native[i].ni_event & PAPI_NATIVE_AND_MASK;
186 if( index < 0 ){
187 PAPIERROR("_sde_update_control_state(): Event at index %d has a negative native event code = %d.\n",i,index);
188 return PAPI_EINVAL;
189 }
190 SUBDBG("_sde_update_control_state: i=%d index=%u\n", i, index );
191 sde_ctl->which_counter[i] = (uint32_t)index;
192 native[i].ni_position = i;
193 }
194
195 // If an event for which overflowing was set is being removed from the eventset, then the
196 // framework will turn overflowing off (by calling PAPI_overflow() with threshold=0),
197 // so we don't need to do anything here.
198
199 sde_ctl->num_events=count;
200
201 return PAPI_OK;
202}
static long count
static int native
Here is the call graph for this function:

◆ _sde_write()

static int _sde_write ( hwd_context_t ctx,
hwd_control_state_t ctl,
long long values 
)
static

Triggered by PAPI_write(), but only if the counters are running

Definition at line 330 of file sde.c.

331{
332 int i, ret_val = PAPI_OK;
333 (void) ctx;
334 (void) ctl;
335
336 SUBDBG( "_sde_write... %p\n", ctx );
337 sde_control_state_t *sde_ctl = ( sde_control_state_t * ) ctl;
338
339 // Lock before we access global data structures.
341 for( i = 0; i < sde_ctl->num_events; i++ ) {
342 uint32_t counter_uniq_id = sde_ctl->which_counter[i];
343 ret_val = sde_ti_write_counter_ptr( counter_uniq_id, values[i] );
344 if( PAPI_OK != ret_val ){
345 PAPIERROR("_sde_write(): Error when writing event at index %d.\n",i);
346 goto fnct_exit;
347 }
348 }
349
350fnct_exit:
352 return ret_val;
353}
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
Here is the call graph for this function:

◆ do_set_timer_for_overflow()

static int do_set_timer_for_overflow ( sde_control_state_t sde_ctl)
static

This code assumes that it is called ONLY for registered counters, and that is why it sets has_timer to REGISTERED_EVENT_MASK

Definition at line 662 of file sde.c.

662 {
663 int signo, sig_offset;
664 struct sigevent sigev;
665 struct sigaction sa;
666
667 sig_offset = 0;
668
669 // Choose a new real-time signal
670 signo = SIGRTMIN+sig_offset;
671 if(signo > SIGRTMAX){
672 PAPIERROR("do_set_timer_for_overflow(): Unable to create new timer due to large number of existing timers. Overflowing will not be activated for the current event.\n");
673 return PAPI_ECMP;
674 }
675
676 // setup the signal handler
677 sa.sa_flags = SA_SIGINFO;
678 sa.sa_sigaction = _sde_dispatch_timer;
679 sigemptyset(&sa.sa_mask);
680 if (sigaction(signo, &sa, NULL) == -1){
681 PAPIERROR("do_set_timer_for_overflow(): sigaction() failed.");
682 return PAPI_ECMP;
683 }
684
685 // create the timer
686 sigev.sigev_notify = SIGEV_SIGNAL;
687 sigev.sigev_signo = signo;
688 sigev.sigev_value.sival_ptr = &(sde_ctl->timerid);
689 if (timer_create(CLOCK_REALTIME, &sigev, &(sde_ctl->timerid)) == -1){
690 PAPIERROR("do_set_timer_for_overflow(): timer_create() failed.");
691 return PAPI_ECMP;
692 }
694
695 return PAPI_OK;
696}
@ SIGEV_SIGNAL
int sigaction(int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact) __attribute__((__nothrow__
void _sde_dispatch_timer(int n, hwd_siginfo_t *info, void *uc)
Definition: sde.c:721
#define REGISTERED_EVENT_MASK
Definition: sde_internal.h:19
Here is the call graph for this function:
Here is the caller graph for this function:

◆ invoke_user_handler()

static void invoke_user_handler ( uint32_t  cntr_uniq_id)
static

Definition at line 884 of file sde.c.

884 {
885 EventSetInfo_t *ESI;
886 int i, cidx;
888 sde_control_state_t *sde_ctl;
889 _papi_hwi_context_t hw_context;
890 ucontext_t uc;
891 vptr_t address;
892 long long overflow_vector;
893
896 ESI = thread->running_eventset[cidx];
897
898 // checking again, just to be sure.
899 if( !(ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE) ) {
900 return;
901 }
902
903 sde_ctl = ( sde_control_state_t * ) ESI->ctl_state;
904
905 // This path comes from papi_sde_inc_counter() which increment _ONLY_ one counter, so we don't
906 // need to check if any others have overflown.
907 overflow_vector = 0;
908 for( i = 0; i < sde_ctl->num_events; i++ ) {
909 uint32_t uniq_id = sde_ctl->which_counter[i];
910
911 if( uniq_id == cntr_uniq_id ){
912 // pos[0] holds the first among the native events that compose the given event. If it is a derived event,
913 // then it might be made up of multiple native events, but this is a CPU component concept. The SDE component
914 // does not have derived events (the groups are first class citizens, they don't have multiple pos[] entries).
915 int pos = ESI->EventInfoArray[i].pos[0];
916 if( pos == -1 ){
917 PAPIERROR( "The PAPI framework considers this event removed from the eventset, but the component does not\n");
918 return;
919 }
920 overflow_vector = ( long long ) 1 << pos;
921 }
922 }
923
924 getcontext( &uc );
925 hw_context.ucontext = &uc;
926 hw_context.si = NULL;
927 address = GET_OVERFLOW_ADDRESS( hw_context );
928
929 ESI->overflow.handler( ESI->EventSetIndex, ( void * ) address, overflow_vector, hw_context.ucontext );
930 return;
931}
static int num_events
PAPI_overflow_handler_t handler
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sde_arm_timer()

static int sde_arm_timer ( sde_control_state_t sde_ctl)
inlinestatic

Definition at line 698 of file sde.c.

698 {
699 struct itimerspec its;
700
701 // We will start the timer at 100us because we adjust its period in _sde_dispatch_timer()
702 // if the counter is not growing fast enough, or growing too slowly.
703 its.it_value.tv_sec = 0;
704 its.it_value.tv_nsec = 100*1000; // 100us
705 its.it_interval.tv_sec = its.it_value.tv_sec;
706 its.it_interval.tv_nsec = its.it_value.tv_nsec;
707
708 SUBDBG( "starting SDE internal timer for emulating HARDWARE overflowing\n");
709 if (timer_settime(sde_ctl->timerid, 0, &its, NULL) == -1){
710 PAPIERROR("timer_settime");
711 timer_delete(sde_ctl->timerid);
712 sde_ctl->has_timer = 0;
713
714 // If the timer is broken, let the caller know that something internal went wrong.
715 return PAPI_ECMP;
716 }
717
718 return PAPI_OK;
719}
Here is the call graph for this function:

◆ sde_load_sde_ti()

static int sde_load_sde_ti ( void  )
static

Definition at line 46 of file sde.c.

46 {
47 char *err;
48
49 // In case of static linking the function pointers will be automatically set
50 // by the linker and the dlopen()/dlsym() would fail at runtime, so we want to
51 // check if the linker has done its magic first.
52 if( (NULL != sde_ti_reset_counter_ptr) &&
53 (NULL != sde_ti_reset_counter_ptr) &&
54 (NULL != sde_ti_read_counter_ptr) &&
55 (NULL != sde_ti_write_counter_ptr) &&
56 (NULL != sde_ti_name_to_code_ptr) &&
57 (NULL != sde_ti_is_simple_counter_ptr) &&
58 (NULL != sde_ti_is_counter_set_to_overflow_ptr) &&
59 (NULL != sde_ti_set_counter_overflow_ptr) &&
60 (NULL != sde_ti_get_event_name_ptr) &&
61 (NULL != sde_ti_get_event_description_ptr) &&
62 (NULL != sde_ti_get_num_reg_events_ptr) &&
63 (NULL != sde_ti_shutdown_ptr)
64 ){
65 return PAPI_OK;
66 }
67
68 (void)dlerror(); // Clear the internal string so we can diagnose errors later on.
69
70 void *handle = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
71 if( NULL != (err = dlerror()) ){
72 SUBDBG("sde_load_sde_ti(): %s\n",err);
73 return PAPI_ENOSUPP;
74 }
75
76 sde_ti_reset_counter_ptr = (int (*)( uint32_t ))dlsym( handle, "sde_ti_reset_counter" );
78
79 sde_ti_read_counter_ptr = (int (*)( uint32_t, long long int * ))dlsym( handle, "sde_ti_read_counter" );
81
82 sde_ti_write_counter_ptr = (int (*)( uint32_t, long long ))dlsym( handle, "sde_ti_write_counter" );
84
85 sde_ti_name_to_code_ptr = (int (*)( const char *, uint32_t * ))dlsym( handle, "sde_ti_name_to_code" );
87
88 sde_ti_is_simple_counter_ptr = (int (*)( uint32_t ))dlsym( handle, "sde_ti_is_simple_counter" );
90
91 sde_ti_is_counter_set_to_overflow_ptr = (int (*)( uint32_t ))dlsym( handle, "sde_ti_is_counter_set_to_overflow" );
93
94 sde_ti_set_counter_overflow_ptr = (int (*)( uint32_t, int ))dlsym( handle, "sde_ti_set_counter_overflow" );
96
97 sde_ti_get_event_name_ptr = (char * (*)( int ))dlsym( handle, "sde_ti_get_event_name" );
99
100 sde_ti_get_event_description_ptr = (char * (*)( int ))dlsym( handle, "sde_ti_get_event_description" );
102
103 sde_ti_get_num_reg_events_ptr = (int (*)( void ))dlsym( handle, "sde_ti_get_num_reg_events" );
105
106 sde_ti_shutdown_ptr = (int (*)( void ))dlsym( handle, "sde_ti_shutdown" );
108
109 return PAPI_OK;
110}
static papi_handle_t handle
Definition: Gamum.c:21
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define DLSYM_CHECK(name)
Definition: sde.c:24
int sde_ti_read_counter(uint32_t, long long int *)
int sde_ti_is_simple_counter(uint32_t)
Definition: sde_lib_ti.c:325
int sde_ti_name_to_code(const char *, uint32_t *)
Definition: sde_lib_ti.c:204
int sde_ti_is_counter_set_to_overflow(uint32_t)
Definition: sde_lib_ti.c:343
int sde_ti_reset_counter(uint32_t)
Definition: sde_lib_ti.c:169
int sde_ti_set_counter_overflow(uint32_t, int)
Definition: sde_lib_ti.c:360
int sde_ti_get_num_reg_events(void)
Definition: sde_lib_ti.c:433
char * sde_ti_get_event_name(int)
Definition: sde_lib_ti.c:399
char * sde_ti_get_event_description(int)
Definition: sde_lib_ti.c:416
int sde_ti_write_counter(uint32_t, long long)
Definition: sde_lib_ti.c:136
int sde_ti_shutdown(void)
Definition: sde_lib_ti.c:446
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ _sde_component_lock

int _sde_component_lock

Definition at line 18 of file sde.c.

◆ _sde_vector

papi_vector_t _sde_vector

Vector that points to entry points for our component

Definition at line 17 of file sde.c.

◆ papi_sde_check_overflow_status_ptr

void(* papi_sde_check_overflow_status_ptr) (uint32_t cntr_id, long long int value) ( uint32_t  cntr_id,
long long int  value 
) = &papi_sde_check_overflow_status

Definition at line 21 of file sde.c.

◆ papi_sde_set_timer_for_overflow_ptr

int(* papi_sde_set_timer_for_overflow_ptr) (void) ( void  ) = &papi_sde_set_timer_for_overflow

Definition at line 22 of file sde.c.