PAPI  5.3.2.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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

#define PAPI_MAX_SW_MPX_EVENTS   32

Definition at line 4 of file sw_multiplex.h.

Enumeration Type Documentation

enum MPX_status
Enumerator
MPX_STOPPED 
MPX_RUNNING 

Definition at line 9 of file sw_multiplex.h.

Function Documentation

int mpx_add_event ( MPX_EventSet **  ,
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 
333  if ( _papi_hwi_thread_id_fn ) {
334  MPXDBG( "New thread at %p\n", t );
335  t->tid = _papi_hwi_thread_id_fn( );
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_ENOMEM
Definition: fpapi.h:107
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_malloc(a)
Definition: papi_memory.h:34
static Threadlist * tlist
Definition: sw_multiplex.c:140
return PAPI_OK
Definition: linux-nvml.c:458
t
Definition: iozone.c:23562
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:64
#define MULTIPLEX_LOCK
Definition: papi_internal.h:86
MasterEvent * cur_event
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:78
MasterEvent * head
void *long long tid
Definition: iozone.c:18586
static int mpx_insert_events(MPX_EventSet *, int *event_list, int num_events, int domain, int granularity)
long long
Definition: iozone.c:19827
unsigned long int(* _papi_hwi_thread_id_fn)(void)
Definition: threads.c:42
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
static MPX_EventSet * mpx_malloc(Threadlist *t)
Definition: sw_multiplex.c:292
struct _threadlist * next
unsigned long int tid
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
ssize_t retval
Definition: libasync.c:338

Here is the call graph for this function:

Here is the caller graph for this function:

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 num_events
return PAPI_OK
Definition: linux-nvml.c:458
int i
Definition: fileop.c:140
int mpx_add_event(MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
Definition: sw_multiplex.c:305
ssize_t retval
Definition: libasync.c:338

Here is the call graph for this function:

Here is the caller graph for this function:

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  if ( ESI == NULL )
1140  return ( PAPI_ENOEVST );
1141 
1142  if ( ( ESI->domain.domain & chk_domain ) != chk_domain ) {
1143  PAPIERROR
1144  ( "This platform requires PAPI_DOM_USER+PAPI_DOM_KERNEL+PAPI_DOM_SUPERVISOR\n"
1145  "to be set in the domain when using multiplexing. Instead, found %#x\n",
1146  ESI->domain.domain );
1147  return ( PAPI_EINVAL_DOM );
1148  }
1149  }
1150  return PAPI_OK;
1151 }
#define PAPI_EINVAL_DOM
Definition: fpapi.h:126
EventSetDomainInfo_t domain
return PAPI_OK
Definition: linux-nvml.c:458
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
#define PAPI_ENOEVST
Definition: fpapi.h:116
#define PAPI_DOM_SUPERVISOR
Definition: fpapi.h:24
void PAPIERROR(char *format,...)
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:57
PAPI_hw_info_t hw_info
int EventSet
#define PAPI_EBUG
Definition: fpapi.h:111
struct papi_vectors * _papi_hwd[]
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:785
#define PAPI_DOM_USER
Definition: fpapi.h:21

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
#define papi_free(a)
Definition: papi_memory.h:35
return PAPI_OK
Definition: linux-nvml.c:458
return PAPI_EINVAL
Definition: linux-nvml.c:408
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
ssize_t retval
Definition: libasync.c:338
static void mpx_delete_events(MPX_EventSet *)

Here is the call graph for this function:

Here is the caller graph for this function:

int mpx_init ( int  )

Definition at line 1154 of file sw_multiplex.c.

1155 {
1156 #if defined(PTHREADS) || defined(_POWER6)
1157  int retval;
1158 #endif
1159 
1160 #ifdef _POWER6
1161  retval = PAPI_event_name_to_code( "PM_RUN_CYC", &_PNE_PM_RUN_CYC );
1162  if ( retval != PAPI_OK )
1163  return ( retval );
1164 #endif
1165  tlist = NULL;
1166  mpx_hold( );
1168  mpx_init_timers( interval_ns / 1000 );
1169 
1170  return ( PAPI_OK );
1171 }
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
static void mpx_shutdown_itimer(void)
Definition: sw_multiplex.c:257
static Threadlist * tlist
Definition: sw_multiplex.c:140
return PAPI_OK
Definition: linux-nvml.c:458
int PAPI_event_name_to_code(char *in, int *out)
Definition: papi.c:1008
static void mpx_init_timers(int interval)
Definition: sw_multiplex.c:194
ssize_t retval
Definition: libasync.c:338

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
long long total_c
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
double rate_estimate
long long stop_c
Definition: sw_multiplex.h:25
long long stop_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:27
return PAPI_OK
Definition: linux-nvml.c:458
long long start_hc[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:28
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
MPX_status status
Definition: sw_multiplex.h:17
int i
Definition: fileop.c:140
MasterEvent * cur_event
long long
Definition: iozone.c:19827
long long cycles
PapiInfo pi
#define SCALE_EVENT
Definition: sw_multiplex.c:440
struct _threadlist * mythr
Definition: sw_multiplex.h:19
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
long long event_type
int PAPI_read(int EventSet, long long *values)
Definition: papi.c:2476
long long count
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:26
long long prev_total_c
long long count_estimate

Here is the call graph for this function:

Here is the caller graph for this function:

int mpx_remove_event ( MPX_EventSet **  ,
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 }
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
return PAPI_OK
Definition: linux-nvml.c:458
static void mpx_delete_one_event(MPX_EventSet *mpx_events, int Event)
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187

Here is the call graph for this function:

Here is the caller graph for this function:

int MPX_reset ( MPX_EventSet mpx_events)

Definition at line 937 of file sw_multiplex.c.

938 {
939  int i, retval;
940  long long values[PAPI_MAX_SW_MPX_EVENTS];
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 }
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
long long stop_c
Definition: sw_multiplex.h:25
return PAPI_OK
Definition: linux-nvml.c:458
#define PAPI_MAX_SW_MPX_EVENTS
Definition: sw_multiplex.h:4
long long start_hc[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:28
int MPX_read(MPX_EventSet *mpx_events, long long *values, int called_by_stop)
Definition: sw_multiplex.c:823
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
int i
Definition: fileop.c:140
long long cycles
long long count
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:26
long long start_c
Definition: sw_multiplex.h:25

Here is the call graph for this function:

Here is the caller graph for this function:

void MPX_shutdown ( void  )

Definition at line 1102 of file sw_multiplex.c.

1103 {
1104  MPXDBG( "%d\n", getpid( ) );
1106  mpx_restore_signal( );
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 }
#define papi_free(a)
Definition: papi_memory.h:35
static void mpx_shutdown_itimer(void)
Definition: sw_multiplex.c:257
static Threadlist * tlist
Definition: sw_multiplex.c:140
t
Definition: iozone.c:23562
static void mpx_restore_signal(void)
Definition: sw_multiplex.c:247
nsize_list next
Definition: iozone.c:20053
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
struct _threadlist * next

Here is the call graph for this function:

Here is the caller graph for this function:

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;
706  retval = PAPI_read( t->cur_event->papi_event, values );
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 
817  retval = mpx_startup_itimer( );
818 
819  return retval;
820 }
#define DEBUG_MULTIPLEX
Definition: papi_debug.h:31
long long total_c
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
double rate_estimate
long long stop_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:27
return PAPI_OK
Definition: linux-nvml.c:458
long long start_hc[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:28
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
t
Definition: iozone.c:23562
MPX_status status
Definition: sw_multiplex.h:17
static unsigned int randomseed
Definition: sw_multiplex.c:141
int i
Definition: fileop.c:140
MasterEvent * cur_event
long long
Definition: iozone.c:19827
long long cycles
static int mpx_startup_itimer(void)
Definition: sw_multiplex.c:222
#define MPX_MINCYC
Definition: sw_multiplex.c:134
PapiInfo pi
#define SCALE_EVENT
Definition: sw_multiplex.c:440
struct _threadlist * mythr
Definition: sw_multiplex.h:19
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
long long event_type
#define ISLEVEL(a)
Definition: papi_debug.h:54
int PAPI_read(int EventSet, long long *values)
Definition: papi.c:2476
long long count
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
int PAPI_start(int EventSet)
Definition: papi.c:2026
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:26
long long prev_total_c
long long count_estimate
long long start_c
Definition: sw_multiplex.h:25
else
Definition: iozone.c:12373

Here is the call graph for this function:

Here is the caller graph for this function:

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) {
1002  retval=PAPI_EBUG;
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 ) {
1050  retval = PAPI_start( thr->cur_event->papi_event );
1051  assert( retval == PAPI_OK );
1052  } else {
1054  }
1055  }
1056  }
1057  mpx_events->status = MPX_STOPPED;
1058 
1059 exit_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 }
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2232
inline_static void mpx_hold(void)
Definition: sw_multiplex.c:180
gc head
Definition: libasync.c:669
static void mpx_shutdown_itimer(void)
Definition: sw_multiplex.c:257
double rate_estimate
return PAPI_OK
Definition: linux-nvml.c:458
return PAPI_EINVAL
Definition: linux-nvml.c:408
#define PAPI_MAX_SW_MPX_EVENTS
Definition: sw_multiplex.h:4
int MPX_read(MPX_EventSet *mpx_events, long long *values, int called_by_stop)
Definition: sw_multiplex.c:823
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
MPX_status status
Definition: sw_multiplex.h:17
int i
Definition: fileop.c:140
MasterEvent * cur_event
struct _masterevent * next
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
#define PAPI_EBUG
Definition: fpapi.h:111
static MasterEvent * get_my_threads_master_event_list(void)
Definition: sw_multiplex.c:268
#define PAPI_ENOTRUN
Definition: fpapi.h:114
inline_static void mpx_release(void)
Definition: sw_multiplex.c:187
int PAPI_start(int EventSet)
Definition: papi.c:2026
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long tmp
Definition: iozone.c:12031

Here is the call graph for this function:

Here is the caller graph for this function: