24#define MPX_NONDECR_HYBRID
134#define MPX_MINCYC 25000
153static const struct itimerval
itimestop = { {0, 0}, {0, 0} };
160static int threads_responding = 0;
167static void *global_process_record;
176 int domain,
int granularity );
183 MPXDBG(
"signal held\n" );
189 MPXDBG(
"signal released\n" );
200 interval = MPX_DEFAULT_INTERVAL;
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;
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;
228 MPXDBG(
"PID %d\n", getpid( ) );
229 memset( &sigact, 0,
sizeof ( sigact ) );
230 sigact.sa_flags = SA_RESTART;
249 MPXDBG(
"restore signal\n" );
259 MPXDBG(
"setitimer off\n" );
262 (
struct itimerval * ) &
itimestop, NULL ) == -1 )
281 unsigned long pid = (
unsigned long ) getpid( );
284 if ( t->
tid == tid || ( ( tid == 0 ) && ( t->
tid ==
pid ) ) )
296 if ( newset == NULL )
309 int retval, alloced_newset = 0;
314 MPXDBG(
"Adding %p %#x\n",newset,EventCode);
334 MPXDBG(
"New thread at %p\n", t );
337 MPXDBG(
"New process at %p\n", t );
338 t->
tid = (
unsigned long ) getpid( );
358 if ( t->
tid == tid ) {
369 MPXDBG(
"New thread %lx\n", tid );
378 if ( newset == NULL ) {
380 if ( newset == NULL ) {
400 domain, granularity );
402 if ( alloced_newset ) {
412 *mpx_events = newset;
427#ifdef MPX_DEBUG_TIMER
428static long long lastcall;
438#define SCALE_EVENT _PNE_PM_RUN_CYC
440#define SCALE_EVENT PAPI_TOT_CYC
453#ifdef MPX_DEBUG_OVERHEAD
458#ifdef MPX_DEBUG_TIMER
464 MPXDBG(
"Handler in thread\n" );
501 if ( threads_responding == 0 ) {
503#ifdef MPX_DEBUG_TIMER
504 thiscall = _papi_hwd_get_real_usec( );
505 MPXDBG(
"last signal was %lld usec ago\n", thiscall - lastcall );
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;
514#ifdef MPX_DEBUG_SIGNALS
515 MPXDBG(
"%#x signaling %#x\n", self, t->thr );
520#ifdef MPX_DEBUG_SIGNALS
521 MPXDBG(
"%#x was tapped, tr = %d\n", self, threads_responding );
523 --threads_responding;
526 lastthread = ( threads_responding == 0 );
533 if ( head != NULL ) {
546 if ( me != NULL && me->
cur_event != NULL ) {
549 long long cycles = 0, total_cycles = 0;
552 MPXDBG(
"retval=%d, cur_event=%p, I'm tid=%lx\n",
556 MPXDBG(
"counts[0] = %lld counts[1] = %lld\n", counts[0],
559 cur_event->
count += counts[0];
561 ? counts[0] : counts[1];
569 cur_event->
cycles += cycles;
572 ( double ) counts[0] / (
double ) cycles;
575 (
long long ) ( (
double ) total_cycles *
577 MPXDBG(
"New estimate = %lld (%lld cycles * %lf rate)\n",
588 cur_event->
count -= counts[0];
593 MPXDBG(
"%lx value = %lld cycles = %lld\n\n",
598 (
"tid(%lx): value = %lld (%lld) cycles = %lld (%lld) rate = %lf\n\n",
611 ( cur_event->
next == NULL ) ? head : cur_event->
next;
613 mev = ( mev->
next == NULL ) ? head : mev->
next ) {
625#ifdef MPX_DEBUG_OVERHEAD
630#ifdef ANY_THREAD_GETS_SIGNAL
633 for ( t =
tlist; t != NULL; t = t->
next ) {
635 ( t->
head == NULL ) )
637 MPXDBG(
"forwarding signal to thread %lx\n", t->
tid );
640 MPXDBG(
"forwarding signal to thread %lx returned %d\n",
662#ifdef MPX_DEBUG_TIMER
663 MPXDBG(
"timer restarted by %lx\n", me->
tid );
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 );
677 int domain,
int granularity )
697 long long cycles_this_slice, current_thread_mpx_c = 0;
700 t = mpx_events->
mythr;
705 current_thread_mpx_c += t->
total_c;
713 cycles_this_slice = 0;
718 cycles_this_slice = 0;
738#ifdef MPX_NONDECR_HYBRID
742 ( cycles_this_slice + t->
total_c -
747 ( (
values[0] / (
double ) cycles_this_slice ) *
802 MPXDBG(
"%s:%d:: start_c=%lld thread->total_c=%lld\n", __FILE__,
806 (
"%s:%d:: start_values[%d]=%lld estimate=%lld rate=%g last active=%lld\n",
808 mpx_events->
mev[
i]->count_estimate,
809 mpx_events->
mev[
i]->rate_estimate,
810 mpx_events->
mev[
i]->prev_total_c );
827 long long last_value[2];
828 long long cycles_this_slice = 0;
837 thread_data = mpx_events->
mythr;
845 ? last_value[0] : last_value[1];
859#ifdef MPX_NONDECR_HYBRID
867 if (called_by_stop) {
876 ( cycles_this_slice +
880 (
"%s:%d:: Inactive %d, stop values=%lld (est. %lld, rate %g, cycles %lld)\n",
883 cycles_this_slice + thread_data->
total_c -
891 (
"%s:%d:: -Active- %d, stop values=%lld (est. %lld, rate %g, cycles %lld)\n",
901 mpx_events->
stop_c = thread_data->
total_c + cycles_this_slice;
910 long long elapsed_slices = 0;
924 elapsed_slices ? ( elapsed_values / elapsed_slices ) : 0;
926 MPXDBG(
"%s:%d:: event %d, values=%lld ( %lld - %lld), cycles %lld\n",
927 __FILE__, __LINE__,
i,
976 int i, cur_mpx_event;
978 long long dummy_value[2];
984 if ( mpx_events == NULL )
1017 --mpx_events->
mev[
i]->active;
1018 if ( mpx_events->
mev[
i] == cur_event )
1026 if ( cur_mpx_event > -1 ) {
1029 if ( mev->
active == 0 ) {
1040 for (
tmp = ( cur_event->
next == NULL ) ? head : cur_event->
next;
1042 tmp = (
tmp->next == NULL ) ? head :
tmp->next ) {
1043 if (
tmp->active ) {
1075 if ( mpx_events == NULL )
1078 if ( *mpx_events == NULL )
1104 MPXDBG(
"%d\n", getpid( ) );
1133 if ( strstr(
_papi_hwd[ESI->
CmpIdx]->cmp_info.name,
"perfctr.c" ) == NULL )
1137 unsigned int chk_domain =
1140 if ( ( ESI->
domain.
domain & chk_domain ) != chk_domain ) {
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",
1154#if defined(PTHREADS) || defined(_POWER6)
1177 int num_events,
int domain,
int granularity )
1179 int i,
retval = 0, num_events_success = 0;
1197 for( mev = *head; mev != NULL; mev = mev->
next ) {
1205 if ( mev == NULL ) {
1207 if ( mev == NULL ) {
1223 MPXDBG(
"Event %d could not be counted.\n",
1230 MPXDBG(
"Event %d could not be counted.\n",
1242 MPXDBG(
"Scale event could not be counted "
1243 "at the same time.\n" );
1251 options.domain.domain = domain;
1254 MPXDBG(
"PAPI_set_opt(PAPI_DOMAIN, ...) = %d\n",
1261 options.granularity.granularity = granularity;
1267 MPXDBG(
"PAPI_set_opt(PAPI_GRANUL, ...) = %d\n",
1289 mpx_events->
mev[mpx_events->
num_events + num_events_success] = mev;
1290 mpx_events->
mev[mpx_events->
num_events + num_events_success]->uses++;
1291 num_events_success++;
1296 if ( *head != NULL ) {
1297 ( *head )->mythr = mpx_events->
mythr;
1300 mpx_events->
num_events += num_events_success;
1320 for (
i = 0;
i < num_events_success;
i++ ) {
1325 if ( num_events_success )
1346 mev = mpx_events->
mev[
i];
1348 mpx_events->
mev[
i] = NULL;
1371 mev = mpx_events->
mev[
i];
1375 mpx_events->
mev[
i] = NULL;
1387 mpx_events->
mev[
i] = mpx_events->
mev[
i + 1];
1392 mpx_events->
mev[
i] = NULL;
1406 Threadlist *thr = ( *head == NULL ) ? NULL : ( *head )->mythr;
1410 for ( mev = *head; mev != NULL; mev = nextmev ) {
1411 nextmev = mev->
next;
1413 if ( lastmev == NULL ) {
1416 lastmev->
next = nextmev;
1428 if ( *head != NULL ) {
1429 ( *head )->
mythr = thr;
PAPI_os_info_t _papi_os_info
static int Event[MAX_EVENTS]
add PAPI preset or native hardware event to an event set
Empty and destroy an EventSet.
Create a new empty PAPI EventSet.
Empty and destroy an EventSet.
Convert a name to a numeric hardware event code.
get real time counter value in microseconds
Read hardware counters from an event set.
Set PAPI library or event set options.
Start counting hardware events in an event set.
Stop counting hardware events in an event set.
struct papi_vectors * _papi_hwd[]
#define PAPI_DOM_SUPERVISOR
static long long values[NUM_EVENTS]
Return codes and api definitions.
unsigned long int(* _papi_hwi_thread_id_fn)(void)
#define MPXDBG(format, args...)
__sighandler_t signal(int __sig, __sighandler_t __handler) __attribute__((__nothrow__
unsigned int pthread_key_t
int sigaction(int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact) __attribute__((__nothrow__
int pthread_kill(pthread_t __threadid, int __signo) __attribute__((__nothrow__
int sigprocmask(int __how, const sigset_t *__restrict __set, sigset_t *__restrict __oset) __attribute__((__nothrow__
void PAPIERROR(char *format,...)
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
papi_mdi_t _papi_hwi_system_info
EventSetDomainInfo_t domain
struct _masterevent * mev[PAPI_MAX_SW_MPX_EVENTS]
long long stop_values[PAPI_MAX_SW_MPX_EVENTS]
long long start_values[PAPI_MAX_SW_MPX_EVENTS]
long long start_hc[PAPI_MAX_SW_MPX_EVENTS]
struct _threadlist * mythr
struct _threadlist * mythr
struct _masterevent * next
char model_string[PAPI_MAX_STR_LEN]
struct _threadlist * next
static int mpx_insert_events(MPX_EventSet *, int *event_list, int num_events, int domain, int granularity)
inline_static void mpx_hold(void)
static void mpx_delete_one_event(MPX_EventSet *mpx_events, int Event)
static void mpx_handler(int signal)
static int mpx_startup_itimer(void)
static void mpx_restore_signal(void)
static const struct itimerval itimestop
int mpx_remove_event(MPX_EventSet **mpx_events, int EventCode)
static Threadlist * tlist
static struct itimerval itime
static MPX_EventSet * mpx_malloc(Threadlist *t)
int mpx_check(int EventSet)
int MPX_read(MPX_EventSet *mpx_events, long long *values, int called_by_stop)
static struct sigaction oaction
inline_static void mpx_release(void)
int mpx_init(int interval_ns)
static void mpx_shutdown_itimer(void)
static void mpx_delete_events(MPX_EventSet *)
int MPX_add_events(MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
int mpx_add_event(MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
int MPX_start(MPX_EventSet *mpx_events)
static MasterEvent * get_my_threads_master_event_list(void)
int MPX_reset(MPX_EventSet *mpx_events)
static unsigned int randomseed
static void mpx_remove_unused(MasterEvent **head)
int MPX_stop(MPX_EventSet *mpx_events, long long *values)
static void mpx_init_timers(int interval)
int MPX_cleanup(MPX_EventSet **mpx_events)
#define PAPI_MAX_SW_MPX_EVENTS
inline_static int _papi_hwi_lock(int lck)
inline_static int _papi_hwi_unlock(int lck)
A pointer to the following is passed to PAPI_set/get_opt()