Blame src/components/perfctr/perfctr.c

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
}