|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* File: perfctr.c
|
|
Packit Service |
a1973e |
* Author: Philip Mucci
|
|
Packit Service |
a1973e |
* mucci at cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Kevin London
|
|
Packit Service |
a1973e |
* london at cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Maynard Johnson
|
|
Packit Service |
a1973e |
* maynardj at us.ibm.com
|
|
Packit Service |
a1973e |
* Mods: Brian Sheely
|
|
Packit Service |
a1973e |
* bsheely at eecs.utk.edu
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
#include <linux/unistd.h>
|
|
Packit Service |
a1973e |
#include <errno.h>
|
|
Packit Service |
a1973e |
#include <sys/time.h>
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi.h"
|
|
Packit Service |
a1973e |
#include "papi_internal.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef PPC64
|
|
Packit Service |
a1973e |
#include "perfctr-ppc64.h"
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
#include "perfctr-x86.h"
|
|
Packit Service |
a1973e |
#include "papi_libpfm_events.h"
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi_vector.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi_memory.h"
|
|
Packit Service |
a1973e |
#include "extras.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "linux-common.h"
|
|
Packit Service |
a1973e |
#include "linux-context.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
extern papi_vector_t _perfctr_vector;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef PPC64
|
|
Packit Service |
a1973e |
extern int setup_ppc64_presets( int cputype, int cidx );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This should be in a linux.h header file maybe. */
|
|
Packit Service |
a1973e |
#define FOPEN_ERROR "fopen(%s) returned NULL"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(PERFCTR26)
|
|
Packit Service |
a1973e |
#define PERFCTR_CPU_NAME(pi) perfctr_info_cpu_name(pi)
|
|
Packit Service |
a1973e |
#define PERFCTR_CPU_NRCTRS(pi) perfctr_info_nrctrs(pi)
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
#define PERFCTR_CPU_NAME perfctr_cpu_name
|
|
Packit Service |
a1973e |
#define PERFCTR_CPU_NRCTRS perfctr_cpu_nrctrs
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if !defined(PPC64)
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
xlate_cpu_type_to_vendor( unsigned perfctr_cpu_type )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
switch ( perfctr_cpu_type ) {
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P5:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P5MMX:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P6:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_PII:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_PIII:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_P4M3
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_PENTM
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_PENTM:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_CORE
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_CORE:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_CORE2
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_CORE2:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_ATOM /* family 6 model 28 */
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_ATOM:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_NHLM /* family 6 model 26 */
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_NHLM:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_INTEL_WSTMR
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_WSTMR:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
return ( PAPI_VENDOR_INTEL );
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_AMD_K8
|
|
Packit Service |
a1973e |
case PERFCTR_X86_AMD_K8:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_AMD_K8C
|
|
Packit Service |
a1973e |
case PERFCTR_X86_AMD_K8C:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#ifdef PERFCTR_X86_AMD_FAM10 /* this is defined in perfctr 2.6.29 */
|
|
Packit Service |
a1973e |
case PERFCTR_X86_AMD_FAM10:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
case PERFCTR_X86_AMD_K7:
|
|
Packit Service |
a1973e |
return ( PAPI_VENDOR_AMD );
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
return ( PAPI_VENDOR_UNKNOWN );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
long long tb_scale_factor = ( long long ) 1; /* needed to scale get_cycles on PPC series */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_perfctr_init_component( int cidx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int retval;
|
|
Packit Service |
a1973e |
struct perfctr_info info;
|
|
Packit Service |
a1973e |
char abiv[PAPI_MIN_STR_LEN];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(PERFCTR26)
|
|
Packit Service |
a1973e |
int fd;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
struct vperfctr *dev;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(PERFCTR26)
|
|
Packit Service |
a1973e |
/* Get info from the kernel */
|
|
Packit Service |
a1973e |
/* Use lower level calls per Mikael to get the perfctr info
|
|
Packit Service |
a1973e |
without actually creating a new kernel-side state.
|
|
Packit Service |
a1973e |
Also, close the fd immediately after retrieving the info.
|
|
Packit Service |
a1973e |
This is much lighter weight and doesn't reserve the counter
|
|
Packit Service |
a1973e |
resources. Also compatible with perfctr 2.6.14.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
fd = _vperfctr_open( 0 );
|
|
Packit Service |
a1973e |
if ( fd < 0 ) {
|
|
Packit Service |
a1973e |
strncpy(_perfctr_vector.cmp_info.disabled_reason,
|
|
Packit Service |
a1973e |
VOPEN_ERROR,PAPI_MAX_STR_LEN);
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
retval = perfctr_info( fd, &info );
|
|
Packit Service |
a1973e |
close( fd );
|
|
Packit Service |
a1973e |
if ( retval < 0 ) {
|
|
Packit Service |
a1973e |
strncpy(_perfctr_vector.cmp_info.disabled_reason,
|
|
Packit Service |
a1973e |
VINFO_ERROR,PAPI_MAX_STR_LEN);
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* copy tsc multiplier to local variable */
|
|
Packit Service |
a1973e |
/* this field appears in perfctr 2.6 and higher */
|
|
Packit Service |
a1973e |
tb_scale_factor = ( long long ) info.tsc_to_cpu_mult;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
/* Opened once for all threads. */
|
|
Packit Service |
a1973e |
if ( ( dev = vperfctr_open( ) ) == NULL ) {
|
|
Packit Service |
a1973e |
strncpy(_perfctr_vector.cmp_info.disabled_reason,
|
|
Packit Service |
a1973e |
VOPEN_ERROR,PAPI_MAX_STR_LEN);
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "_perfctr_init_component vperfctr_open = %p\n", dev );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Get info from the kernel */
|
|
Packit Service |
a1973e |
retval = vperfctr_info( dev, &info );
|
|
Packit Service |
a1973e |
if ( retval < 0 ) {
|
|
Packit Service |
a1973e |
strncpy(_perfctr_vector.cmp_info.disabled_reason,
|
|
Packit Service |
a1973e |
VINFO_ERROR,PAPI_MAX_STR_LEN);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
vperfctr_close( dev );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Fill in what we can of the papi_system_info. */
|
|
Packit Service |
a1973e |
retval = _papi_os_vector.get_system_info( &_papi_hwi_system_info );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Setup memory info */
|
|
Packit Service |
a1973e |
retval = _papi_os_vector.get_memory_info( &_papi_hwi_system_info.hw_info,
|
|
Packit Service |
a1973e |
( int ) info.cpu_type );
|
|
Packit Service |
a1973e |
if ( retval )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
strcpy( _perfctr_vector.cmp_info.name,"perfctr.c" );
|
|
Packit Service |
a1973e |
strcpy( _perfctr_vector.cmp_info.version, "$Revision$" );
|
|
Packit Service |
a1973e |
sprintf( abiv, "0x%08X", info.abi_version );
|
|
Packit Service |
a1973e |
strcpy( _perfctr_vector.cmp_info.support_version, abiv );
|
|
Packit Service |
a1973e |
strcpy( _perfctr_vector.cmp_info.kernel_version, info.driver_version );
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.CmpIdx = cidx;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.num_cntrs = ( int ) PERFCTR_CPU_NRCTRS( &info );
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.num_mpx_cntrs=_perfctr_vector.cmp_info.num_cntrs;
|
|
Packit Service |
a1973e |
if ( info.cpu_features & PERFCTR_FEATURE_RDPMC )
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.fast_counter_read = 1;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.fast_counter_read = 0;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.fast_real_timer = 1;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.fast_virtual_timer = 1;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.attach = 1;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.attach_must_ptrace = 1;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.default_domain = PAPI_DOM_USER;
|
|
Packit Service |
a1973e |
#if !defined(PPC64)
|
|
Packit Service |
a1973e |
/* AMD and Intel ia386 processors all support unit mask bits */
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.cntr_umasks = 1;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
#if defined(PPC64)
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.available_domains =
|
|
Packit Service |
a1973e |
PAPI_DOM_USER | PAPI_DOM_KERNEL | PAPI_DOM_SUPERVISOR;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.default_granularity = PAPI_GRN_THR;
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.available_granularities = PAPI_GRN_THR;
|
|
Packit Service |
a1973e |
if ( info.cpu_features & PERFCTR_FEATURE_PCINT )
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.hardware_intr = 1;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.hardware_intr = 0;
|
|
Packit Service |
a1973e |
SUBDBG( "Hardware/OS %s support counter generated interrupts\n",
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.hardware_intr ? "does" : "does not" );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
strcpy( _papi_hwi_system_info.hw_info.model_string,
|
|
Packit Service |
a1973e |
PERFCTR_CPU_NAME( &info ) );
|
|
Packit Service |
a1973e |
_papi_hwi_system_info.hw_info.model = ( int ) info.cpu_type;
|
|
Packit Service |
a1973e |
#if defined(PPC64)
|
|
Packit Service |
a1973e |
_papi_hwi_system_info.hw_info.vendor = PAPI_VENDOR_IBM;
|
|
Packit Service |
a1973e |
if ( strlen( _papi_hwi_system_info.hw_info.vendor_string ) == 0 )
|
|
Packit Service |
a1973e |
strcpy( _papi_hwi_system_info.hw_info.vendor_string, "IBM" );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
_papi_hwi_system_info.hw_info.vendor =
|
|
Packit Service |
a1973e |
xlate_cpu_type_to_vendor( info.cpu_type );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Setup presets last. Some platforms depend on earlier info */
|
|
Packit Service |
a1973e |
#if !defined(PPC64)
|
|
Packit Service |
a1973e |
// retval = setup_p3_vector_table(vtable);
|
|
Packit Service |
a1973e |
if ( !retval )
|
|
Packit Service |
a1973e |
retval = _papi_libpfm_init(&_perfctr_vector, cidx );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
/* Setup native and preset events */
|
|
Packit Service |
a1973e |
// retval = ppc64_setup_vector_table(vtable);
|
|
Packit Service |
a1973e |
if ( !retval )
|
|
Packit Service |
a1973e |
retval = perfctr_ppc64_setup_native_table( );
|
|
Packit Service |
a1973e |
if ( !retval )
|
|
Packit Service |
a1973e |
retval = setup_ppc64_presets( info.cpu_type, cidx );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
if ( retval )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
attach( hwd_control_state_t * ctl, unsigned long tid )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
struct vperfctr_control tmp;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef VPERFCTR_CONTROL_CLOEXEC
|
|
Packit Service |
a1973e |
tmp.flags = VPERFCTR_CONTROL_CLOEXEC;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ctl->rvperfctr = rvperfctr_open( ( int ) tid );
|
|
Packit Service |
a1973e |
if ( ctl->rvperfctr == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( VOPEN_ERROR );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "_papi_hwd_ctl rvperfctr_open() = %p\n", ctl->rvperfctr );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Initialize the per thread/process virtualized TSC */
|
|
Packit Service |
a1973e |
memset( &tmp, 0x0, sizeof ( tmp ) );
|
|
Packit Service |
a1973e |
tmp.cpu_control.tsc_on = 1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Start the per thread/process virtualized TSC */
|
|
Packit Service |
a1973e |
if ( rvperfctr_control( ctl->rvperfctr, &tmp ) < 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( RCNTRL_ERROR );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
} /* end attach() */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
detach( hwd_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
rvperfctr_close( ctl->rvperfctr );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
} /* end detach() */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
round_requested_ns( int ns )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( ns < _papi_os_info.itimer_res_ns ) {
|
|
Packit Service |
a1973e |
return _papi_os_info.itimer_res_ns;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
int leftover_ns = ns % _papi_os_info.itimer_res_ns;
|
|
Packit Service |
a1973e |
return ns + leftover_ns;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_perfctr_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ctx; /*unused */
|
|
Packit Service |
a1973e |
switch ( code ) {
|
|
Packit Service |
a1973e |
case PAPI_DOMAIN:
|
|
Packit Service |
a1973e |
case PAPI_DEFDOM:
|
|
Packit Service |
a1973e |
#if defined(PPC64)
|
|
Packit Service |
a1973e |
return ( _perfctr_vector.
|
|
Packit Service |
a1973e |
set_domain( option->domain.ESI, option->domain.domain ) );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
return ( _perfctr_vector.
|
|
Packit Service |
a1973e |
set_domain( option->domain.ESI->ctl_state,
|
|
Packit Service |
a1973e |
option->domain.domain ) );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
case PAPI_GRANUL:
|
|
Packit Service |
a1973e |
case PAPI_DEFGRN:
|
|
Packit Service |
a1973e |
return PAPI_ECMP;
|
|
Packit Service |
a1973e |
case PAPI_ATTACH:
|
|
Packit Service |
a1973e |
return ( attach( option->attach.ESI->ctl_state, option->attach.tid ) );
|
|
Packit Service |
a1973e |
case PAPI_DETACH:
|
|
Packit Service |
a1973e |
return ( detach( option->attach.ESI->ctl_state ) );
|
|
Packit Service |
a1973e |
case PAPI_DEF_ITIMER:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
/* flags are currently ignored, eventually the flags will be able
|
|
Packit Service |
a1973e |
to specify whether or not we use POSIX itimers (clock_gettimer) */
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_REAL ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGALRM ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGVTALRM ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_PROF ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGPROF ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( option->itimer.ns > 0 )
|
|
Packit Service |
a1973e |
option->itimer.ns = round_requested_ns( option->itimer.ns );
|
|
Packit Service |
a1973e |
/* At this point, we assume the user knows what he or
|
|
Packit Service |
a1973e |
she is doing, they maybe doing something arch specific */
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case PAPI_DEF_MPX_NS:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
option->multiplex.ns =
|
|
Packit Service |
a1973e |
( unsigned long ) round_requested_ns( ( int ) option->multiplex.
|
|
Packit Service |
a1973e |
ns );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case PAPI_DEF_ITIMER_NS:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
option->itimer.ns = round_requested_ns( option->itimer.ns );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
return ( PAPI_ENOSUPP );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
void
|
|
Packit Service |
a1973e |
_perfctr_dispatch_timer( int signal, siginfo_t * si, void *context )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) signal; /*unused */
|
|
Packit Service |
a1973e |
_papi_hwi_context_t ctx;
|
|
Packit Service |
a1973e |
ThreadInfo_t *master = NULL;
|
|
Packit Service |
a1973e |
int isHardware = 0;
|
|
Packit Service |
a1973e |
caddr_t address;
|
|
Packit Service |
a1973e |
int cidx = _perfctr_vector.cmp_info.CmpIdx;
|
|
Packit Service |
a1973e |
hwd_context_t *our_context;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ctx.si = si;
|
|
Packit Service |
a1973e |
ctx.ucontext = ( ucontext_t * ) context;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define OVERFLOW_MASK si->si_pmc_ovf_mask
|
|
Packit Service |
a1973e |
#define GEN_OVERFLOW 0
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
address = ( caddr_t ) GET_OVERFLOW_ADDRESS( ( ctx ) );
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, &isHardware,
|
|
Packit Service |
a1973e |
OVERFLOW_MASK, GEN_OVERFLOW, &master,
|
|
Packit Service |
a1973e |
_perfctr_vector.cmp_info.CmpIdx );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* We are done, resume interrupting counters */
|
|
Packit Service |
a1973e |
if ( isHardware ) {
|
|
Packit Service |
a1973e |
our_context=(hwd_context_t *) master->context[cidx];
|
|
Packit Service |
a1973e |
errno = vperfctr_iresume( our_context->perfctr );
|
|
Packit Service |
a1973e |
if ( errno < 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "vperfctr_iresume errno %d", errno );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_perfctr_init_thread( hwd_context_t * ctx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
struct vperfctr_control tmp;
|
|
Packit Service |
a1973e |
int error;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Initialize our thread/process pointer. */
|
|
Packit Service |
a1973e |
if ( ( ctx->perfctr = vperfctr_open( ) ) == NULL ) {
|
|
Packit Service |
a1973e |
#ifdef VPERFCTR_OPEN_CREAT_EXCL
|
|
Packit Service |
a1973e |
/* New versions of perfctr have this, which allows us to
|
|
Packit Service |
a1973e |
get a previously created context, i.e. one created after
|
|
Packit Service |
a1973e |
a fork and now we're inside a new process that has been exec'd */
|
|
Packit Service |
a1973e |
if ( errno ) {
|
|
Packit Service |
a1973e |
if ( ( ctx->perfctr = vperfctr_open_mode( 0 ) ) == NULL ) {
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "_papi_hwd_init vperfctr_open() = %p\n", ctx->perfctr );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Initialize the per thread/process virtualized TSC */
|
|
Packit Service |
a1973e |
memset( &tmp, 0x0, sizeof ( tmp ) );
|
|
Packit Service |
a1973e |
tmp.cpu_control.tsc_on = 1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef VPERFCTR_CONTROL_CLOEXEC
|
|
Packit Service |
a1973e |
tmp.flags = VPERFCTR_CONTROL_CLOEXEC;
|
|
Packit Service |
a1973e |
SUBDBG( "close on exec\t\t\t%u\n", tmp.flags );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Start the per thread/process virtualized TSC */
|
|
Packit Service |
a1973e |
error = vperfctr_control( ctx->perfctr, &tmp );
|
|
Packit Service |
a1973e |
if ( error < 0 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "starting virtualized TSC; vperfctr_control returns %d\n",
|
|
Packit Service |
a1973e |
error );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This routine is for shutting down threads, including the
|
|
Packit Service |
a1973e |
master thread. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_perfctr_shutdown_thread( hwd_context_t * ctx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
#ifdef DEBUG
|
|
Packit Service |
a1973e |
int retval = vperfctr_unlink( ctx->perfctr );
|
|
Packit Service |
a1973e |
SUBDBG( "_papi_hwd_shutdown vperfctr_unlink(%p) = %d\n", ctx->perfctr,
|
|
Packit Service |
a1973e |
retval );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
vperfctr_unlink( ctx->perfctr );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
vperfctr_close( ctx->perfctr );
|
|
Packit Service |
a1973e |
SUBDBG( "_perfctr_shutdown vperfctr_close(%p)\n", ctx->perfctr );
|
|
Packit Service |
a1973e |
memset( ctx, 0x0, sizeof ( hwd_context_t ) );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|