Blame src/solaris-niagara2.c

Packit 577717
/*******************************************************************************
Packit 577717
 * >>>>>> "Development of a PAPI Backend for the Sun Niagara 2 Processor" <<<<<<
Packit 577717
 * -----------------------------------------------------------------------------
Packit 577717
 *
Packit 577717
 * Fabian Gorsler <fabian.gorsler@smail.inf.h-bonn-rhein-sieg.de>
Packit 577717
 *
Packit 577717
 *       Hochschule Bonn-Rhein-Sieg, Sankt Augustin, Germany
Packit 577717
 *       University of Applied Sciences
Packit 577717
 *
Packit 577717
 * -----------------------------------------------------------------------------
Packit 577717
 *
Packit 577717
 * File:   solaris-niagara2.c
Packit 577717
 * Author: fg215045
Packit 577717
 * 
Packit 577717
 * Description: This source file is the implementation of a PAPI 
Packit 577717
 * component for the Sun Niagara 2 processor (aka UltraSPARC T2) 
Packit 577717
 * running on Solaris 10 with libcpc 2. 
Packit 577717
 * The machine for implementing this component was courtesy of RWTH 
Packit 577717
 * Aachen University, Germany. Thanks to the HPC-Team at RWTH! 
Packit 577717
 *
Packit 577717
 * Conventions used:
Packit 577717
 *  - __cpc_*: Functions, variables, etc. related to libcpc handling
Packit 577717
 *  - __sol_*: Functions, variables, etc. related to Solaris handling
Packit 577717
 *  - __int_*: Functions, variables, etc. related to extensions of libcpc
Packit 577717
 *  - _niagara*: Functions, variables, etc. needed by PAPI hardware dependent
Packit 577717
 *                 layer, i.e. the component itself
Packit 577717
 *
Packit 577717
 * 
Packit 577717
 *      ***** Feel free to convert this header to the PAPI default *****
Packit 577717
 *
Packit 577717
 * -----------------------------------------------------------------------------
Packit 577717
 * Created on April 23, 2009, 7:31 PM
Packit 577717
 ******************************************************************************/
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "solaris-niagara2.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
Packit 577717
#include <libcpc.h>
Packit 577717
#include <procfs.h>
Packit 577717
#include <sys/types.h>
Packit 577717
#include <sys/stat.h>
Packit 577717
#include <fcntl.h>
Packit 577717
#include <unistd.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <strings.h>
Packit 577717
#include <sys/lwp.h>
Packit 577717
#include <limits.h>
Packit 577717
#include <sys/processor.h>
Packit 577717
#include <sys/types.h>
Packit 577717
#include <sys/time.h>
Packit 577717
#include <stdarg.h>
Packit 577717
#include <libgen.h>
Packit 577717
#include <ucontext.h>
Packit 577717
#include <sys/regset.h>
Packit 577717
#include <sys/utsname.h>
Packit 577717
Packit 577717
#include "solaris-common.h"
Packit 577717
#include "solaris-memory.h"
Packit 577717
Packit 577717
#define hwd_control_state_t _niagara2_control_state_t
Packit 577717
#define hwd_context_t       _niagara2_context_t
Packit 577717
#define hwd_register_t      _niagara2_register_t
Packit 577717
Packit 577717
extern caddr_t _start, _end, _etext, _edata;
Packit 577717
extern papi_vector_t _niagara2_vector;
Packit 577717
Packit 577717
/* Synthetic events */
Packit 577717
int __int_setup_synthetic_event( int, hwd_control_state_t *, void * );
Packit 577717
uint64_t __int_get_synthetic_event( int, hwd_control_state_t *, void * );
Packit 577717
void __int_walk_synthetic_events_action_count( void );
Packit 577717
void __int_walk_synthetic_events_action_store( void );
Packit 577717
Packit 577717
/* Simple error handlers for convenience */
Packit 577717
#define __CHECK_ERR_DFLT(retval) \
Packit 577717
    if(retval != 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
Packit 577717
Packit 577717
#define __CHECK_ERR_NULL(retval) \
Packit 577717
    if(retval == NULL){ SUBDBG("RETVAL: NULL\n"); return PAPI_ECMP;}
Packit 577717
Packit 577717
#define __CHECK_ERR_PAPI(retval) \
Packit 577717
    if(retval != PAPI_OK){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
Packit 577717
Packit 577717
#define __CHECK_ERR_INVA(retval) \
Packit 577717
    if(retval != 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_EINVAL;}
Packit 577717
Packit 577717
#define __CHECK_ERR_NEGV(retval) \
Packit 577717
    if(retval < 0){ SUBDBG("RETVAL: %d\n", retval); return PAPI_ECMP;}
Packit 577717
Packit 577717
// PAPI defined variables
Packit 577717
extern papi_mdi_t _papi_hwi_system_info;
Packit 577717
Packit 577717
// The instance of libcpc
Packit 577717
static cpc_t *cpc = NULL;
Packit 577717
Packit 577717
typedef struct __t2_store
Packit 577717
{
Packit 577717
	// Number of counters for a processing unit
Packit 577717
	int npic;
Packit 577717
	int *pic_ntv_count;
Packit 577717
	int syn_evt_count;
Packit 577717
} __t2_store_t;
Packit 577717
Packit 577717
static __t2_store_t __t2_store;
Packit 577717
static char **__t2_ntv_events;
Packit 577717
Packit 577717
// Variables copied from the old component
Packit 577717
static int pid;
Packit 577717
Packit 577717
// Data types for utility functions
Packit 577717
Packit 577717
typedef struct __sol_processor_information
Packit 577717
{
Packit 577717
	int total;
Packit 577717
	int clock;
Packit 577717
} __sol_processor_information_t;
Packit 577717
Packit 577717
typedef struct __t2_pst_table
Packit 577717
{
Packit 577717
	int papi_pst;
Packit 577717
	char *ntv_event[MAX_COUNTERS];
Packit 577717
	int ntv_ctrs;
Packit 577717
	int ntv_opcode;
Packit 577717
} __t2_pst_table_t;
Packit 577717
Packit 577717
#define SYNTHETIC_EVENTS_SUPPORTED  1
Packit 577717
Packit 577717
/* This table structure holds all preset events */
Packit 577717
static __t2_pst_table_t __t2_table[] = {
Packit 577717
	/* Presets defined by generic_events(3CPC) */
Packit 577717
	{PAPI_L1_DCM,
Packit 577717
	 {"DC_miss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L1_ICM,
Packit 577717
	 {"IC_miss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L2_ICM,
Packit 577717
	 {"L2_imiss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_TLB_DM,
Packit 577717
	 {"DTLB_miss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_TLB_IM,
Packit 577717
	 {"ITLB_miss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_TLB_TL,
Packit 577717
	 {"TLB_miss", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L2_LDM,
Packit 577717
	 {"L2_dmiss_ld", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_BR_TKN,
Packit 577717
	 {"Br_taken", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_TOT_INS,
Packit 577717
	 {"Instr_cnt", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_LD_INS,
Packit 577717
	 {"Instr_ld", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_SR_INS,
Packit 577717
	 {"Instr_st", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_BR_INS,
Packit 577717
	 {"Br_completed", NULL}, 1, NOT_DERIVED},
Packit 577717
	/* Presets additionally found, should be checked twice */
Packit 577717
	{PAPI_BR_MSP,
Packit 577717
	 {"Br_taken", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_FP_INS,
Packit 577717
	 {"Instr_FGU_arithmetic", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_RES_STL,
Packit 577717
	 {"Idle_strands", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_SYC_INS,
Packit 577717
	 {"Atomics", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L2_ICR,
Packit 577717
	 {"CPU_ifetch_to_PCX", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L1_TCR,
Packit 577717
	 {"CPU_ld_to_PCX", NULL}, 1, NOT_DERIVED},
Packit 577717
	{PAPI_L2_TCW,
Packit 577717
	 {"CPU_st_to_PCX", NULL}, 1, NOT_DERIVED},
Packit 577717
	/* Derived presets found, should be checked twice */
Packit 577717
	{PAPI_L1_TCM,
Packit 577717
	 {"IC_miss", "DC_miss"}, 2, DERIVED_ADD},
Packit 577717
	{PAPI_BR_CN,
Packit 577717
	 {"Br_completed", "Br_taken"}, 2, DERIVED_ADD},
Packit 577717
	{PAPI_BR_PRC,
Packit 577717
	 {"Br_completed", "Br_taken"}, 2, DERIVED_SUB},
Packit 577717
	{PAPI_LST_INS,
Packit 577717
	 {"Instr_st", "Instr_ld"}, 2, DERIVED_ADD},
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	/* This preset does exist in order to support multiplexing */
Packit 577717
	{PAPI_TOT_CYC,
Packit 577717
	 {"_syn_cycles_elapsed", "DC_miss"}, 1, NOT_DERIVED},
Packit 577717
#endif
Packit 577717
	{0,
Packit 577717
	 {NULL, NULL}, 0, 0},
Packit 577717
};
Packit 577717
Packit 577717
hwi_search_t *preset_table;
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
enum
Packit 577717
{
Packit 577717
	SYNTHETIC_CYCLES_ELAPSED = 1,
Packit 577717
	SYNTHETIC_RETURN_ONE,
Packit 577717
	SYNTHETIC_RETURN_TWO,
Packit 577717
} __int_synthetic_enum;
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
typedef struct __int_synthetic_table
Packit 577717
{
Packit 577717
	int code;
Packit 577717
	char *name;
Packit 577717
} __int_syn_table_t;
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
static __int_syn_table_t __int_syn_table[] = {
Packit 577717
	{SYNTHETIC_CYCLES_ELAPSED, "_syn_cycles_elapsed"},
Packit 577717
	{SYNTHETIC_RETURN_ONE, "_syn_return_one"},
Packit 577717
	{SYNTHETIC_RETURN_TWO, "_syn_return_two"},
Packit 577717
	{-1, NULL},
Packit 577717
};
Packit 577717
#endif
Packit 577717
Packit 577717
////////////////////////////////////////////////////////////////////////////////
Packit 577717
/// PAPI HWD LAYER RELATED FUNCTIONS ///////////////////////////////////////////
Packit 577717
////////////////////////////////////////////////////////////////////////////////
Packit 577717
Packit 577717
/* DESCRIPTION:
Packit 577717
 * -----------------------------------------------------------------------------
Packit 577717
 * Functions in this section are related to the PAPI hardware dependend layer,
Packit 577717
 * also known as "HWD". In this case the HWD layer is the interface from PAPI
Packit 577717
 * to libcpc 2/Solaris 10.
Packit 577717
 ******************************************************************************/
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_set_domain( hwd_control_state_t * ctrl, int domain )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Clean and set the new flag for each counter */
Packit 577717
Packit 577717
	for ( i = 0; i < MAX_COUNTERS; i++ ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Setting flags for PIC#%d, old value: %p\n",
Packit 577717
				__func__, i, ctrl->flags[i] );
Packit 577717
#endif
Packit 577717
Packit 577717
		ctrl->flags[i] &= ~( CPC_COUNTING_DOMAINS );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: +++                      cleaned value: %p\n",
Packit 577717
				__func__, ctrl->flags[i] );
Packit 577717
#endif
Packit 577717
Packit 577717
		ctrl->flags[i] |= __cpc_domain_translator( domain );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: +++                      new value: %p\n",
Packit 577717
				__func__, ctrl->flags[i] );
Packit 577717
#endif
Packit 577717
	}
Packit 577717
Packit 577717
	/* Recreate the set */
Packit 577717
	__CHECK_ERR_PAPI( __cpc_recreate_set( ctrl ) );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: Option #%d requested\n", __func__, code );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Only these options are handled which are handled in PAPI_set_opt, as many
Packit 577717
	   of the left out options are not settable, like PAPI_MAX_CPUS. */
Packit 577717
Packit 577717
	switch ( code ) {
Packit 577717
	case PAPI_DEFDOM:
Packit 577717
		/* From papi.h: Domain for all new eventsets. Takes non-NULL option
Packit 577717
		   pointer. */
Packit 577717
Packit 577717
		_niagara2_vector.cmp_info.default_domain = option->domain.domain;
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	case PAPI_DOMAIN:
Packit 577717
		/* From papi.h: Domain for an eventset */
Packit 577717
Packit 577717
		return _niagara2_set_domain( ctx, option->domain.domain );
Packit 577717
	case PAPI_DEFGRN:
Packit 577717
		/* From papi.h: Granularity for all new eventsets */
Packit 577717
Packit 577717
		_niagara2_vector.cmp_info.default_granularity =
Packit 577717
			option->granularity.granularity;
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	case PAPI_GRANUL:
Packit 577717
		/* From papi.h: Granularity for an eventset */
Packit 577717
Packit 577717
		/* Only supported granularity is PAPI_GRN_THREAD */
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	case PAPI_DEF_MPX_NS:
Packit 577717
		/* From papi.h: Multiplexing/overflowing interval in ns, same as
Packit 577717
		   PAPI_DEF_ITIMER_NS */
Packit 577717
Packit 577717
		/* From the old component */
Packit 577717
		option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: PAPI_DEF_MPX_NS, option->itimer.ns=%d\n",
Packit 577717
				__func__, option->itimer.ns );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	case PAPI_DEF_ITIMER:	 // IN THE OLD COMPONENT // USED
Packit 577717
		/* From papi.h: Option to set the type of itimer used in both software
Packit 577717
		   multiplexing, overflowing and profiling */
Packit 577717
Packit 577717
		/* These tests are taken from the old component. For Solaris 10 the
Packit 577717
		   same rules apply as documented in getitimer(2). */
Packit 577717
Packit 577717
		if ( ( option->itimer.itimer_num == ITIMER_REAL ) &&
Packit 577717
			 ( option->itimer.itimer_sig != SIGALRM ) ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_REAL needs SIGALRM\n",
Packit 577717
					__func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
			return PAPI_EINVAL;
Packit 577717
		}
Packit 577717
Packit 577717
Packit 577717
		if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) &&
Packit 577717
			 ( option->itimer.itimer_sig != SIGVTALRM ) ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_VIRTUAL needs SIGVTALRM\n",
Packit 577717
					__func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
			return PAPI_EINVAL;
Packit 577717
		}
Packit 577717
Packit 577717
Packit 577717
		if ( ( option->itimer.itimer_num == ITIMER_PROF ) &&
Packit 577717
			 ( option->itimer.itimer_sig != SIGPROF ) ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: PAPI_DEF_ITIMER, ITIMER_PROF needs SIGPROF\n",
Packit 577717
					__func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
			return PAPI_EINVAL;
Packit 577717
		}
Packit 577717
Packit 577717
Packit 577717
		/* As in the old component defined, timer values below 0 are NOT
Packit 577717
		   filtered out, but timer values greater than 0 are rounded, either to
Packit 577717
		   a value which is at least itimer_res_ns or padded to a multiple of
Packit 577717
		   itimer_res_ns. */
Packit 577717
Packit 577717
		if ( option->itimer.ns > 0 ) {
Packit 577717
			option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: PAPI_DEF_ITIMER, option->itimer.ns=%d\n",
Packit 577717
					__func__, option->itimer.ns );
Packit 577717
#endif
Packit 577717
		}
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	case PAPI_DEF_ITIMER_NS:	// IN THE OLD COMPONENT // USED
Packit 577717
		/* From papi.h: Multiplexing/overflowing interval in ns, same as
Packit 577717
		   PAPI_DEF_MPX_NS */
Packit 577717
Packit 577717
		/* From the old component */
Packit 577717
		option->itimer.ns = __sol_get_itimer_ns( option->itimer.ns );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: PAPI_DEF_ITIMER_NS, option->itimer.ns=%d\n",
Packit 577717
				__func__, option->itimer.ns );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Option not found\n", __func__ );
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* This place should never be reached */
Packit 577717
	return PAPI_EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
_niagara2_dispatch_timer( int signal, siginfo_t * si, void *info )
Packit 577717
{
Packit 577717
	EventSetInfo_t *ESI = NULL;
Packit 577717
	ThreadInfo_t *thread = NULL;
Packit 577717
	int overflow_vector = 0;
Packit 577717
	hwd_control_state_t *ctrl = NULL;
Packit 577717
	long_long results[MAX_COUNTERS];
Packit 577717
	int i;
Packit 577717
	// Hint from perf_events.c
Packit 577717
	int cidx = _niagara2_vector.cmp_info.CmpIdx;
Packit 577717
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: Overflow handler called by signal #%d\n", __func__,
Packit 577717
			signal );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* From the old component */
Packit 577717
	thread = _papi_hwi_lookup_thread( 0 );
Packit 577717
	ESI = ( EventSetInfo_t * ) thread->running_eventset[cidx];
Packit 577717
Packit 577717
	/* From the old component, modified */
Packit 577717
	// 
Packit 577717
	if ( ESI == NULL || ESI->master != thread || ESI->ctl_state == NULL ||
Packit 577717
		 ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Problems with ESI, not necessarily serious\n",
Packit 577717
				__func__ );
Packit 577717
Packit 577717
		if ( ESI == NULL ) {
Packit 577717
			SUBDBG( " -> %s: +++ ESI is NULL\n", __func__ );
Packit 577717
		}
Packit 577717
Packit 577717
		if ( ESI->master != thread ) {
Packit 577717
			SUBDBG( " -> %s: +++ Thread mismatch, ESI->master=%#x thread=%#x\n",
Packit 577717
					__func__, ESI->master, thread );
Packit 577717
		}
Packit 577717
Packit 577717
		if ( ESI->ctl_state == NULL ) {
Packit 577717
			SUBDBG( " -> %s: +++ Counter state invalid\n", __func__ );
Packit 577717
		}
Packit 577717
Packit 577717
		if ( ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
Packit 577717
			SUBDBG
Packit 577717
				( " -> %s: +++ Overflow flag missing, ESI->overflow.flags=%#x\n",
Packit 577717
				  __func__, ESI->overflow.flags );
Packit 577717
		}
Packit 577717
#endif
Packit 577717
Packit 577717
		return;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	printf( " -> %s: Preconditions valid, trying to read counters\n",
Packit 577717
			__func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	ctrl = ESI->ctl_state;
Packit 577717
Packit 577717
	if ( _niagara2_read
Packit 577717
		 ( ctrl, ctrl, ( long_long ** ) & results, NOT_A_PAPI_HWD_READ )
Packit 577717
		 != PAPI_OK ) {
Packit 577717
		/* Failure */
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		printf( "%s: Failed to read counters\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return;
Packit 577717
	} else {
Packit 577717
		/* Success */
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Counters read\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Iterate over all available counters in order to detect which counter
Packit 577717
		   overflowed (counter value should be 0 if an hw overflow happened),
Packit 577717
		   store the position in the overflow_vector, calculte the offset and
Packit 577717
		   shift (value range signed long long vs. unsigned long long). */
Packit 577717
		for ( i = 0; i < ctrl->count; i++ ) {
Packit 577717
			if ( results[i] >= 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
				SUBDBG( " -> %s: Overflow detected at PIC #%d\n", __func__, i );
Packit 577717
#endif
Packit 577717
Packit 577717
				/* Set the bit in the overflow_vector */
Packit 577717
				overflow_vector = overflow_vector | ( 1 << i );
Packit 577717
Packit 577717
				/* hoose which method to use depending on the overflow signal. */
Packit 577717
				if ( signal == SIGEMT ) {
Packit 577717
					/* Store the counter value, but only if we have a real *
Packit 577717
					   hardware overflow counting with libcpc/SIGEMT. */
Packit 577717
					ctrl->preset[i] = UINT64_MAX - ctrl->threshold[i];
Packit 577717
					ctrl->hangover[i] += ctrl->threshold[i];
Packit 577717
				} else {
Packit 577717
					/* Push the value back, this time PAPI does the work. This is
Packit 577717
					   software overflow handling. */
Packit 577717
					cpc_request_preset( cpc, ctrl->idx[i], ctrl->result[i] );
Packit 577717
				}
Packit 577717
			} else {
Packit 577717
#ifdef DEBUG
Packit 577717
				SUBDBG( " -> %s: No overflow detected at PIC #%d, value=%ld\n",
Packit 577717
						__func__, i, results[i] );
Packit 577717
#endif
Packit 577717
Packit 577717
				/* Save the results read from the counter as we can not store the
Packit 577717
				   temporary value in hardware or libcpc. */
Packit 577717
				if ( signal == SIGEMT ) {
Packit 577717
					ctrl->preset[i] += results[i];
Packit 577717
					ctrl->hangover[i] = results[i];
Packit 577717
				}
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Restarting set to push values back\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Push all values back to the counter as preset */
Packit 577717
		cpc_set_restart( cpc, ctrl->set );
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Passing overflow to PAPI with overflow_vector=%p\n",
Packit 577717
			__func__, overflow_vector );
Packit 577717
#endif
Packit 577717
Packit 577717
	{
Packit 577717
		/* hw is used as pointer in the dispatching routine of PAPI and might be
Packit 577717
		   changed. For safety it is not a pseudo pointer to NULL. */
Packit 577717
		int hw;
Packit 577717
Packit 577717
		if ( signal == SIGEMT ) {
Packit 577717
			/* This is a hardware overflow */
Packit 577717
			hw = 1;
Packit 577717
			_papi_hwi_dispatch_overflow_signal( ctrl, ( caddr_t )
Packit 577717
												_niagara2_get_overflow_address
Packit 577717
												( info ), &hw, overflow_vector,
Packit 577717
												1, &thread, ESI->CmpIdx );
Packit 577717
		} else {
Packit 577717
			/* This is a software overflow */
Packit 577717
			hw = 0;
Packit 577717
			_papi_hwi_dispatch_overflow_signal( ctrl, ( caddr_t )
Packit 577717
												_niagara2_get_overflow_address
Packit 577717
												( info ), &hw, overflow_vector,
Packit 577717
												1, &thread, ESI->CmpIdx );
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
static inline void *
Packit 577717
_niagara2_get_overflow_address( void *context )
Packit 577717
{
Packit 577717
	ucontext_t *ctx = ( ucontext_t * ) context;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return ( void * ) ctx->uc_mcontext.gregs[REG_PC];
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Although the created set in this function will be destroyed by 
Packit 577717
 * _papi_update_control_state later, at least the functionality of the
Packit 577717
 * underlying CPU driver will be tested completly.
Packit 577717
 */
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_init_control_state( hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	// cpc_seterrhndlr(cpc, myapp_errfn);
Packit 577717
Packit 577717
	/* Clear the buffer */
Packit 577717
	if ( ctrl->counter_buffer != NULL ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Cleaning buffer\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		cpc_buf_destroy( cpc, ctrl->counter_buffer );
Packit 577717
		ctrl->counter_buffer = NULL;
Packit 577717
	}
Packit 577717
Packit 577717
	/* Clear the set */
Packit 577717
	if ( ctrl->set != NULL ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Cleaning set\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		cpc_set_destroy( cpc, ctrl->set );
Packit 577717
		ctrl->set = NULL;
Packit 577717
	}
Packit 577717
Packit 577717
	/* Indicate this idx has no request associated, this counter is unused. */
Packit 577717
	for ( i = 0; i < MAX_COUNTERS; i++ ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Cleaning counter state #%d\n", __func__, i );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Indicate missing setup values */
Packit 577717
		ctrl->idx[i] = EVENT_NOT_SET;
Packit 577717
		ctrl->code[i].event_code = EVENT_NOT_SET;
Packit 577717
Packit 577717
		/* No flags yet set, this is for overflow and binding */
Packit 577717
		ctrl->flags[i] = 0;
Packit 577717
Packit 577717
		/* Preset value for counting results */
Packit 577717
		ctrl->preset[i] = DEFAULT_CNTR_PRESET;
Packit 577717
Packit 577717
		/* Needed for overflow handling, will be set later */
Packit 577717
		ctrl->threshold[i] = 0;
Packit 577717
		ctrl->hangover[i] = 0;
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
		ctrl->syn_hangover[i] = 0;
Packit 577717
#endif
Packit 577717
	}
Packit 577717
Packit 577717
	/* No counters active in this set */
Packit 577717
	ctrl->count = 0;
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	ctrl->syn_count = 0;
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_init_component( int cidx )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Create an instance of libcpc */
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Trying to initalize libcpc\n", __func__ );
Packit 577717
#endif
Packit 577717
	cpc = cpc_open( CPC_VER_CURRENT );
Packit 577717
	__CHECK_ERR_NULL( cpc );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Registering libcpc error handler\n", __func__ );
Packit 577717
#endif
Packit 577717
	cpc_seterrhndlr( cpc, __cpc_error_handler );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Detecting supported PICs", __func__ );
Packit 577717
#endif
Packit 577717
	__t2_store.npic = cpc_npic( cpc );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Storing component index, cidx=%d\n", __func__, cidx );
Packit 577717
#endif
Packit 577717
	_niagara2_vector.cmp_info.CmpIdx = cidx;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Gathering system information for PAPI\n", __func__ );
Packit 577717
#endif
Packit 577717
	/* Store system info in central data structure */
Packit 577717
	__CHECK_ERR_PAPI( _niagara2_get_system_info( &_papi_hwi_system_info ) );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Initializing locks\n", __func__ );
Packit 577717
#endif
Packit 577717
	/* Set up the lock after initialization */
Packit 577717
	_niagara2_lock_init(  );
Packit 577717
Packit 577717
	// Copied from the old component, _papi_init_component()
Packit 577717
	SUBDBG( "Found %d %s %s CPUs at %d Mhz.\n",
Packit 577717
			_papi_hwi_system_info.hw_info.totalcpus,
Packit 577717
			_papi_hwi_system_info.hw_info.vendor_string,
Packit 577717
			_papi_hwi_system_info.hw_info.model_string,
Packit 577717
			_papi_hwi_system_info.hw_info.cpu_max_mhz );
Packit 577717
Packit 577717
	/* Build native event table */
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Building native event table\n", __func__ );
Packit 577717
#endif
Packit 577717
	__CHECK_ERR_PAPI( __cpc_build_ntv_table(  ) );
Packit 577717
Packit 577717
	/* Build preset event table */
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Building PAPI preset table\n", __func__ );
Packit 577717
#endif
Packit 577717
	__CHECK_ERR_PAPI( __cpc_build_pst_table(  ) );
Packit 577717
Packit 577717
	/* Register presets and finish event related setup */
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Registering presets in PAPI\n", __func__ );
Packit 577717
#endif
Packit 577717
	__CHECK_ERR_PAPI( _papi_hwi_setup_all_presets( preset_table, NULL ) );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Everything is ok */
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
_niagara2_lock_init( void )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Copied from old component, lock_init() */
Packit 577717
	memset( lock, 0x0, sizeof ( rwlock_t ) * PAPI_MAX_LOCK );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
Packit 577717
{
Packit 577717
	int event_code = EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	if ( event_code >= 0 &&
Packit 577717
		 event_code <= _niagara2_vector.cmp_info.num_native_events ) {
Packit 577717
		return PAPI_ENOEVNT;
Packit 577717
	}
Packit 577717
Packit 577717
	bits->event_code = event_code;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* libcpc offers no descriptions, just a link to the reference manual */
Packit 577717
	return _niagara2_ntv_code_to_name( EventCode, ntv_descr, len );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len )
Packit 577717
{
Packit 577717
	int event_code = EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	if ( event_code >= 0 &&
Packit 577717
		 event_code <= _niagara2_vector.cmp_info.num_native_events ) {
Packit 577717
		strlcpy( ntv_name, __t2_ntv_events[event_code], len );
Packit 577717
Packit 577717
		if ( strlen( __t2_ntv_events[event_code] ) > len - 1 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
					__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
			/* It's not a real error, but at least a hint */
Packit 577717
			return PAPI_EBUF;
Packit 577717
		}
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_ENOEVNT;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_ntv_enum_events( unsigned int *EventCode, int modifier )
Packit 577717
{
Packit 577717
	/* This code is very similar to the code from the old component. */
Packit 577717
Packit 577717
	int event_code = *EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	if ( modifier == PAPI_ENUM_FIRST ) {
Packit 577717
		*EventCode = PAPI_NATIVE_MASK + 1;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	}
Packit 577717
Packit 577717
	/* The table needs to be shifted by one position (starting index 1), as PAPI
Packit 577717
	   expects native event codes not to be 0 (papi_internal.c:744). */
Packit 577717
Packit 577717
	if ( event_code >= 1 &&
Packit 577717
		 event_code <= _niagara2_vector.cmp_info.num_native_events - 1 ) {
Packit 577717
		*EventCode = *EventCode + 1;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_OK;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	// If nothing found report an error
Packit 577717
	return PAPI_ENOEVNT;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_read( hwd_context_t * ctx, hwd_control_state_t * ctrl,
Packit 577717
				long_long ** events, int flags )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: called with flags=%p\n", __func__, flags );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Take a new sample from the PIC to the buffer */
Packit 577717
	__CHECK_ERR_DFLT( cpc_set_sample( cpc, ctrl->set, ctrl->counter_buffer ) );
Packit 577717
Packit 577717
	/* Copy the buffer values from all active counters */
Packit 577717
	for ( i = 0; i < ctrl->count; i++ ) {
Packit 577717
		/* Retrieve the counting results of libcpc */
Packit 577717
		__CHECK_ERR_DFLT( cpc_buf_get( cpc, ctrl->counter_buffer, ctrl->idx[i],
Packit 577717
									   &ctrl->result[i] ) );
Packit 577717
Packit 577717
		/* As libcpc uses uint64_t and PAPI uses int64_t, we need to normalize
Packit 577717
		   the result back to a value that PAPI can handle, otherwise the result
Packit 577717
		   is not usable as its in the negative range of int64_t and the result
Packit 577717
		   becomes useless for PAPI. */
Packit 577717
		if ( ctrl->threshold[i] > 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Normalizing result on PIC#%d to %lld\n",
Packit 577717
					__func__, i, ctrl->result[i] );
Packit 577717
#endif /* DEBUG */
Packit 577717
Packit 577717
			/* This shifts the retrieved value back to the PAPI value range */
Packit 577717
			ctrl->result[i] = ctrl->result[i] -
Packit 577717
				( UINT64_MAX - ctrl->threshold[i] ) - 1;
Packit 577717
Packit 577717
			/* Needed if called internally if a PIC didn't really overflow, but
Packit 577717
			   was programmed in the same set. */
Packit 577717
			if ( flags != NOT_A_PAPI_HWD_READ ) {
Packit 577717
				ctrl->result[i] = ctrl->hangover[i];
Packit 577717
			}
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Overflow scaling on PIC#%d:\n", __func__, i );
Packit 577717
			SUBDBG( " -> %s: +++ ctrl->result[%d]=%llu\n",
Packit 577717
					__func__, i, ctrl->result[i] );
Packit 577717
			SUBDBG( " -> %s: +++ ctrl->threshold[%d]=%lld\n",
Packit 577717
					__func__, i, ctrl->threshold[i] );
Packit 577717
			SUBDBG( " -> %s: +++ ctrl->hangover[%d]=%lld\n",
Packit 577717
					__func__, i, ctrl->hangover[i] );
Packit 577717
#endif
Packit 577717
		}
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: +++ ctrl->result[%d]=%llu\n",
Packit 577717
				__func__, i, ctrl->result[i] );
Packit 577717
#endif
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	{
Packit 577717
		int i;
Packit 577717
		const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
Packit 577717
			- __t2_store.syn_evt_count;
Packit 577717
Packit 577717
		for ( i = 0; i < ctrl->count; i++ ) {
Packit 577717
			if ( ctrl->code[i].event_code >= syn_barrier ) {
Packit 577717
				ctrl->result[i] =
Packit 577717
					__int_get_synthetic_event( ctrl->code[i].event_code
Packit 577717
											   - syn_barrier, ctrl, &i );
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Pass the address of the results back to the calling function */
Packit 577717
	*events = ( long_long * ) & ctrl->result[0];
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING: %s\n", "_papi_read" );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* This does a restart of the whole set, setting the internal counters back
Packit 577717
	   to the value passed as preset of the last call of cpc_set_add_request or
Packit 577717
	   cpc_request_preset. */
Packit 577717
	cpc_set_restart( cpc, ctrl->set );
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	{
Packit 577717
		const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
Packit 577717
			- __t2_store.syn_evt_count;
Packit 577717
		int i;
Packit 577717
Packit 577717
		if ( ctrl->syn_count > 0 ) {
Packit 577717
			for ( i = 0; i < MAX_COUNTERS; i++ ) {
Packit 577717
				if ( ctrl->code[i].event_code >= syn_barrier ) {
Packit 577717
Packit 577717
					ctrl->syn_hangover[i] +=
Packit 577717
						__int_get_synthetic_event( ctrl->code[i].event_code -
Packit 577717
												   syn_barrier, ctrl, &i );
Packit 577717
				}
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold )
Packit 577717
{
Packit 577717
	/* Seems not to be used. */
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING/LEAVING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_ENOSUPP;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
Packit 577717
{
Packit 577717
	hwd_control_state_t *ctrl = ESI->ctl_state;
Packit 577717
	struct sigaction sigact;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: Overflow handling for %#x on PIC#%d requested\n",
Packit 577717
			__func__, ctrl, EventIndex );
Packit 577717
	SUBDBG( " -> %s: ESI->overflow.flags=%#x\n\n", __func__, ctrl,
Packit 577717
			ESI->overflow.flags );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* If threshold > 0, then activate hardware overflow handling, otherwise
Packit 577717
	   disable it. */
Packit 577717
	if ( threshold > 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Activating overflow handling\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		ctrl->preset[EventIndex] = UINT64_MAX - threshold;
Packit 577717
		ctrl->threshold[EventIndex] = threshold;
Packit 577717
Packit 577717
		/* If SIGEMT is not yet enabled, enable it. In libcpc this means to re-
Packit 577717
		   recreate the used set. In order not to break PAPI operations only the
Packit 577717
		   event referred by EventIndex will be updated to use SIGEMT. */
Packit 577717
		if ( !( ctrl->flags[EventIndex] & CPC_OVF_NOTIFY_EMT ) ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Need to activate SIGEMT on PIC %d\n",
Packit 577717
					__func__, EventIndex );
Packit 577717
#endif
Packit 577717
Packit 577717
			/* Enable overflow handling */
Packit 577717
			if ( __cpc_enable_sigemt( ctrl, EventIndex ) != PAPI_OK ) {
Packit 577717
#ifdef DEBUG
Packit 577717
				SUBDBG( " -> %s: Activating SIGEMT failed for PIC %d\n",
Packit 577717
						__func__, EventIndex );
Packit 577717
#endif
Packit 577717
Packit 577717
				return PAPI_ESYS;
Packit 577717
			}
Packit 577717
		}
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: SIGEMT activated, will install signal handler\n",
Packit 577717
				__func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		// FIXME: Not really sure that this construct is working
Packit 577717
		return _papi_hwi_start_signal( SIGEMT, 1, 0 );
Packit 577717
Packit 577717
	} else {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Disabling overflow handling\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Resetting values which were used for overflow handling */
Packit 577717
		ctrl->preset[EventIndex] = DEFAULT_CNTR_PRESET;
Packit 577717
		ctrl->flags[EventIndex] &= ~( CPC_OVF_NOTIFY_EMT );
Packit 577717
		ctrl->threshold[EventIndex] = 0;
Packit 577717
		ctrl->hangover[EventIndex] = 0;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s:ctrl->preset[%d]=%d, ctrl->flags[%d]=%p\n",
Packit 577717
				__func__, EventIndex, ctrl->preset[EventIndex],
Packit 577717
				EventIndex, ctrl->flags[EventIndex] );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Recreate the undelying set and disable the signal handler */
Packit 577717
		__CHECK_ERR_PAPI( __cpc_recreate_set( ctrl ) );
Packit 577717
		__CHECK_ERR_PAPI( _papi_hwi_stop_signal( SIGEMT ) );
Packit 577717
	}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_shutdown( hwd_context_t * ctx )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	cpc_buf_destroy( cpc, ctx->counter_buffer );
Packit 577717
	cpc_set_destroy( cpc, ctx->set );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_shutdown_global( void )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Free allocated memory */
Packit 577717
Packit 577717
	// papi_calloc in __cpc_build_ntv_table
Packit 577717
	papi_free( __t2_store.pic_ntv_count );
Packit 577717
	// papi_calloc in __cpc_build_ntv_table
Packit 577717
	papi_free( __t2_ntv_events );
Packit 577717
	// papi_calloc in __cpc_build_pst_table
Packit 577717
	papi_free( preset_table );
Packit 577717
Packit 577717
	/* Shutdown libcpc */
Packit 577717
Packit 577717
	// cpc_open in _papi_init_component
Packit 577717
	cpc_close( cpc );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_start( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: Starting EventSet %p\n", __func__, ctrl );
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	{
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Event count: ctrl->count=%d, ctrl->syn_count=%d\n",
Packit 577717
				__func__, ctrl->count, ctrl->syn_count );
Packit 577717
#endif
Packit 577717
Packit 577717
		if ( ctrl->count > 0 && ctrl->count == ctrl->syn_count ) {
Packit 577717
			ctrl->idx[0] = cpc_set_add_request( cpc, ctrl->set, "Instr_cnt",
Packit 577717
												ctrl->preset[0], ctrl->flags[0],
Packit 577717
												0, NULL );
Packit 577717
			ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	{
Packit 577717
		int i;
Packit 577717
Packit 577717
		for ( i = 0; i < MAX_COUNTERS; i++ ) {
Packit 577717
			SUBDBG( " -> %s: Flags for PIC#%d: ctrl->flags[%d]=%d\n", __func__,
Packit 577717
					i, i, ctrl->flags[i] );
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
	__CHECK_ERR_DFLT( cpc_bind_curlwp( cpc, ctrl->set, CPC_BIND_LWP_INHERIT ) );
Packit 577717
Packit 577717
	/* Ensure the set is working properly */
Packit 577717
	retval = cpc_set_sample( cpc, ctrl->set, ctrl->counter_buffer );
Packit 577717
Packit 577717
	if ( retval != 0 ) {
Packit 577717
		printf( "%s: cpc_set_sample failed, return=%d, errno=%d\n",
Packit 577717
				__func__, retval, errno );
Packit 577717
		return PAPI_ECMP;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_stop( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	__CHECK_ERR_DFLT( cpc_unbind( cpc, ctrl->set ) );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_update_control_state( hwd_control_state_t * ctrl,
Packit 577717
								NativeInfo_t * native, int count,
Packit 577717
								hwd_context_t * ctx )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Delete everything as we can't change an existing set */
Packit 577717
	if ( ctrl->counter_buffer != NULL ) {
Packit 577717
		__CHECK_ERR_DFLT( cpc_buf_destroy( cpc, ctrl->counter_buffer ) );
Packit 577717
	}
Packit 577717
Packit 577717
	if ( ctrl->set != NULL ) {
Packit 577717
		__CHECK_ERR_DFLT( cpc_set_destroy( cpc, ctrl->set ) );
Packit 577717
	}
Packit 577717
Packit 577717
	for ( i = 0; i < MAX_COUNTERS; i++ ) {
Packit 577717
		ctrl->idx[i] = EVENT_NOT_SET;
Packit 577717
	}
Packit 577717
Packit 577717
	/* New setup */
Packit 577717
Packit 577717
	ctrl->set = cpc_set_create( cpc );
Packit 577717
	__CHECK_ERR_NULL( ctrl->set );
Packit 577717
Packit 577717
	ctrl->count = count;
Packit 577717
	ctrl->syn_count = 0;
Packit 577717
Packit 577717
	for ( i = 0; i < count; i++ ) {
Packit 577717
		/* Store the active event */
Packit 577717
		ctrl->code[i].event_code = native[i].ni_event & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
		ctrl->flags[i] = __cpc_domain_translator( PAPI_DOM_USER );
Packit 577717
		ctrl->preset[i] = DEFAULT_CNTR_PRESET;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG
Packit 577717
			( " -> %s: EventSet@%p/PIC#%d - ntv request >>%s<< (%d), flags=%#x\n",
Packit 577717
			  __func__, ctrl, i, __t2_ntv_events[ctrl->code[i].event_code],
Packit 577717
			  ctrl->code[i].event_code, ctrl->flags[i] );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Store the counter position (???) */
Packit 577717
		native[i].ni_position = i;
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
		{
Packit 577717
			int syn_code = ctrl->code[i].event_code -
Packit 577717
				( _niagara2_vector.cmp_info.num_native_events
Packit 577717
				  - __t2_store.syn_evt_count ) - 1;
Packit 577717
Packit 577717
			/* Check if the event code is bigger than the CPC provided events. */
Packit 577717
			if ( syn_code >= 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
				SUBDBG
Packit 577717
					( " -> %s: Adding synthetic event %#x (%s) on position %d\n",
Packit 577717
					  __func__, native[i].ni_event,
Packit 577717
					  __t2_ntv_events[ctrl->code[i].event_code], i );
Packit 577717
#endif
Packit 577717
Packit 577717
				/* Call the setup routine */
Packit 577717
				__int_setup_synthetic_event( syn_code, ctrl, NULL );
Packit 577717
Packit 577717
				/* Clean the hangover count as this event is new */
Packit 577717
				ctrl->syn_hangover[i] = 0;
Packit 577717
Packit 577717
				/* Register this event as being synthetic, as an event set only
Packit 577717
				   based on synthetic events can not be actived through libcpc */
Packit 577717
				ctrl->syn_count++;
Packit 577717
Packit 577717
				/* Jump to next iteration */
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
		}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Adding native event %#x (%s) on position %d\n",
Packit 577717
				__func__, native[i].ni_event,
Packit 577717
				__t2_ntv_events[ctrl->code[i].event_code], i );
Packit 577717
#endif
Packit 577717
Packit 577717
		/* Pass the event as request to libcpc */
Packit 577717
		ctrl->idx[i] = cpc_set_add_request( cpc, ctrl->set,
Packit 577717
											__t2_ntv_events[ctrl->code[i].
Packit 577717
															event_code],
Packit 577717
											ctrl->preset[i], ctrl->flags[i], 0,
Packit 577717
											NULL );
Packit 577717
		__CHECK_ERR_NEGV( ctrl->idx[i] );
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	if ( i == 0 ) {
Packit 577717
		SUBDBG( " -> %s: nothing added\n", __func__ );
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
	ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
Packit 577717
	__CHECK_ERR_NULL( ctrl->counter_buffer );
Packit 577717
Packit 577717
	/* Finished the new setup */
Packit 577717
Packit 577717
	/* Linking to context (same data type by typedef!) */
Packit 577717
	ctx = ctrl;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_niagara2_update_shlib_info( papi_mdi_t *mdi )
Packit 577717
{
Packit 577717
	char *file = "/proc/self/map";
Packit 577717
	char *resolve_pattern = "/proc/self/path/%s";
Packit 577717
Packit 577717
	char lastobject[PRMAPSZ];
Packit 577717
	char link[PAPI_HUGE_STR_LEN];
Packit 577717
	char path[PAPI_HUGE_STR_LEN];
Packit 577717
Packit 577717
	prmap_t mapping;
Packit 577717
Packit 577717
	int fd, count = 0, total = 0, position = -1, first = 1;
Packit 577717
	caddr_t t_min, t_max, d_min, d_max;
Packit 577717
Packit 577717
	PAPI_address_map_t *pam, *cur;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	fd = open( file, O_RDONLY );
Packit 577717
Packit 577717
	if ( fd == -1 ) {
Packit 577717
		return PAPI_ESYS;
Packit 577717
	}
Packit 577717
Packit 577717
	memset( lastobject, 0, PRMAPSZ );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Preprocessing memory maps from procfs\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Search through the list of mappings in order to identify a) how many
Packit 577717
	   mappings are available and b) how many unique mappings are available. */
Packit 577717
	while ( read( fd, &mapping, sizeof ( prmap_t ) ) > 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Found a new memory map entry\n", __func__ );
Packit 577717
#endif
Packit 577717
		/* Another entry found, just the total count of entries. */
Packit 577717
		total++;
Packit 577717
Packit 577717
		/* Is the mapping accessible and not anonymous? */
Packit 577717
		if ( mapping.pr_mflags & ( MA_READ | MA_WRITE | MA_EXEC ) &&
Packit 577717
			 !( mapping.pr_mflags & MA_ANON ) ) {
Packit 577717
			/* Test if a new library has been found. If a new library has been
Packit 577717
			   found a new entry needs to be counted. */
Packit 577717
			if ( strcmp( lastobject, mapping.pr_mapname ) != 0 ) {
Packit 577717
				strncpy( lastobject, mapping.pr_mapname, PRMAPSZ );
Packit 577717
				count++;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
				SUBDBG( " -> %s: Memory mapping entry valid for %s\n", __func__,
Packit 577717
						mapping.pr_mapname );
Packit 577717
#endif
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Preprocessing done, starting to analyze\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
	/* Start from the beginning, now fill in the found mappings */
Packit 577717
	if ( lseek( fd, 0, SEEK_SET ) == -1 ) {
Packit 577717
		return PAPI_ESYS;
Packit 577717
	}
Packit 577717
Packit 577717
	memset( lastobject, 0, PRMAPSZ );
Packit 577717
Packit 577717
	/* Allocate memory */
Packit 577717
	pam =
Packit 577717
		( PAPI_address_map_t * ) papi_calloc( count,
Packit 577717
											  sizeof ( PAPI_address_map_t ) );
Packit 577717
Packit 577717
	while ( read( fd, &mapping, sizeof ( prmap_t ) ) > 0 ) {
Packit 577717
Packit 577717
		if ( mapping.pr_mflags & MA_ANON ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG
Packit 577717
				( " -> %s: Anonymous mapping (MA_ANON) found for %s, skipping\n",
Packit 577717
				  __func__, mapping.pr_mapname );
Packit 577717
#endif
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
Packit 577717
		/* Check for a new entry */
Packit 577717
		if ( strcmp( mapping.pr_mapname, lastobject ) != 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Analyzing mapping for %s\n", __func__,
Packit 577717
					mapping.pr_mapname );
Packit 577717
#endif
Packit 577717
			cur = &( pam[++position] );
Packit 577717
			strncpy( lastobject, mapping.pr_mapname, PRMAPSZ );
Packit 577717
			snprintf( link, PAPI_HUGE_STR_LEN, resolve_pattern, lastobject );
Packit 577717
			memset( path, 0, PAPI_HUGE_STR_LEN );
Packit 577717
			readlink( link, path, PAPI_HUGE_STR_LEN );
Packit 577717
			strncpy( cur->name, path, PAPI_HUGE_STR_LEN );
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Resolved name for %s: %s\n", __func__,
Packit 577717
					mapping.pr_mapname, cur->name );
Packit 577717
#endif
Packit 577717
		}
Packit 577717
Packit 577717
		if ( mapping.pr_mflags & MA_READ ) {
Packit 577717
			/* Data (MA_WRITE) or text (MA_READ) segment? */
Packit 577717
			if ( mapping.pr_mflags & MA_WRITE ) {
Packit 577717
				cur->data_start = ( caddr_t ) mapping.pr_vaddr;
Packit 577717
				cur->data_end =
Packit 577717
					( caddr_t ) ( mapping.pr_vaddr + mapping.pr_size );
Packit 577717
Packit 577717
				if ( strcmp
Packit 577717
					 ( cur->name,
Packit 577717
					   _papi_hwi_system_info.exe_info.fullname ) == 0 ) {
Packit 577717
					_papi_hwi_system_info.exe_info.address_info.data_start =
Packit 577717
						cur->data_start;
Packit 577717
					_papi_hwi_system_info.exe_info.address_info.data_end =
Packit 577717
						cur->data_end;
Packit 577717
				}
Packit 577717
Packit 577717
				if ( first )
Packit 577717
					d_min = cur->data_start;
Packit 577717
				if ( first )
Packit 577717
					d_max = cur->data_end;
Packit 577717
Packit 577717
				if ( cur->data_start < d_min ) {
Packit 577717
					d_min = cur->data_start;
Packit 577717
				}
Packit 577717
Packit 577717
				if ( cur->data_end > d_max ) {
Packit 577717
					d_max = cur->data_end;
Packit 577717
				}
Packit 577717
			} else if ( mapping.pr_mflags & MA_EXEC ) {
Packit 577717
				cur->text_start = ( caddr_t ) mapping.pr_vaddr;
Packit 577717
				cur->text_end =
Packit 577717
					( caddr_t ) ( mapping.pr_vaddr + mapping.pr_size );
Packit 577717
Packit 577717
				if ( strcmp
Packit 577717
					 ( cur->name,
Packit 577717
					   _papi_hwi_system_info.exe_info.fullname ) == 0 ) {
Packit 577717
					_papi_hwi_system_info.exe_info.address_info.text_start =
Packit 577717
						cur->text_start;
Packit 577717
					_papi_hwi_system_info.exe_info.address_info.text_end =
Packit 577717
						cur->text_end;
Packit 577717
				}
Packit 577717
Packit 577717
				if ( first )
Packit 577717
					t_min = cur->text_start;
Packit 577717
				if ( first )
Packit 577717
					t_max = cur->text_end;
Packit 577717
Packit 577717
				if ( cur->text_start < t_min ) {
Packit 577717
					t_min = cur->text_start;
Packit 577717
				}
Packit 577717
Packit 577717
				if ( cur->text_end > t_max ) {
Packit 577717
					t_max = cur->text_end;
Packit 577717
				}
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
		first = 0;
Packit 577717
	}
Packit 577717
Packit 577717
	close( fd );
Packit 577717
Packit 577717
	/* During the walk of shared objects the upper and lower bound of the
Packit 577717
	   segments could be discovered. The bounds are stored in the PAPI info
Packit 577717
	   structure. The information is important for the profiling functions of
Packit 577717
	   PAPI. */
Packit 577717
Packit 577717
/* This variant would pass the addresses of all text and data segments 
Packit 577717
  _papi_hwi_system_info.exe_info.address_info.text_start = t_min;
Packit 577717
  _papi_hwi_system_info.exe_info.address_info.text_end = t_max;
Packit 577717
  _papi_hwi_system_info.exe_info.address_info.data_start = d_min;
Packit 577717
  _papi_hwi_system_info.exe_info.address_info.data_end = d_max;
Packit 577717
*/
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Analysis of memory maps done, results:\n", __func__ );
Packit 577717
	SUBDBG( " -> %s: text_start=%#x, text_end=%#x, text_size=%lld\n", __func__,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.text_start,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.text_end,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.text_end
Packit 577717
			- _papi_hwi_system_info.exe_info.address_info.text_start );
Packit 577717
	SUBDBG( " -> %s: data_start=%#x, data_end=%#x, data_size=%lld\n", __func__,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.data_start,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.data_end,
Packit 577717
			_papi_hwi_system_info.exe_info.address_info.data_end
Packit 577717
			- _papi_hwi_system_info.exe_info.address_info.data_start );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Store the map read and the total count of shlibs found */
Packit 577717
	_papi_hwi_system_info.shlib_info.map = pam;
Packit 577717
	_papi_hwi_system_info.shlib_info.count = count;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
//////////////////////////////////////////////////////////////////////////////////
Packit 577717
/// UTILITY FUNCTIONS FOR ACCESS TO LIBCPC AND SOLARIS /////////////////////////
Packit 577717
////////////////////////////////////////////////////////////////////////////////
Packit 577717
Packit 577717
/* DESCRIPTION:
Packit 577717
 * -----------------------------------------------------------------------------
Packit 577717
 * The following functions are for accessing libcpc 2 and Solaris related stuff
Packit 577717
 * needed for PAPI.
Packit 577717
 ******************************************************************************/
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_build_ntv_table( void )
Packit 577717
{
Packit 577717
	int i, tmp;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	__t2_store.pic_ntv_count = papi_calloc( __t2_store.npic, sizeof ( int ) );
Packit 577717
	__CHECK_ERR_NULL( __t2_store.pic_ntv_count );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Checking PICs for functionality\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	for ( i = 0; i < __t2_store.npic; i++ ) {
Packit 577717
		cpc_walk_events_pic( cpc, i, NULL, __cpc_walk_events_pic_action_count );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Found %d events on PIC#%d\n", __func__,
Packit 577717
				__t2_store.pic_ntv_count[i], i );
Packit 577717
#endif
Packit 577717
	}
Packit 577717
Packit 577717
	tmp = __t2_store.pic_ntv_count[0];
Packit 577717
Packit 577717
	/* There should be at least one counter... */
Packit 577717
	if ( tmp == 0 ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: PIC#0 has 0 events\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_ECMP;
Packit 577717
	}
Packit 577717
Packit 577717
	/* Check if all PICs have the same number of counters */
Packit 577717
	for ( i = 0; i < __t2_store.npic; i++ ) {
Packit 577717
		if ( __t2_store.pic_ntv_count[i] != tmp ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: PIC#%d has %d events, should have %d\n",
Packit 577717
					__func__, i, __t2_store.pic_ntv_count[i], tmp );
Packit 577717
#endif
Packit 577717
Packit 577717
			return PAPI_ECMP;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	/* Count synthetic events which add functionality to libcpc */
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	__t2_store.syn_evt_count = 0;
Packit 577717
	__int_walk_synthetic_events_action_count(  );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Store the count of events available in central data structure */
Packit 577717
#ifndef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	_niagara2_vector.cmp_info.num_native_events = __t2_store.pic_ntv_count[0];
Packit 577717
#else
Packit 577717
	_niagara2_vector.cmp_info.num_native_events =
Packit 577717
		__t2_store.pic_ntv_count[0] + __t2_store.syn_evt_count;
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
	/* Allocate memory for storing all events found, including the first empty
Packit 577717
	   slot */
Packit 577717
	__t2_ntv_events =
Packit 577717
		papi_calloc( _niagara2_vector.cmp_info.num_native_events + 1,
Packit 577717
					 sizeof ( char * ) );
Packit 577717
Packit 577717
	__t2_ntv_events[0] = "THIS IS A BUG!";
Packit 577717
Packit 577717
	tmp = 1;
Packit 577717
	cpc_walk_events_pic( cpc, 0, ( void * ) &tmp,
Packit 577717
						 __cpc_walk_events_pic_action_store );
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	__int_walk_synthetic_events_action_store(  );
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	for ( i = 1; i < __t2_store.pic_ntv_count[0]; i++ ) {
Packit 577717
		SUBDBG( " -> %s: Event #%d: %s\n", __func__, i, __t2_ntv_events[i] );
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* Return event code for event_name */
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_search_ntv_event( char *event_name, int *event_code )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	for ( i = 0; i < _niagara2_vector.cmp_info.num_native_events; i++ ) {
Packit 577717
		if ( strcmp( event_name, __t2_ntv_events[i] ) == 0 ) {
Packit 577717
			*event_code = i;
Packit 577717
			return PAPI_OK;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	return PAPI_ENOEVNT;
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_build_pst_table( void )
Packit 577717
{
Packit 577717
	int num_psts, i, j, event_code, pst_events;
Packit 577717
	hwi_search_t tmp;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	num_psts = 0;
Packit 577717
Packit 577717
	while ( __t2_table[num_psts].papi_pst != 0 ) {
Packit 577717
		num_psts++;
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Found %d presets\n", __func__, num_psts );
Packit 577717
#endif
Packit 577717
Packit 577717
	preset_table = papi_calloc( num_psts + 1, sizeof ( hwi_search_t ) );
Packit 577717
	__CHECK_ERR_NULL( preset_table );
Packit 577717
Packit 577717
	pst_events = 0;
Packit 577717
Packit 577717
	for ( i = 0; i < num_psts; i++ ) {
Packit 577717
		memset( &tmp, PAPI_NULL, sizeof ( tmp ) );
Packit 577717
Packit 577717
		/* Mark counters as unused. If they are needed, they will be overwritten
Packit 577717
		   later. See papi_preset.c:51 for more details. */
Packit 577717
		for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
Packit 577717
			tmp.data.native[j] = PAPI_NULL;
Packit 577717
		}
Packit 577717
Packit 577717
		tmp.event_code = __t2_table[i].papi_pst;
Packit 577717
		tmp.data.derived = __t2_table[i].ntv_opcode;
Packit 577717
		tmp.data.operation[0] = '\0';
Packit 577717
Packit 577717
		switch ( __t2_table[i].ntv_opcode ) {
Packit 577717
		case DERIVED_ADD:
Packit 577717
			tmp.data.operation[0] = '+';
Packit 577717
			break;
Packit 577717
		case DERIVED_SUB:
Packit 577717
			tmp.data.operation[0] = '-';
Packit 577717
			break;
Packit 577717
		}
Packit 577717
Packit 577717
		for ( j = 0; j < __t2_table[i].ntv_ctrs; j++ ) {
Packit 577717
			if ( __cpc_search_ntv_event
Packit 577717
				 ( __t2_table[i].ntv_event[j], &event_code )
Packit 577717
				 >= PAPI_OK ) {
Packit 577717
				tmp.data.native[j] = event_code;
Packit 577717
			} else {
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: pst row %d - event_code=%d\n",
Packit 577717
				__func__, i, tmp.event_code );
Packit 577717
		SUBDBG( " -> %s: pst row %d - data.derived=%d, data.operation=%c\n",
Packit 577717
				__func__, i, tmp.data.derived, tmp.data.operation[0] );
Packit 577717
		SUBDBG( " -> %s: pst row %d - native event codes:\n", __func__, i );
Packit 577717
		{
Packit 577717
			int d_i;
Packit 577717
Packit 577717
			for ( d_i = 0; d_i < PAPI_EVENTS_IN_DERIVED_EVENT; d_i++ ) {
Packit 577717
				SUBDBG( " -> %s: pst row %d - +++ data.native[%d]=%d\n",
Packit 577717
						__func__, i, d_i, tmp.data.native[d_i] );
Packit 577717
			}
Packit 577717
		}
Packit 577717
#endif
Packit 577717
Packit 577717
		memcpy( &preset_table[i], &tmp, sizeof ( tmp ) );
Packit 577717
Packit 577717
		pst_events++;
Packit 577717
	}
Packit 577717
Packit 577717
	// Check!
Packit 577717
	memset( &preset_table[num_psts], 0, sizeof ( hwi_search_t ) );
Packit 577717
Packit 577717
	_niagara2_vector.cmp_info.num_preset_events = pst_events;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_recreate_set( hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
	const int syn_barrier = _niagara2_vector.cmp_info.num_native_events
Packit 577717
		- __t2_store.syn_evt_count;
Packit 577717
#endif
Packit 577717
Packit 577717
	int i;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Destroy the old buffer and the old set if they exist, we need to do a full
Packit 577717
	   recreate as changing flags or events through libcpc is not possible */
Packit 577717
	if ( ctrl->counter_buffer != NULL ) {
Packit 577717
		__CHECK_ERR_DFLT( cpc_buf_destroy( cpc, ctrl->counter_buffer ) );
Packit 577717
	}
Packit 577717
Packit 577717
	if ( ctrl->set != NULL ) {
Packit 577717
		__CHECK_ERR_DFLT( cpc_set_destroy( cpc, ctrl->set ) );
Packit 577717
	}
Packit 577717
Packit 577717
	/* Create a new set */
Packit 577717
	ctrl->set = cpc_set_create( cpc );
Packit 577717
	__CHECK_ERR_NULL( ctrl->set );
Packit 577717
Packit 577717
	for ( i = 0; i < ctrl->count; i++ ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Adding native event %#x (%s) on position %d\n",
Packit 577717
				__func__, ctrl->code[i].event_code,
Packit 577717
				__t2_ntv_events[ctrl->code[i].event_code], i );
Packit 577717
		SUBDBG( " -> %s: Event setup: ctrl->code[%d].event_code=%#x\n",
Packit 577717
				__func__, i, ctrl->code[i].event_code );
Packit 577717
		SUBDBG( " -> %s: Event setup: ctrl->preset[%d]=%d\n",
Packit 577717
				__func__, i, ctrl->preset[i] );
Packit 577717
		SUBDBG( " -> %s: Event setup: ctrl->flags[%d]=%#x\n",
Packit 577717
				__func__, i, ctrl->flags[i] );
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
		/* Ensure that synthetic events are skipped */
Packit 577717
		if ( ctrl->code[i].event_code >= syn_barrier ) {
Packit 577717
#ifdef DEBUG
Packit 577717
			SUBDBG( " -> %s: Skipping counter %d, synthetic event found\n",
Packit 577717
					__func__, i );
Packit 577717
#endif
Packit 577717
Packit 577717
			/* Next iteration */
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
#endif
Packit 577717
Packit 577717
		ctrl->idx[i] = cpc_set_add_request( cpc, ctrl->set,
Packit 577717
											__t2_ntv_events[ctrl->code[i].
Packit 577717
															event_code],
Packit 577717
											ctrl->preset[i], ctrl->flags[i], 0,
Packit 577717
											NULL );
Packit 577717
		__CHECK_ERR_NEGV( ctrl->idx[i] );
Packit 577717
	}
Packit 577717
Packit 577717
	ctrl->counter_buffer = cpc_buf_create( cpc, ctrl->set );
Packit 577717
	__CHECK_ERR_NULL( ctrl->counter_buffer );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_domain_translator( const int papi_domain )
Packit 577717
{
Packit 577717
	int domain = 0;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
	SUBDBG( " -> %s: papi_domain=%d requested\n", __func__, papi_domain );
Packit 577717
#endif
Packit 577717
Packit 577717
	if ( papi_domain & PAPI_DOM_USER ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Domain PAPI_DOM_USER/CPC_COUNT_USER selected\n",
Packit 577717
				__func__ );
Packit 577717
#endif
Packit 577717
		domain |= CPC_COUNT_USER;
Packit 577717
	}
Packit 577717
Packit 577717
	if ( papi_domain & PAPI_DOM_KERNEL ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Domain PAPI_DOM_KERNEL/CPC_COUNT_SYSTEM selected\n",
Packit 577717
				__func__ );
Packit 577717
#endif
Packit 577717
		domain |= CPC_COUNT_SYSTEM;
Packit 577717
	}
Packit 577717
Packit 577717
	if ( papi_domain & PAPI_DOM_SUPERVISOR ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Domain PAPI_DOM_SUPERVISOR/CPC_COUNT_HV selected\n",
Packit 577717
				__func__ );
Packit 577717
#endif
Packit 577717
		domain |= CPC_COUNT_HV;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: domain=%d\n", __func__, domain );
Packit 577717
#endif
Packit 577717
Packit 577717
	return domain;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
__cpc_error_handler( const char *fn, int subcode, const char *fmt, va_list ap )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* From the libcpc manpages */
Packit 577717
	fprintf( stderr, "ERROR - libcpc error handler in %s() called!\n", fn );
Packit 577717
	vfprintf( stderr, fmt, ap );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
__cpc_enable_sigemt( hwd_control_state_t * ctrl, int position )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	if ( position >= MAX_COUNTERS ) {
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Position of the counter does not exist\n", __func__ );
Packit 577717
#endif
Packit 577717
Packit 577717
		return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
Packit 577717
	ctrl->flags[position] = ctrl->flags[position] | CPC_OVF_NOTIFY_EMT;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return __cpc_recreate_set( ctrl );
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
__cpc_walk_events_pic_action_count( void *arg, uint_t picno, const char *event )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	__t2_store.pic_ntv_count[picno]++;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG
Packit 577717
		( " -> %s: Found one native event on PIC#%d (now totally %d events)\n",
Packit 577717
		  __func__, picno, __t2_store.pic_ntv_count[picno] );
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
__cpc_walk_events_pic_action_store( void *arg, uint_t picno, const char *event )
Packit 577717
{
Packit 577717
	int *tmp = ( int * ) arg;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	__t2_ntv_events[*tmp] = papi_strdup( event );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( " -> %s: Native event >>%s<< registered\n",
Packit 577717
			__func__, __t2_ntv_events[*tmp] );
Packit 577717
#endif
Packit 577717
Packit 577717
	*tmp = *tmp + 1;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
static inline int
Packit 577717
__sol_get_processor_clock( void )
Packit 577717
{
Packit 577717
	processor_info_t pinfo;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	// Fetch information from the first processor in the system
Packit 577717
	if ( processor_info( getcpuid(  ), &pinfo ) == 0 ) {
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( " -> %s: Clock at %d MHz\n", __func__, pinfo.pi_clock );
Packit 577717
#endif
Packit 577717
Packit 577717
		return pinfo.pi_clock;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_ESYS;
Packit 577717
}
Packit 577717
Packit 577717
/* This function either increases the ns supplied to itimer_res_ns or pads it up
Packit 577717
 * to a multiple of itimer_res_ns if the value is bigger than itimer_res_ns.
Packit 577717
 *
Packit 577717
 * The source is taken from the old component.
Packit 577717
 */
Packit 577717
static inline int
Packit 577717
__sol_get_itimer_ns( int ns )
Packit 577717
{
Packit 577717
	if ( ns < _papi_os_info.itimer_res_ns ) {
Packit 577717
		return _papi_os_info.itimer_res_ns;
Packit 577717
	} else {
Packit 577717
		int leftover_ns = ns % _papi_os_info.itimer_res_ns;
Packit 577717
		return ns + leftover_ns;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
static inline lwpstatus_t *
Packit 577717
__sol_get_lwp_status( const pid_t pid, const lwpid_t lwpid )
Packit 577717
{
Packit 577717
	char *pattern = "/proc/%d/lwp/%d/lwpstatus";
Packit 577717
	char filename[PAPI_MIN_STR_LEN];
Packit 577717
	int fd;
Packit 577717
	static lwpstatus_t lwp;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	memset( &lwp, 0, sizeof ( lwp ) );
Packit 577717
	snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid, lwpid );
Packit 577717
Packit 577717
	fd = open( filename, O_RDONLY );
Packit 577717
	if ( fd == -1 )
Packit 577717
		return NULL;
Packit 577717
Packit 577717
	read( fd, ( void * ) &lwp, sizeof ( lwp ) );
Packit 577717
Packit 577717
	close( fd );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return &lw;;
Packit 577717
}
Packit 577717
Packit 577717
static inline psinfo_t *
Packit 577717
__sol_get_proc_info( const pid_t pid )
Packit 577717
{
Packit 577717
	char *pattern = "/proc/%d/psinfo";
Packit 577717
	char filename[PAPI_MIN_STR_LEN];
Packit 577717
	int fd;
Packit 577717
	static psinfo_t proc;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	memset( &proc, 0, sizeof ( proc ) );
Packit 577717
	snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid );
Packit 577717
Packit 577717
	fd = open( filename, O_RDONLY );
Packit 577717
	if ( fd == -1 )
Packit 577717
		return NULL;
Packit 577717
Packit 577717
	read( fd, ( void * ) &proc, sizeof ( proc ) );
Packit 577717
Packit 577717
	close( fd );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return &proc;
Packit 577717
}
Packit 577717
Packit 577717
static inline pstatus_t *
Packit 577717
__sol_get_proc_status( const pid_t pid )
Packit 577717
{
Packit 577717
	char *pattern = "/proc/%d/status";
Packit 577717
	char filename[PAPI_MIN_STR_LEN];
Packit 577717
	int fd;
Packit 577717
	static pstatus_t proc;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	memset( &proc, 0, sizeof ( proc ) );
Packit 577717
	snprintf( filename, PAPI_MIN_STR_LEN, pattern, pid );
Packit 577717
Packit 577717
	fd = open( filename, O_RDONLY );
Packit 577717
	if ( fd == -1 )
Packit 577717
		return NULL;
Packit 577717
Packit 577717
	read( fd, ( void * ) &proc, sizeof ( proc ) );
Packit 577717
Packit 577717
	close( fd );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	return &proc;
Packit 577717
}
Packit 577717
Packit 577717
/* This function handles synthetic events and returns their result. Synthetic 
Packit 577717
 * events are events retrieved from outside of libcpc, e.g. all events which
Packit 577717
 * can not be retrieved using cpc_set_add_request/cpc_buf_get. */
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
Packit 577717
uint64_t
Packit 577717
__int_get_synthetic_event( int code, hwd_control_state_t * ctrl, void *arg )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	switch ( code ) {
Packit 577717
	case SYNTHETIC_CYCLES_ELAPSED:
Packit 577717
		/* Return the count of ticks this set was bound. If a reset of the set
Packit 577717
		   has been executed the last count will be subtracted. */
Packit 577717
	{
Packit 577717
		int *i = ( int * ) arg;
Packit 577717
		return cpc_buf_tick( cpc,
Packit 577717
							 ctrl->counter_buffer ) - ctrl->syn_hangover[*i];
Packit 577717
	}
Packit 577717
	case SYNTHETIC_RETURN_ONE:
Packit 577717
		// The name says it - only for testing purposes.
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
		return 1;
Packit 577717
	case SYNTHETIC_RETURN_TWO:
Packit 577717
		// The name says it - only for testing purposes.
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
		return 2;
Packit 577717
	default:
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
		return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
Packit 577717
int
Packit 577717
__int_setup_synthetic_event( int code, hwd_control_state_t * ctrl, void *arg )
Packit 577717
{
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	switch ( code ) {
Packit 577717
	case SYNTHETIC_CYCLES_ELAPSED:
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
		return PAPI_OK;
Packit 577717
	default:
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
		SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
				__LINE__ );
Packit 577717
#endif
Packit 577717
		return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
Packit 577717
void
Packit 577717
__int_walk_synthetic_events_action_count( void )
Packit 577717
{
Packit 577717
	int i = 0;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	/* Count all synthetic events in __int_syn_table, the last event is marked
Packit 577717
	   with an event code of -1. */
Packit 577717
	while ( __int_syn_table[i].code != -1 ) {
Packit 577717
		__t2_store.syn_evt_count++;
Packit 577717
		i++;
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef SYNTHETIC_EVENTS_SUPPORTED
Packit 577717
Packit 577717
void
Packit 577717
__int_walk_synthetic_events_action_store( void )
Packit 577717
{
Packit 577717
	/* The first index of a synthetic event starts after last native event */
Packit 577717
	int i = 0;
Packit 577717
	int offset = _niagara2_vector.cmp_info.num_native_events + 1 -
Packit 577717
		__t2_store.syn_evt_count;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "ENTERING FUNCTION >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
Packit 577717
	while ( i < __t2_store.syn_evt_count ) {
Packit 577717
		__t2_ntv_events[i + offset] = papi_strdup( __int_syn_table[i].name );
Packit 577717
		i++;
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	SUBDBG( "LEAVING FUNCTION  >>%s<< at %s:%d\n", __func__, __FILE__,
Packit 577717
			__LINE__ );
Packit 577717
#endif
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
papi_vector_t _niagara2_vector = {
Packit 577717
/************* COMPONENT CAPABILITIES/INFORMATION/ETC ************************/
Packit 577717
	.cmp_info = {
Packit 577717
                                 .name = "solaris-niagara2",
Packit 577717
                                 .description = "Solaris Counters",
Packit 577717
				 .num_cntrs = MAX_COUNTERS,
Packit 577717
				 .num_mpx_cntrs = MAX_COUNTERS,
Packit 577717
				 .default_domain = PAPI_DOM_USER,
Packit 577717
				 .available_domains = ( PAPI_DOM_USER | PAPI_DOM_KERNEL
Packit 577717
										| PAPI_DOM_SUPERVISOR ),
Packit 577717
				 .default_granularity = PAPI_GRN_THR,
Packit 577717
				 .available_granularities = PAPI_GRN_THR,
Packit 577717
				 .fast_real_timer = 1,
Packit 577717
				 .fast_virtual_timer = 1,
Packit 577717
				 .attach = 1,
Packit 577717
				 .attach_must_ptrace = 1,
Packit 577717
				 .hardware_intr = 1,
Packit 577717
				 .hardware_intr_sig = SIGEMT,
Packit 577717
				 .precise_intr = 1,
Packit 577717
				 }
Packit 577717
	,
Packit 577717
/************* COMPONENT DATA STRUCTURE SIZES ********************************/
Packit 577717
	.size = {
Packit 577717
			 .context = sizeof ( hwd_context_t ),
Packit 577717
			 .control_state = sizeof ( hwd_control_state_t ),
Packit 577717
			 .reg_value = sizeof ( hwd_register_t ),
Packit 577717
			 .reg_alloc = sizeof ( niagara2_reg_alloc_t ),
Packit 577717
			 }
Packit 577717
	,
Packit 577717
/************* COMPONENT INTERFACE FUNCTIONS *********************************/
Packit 577717
	.init_control_state = _niagara2_init_control_state,
Packit 577717
	.start = _niagara2_start,
Packit 577717
	.stop = _niagara2_stop,
Packit 577717
	.read = _niagara2_read,
Packit 577717
	.write = NULL,			 /* NOT IMPLEMENTED */
Packit 577717
	.shutdown_thread = _niagara2_shutdown,
Packit 577717
	.shutdown_component = _niagara2_shutdown_global,
Packit 577717
	.ctl = _niagara2_ctl,
Packit 577717
	.update_control_state = _niagara2_update_control_state,
Packit 577717
	.set_domain = _niagara2_set_domain,
Packit 577717
	.reset = _niagara2_reset,
Packit 577717
	.set_overflow = _niagara2_set_overflow,
Packit 577717
	.set_profile = _niagara2_set_profile,
Packit 577717
	.stop_profiling = NULL,	 /* NOT IMPLEMENTED */
Packit 577717
	.ntv_enum_events = _niagara2_ntv_enum_events,
Packit 577717
	.ntv_name_to_code = NULL,	/* NOT IMPLEMENTED */
Packit 577717
	.ntv_code_to_name = _niagara2_ntv_code_to_name,
Packit 577717
	.ntv_code_to_descr = _niagara2_ntv_code_to_descr,
Packit 577717
	.ntv_code_to_bits = _niagara2_ntv_code_to_bits,
Packit 577717
	.init_component = _niagara2_init_component,
Packit 577717
	.dispatch_timer = _niagara2_dispatch_timer,
Packit 577717
};
Packit 577717
Packit 577717
papi_os_vector_t _papi_os_vector = {
Packit 577717
	.get_memory_info = _niagara2_get_memory_info,
Packit 577717
	.get_dmem_info   = _solaris_get_dmem_info,
Packit 577717
Packit 577717
	.get_real_usec =     _solaris_get_real_usec,
Packit 577717
	.get_real_cycles =   _solaris_get_real_cycles,
Packit 577717
	.get_virt_usec =     _solaris_get_virt_usec,
Packit 577717
	.update_shlib_info = _solaris_update_shlib_info,
Packit 577717
	.get_system_info =   _solaris_get_system_info,
Packit 577717
};