PAPI  5.3.2.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sw_multiplex.c File Reference
Include dependency graph for sw_multiplex.c:

Go to the source code of this file.

Macros

#define MPX_NONDECR_HYBRID
 
#define MPX_MINCYC   25000
 
#define SCALE_EVENT   PAPI_TOT_CYC
 

Functions

static void mpx_remove_unused (MasterEvent **head)
 
static void mpx_delete_events (MPX_EventSet *)
 
static void mpx_delete_one_event (MPX_EventSet *mpx_events, int Event)
 
static int mpx_insert_events (MPX_EventSet *, int *event_list, int num_events, int domain, int granularity)
 
static void mpx_handler (int signal)
 
inline_static void mpx_hold (void)
 
inline_static void mpx_release (void)
 
static void mpx_init_timers (int interval)
 
static int mpx_startup_itimer (void)
 
static void mpx_restore_signal (void)
 
static void mpx_shutdown_itimer (void)
 
static MasterEventget_my_threads_master_event_list (void)
 
static MPX_EventSetmpx_malloc (Threadlist *t)
 
int mpx_add_event (MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
 
int mpx_remove_event (MPX_EventSet **mpx_events, int EventCode)
 
int MPX_add_events (MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
 
int MPX_start (MPX_EventSet *mpx_events)
 
int MPX_read (MPX_EventSet *mpx_events, long long *values, int called_by_stop)
 
int MPX_reset (MPX_EventSet *mpx_events)
 
int MPX_stop (MPX_EventSet *mpx_events, long long *values)
 
int MPX_cleanup (MPX_EventSet **mpx_events)
 
void MPX_shutdown (void)
 
int mpx_check (int EventSet)
 
int mpx_init (int interval_ns)
 

Variables

static Threadlisttlist = NULL
 
static unsigned int randomseed
 
static sigset_t sigreset
 
static struct itimerval itime
 
static struct itimerval itimestop = { {0, 0}, {0, 0} }
 
static struct sigaction oaction
 

Detailed Description

Macro Definition Documentation

#define MPX_MINCYC   25000

Definition at line 134 of file sw_multiplex.c.

#define MPX_NONDECR_HYBRID

xxxx Will this stuff run unmodified on multiple components? What happens when several components are counting multiplexed?

Definition at line 24 of file sw_multiplex.c.

#define SCALE_EVENT   PAPI_TOT_CYC

Definition at line 440 of file sw_multiplex.c.

Function Documentation

static MasterEvent* get_my_threads_master_event_list ( void  )
static

Definition at line 268 of file sw_multiplex.c.

269 {
270  Threadlist *t = tlist;
271  unsigned long tid;
272 
273  MPXDBG( "tlist is %p\n", tlist );
274  if ( tlist == NULL )
275  return NULL;
276 
277  if ( _papi_hwi_thread_id_fn == NULL )
278  return ( tlist->head );
279 
280  tid = _papi_hwi_thread_id_fn( );
281  unsigned long pid = ( unsigned long ) getpid( );
282 
283  while ( t ) {
284  if ( t->tid == tid || ( ( tid == 0 ) && ( t->tid == pid ) ) )
285  return ( t->head );
286  t = t->next;
287  }
288  return ( NULL );
289 }
static Threadlist * tlist
Definition: sw_multiplex.c:140
t
Definition: iozone.c:23562
static int pid
MasterEvent * head
void *long long tid
Definition: iozone.c:18586
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
struct _threadlist * next
unsigned long int tid

Here is the caller graph for this function:

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 
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:

static void mpx_delete_events ( MPX_EventSet mpx_events)
static

Remove events from an mpx event set (and from the master event set for this thread, if the events are unused). MUST BE CALLED WITH THE SIGNAL HANDLER DISABLED

Definition at line 1338 of file sw_multiplex.c.

1339 {
1340  int i;
1341  MasterEvent *mev;
1342 
1343  /* First decrement the reference counter for each master
1344  * event in this event set, then see if the master events
1345  * can be deleted.
1346  */
1347  for ( i = 0; i < mpx_events->num_events; i++ ) {
1348  mev = mpx_events->mev[i];
1349  --mev->uses;
1350  mpx_events->mev[i] = NULL;
1351  /* If it's no longer used, it should not be active! */
1352  assert( mev->uses || !( mev->active ) );
1353  }
1354  mpx_events->num_events = 0;
1355  mpx_remove_unused( &mpx_events->mythr->head );
1356 }
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
int i
Definition: fileop.c:140
static void mpx_remove_unused(MasterEvent **head)
struct _threadlist * mythr
Definition: sw_multiplex.h:19

Here is the call graph for this function:

Here is the caller graph for this function:

static void mpx_delete_one_event ( MPX_EventSet mpx_events,
int  Event 
)
static

Remove one event from an mpx event set (and from the master event set for this thread, if the events are unused). MUST BE CALLED WITH THE SIGNAL HANDLER DISABLED

Definition at line 1363 of file sw_multiplex.c.

1364 {
1365  int i;
1366  MasterEvent *mev;
1367 
1368  /* First decrement the reference counter for each master
1369  * event in this event set, then see if the master events
1370  * can be deleted.
1371  */
1372  for ( i = 0; i < mpx_events->num_events; i++ ) {
1373  mev = mpx_events->mev[i];
1374  if ( mev->pi.event_type == Event ) {
1375  --mev->uses;
1376  mpx_events->num_events--;
1377  mpx_events->mev[i] = NULL;
1378  /* If it's no longer used, it should not be active! */
1379  assert( mev->uses || !( mev->active ) );
1380  break;
1381  }
1382  }
1383 
1384  /* If we removed an event that is not last in the list we
1385  * need to compact the event list
1386  */
1387 
1388  for ( ; i < mpx_events->num_events; i++ ) {
1389  mpx_events->mev[i] = mpx_events->mev[i + 1];
1390  mpx_events->start_values[i] = mpx_events->start_values[i + 1];
1391  mpx_events->stop_values[i] = mpx_events->stop_values[i + 1];
1392  mpx_events->start_hc[i] = mpx_events->start_hc[i + 1];
1393  }
1394  mpx_events->mev[i] = NULL;
1395 
1396  mpx_remove_unused( &mpx_events->mythr->head );
1397 
1398 }
long long stop_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:27
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
int i
Definition: fileop.c:140
static void mpx_remove_unused(MasterEvent **head)
PapiInfo pi
struct _threadlist * mythr
Definition: sw_multiplex.h:19
long long event_type
int Event[MAX_EVENTS]
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:26

Here is the call graph for this function:

Here is the caller graph for this function:

static void mpx_handler ( int  signal)
static

Definition at line 445 of file sw_multiplex.c.

446 {
447  int retval;
448  MasterEvent *mev, *head;
449  Threadlist *me = NULL;
450 #ifdef REGENERATE
451  int lastthread;
452 #endif
453 #ifdef MPX_DEBUG_OVERHEAD
454  long long usec;
455  int didwork = 0;
456  usec = PAPI_get_real_usec( );
457 #endif
458 #ifdef MPX_DEBUG_TIMER
459  long long thiscall;
460 #endif
461 
462  signal = signal; /* unused */
463 
464  MPXDBG( "Handler in thread\n" );
465 
466  /* This handler can be invoked either when a timer expires
467  * or when another thread in this handler responding to the
468  * timer signals other threads. We have to distinguish
469  * these two cases so that we don't get infinite loop of
470  * handler calls. To do that, we look at the value of
471  * threads_responding. We assume that only one thread can
472  * be active in this signal handler at a time, since the
473  * invoking signal is blocked while the handler is active.
474  * If threads_responding == 0, the current thread caught
475  * the original timer signal. (This thread may not have
476  * any active event lists itself, though.) This first
477  * thread sends a signal to each of the other threads in
478  * our list of threads that have master events lists. If
479  * threads_responding != 0, then this thread was signaled
480  * by another thread. We decrement that value and look
481  * for an active events. threads_responding should
482  * reach zero when all active threads have handled their
483  * signal. It's probably possible for a thread to die
484  * before it responds to a signal; if that happens,
485  * threads_responding won't reach zero until the next
486  * timer signal happens. Then the signalled thread won't
487  * signal any other threads. If that happens only
488  * occasionally, there should be no harm. Likewise if
489  * a new thread is added that fails to get signalled.
490  * As for locking, we have to lock this list to prevent
491  * another thread from modifying it, but if *this* thread
492  * is trying to update the list (from another function) and
493  * is signaled while it holds the lock, we will have deadlock.
494  * Therefore, noninterrupt functions that update *this* list
495  * must disable the signal that invokes this handler.
496  */
497 
498 #ifdef PTHREADS
500 
501  if ( threads_responding == 0 ) { /* this thread caught the timer sig */
502  /* Signal the other threads with event lists */
503 #ifdef MPX_DEBUG_TIMER
504  thiscall = _papi_hwd_get_real_usec( );
505  MPXDBG( "last signal was %lld usec ago\n", thiscall - lastcall );
506  lastcall = thiscall;
507 #endif
508  MPXDBG( "%#x caught it, tlist is %p\n", self, tlist );
509  for ( t = tlist; t != NULL; t = t->next ) {
510  if ( pthread_equal( t->thr, self ) == 0 ) {
511  ++threads_responding;
512  retval = pthread_kill( t->thr, _papi_os_info.itimer_sig );
513  assert( retval == 0 );
514 #ifdef MPX_DEBUG_SIGNALS
515  MPXDBG( "%#x signaling %#x\n", self, t->thr );
516 #endif
517  }
518  }
519  } else {
520 #ifdef MPX_DEBUG_SIGNALS
521  MPXDBG( "%#x was tapped, tr = %d\n", self, threads_responding );
522 #endif
523  --threads_responding;
524  }
525 #ifdef REGENERATE
526  lastthread = ( threads_responding == 0 );
527 #endif
529 #endif
530 
531  /* See if this thread has an active event list */
533  if ( head != NULL ) {
534 
535  /* Get the thread header for this master event set. It's
536  * always in the first record of the set (and maybe in others)
537  * if any record in the set is active.
538  */
539  me = head->mythr;
540 
541  /* Find the event that's currently active, stop and read
542  * it, then start the next event in the list.
543  * No need to lock the list because other functions
544  * disable the timer interrupt before they update the list.
545  */
546  if ( me != NULL && me->cur_event != NULL ) {
547  long long counts[2];
548  MasterEvent *cur_event = me->cur_event;
549  long long cycles = 0, total_cycles = 0;
550 
551  retval = PAPI_stop( cur_event->papi_event, counts );
552  MPXDBG( "retval=%d, cur_event=%p, I'm tid=%lx\n",
553  retval, cur_event, me->tid );
554 
555  if ( retval == PAPI_OK ) {
556  MPXDBG( "counts[0] = %lld counts[1] = %lld\n", counts[0],
557  counts[1] );
558 
559  cur_event->count += counts[0];
560  cycles = ( cur_event->pi.event_type == SCALE_EVENT )
561  ? counts[0] : counts[1];
562 
563  me->total_c += cycles;
564  total_cycles = me->total_c - cur_event->prev_total_c;
565  cur_event->prev_total_c = me->total_c;
566 
567  /* If it's a rate, count occurrences & average later */
568  if ( !cur_event->is_a_rate ) {
569  cur_event->cycles += cycles;
570  if ( cycles >= MPX_MINCYC ) { /* Only update current rate on a decent slice */
571  cur_event->rate_estimate =
572  ( double ) counts[0] / ( double ) cycles;
573  }
574  cur_event->count_estimate +=
575  ( long long ) ( ( double ) total_cycles *
576  cur_event->rate_estimate );
577  MPXDBG("New estimate = %lld (%lld cycles * %lf rate)\n",
578  cur_event->count_estimate,total_cycles,
579  cur_event->rate_estimate);
580  } else {
581  /* Make sure we ran long enough to get a useful measurement (otherwise
582  * potentially inaccurate rate measurements get averaged in with
583  * the same weight as longer, more accurate ones.)
584  */
585  if ( cycles >= MPX_MINCYC ) {
586  cur_event->cycles += 1;
587  } else {
588  cur_event->count -= counts[0];
589  }
590  }
591  } else {
592  MPXDBG( "%lx retval = %d, skipping\n", me->tid, retval );
593  MPXDBG( "%lx value = %lld cycles = %lld\n\n",
594  me->tid, cur_event->count, cur_event->cycles );
595  }
596 
597  MPXDBG
598  ( "tid(%lx): value = %lld (%lld) cycles = %lld (%lld) rate = %lf\n\n",
599  me->tid, cur_event->count, cur_event->count_estimate,
600  cur_event->cycles, total_cycles, cur_event->rate_estimate );
601  /* Start running the next event; look for the
602  * next one in the list that's marked active.
603  * It's possible that this event is the only
604  * one active; if so, we should restart it,
605  * but only after considerating all the other
606  * possible events.
607  */
608  if ( ( retval != PAPI_OK ) ||
609  ( ( retval == PAPI_OK ) && ( cycles >= MPX_MINCYC ) ) ) {
610  for ( mev =
611  ( cur_event->next == NULL ) ? head : cur_event->next;
612  mev != cur_event;
613  mev = ( mev->next == NULL ) ? head : mev->next ) {
614  /* Found the next one to start */
615  if ( mev->active ) {
616  me->cur_event = mev;
617  break;
618  }
619  }
620  }
621 
622  if ( me->cur_event->active ) {
623  retval = PAPI_start( me->cur_event->papi_event );
624  }
625 #ifdef MPX_DEBUG_OVERHEAD
626  didwork = 1;
627 #endif
628  }
629  }
630 #ifdef ANY_THREAD_GETS_SIGNAL
631  else {
632  Threadlist *t;
633  for ( t = tlist; t != NULL; t = t->next ) {
634  if ( ( t->tid == _papi_hwi_thread_id_fn( ) ) ||
635  ( t->head == NULL ) )
636  continue;
637  MPXDBG( "forwarding signal to thread %lx\n", t->tid );
638  retval = ( *_papi_hwi_thread_kill_fn ) ( t->tid, _papi_os_info.itimer_sig );
639  if ( retval != 0 ) {
640  MPXDBG( "forwarding signal to thread %lx returned %d\n",
641  t->tid, retval );
642  }
643  }
644  }
645 #endif
646 
647 #ifdef REGENERATE
648  /* Regenerating the signal each time through has the
649  * disadvantage that if any thread ever drops a signal,
650  * the whole time slicing system will stop. Using
651  * an automatically regenerated signal may have the
652  * disadvantage that a new signal can arrive very
653  * soon after all the threads have finished handling
654  * the last one, so the interval may be too small for
655  * accurate data collection. However, using the
656  * MIN_CYCLES check above should alleviate this.
657  */
658  /* Reset the timer once all threads have responded */
659  if ( lastthread ) {
660  retval = setitimer( _papi_os_info.itimer_num, &itime, NULL );
661  assert( retval == 0 );
662 #ifdef MPX_DEBUG_TIMER
663  MPXDBG( "timer restarted by %lx\n", me->tid );
664 #endif
665  }
666 #endif
667 
668 #ifdef MPX_DEBUG_OVERHEAD
669  usec = _papi_hwd_get_real_usec( ) - usec;
670  MPXDBG( "handler %#x did %swork in %lld usec\n",
671  self, ( didwork ? "" : "no " ), usec );
672 #endif
673 }
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2232
unsigned int me
Definition: iozone.c:20357
long long total_c
gc head
Definition: libasync.c:669
double rate_estimate
static Threadlist * tlist
Definition: sw_multiplex.c:140
return PAPI_OK
Definition: linux-nvml.c:458
static double
Definition: fileop.c:1281
t
Definition: iozone.c:23562
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:64
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
#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
long long
Definition: iozone.c:19827
long long cycles
struct _masterevent * next
#define MPX_MINCYC
Definition: sw_multiplex.c:134
unsigned long int(* _papi_hwi_thread_id_fn)(void)
Definition: threads.c:42
PapiInfo pi
#define SCALE_EVENT
Definition: sw_multiplex.c:440
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
long long PAPI_get_real_usec(void)
Definition: papi.c:6138
struct _threadlist * next
long long event_type
static MasterEvent * get_my_threads_master_event_list(void)
Definition: sw_multiplex.c:268
long long count
unsigned long int tid
int PAPI_start(int EventSet)
Definition: papi.c:2026
static struct itimerval itime
Definition: sw_multiplex.c:152
ssize_t retval
Definition: libasync.c:338
struct _threadlist * mythr
long long count_estimate
long long prev_total_c
signal(SIGINT, signal_handler)

Here is the call graph for this function:

Here is the caller graph for this function:

inline_static void mpx_hold ( void  )

Definition at line 180 of file sw_multiplex.c.

181 {
182  sigprocmask( SIG_BLOCK, &sigreset, NULL );
183  MPXDBG( "signal held\n" );
184 }
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
static sigset_t sigreset
Definition: sw_multiplex.c:151

Here is the caller graph for this function:

int mpx_init ( int  interval_ns)

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:

static void mpx_init_timers ( int  interval)
static

Definition at line 194 of file sw_multiplex.c.

195 {
196  /* Fill in the interval timer values now to save a
197  * little time later.
198  */
199 #ifdef OUTSIDE_PAPI
200  interval = MPX_DEFAULT_INTERVAL;
201 #endif
202 
203 #ifdef REGENERATE
204  /* Signal handler restarts the timer every time it runs */
205  itime.it_interval.tv_sec = 0;
206  itime.it_interval.tv_usec = 0;
207  itime.it_value.tv_sec = 0;
208  itime.it_value.tv_usec = interval;
209 #else
210  /* Timer resets itself automatically */
211  itime.it_interval.tv_sec = 0;
212  itime.it_interval.tv_usec = interval;
213  itime.it_value.tv_sec = 0;
214  itime.it_value.tv_usec = interval;
215 #endif
216 
217  sigemptyset( &sigreset );
218  sigaddset( &sigreset, _papi_os_info.itimer_sig );
219 }
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
static sigset_t sigreset
Definition: sw_multiplex.c:151
static struct itimerval itime
Definition: sw_multiplex.c:152

Here is the caller graph for this function:

static int mpx_insert_events ( MPX_EventSet mpx_events,
int event_list,
int  num_events,
int  domain,
int  granularity 
)
static

Inserts a list of events into the master event list, and adds new mev pointers to the MPX_EventSet. MUST BE CALLED WITH THE TIMER INTERRUPT DISABLED

Definition at line 1178 of file sw_multiplex.c.

1180 {
1181  int i, retval = 0, num_events_success = 0;
1182  MasterEvent *mev;
1184  MasterEvent **head = &mpx_events->mythr->head;
1185 
1186  MPXDBG("Inserting %p %d\n",mpx_events,mpx_events->num_events );
1187 
1188  /* Make sure we don't overrun our buffers */
1189  if (mpx_events->num_events + num_events > PAPI_MAX_SW_MPX_EVENTS) {
1190  return PAPI_ECOUNT;
1191  }
1192 
1193  /* For each event, see if there is already a corresponding
1194  * event in the master set for this thread. If not, add it.
1195  */
1196  for ( i = 0; i < num_events; i++ ) {
1197 
1198  /* Look for a matching event in the master list */
1199  for( mev = *head; mev != NULL; mev = mev->next ) {
1200  if ( (mev->pi.event_type == event_list[i]) &&
1201  (mev->pi.domain == domain) &&
1202  (mev->pi.granularity == granularity ))
1203  break;
1204  }
1205 
1206  /* No matching event in the list; add a new one */
1207  if ( mev == NULL ) {
1208  mev = (MasterEvent *) papi_malloc( sizeof ( MasterEvent ) );
1209  if ( mev == NULL ) {
1210  return PAPI_ENOMEM;
1211  }
1212 
1213  mev->pi.event_type = event_list[i];
1214  mev->pi.domain = domain;
1215  mev->pi.granularity = granularity;
1216  mev->uses = mev->active = 0;
1217  mev->prev_total_c = mev->count = mev->cycles = 0;
1218  mev->rate_estimate = 0.0;
1219  mev->count_estimate = 0;
1220  mev->is_a_rate = 0;
1221  mev->papi_event = PAPI_NULL;
1222 
1223  retval = PAPI_create_eventset( &( mev->papi_event ) );
1224  if ( retval != PAPI_OK ) {
1225  MPXDBG( "Event %d could not be counted.\n",
1226  event_list[i] );
1227  goto bail;
1228  }
1229 
1230  retval = PAPI_add_event( mev->papi_event, event_list[i] );
1231  if ( retval != PAPI_OK ) {
1232  MPXDBG( "Event %d could not be counted.\n",
1233  event_list[i] );
1234  goto bail;
1235  }
1236 
1237  /* Always count total cycles so we can scale results.
1238  * If user just requested cycles,
1239  * don't add that event again. */
1240 
1241  if ( event_list[i] != SCALE_EVENT ) {
1242  retval = PAPI_add_event( mev->papi_event, SCALE_EVENT );
1243  if ( retval != PAPI_OK ) {
1244  MPXDBG( "Scale event could not be counted "
1245  "at the same time.\n" );
1246  goto bail;
1247  }
1248  }
1249 
1250  /* Set the options for the event set */
1251  memset( &options, 0x0, sizeof ( options ) );
1252  options.domain.eventset = mev->papi_event;
1253  options.domain.domain = domain;
1254  retval = PAPI_set_opt( PAPI_DOMAIN, &options );
1255  if ( retval != PAPI_OK ) {
1256  MPXDBG( "PAPI_set_opt(PAPI_DOMAIN, ...) = %d\n",
1257  retval );
1258  goto bail;
1259  }
1260 
1261  memset( &options, 0x0, sizeof ( options ) );
1262  options.granularity.eventset = mev->papi_event;
1263  options.granularity.granularity = granularity;
1264  retval = PAPI_set_opt( PAPI_GRANUL, &options );
1265  if ( retval != PAPI_OK ) {
1266  if ( retval != PAPI_ECMP ) {
1267  /* ignore component errors because they typically mean
1268  "not supported by the component" */
1269  MPXDBG( "PAPI_set_opt(PAPI_GRANUL, ...) = %d\n",
1270  retval );
1271  goto bail;
1272  }
1273  }
1274 
1275 
1276  /* Chain the event set into the
1277  * master list of event sets used in
1278  * multiplexing. */
1279 
1280  mev->next = *head;
1281  *head = mev;
1282 
1283  }
1284 
1285  /* If we created a new event set, or we found a matching
1286  * eventset already in the list, then add the pointer in
1287  * the master list to this threads list. Then we bump the
1288  * number of successfully added events. */
1289  MPXDBG("Inserting now %p %d\n",mpx_events,mpx_events->num_events );
1290 
1291  mpx_events->mev[mpx_events->num_events + num_events_success] = mev;
1292  mpx_events->mev[mpx_events->num_events + num_events_success]->uses++;
1293  num_events_success++;
1294 
1295  }
1296 
1297  /* Always be sure the head master event points to the thread */
1298  if ( *head != NULL ) {
1299  ( *head )->mythr = mpx_events->mythr;
1300  }
1301  MPXDBG( "%d of %d events were added.\n", num_events_success, num_events );
1302  mpx_events->num_events += num_events_success;
1303  return ( PAPI_OK );
1304 
1305  bail:
1306  /* If there is a current mev, it is currently not linked into the list
1307  * of multiplexing events, so we can just delete that
1308  */
1309  if ( mev && mev->papi_event ) {
1310  if (PAPI_cleanup_eventset( mev->papi_event )!=PAPI_OK) {
1311  PAPIERROR("Cleanup eventset\n");
1312  }
1313  if (PAPI_destroy_eventset( &( mev->papi_event )) !=PAPI_OK) {
1314  PAPIERROR("Destory eventset\n");
1315  }
1316  }
1317  if ( mev )
1318  papi_free( mev );
1319  mev = NULL;
1320 
1321  /* Decrease the usage count of events */
1322  for ( i = 0; i < num_events_success; i++ ) {
1323  mpx_events->mev[mpx_events->num_events + i]->uses--;
1324  }
1325 
1326  /* Run the garbage collector to remove unused events */
1327  if ( num_events_success )
1328  mpx_remove_unused( head );
1329 
1330  return ( retval );
1331 }
memset(eventId, 0, size)
#define PAPI_ENOMEM
Definition: fpapi.h:107
int PAPI_add_event(int EventSet, int EventCode)
Definition: papi.c:1604
#define PAPI_NULL
Definition: fpapi.h:13
#define papi_free(a)
Definition: papi_memory.h:35
gc head
Definition: libasync.c:669
#define papi_malloc(a)
Definition: papi_memory.h:34
double rate_estimate
int num_events
PAPI_granularity_option_t granularity
Definition: papi.h:848
return PAPI_OK
Definition: linux-nvml.c:458
A pointer to the following is passed to PAPI_set/get_opt()
Definition: papi.h:843
#define PAPI_MAX_SW_MPX_EVENTS
Definition: sw_multiplex.h:4
int PAPI_set_opt(int option, PAPI_option_t *ptr)
Definition: papi.c:3371
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
Definition: sw_multiplex.h:21
#define PAPI_ECOUNT
Definition: fpapi.h:128
int i
Definition: fileop.c:140
static void mpx_remove_unused(MasterEvent **head)
#define PAPI_ECMP
Definition: fpapi.h:109
long long cycles
int granularity
void PAPIERROR(char *format,...)
#define PAPI_DOMAIN
Definition: fpapi.h:50
struct _masterevent * next
#define PAPI_GRANUL
Definition: fpapi.h:52
int PAPI_cleanup_eventset(int EventSet)
Definition: papi.c:2805
int PAPI_create_eventset(int *EventSet)
Definition: papi.c:1406
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_destroy_eventset(int *EventSet)
Definition: papi.c:1944
PAPI_domain_option_t domain
Definition: papi.h:850
long long count
ssize_t retval
Definition: libasync.c:338
long long count_estimate
long long prev_total_c
static options_t options

Here is the call graph for this function:

Here is the caller graph for this function:

static MPX_EventSet* mpx_malloc ( Threadlist t)
static

Definition at line 292 of file sw_multiplex.c.

293 {
294  MPX_EventSet *newset =
295  ( MPX_EventSet * ) papi_malloc( sizeof ( MPX_EventSet ) );
296  if ( newset == NULL )
297  return ( NULL );
298  memset( newset, 0, sizeof ( MPX_EventSet ) );
299  newset->status = MPX_STOPPED;
300  newset->mythr = t;
301  return ( newset );
302 }
memset(eventId, 0, size)
#define papi_malloc(a)
Definition: papi_memory.h:34
t
Definition: iozone.c:23562
MPX_status status
Definition: sw_multiplex.h:17
struct _threadlist * mythr
Definition: sw_multiplex.h:19

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:

inline_static void mpx_release ( void  )

Definition at line 187 of file sw_multiplex.c.

188 {
189  MPXDBG( "signal released\n" );
190  sigprocmask( SIG_UNBLOCK, &sigreset, NULL );
191 }
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
static sigset_t sigreset
Definition: sw_multiplex.c:151

Here is the caller graph for this function:

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 }
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:

static void mpx_remove_unused ( MasterEvent **  head)
static

Remove events that are not used any longer from the run list of events to multiplex by the handler MUST BE CALLED WITH THE SIGNAL HANDLER DISABLED

Definition at line 1405 of file sw_multiplex.c.

1406 {
1407  MasterEvent *mev, *lastmev = NULL, *nextmev;
1408  Threadlist *thr = ( *head == NULL ) ? NULL : ( *head )->mythr;
1409  int retval;
1410 
1411  /* Clean up and remove unused master events. */
1412  for ( mev = *head; mev != NULL; mev = nextmev ) {
1413  nextmev = mev->next; /* get link before mev is freed */
1414  if ( !mev->uses ) {
1415  if ( lastmev == NULL ) { /* this was the head event */
1416  *head = nextmev;
1417  } else {
1418  lastmev->next = nextmev;
1419  }
1422  if (retval!=PAPI_OK) PAPIERROR("Error destroying event\n");
1423  papi_free( mev );
1424  } else {
1425  lastmev = mev;
1426  }
1427  }
1428 
1429  /* Always be sure the head master event points to the thread */
1430  if ( *head != NULL ) {
1431  ( *head )->mythr = thr;
1432  }
1433 }
#define papi_free(a)
Definition: papi_memory.h:35
for(i=0;i<=max_y;i++)
Definition: iozone.c:11615
return PAPI_OK
Definition: linux-nvml.c:458
void PAPIERROR(char *format,...)
struct _masterevent * next
int PAPI_cleanup_eventset(int EventSet)
Definition: papi.c:2805
int PAPI_destroy_eventset(int *EventSet)
Definition: papi.c:1944
ssize_t retval
Definition: libasync.c:338
struct _threadlist * mythr

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:

static void mpx_restore_signal ( void  )
static

Definition at line 247 of file sw_multiplex.c.

248 {
249  MPXDBG( "restore signal\n" );
251  if ( signal( _papi_os_info.itimer_sig, SIG_IGN ) == SIG_ERR )
252  PAPIERROR( "sigaction stop errno %d", errno );
253  }
254 }
int errno
#define PAPI_NULL
Definition: fpapi.h:13
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
void PAPIERROR(char *format,...)
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
signal(SIGINT, signal_handler)

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:

static void mpx_shutdown_itimer ( void  )
static

Definition at line 257 of file sw_multiplex.c.

258 {
259  MPXDBG( "setitimer off\n" );
261  if ( setitimer( _papi_os_info.itimer_num,
262  ( struct itimerval * ) &itimestop, NULL ) == -1 )
263  PAPIERROR( "setitimer stop errno %d", errno );
264  }
265 }
int errno
#define PAPI_NULL
Definition: fpapi.h:13
static struct itimerval itimestop
Definition: sw_multiplex.c:153
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
void PAPIERROR(char *format,...)
#define MPXDBG(format, args...)
Definition: papi_debug.h:67

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:

static int mpx_startup_itimer ( void  )
static

Definition at line 222 of file sw_multiplex.c.

223 {
224  struct sigaction sigact;
225 
226  /* Set up the signal handler and the timer that triggers it */
227 
228  MPXDBG( "PID %d\n", getpid( ) );
229  memset( &sigact, 0, sizeof ( sigact ) );
230  sigact.sa_flags = SA_RESTART;
231  sigact.sa_handler = mpx_handler;
232 
233  if ( sigaction( _papi_os_info.itimer_sig, &sigact, NULL ) == -1 ) {
234  PAPIERROR( "sigaction start errno %d", errno );
235  return PAPI_ESYS;
236  }
237 
238  if ( setitimer( _papi_os_info.itimer_num, &itime, NULL ) == -1 ) {
239  sigaction( _papi_os_info.itimer_sig, &oaction, NULL );
240  PAPIERROR( "setitimer start errno %d", errno );
241  return PAPI_ESYS;
242  }
243  return ( PAPI_OK );
244 }
memset(eventId, 0, size)
int errno
return PAPI_OK
Definition: linux-nvml.c:458
static void mpx_handler(int signal)
Definition: sw_multiplex.c:445
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
void PAPIERROR(char *format,...)
static struct sigaction oaction
Definition: sw_multiplex.c:154
#define PAPI_ESYS
Definition: fpapi.h:108
#define MPXDBG(format, args...)
Definition: papi_debug.h:67
static struct itimerval itime
Definition: sw_multiplex.c:152

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:

Variable Documentation

struct itimerval itime
static

Definition at line 152 of file sw_multiplex.c.

struct itimerval itimestop = { {0, 0}, {0, 0} }
static

Definition at line 153 of file sw_multiplex.c.

struct sigaction oaction
static

Definition at line 154 of file sw_multiplex.c.

unsigned int randomseed
static

Definition at line 141 of file sw_multiplex.c.

sigset_t sigreset
static

Definition at line 151 of file sw_multiplex.c.

Threadlist* tlist = NULL
static

List of threads that are multiplexing.

Definition at line 140 of file sw_multiplex.c.