int _papi_hwd_read( hwd_context_t * ctx, hwd_control_state_t * spc, long long **dp, int flags ) { if ( flags & PAPI_PAUSED ) { vperfctr_read_state( ctx->perfctr, &spc->state, NULL ); } else { SUBDBG( "vperfctr_read_ctrs\n" ); if ( spc->rvperfctr != NULL ) { rvperfctr_read_ctrs( spc->rvperfctr, &spc->state ); } else { vperfctr_read_ctrs( ctx->perfctr, &spc->state ); } } *dp = ( long long * ) spc->state.pmc; #ifdef DEBUG { if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { int i; for ( i = 0; i < spc->control.cpu_control.nractrs + spc->control.cpu_control.nrictrs; i++ ) { SUBDBG( "raw val hardware index %d is %lld\n", i, ( long long ) spc->state.pmc[i] ); } } } #endif return ( PAPI_OK ); }
int _papi_hwd_read( hwd_context_t * ctx, hwd_control_state_t * spc, long long **dp, int flags ) { pmc_read_state( _papi_hwi_system_info.num_cntrs, &spc->state ); *dp = ( long long * ) spc->state.sum.pmc; #ifdef DEBUG { if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { unsigned int i; for ( i = 0; i < spc->control.cpu_control.nractrs; i++ ) { SUBDBG( "raw val hardware index %d is %lld\n", i, ( long long ) spc->state.sum.pmc[i] ); } } } #endif return ( PAPI_OK ); }
static int build_tables( void ) { int i; int regno; int npic; einfo_t *ep; int n; int npresets; npic = cpc_getnpic( cpuver ); nctrs = 0; for ( regno = 0; regno < npic; ++regno ) { cpc_walk_names( cpuver, regno, 0, action ); } SUBDBG( "%d counters\n", nctrs ); if ( ( ctrs = papi_malloc( nctrs * sizeof ( struct ctr_info ) ) ) == 0 ) { return PAPI_ENOMEM; } nctrs = 0; for ( regno = 0; regno < npic; ++regno ) { cpc_walk_names( cpuver, regno, ( void * ) 1, action ); } SUBDBG( "%d counters\n", nctrs ); #if DEBUG if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { for ( i = 0; i < nctrs; ++i ) { SUBDBG( "%s: bits (%x,%x) pics %x\n", ctrs[i].name, ctrs[i].bits[0], ctrs[i].bits[1], ctrs[i].bitmask ); } } #endif /* Build the native event table */ if ( ( native_table = papi_malloc( nctrs * sizeof ( native_info_t ) ) ) == 0 ) { papi_free( ctrs ); return PAPI_ENOMEM; } for ( i = 0; i < nctrs; ++i ) { native_table[i].name[39] = 0; strncpy( native_table[i].name, ctrs[i].name, 39 ); if ( ctrs[i].bitmask & 1 ) native_table[i].encoding[0] = ctrs[i].bits[0]; else native_table[i].encoding[0] = -1; if ( ctrs[i].bitmask & 2 ) native_table[i].encoding[1] = ctrs[i].bits[1]; else native_table[i].encoding[1] = -1; } papi_free( ctrs ); /* Build the preset table */ if ( cpuver <= CPC_ULTRA2 ) { n = sizeof ( us2info ) / sizeof ( einfo_t ); ep = us2info; } else if ( cpuver <= LASTULTRA3 ) { n = sizeof ( us3info ) / sizeof ( einfo_t ); ep = us3info; } else return PAPI_ESBSTR; preset_table = papi_malloc( ( n + 1 ) * sizeof ( hwi_search_t ) ); npresets = 0; for ( i = 0; i < n; ++i ) { add_preset( preset_table, &npresets, ep[i] ); } memset( &preset_table[npresets], 0, sizeof ( hwi_search_t ) ); #ifdef DEBUG if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { SUBDBG( "Native table: %d\n", nctrs ); for ( i = 0; i < nctrs; ++i ) { SUBDBG( "%40s: %8x %8x\n", native_table[i].name, native_table[i].encoding[0], native_table[i].encoding[1] ); } SUBDBG( "\nPreset table: %d\n", npresets ); for ( i = 0; preset_table[i].event_code != 0; ++i ) { SUBDBG( "%8x: op %2d e0 %8x e1 %8x\n", preset_table[i].event_code, preset_table[i].data.derived, preset_table[i].data.native[0], preset_table[i].data.native[1] ); } } #endif _solaris_vector.cmp_info.num_native_events = nctrs; return PAPI_OK; }
static int get_system_info( papi_mdi_t *mdi ) { int retval; pid_t pid; char maxargs[PAPI_MAX_STR_LEN] = "<none>"; psinfo_t psi; int fd; int hz, version; char cpuname[PAPI_MAX_STR_LEN], pname[PAPI_HUGE_STR_LEN]; /* Check counter access */ if ( cpc_version( CPC_VER_CURRENT ) != CPC_VER_CURRENT ) return ( PAPI_ESBSTR ); SUBDBG( "CPC version %d successfully opened\n", CPC_VER_CURRENT ); if ( cpc_access( ) == -1 ) return ( PAPI_ESBSTR ); /* Global variable cpuver */ cpuver = cpc_getcpuver( ); SUBDBG( "Got %d from cpc_getcpuver()\n", cpuver ); if ( cpuver == -1 ) return ( PAPI_ESBSTR ); #ifdef DEBUG { if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { const char *name; int i; name = cpc_getcpuref( cpuver ); if ( name ) SUBDBG( "CPC CPU reference: %s\n", name ); else SUBDBG( "Could not get a CPC CPU reference\n" ); for ( i = 0; i < cpc_getnpic( cpuver ); i++ ) { SUBDBG( "\n%6s %-40s %8s\n", "Reg", "Symbolic name", "Code" ); cpc_walk_names( cpuver, i, "%6d %-40s %02x\n", print_walk_names ); } SUBDBG( "\n" ); } } #endif /* Initialize other globals */ if ( ( retval = build_tables( ) ) != PAPI_OK ) return retval; preset_search_map = preset_table; if ( cpuver <= CPC_ULTRA2 ) { SUBDBG( "cpuver (==%d) <= CPC_ULTRA2 (==%d)\n", cpuver, CPC_ULTRA2 ); pcr_shift[0] = CPC_ULTRA_PCR_PIC0_SHIFT; pcr_shift[1] = CPC_ULTRA_PCR_PIC1_SHIFT; } else if ( cpuver <= LASTULTRA3 ) { SUBDBG( "cpuver (==%d) <= CPC_ULTRA3x (==%d)\n", cpuver, LASTULTRA3 ); pcr_shift[0] = CPC_ULTRA_PCR_PIC0_SHIFT; pcr_shift[1] = CPC_ULTRA_PCR_PIC1_SHIFT; _solaris_vector.cmp_info.hardware_intr = 1; _solaris_vector.cmp_info.hardware_intr_sig = SIGEMT; } else return ( PAPI_ESBSTR ); /* Path and args */ pid = getpid( ); if ( pid == -1 ) return ( PAPI_ESYS ); /* Turn on microstate accounting for this process and any LWPs. */ sprintf( maxargs, "/proc/%d/ctl", ( int ) pid ); if ( ( fd = open( maxargs, O_WRONLY ) ) == -1 ) return ( PAPI_ESYS ); { int retval; struct { long cmd; long flags; } cmd; cmd.cmd = PCSET; cmd.flags = PR_MSACCT | PR_MSFORK; retval = write( fd, &cmd, sizeof ( cmd ) ); close( fd ); SUBDBG( "Write PCSET returned %d\n", retval ); if ( retval != sizeof ( cmd ) ) return ( PAPI_ESYS ); } /* Get executable info */ sprintf( maxargs, "/proc/%d/psinfo", ( int ) pid ); if ( ( fd = open( maxargs, O_RDONLY ) ) == -1 ) return ( PAPI_ESYS ); read( fd, &psi, sizeof ( psi ) ); close( fd ); /* Cut off any arguments to exe */ { char *tmp; tmp = strchr( psi.pr_psargs, ' ' ); if ( tmp != NULL ) *tmp = '\0'; } if ( realpath( psi.pr_psargs, pname ) ) strncpy( _papi_hwi_system_info.exe_info.fullname, pname, PAPI_HUGE_STR_LEN ); else strncpy( _papi_hwi_system_info.exe_info.fullname, psi.pr_psargs, PAPI_HUGE_STR_LEN ); /* please don't use pr_fname here, because it can only store less that 16 characters */ strcpy( _papi_hwi_system_info.exe_info.address_info.name, basename( _papi_hwi_system_info.exe_info.fullname ) ); SUBDBG( "Full Executable is %s\n", _papi_hwi_system_info.exe_info.fullname ); /* Executable regions, reading /proc/pid/maps file */ retval = _ultra_hwd_update_shlib_info( &_papi_hwi_system_info ); /* Hardware info */ _papi_hwi_system_info.hw_info.ncpu = sysconf( _SC_NPROCESSORS_ONLN ); _papi_hwi_system_info.hw_info.nnodes = 1; _papi_hwi_system_info.hw_info.totalcpus = sysconf( _SC_NPROCESSORS_CONF ); retval = scan_prtconf( cpuname, PAPI_MAX_STR_LEN, &hz, &version ); if ( retval == -1 ) return ( PAPI_ESBSTR ); strcpy( _papi_hwi_system_info.hw_info.model_string, cpc_getcciname( cpuver ) ); _papi_hwi_system_info.hw_info.model = cpuver; strcpy( _papi_hwi_system_info.hw_info.vendor_string, "SUN" ); _papi_hwi_system_info.hw_info.vendor = PAPI_VENDOR_SUN; _papi_hwi_system_info.hw_info.revision = version; _papi_hwi_system_info.hw_info.mhz = ( ( float ) hz / 1.0e6 ); SUBDBG( "hw_info.mhz = %f\n", _papi_hwi_system_info.hw_info.mhz ); /* Number of PMCs */ retval = cpc_getnpic( cpuver ); if ( retval < 0 ) return ( PAPI_ESBSTR ); _solaris_vector.cmp_info.num_cntrs = retval; _solaris_vector.cmp_info.fast_real_timer = 1; _solaris_vector.cmp_info.fast_virtual_timer = 1; _solaris_vector.cmp_info.default_domain = PAPI_DOM_USER; _solaris_vector.cmp_info.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL; /* Setup presets */ retval = _papi_hwi_setup_all_presets( preset_search_map, NULL ); if ( retval ) return ( retval ); return ( PAPI_OK ); }
int MPX_start( MPX_EventSet * mpx_events ) { int retval = PAPI_OK; int i; long long values[2]; long long cycles_this_slice, current_thread_mpx_c = 0; Threadlist *t; t = mpx_events->mythr; mpx_hold( ); if ( t->cur_event && t->cur_event->active ) { current_thread_mpx_c += t->total_c; retval = PAPI_read( t->cur_event->papi_event, values ); assert( retval == PAPI_OK ); if ( retval == PAPI_OK ) { cycles_this_slice = ( t->cur_event->pi.event_type == SCALE_EVENT ) ? values[0] : values[1]; } else { values[0] = values[1] = 0; cycles_this_slice = 0; } } else { values[0] = values[1] = 0; cycles_this_slice = 0; } /* Make all events in this set active, and for those * already active, get the current count and cycles. */ for ( i = 0; i < mpx_events->num_events; i++ ) { MasterEvent *mev = mpx_events->mev[i]; if ( mev->active++ ) { mpx_events->start_values[i] = mev->count_estimate; mpx_events->start_hc[i] = mev->cycles; /* If this happens to be the currently-running * event, add in the current amounts from this * time slice. If it's a rate, though, don't * bother since the event might not have been * running long enough to get an accurate count. */ if ( t->cur_event && !( t->cur_event->is_a_rate ) ) { #ifdef MPX_NONDECR_HYBRID if ( mev != t->cur_event ) { /* This event is not running this slice */ mpx_events->start_values[i] += ( long long ) ( mev->rate_estimate * ( cycles_this_slice + t->total_c - mev->prev_total_c ) ); } else { /* The event is running, use current value + estimate */ if ( cycles_this_slice >= MPX_MINCYC ) mpx_events->start_values[i] += values[0] + ( long long ) ( ( values[0] / ( double ) cycles_this_slice ) * ( t->total_c - mev->prev_total_c ) ); else /* Use previous rate if the event has run too short time */ mpx_events->start_values[i] += values[0] + ( long long ) ( mev->rate_estimate * ( t->total_c - mev->prev_total_c ) ); } #endif } else { mpx_events->start_values[i] = mev->count; } } else { /* The = 0 isn't actually necessary; we only need * to sync up the mpx event to the master event, * but it seems safe to set the mev to 0 here, and * that gives us a change to avoid (very unlikely) * rollover problems for events used repeatedly over * a long time. */ mpx_events->start_values[i] = 0; mpx_events->stop_values[i] = 0; mpx_events->start_hc[i] = mev->cycles = 0; mev->count_estimate = 0; mev->rate_estimate = 0.0; mev->prev_total_c = current_thread_mpx_c; mev->count = 0; } /* Adjust start value to include events and cycles * counted previously for this event set. */ } mpx_events->status = MPX_RUNNING; /* Start first counter if one isn't already running */ if ( t->cur_event == NULL ) { /* Pick an events at random to start. */ int index = ( rand_r( &randomseed ) % mpx_events->num_events ); t->cur_event = mpx_events->mev[index]; t->total_c = 0; t->cur_event->prev_total_c = 0; mpx_events->start_c = 0; retval = PAPI_start( mpx_events->mev[index]->papi_event ); assert( retval == PAPI_OK ); } else { /* If an event is already running, record the starting cycle * count for mpx_events, which is the accumlated cycle count * for the master event set plus the cycles for this time * slice. */ mpx_events->start_c = t->total_c + cycles_this_slice; } #if defined(DEBUG) if ( ISLEVEL( DEBUG_MULTIPLEX ) ) { MPXDBG( "%s:%d:: start_c=%lld thread->total_c=%lld\n", __FILE__, __LINE__, mpx_events->start_c, t->total_c ); for ( i = 0; i < mpx_events->num_events; i++ ) { MPXDBG ( "%s:%d:: start_values[%d]=%lld estimate=%lld rate=%g last active=%lld\n", __FILE__, __LINE__, i, mpx_events->start_values[i], mpx_events->mev[i]->count_estimate, mpx_events->mev[i]->rate_estimate, mpx_events->mev[i]->prev_total_c ); } } #endif mpx_release( ); retval = mpx_startup_itimer( ); return retval; }
int _papi_hwi_shutdown_global_threads( void ) { int err,num_threads,i; ThreadInfo_t *tmp,*next; unsigned long our_tid; tmp = _papi_hwi_lookup_thread( 0 ); if ( tmp == NULL ) { THRDBG( "Did not find my thread for shutdown!\n" ); err = PAPI_EBUG; } else { our_tid=tmp->tid; THRDBG("Shutting down %ld\n",our_tid); err = _papi_hwi_shutdown_thread( tmp ); /* count threads */ tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head; num_threads=0; while(tmp!=NULL) { num_threads++; if (tmp->next==_papi_hwi_thread_head) break; tmp=tmp->next; } /* Shut down all threads allocated by this thread */ /* Urgh it's a circular list where we removed in the loop */ /* so the only sane way to do it is get a count in advance */ tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head; for(i=0;i<num_threads;i++) { next=tmp->next; THRDBG("looking at #%d %ld our_tid: %ld alloc_tid: %ld\n", i,tmp->tid,our_tid,tmp->allocator_tid); if (tmp->allocator_tid==our_tid) { THRDBG("Also removing thread %ld\n",tmp->tid); err = _papi_hwi_shutdown_thread( tmp ); } tmp=next; } } #ifdef DEBUG if ( ISLEVEL( DEBUG_THREADS ) ) { if ( _papi_hwi_thread_head ) { THRDBG( "Thread head %p still exists!\n", _papi_hwi_thread_head ); } } #endif #if defined(HAVE_THREAD_LOCAL_STORAGE) _papi_hwi_my_thread = NULL; #endif _papi_hwi_thread_head = NULL; _papi_hwi_thread_id_fn = NULL; #if defined(ANY_THREAD_GETS_SIGNAL) _papi_hwi_thread_kill_fn = NULL; #endif return err; }