Blame src/papi_internal.c

Packit Service a1973e
/****************************/
Packit Service a1973e
/* THIS IS OPEN SOURCE CODE */
Packit Service a1973e
/****************************/
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
* File:    papi_internal.c
Packit Service a1973e
*
Packit Service a1973e
* Author:  Philip Mucci
Packit Service a1973e
*          mucci@cs.utk.edu
Packit Service a1973e
* Mods:    dan terpstra
Packit Service a1973e
*          terpstra@cs.utk.edu
Packit Service a1973e
* Mods:    Min Zhou
Packit Service a1973e
*          min@cs.utk.edu
Packit Service a1973e
* Mods:    Kevin London
Packit Service a1973e
*	   london@cs.utk.edu
Packit Service a1973e
* Mods:    Per Ekman
Packit Service a1973e
*          pek@pdc.kth.se
Packit Service a1973e
* Mods:    Haihang You
Packit Service a1973e
*          you@cs.utk.edu
Packit Service a1973e
* Mods:    Maynard Johnson
Packit Service a1973e
*          maynardj@us.ibm.com
Packit Service a1973e
* Mods:    Brian Sheely
Packit Service a1973e
*          bsheely@eecs.utk.edu
Packit Service a1973e
* Mods:    <Gary Mohr>
Packit Service a1973e
*          <gary.mohr@bull.com>
Packit Service a1973e
* Mods:    <your name here>
Packit Service a1973e
*          <your email address>
Packit Service a1973e
*/
Packit Service a1973e
Packit Service a1973e
#include <stdarg.h>
Packit Service a1973e
#include <stdio.h>
Packit Service a1973e
#include <errno.h>
Packit Service a1973e
#include <string.h>
Packit Service a1973e
#include <ctype.h>
Packit Service a1973e
#include <assert.h>
Packit Service a1973e
Packit Service a1973e
#include "papi.h"
Packit Service a1973e
#include "papi_internal.h"
Packit Service a1973e
#include "papi_vector.h"
Packit Service a1973e
#include "papi_memory.h"
Packit Service a1973e
#include "sw_multiplex.h"
Packit Service a1973e
#include "extras.h"
Packit Service a1973e
#include "papi_preset.h"
Packit Service a1973e
#include "cpus.h"
Packit Service a1973e
Packit Service a1973e
#include "papi_common_strings.h"
Packit Service a1973e
Packit Service a1973e
/* Advanced definitons */
Packit Service a1973e
static int default_debug_handler( int errorCode );
Packit Service a1973e
static long long handle_derived( EventInfo_t * evi, long long *from );
Packit Service a1973e
Packit Service a1973e
/* Global definitions used by other files */
Packit Service a1973e
int init_level = PAPI_NOT_INITED;
Packit Service a1973e
int _papi_hwi_error_level = PAPI_QUIET;
Packit Service a1973e
PAPI_debug_handler_t _papi_hwi_debug_handler = default_debug_handler;
Packit Service a1973e
papi_mdi_t _papi_hwi_system_info;
Packit Service a1973e
int _papi_hwi_errno = PAPI_OK;
Packit Service a1973e
int _papi_hwi_num_errors = 0;
Packit Service a1973e
hwi_presets_t user_defined_events[PAPI_MAX_USER_EVENTS];
Packit Service a1973e
int user_defined_events_count = 0;
Packit Service a1973e
Packit Service a1973e
/*****************************/
Packit Service a1973e
/* Native Event Mapping Code */
Packit Service a1973e
/*****************************/
Packit Service a1973e
Packit Service a1973e
#define NATIVE_EVENT_CHUNKSIZE 1024
Packit Service a1973e
Packit Service a1973e
struct native_event_info {
Packit Service a1973e
  int cidx;
Packit Service a1973e
  int component_event;
Packit Service a1973e
  int ntv_idx;
Packit Service a1973e
  char *evt_name;
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
// The following array is indexed by the papi event code (after the native bit has been removed)
Packit Service a1973e
static struct native_event_info *_papi_native_events=NULL;
Packit Service a1973e
static int num_native_events=0;
Packit Service a1973e
static int num_native_chunks=0;
Packit Service a1973e
Packit Service a1973e
char **_papi_errlist= NULL;
Packit Service a1973e
static int num_error_chunks = 0;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
// pointer to event:mask string associated with last enum call to a components
Packit Service a1973e
// will be NULL for non libpfm4 components
Packit Service a1973e
// this is needed because libpfm4 event codes and papi event codes do not contain mask information
Packit Service a1973e
char *papi_event_string = NULL;
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_set_papi_event_string (const char *event_string) {
Packit Service a1973e
	INTDBG("event_string: %s\n", event_string);
Packit Service a1973e
	if (papi_event_string != NULL) {
Packit Service a1973e
		free (papi_event_string);
Packit Service a1973e
		papi_event_string = NULL;
Packit Service a1973e
	}
Packit Service a1973e
	if (event_string != NULL) {
Packit Service a1973e
		papi_event_string = strdup(event_string);
Packit Service a1973e
	}
Packit Service a1973e
	return;
Packit Service a1973e
}
Packit Service a1973e
char *
Packit Service a1973e
_papi_hwi_get_papi_event_string () {
Packit Service a1973e
	INTDBG("papi_event_string: %s\n", papi_event_string);
Packit Service a1973e
	return papi_event_string;
Packit Service a1973e
}
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_free_papi_event_string() {
Packit Service a1973e
	if (papi_event_string != NULL) {
Packit Service a1973e
		free(papi_event_string);
Packit Service a1973e
		papi_event_string = NULL;
Packit Service a1973e
	}
Packit Service a1973e
	return;
Packit Service a1973e
}
Packit Service 0798ad
Packit Service eb61f6
// A place to keep the current papi event code so some component functions can fetch its value
Packit Service eb61f6
// The current event code can be stored here prior to component calls and cleared after the component returns
Packit Service eb61f6
static THREAD_LOCAL_STORAGE_KEYWORD unsigned int papi_event_code = -1;
Packit Service eb61f6
static THREAD_LOCAL_STORAGE_KEYWORD int papi_event_code_changed = -1;
Packit Service eb61f6
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_set_papi_event_code (unsigned int event_code, int update_flag) {
Packit Service a1973e
	INTDBG("new event_code: %#x, update_flag: %d, previous event_code: %#x\n", event_code, update_flag, papi_event_code);
Packit Service a1973e
Packit Service a1973e
	// if call is just to reset and start over, set both flags to show nothing saved yet
Packit Service a1973e
	if (update_flag < 0) {
Packit Service eb61f6
		papi_event_code_changed = -1;
Packit Service eb61f6
		papi_event_code = -1;
Packit Service a1973e
		return;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	// if 0, it is being set prior to calling a component, if >0 it is being changed by the component
Packit Service eb61f6
	papi_event_code_changed = update_flag;
Packit Service a1973e
	// save the event code passed in
Packit Service eb61f6
	papi_event_code = event_code;
Packit Service a1973e
	return;
Packit Service a1973e
}
Packit Service a1973e
unsigned int
Packit Service a1973e
_papi_hwi_get_papi_event_code () {
Packit Service a1973e
	INTDBG("papi_event_code: %#x\n", papi_event_code);
Packit Service eb61f6
	return papi_event_code;
Packit Service a1973e
}
Packit Service a1973e
/* Get the index into the ESI->NativeInfoArray for the current PAPI event code */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_get_ntv_idx (unsigned int papi_evt_code) {
Packit Service a1973e
	INTDBG("ENTER: papi_evt_code: %#x\n", papi_evt_code);
Packit Service a1973e
Packit Service a1973e
	int result;
Packit Service a1973e
	int event_index;
Packit Service a1973e
Packit Service a1973e
	if (papi_evt_code == 0) {
Packit Service a1973e
		INTDBG("EXIT: PAPI_ENOEVNT, invalid papi event code\n");
Packit Service a1973e
		return PAPI_ENOEVNT;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	event_index=papi_evt_code&PAPI_NATIVE_AND_MASK;
Packit Service a1973e
	if ((event_index<0) || (event_index>=num_native_events)) {
Packit Service a1973e
		INTDBG("EXIT: PAPI_ENOEVNT, invalid index into native event array\n");
Packit Service a1973e
		return PAPI_ENOEVNT;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	result=_papi_native_events[event_index].ntv_idx;
Packit Service a1973e
Packit Service a1973e
	INTDBG("EXIT: result: %d\n", result);
Packit Service a1973e
	return result;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
//
Packit Service a1973e
// Check for the presence of a component name or pmu name in the event string.
Packit Service a1973e
// If found check if it matches this component or one of the pmu's supported by this component.
Packit Service a1973e
//
Packit Service a1973e
// returns true if the event could be for this component and false if it is not for this component.
Packit Service a1973e
//    if there is no component or pmu name then it could be for this component and returns true.
Packit Service a1973e
//
Packit Service a1973e
static int
Packit Service a1973e
is_supported_by_component(int cidx, char *event_name) {
Packit Service a1973e
	INTDBG("ENTER: cidx: %d, event_name: %s\n", cidx, event_name);
Packit Service a1973e
	int i;
Packit Service a1973e
	int component_name = 0;
Packit Service a1973e
	int pmu_name = 0;
Packit Service a1973e
	char *wptr = NULL;
Packit Service a1973e
Packit Service a1973e
	// if event does not have a component name or pmu name, return to show it could be supported by this component
Packit Service a1973e
	// when component and pmu names are not provided, we just have to call the components to see if they recognize the event
Packit Service a1973e
	//
Packit Service a1973e
Packit Service a1973e
	// look for component names first
Packit Service a1973e
	if ((wptr = strstr(event_name, ":::")) != NULL) {
Packit Service a1973e
		component_name = 1;
Packit Service a1973e
	} else if ((wptr = strstr(event_name, "::")) != NULL) {
Packit Service a1973e
		pmu_name = 1;
Packit Service a1973e
	} else {
Packit Service a1973e
		INTDBG("EXIT: No Component or PMU name in event string, try this component\n");
Packit Service a1973e
		// need to force all components to be called to find owner of this event
Packit Service a1973e
		// ????  can we assume the default pmu when no component or pmu name is provided ????
Packit Service a1973e
		return 1;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	// get a temporary copy of the component or pmu name
Packit Service a1973e
	int name_len = wptr - event_name;
Packit Service a1973e
	wptr = strdup(event_name);
Packit Service a1973e
	wptr[name_len] = '\0';
Packit Service a1973e
Packit Service a1973e
	// if a component name was found, compare it to the component name in the component info structure
Packit Service a1973e
	if (component_name) {
Packit Service a1973e
//		INTDBG("component_name: %s\n", _papi_hwd[cidx]->cmp_info.name);
Packit Service a1973e
		if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.name) == 0) {
Packit Service a1973e
			free (wptr);
Packit Service a1973e
			INTDBG("EXIT: Component %s supports this event\n", _papi_hwd[cidx]->cmp_info.name);
Packit Service a1973e
			return 1;
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	// if a pmu name was found, compare it to the pmu name list if the component info structure (if there is one)
Packit Service a1973e
	if (pmu_name) {
Packit Service a1973e
		for ( i=0 ; i
Packit Service a1973e
			if (_papi_hwd[cidx]->cmp_info.pmu_names[i] == NULL) {
Packit Service a1973e
				continue;
Packit Service a1973e
			}
Packit Service a1973e
//			INTDBG("pmu_name[%d]: %p (%s)\n", i, _papi_hwd[cidx]->cmp_info.pmu_names[i], _papi_hwd[cidx]->cmp_info.pmu_names[i]);
Packit Service a1973e
			if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.pmu_names[i]) == 0) {
Packit Service a1973e
				INTDBG("EXIT: Component %s supports PMU %s and this event\n", _papi_hwd[cidx]->cmp_info.name, wptr);
Packit Service a1973e
				free (wptr);
Packit Service a1973e
				return 1;
Packit Service a1973e
			}
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	free (wptr);
Packit Service a1973e
	INTDBG("EXIT: Component does not support this event\n");
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/** @internal
Packit Service a1973e
 * @class _papi_hwi_prefix_component_name
Packit Service a1973e
 * @brief Prefixes a component's name to each of its events. 
Packit Service a1973e
 * @param *component_name
Packit Service a1973e
 * @param *event_name
Packit Service a1973e
 * @param *out
Packit Service a1973e
 * @param *out_len
Packit Service a1973e
 *
Packit Service a1973e
 * Given sane component_name and event_name it returns component_name:::event_name. 
Packit Service a1973e
 * It is safe in the case that event_name == out and it checks against the 
Packit Service a1973e
 * traditional PAPI 'cpu' components, opting to not prepend those. 
Packit Service a1973e
 */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_prefix_component_name( char *component_name, char *event_name, char *out, int out_len) 
Packit Service a1973e
{
Packit Service a1973e
	int size1, size2;
Packit Service a1973e
	char temp[out_len];
Packit Service a1973e
Packit Service a1973e
	size1 = strlen(event_name);
Packit Service a1973e
	size2 = strlen(component_name);
Packit Service a1973e
Packit Service a1973e
/* sanity checks */
Packit Service a1973e
	if ( size1 == 0 ) {
Packit Service a1973e
		return (PAPI_EBUG); /* hopefully event_name always has length?! */
Packit Service a1973e
	}	
Packit Service a1973e
Packit Service a1973e
	if ( size1 >= out_len )
Packit Service a1973e
		return (PAPI_ENOMEM);
Packit Service a1973e
Packit Service a1973e
/* Guard against event_name == out */
Packit Service a1973e
	memcpy( temp, event_name, out_len );
Packit Service a1973e
Packit Service a1973e
/* no component name to prefix */
Packit Service a1973e
	if ( size2 == 0 ) {
Packit Service a1973e
		sprintf(out, "%s%c", temp, '\0' );
Packit Service a1973e
		return (PAPI_OK);
Packit Service a1973e
	}
Packit Service a1973e
	
Packit Service a1973e
/* Don't prefix 'cpu' component names for now */
Packit Service a1973e
	if ( strstr(component_name, "pe") ||
Packit Service a1973e
		 strstr(component_name, "bgq") ||
Packit Service a1973e
		 strstr(component_name, "bgp") ) {
Packit Service a1973e
		sprintf( out, "%s%c", temp, '\0'); 
Packit Service a1973e
		return (PAPI_OK);
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
/* strlen(component_name) + ::: + strlen(event_name) + NULL */
Packit Service a1973e
	if ( size1+size2+3+1 > out_len )
Packit Service a1973e
		return (PAPI_ENOMEM);
Packit Service a1973e
Packit Service a1973e
	sprintf( out, "%s:::%s%c" , component_name, temp, '\0');
Packit Service a1973e
	return (PAPI_OK);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/** @internal
Packit Service a1973e
 *  @class _papi_hwi_strip_component_prefix
Packit Service a1973e
 *  @brief Strip off cmp_name::: from an event name. 
Packit Service a1973e
 *
Packit Service a1973e
 *  @param *event_name
Packit Service a1973e
 *  @return Start of the component consumable portion of the name. 
Packit Service a1973e
 *
Packit Service a1973e
 *  This function checks specifically for ':::' and will return the start of 
Packit Service a1973e
 *  event_name if it doesn't find the ::: .
Packit Service a1973e
 */
Packit Service a1973e
const char *_papi_hwi_strip_component_prefix(const char *event_name)
Packit Service a1973e
{
Packit Service a1973e
	const char *start = NULL;
Packit Service a1973e
/* We assume ::: is the seperator 
Packit Service a1973e
 * eg: 
Packit Service a1973e
 * 		papi_component:::event_name 
Packit Service a1973e
 */
Packit Service a1973e
Packit Service a1973e
	start = strstr( event_name, ":::" );
Packit Service a1973e
	if ( start != NULL )
Packit Service a1973e
		start+= 3; /* return the actual start of event_name */
Packit Service a1973e
	else
Packit Service a1973e
		start = event_name;
Packit Service a1973e
Packit Service a1973e
	return (start);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* find the papi event code (4000xxx) associated with the specified component, native event, and event name */
Packit Service a1973e
static int
Packit Service a1973e
_papi_hwi_find_native_event(int cidx, int event, const char *event_name) {
Packit Service a1973e
  INTDBG("ENTER: cidx: %x, event: %#x, event_name: %s\n", cidx, event, event_name);
Packit Service a1973e
Packit Service a1973e
  int i;
Packit Service a1973e
Packit Service a1973e
  // if no event name passed in, it can not be found
Packit Service a1973e
  if (event_name == NULL) {
Packit Service a1973e
		INTDBG("EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
		return PAPI_ENOEVNT;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  for(i=0;i
Packit Service a1973e
  	// if we have have not set up this event name yet, look at next
Packit Service a1973e
  	if (_papi_native_events[i].evt_name == NULL) {
Packit Service a1973e
  		continue;
Packit Service a1973e
  	}
Packit Service a1973e
Packit Service a1973e
  	// is this entry for the correct component and event code
Packit Service a1973e
  	if ((_papi_native_events[i].cidx==cidx) &&
Packit Service a1973e
	(_papi_native_events[i].component_event==event)) {
Packit Service a1973e
		// if this event name matches what we want, return its papi event code
Packit Service a1973e
		if (strcmp(event_name, _papi_native_events[i].evt_name) == 0) {
Packit Service a1973e
			INTDBG("EXIT: event: %#x, component_event: %#x, ntv_idx: %d, event_name: %s\n",
Packit Service a1973e
				i|PAPI_NATIVE_MASK, _papi_native_events[i].component_event, _papi_native_events[i].ntv_idx, _papi_native_events[i].evt_name);
Packit Service a1973e
			return i|PAPI_NATIVE_MASK;
Packit Service a1973e
		}
Packit Service a1973e
    }
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
	INTDBG("EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
	return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_papi_hwi_add_native_event(int cidx, int ntv_event, int ntv_idx, const char *event_name) {
Packit Service a1973e
	INTDBG("ENTER: cidx: %d, ntv_event: %#x, ntv_idx: %d, event_name: %s\n", cidx, ntv_event, ntv_idx, event_name);
Packit Service a1973e
Packit Service a1973e
  int new_native_event;
Packit Service a1973e
  
Packit Service a1973e
  _papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
  if (num_native_events>=num_native_chunks*NATIVE_EVENT_CHUNKSIZE) {
Packit Service a1973e
     num_native_chunks++;
Packit Service a1973e
     _papi_native_events=(struct native_event_info *) realloc(_papi_native_events,
Packit Service a1973e
				 num_native_chunks*NATIVE_EVENT_CHUNKSIZE*
Packit Service a1973e
				 sizeof(struct native_event_info));
Packit Service a1973e
     if (_papi_native_events==NULL) {
Packit Service a1973e
        new_native_event=PAPI_ENOMEM;
Packit Service a1973e
	goto native_alloc_early_out;
Packit Service a1973e
     }
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  _papi_native_events[num_native_events].cidx=cidx;
Packit Service a1973e
  _papi_native_events[num_native_events].component_event=ntv_event;
Packit Service a1973e
  _papi_native_events[num_native_events].ntv_idx=ntv_idx;
Packit Service a1973e
  if (event_name != NULL) {
Packit Service a1973e
	  _papi_native_events[num_native_events].evt_name=strdup(event_name);
Packit Service a1973e
  } else {
Packit Service a1973e
	  _papi_native_events[num_native_events].evt_name=NULL;
Packit Service a1973e
  }
Packit Service a1973e
  new_native_event=num_native_events|PAPI_NATIVE_MASK;
Packit Service a1973e
Packit Service a1973e
  num_native_events++;
Packit Service a1973e
Packit Service a1973e
native_alloc_early_out:
Packit Service a1973e
Packit Service a1973e
  _papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
  INTDBG("EXIT: new_native_event: %#x, num_native_events: %d\n", new_native_event, num_native_events);
Packit Service a1973e
  return new_native_event;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/** @internal
Packit Service a1973e
 * @class _papi_hwi_add_error
Packit Service a1973e
 *
Packit Service a1973e
 * Adds a new error string to PAPI's internal store.
Packit Service a1973e
 * MAKE SURE you are not holding INTERNAL_LOCK when you call me!
Packit Service a1973e
 */ 
Packit Service a1973e
static int
Packit Service a1973e
_papi_hwi_add_error( char *error )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("Adding a new Error message |%s|\n", error);
Packit Service a1973e
	_papi_hwi_lock(INTERNAL_LOCK);
Packit Service a1973e
Packit Service a1973e
	if (_papi_hwi_num_errors >= num_error_chunks*NATIVE_EVENT_CHUNKSIZE) {
Packit Service a1973e
		num_error_chunks++;
Packit Service a1973e
		_papi_errlist= (char **) realloc(_papi_errlist, 
Packit Service a1973e
						num_error_chunks*NATIVE_EVENT_CHUNKSIZE*sizeof(char *));
Packit Service a1973e
		if (_papi_errlist==NULL) {
Packit Service a1973e
			_papi_hwi_num_errors = -2;
Packit Service a1973e
			goto bail;
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	_papi_errlist[_papi_hwi_num_errors] = strdup( error );
Packit Service a1973e
	if ( _papi_errlist[_papi_hwi_num_errors] == NULL )
Packit Service a1973e
		_papi_hwi_num_errors = -2;
Packit Service a1973e
Packit Service a1973e
bail:
Packit Service a1973e
	_papi_hwi_unlock(INTERNAL_LOCK);
Packit Service a1973e
Packit Service a1973e
	return _papi_hwi_num_errors++;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
_papi_hwi_cleanup_errors()
Packit Service a1973e
{
Packit Service a1973e
	int i; 
Packit Service a1973e
	
Packit Service a1973e
	if ( _papi_errlist == NULL || 
Packit Service a1973e
			_papi_hwi_num_errors == 0 )
Packit Service a1973e
		return; 
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
	for (i=0; i < _papi_hwi_num_errors; i++ ) {
Packit Service a1973e
		free( _papi_errlist[i]);
Packit Service a1973e
		_papi_errlist[i] = NULL;
Packit Service a1973e
	} 
Packit Service a1973e
Packit Service a1973e
	free( _papi_errlist );
Packit Service a1973e
	_papi_errlist = NULL;
Packit Service a1973e
	_papi_hwi_num_errors = 0;
Packit Service a1973e
	num_error_chunks=0;
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_papi_hwi_lookup_error( char *error ) 
Packit Service a1973e
{
Packit Service a1973e
	int i;
Packit Service a1973e
Packit Service a1973e
	for (i=0; i<_papi_hwi_num_errors; i++) {
Packit Service a1973e
		if ( !strncasecmp( _papi_errlist[i], error, strlen( error ) ) )
Packit Service a1973e
			return i; 
Packit Service a1973e
		
Packit Service a1973e
	} 
Packit Service a1973e
Packit Service a1973e
	return (-1);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/** @internal
Packit Service a1973e
 *  @class _papi_hwi_publish_error 
Packit Service a1973e
 *
Packit Service a1973e
 *  @return 
Packit Service a1973e
 *  	<= 0 : Code for the error. 
Packit Service a1973e
 *  	< 0  : We couldn't get memory to allocate for your error.
Packit Service a1973e
 *  	 	
Packit Service a1973e
 * 	An internal interface for adding an error code to the library. 
Packit Service a1973e
 * 	The returned code is suitable for returning to users. 
Packit Service a1973e
 *  */
Packit Service a1973e
int _papi_hwi_publish_error( char *error )
Packit Service a1973e
{
Packit Service a1973e
	int error_code = -1;
Packit Service a1973e
Packit Service a1973e
	if ( (error_code = _papi_hwi_lookup_error( error )) < 0 )
Packit Service a1973e
		error_code = _papi_hwi_add_error(error);
Packit Service a1973e
Packit Service a1973e
	return (-error_code); /* internally error_code is an index, externally, it should be <= 0 */
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_init_errors(void) {
Packit Service a1973e
/* we use add error to avoid the cost of lookups, we know the errors are not there yet */
Packit Service a1973e
	_papi_hwi_add_error("No error");
Packit Service a1973e
    _papi_hwi_add_error("Invalid argument");
Packit Service a1973e
    _papi_hwi_add_error("Insufficient memory");
Packit Service a1973e
    _papi_hwi_add_error("A System/C library call failed");
Packit Service a1973e
    _papi_hwi_add_error("Not supported by component");
Packit Service a1973e
    _papi_hwi_add_error("Access to the counters was lost or interrupted");
Packit Service a1973e
    _papi_hwi_add_error("Internal error, please send mail to the developers");
Packit Service a1973e
    _papi_hwi_add_error("Event does not exist");
Packit Service a1973e
    _papi_hwi_add_error("Event exists, but cannot be counted due to hardware resource limits");
Packit Service a1973e
    _papi_hwi_add_error("EventSet is currently not running");
Packit Service a1973e
    _papi_hwi_add_error("EventSet is currently counting");
Packit Service a1973e
    _papi_hwi_add_error("No such EventSet available");
Packit Service a1973e
    _papi_hwi_add_error("Event in argument is not a valid preset");
Packit Service a1973e
    _papi_hwi_add_error("Hardware does not support performance counters");
Packit Service a1973e
    _papi_hwi_add_error("Unknown error code");
Packit Service a1973e
    _papi_hwi_add_error("Permission level does not permit operation");
Packit Service a1973e
    _papi_hwi_add_error("PAPI hasn't been initialized yet");
Packit Service a1973e
    _papi_hwi_add_error("Component Index isn't set");
Packit Service a1973e
    _papi_hwi_add_error("Not supported");
Packit Service a1973e
    _papi_hwi_add_error("Not implemented");
Packit Service a1973e
    _papi_hwi_add_error("Buffer size exceeded");
Packit Service a1973e
    _papi_hwi_add_error("EventSet domain is not supported for the operation");
Packit Service a1973e
    _papi_hwi_add_error("Invalid or missing event attributes");
Packit Service a1973e
    _papi_hwi_add_error("Too many events or attributes");
Packit Service a1973e
    _papi_hwi_add_error("Bad combination of features");
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_invalid_cmp( int cidx )
Packit Service a1973e
{
Packit Service a1973e
  return ( cidx < 0 || cidx >= papi_num_components );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int 
Packit Service a1973e
_papi_hwi_component_index( int event_code ) {
Packit Service a1973e
	INTDBG("ENTER: event_code: %#x\n", event_code);
Packit Service a1973e
Packit Service a1973e
  int cidx;
Packit Service a1973e
  int event_index;
Packit Service a1973e
Packit Service a1973e
  /* currently assume presets are for component 0 only */
Packit Service a1973e
  if (IS_PRESET(event_code)) {
Packit Service a1973e
     INTDBG("EXIT: Event %#x is a PRESET, assigning component %d\n", event_code,0);
Packit Service a1973e
     return 0;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  /* user defined events are treated like preset events (component 0 only) */
Packit Service a1973e
  if (IS_USER_DEFINED(event_code)) {
Packit Service a1973e
     INTDBG("EXIT: Event %#x is USER DEFINED, assigning component %d\n", event_code,0);
Packit Service a1973e
     return 0;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  event_index=event_code&PAPI_NATIVE_AND_MASK;
Packit Service a1973e
Packit Service a1973e
  if ( (event_index < 0) || (event_index>=num_native_events)) {
Packit Service a1973e
     INTDBG("EXIT: Event index %#x is out of range, num_native_events: %d\n", event_index, num_native_events);
Packit Service a1973e
     return PAPI_ENOEVNT;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  cidx=_papi_native_events[event_index].cidx;
Packit Service a1973e
Packit Service a1973e
  if ((cidx<0) || (cidx >= papi_num_components)) {
Packit Service a1973e
	  INTDBG("EXIT: Component index %#x is out of range, papi_num_components: %d\n", cidx, papi_num_components);
Packit Service a1973e
	  return PAPI_ENOCMP;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  INTDBG("EXIT: Found cidx: %d event_index: %d, event_code: %#x\n", cidx, event_index, event_code);
Packit Service a1973e
  return cidx;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Convert an internal component event to a papi event code */
Packit Service a1973e
int 
Packit Service a1973e
_papi_hwi_native_to_eventcode(int cidx, int event_code, int ntv_idx, const char *event_name) {
Packit Service a1973e
  INTDBG("Entry: cidx: %d, event: %#x, ntv_idx: %d, event_name: %s\n", cidx, event_code, ntv_idx, event_name);
Packit Service a1973e
Packit Service a1973e
  int result;
Packit Service a1973e
Packit Service eb61f6
  if (papi_event_code_changed > 0) {
Packit Service a1973e
	  result = _papi_hwi_get_papi_event_code();
Packit Service a1973e
	  INTDBG("EXIT: papi_event_code: %#x set by the component\n", result);
Packit Service a1973e
	  return result;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  result=_papi_hwi_find_native_event(cidx, event_code, event_name);
Packit Service a1973e
  if (result==PAPI_ENOEVNT) {
Packit Service a1973e
     // Need to create one
Packit Service a1973e
     result=_papi_hwi_add_native_event(cidx, event_code, ntv_idx, event_name);
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  INTDBG("EXIT: result: %#x\n", result);
Packit Service a1973e
  return result;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Convert a native_event code to an internal event code */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_eventcode_to_native(int event_code) {
Packit Service a1973e
	INTDBG("ENTER: event_code: %#x\n", event_code);
Packit Service a1973e
Packit Service a1973e
  int result;
Packit Service a1973e
  int event_index;
Packit Service a1973e
Packit Service a1973e
  event_index=event_code&PAPI_NATIVE_AND_MASK;
Packit Service a1973e
 if ((event_index < 0)  ||  (event_index>=num_native_events)) {
Packit Service a1973e
    INTDBG("EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  result=_papi_native_events[event_index].component_event;
Packit Service a1973e
  
Packit Service a1973e
  INTDBG("EXIT: result: %#x\n", result);
Packit Service a1973e
  return result;
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*********************/
Packit Service a1973e
/* Utility functions */
Packit Service a1973e
/*********************/
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
PAPIERROR( char *format, ... )
Packit Service a1973e
{
Packit Service a1973e
	va_list args;
Packit Service a1973e
	if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
Packit Service a1973e
		 ( getenv( "PAPI_VERBOSE" ) ) ) {
Packit Service a1973e
		va_start( args, format );
Packit Service a1973e
		fprintf( stderr, "PAPI Error: " );
Packit Service a1973e
		vfprintf( stderr, format, args );
Packit Service a1973e
		fprintf( stderr, "\n" );
Packit Service a1973e
		va_end( args );
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
PAPIWARN( char *format, ... )
Packit Service a1973e
{
Packit Service a1973e
	va_list args;
Packit Service a1973e
	if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
Packit Service a1973e
		 ( getenv( "PAPI_VERBOSE" ) ) ) {
Packit Service a1973e
		va_start( args, format );
Packit Service a1973e
		fprintf( stderr, "PAPI Warning: " );
Packit Service a1973e
		vfprintf( stderr, format, args );
Packit Service a1973e
		fprintf( stderr, "\n" );
Packit Service a1973e
		va_end( args );
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
default_debug_handler( int errorCode )
Packit Service a1973e
{
Packit Service a1973e
	char str[PAPI_HUGE_STR_LEN];
Packit Service a1973e
Packit Service a1973e
	if ( errorCode == PAPI_OK )
Packit Service a1973e
		return ( errorCode );
Packit Service a1973e
	if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) {
Packit Service a1973e
		PAPIERROR( "%s %d,%s,Bug! Unknown error code", PAPI_ERROR_CODE_str,
Packit Service a1973e
				   errorCode, "" );
Packit Service a1973e
		return ( PAPI_EBUG );
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	switch ( _papi_hwi_error_level ) {
Packit Service a1973e
	case PAPI_VERB_ECONT:
Packit Service a1973e
	case PAPI_VERB_ESTOP:
Packit Service a1973e
		/* gcc 2.96 bug fix, do not change */
Packit Service a1973e
		/* fprintf(stderr,"%s %d: %s: %s\n",PAPI_ERROR_CODE_str,errorCode,_papi_hwi_err[-errorCode].name,_papi_hwi_err[-errorCode].descr); */
Packit Service a1973e
Packit Service a1973e
		sprintf( str, "%s %d,%s", PAPI_ERROR_CODE_str, errorCode,
Packit Service a1973e
				 _papi_errlist[-errorCode] );
Packit Service a1973e
		if ( errorCode == PAPI_ESYS )
Packit Service a1973e
			sprintf( str + strlen( str ), ": %s", strerror( errno ) );
Packit Service a1973e
Packit Service a1973e
		PAPIERROR( str );
Packit Service a1973e
Packit Service a1973e
		if ( _papi_hwi_error_level == PAPI_VERB_ESTOP )
Packit Service a1973e
			abort(  );		 /* patch provided by will cohen of redhat */
Packit Service a1973e
		else
Packit Service a1973e
			return errorCode;
Packit Service a1973e
		break;
Packit Service a1973e
Packit Service a1973e
	case PAPI_QUIET:
Packit Service a1973e
	default:
Packit Service a1973e
		return errorCode;
Packit Service a1973e
	}
Packit Service a1973e
	return ( PAPI_EBUG );	 /* Never get here */
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
allocate_eventset_map( DynamicArray_t * map )
Packit Service a1973e
{
Packit Service a1973e
	/* Allocate and clear the Dynamic Array structure */
Packit Service a1973e
	if ( map->dataSlotArray != NULL )
Packit Service a1973e
		papi_free( map->dataSlotArray );
Packit Service a1973e
	memset( map, 0x00, sizeof ( DynamicArray_t ) );
Packit Service a1973e
Packit Service a1973e
	/* Allocate space for the EventSetInfo_t pointers */
Packit Service a1973e
Packit Service a1973e
	map->dataSlotArray =
Packit Service a1973e
		( EventSetInfo_t ** ) papi_malloc( PAPI_INIT_SLOTS *
Packit Service a1973e
										   sizeof ( EventSetInfo_t * ) );
Packit Service a1973e
	if ( map->dataSlotArray == NULL ) {
Packit Service a1973e
		return ( PAPI_ENOMEM );
Packit Service a1973e
	}
Packit Service a1973e
	memset( map->dataSlotArray, 0x00,
Packit Service a1973e
			PAPI_INIT_SLOTS * sizeof ( EventSetInfo_t * ) );
Packit Service a1973e
	map->totalSlots = PAPI_INIT_SLOTS;
Packit Service a1973e
	map->availSlots = PAPI_INIT_SLOTS;
Packit Service a1973e
	map->fullSlots = 0;
Packit Service a1973e
Packit Service a1973e
	return ( PAPI_OK );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
expand_dynamic_array( DynamicArray_t * DA )
Packit Service a1973e
{
Packit Service a1973e
	int number;
Packit Service a1973e
	EventSetInfo_t **n;
Packit Service a1973e
Packit Service a1973e
	/*realloc existing PAPI_EVENTSET_MAP.dataSlotArray */
Packit Service a1973e
Packit Service a1973e
	number = DA->totalSlots * 2;
Packit Service a1973e
	n = ( EventSetInfo_t ** ) papi_realloc( DA->dataSlotArray,
Packit Service a1973e
											( size_t ) number *
Packit Service a1973e
											sizeof ( EventSetInfo_t * ) );
Packit Service a1973e
	if ( n == NULL )
Packit Service a1973e
		return ( PAPI_ENOMEM );
Packit Service a1973e
Packit Service a1973e
	/* Need to assign this value, what if realloc moved it? */
Packit Service a1973e
Packit Service a1973e
	DA->dataSlotArray = n;
Packit Service a1973e
Packit Service a1973e
	memset( DA->dataSlotArray + DA->totalSlots, 0x00,
Packit Service a1973e
			( size_t ) DA->totalSlots * sizeof ( EventSetInfo_t * ) );
Packit Service a1973e
Packit Service a1973e
	DA->totalSlots = number;
Packit Service a1973e
	DA->availSlots = number - DA->fullSlots;
Packit Service a1973e
Packit Service a1973e
	return ( PAPI_OK );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
EventInfoArrayLength( const EventSetInfo_t * ESI )
Packit Service a1973e
{
Packit Service a1973e
   return ( _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*========================================================================*/
Packit Service a1973e
/* This function allocates space for one EventSetInfo_t structure and for */
Packit Service a1973e
/* all of the pointers in this structure.  If any malloc in this function */
Packit Service a1973e
/* fails, all memory malloced to the point of failure is freed, and NULL  */
Packit Service a1973e
/* is returned.  Upon success, a pointer to the EventSetInfo_t data       */
Packit Service a1973e
/* structure is returned.                                                 */
Packit Service a1973e
/*========================================================================*/
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
create_EventSet( EventSetInfo_t ** here )
Packit Service a1973e
{
Packit Service a1973e
   EventSetInfo_t *ESI;
Packit Service a1973e
Packit Service a1973e
   ESI = ( EventSetInfo_t * ) papi_calloc( 1, sizeof ( EventSetInfo_t ) );
Packit Service a1973e
   if ( ESI == NULL ) {
Packit Service a1973e
      return PAPI_ENOMEM;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   *here = ESI;
Packit Service a1973e
Packit Service a1973e
   return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_assign_eventset( EventSetInfo_t *ESI, int cidx )
Packit Service a1973e
{
Packit Service a1973e
   INTDBG("ENTER: ESI: %p (%d), cidx: %d\n", ESI, ESI->EventSetIndex, cidx);
Packit Service a1973e
   int retval;
Packit Service a1973e
   size_t max_counters;
Packit Service a1973e
   char *ptr;
Packit Service a1973e
   unsigned int i, j;
Packit Service a1973e
Packit Service a1973e
   /* If component doesn't exist... */
Packit Service a1973e
   if (_papi_hwi_invalid_cmp(cidx)) return PAPI_ECMP;
Packit Service a1973e
Packit Service a1973e
   /* Assigned at create time */
Packit Service a1973e
   ESI->domain.domain = _papi_hwd[cidx]->cmp_info.default_domain;
Packit Service a1973e
   ESI->granularity.granularity =
Packit Service a1973e
	                         _papi_hwd[cidx]->cmp_info.default_granularity;
Packit Service a1973e
   ESI->CmpIdx = cidx;
Packit Service a1973e
Packit Service a1973e
   /* ??? */
Packit Service a1973e
   max_counters = ( size_t ) _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
Packit Service a1973e
Packit Service a1973e
   ESI->ctl_state = (hwd_control_state_t *) papi_calloc( 1, (size_t) 
Packit Service a1973e
				   _papi_hwd[cidx]->size.control_state );
Packit Service a1973e
   ESI->sw_stop = (long long *) papi_calloc( ( size_t ) max_counters,
Packit Service a1973e
						      sizeof ( long long ) );
Packit Service a1973e
   ESI->hw_start = ( long long * ) papi_calloc( ( size_t ) max_counters,
Packit Service a1973e
                                                      sizeof ( long long ) );
Packit Service a1973e
   ESI->EventInfoArray = ( EventInfo_t * ) papi_calloc( (size_t) max_counters,
Packit Service a1973e
                                                      sizeof ( EventInfo_t ) );
Packit Service a1973e
Packit Service a1973e
   /* allocate room for the native events and for the component-private */
Packit Service a1973e
   /* register structures */
Packit Service a1973e
   /* ugh is there a cleaner way to allocate this?  vmw */
Packit Service a1973e
   ESI->NativeInfoArray = ( NativeInfo_t * ) 
Packit Service a1973e
     papi_calloc( ( size_t ) max_counters, sizeof ( NativeInfo_t ));
Packit Service a1973e
Packit Service a1973e
   ESI->NativeBits = papi_calloc(( size_t ) max_counters,
Packit Service a1973e
                                 ( size_t ) _papi_hwd[cidx]->size.reg_value );
Packit Service a1973e
Packit Service a1973e
   /* NOTE: the next two malloc allocate blocks of memory that are later */
Packit Service a1973e
   /* parcelled into overflow and profile arrays                         */
Packit Service a1973e
   ESI->overflow.deadline = ( long long * )
Packit Service a1973e
		papi_malloc( ( sizeof ( long long ) +
Packit Service a1973e
					   sizeof ( int ) * 3 ) * ( size_t ) max_counters );
Packit Service a1973e
Packit Service a1973e
   ESI->profile.prof = ( PAPI_sprofil_t ** )
Packit Service a1973e
		papi_malloc( ( sizeof ( PAPI_sprofil_t * ) * ( size_t ) max_counters +
Packit Service a1973e
					   ( size_t ) max_counters * sizeof ( int ) * 4 ) );
Packit Service a1973e
Packit Service a1973e
   /* If any of these allocations failed, free things up and fail */
Packit Service a1973e
Packit Service a1973e
   if ( ( ESI->ctl_state == NULL ) ||
Packit Service a1973e
	( ESI->sw_stop == NULL )   || 
Packit Service a1973e
        ( ESI->hw_start == NULL )  ||
Packit Service a1973e
	( ESI->NativeInfoArray == NULL ) || 
Packit Service a1973e
	( ESI->NativeBits == NULL ) || 
Packit Service a1973e
        ( ESI->EventInfoArray == NULL )  ||
Packit Service a1973e
	( ESI->profile.prof == NULL ) || 
Packit Service a1973e
        ( ESI->overflow.deadline == NULL ) ) {
Packit Service a1973e
Packit Service a1973e
      if ( ESI->sw_stop ) papi_free( ESI->sw_stop );
Packit Service a1973e
      if ( ESI->hw_start ) papi_free( ESI->hw_start );
Packit Service a1973e
      if ( ESI->EventInfoArray ) papi_free( ESI->EventInfoArray );
Packit Service a1973e
      if ( ESI->NativeInfoArray ) papi_free( ESI->NativeInfoArray );
Packit Service a1973e
      if ( ESI->NativeBits ) papi_free( ESI->NativeBits );
Packit Service a1973e
      if ( ESI->ctl_state ) papi_free( ESI->ctl_state );
Packit Service a1973e
      if ( ESI->overflow.deadline ) papi_free( ESI->overflow.deadline );
Packit Service a1973e
      if ( ESI->profile.prof ) papi_free( ESI->profile.prof );
Packit Service a1973e
      papi_free( ESI );
Packit Service a1973e
      return PAPI_ENOMEM;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
   /* Carve up the overflow block into separate arrays */
Packit Service a1973e
   ptr = ( char * ) ESI->overflow.deadline;
Packit Service a1973e
   ptr += sizeof ( long long ) * max_counters;
Packit Service a1973e
   ESI->overflow.threshold = ( int * ) ptr;
Packit Service a1973e
   ptr += sizeof ( int ) * max_counters;
Packit Service a1973e
   ESI->overflow.EventIndex = ( int * ) ptr;
Packit Service a1973e
   ptr += sizeof ( int ) * max_counters;
Packit Service a1973e
   ESI->overflow.EventCode = ( int * ) ptr;
Packit Service a1973e
Packit Service a1973e
   /* Carve up the profile block into separate arrays */
Packit Service a1973e
   ptr = ( char * ) ESI->profile.prof +
Packit Service a1973e
		( sizeof ( PAPI_sprofil_t * ) * max_counters );
Packit Service a1973e
   ESI->profile.count = ( int * ) ptr;
Packit Service a1973e
   ptr += sizeof ( int ) * max_counters;
Packit Service a1973e
   ESI->profile.threshold = ( int * ) ptr;
Packit Service a1973e
   ptr += sizeof ( int ) * max_counters;
Packit Service a1973e
   ESI->profile.EventIndex = ( int * ) ptr;
Packit Service a1973e
   ptr += sizeof ( int ) * max_counters;
Packit Service a1973e
   ESI->profile.EventCode = ( int * ) ptr;
Packit Service a1973e
Packit Service a1973e
   /* initialize_EventInfoArray */
Packit Service a1973e
Packit Service a1973e
   for ( i = 0; i < max_counters; i++ ) {
Packit Service a1973e
       ESI->EventInfoArray[i].event_code=( unsigned int ) PAPI_NULL;
Packit Service a1973e
       ESI->EventInfoArray[i].ops = NULL;
Packit Service a1973e
       ESI->EventInfoArray[i].derived=NOT_DERIVED;
Packit Service a1973e
       for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
Packit Service a1973e
	   ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
Packit Service a1973e
       }
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   /* initialize_NativeInfoArray */
Packit Service a1973e
   for( i = 0; i < max_counters; i++ ) {
Packit Service a1973e
      ESI->NativeInfoArray[i].ni_event = -1;
Packit Service a1973e
      ESI->NativeInfoArray[i].ni_position = -1;
Packit Service a1973e
      ESI->NativeInfoArray[i].ni_papi_code = -1;
Packit Service a1973e
      ESI->NativeInfoArray[i].ni_owners = 0;
Packit Service a1973e
      ESI->NativeInfoArray[i].ni_bits = ((unsigned char*)ESI->NativeBits) + 
Packit Service a1973e
                                          (i*_papi_hwd[cidx]->size.reg_value);
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   ESI->NativeCount = 0;
Packit Service a1973e
Packit Service a1973e
   ESI->state = PAPI_STOPPED;
Packit Service a1973e
Packit Service a1973e
   /* these used to be init_config */
Packit Service a1973e
   retval = _papi_hwd[cidx]->init_control_state( ESI->ctl_state );	
Packit Service a1973e
   retval |= _papi_hwd[cidx]->set_domain( ESI->ctl_state, ESI->domain.domain);
Packit Service a1973e
Packit Service a1973e
   return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*========================================================================*/
Packit Service a1973e
/* This function should free memory for one EventSetInfo_t structure.     */
Packit Service a1973e
/* The argument list consists of a pointer to the EventSetInfo_t          */
Packit Service a1973e
/* structure, *ESI.                                                       */
Packit Service a1973e
/* The calling function should check  for ESI==NULL.                      */
Packit Service a1973e
/*========================================================================*/
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_free_EventSet( EventSetInfo_t * ESI )
Packit Service a1973e
{
Packit Service a1973e
	_papi_hwi_cleanup_eventset( ESI );
Packit Service a1973e
Packit Service a1973e
#ifdef DEBUG
Packit Service a1973e
	memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
Packit Service a1973e
#endif
Packit Service a1973e
	papi_free( ESI );
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
add_EventSet( EventSetInfo_t * ESI, ThreadInfo_t * master )
Packit Service a1973e
{
Packit Service a1973e
	DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
Packit Service a1973e
	int i, errorCode;
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
	if ( map->availSlots == 0 ) {
Packit Service a1973e
		errorCode = expand_dynamic_array( map );
Packit Service a1973e
		if ( errorCode < PAPI_OK ) {
Packit Service a1973e
			_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
			return ( errorCode );
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	i = 0;
Packit Service a1973e
	for ( i = 0; i < map->totalSlots; i++ ) {
Packit Service a1973e
		if ( map->dataSlotArray[i] == NULL ) {
Packit Service a1973e
			ESI->master = master;
Packit Service a1973e
			ESI->EventSetIndex = i;
Packit Service a1973e
			map->fullSlots++;
Packit Service a1973e
			map->availSlots--;
Packit Service a1973e
			map->dataSlotArray[i] = ESI;
Packit Service a1973e
			_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
			return ( PAPI_OK );
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
	return ( PAPI_EBUG );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_create_eventset( int *EventSet, ThreadInfo_t * handle )
Packit Service a1973e
{
Packit Service a1973e
	EventSetInfo_t *ESI;
Packit Service a1973e
	int retval;
Packit Service a1973e
Packit Service a1973e
	/* Is the EventSet already in existence? */
Packit Service a1973e
Packit Service a1973e
	if ( ( EventSet == NULL ) || ( handle == NULL ) )
Packit Service a1973e
		return PAPI_EINVAL;
Packit Service a1973e
Packit Service a1973e
	if ( *EventSet != PAPI_NULL )
Packit Service a1973e
		return PAPI_EINVAL;
Packit Service a1973e
Packit Service a1973e
	/* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
Packit Service a1973e
Packit Service a1973e
	retval = create_EventSet( &ESI );
Packit Service a1973e
	if ( retval != PAPI_OK )
Packit Service a1973e
		return retval;
Packit Service a1973e
Packit Service a1973e
	ESI->CmpIdx = -1;		 /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
Packit Service a1973e
	ESI->state = PAPI_STOPPED;
Packit Service a1973e
Packit Service a1973e
	/* Add it to the global table */
Packit Service a1973e
Packit Service a1973e
	retval = add_EventSet( ESI, handle );
Packit Service a1973e
	if ( retval < PAPI_OK ) {
Packit Service a1973e
		_papi_hwi_free_EventSet( ESI );
Packit Service a1973e
		return retval ;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	*EventSet = ESI->EventSetIndex;
Packit Service a1973e
Packit Service a1973e
	INTDBG( "(%p,%p): new EventSet in slot %d\n",
Packit Service a1973e
			( void * ) EventSet, handle, *EventSet );
Packit Service a1973e
Packit Service a1973e
	return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* This function returns the index of the the next free slot
Packit Service a1973e
   in the EventInfoArray. If EventCode is already in the list,
Packit Service a1973e
   it returns PAPI_ECNFLCT. */
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
Packit Service a1973e
{
Packit Service a1973e
	int k;
Packit Service a1973e
	int lowslot = PAPI_ECNFLCT;
Packit Service a1973e
	int limit = EventInfoArrayLength( ESI );
Packit Service a1973e
Packit Service a1973e
	/* Check for duplicate events and get the lowest empty slot */
Packit Service a1973e
Packit Service a1973e
	for ( k = 0; k < limit; k++ ) {
Packit Service a1973e
		if ( ESI->EventInfoArray[k].event_code == EventCode )
Packit Service a1973e
			return ( PAPI_ECNFLCT );
Packit Service a1973e
		/*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
Packit Service a1973e
		if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
Packit Service a1973e
			lowslot = k;
Packit Service a1973e
			break;
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	return ( lowslot );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* This function returns the index of the EventCode or error */
Packit Service a1973e
/* Index to what? The index to everything stored EventCode in the */
Packit Service a1973e
/* EventSet. */
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_lookup_EventCodeIndex( const EventSetInfo_t * ESI,
Packit Service a1973e
				 unsigned int EventCode )
Packit Service a1973e
{
Packit Service a1973e
	int i;
Packit Service a1973e
	int limit = EventInfoArrayLength( ESI );
Packit Service a1973e
Packit Service a1973e
	for ( i = 0; i < limit; i++ ) {
Packit Service a1973e
	   if ( ESI->EventInfoArray[i].event_code == EventCode ) {
Packit Service a1973e
	      return i;
Packit Service a1973e
	   }
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	return PAPI_EINVAL;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* This function only removes empty EventSets */
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_remove_EventSet( EventSetInfo_t * ESI )
Packit Service a1973e
{
Packit Service a1973e
	DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
Packit Service a1973e
	int i;
Packit Service a1973e
Packit Service a1973e
	i = ESI->EventSetIndex;
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_free_EventSet( ESI );
Packit Service a1973e
Packit Service a1973e
	/* do bookkeeping for PAPI_EVENTSET_MAP */
Packit Service a1973e
Packit Service a1973e
	map->dataSlotArray[i] = NULL;
Packit Service a1973e
	map->availSlots++;
Packit Service a1973e
	map->fullSlots--;
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
	return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* this function checks if an event is already in an EventSet
Packit Service a1973e
     Success, return ESI->NativeInfoArray[] index
Packit Service a1973e
     Fail,    return PAPI_ENOEVNT;
Packit Service a1973e
*/
Packit Service a1973e
static int
Packit Service a1973e
event_already_in_eventset( EventSetInfo_t * ESI, int papi_event )
Packit Service a1973e
{
Packit Service a1973e
   INTDBG( "ENTER: ESI: %p, papi_event: %#x\n", ESI, papi_event);
Packit Service a1973e
   int i;
Packit Service a1973e
Packit Service a1973e
   int nevt = _papi_hwi_eventcode_to_native(papi_event);
Packit Service a1973e
Packit Service a1973e
   /* to find the native event from the native events list */
Packit Service a1973e
   for( i = 0; i < ESI->NativeCount; i++ ) {
Packit Service a1973e
      if ( nevt == ESI->NativeInfoArray[i].ni_event ) {
Packit Service a1973e
         // Also need to check papi event code if set because the same event with different masks
Packit Service a1973e
         // will generate the same libpfm4 event code (what was checked above).  But there will be
Packit Service a1973e
         // different papi events created for it and they need to be handled separately.
Packit Service a1973e
         if (papi_event == ESI->NativeInfoArray[i].ni_papi_code) {
Packit Service a1973e
            INTDBG( "EXIT: event: %#x already mapped at index: %d\n", papi_event, i);
Packit Service a1973e
            return i;
Packit Service a1973e
         }
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
   INTDBG( "EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
   return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* This function goes through the events in an EventSet's EventInfoArray */
Packit Service a1973e
/* And maps each event (whether native or part of a preset) to           */
Packit Service a1973e
/* an event in the EventSets NativeInfoArray.                            */
Packit Service a1973e
Packit Service a1973e
/* We need to do this every time a native event is added to or removed   */
Packit Service a1973e
/* from an eventset.                                                     */
Packit Service a1973e
Packit Service a1973e
/* It is also called after a update controlstate as the components are   */
Packit Service a1973e
/* allowed to re-arrange the native events to fit hardware constraints.  */
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_map_events_to_native( EventSetInfo_t *ESI)
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: ESI: %p, ESI->EventInfoArray: %p, ESI->NativeInfoArray: %p, ESI->NumberOfEvents: %d, ESI->NativeCount: %d\n", ESI, ESI->EventInfoArray, ESI->NativeInfoArray, ESI->NumberOfEvents, ESI->NativeCount);
Packit Service a1973e
Packit Service a1973e
	int i, event, k, n, preset_index = 0, nevt;
Packit Service a1973e
	int total_events = ESI->NumberOfEvents;
Packit Service a1973e
Packit Service a1973e
	event = 0;
Packit Service a1973e
	for( i = 0; i < total_events; i++ ) {
Packit Service a1973e
Packit Service a1973e
		/* find the first event that isn't PAPI_NULL */
Packit Service a1973e
		/* Is this really necessary? --vmw           */
Packit Service a1973e
		while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
Packit Service a1973e
			event++;
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
		/* If it's a preset */
Packit Service a1973e
		if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
Packit Service a1973e
			preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
Packit Service a1973e
Packit Service a1973e
			/* walk all sub-events in the preset */
Packit Service a1973e
			for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
Packit Service a1973e
				nevt = _papi_hwi_presets[preset_index].code[k];
Packit Service a1973e
				if ( nevt == PAPI_NULL ) {
Packit Service a1973e
					break;
Packit Service a1973e
				}
Packit Service a1973e
Packit Service a1973e
				INTDBG("Looking for subevent %#x\n",nevt);
Packit Service a1973e
Packit Service a1973e
				/* Match each sub-event to something in the Native List */
Packit Service a1973e
				for( n = 0; n < ESI->NativeCount; n++ ) {
Packit Service a1973e
					if ( nevt == ESI->NativeInfoArray[n].ni_papi_code ) {
Packit Service a1973e
						INTDBG("Found papi event: %#x, &ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_position %d\n",
Packit Service a1973e
								nevt, n, &(ESI->NativeInfoArray[n]), ESI->NativeInfoArray[n].ni_event, ESI->NativeInfoArray[n].ni_position);
Packit Service a1973e
						ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
Packit Service a1973e
						break;
Packit Service a1973e
					}
Packit Service a1973e
				}
Packit Service a1973e
			}
Packit Service a1973e
		}
Packit Service a1973e
		/* If it's a native event */
Packit Service a1973e
		else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
Packit Service a1973e
			nevt = ( int ) ESI->EventInfoArray[event].event_code;
Packit Service a1973e
Packit Service a1973e
			// get index into native info array for this event
Packit Service a1973e
			int nidx = event_already_in_eventset( ESI, nevt );
Packit Service a1973e
			// if not found, then we need to return an error
Packit Service a1973e
			if (nidx == PAPI_ENOEVNT) {
Packit Service a1973e
				INTDBG("EXIT: needed event not found\n");
Packit Service a1973e
				return;
Packit Service a1973e
			}
Packit Service a1973e
			ESI->EventInfoArray[event].pos[0] = ESI->NativeInfoArray[nidx].ni_position;
Packit Service a1973e
			INTDBG("nidx: %d, ni_position: %d\n", nidx, ESI->NativeInfoArray[nidx].ni_position);
Packit Service a1973e
Packit Service a1973e
		}
Packit Service a1973e
		/* If it's a user-defined event */
Packit Service a1973e
		else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
Packit Service a1973e
			preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_UE_AND_MASK;
Packit Service a1973e
			for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
Packit Service a1973e
				nevt = user_defined_events[preset_index].code[k];
Packit Service a1973e
				INTDBG("nevt: %#x, user_defined_events[%d].code[%d]: %#x, code[%d]: %#x\n",
Packit Service a1973e
						nevt, preset_index, k, user_defined_events[preset_index].code[k], k+1, user_defined_events[preset_index].code[k+1]);
Packit Service a1973e
Packit Service a1973e
				if ( nevt == PAPI_NULL ) break;
Packit Service a1973e
Packit Service a1973e
				/* Match each sub-event to something in the Native List */
Packit Service a1973e
				for ( n = 0; n < ESI->NativeCount; n++ ) {
Packit Service a1973e
					// if this is the event we are looking for, set its position and exit inner loop to look for next sub-event
Packit Service a1973e
					if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[n].ni_event ) {
Packit Service a1973e
						ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
Packit Service a1973e
						break;
Packit Service a1973e
					}
Packit Service a1973e
				}
Packit Service a1973e
			}
Packit Service a1973e
		}
Packit Service a1973e
		event++;
Packit Service a1973e
	}
Packit Service a1973e
	INTDBG("EXIT: \n");
Packit Service a1973e
	return;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
add_native_fail_clean( EventSetInfo_t *ESI, int nevt )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: ESI: %p, nevt: %#x\n", ESI, nevt);
Packit Service a1973e
Packit Service a1973e
   int i, max_counters;
Packit Service a1973e
   int cidx;
Packit Service a1973e
Packit Service a1973e
   cidx = _papi_hwi_component_index( nevt );
Packit Service a1973e
   if (cidx<0) return PAPI_ENOCMP;
Packit Service a1973e
Packit Service a1973e
   max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
Packit Service a1973e
Packit Service a1973e
   /* to find the native event from the native events list */
Packit Service a1973e
   for( i = 0; i < max_counters; i++ ) {
Packit Service a1973e
//	   INTDBG("ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_papi_event_code: %#x, ni_position: %d, ni_owners: %d\n",
Packit Service a1973e
//			   i, &(ESI->NativeInfoArray[i]), ESI->NativeInfoArray[i].ni_event, ESI->NativeInfoArray[i].ni_papi_code, ESI->NativeInfoArray[i].ni_position, ESI->NativeInfoArray[i].ni_owners);
Packit Service a1973e
     if ( nevt == ESI->NativeInfoArray[i].ni_papi_code ) {
Packit Service a1973e
	 ESI->NativeInfoArray[i].ni_owners--;
Packit Service a1973e
	 /* to clean the entry in the nativeInfo array */
Packit Service a1973e
	 if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
Packit Service a1973e
	    ESI->NativeInfoArray[i].ni_event = -1;
Packit Service a1973e
	    ESI->NativeInfoArray[i].ni_position = -1;
Packit Service a1973e
	    ESI->NativeInfoArray[i].ni_papi_code = -1;
Packit Service a1973e
	    ESI->NativeCount--;
Packit Service a1973e
	 }
Packit Service a1973e
	 INTDBG( "EXIT: nevt: %#x, returned: %d\n", nevt, i);
Packit Service a1973e
	 return i;
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
	INTDBG( "EXIT: returned: -1\n");
Packit Service a1973e
   return -1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* since update_control_state trashes overflow settings, this puts things
Packit Service a1973e
   back into balance. */
Packit Service a1973e
static int
Packit Service a1973e
update_overflow( EventSetInfo_t * ESI )
Packit Service a1973e
{
Packit Service a1973e
   int i, retval = PAPI_OK;
Packit Service a1973e
Packit Service a1973e
   if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
Packit Service a1973e
      for( i = 0; i < ESI->overflow.event_counter; i++ ) {
Packit Service a1973e
	 retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
Packit Service a1973e
							ESI->overflow.EventIndex[i],
Packit Service a1973e
							ESI->overflow.threshold[i] );
Packit Service a1973e
	 if ( retval != PAPI_OK ) {
Packit Service a1973e
	    break;
Packit Service a1973e
	 }
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
   return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* this function is called by _papi_hwi_add_event when adding native events 
Packit Service a1973e
   ESI:   event set to add the events to
Packit Service a1973e
   nevnt: pointer to array of native event table indexes to add
Packit Service a1973e
   size:  number of native events to add
Packit Service a1973e
   out:   ???
Packit Service a1973e
Packit Service a1973e
   return:  < 0 = error
Packit Service a1973e
              0 = no new events added
Packit Service a1973e
              1 = new events added
Packit Service a1973e
*/
Packit Service a1973e
static int
Packit Service a1973e
add_native_events( EventSetInfo_t *ESI, unsigned int *nevt, 
Packit Service a1973e
                   int size, EventInfo_t *out )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG ("ENTER: ESI: %p, nevt: %p, size: %d, out: %p\n", ESI, nevt, size, out);
Packit Service a1973e
   int nidx, i, j, added_events = 0;
Packit Service a1973e
   int retval, retval2;
Packit Service a1973e
   int max_counters;
Packit Service a1973e
   hwd_context_t *context;
Packit Service a1973e
Packit Service a1973e
   max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
Packit Service a1973e
Packit Service a1973e
   /* Walk through the list of native events, adding them */
Packit Service a1973e
   for( i = 0; i < size; i++ ) {
Packit Service a1973e
Packit Service a1973e
      /* Check to see if event is already in EventSet */
Packit Service a1973e
      nidx = event_already_in_eventset( ESI, nevt[i] );
Packit Service a1973e
Packit Service a1973e
      if ( nidx >= 0 ) {
Packit Service a1973e
	 /* Event is already there.  Set position */
Packit Service a1973e
	 out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
Packit Service a1973e
	 ESI->NativeInfoArray[nidx].ni_owners++;
Packit Service a1973e
	 continue;
Packit Service a1973e
      }
Packit Service a1973e
Packit Service a1973e
	 /* Event wasn't already there */
Packit Service a1973e
Packit Service a1973e
	 if ( ESI->NativeCount == max_counters ) {
Packit Service a1973e
Packit Service a1973e
	    /* No more room in counters! */
Packit Service a1973e
	    for( j = 0; j < i; j++ ) {
Packit Service a1973e
	       if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
Packit Service a1973e
		  out->pos[j] = -1;
Packit Service a1973e
		  continue;
Packit Service a1973e
	       }
Packit Service a1973e
	       INTDBG( "should not happen!\n" );
Packit Service a1973e
	    }
Packit Service a1973e
	    INTDBG( "EXIT: counters are full!\n" );
Packit Service a1973e
	    return PAPI_ECOUNT;
Packit Service a1973e
	 }
Packit Service a1973e
			
Packit Service a1973e
	    /* there is an empty slot for the native event; */
Packit Service a1973e
	    /* initialize the native index for the new added event */
Packit Service a1973e
	    INTDBG( "Adding nevt[%d]: %#x, ESI->NativeInfoArray[%d]: %p, Component: %d\n",
Packit Service a1973e
		    i, nevt[i], ESI->NativeCount, &ESI->NativeInfoArray[ESI->NativeCount], ESI->CmpIdx );
Packit Service a1973e
	    ESI->NativeInfoArray[ESI->NativeCount].ni_event = 
Packit Service a1973e
			  _papi_hwi_eventcode_to_native(nevt[i]);
Packit Service a1973e
	    ESI->NativeInfoArray[ESI->NativeCount].ni_papi_code = nevt[i];
Packit Service a1973e
Packit Service a1973e
	    ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
Packit Service a1973e
	    ESI->NativeCount++;
Packit Service a1973e
	    added_events++;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   INTDBG("added_events: %d\n", added_events);
Packit Service a1973e
Packit Service a1973e
   /* if we added events we need to tell the component so it */
Packit Service a1973e
   /* can add them too.                                      */
Packit Service a1973e
   if ( added_events ) {
Packit Service a1973e
      /* get the context we should use for this event set */
Packit Service a1973e
      context = _papi_hwi_get_context( ESI, NULL );
Packit Service a1973e
	   
Packit Service a1973e
      if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
Packit Service a1973e
Packit Service a1973e
	 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
Packit Service a1973e
		  ESI->NativeInfoArray,
Packit Service a1973e
		  ESI->NativeCount,
Packit Service a1973e
		  context);
Packit Service a1973e
	 if ( retval != PAPI_OK ) {
Packit Service a1973e
clean:
Packit Service a1973e
	    for( i = 0; i < size; i++ ) {
Packit Service a1973e
	       if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
Packit Service a1973e
		  out->pos[i] = -1;
Packit Service a1973e
		  continue;
Packit Service a1973e
	       }
Packit Service a1973e
	       INTDBG( "should not happen!\n" );
Packit Service a1973e
	    }
Packit Service a1973e
	    /* re-establish the control state after the previous error */
Packit Service a1973e
	    retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state( 
Packit Service a1973e
                       ESI->ctl_state,
Packit Service a1973e
		       ESI->NativeInfoArray,
Packit Service a1973e
		       ESI->NativeCount,
Packit Service a1973e
		       context);
Packit Service a1973e
	    if ( retval2 != PAPI_OK ) {
Packit Service a1973e
	       PAPIERROR("update_control_state failed to re-establish working events!" );
Packit Service a1973e
	       INTDBG( "EXIT: update_control_state returned: %d\n", retval2);
Packit Service a1973e
	       return retval2;
Packit Service a1973e
	    }
Packit Service a1973e
	    INTDBG( "EXIT: update_control_state returned: %d\n", retval);
Packit Service a1973e
	    return retval;
Packit Service a1973e
	 }
Packit Service a1973e
     INTDBG( "EXIT: update_control_state returned: %d, we return: 1 (need remap)\n", retval);
Packit Service a1973e
	 return 1; /* need remap */
Packit Service a1973e
      } else {
Packit Service a1973e
	 retval = PAPI_EMISC;
Packit Service a1973e
	 goto clean;
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
   INTDBG( "EXIT: PAPI_OK\n");
Packit Service a1973e
   return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_add_event( EventSetInfo_t * ESI, int EventCode )
Packit Service a1973e
{
Packit Service a1973e
    INTDBG("ENTER: ESI: %p (%d), EventCode: %#x\n", ESI, ESI->EventSetIndex, EventCode);
Packit Service a1973e
Packit Service a1973e
    int i, j, thisindex, remap, retval = PAPI_OK;
Packit Service a1973e
    int cidx;
Packit Service a1973e
Packit Service a1973e
    cidx=_papi_hwi_component_index( EventCode );
Packit Service a1973e
    if (cidx<0) return PAPI_ENOCMP;
Packit Service a1973e
Packit Service a1973e
    /* Sanity check that the new EventCode is from the same component */
Packit Service a1973e
    /* as previous events.                                            */
Packit Service a1973e
    
Packit Service a1973e
    if ( ESI->CmpIdx < 0 ) {
Packit Service a1973e
       if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx)) != PAPI_OK ) {
Packit Service a1973e
   	      INTDBG("EXIT: Error assigning eventset to component index %d\n", cidx);
Packit Service a1973e
          return retval;
Packit Service a1973e
       }
Packit Service a1973e
    } else {
Packit Service a1973e
       if ( ESI->CmpIdx != cidx ) {
Packit Service a1973e
    	    INTDBG("EXIT: Event is not valid for component index %d\n", cidx);
Packit Service a1973e
    	    return PAPI_EINVAL;
Packit Service a1973e
       }
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    /* Make sure the event is not present and get the next free slot. */
Packit Service a1973e
    thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
Packit Service a1973e
    if ( thisindex < PAPI_OK ) {
Packit Service a1973e
       return thisindex;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    INTDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
Packit Service a1973e
Packit Service a1973e
    /* If it is a software MPX EventSet, add it to the multiplex data structure */
Packit Service a1973e
    /* and this thread's multiplex list                                         */
Packit Service a1973e
Packit Service a1973e
    if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
Packit Service a1973e
Packit Service a1973e
       /* Handle preset case */
Packit Service a1973e
       if ( IS_PRESET(EventCode) ) {
Packit Service a1973e
	  int count;
Packit Service a1973e
	  int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
Packit Service a1973e
Packit Service a1973e
	  /* Check if it's within the valid range */
Packit Service a1973e
	  if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
Packit Service a1973e
	     return PAPI_EINVAL;
Packit Service a1973e
	  }
Packit Service a1973e
Packit Service a1973e
	  /* count the number of native events in this preset */
Packit Service a1973e
	  count = ( int ) _papi_hwi_presets[preset_index].count;
Packit Service a1973e
Packit Service a1973e
	  /* Check if event exists */
Packit Service a1973e
	  if ( !count ) {
Packit Service a1973e
	     return PAPI_ENOEVNT;
Packit Service a1973e
	  }
Packit Service a1973e
			
Packit Service a1973e
	  /* check if the native events have been used as overflow events */
Packit Service a1973e
	  /* this is not allowed                                          */
Packit Service a1973e
	  if ( ESI->state & PAPI_OVERFLOWING ) {
Packit Service a1973e
	     for( i = 0; i < count; i++ ) {
Packit Service a1973e
		for( j = 0; j < ESI->overflow.event_counter; j++ ) {
Packit Service a1973e
		  if ( ESI->overflow.EventCode[j] ==(int)
Packit Service a1973e
			( _papi_hwi_presets[preset_index].code[i] ) ) {
Packit Service a1973e
		      return PAPI_ECNFLCT;
Packit Service a1973e
		   }
Packit Service a1973e
		}
Packit Service a1973e
	     }
Packit Service a1973e
	  }
Packit Service a1973e
Packit Service a1973e
	  /* Try to add the preset. */
Packit Service a1973e
Packit Service a1973e
	  remap = add_native_events( ESI,
Packit Service a1973e
				     _papi_hwi_presets[preset_index].code,
Packit Service a1973e
				     count, &ESI->EventInfoArray[thisindex] );
Packit Service a1973e
	  if ( remap < 0 ) {
Packit Service a1973e
	     return remap;
Packit Service a1973e
	  }
Packit Service a1973e
          else {
Packit Service a1973e
	     /* Fill in the EventCode (machine independent) information */
Packit Service a1973e
	     ESI->EventInfoArray[thisindex].event_code = 
Packit Service a1973e
                                  ( unsigned int ) EventCode;
Packit Service a1973e
	     ESI->EventInfoArray[thisindex].derived =
Packit Service a1973e
				  _papi_hwi_presets[preset_index].derived_int;
Packit Service a1973e
	     ESI->EventInfoArray[thisindex].ops =
Packit Service a1973e
				  _papi_hwi_presets[preset_index].postfix;
Packit Service a1973e
             ESI->NumberOfEvents++;
Packit Service a1973e
	     _papi_hwi_map_events_to_native( ESI );
Packit Service a1973e
	     
Packit Service a1973e
	  }
Packit Service a1973e
       }
Packit Service a1973e
       /* Handle adding Native events */
Packit Service a1973e
       else if ( IS_NATIVE(EventCode) ) {
Packit Service a1973e
Packit Service a1973e
	  /* Check if native event exists */
Packit Service a1973e
	  if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
Packit Service a1973e
	     return PAPI_ENOEVNT;
Packit Service a1973e
	  }
Packit Service a1973e
			
Packit Service a1973e
	  /* check if the native events have been used as overflow events */
Packit Service a1973e
	  /* This is not allowed                                          */
Packit Service a1973e
	  if ( ESI->state & PAPI_OVERFLOWING ) {
Packit Service a1973e
	     for( j = 0; j < ESI->overflow.event_counter; j++ ) {
Packit Service a1973e
	        if ( EventCode == ESI->overflow.EventCode[j] ) {
Packit Service a1973e
		   return PAPI_ECNFLCT;
Packit Service a1973e
		}
Packit Service a1973e
	     }
Packit Service a1973e
	  }
Packit Service a1973e
Packit Service a1973e
	  /* Try to add the native event. */
Packit Service a1973e
Packit Service a1973e
	  remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
Packit Service a1973e
				     &ESI->EventInfoArray[thisindex] );
Packit Service a1973e
Packit Service a1973e
	  if ( remap < 0 ) {
Packit Service a1973e
	     return remap;
Packit Service a1973e
	  } else {
Packit Service a1973e
Packit Service a1973e
	     /* Fill in the EventCode (machine independent) information */
Packit Service a1973e
	     ESI->EventInfoArray[thisindex].event_code = 
Packit Service a1973e
	                                   ( unsigned int ) EventCode;
Packit Service a1973e
             ESI->NumberOfEvents++;
Packit Service a1973e
	     _papi_hwi_map_events_to_native( ESI );
Packit Service a1973e
	     
Packit Service a1973e
	  }
Packit Service a1973e
       } else if ( IS_USER_DEFINED( EventCode ) ) {
Packit Service a1973e
		 int count;
Packit Service a1973e
		 int index = EventCode & PAPI_UE_AND_MASK;
Packit Service a1973e
Packit Service a1973e
		 if ( index < 0 || index >= user_defined_events_count )
Packit Service a1973e
		   return ( PAPI_EINVAL );
Packit Service a1973e
Packit Service a1973e
		 count = ( int ) user_defined_events[index].count;
Packit Service a1973e
Packit Service a1973e
		 for ( i = 0; i < count; i++ ) {
Packit Service a1973e
		   for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
Packit Service a1973e
			 if ( ESI->overflow.EventCode[j] ==
Packit Service a1973e
				 (int)(user_defined_events[index].code[i]) ) {
Packit Service a1973e
			   return ( PAPI_EBUG );
Packit Service a1973e
			 }
Packit Service a1973e
		   }
Packit Service a1973e
		 }
Packit Service a1973e
Packit Service a1973e
		 remap = add_native_events( ESI,
Packit Service a1973e
			 user_defined_events[index].code,
Packit Service a1973e
			 count, &ESI->EventInfoArray[thisindex] );
Packit Service a1973e
Packit Service a1973e
		 if ( remap < 0 ) {
Packit Service a1973e
		   return remap;
Packit Service a1973e
		 } else {
Packit Service a1973e
		   ESI->EventInfoArray[thisindex].event_code = (unsigned int) EventCode;
Packit Service a1973e
		   ESI->EventInfoArray[thisindex].derived = user_defined_events[index].derived_int;
Packit Service a1973e
		   ESI->EventInfoArray[thisindex].ops = user_defined_events[index].postfix;
Packit Service a1973e
           ESI->NumberOfEvents++;
Packit Service a1973e
		   _papi_hwi_map_events_to_native( ESI );
Packit Service a1973e
		 }
Packit Service a1973e
       } else {
Packit Service a1973e
Packit Service a1973e
	  /* not Native, Preset, or User events */
Packit Service a1973e
Packit Service a1973e
	  return PAPI_EBUG;
Packit Service a1973e
       }
Packit Service a1973e
    }
Packit Service a1973e
    else {
Packit Service a1973e
		
Packit Service a1973e
       /* Multiplexing is special. See multiplex.c */
Packit Service a1973e
Packit Service a1973e
       retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
Packit Service a1973e
			       ESI->domain.domain, 
Packit Service a1973e
			       ESI->granularity.granularity );
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
       if ( retval < PAPI_OK ) {
Packit Service a1973e
	  return retval;
Packit Service a1973e
       }
Packit Service a1973e
Packit Service a1973e
       /* Relevant (???) */
Packit Service a1973e
       ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;	
Packit Service a1973e
       ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
Packit Service a1973e
Packit Service a1973e
       ESI->NumberOfEvents++;
Packit Service a1973e
Packit Service a1973e
       /* event is in the EventInfoArray but not mapped to the NativeEvents */
Packit Service a1973e
       /* this causes issues if you try to set overflow on the event.       */
Packit Service a1973e
       /* in theory this wouldn't matter anyway.                            */
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    /* reinstate the overflows if any */
Packit Service a1973e
    retval=update_overflow( ESI );
Packit Service a1973e
Packit Service a1973e
    return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
remove_native_events( EventSetInfo_t *ESI, int *nevt, int size )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG( "Entry: ESI: %p, nevt: %p, size: %d\n", ESI, nevt, size);
Packit Service a1973e
   NativeInfo_t *native = ESI->NativeInfoArray;
Packit Service a1973e
   hwd_context_t *context;
Packit Service a1973e
   int i, j, zero = 0, retval;
Packit Service a1973e
Packit Service a1973e
   /* Remove the references to this event from the native events:
Packit Service a1973e
      for all the metrics in this event,
Packit Service a1973e
      compare to each native event in this event set,
Packit Service a1973e
      and decrement owners if they match  */
Packit Service a1973e
   for( i = 0; i < size; i++ ) {
Packit Service a1973e
	int cevt = _papi_hwi_eventcode_to_native(nevt[i]);
Packit Service a1973e
//	INTDBG( "nevt[%d]: %#x, cevt: %#x\n", i, nevt[i], cevt);
Packit Service a1973e
      for( j = 0; j < ESI->NativeCount; j++ ) {
Packit Service a1973e
	 if ((native[j].ni_event == cevt)  &&  (native[j].ni_papi_code == nevt[i]) ) {
Packit Service a1973e
//		INTDBG( "native[%d]: %p, ni_papi_code: %#x, ni_event: %#x, ni_position: %d, ni_owners: %d\n", 
Packit Service a1973e
//			j, &(native[j]), native[j].ni_papi_code, native[j].ni_event, native[j].ni_position, native[j].ni_owners);
Packit Service a1973e
	    native[j].ni_owners--;
Packit Service a1973e
	    if ( native[j].ni_owners == 0 ) {
Packit Service a1973e
	       zero++;
Packit Service a1973e
	    }
Packit Service a1973e
	    break;
Packit Service a1973e
	 }
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   /* Remove any native events from the array if owners dropped to zero.
Packit Service a1973e
      The NativeInfoArray must be dense, with no empty slots, so if we
Packit Service a1973e
      remove an element, we must compact the list */
Packit Service a1973e
   for( i = 0; i < ESI->NativeCount; i++ ) {
Packit Service a1973e
Packit Service a1973e
      if ( native[i].ni_event == -1 ) continue;
Packit Service a1973e
Packit Service a1973e
      if ( native[i].ni_owners == 0 ) {
Packit Service a1973e
	 int copy = 0;
Packit Service a1973e
	 int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
Packit Service a1973e
	 for( j = ESI->NativeCount - 1; j > i; j-- ) {
Packit Service a1973e
	    if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
Packit Service a1973e
	    else {
Packit Service a1973e
	       /* copy j into i */
Packit Service a1973e
	       native[i].ni_event = native[j].ni_event;
Packit Service a1973e
	       native[i].ni_position = native[j].ni_position;
Packit Service a1973e
	       native[i].ni_owners = native[j].ni_owners;
Packit Service a1973e
	       /* copy opaque [j].ni_bits to [i].ni_bits */
Packit Service a1973e
	       memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
Packit Service a1973e
	       /* reset j to initialized state */
Packit Service a1973e
	       native[j].ni_event = -1;
Packit Service a1973e
	       native[j].ni_position = -1;
Packit Service a1973e
	       native[j].ni_owners = 0;
Packit Service a1973e
	       copy++;
Packit Service a1973e
	       break;
Packit Service a1973e
	    }
Packit Service a1973e
	 }
Packit Service a1973e
Packit Service a1973e
	 if ( copy == 0 ) {
Packit Service a1973e
	    /* set this structure back to empty state */
Packit Service a1973e
	    /* ni_owners is already 0 and contents of ni_bits doesn't matter */
Packit Service a1973e
	    native[i].ni_event = -1;
Packit Service a1973e
	    native[i].ni_position = -1;
Packit Service a1973e
	 }
Packit Service a1973e
      }
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
	INTDBG( "ESI->NativeCount: %d, zero: %d\n", ESI->NativeCount, zero);
Packit Service a1973e
Packit Service a1973e
   /* to reset hwd_control_state values */
Packit Service a1973e
   ESI->NativeCount -= zero;
Packit Service a1973e
Packit Service a1973e
   /* If we removed any elements, 
Packit Service a1973e
      clear the now empty slots, reinitialize the index, and update the count.
Packit Service a1973e
      Then send the info down to the component to update the hwd control structure. */
Packit Service a1973e
	retval = PAPI_OK;
Packit Service a1973e
	if ( zero ) {
Packit Service a1973e
      /* get the context we should use for this event set */
Packit Service a1973e
      context = _papi_hwi_get_context( ESI, NULL );
Packit Service a1973e
		retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
Packit Service a1973e
														  native, ESI->NativeCount, context);
Packit Service a1973e
		if ( retval == PAPI_OK )
Packit Service a1973e
			retval = update_overflow( ESI );
Packit Service a1973e
	}
Packit Service a1973e
	return ( retval );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_remove_event( EventSetInfo_t * ESI, int EventCode )
Packit Service a1973e
{
Packit Service a1973e
	int j = 0, retval, thisindex;
Packit Service a1973e
	EventInfo_t *array;
Packit Service a1973e
Packit Service a1973e
	thisindex =
Packit Service a1973e
		_papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
Packit Service a1973e
	if ( thisindex < PAPI_OK )
Packit Service a1973e
		return ( thisindex );
Packit Service a1973e
Packit Service a1973e
	/* If it is a MPX EventSet, remove it from the multiplex data structure and
Packit Service a1973e
	   this threads multiplex list */
Packit Service a1973e
Packit Service a1973e
	if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
Packit Service a1973e
		retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
Packit Service a1973e
		if ( retval < PAPI_OK )
Packit Service a1973e
			return ( retval );
Packit Service a1973e
	} else
Packit Service a1973e
		/* Remove the events hardware dependent stuff from the EventSet */
Packit Service a1973e
	{
Packit Service a1973e
		if ( IS_PRESET(EventCode) ) {
Packit Service a1973e
			int preset_index = EventCode & PAPI_PRESET_AND_MASK;
Packit Service a1973e
Packit Service a1973e
			/* Check if it's within the valid range */
Packit Service a1973e
			if ( ( preset_index < 0 ) ||
Packit Service a1973e
				 ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
Packit Service a1973e
				return PAPI_EINVAL;
Packit Service a1973e
Packit Service a1973e
			/* Check if event exists */
Packit Service a1973e
			if ( !_papi_hwi_presets[preset_index].count )
Packit Service a1973e
				return PAPI_ENOEVNT;
Packit Service a1973e
Packit Service a1973e
			/* Remove the preset event. */
Packit Service a1973e
			for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
Packit Service a1973e
				  j++ );
Packit Service a1973e
			retval = remove_native_events( ESI, ( int * )_papi_hwi_presets[preset_index].code, j );
Packit Service a1973e
			if ( retval != PAPI_OK )
Packit Service a1973e
				return ( retval );
Packit Service a1973e
		} else if ( IS_NATIVE(EventCode) ) {
Packit Service a1973e
			/* Check if native event exists */
Packit Service a1973e
			if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
Packit Service a1973e
				 PAPI_OK )
Packit Service a1973e
				return PAPI_ENOEVNT;
Packit Service a1973e
Packit Service a1973e
			/* Remove the native event. */
Packit Service a1973e
			retval = remove_native_events( ESI, &EventCode, 1 );
Packit Service a1973e
			if ( retval != PAPI_OK )
Packit Service a1973e
				return ( retval );
Packit Service a1973e
		} else if ( IS_USER_DEFINED( EventCode ) ) {
Packit Service a1973e
		  int index = EventCode & PAPI_UE_AND_MASK;
Packit Service a1973e
Packit Service a1973e
		  if ( (index < 0) || (index >= user_defined_events_count) )
Packit Service a1973e
			return ( PAPI_EINVAL );
Packit Service a1973e
Packit Service a1973e
		  for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
Packit Service a1973e
			  user_defined_events[index].code[j] != 0; j++ ) {
Packit Service a1973e
			retval = remove_native_events( ESI, ( int * )user_defined_events[index].code, j);
Packit Service a1973e
Packit Service a1973e
			if ( retval != PAPI_OK )
Packit Service a1973e
			  return ( retval );
Packit Service a1973e
		  }
Packit Service a1973e
		} else
Packit Service a1973e
			return ( PAPI_ENOEVNT );
Packit Service a1973e
	}
Packit Service a1973e
	array = ESI->EventInfoArray;
Packit Service a1973e
Packit Service a1973e
	/* Compact the Event Info Array list if it's not the last event */
Packit Service a1973e
	/* clear the newly empty slot in the array */
Packit Service a1973e
	for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
Packit Service a1973e
		array[thisindex] = array[thisindex + 1];
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
Packit Service a1973e
	for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
Packit Service a1973e
		array[thisindex].pos[j] = PAPI_NULL;
Packit Service a1973e
	array[thisindex].ops = NULL;
Packit Service a1973e
	array[thisindex].derived = NOT_DERIVED;
Packit Service a1973e
	ESI->NumberOfEvents--;
Packit Service a1973e
Packit Service a1973e
	return ( PAPI_OK );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_read( hwd_context_t * context, EventSetInfo_t * ESI,
Packit Service a1973e
				long long *values )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: context: %p, ESI: %p, values: %p\n", context, ESI, values);
Packit Service a1973e
	int retval;
Packit Service a1973e
	long long *dp = NULL;
Packit Service a1973e
	int i, index;
Packit Service a1973e
Packit Service a1973e
	retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state, 
Packit Service a1973e
					       &dp, ESI->state );
Packit Service a1973e
	if ( retval != PAPI_OK ) {
Packit Service a1973e
		INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
	   return retval;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* This routine distributes hardware counters to software counters in the
Packit Service a1973e
	   order that they were added. Note that the higher level
Packit Service a1973e
	   EventInfoArray[i] entries may not be contiguous because the user
Packit Service a1973e
	   has the right to remove an event.
Packit Service a1973e
	   But if we do compaction after remove event, this function can be 
Packit Service a1973e
	   changed.  
Packit Service a1973e
	 */
Packit Service a1973e
Packit Service a1973e
	for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
Packit Service a1973e
Packit Service a1973e
		index = ESI->EventInfoArray[i].pos[0];
Packit Service a1973e
Packit Service a1973e
		if ( index == -1 )
Packit Service a1973e
			continue;
Packit Service a1973e
Packit Service a1973e
		INTDBG( "ESI->EventInfoArray: %p, pos[%d]: %d, dp[%d]: %lld, derived[%d]: %#x\n", ESI->EventInfoArray, i, index, index, dp[index], i, ESI->EventInfoArray[i].derived );
Packit Service a1973e
Packit Service a1973e
		/* If this is not a derived event */
Packit Service a1973e
Packit Service a1973e
		if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
Packit Service a1973e
			values[i] = dp[index];
Packit Service a1973e
			INTDBG( "value: %#llx\n", values[i] );
Packit Service a1973e
		} else {			 /* If this is a derived event */
Packit Service a1973e
			values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
Packit Service a1973e
#ifdef DEBUG
Packit Service a1973e
			if ( values[i] < ( long long ) 0 ) {
Packit Service a1973e
				INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
Packit Service a1973e
			}
Packit Service a1973e
			INTDBG( "derived value: %#llx \n", values[i] );
Packit Service a1973e
#endif
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	INTDBG("EXIT: PAPI_OK\n");
Packit Service a1973e
	return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_cleanup_eventset( EventSetInfo_t * ESI )
Packit Service a1973e
{
Packit Service a1973e
   int i, j, num_cntrs, retval;
Packit Service a1973e
   hwd_context_t *context;
Packit Service a1973e
   int EventCode;
Packit Service a1973e
   NativeInfo_t *native;
Packit Service a1973e
   if ( !_papi_hwi_invalid_cmp( ESI->CmpIdx ) ) {
Packit Service a1973e
   num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
Packit Service a1973e
Packit Service a1973e
   for(i=0;i
Packit Service a1973e
Packit Service a1973e
      EventCode=ESI->EventInfoArray[i].event_code;     
Packit Service a1973e
Packit Service a1973e
      /* skip if event not there */
Packit Service a1973e
      if ( EventCode == PAPI_NULL ) continue;
Packit Service a1973e
Packit Service a1973e
      /* If it is a MPX EventSet, remove it from the multiplex */
Packit Service a1973e
      /* data structure and this thread's multiplex list */
Packit Service a1973e
Packit Service a1973e
      if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
Packit Service a1973e
	 retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
Packit Service a1973e
	 if ( retval < PAPI_OK )
Packit Service a1973e
	    return retval;
Packit Service a1973e
      } else {
Packit Service a1973e
Packit Service a1973e
	  native = ESI->NativeInfoArray;
Packit Service a1973e
Packit Service a1973e
	  /* clear out ESI->NativeInfoArray */
Packit Service a1973e
	  /* do we really need to do this, seeing as we free() it later? */
Packit Service a1973e
Packit Service a1973e
	  for( j = 0; j < ESI->NativeCount; j++ ) {
Packit Service a1973e
	     native[j].ni_event = -1;
Packit Service a1973e
	     native[j].ni_position = -1;
Packit Service a1973e
	     native[j].ni_owners = 0;
Packit Service a1973e
	     /* native[j].ni_bits?? */
Packit Service a1973e
	  }
Packit Service a1973e
      }
Packit Service a1973e
Packit Service a1973e
      /* do we really need to do this, seeing as we free() it later? */
Packit Service a1973e
      ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
Packit Service a1973e
      for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
Packit Service a1973e
	  ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
Packit Service a1973e
      }
Packit Service a1973e
      ESI->EventInfoArray[i].ops = NULL;
Packit Service a1973e
      ESI->EventInfoArray[i].derived = NOT_DERIVED;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   context = _papi_hwi_get_context( ESI, NULL );
Packit Service a1973e
   /* calling with count of 0 equals a close? */
Packit Service a1973e
   retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
Packit Service a1973e
			       NULL, 0, context);
Packit Service a1973e
   if (retval!=PAPI_OK) {
Packit Service a1973e
     return retval;
Packit Service a1973e
   }
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   ESI->CmpIdx = -1;
Packit Service a1973e
   ESI->NumberOfEvents = 0;
Packit Service a1973e
   ESI->NativeCount = 0;
Packit Service a1973e
Packit Service a1973e
   if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
Packit Service a1973e
		   papi_free( ESI->multiplex.mpx_evset );
Packit Service a1973e
Packit Service a1973e
   if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
Packit Service a1973e
		   _papi_hwi_shutdown_cpu( ESI->CpuInfo );
Packit Service a1973e
Packit Service a1973e
   if ( ESI->ctl_state )
Packit Service a1973e
      papi_free( ESI->ctl_state );
Packit Service a1973e
Packit Service a1973e
   if ( ESI->sw_stop )
Packit Service a1973e
      papi_free( ESI->sw_stop );
Packit Service a1973e
Packit Service a1973e
   if ( ESI->hw_start )
Packit Service a1973e
      papi_free( ESI->hw_start );
Packit Service a1973e
	
Packit Service a1973e
   if ( ESI->EventInfoArray )
Packit Service a1973e
      papi_free( ESI->EventInfoArray );
Packit Service a1973e
	
Packit Service a1973e
   if ( ESI->NativeInfoArray ) 
Packit Service a1973e
      papi_free( ESI->NativeInfoArray );
Packit Service a1973e
Packit Service a1973e
   if ( ESI->NativeBits ) 
Packit Service a1973e
      papi_free( ESI->NativeBits );
Packit Service a1973e
	
Packit Service a1973e
   if ( ESI->overflow.deadline )
Packit Service a1973e
      papi_free( ESI->overflow.deadline );
Packit Service a1973e
	
Packit Service a1973e
   if ( ESI->profile.prof )
Packit Service a1973e
      papi_free( ESI->profile.prof );
Packit Service a1973e
Packit Service a1973e
   ESI->ctl_state = NULL;
Packit Service a1973e
   ESI->sw_stop = NULL;
Packit Service a1973e
   ESI->hw_start = NULL;
Packit Service a1973e
   ESI->EventInfoArray = NULL;
Packit Service a1973e
   ESI->NativeInfoArray = NULL;
Packit Service a1973e
   ESI->NativeBits = NULL;
Packit Service a1973e
Packit Service a1973e
   memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
Packit Service a1973e
   memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
Packit Service a1973e
   memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
Packit Service a1973e
   memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
Packit Service a1973e
   memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
Packit Service a1973e
   memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
Packit Service a1973e
   memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
Packit Service a1973e
   memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
Packit Service a1973e
Packit Service a1973e
   ESI->CpuInfo = NULL;
Packit Service a1973e
Packit Service a1973e
   return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_convert_eventset_to_multiplex( _papi_int_multiplex_t * mpx )
Packit Service a1973e
{
Packit Service a1973e
	int retval, i, j = 0, *mpxlist = NULL;
Packit Service a1973e
	EventSetInfo_t *ESI = mpx->ESI;
Packit Service a1973e
	int flags = mpx->flags;
Packit Service a1973e
Packit Service a1973e
	/* If there are any events in the EventSet, 
Packit Service a1973e
	   convert them to multiplex events */
Packit Service a1973e
Packit Service a1973e
	if ( ESI->NumberOfEvents ) {
Packit Service a1973e
Packit Service a1973e
		mpxlist =
Packit Service a1973e
			( int * ) papi_malloc( sizeof ( int ) *
Packit Service a1973e
								   ( size_t ) ESI->NumberOfEvents );
Packit Service a1973e
		if ( mpxlist == NULL )
Packit Service a1973e
			return ( PAPI_ENOMEM );
Packit Service a1973e
Packit Service a1973e
		/* Build the args to MPX_add_events(). */
Packit Service a1973e
Packit Service a1973e
		/* Remember the EventInfoArray can be sparse
Packit Service a1973e
		   and the data can be non-contiguous */
Packit Service a1973e
Packit Service a1973e
		for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
Packit Service a1973e
			if ( ESI->EventInfoArray[i].event_code !=
Packit Service a1973e
				 ( unsigned int ) PAPI_NULL )
Packit Service a1973e
				mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
Packit Service a1973e
Packit Service a1973e
		/* Resize the EventInfo_t array */
Packit Service a1973e
Packit Service a1973e
		if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
Packit Service a1973e
			 ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
Packit Service a1973e
			   ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
Packit Service a1973e
			retval =
Packit Service a1973e
				MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
Packit Service a1973e
								ESI->domain.domain,
Packit Service a1973e
								ESI->granularity.granularity );
Packit Service a1973e
			if ( retval != PAPI_OK ) {
Packit Service a1973e
				papi_free( mpxlist );
Packit Service a1973e
				return ( retval );
Packit Service a1973e
			}
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
		papi_free( mpxlist );
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* Update the state before initialization! */
Packit Service a1973e
Packit Service a1973e
	ESI->state |= PAPI_MULTIPLEXING;
Packit Service a1973e
	if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
Packit Service a1973e
		 ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
Packit Service a1973e
		ESI->multiplex.flags = PAPI_MULTIPLEX_FORCE_SW;
Packit Service a1973e
	ESI->multiplex.ns = ( int ) mpx->ns;
Packit Service a1973e
Packit Service a1973e
	return ( PAPI_OK );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#include "components_config.h"
Packit Service a1973e
Packit Service a1973e
int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Routine that initializes all available components.
Packit Service a1973e
 * A component is available if a pointer to its info vector
Packit Service a1973e
 * appears in the NULL terminated_papi_hwd table.
Packit Service a1973e
 */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_init_global( void )
Packit Service a1973e
{
Packit Service a1973e
        int retval, i = 0;
Packit Service a1973e
Packit Service a1973e
	retval = _papi_hwi_innoculate_os_vector( &_papi_os_vector );
Packit Service a1973e
	if ( retval != PAPI_OK ) {
Packit Service a1973e
	   return retval;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	while ( _papi_hwd[i] ) {
Packit Service a1973e
Packit Service a1973e
	   retval = _papi_hwi_innoculate_vector( _papi_hwd[i] );
Packit Service a1973e
	   if ( retval != PAPI_OK ) {
Packit Service a1973e
	      return retval;
Packit Service a1973e
	   }
Packit Service a1973e
Packit Service a1973e
	   /* We can be disabled by user before init */
Packit Service a1973e
	   if (!_papi_hwd[i]->cmp_info.disabled) {
Packit Service a1973e
	      retval = _papi_hwd[i]->init_component( i );
Packit Service a1973e
	      _papi_hwd[i]->cmp_info.disabled=retval;
Packit Service a1973e
Packit Service a1973e
	      /* Do some sanity checking */
Packit Service a1973e
	      if (retval==PAPI_OK) {
Packit Service a1973e
		if (_papi_hwd[i]->cmp_info.num_cntrs >
Packit Service a1973e
		    _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
Packit Service a1973e
		  fprintf(stderr,"Warning!  num_cntrs %d is more than num_mpx_cntrs %d for component %s\n",
Packit Service a1973e
                        _papi_hwd[i]->cmp_info.num_cntrs,
Packit Service a1973e
                        _papi_hwd[i]->cmp_info.num_mpx_cntrs,
Packit Service a1973e
                        _papi_hwd[i]->cmp_info.name);
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
	      }
Packit Service a1973e
	   }
Packit Service a1973e
Packit Service a1973e
	   i++;
Packit Service a1973e
	}
Packit Service a1973e
	return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Machine info struct initialization using defaults */
Packit Service a1973e
/* See _papi_mdi definition in papi_internal.h       */
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_init_global_internal( void )
Packit Service a1973e
{
Packit Service a1973e
Packit Service a1973e
	int retval;
Packit Service a1973e
Packit Service a1973e
	memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
Packit Service a1973e
Packit Service a1973e
	memset( _papi_hwi_using_signal,0x0,sizeof( _papi_hwi_using_signal ));
Packit Service a1973e
Packit Service a1973e
	/* Global struct to maintain EventSet mapping */
Packit Service a1973e
	retval = allocate_eventset_map( &_papi_hwi_system_info.global_eventset_map );
Packit Service a1973e
	if ( retval != PAPI_OK ) {
Packit Service a1973e
		return retval;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_system_info.pid = 0;	/* Process identifier */
Packit Service a1973e
Packit Service a1973e
	/* PAPI_hw_info_t struct */
Packit Service a1973e
	memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
Packit Service a1973e
Packit Service a1973e
	return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_shutdown_global_internal( void )
Packit Service a1973e
{
Packit Service a1973e
	_papi_hwi_cleanup_all_presets(  );
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_cleanup_errors( );
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
	papi_free(  _papi_hwi_system_info.global_eventset_map.dataSlotArray );
Packit Service a1973e
	memset(  &_papi_hwi_system_info.global_eventset_map, 
Packit Service a1973e
		 0x00, sizeof ( DynamicArray_t ) );
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
	if ( _papi_hwi_system_info.shlib_info.map ) {
Packit Service a1973e
		papi_free( _papi_hwi_system_info.shlib_info.map );
Packit Service a1973e
	}
Packit Service a1973e
	memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
_papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
Packit Service a1973e
						 void *context )
Packit Service a1973e
{
Packit Service a1973e
	/* This function is not used and shouldn't be called. */
Packit Service a1973e
	( void ) EventSet;		 /*unused */
Packit Service a1973e
	( void ) address;		 /*unused */
Packit Service a1973e
	( void ) overflow_vector;	/*unused */
Packit Service a1973e
	( void ) context;		 /*unused */
Packit Service a1973e
	return;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static long long
Packit Service a1973e
handle_derived_add( int *position, long long *from )
Packit Service a1973e
{
Packit Service a1973e
	int pos, i;
Packit Service a1973e
	long long retval = 0;
Packit Service a1973e
Packit Service a1973e
	i = 0;
Packit Service a1973e
	while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
Packit Service a1973e
		pos = position[i++];
Packit Service a1973e
		if ( pos == PAPI_NULL )
Packit Service a1973e
			break;
Packit Service a1973e
		INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
Packit Service a1973e
		retval += from[pos];
Packit Service a1973e
	}
Packit Service a1973e
	return ( retval );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static long long
Packit Service a1973e
handle_derived_subtract( int *position, long long *from )
Packit Service a1973e
{
Packit Service a1973e
	int pos, i;
Packit Service a1973e
	long long retval = from[position[0]];
Packit Service a1973e
Packit Service a1973e
	i = 1;
Packit Service a1973e
	while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
Packit Service a1973e
		pos = position[i++];
Packit Service a1973e
		if ( pos == PAPI_NULL )
Packit Service a1973e
			break;
Packit Service a1973e
		INTDBG( "Compound event, subtracting pos=%d  %lld from %lld\n", pos,
Packit Service a1973e
				from[pos], retval );
Packit Service a1973e
		retval -= from[pos];
Packit Service a1973e
	}
Packit Service a1973e
	return ( retval );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static long long
Packit Service a1973e
units_per_second( long long units, long long cycles )
Packit Service a1973e
{
Packit Service a1973e
   return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
Packit Service a1973e
		      (long long) 1000000 ) / cycles );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static long long
Packit Service a1973e
handle_derived_ps( int *position, long long *from )
Packit Service a1973e
{
Packit Service a1973e
	return ( units_per_second( from[position[1]], from[position[0]] ) );
Packit Service a1973e
}
Packit Service a1973e
static long long
Packit Service a1973e
handle_derived_add_ps( int *position, long long *from )
Packit Service a1973e
{
Packit Service a1973e
	long long tmp = handle_derived_add( position + 1, from );
Packit Service a1973e
	return ( units_per_second( tmp, from[position[0]] ) );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* this function implement postfix calculation, it reads in a string where I use:
Packit Service a1973e
      |      as delimiter
Packit Service a1973e
      N2     indicate No. 2 native event in the derived preset
Packit Service a1973e
      +, -, *, /  as operator
Packit Service a1973e
      #      as MHZ(million hz) got from  _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
Packit Service a1973e
Packit Service a1973e
  Haihang (you@cs.utk.edu)
Packit Service a1973e
*/ 
Packit Service a1973e
 static long long
Packit Service a1973e
 _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
Packit Service a1973e
 {
Packit Service a1973e
        char *point = evi->ops, operand[16];
Packit Service a1973e
        double stack[PAPI_EVENTS_IN_DERIVED_EVENT];
Packit Service a1973e
       int i, val, top = 0;
Packit Service a1973e
Packit Service a1973e
       INTDBG("ENTER: evi: %p, evi->ops: %p (%s), evi->pos[0]: %d, evi->pos[1]: %d, hw_counter: %p (%lld %lld)\n",
Packit Service a1973e
              evi, evi->ops, evi->ops, evi->pos[0], evi->pos[1], hw_counter, hw_counter[0], hw_counter[1]);
Packit Service a1973e
Packit Service a1973e
        memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
Packit Service a1973e
Packit Service a1973e
        while ( *point != '\0' ) {
Packit Service a1973e
               if ( *point == '|' ) {  /* consume '|' characters */
Packit Service a1973e
                        point++;
Packit Service a1973e
                } else if ( *point == 'N' ) {   /* to get count for each native event */
Packit Service a1973e
                        point++;
Packit Service a1973e
                       i = 0;
Packit Service a1973e
                       while ( isdigit(*point) ) {
Packit Service a1973e
                               assert(i<16);
Packit Service a1973e
                                operand[i] = *point;
Packit Service a1973e
                                point++;
Packit Service a1973e
                                i++;
Packit Service a1973e
                       }
Packit Service a1973e
                       assert(0
Packit Service a1973e
                        operand[i] = '\0';
Packit Service a1973e
                       val = atoi( operand );
Packit Service a1973e
                       assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
Packit Service a1973e
                       assert( 0 <= val && val < PAPI_EVENTS_IN_DERIVED_EVENT );
Packit Service a1973e
                       stack[top] = ( double ) hw_counter[evi->pos[val]];
Packit Service a1973e
                        top++;
Packit Service a1973e
               } else if ( *point == '#' ) {   /* to get mhz */
Packit Service a1973e
                        point++;
Packit Service a1973e
                       assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
Packit Service a1973e
                        stack[top] = _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000000.0;
Packit Service a1973e
                        top++;
Packit Service a1973e
               } else if ( isdigit( *point ) ) {
Packit Service a1973e
                        i = 0;
Packit Service a1973e
                       while ( isdigit(*point) ) {
Packit Service a1973e
                               assert(i<16);
Packit Service a1973e
                                operand[i] = *point;
Packit Service a1973e
                                point++;
Packit Service a1973e
                                i++;
Packit Service a1973e
                       }
Packit Service a1973e
                       assert(0
Packit Service a1973e
                        operand[i] = '\0';
Packit Service a1973e
                       assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
Packit Service a1973e
                        stack[top] = atoi( operand );
Packit Service a1973e
                        top++;
Packit Service a1973e
                } else if ( *point == '+' ) {   /* + calculation */
Packit Service a1973e
                       point++;
Packit Service a1973e
                       assert(top >= 2);
Packit Service a1973e
                        stack[top - 2] += stack[top - 1];
Packit Service a1973e
                        top--;
Packit Service a1973e
                } else if ( *point == '-' ) {   /* - calculation */
Packit Service a1973e
                       point++;
Packit Service a1973e
                       assert(top >= 2);
Packit Service a1973e
                        stack[top - 2] -= stack[top - 1];
Packit Service a1973e
                        top--;
Packit Service a1973e
                } else if ( *point == '*' ) {   /* * calculation */
Packit Service a1973e
                       point++;
Packit Service a1973e
                       assert(top >= 2);
Packit Service a1973e
                        stack[top - 2] *= stack[top - 1];
Packit Service a1973e
                        top--;
Packit Service a1973e
                } else if ( *point == '/' ) {   /* / calculation */
Packit Service a1973e
                       point++;
Packit Service a1973e
                       assert(top >= 2);
Packit Service a1973e
                       /* FIXME should handle runtime divide by zero */
Packit Service a1973e
                        stack[top - 2] /= stack[top - 1];
Packit Service a1973e
                        top--;
Packit Service a1973e
               } else { /* flag an error parsing the preset */
Packit Service a1973e
                       PAPIERROR( "BUG! Unable to parse \"%s\"", evi->ops );
Packit Service a1973e
                       return ( long long ) stack[0];
Packit Service a1973e
                }
Packit Service a1973e
        }
Packit Service a1973e
        assert(top == 1);
Packit Service a1973e
        INTDBG("EXIT: stack[0]: %lld\n", (long long)stack[0]);
Packit Service a1973e
        return ( long long ) stack[0];
Packit Service a1973e
 }
Packit Service a1973e
Packit Service a1973e
static long long
Packit Service a1973e
handle_derived( EventInfo_t * evi, long long *from )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: evi: %p, evi->derived: %d, from: %p\n", evi, evi->derived, from);
Packit Service a1973e
	switch ( evi->derived ) {
Packit Service a1973e
	case DERIVED_ADD:
Packit Service a1973e
		return ( handle_derived_add( evi->pos, from ) );
Packit Service a1973e
	case DERIVED_ADD_PS:
Packit Service a1973e
		return ( handle_derived_add_ps( evi->pos, from ) );
Packit Service a1973e
	case DERIVED_SUB:
Packit Service a1973e
		return ( handle_derived_subtract( evi->pos, from ) );
Packit Service a1973e
	case DERIVED_PS:
Packit Service a1973e
		return ( handle_derived_ps( evi->pos, from ) );
Packit Service a1973e
	case DERIVED_POSTFIX:
Packit Service a1973e
		return ( _papi_hwi_postfix_calc( evi, from ) );
Packit Service a1973e
	case DERIVED_CMPD:		 /* This type has existed for a long time, but was never implemented.
Packit Service a1973e
							    Probably because its a no-op. However, if it's in a header, it
Packit Service a1973e
							    should be supported. As I found out when I implemented it in 
Packit Service a1973e
							    Pentium 4 for testing...dkt */
Packit Service a1973e
		return ( from[evi->pos[0]] );
Packit Service a1973e
	default:
Packit Service a1973e
		PAPIERROR( "BUG! Unknown derived command %d, returning 0", evi->derived );
Packit Service a1973e
		INTDBG("EXIT: Unknown derived command %d\n", evi->derived);
Packit Service a1973e
		return ( ( long long ) 0 );
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* table matching derived types to derived strings.                             
Packit Service a1973e
   used by get_info, encode_event, xml translator                               
Packit Service a1973e
*/
Packit Service a1973e
static const hwi_describe_t _papi_hwi_derived[] = {
Packit Service a1973e
  {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
Packit Service a1973e
  {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
Packit Service a1973e
  {DERIVED_PS, "DERIVED_PS",
Packit Service a1973e
   "Divide by the cycle counter and convert to seconds"},
Packit Service a1973e
  {DERIVED_ADD_PS, "DERIVED_ADD_PS",
Packit Service a1973e
   "Add 2 counters then divide by the cycle counter and xl8 to secs."},
Packit Service a1973e
  {DERIVED_CMPD, "DERIVED_CMPD",
Packit Service a1973e
   "Event lives in first counter but takes 2 or more codes"},
Packit Service a1973e
  {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
Packit Service a1973e
  {DERIVED_POSTFIX, "DERIVED_POSTFIX",
Packit Service a1973e
   "Process counters based on specified postfix string"},
Packit Service a1973e
  {DERIVED_INFIX, "DERIVED_INFIX",
Packit Service a1973e
   "Process counters based on specified infix string"},
Packit Service a1973e
  {-1, NULL, NULL}
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
/* _papi_hwi_derived_type:
Packit Service a1973e
   Helper routine to extract a derived type from a derived string
Packit Service a1973e
   returns type value if found, otherwise returns -1
Packit Service a1973e
*/
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_derived_type( char *tmp, int *code )
Packit Service a1973e
{
Packit Service a1973e
  int i = 0;
Packit Service a1973e
  while ( _papi_hwi_derived[i].name != NULL ) {
Packit Service a1973e
    if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
Packit Service a1973e
      *code = _papi_hwi_derived[i].value;
Packit Service a1973e
      return PAPI_OK;
Packit Service a1973e
    }
Packit Service a1973e
    i++;
Packit Service a1973e
  }
Packit Service a1973e
  INTDBG( "Invalid derived string %s\n", tmp );
Packit Service a1973e
  return PAPI_EINVAL;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* _papi_hwi_derived_string:
Packit Service a1973e
   Helper routine to extract a derived string from a derived type  
Packit Service a1973e
   copies derived type string into derived if found,
Packit Service a1973e
   otherwise returns PAPI_EINVAL
Packit Service a1973e
*/
Packit Service a1973e
static int
Packit Service a1973e
_papi_hwi_derived_string( int type, char *derived, int len )
Packit Service a1973e
{
Packit Service a1973e
  int j;
Packit Service a1973e
Packit Service a1973e
  for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
Packit Service a1973e
    if ( _papi_hwi_derived[j].value == type ) {
Packit Service a1973e
      strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
Packit Service a1973e
	       len );
Packit Service a1973e
      return PAPI_OK;
Packit Service a1973e
    }
Packit Service a1973e
  }
Packit Service a1973e
  INTDBG( "Invalid derived type %d\n", type );
Packit Service a1973e
  return PAPI_EINVAL;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* _papi_hwi_get_preset_event_info:
Packit Service a1973e
   Assumes EventCode contains a valid preset code.
Packit Service a1973e
   But defensive programming says check for NULL pointers.
Packit Service a1973e
   Returns a filled in PAPI_event_info_t structure containing
Packit Service a1973e
   descriptive strings and values for the specified preset event.
Packit Service a1973e
*/
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_get_preset_event_info( int EventCode, PAPI_event_info_t * info )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
Packit Service a1973e
Packit Service a1973e
	int i = EventCode & PAPI_PRESET_AND_MASK;
Packit Service a1973e
	unsigned int j;
Packit Service a1973e
Packit Service a1973e
	if ( _papi_hwi_presets[i].symbol ) {	/* if the event is in the preset table */
Packit Service a1973e
      // since we are setting the whole structure to zero the strncpy calls below will 
Packit Service a1973e
      // be leaving NULL terminates strings as long as they copy 1 less byte than the 
Packit Service a1973e
      // buffer size of the field.
Packit Service a1973e
	   memset( info, 0, sizeof ( PAPI_event_info_t ) );
Packit Service a1973e
Packit Service a1973e
	   info->event_code = ( unsigned int ) EventCode;
Packit Service a1973e
	   strncpy( info->symbol, _papi_hwi_presets[i].symbol,
Packit Service a1973e
	    sizeof(info->symbol)-1);
Packit Service a1973e
Packit Service a1973e
	   if ( _papi_hwi_presets[i].short_descr != NULL )
Packit Service a1973e
	      strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
Packit Service a1973e
		          sizeof ( info->short_descr )-1 );
Packit Service a1973e
Packit Service a1973e
	   if ( _papi_hwi_presets[i].long_descr != NULL )
Packit Service a1973e
	      strncpy( info->long_descr,  _papi_hwi_presets[i].long_descr,
Packit Service a1973e
		          sizeof ( info->long_descr )-1 );
Packit Service a1973e
Packit Service a1973e
	   info->event_type = _papi_hwi_presets[i].event_type;
Packit Service a1973e
	   info->count = _papi_hwi_presets[i].count;
Packit Service a1973e
Packit Service a1973e
	   _papi_hwi_derived_string( _papi_hwi_presets[i].derived_int,
Packit Service a1973e
				     info->derived,  sizeof ( info->derived ) );
Packit Service a1973e
Packit Service a1973e
	   if ( _papi_hwi_presets[i].postfix != NULL )
Packit Service a1973e
	      strncpy( info->postfix, _papi_hwi_presets[i].postfix,
Packit Service a1973e
		          sizeof ( info->postfix )-1 );
Packit Service a1973e
Packit Service a1973e
	   for(j=0;j < info->count; j++) {
Packit Service a1973e
	      info->code[j]=_papi_hwi_presets[i].code[j];
Packit Service a1973e
	      strncpy(info->name[j], _papi_hwi_presets[i].name[j],
Packit Service a1973e
	      sizeof(info->name[j])-1);
Packit Service a1973e
	   }
Packit Service a1973e
Packit Service a1973e
	   if ( _papi_hwi_presets[i].note != NULL ) {
Packit Service a1973e
	      strncpy( info->note, _papi_hwi_presets[i].note,
Packit Service a1973e
		          sizeof ( info->note )-1 );
Packit Service a1973e
	   }
Packit Service a1973e
Packit Service a1973e
	   return PAPI_OK;
Packit Service a1973e
	} else {
Packit Service a1973e
	   return PAPI_ENOEVNT;
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* _papi_hwi_get_user_event_info:
Packit Service a1973e
   Assumes EventCode contains a valid user event code.
Packit Service a1973e
   But defensive programming says check for NULL pointers.
Packit Service a1973e
   Returns a filled in PAPI_event_info_t structure containing
Packit Service a1973e
   descriptive strings and values for the specified preset event.
Packit Service a1973e
*/
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_get_user_event_info( int EventCode, PAPI_event_info_t * info )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
Packit Service a1973e
Packit Service a1973e
	unsigned int i = EventCode & PAPI_UE_AND_MASK;
Packit Service a1973e
	unsigned int j;
Packit Service a1973e
Packit Service a1973e
	// if event code not in valid range, return error
Packit Service a1973e
	if (i >= PAPI_MAX_USER_EVENTS) {
Packit Service a1973e
		INTDBG("EXIT: Invalid event index: %d, max value is: %d\n", i, PAPI_MAX_USER_EVENTS - 1);
Packit Service a1973e
		return( PAPI_ENOEVNT );
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if ( user_defined_events[i].symbol == NULL) {	/* if the event is in the preset table */
Packit Service a1973e
		INTDBG("EXIT: Event symbol for this event is NULL\n");
Packit Service a1973e
		return PAPI_ENOEVNT;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* set whole structure to 0 */
Packit Service a1973e
	memset( info, 0, sizeof ( PAPI_event_info_t ) );
Packit Service a1973e
Packit Service a1973e
	info->event_code = ( unsigned int ) EventCode;
Packit Service a1973e
	strncpy( info->symbol, user_defined_events[i].symbol,
Packit Service a1973e
		sizeof(info->symbol)-1);
Packit Service a1973e
Packit Service a1973e
	if ( user_defined_events[i].short_descr != NULL )
Packit Service a1973e
		strncpy( info->short_descr, user_defined_events[i].short_descr,
Packit Service a1973e
			sizeof(info->short_descr)-1);
Packit Service a1973e
Packit Service a1973e
	if ( user_defined_events[i].long_descr != NULL )
Packit Service a1973e
		strncpy( info->long_descr,  user_defined_events[i].long_descr,
Packit Service a1973e
			sizeof(info->long_descr)-1);
Packit Service a1973e
Packit Service a1973e
//	info->event_type = user_defined_events[i].event_type;
Packit Service a1973e
	info->count = user_defined_events[i].count;
Packit Service a1973e
Packit Service a1973e
	_papi_hwi_derived_string( user_defined_events[i].derived_int,
Packit Service a1973e
			info->derived,  sizeof(info->derived)-1);
Packit Service a1973e
Packit Service a1973e
	if ( user_defined_events[i].postfix != NULL )
Packit Service a1973e
		strncpy( info->postfix, user_defined_events[i].postfix,
Packit Service a1973e
			sizeof(info->postfix)-1);
Packit Service a1973e
Packit Service a1973e
	for(j=0;j < info->count; j++) {
Packit Service a1973e
		info->code[j]=user_defined_events[i].code[j];
Packit Service a1973e
		INTDBG("info->code[%d]: %#x\n", j, info->code[j]);
Packit Service a1973e
		strncpy(info->name[j], user_defined_events[i].name[j], sizeof(info->name[j])-1);
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if ( user_defined_events[i].note != NULL ) {
Packit Service a1973e
		strncpy( info->note, user_defined_events[i].note, sizeof(info->note)-1);
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	INTDBG("EXIT: PAPI_OK: event_code: %#x, symbol: %s, short_desc: %s, long_desc: %s\n", info->event_code, info->symbol, info->short_descr, info->long_descr);
Packit Service a1973e
	return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
Packit Service a1973e
   Used to enumerate the entire array, e.g. for native_avail.c */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_query_native_event( unsigned int EventCode )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: EventCode: %#x\n", EventCode);
Packit Service a1973e
   char name[PAPI_HUGE_STR_LEN];      /* probably overkill, */
Packit Service a1973e
                                      /* but should always be big enough */
Packit Service a1973e
   int cidx;
Packit Service a1973e
   int nevt_code;
Packit Service a1973e
Packit Service a1973e
   cidx = _papi_hwi_component_index( EventCode );
Packit Service a1973e
   if (cidx<0) {
Packit Service a1973e
	   INTDBG("EXIT: PAPI_ENOCMP\n");
Packit Service a1973e
	   return PAPI_ENOCMP;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
Packit Service a1973e
   _papi_hwi_set_papi_event_code(EventCode, 0);
Packit Service a1973e
Packit Service a1973e
	if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
Packit Service a1973e
		INTDBG("EXIT: nevt_code: %d\n", nevt_code);
Packit Service a1973e
		return nevt_code;
Packit Service a1973e
	}
Packit Service a1973e
   int ret = _papi_hwd[cidx]->ntv_code_to_name( (unsigned int)nevt_code, name, sizeof(name));
Packit Service a1973e
Packit Service a1973e
   INTDBG("EXIT: ret: %d\n", ret);
Packit Service a1973e
   return (ret);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Converts an ASCII name into a native event code usable by other routines
Packit Service a1973e
   Returns code = 0 and PAPI_OK if name not found.
Packit Service a1973e
   This allows for sparse native event arrays */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_native_name_to_code( const char *in, int *out )
Packit Service a1973e
{
Packit Service a1973e
    INTDBG("ENTER: in: %s, out: %p\n", in, out);
Packit Service a1973e
Packit Service a1973e
    int retval = PAPI_ENOEVNT;
Packit Service a1973e
    char name[PAPI_HUGE_STR_LEN];	   /* make sure it's big enough */
Packit Service a1973e
    unsigned int i;
Packit Service a1973e
    int cidx;
Packit Service a1973e
    char *full_event_name;
Packit Service a1973e
Packit Service a1973e
    if (in == NULL) {
Packit Service a1973e
		INTDBG("EXIT: PAPI_EINVAL\n");
Packit Service a1973e
    	return PAPI_EINVAL;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    full_event_name = strdup(in);
Packit Service a1973e
Packit Service a1973e
	in = _papi_hwi_strip_component_prefix(in);
Packit Service a1973e
Packit Service a1973e
	// look in each component
Packit Service a1973e
    for(cidx=0; cidx < papi_num_components; cidx++) {
Packit Service a1973e
Packit Service a1973e
       if (_papi_hwd[cidx]->cmp_info.disabled) continue;
Packit Service a1973e
Packit Service a1973e
       // if this component does not support the pmu which defines this event, no need to call it
Packit Service a1973e
       if (is_supported_by_component(cidx, full_event_name) == 0) continue;
Packit Service a1973e
Packit Service a1973e
       INTDBG("cidx: %d, name: %s, event: %s\n", cidx, _papi_hwd[cidx]->cmp_info.name, in);
Packit Service a1973e
Packit Service a1973e
       // show that we do not have an event code yet (the component may create one and update this info)
Packit Service a1973e
       // this also clears any values left over from a previous call
Packit Service a1973e
       _papi_hwi_set_papi_event_code(-1, -1);
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
		// if component has a ntv_name_to_code function, use it to get event code
Packit Service a1973e
		if (_papi_hwd[cidx]->ntv_name_to_code != NULL) {
Packit Service a1973e
			// try and get this events event code
Packit Service a1973e
			retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
Packit Service a1973e
			if (retval==PAPI_OK) {
Packit Service a1973e
				*out = _papi_hwi_native_to_eventcode(cidx, *out, -1, in);
Packit Service a1973e
				free (full_event_name);
Packit Service a1973e
				INTDBG("EXIT: PAPI_OK  event: %s code: %#x\n", in, *out);
Packit Service a1973e
				return PAPI_OK;
Packit Service a1973e
			}
Packit Service a1973e
		} else {
Packit Service a1973e
			// force the code through the work around
Packit Service a1973e
			retval = PAPI_ECMP;
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
		/* If not implemented, work around */
Packit Service a1973e
		if ( retval==PAPI_ECMP) {
Packit Service a1973e
			i = 0;
Packit Service a1973e
			retval = _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
Packit Service a1973e
			if (retval != PAPI_OK) {
Packit Service a1973e
				free (full_event_name);
Packit Service a1973e
				INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
				return retval;
Packit Service a1973e
			}
Packit Service a1973e
Packit Service a1973e
//			_papi_hwi_lock( INTERNAL_LOCK );
Packit Service a1973e
Packit Service a1973e
			do {
Packit Service a1973e
				// save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
Packit Service a1973e
				_papi_hwi_set_papi_event_code(i, 0);
Packit Service a1973e
				retval = _papi_hwd[cidx]->ntv_code_to_name(i, name, sizeof(name));
Packit Service a1973e
				/* printf("%#x\nname =|%s|\ninput=|%s|\n", i, name, in); */
Packit Service a1973e
				if ( retval == PAPI_OK && in != NULL) {
Packit Service a1973e
					if ( strcasecmp( name, in ) == 0 ) {
Packit Service a1973e
						*out = _papi_hwi_native_to_eventcode(cidx, i, -1, name);
Packit Service a1973e
						free (full_event_name);
Packit Service a1973e
						INTDBG("EXIT: PAPI_OK, event: %s, code: %#x\n", in, *out);
Packit Service a1973e
						return PAPI_OK;
Packit Service a1973e
					}
Packit Service a1973e
					retval = PAPI_ENOEVNT;
Packit Service a1973e
				} else {
Packit Service a1973e
					*out = 0;
Packit Service a1973e
					retval = PAPI_ENOEVNT;
Packit Service a1973e
					break;
Packit Service a1973e
				}
Packit Service a1973e
			} while ( ( _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_EVENTS ) == PAPI_OK ) );
Packit Service a1973e
Packit Service a1973e
//			_papi_hwi_unlock( INTERNAL_LOCK );
Packit Service a1973e
		}
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    free (full_event_name);
Packit Service a1973e
    INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
    return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Returns event name based on native event code. 
Packit Service a1973e
   Returns NULL if name not found */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_native_code_to_name( unsigned int EventCode, 
Packit Service a1973e
			       char *hwi_name, int len )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("ENTER: EventCode: %#x, hwi_name: %p, len: %d\n", EventCode, hwi_name, len);
Packit Service a1973e
  int cidx;
Packit Service a1973e
  int retval; 
Packit Service a1973e
  int nevt_code;
Packit Service a1973e
Packit Service a1973e
  cidx = _papi_hwi_component_index( EventCode );
Packit Service a1973e
  if (cidx<0) return PAPI_ENOEVNT;
Packit Service a1973e
Packit Service a1973e
  if ( EventCode & PAPI_NATIVE_MASK ) {
Packit Service a1973e
	  // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
Packit Service a1973e
	  _papi_hwi_set_papi_event_code(EventCode, 0);
Packit Service a1973e
Packit Service a1973e
	if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
Packit Service a1973e
		INTDBG("EXIT: nevt_code: %d\n", nevt_code);
Packit Service a1973e
		return nevt_code;
Packit Service a1973e
	}
Packit Service a1973e
	if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
Packit Service a1973e
						(unsigned int)nevt_code,
Packit Service a1973e
						hwi_name, len) ) == PAPI_OK ) {
Packit Service a1973e
			retval = _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name, 
Packit Service a1973e
											 hwi_name, hwi_name, len);
Packit Service a1973e
			INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
			return retval;
Packit Service a1973e
	}
Packit Service a1973e
	INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
	return (retval);
Packit Service a1973e
  }
Packit Service a1973e
  INTDBG("EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
  return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* The native event equivalent of PAPI_get_event_info */
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_get_native_event_info( unsigned int EventCode,
Packit Service a1973e
				 PAPI_event_info_t *info )
Packit Service a1973e
{
Packit Service a1973e
	  INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
Packit Service a1973e
    int retval;
Packit Service a1973e
    int cidx;
Packit Service a1973e
    int nevt_code;
Packit Service a1973e
Packit Service a1973e
    cidx = _papi_hwi_component_index( EventCode );
Packit Service a1973e
    if (cidx<0) return PAPI_ENOCMP;
Packit Service a1973e
Packit Service a1973e
    if (_papi_hwd[cidx]->cmp_info.disabled) return PAPI_ENOCMP;
Packit Service a1973e
Packit Service a1973e
    if ( EventCode & PAPI_NATIVE_MASK ) {
Packit Service a1973e
        // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
Packit Service a1973e
        _papi_hwi_set_papi_event_code(EventCode, 0);
Packit Service a1973e
Packit Service a1973e
       /* clear the event info */
Packit Service a1973e
       memset( info, 0, sizeof ( PAPI_event_info_t ) );
Packit Service a1973e
       info->event_code = ( unsigned int ) EventCode;
Packit Service a1973e
       info->component_index = (unsigned int) cidx;
Packit Service a1973e
       retval = _papi_hwd[cidx]->ntv_code_to_info( 
Packit Service a1973e
			      _papi_hwi_eventcode_to_native(EventCode), info);
Packit Service a1973e
Packit Service a1973e
       /* If component error, it's missing the ntv_code_to_info vector */
Packit Service a1973e
       /* so we'll have to fake it.                                    */
Packit Service a1973e
       if ( retval == PAPI_ECMP ) {
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	  INTDBG("missing NTV_CODE_TO_INFO, faking\n");
Packit Service a1973e
	  /* Fill in the info structure */
Packit Service a1973e
Packit Service a1973e
		if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
Packit Service a1973e
			INTDBG("EXIT: nevt_code: %d\n", nevt_code);
Packit Service a1973e
			return nevt_code;
Packit Service a1973e
		}
Packit Service a1973e
	  if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
Packit Service a1973e
				    (unsigned int)nevt_code,
Packit Service a1973e
				    info->symbol,
Packit Service a1973e
				    sizeof(info->symbol)) ) == PAPI_OK ) {
Packit Service a1973e
Packit Service a1973e
	  } else {
Packit Service a1973e
	     INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
	     return retval;
Packit Service a1973e
	  }
Packit Service a1973e
Packit Service a1973e
		if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) <0) {
Packit Service a1973e
			INTDBG("EXIT: nevt_code: %d\n", nevt_code);
Packit Service a1973e
			return nevt_code;
Packit Service a1973e
		}
Packit Service a1973e
	  retval = _papi_hwd[cidx]->ntv_code_to_descr( 
Packit Service a1973e
				     (unsigned int)nevt_code,
Packit Service a1973e
				     info->long_descr,
Packit Service a1973e
				     sizeof ( info->long_descr));
Packit Service a1973e
	  if (retval!=PAPI_OK) {
Packit Service a1973e
	     INTDBG("Failed ntv_code_to_descr()\n");
Packit Service a1973e
	  }
Packit Service a1973e
Packit Service a1973e
       }
Packit Service a1973e
	   retval = _papi_hwi_prefix_component_name( 
Packit Service a1973e
						_papi_hwd[cidx]->cmp_info.short_name, 
Packit Service a1973e
						info->symbol,
Packit Service a1973e
						info->symbol, 
Packit Service a1973e
						sizeof(info->symbol) );
Packit Service a1973e
Packit Service a1973e
       INTDBG("EXIT: retval: %d\n", retval);
Packit Service a1973e
       return retval;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
	INTDBG("EXIT: PAPI_ENOEVNT\n");
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
EventSetInfo_t *
Packit Service a1973e
_papi_hwi_lookup_EventSet( int eventset )
Packit Service a1973e
{
Packit Service a1973e
	const DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
Packit Service a1973e
	EventSetInfo_t *set;
Packit Service a1973e
Packit Service a1973e
	if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
Packit Service a1973e
		return ( NULL );
Packit Service a1973e
Packit Service a1973e
	set = map->dataSlotArray[eventset];
Packit Service a1973e
#ifdef DEBUG
Packit Service a1973e
	if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
Packit Service a1973e
		 ( set->master->tid != _papi_hwi_thread_id_fn(  ) ) )
Packit Service a1973e
		return ( NULL );
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
	return ( set );
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
_papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
Packit Service a1973e
{
Packit Service a1973e
   /* Are we multiplexing at all */
Packit Service a1973e
   if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
Packit Service a1973e
      return 0;
Packit Service a1973e
   }
Packit Service a1973e
Packit Service a1973e
   /* Does the component support kernel multiplexing */
Packit Service a1973e
   if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
Packit Service a1973e
      /* Have we forced software multiplexing */
Packit Service a1973e
      if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
Packit Service a1973e
	 return 1;
Packit Service a1973e
      }
Packit Service a1973e
      /* Nope, using hardware multiplexing */
Packit Service a1973e
      return 0;
Packit Service a1973e
   } 
Packit Service a1973e
Packit Service a1973e
   /* We are multiplexing but the component does not support hardware */
Packit Service a1973e
Packit Service a1973e
   return 1;
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
hwd_context_t *
Packit Service a1973e
_papi_hwi_get_context( EventSetInfo_t * ESI, int *is_dirty )
Packit Service a1973e
{
Packit Service a1973e
	INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
Packit Service a1973e
	int dirty_ctx;
Packit Service a1973e
	hwd_context_t *ctx=NULL;
Packit Service a1973e
Packit Service a1973e
	/* assume for now the control state is clean (last updated by this ESI) */
Packit Service a1973e
	dirty_ctx = 0;
Packit Service a1973e
	
Packit Service a1973e
	/* get a context pointer based on if we are counting for a thread or for a cpu */
Packit Service a1973e
	if (ESI->state & PAPI_CPU_ATTACHED) {
Packit Service a1973e
		/* use cpu context */
Packit Service a1973e
		ctx = ESI->CpuInfo->context[ESI->CmpIdx];
Packit Service a1973e
Packit Service a1973e
		/* if the user wants to know if the control state was last set by the same event set, tell him */
Packit Service a1973e
		if (is_dirty != NULL) {
Packit Service a1973e
			if (ESI->CpuInfo->from_esi != ESI) {
Packit Service a1973e
				dirty_ctx = 1;
Packit Service a1973e
			}
Packit Service a1973e
			*is_dirty = dirty_ctx;
Packit Service a1973e
		}
Packit Service a1973e
		ESI->CpuInfo->from_esi = ESI;
Packit Service a1973e
	   
Packit Service a1973e
	} else {
Packit Service a1973e
Packit Service a1973e
		/* use thread context */
Packit Service a1973e
		ctx = ESI->master->context[ESI->CmpIdx];
Packit Service a1973e
Packit Service a1973e
		/* if the user wants to know if the control state was last set by the same event set, tell him */
Packit Service a1973e
		if (is_dirty != NULL) {
Packit Service a1973e
			if (ESI->master->from_esi != ESI) {
Packit Service a1973e
				dirty_ctx = 1;
Packit Service a1973e
			}
Packit Service a1973e
			*is_dirty = dirty_ctx;
Packit Service a1973e
		}
Packit Service a1973e
		ESI->master->from_esi = ESI;
Packit Service a1973e
Packit Service a1973e
	}
Packit Service a1973e
	return( ctx );
Packit Service a1973e
}