PAPI 7.1.0.0
Loading...
Searching...
No Matches
sw_multiplex.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MPX_EventSet
 
struct  EventSetMultiplexInfo_t
 

Macros

#define PAPI_MAX_SW_MPX_EVENTS   32
 

Enumerations

enum  MPX_status { MPX_STOPPED , MPX_RUNNING }
 

Functions

int mpx_check (int EventSet)
 
int mpx_init (int)
 
int mpx_add_event (MPX_EventSet **, int EventCode, int domain, int granularity)
 
int mpx_remove_event (MPX_EventSet **, int EventCode)
 
int MPX_add_events (MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
 
int MPX_stop (MPX_EventSet *mpx_events, long long *values)
 
int MPX_cleanup (MPX_EventSet **mpx_events)
 
void MPX_shutdown (void)
 
int MPX_reset (MPX_EventSet *mpx_events)
 
int MPX_read (MPX_EventSet *mpx_events, long long *values, int called_by_stop)
 
int MPX_start (MPX_EventSet *mpx_events)
 

Macro Definition Documentation

◆ PAPI_MAX_SW_MPX_EVENTS

#define PAPI_MAX_SW_MPX_EVENTS   32

Definition at line 4 of file sw_multiplex.h.

Enumeration Type Documentation

◆ MPX_status

enum MPX_status
Enumerator
MPX_STOPPED 
MPX_RUNNING 

Definition at line 9 of file sw_multiplex.h.

MPX_status
Definition: sw_multiplex.h:10
@ MPX_RUNNING
Definition: sw_multiplex.h:10
@ MPX_STOPPED
Definition: sw_multiplex.h:10

Function Documentation

◆ mpx_add_event()

int mpx_add_event ( MPX_EventSet **  mpx_events,
int  EventCode,
int  domain,
int  granularity 
)

Definition at line 305 of file sw_multiplex.c.

307{
308 MPX_EventSet *newset = *mpx_events;
309 int retval, alloced_newset = 0;
310 Threadlist *t;
311
312 /* Get the global list of threads */
313
314 MPXDBG("Adding %p %#x\n",newset,EventCode);
315
317 t = tlist;
318
319 /* If there are no threads in the list at all, then allocate the new Threadlist */
320
321 if ( t == NULL ) {
322 new_thread:
323 t = ( Threadlist * ) papi_malloc( sizeof ( Threadlist ) );
324 if ( t == NULL ) {
326 return ( PAPI_ENOMEM );
327 }
328
329 /* If we're actually threaded, fill the
330 * field with the thread_id otherwise
331 * use getpid() as a placeholder. */
332
334 MPXDBG( "New thread at %p\n", t );
336 } else {
337 MPXDBG( "New process at %p\n", t );
338 t->tid = ( unsigned long ) getpid( );
339 }
340
341 /* Fill in the fields */
342
343 t->head = NULL;
344 t->cur_event = NULL;
345 t->next = tlist;
346 tlist = t;
347 MPXDBG( "New head is at %p(%lu).\n", tlist,
348 ( long unsigned ) tlist->tid );
349 /* alloced_thread = 1; */
350 } else if ( _papi_hwi_thread_id_fn ) {
351
352 /* If we are threaded, AND there exists threads in the list,
353 * then try to find our thread in the list. */
354
355 unsigned long tid = _papi_hwi_thread_id_fn( );
356
357 while ( t ) {
358 if ( t->tid == tid ) {
359 MPXDBG( "Found thread %#lx\n", t->tid );
360 break;
361 }
362 t = t->next;
363 }
364
365 /* Our thread is not in the list, so make a new
366 * thread entry. */
367
368 if ( t == NULL ) {
369 MPXDBG( "New thread %lx\n", tid );
370 goto new_thread;
371 }
372 }
373
374 /* Now t & tlist points to our thread, also at the head of the list */
375
376 /* Allocate a the MPX_EventSet if necessary */
377
378 if ( newset == NULL ) {
379 newset = mpx_malloc( t );
380 if ( newset == NULL ) {
382 return ( PAPI_ENOMEM );
383 }
384 alloced_newset = 1;
385 }
386
387 /* Now we're finished playing with the thread list */
388
390
391 /* Removed newset->num_events++, moved to mpx_insert_events() */
392
393 mpx_hold( );
394
395 /* Create PAPI events (if they don't already exist) and link
396 * the new event set to them, add them to the master list for
397 the thread, reset master event list for this thread */
398
399 retval = mpx_insert_events( newset, &EventCode, 1,
400 domain, granularity );
401 if ( retval != PAPI_OK ) {
402 if ( alloced_newset ) {
403 papi_free( newset );
404 newset = NULL;
405 }
406 }
407
408 mpx_release( );
409
410 /* Output the new or existing EventSet */
411
412 *mpx_events = newset;
413
414 return retval;
415}
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENOMEM
Definition: f90papi.h:16
unsigned long int(* _papi_hwi_thread_id_fn)(void)
Definition: threads.c:42
#define MPXDBG(format, args...)
Definition: papi_debug.h:68
#define MULTIPLEX_LOCK
Definition: papi_internal.h:86
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_malloc(a)
Definition: papi_memory.h:34
long long int long long
Definition: sde_internal.h:85
struct _threadlist * next
MasterEvent * head
unsigned long int tid
MasterEvent * cur_event
static int mpx_insert_events(MPX_EventSet *, int *event_list, int num_events, int domain, int granularity)
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
static Threadlist * tlist
Definition: sw_multiplex.c:140
static MPX_EventSet * mpx_malloc(Threadlist *t)
Definition: sw_multiplex.c:292
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
int retval
Definition: zero_fork.c:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_add_events()

int MPX_add_events ( MPX_EventSet **  mpx_events,
int event_list,
int  num_events,
int  domain,
int  granularity 
)

Definition at line 676 of file sw_multiplex.c.

678{
679 int i, retval = PAPI_OK;
680
681 for ( i = 0; i < num_events; i++ ) {
682 retval =
683 mpx_add_event( mpx_events, event_list[i], domain, granularity );
684
685 if ( retval != PAPI_OK )
686 return ( retval );
687 }
688 return ( retval );
689}
int i
static int num_events
int mpx_add_event(MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
Definition: sw_multiplex.c:305
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mpx_check()

int mpx_check ( int  EventSet)

Definition at line 1121 of file sw_multiplex.c.

1122{
1123 /* Currently, there is only the need for one mpx check: if
1124 * running on POWER6/perfctr platform, the domain must
1125 * include user, kernel, and supervisor, since the scale
1126 * event uses the dedicated counter #6, PM_RUN_CYC, which
1127 * cannot be controlled on a domain level.
1128 */
1130
1131 if (ESI==NULL) return PAPI_EBUG;
1132
1133 if ( strstr( _papi_hwd[ESI->CmpIdx]->cmp_info.name, "perfctr.c" ) == NULL )
1134 return PAPI_OK;
1135
1136 if ( strcmp( _papi_hwi_system_info.hw_info.model_string, "POWER6" ) == 0 ) {
1137 unsigned int chk_domain =
1139
1140 if ( ( ESI->domain.domain & chk_domain ) != chk_domain ) {
1141 PAPIERROR
1142 ( "This platform requires PAPI_DOM_USER+PAPI_DOM_KERNEL+PAPI_DOM_SUPERVISOR\n"
1143 "to be set in the domain when using multiplexing. Instead, found %#x\n",
1144 ESI->domain.domain );
1145 return ( PAPI_EINVAL_DOM );
1146 }
1147 }
1148 return PAPI_OK;
1149}
struct papi_vectors * _papi_hwd[]
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_EBUG
Definition: f90papi.h:176
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_DOM_SUPERVISOR
Definition: f90papi.h:109
#define PAPI_EINVAL_DOM
Definition: f90papi.h:175
static int EventSet
Definition: init_fini.c:8
void PAPIERROR(char *format,...)
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
EventSetDomainInfo_t domain
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:784
PAPI_hw_info_t hw_info
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_cleanup()

int MPX_cleanup ( MPX_EventSet **  mpx_events)

Definition at line 1069 of file sw_multiplex.c.

1070{
1071#ifdef PTHREADS
1072 int retval;
1073#endif
1074
1075 if ( mpx_events == NULL )
1076 return PAPI_EINVAL;
1077
1078 if ( *mpx_events == NULL )
1079 return PAPI_OK;
1080
1081 if (( *mpx_events )->status == MPX_RUNNING )
1082 return PAPI_EINVAL;
1083
1084 mpx_hold( );
1085
1086 /* Remove master events from this event set and from
1087 * the master list, if necessary.
1088 */
1089 mpx_delete_events( *mpx_events );
1090
1091 mpx_release( );
1092
1093 /* Free all the memory */
1094
1095 papi_free( *mpx_events );
1096
1097 *mpx_events = NULL;
1098 return PAPI_OK;
1099}
#define PAPI_EINVAL
Definition: f90papi.h:115
static void mpx_delete_events(MPX_EventSet *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mpx_init()

int mpx_init ( int  interval_ns)

Definition at line 1152 of file sw_multiplex.c.

1153{
1154#if defined(PTHREADS) || defined(_POWER6)
1155 int retval;
1156#endif
1157
1158#ifdef _POWER6
1159 retval = PAPI_event_name_to_code( "PM_RUN_CYC", &_PNE_PM_RUN_CYC );
1160 if ( retval != PAPI_OK )
1161 return ( retval );
1162#endif
1163 tlist = NULL;
1164 mpx_hold( );
1166 mpx_init_timers( interval_ns / 1000 );
1167
1168 return ( PAPI_OK );
1169}
Convert a name to a numeric hardware event code.
static void mpx_shutdown_itimer(void)
Definition: sw_multiplex.c:257
static void mpx_init_timers(int interval)
Definition: sw_multiplex.c:194
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_read()

int MPX_read ( MPX_EventSet mpx_events,
long long values,
int  called_by_stop 
)

Definition at line 823 of file sw_multiplex.c.

824{
825 int i;
826 int retval;
827 long long last_value[2];
828 long long cycles_this_slice = 0;
829 MasterEvent *cur_event;
830 Threadlist *thread_data;
831
832 if ( mpx_events->status == MPX_RUNNING ) {
833
834 /* Hold timer interrupts while we read values */
835 mpx_hold( );
836
837 thread_data = mpx_events->mythr;
838 cur_event = thread_data->cur_event;
839
840 retval = PAPI_read( cur_event->papi_event, last_value );
841 if ( retval != PAPI_OK )
842 return retval;
843
844 cycles_this_slice = ( cur_event->pi.event_type == SCALE_EVENT )
845 ? last_value[0] : last_value[1];
846
847 /* Save the current counter values and get
848 * the lastest data for the current event
849 */
850 for ( i = 0; i < mpx_events->num_events; i++ ) {
851 MasterEvent *mev = mpx_events->mev[i];
852
853 if ( !( mev->is_a_rate ) ) {
854 mpx_events->stop_values[i] = mev->count_estimate;
855 }
856 else {
857 mpx_events->stop_values[i] = mev->count;
858 }
859#ifdef MPX_NONDECR_HYBRID
860 /* If we are called from MPX_stop() then */
861 /* adjust the final values based on the */
862 /* cycles elapsed since the last read */
863 /* otherwise, don't do this as it can cause */
864 /* decreasing values if read is called again */
865 /* before another sample happens. */
866
867 if (called_by_stop) {
868
869 /* Extrapolate data up to the current time
870 * only if it's not a rate measurement
871 */
872 if ( !( mev->is_a_rate ) ) {
873 if ( mev != thread_data->cur_event ) {
874 mpx_events->stop_values[i] +=
875 ( long long ) ( mev->rate_estimate *
876 ( cycles_this_slice +
877 thread_data->total_c -
878 mev->prev_total_c ) );
879 MPXDBG
880 ( "%s:%d:: Inactive %d, stop values=%lld (est. %lld, rate %g, cycles %lld)\n",
881 __FILE__, __LINE__, i, mpx_events->stop_values[i],
882 mev->count_estimate, mev->rate_estimate,
883 cycles_this_slice + thread_data->total_c -
884 mev->prev_total_c );
885 } else {
886 mpx_events->stop_values[i] += last_value[0] +
887 ( long long ) ( mev->rate_estimate *
888 ( thread_data->total_c -
889 mev->prev_total_c ) );
890 MPXDBG
891 ( "%s:%d:: -Active- %d, stop values=%lld (est. %lld, rate %g, cycles %lld)\n",
892 __FILE__, __LINE__, i, mpx_events->stop_values[i],
893 mev->count_estimate, mev->rate_estimate,
894 thread_data->total_c - mev->prev_total_c );
895 }
896 }
897 }
898#endif
899 }
900
901 mpx_events->stop_c = thread_data->total_c + cycles_this_slice;
902
903 /* Restore the interrupt */
904 mpx_release( );
905 }
906
907 /* Store the values in user array. */
908 for ( i = 0; i < mpx_events->num_events; i++ ) {
909 MasterEvent *mev = mpx_events->mev[i];
910 long long elapsed_slices = 0;
911 long long elapsed_values = mpx_events->stop_values[i]
912 - mpx_events->start_values[i];
913
914 /* For rates, cycles contains the number of measurements,
915 * not the number of cycles, so just divide to compute
916 * an average value. This assumes that the rate was
917 * constant over the whole measurement period.
918 */
919 values[i] = elapsed_values;
920 if ( mev->is_a_rate ) {
921 /* Handler counts */
922 elapsed_slices = mev->cycles - mpx_events->start_hc[i];
923 values[i] =
924 elapsed_slices ? ( elapsed_values / elapsed_slices ) : 0;
925 }
926 MPXDBG( "%s:%d:: event %d, values=%lld ( %lld - %lld), cycles %lld\n",
927 __FILE__, __LINE__, i,
928 elapsed_values,
929 mpx_events->stop_values[i], mpx_events->start_values[i],
930 mev->is_a_rate ? elapsed_slices : 0 );
931 }
932
933 return PAPI_OK;
934}
Read hardware counters from an event set.
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
MPX_status status
Definition: sw_multiplex.h:17
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
long long stop_c
Definition: sw_multiplex.h:25
long long stop_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:27
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:26
long long start_hc[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:28
struct _threadlist * mythr
Definition: sw_multiplex.h:19
long long prev_total_c
double rate_estimate
long long count
long long count_estimate
long long cycles
PapiInfo pi
long long event_type
long long total_c
#define SCALE_EVENT
Definition: sw_multiplex.c:440
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mpx_remove_event()

int mpx_remove_event ( MPX_EventSet **  mpx_events,
int  EventCode 
)

Definition at line 418 of file sw_multiplex.c.

419{
420 mpx_hold( );
421 if ( *mpx_events )
422 mpx_delete_one_event( *mpx_events, EventCode );
423 mpx_release( );
424 return ( PAPI_OK );
425}
static void mpx_delete_one_event(MPX_EventSet *mpx_events, int Event)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_reset()

int MPX_reset ( MPX_EventSet mpx_events)

Definition at line 937 of file sw_multiplex.c.

938{
939 int i, retval;
941
942 /* Get the current values from MPX_read */
943 retval = MPX_read( mpx_events, values, 0 );
944 if ( retval != PAPI_OK )
945 return retval;
946
947 /* Disable timer interrupt */
948 mpx_hold( );
949
950 /* Make counters read zero by setting the start values
951 * to the current counter values.
952 */
953 for ( i = 0; i < mpx_events->num_events; i++ ) {
954 MasterEvent *mev = mpx_events->mev[i];
955
956 if ( mev->is_a_rate ) {
957 mpx_events->start_values[i] = mev->count;
958 } else {
959 mpx_events->start_values[i] += values[i];
960 }
961 mpx_events->start_hc[i] = mev->cycles;
962 }
963
964 /* Set the start time for this set to the current cycle count */
965 mpx_events->start_c = mpx_events->stop_c;
966
967 /* Restart the interrupt */
968 mpx_release( );
969
970 return PAPI_OK;
971}
long long start_c
Definition: sw_multiplex.h:25
int MPX_read(MPX_EventSet *mpx_events, long long *values, int called_by_stop)
Definition: sw_multiplex.c:823
#define PAPI_MAX_SW_MPX_EVENTS
Definition: sw_multiplex.h:4
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_shutdown()

void MPX_shutdown ( void  )

Definition at line 1102 of file sw_multiplex.c.

1103{
1104 MPXDBG( "%d\n", getpid( ) );
1107
1108 if ( tlist ) {
1109 Threadlist *next,*t=tlist;
1110
1111 while(t!=NULL) {
1112 next=t->next;
1113 papi_free( t );
1114 t = next;
1115 }
1116 tlist = NULL;
1117 }
1118}
static void mpx_restore_signal(void)
Definition: sw_multiplex.c:247
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_start()

int MPX_start ( MPX_EventSet mpx_events)

Definition at line 692 of file sw_multiplex.c.

693{
694 int retval = PAPI_OK;
695 int i;
696 long long values[2];
697 long long cycles_this_slice, current_thread_mpx_c = 0;
698 Threadlist *t;
699
700 t = mpx_events->mythr;
701
702 mpx_hold( );
703
704 if ( t->cur_event && t->cur_event->active ) {
705 current_thread_mpx_c += t->total_c;
707 assert( retval == PAPI_OK );
708 if ( retval == PAPI_OK ) {
709 cycles_this_slice = ( t->cur_event->pi.event_type == SCALE_EVENT )
710 ? values[0] : values[1];
711 } else {
712 values[0] = values[1] = 0;
713 cycles_this_slice = 0;
714 }
715
716 } else {
717 values[0] = values[1] = 0;
718 cycles_this_slice = 0;
719 }
720
721 /* Make all events in this set active, and for those
722 * already active, get the current count and cycles.
723 */
724 for ( i = 0; i < mpx_events->num_events; i++ ) {
725 MasterEvent *mev = mpx_events->mev[i];
726
727 if ( mev->active++ ) {
728 mpx_events->start_values[i] = mev->count_estimate;
729 mpx_events->start_hc[i] = mev->cycles;
730
731 /* If this happens to be the currently-running
732 * event, add in the current amounts from this
733 * time slice. If it's a rate, though, don't
734 * bother since the event might not have been
735 * running long enough to get an accurate count.
736 */
737 if ( t->cur_event && !( t->cur_event->is_a_rate ) ) {
738#ifdef MPX_NONDECR_HYBRID
739 if ( mev != t->cur_event ) { /* This event is not running this slice */
740 mpx_events->start_values[i] +=
741 ( long long ) ( mev->rate_estimate *
742 ( cycles_this_slice + t->total_c -
743 mev->prev_total_c ) );
744 } else { /* The event is running, use current value + estimate */
745 if ( cycles_this_slice >= MPX_MINCYC )
746 mpx_events->start_values[i] += values[0] + ( long long )
747 ( ( values[0] / ( double ) cycles_this_slice ) *
748 ( t->total_c - mev->prev_total_c ) );
749 else /* Use previous rate if the event has run too short time */
750 mpx_events->start_values[i] += values[0] + ( long long )
751 ( mev->rate_estimate *
752 ( t->total_c - mev->prev_total_c ) );
753 }
754#endif
755 } else {
756 mpx_events->start_values[i] = mev->count;
757 }
758 } else {
759 /* The = 0 isn't actually necessary; we only need
760 * to sync up the mpx event to the master event,
761 * but it seems safe to set the mev to 0 here, and
762 * that gives us a change to avoid (very unlikely)
763 * rollover problems for events used repeatedly over
764 * a long time.
765 */
766 mpx_events->start_values[i] = 0;
767 mpx_events->stop_values[i] = 0;
768 mpx_events->start_hc[i] = mev->cycles = 0;
769 mev->count_estimate = 0;
770 mev->rate_estimate = 0.0;
771 mev->prev_total_c = current_thread_mpx_c;
772 mev->count = 0;
773 }
774 /* Adjust start value to include events and cycles
775 * counted previously for this event set.
776 */
777 }
778
779 mpx_events->status = MPX_RUNNING;
780
781 /* Start first counter if one isn't already running */
782 if ( t->cur_event == NULL ) {
783 /* Pick an events at random to start. */
784 int index = ( rand_r( &randomseed ) % mpx_events->num_events );
785 t->cur_event = mpx_events->mev[index];
786 t->total_c = 0;
787 t->cur_event->prev_total_c = 0;
788 mpx_events->start_c = 0;
789 retval = PAPI_start( mpx_events->mev[index]->papi_event );
790 assert( retval == PAPI_OK );
791 } else {
792 /* If an event is already running, record the starting cycle
793 * count for mpx_events, which is the accumlated cycle count
794 * for the master event set plus the cycles for this time
795 * slice.
796 */
797 mpx_events->start_c = t->total_c + cycles_this_slice;
798 }
799
800#if defined(DEBUG)
801 if ( ISLEVEL( DEBUG_MULTIPLEX ) ) {
802 MPXDBG( "%s:%d:: start_c=%lld thread->total_c=%lld\n", __FILE__,
803 __LINE__, mpx_events->start_c, t->total_c );
804 for ( i = 0; i < mpx_events->num_events; i++ ) {
805 MPXDBG
806 ( "%s:%d:: start_values[%d]=%lld estimate=%lld rate=%g last active=%lld\n",
807 __FILE__, __LINE__, i, mpx_events->start_values[i],
808 mpx_events->mev[i]->count_estimate,
809 mpx_events->mev[i]->rate_estimate,
810 mpx_events->mev[i]->prev_total_c );
811 }
812 }
813#endif
814
815 mpx_release( );
816
818
819 return retval;
820}
Start counting hardware events in an event set.
#define ISLEVEL(a)
Definition: papi_debug.h:55
#define DEBUG_MULTIPLEX
Definition: papi_debug.h:31
static int mpx_startup_itimer(void)
Definition: sw_multiplex.c:222
static unsigned int randomseed
Definition: sw_multiplex.c:141
#define MPX_MINCYC
Definition: sw_multiplex.c:134
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPX_stop()

int MPX_stop ( MPX_EventSet mpx_events,
long long values 
)

Definition at line 974 of file sw_multiplex.c.

975{
976 int i, cur_mpx_event;
977 int retval = PAPI_OK;
978 long long dummy_value[2];
979 long long dummy_mpx_values[PAPI_MAX_SW_MPX_EVENTS];
980 /* long long cycles_this_slice, total_cycles; */
981 MasterEvent *cur_event = NULL, *head;
982 Threadlist *thr = NULL;
983
984 if ( mpx_events == NULL )
985 return PAPI_EINVAL;
986 if ( mpx_events->status != MPX_RUNNING )
987 return PAPI_ENOTRUN;
988
989 /* Read the counter values, this updates mpx_events->stop_values[] */
990 MPXDBG( "Start\n" );
991 if ( values == NULL )
992 retval = MPX_read( mpx_events, dummy_mpx_values, 1 );
993 else
994 retval = MPX_read( mpx_events, values, 1 );
995
996 /* Block timer interrupts while modifying active events */
997 mpx_hold( );
998
999 /* Get the master event list for this thread. */
1001 if (!head) {
1003 goto exit_mpx_stop;
1004 }
1005
1006 /* Get this threads data structure */
1007 thr = head->mythr;
1008 cur_event = thr->cur_event;
1009
1010 /* This would be a good spot to "hold" the counter and then restart
1011 * it at the end, but PAPI_start resets counters so it is not possible
1012 */
1013
1014 /* Run through all the events decrement their activity counters. */
1015 cur_mpx_event = -1;
1016 for ( i = 0; i < mpx_events->num_events; i++ ) {
1017 --mpx_events->mev[i]->active;
1018 if ( mpx_events->mev[i] == cur_event )
1019 cur_mpx_event = i;
1020 }
1021
1022 /* One event in this set is currently running, if this was the
1023 * last active event set using this event, we need to start the next
1024 * event if there still is one left in the queue
1025 */
1026 if ( cur_mpx_event > -1 ) {
1027 MasterEvent *tmp, *mev = mpx_events->mev[cur_mpx_event];
1028
1029 if ( mev->active == 0 ) {
1030 /* Event is now inactive; stop it
1031 * There is no need to update master event set
1032 * counters as this is the last active user
1033 */
1034 retval = PAPI_stop( mev->papi_event, dummy_value );
1035 mev->rate_estimate = 0.0;
1036
1037 /* Fall-back value if none is found */
1038 thr->cur_event = NULL;
1039 /* Now find a new cur_event */
1040 for ( tmp = ( cur_event->next == NULL ) ? head : cur_event->next;
1041 tmp != cur_event;
1042 tmp = ( tmp->next == NULL ) ? head : tmp->next ) {
1043 if ( tmp->active ) { /* Found the next one to start */
1044 thr->cur_event = tmp;
1045 break;
1046 }
1047 }
1048
1049 if ( thr->cur_event != NULL ) {
1051 assert( retval == PAPI_OK );
1052 } else {
1054 }
1055 }
1056 }
1057 mpx_events->status = MPX_STOPPED;
1058
1059exit_mpx_stop:
1060 MPXDBG( "End\n" );
1061
1062 /* Restore the timer (for other event sets that may be running) */
1063 mpx_release( );
1064
1065 return retval;
1066}
double tmp
Stop counting hardware events in an event set.
#define PAPI_ENOTRUN
Definition: f90papi.h:146
struct _masterevent * next
static MasterEvent * get_my_threads_master_event_list(void)
Definition: sw_multiplex.c:268
Here is the call graph for this function:
Here is the caller graph for this function: