PAPI 7.1.0.0
Loading...
Searching...
No Matches
sde.c
Go to the documentation of this file.
1
14#include "sde_internal.h"
15#include <string.h>
16
19
20// The following two function pointers will be used by libsde in case PAPI is statically linked (libpapi.a)
21void (*papi_sde_check_overflow_status_ptr)(uint32_t cntr_id, long long int value) = &papi_sde_check_overflow_status;
23
24#define DLSYM_CHECK(name) \
25 do { \
26 if ( NULL != (err=dlerror()) ) { \
27 int strErr=snprintf(_sde_vector.cmp_info.disabled_reason, \
28 PAPI_MAX_STR_LEN, \
29 "Function '%s' not found in any dynamic lib", \
30 #name); \
31 if (strErr > PAPI_MAX_STR_LEN) \
32 SUBDBG("Unexpected snprintf error.\n"); \
33 name##_ptr = NULL; \
34 SUBDBG("sde_load_sde_ti(): Unable to load symbol %s: %s\n", #name, err);\
35 return ( PAPI_ECMP ); \
36 } \
37 } while (0)
38
39/*
40 If the library is being built statically then there is no need (or ability)
41 to access symbols through dlopen/dlsym; applications using the static version
42 of PAPI (libpapi.a) must also be linked against libsde for supporting SDEs.
43 However, if the dynamic library is used (libpapi.so) then we will look for
44 the symbols from libsde.so dynamically.
45*/
46static int sde_load_sde_ti( void ){
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}
111
112/********************************************************************/
113/* Below are the functions required by the PAPI component interface */
114/********************************************************************/
115
116static int
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}
138
139
140
142static int
144{
145 (void)ctx;
146 SUBDBG( "_sde_init_thread %p...\n", ctx );
147 return PAPI_OK;
148}
149
150
151
157static int
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}
167
168
170static int
173 int count,
174 hwd_context_t *ctx )
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}
203
204
206static int
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}
261
262
264static int
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}
297
299static int
300_sde_read( hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags )
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}
326
328/* otherwise, the updated state is written to ESI->hw_start */
329static int
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}
354
355
357/* If the eventset is not currently running, then the saved value in the */
358/* EventSet is set to zero without calling this routine. */
359static int
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}
383
385static int
387{
388 SUBDBG( "sde_shutdown_component...\n" );
389 return sde_ti_shutdown_ptr();
390}
391
393static int
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}
405
406
407
414static int
415_sde_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
416{
417
418 (void) ctx;
419 (void) code;
420 (void) option;
421
422 SUBDBG( "sde_ctl...\n" );
423
424 return PAPI_OK;
425}
426
436static int
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}
465
466
467/**************************************************************/
468/* Naming functions, used to translate event numbers to names */
469/**************************************************************/
470
471
478static int
479_sde_ntv_enum_events( unsigned int *EventCode, int modifier )
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}
543
549static int
550_sde_ntv_code_to_name( unsigned int EventCode, char *name, int len )
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}
572
578static int
579_sde_ntv_code_to_descr( unsigned int EventCode, char *descr, int len )
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}
602
607static int
608_sde_ntv_name_to_code(const char *event_name, unsigned int *event_code )
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}
618
619
620static int
621_sde_set_overflow( EventSetInfo_t *ESI, int EventIndex, int threshold ){
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}
657
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}
697
698static inline int sde_arm_timer(sde_control_state_t *sde_ctl){
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}
720
721void _sde_dispatch_timer( int n, hwd_siginfo_t *info, void *uc) {
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}
883
884static void invoke_user_handler(uint32_t cntr_uniq_id){
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}
932
933void
934__attribute__((visibility("default")))
935papi_sde_check_overflow_status(uint32_t cntr_uniq_id, long long int latest){
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}
984
985// The following function should only be called from within
986// sde_do_register() in libsde.so, which guarantees we are in cases r[4-6].
987int
988__attribute__((visibility("default")))
991 EventSetInfo_t *ESI;
992 sde_control_state_t *sde_ctl;
993
995 if( NULL == thread )
996 return PAPI_OK;
997
998 // Get the current running eventset and check if it has some events set to overflow.
1000 ESI = thread->running_eventset[cidx];
1001 if( (NULL == ESI) || !(ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE) )
1002 return PAPI_OK;
1003
1004 sde_ctl = ( sde_control_state_t * ) ESI->ctl_state;
1005
1006 // Below this point we know we have a running eventset, so we are in case r5.
1007 // Since the event is set to overfow, if there is no timer in the eventset, create one and arm it.
1008 if( !(sde_ctl->has_timer) ){
1009 int ret = do_set_timer_for_overflow(sde_ctl);
1010 if( PAPI_OK != ret ){
1011 return ret;
1012 }
1013 ret = sde_arm_timer(sde_ctl);
1014 return ret;
1015 }
1016
1017 return PAPI_OK;
1018}
1019
1022 .cmp_info = {
1023 /* default component information */
1024 /* (unspecified values are initialized to 0) */
1025 /* we explicitly set them to zero in this sde */
1026 /* to show what settings are available */
1027
1028 .name = "sde",
1029 .short_name = "sde",
1030 .description = "Software Defined Events (SDE) component",
1031 .version = "1.15",
1032 .support_version = "n/a",
1033 .kernel_version = "n/a",
1034 .num_cntrs = SDE_MAX_SIMULTANEOUS_COUNTERS,
1035 .num_mpx_cntrs = SDE_MAX_SIMULTANEOUS_COUNTERS,
1036 .default_domain = PAPI_DOM_USER,
1037 .available_domains = PAPI_DOM_USER,
1038 .default_granularity = PAPI_GRN_THR,
1039 .available_granularities = PAPI_GRN_THR,
1040 .hardware_intr_sig = PAPI_INT_SIGNAL,
1041 .hardware_intr = 1,
1042
1043 /* component specific cmp_info initializations */
1044 },
1045
1046 /* sizes of framework-opaque component-private structures */
1047 .size = {
1048 /* once per thread */
1049 .context = sizeof ( sde_context_t ),
1050 /* once per eventset */
1051 .control_state = sizeof ( sde_control_state_t ),
1052 /* ?? */
1053 .reg_value = sizeof ( sde_register_t ),
1054 /* ?? */
1055 .reg_alloc = sizeof ( sde_reg_alloc_t ),
1056 },
1057
1058 /* function pointers */
1059 /* by default they are set to NULL */
1060
1061 /* Used for general PAPI interactions */
1062 .start = _sde_start,
1063 .stop = _sde_stop,
1064 .read = _sde_read,
1065 .reset = _sde_reset,
1066 .write = _sde_write,
1067 .init_component = _sde_init_component,
1068 .init_thread = _sde_init_thread,
1069 .init_control_state = _sde_init_control_state,
1070 .update_control_state = _sde_update_control_state,
1071 .ctl = _sde_ctl,
1072 .shutdown_thread = _sde_shutdown_thread,
1073 .shutdown_component = _sde_shutdown_component,
1074 .set_domain = _sde_set_domain,
1075 /* .cleanup_eventset = NULL, */
1076 /* called in add_native_events() */
1077 /* .allocate_registers = NULL, */
1078
1079 /* Used for overflow/profiling */
1080 .dispatch_timer = _sde_dispatch_timer,
1081 .set_overflow = _sde_set_overflow,
1082 /* .get_overflow_address = NULL, */
1083 /* .stop_profiling = NULL, */
1084 /* .set_profile = NULL, */
1085
1086 /* ??? */
1087 /* .user = NULL, */
1088
1089 /* Name Mapping Functions */
1090 .ntv_enum_events = _sde_ntv_enum_events,
1091 .ntv_code_to_name = _sde_ntv_code_to_name,
1092 .ntv_code_to_descr = _sde_ntv_code_to_descr,
1093 /* if .ntv_name_to_code not available, PAPI emulates */
1094 /* it by enumerating all events and looking manually */
1095 .ntv_name_to_code = _sde_ntv_name_to_code,
1096
1097
1098 /* These are only used by _papi_hwi_get_native_event_info() */
1099 /* Which currently only uses the info for printing native */
1100 /* event info, not for any sort of internal use. */
1101 /* .ntv_code_to_bits = NULL, */
1102
1103};
1104
static papi_handle_t handle
Definition: Gamum.c:21
int i
#define GET_OVERFLOW_ADDRESS(ctx)
Definition: aix-context.h:12
static long count
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
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
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_DOM_OTHER
Definition: f90papi.h:21
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_NUM_LOCK
Definition: f90papi.h:80
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_ECMP
Definition: f90papi.h:214
#define PAPI_OVERFLOW_HARDWARE
Definition: f90papi.h:157
#define PAPI_GRN_THR
Definition: f90papi.h:265
#define PAPI_DOM_ALL
Definition: f90papi.h:261
char events[MAX_EVENTS][BUFSIZ]
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
static int threshold
void * thread(void *arg)
Definition: kufrin.c:38
static int num_events
unsigned long AO_t __attribute__((__aligned__(4)))
Definition: m68k.h:21
#define PAPI_NATIVE_AND_MASK
void * vptr_t
Definition: papi.h:576
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
@ SIGEV_SIGNAL
int sigaction(int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact) __attribute__((__nothrow__
void PAPIERROR(char *format,...)
int _papi_hwi_read(hwd_context_t *context, EventSetInfo_t *ESI, long long *values)
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
#define NUM_INNER_LOCK
Definition: papi_lock.h:17
static int native
static int cidx
const char * name
Definition: rocs.c:225
static int sde_arm_timer(sde_control_state_t *sde_ctl)
Definition: sde.c:698
static int _sde_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *values)
Definition: sde.c:330
int _sde_component_lock
Definition: sde.c:18
static int do_set_timer_for_overflow(sde_control_state_t *sde_ctl)
Definition: sde.c:662
static int _sde_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: sde.c:415
static int _sde_init_control_state(hwd_control_state_t *ctl)
Definition: sde.c:158
static int _sde_set_overflow(EventSetInfo_t *ESI, int EventIndex, int threshold)
Definition: sde.c:621
static int _sde_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: sde.c:360
static int _sde_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: sde.c:171
static int _sde_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: sde.c:265
papi_vector_t _sde_vector
Definition: sde.c:17
static int sde_load_sde_ti(void)
Definition: sde.c:46
static int _sde_shutdown_component(void)
Definition: sde.c:386
static int _sde_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: sde.c:207
static int _sde_ntv_code_to_descr(unsigned int EventCode, char *descr, int len)
Definition: sde.c:579
void _sde_dispatch_timer(int n, hwd_siginfo_t *info, void *uc)
Definition: sde.c:721
static int _sde_init_component(int cidx)
Definition: sde.c:117
static int _sde_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: sde.c:550
static int _sde_init_thread(hwd_context_t *ctx)
Definition: sde.c:143
static int _sde_set_domain(hwd_control_state_t *cntrl, int domain)
Definition: sde.c:437
void(* papi_sde_check_overflow_status_ptr)(uint32_t cntr_id, long long int value)
Definition: sde.c:21
static void invoke_user_handler(uint32_t cntr_uniq_id)
Definition: sde.c:884
static int _sde_ntv_name_to_code(const char *event_name, unsigned int *event_code)
Definition: sde.c:608
int(* papi_sde_set_timer_for_overflow_ptr)(void)
Definition: sde.c:22
static int _sde_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: sde.c:300
static int _sde_shutdown_thread(hwd_context_t *ctx)
Definition: sde.c:394
static int _sde_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: sde.c:479
#define DLSYM_CHECK(name)
Definition: sde.c:24
#define SDE_MAX_SIMULTANEOUS_COUNTERS
Definition: sde_internal.h:5
int
Definition: sde_internal.h:89
void papi_sde_check_overflow_status(unsigned int cntr_uniq_id, long long int latest)
#define REGISTERED_EVENT_MASK
Definition: sde_internal.h:19
int papi_sde_set_timer_for_overflow(void)
long long int long long
Definition: sde_internal.h:85
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
int pos[PAPI_EVENTS_IN_DERIVED_EVENT]
long long * sw_stop
EventInfo_t * EventInfoArray
hwd_control_state_t * ctl_state
EventSetOverflowInfo_t overflow
PAPI_overflow_handler_t handler
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
hwd_siginfo_t * si
hwd_ucontext_t * ucontext
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
long long counter[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:41
uint32_t which_counter[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:40
long long previous_value[SDE_MAX_SIMULTANEOUS_COUNTERS]
Definition: sde_internal.h:42
inline_static ThreadInfo_t * _papi_hwi_lookup_thread(int custom_tid)
Definition: threads.h:97
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
int retval
Definition: zero_fork.c:53