Blame src/papi_internal.c

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