|
Packit Service |
a1973e |
/****************************/
|
|
Packit Service |
a1973e |
/* THIS IS OPEN SOURCE CODE */
|
|
Packit Service |
a1973e |
/****************************/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* File: cpus.c
|
|
Packit Service |
a1973e |
* Author: Gary Mohr
|
|
Packit Service |
a1973e |
* gary.mohr@bull.com
|
|
Packit Service |
a1973e |
* - based on threads.c by Philip Mucci -
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This file contains cpu allocation and bookkeeping functions */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi.h"
|
|
Packit Service |
a1973e |
#include "papi_internal.h"
|
|
Packit Service |
a1973e |
#include "papi_vector.h"
|
|
Packit Service |
a1973e |
#include "papi_memory.h"
|
|
Packit Service |
a1973e |
#include "cpus.h"
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
#include <unistd.h>
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The list of cpus; this gets built as user apps set the cpu papi */
|
|
Packit Service |
a1973e |
/* option on an event set */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static CpuInfo_t *_papi_hwi_cpu_head;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static CpuInfo_t *
|
|
Packit Service |
a1973e |
_papi_hwi_lookup_cpu( unsigned int cpu_num )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry:\n");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
CpuInfo_t *tmp;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
tmp = ( CpuInfo_t * ) _papi_hwi_cpu_head;
|
|
Packit Service |
a1973e |
while ( tmp != NULL ) {
|
|
Packit Service |
a1973e |
THRDBG( "Examining cpu %#x at %p\n", tmp->cpu_num, tmp );
|
|
Packit Service |
a1973e |
if ( tmp->cpu_num == cpu_num ) {
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
tmp = tmp->next;
|
|
Packit Service |
a1973e |
if ( tmp == _papi_hwi_cpu_head ) {
|
|
Packit Service |
a1973e |
tmp = NULL;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( tmp ) {
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head = tmp;
|
|
Packit Service |
a1973e |
THRDBG( "Found cpu %#x at %p\n", cpu_num, tmp );
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
THRDBG( "Did not find cpu %#x\n", cpu_num );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return tmp;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_lookup_or_create_cpu( CpuInfo_t **here, unsigned int cpu_num )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: here: %p\n", here);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
CpuInfo_t *tmp = NULL;
|
|
Packit Service |
a1973e |
int retval = PAPI_OK;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_lock( CPUS_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
tmp = _papi_hwi_lookup_cpu(cpu_num);
|
|
Packit Service |
a1973e |
if ( tmp == NULL ) {
|
|
Packit Service |
a1973e |
retval = _papi_hwi_initialize_cpu( &tmp, cpu_num );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Increment use count */
|
|
Packit Service |
a1973e |
tmp->num_users++;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( retval == PAPI_OK ) {
|
|
Packit Service |
a1973e |
*here = tmp;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( CPUS_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static CpuInfo_t *
|
|
Packit Service |
a1973e |
allocate_cpu( unsigned int cpu_num )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: cpu_num: %d\n", cpu_num);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
CpuInfo_t *cpu;
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Allocate new CpuInfo structure */
|
|
Packit Service |
a1973e |
cpu = ( CpuInfo_t * ) papi_calloc( 1, sizeof ( CpuInfo_t ) );
|
|
Packit Service |
a1973e |
if ( cpu == NULL ) {
|
|
Packit Service |
a1973e |
goto allocate_error;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* identify the cpu this info structure represents */
|
|
Packit Service |
a1973e |
cpu->cpu_num = cpu_num;
|
|
Packit Service |
a1973e |
cpu->context = ( hwd_context_t ** )
|
|
Packit Service |
a1973e |
papi_calloc( ( size_t ) papi_num_components ,
|
|
Packit Service |
a1973e |
sizeof ( hwd_context_t * ) );
|
|
Packit Service |
a1973e |
if ( !cpu->context ) {
|
|
Packit Service |
a1973e |
goto error_free_cpu;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Allocate an eventset per component per cpu? Why? */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
cpu->running_eventset = ( EventSetInfo_t ** )
|
|
Packit Service |
a1973e |
papi_calloc(( size_t ) papi_num_components,
|
|
Packit Service |
a1973e |
sizeof ( EventSetInfo_t * ) );
|
|
Packit Service |
a1973e |
if ( !cpu->running_eventset ) {
|
|
Packit Service |
a1973e |
goto error_free_context;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit Service |
a1973e |
cpu->context[i] =
|
|
Packit Service |
a1973e |
( void * ) papi_calloc( 1, ( size_t ) _papi_hwd[i]->size.context );
|
|
Packit Service |
a1973e |
cpu->running_eventset[i] = NULL;
|
|
Packit Service |
a1973e |
if ( cpu->context[i] == NULL ) {
|
|
Packit Service |
a1973e |
goto error_free_contexts;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
cpu->num_users=0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
THRDBG( "Allocated CpuInfo: %p\n", cpu );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return cpu;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
error_free_contexts:
|
|
Packit Service |
a1973e |
for ( i--; i >= 0; i-- ) papi_free( cpu->context[i] );
|
|
Packit Service |
a1973e |
error_free_context:
|
|
Packit Service |
a1973e |
papi_free( cpu->context );
|
|
Packit Service |
a1973e |
error_free_cpu:
|
|
Packit Service |
a1973e |
papi_free( cpu );
|
|
Packit Service |
a1973e |
allocate_error:
|
|
Packit Service |
a1973e |
return NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Must be called with CPUS_LOCK held! */
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
remove_cpu( CpuInfo_t * entry )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: entry: %p\n", entry);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
CpuInfo_t *tmp = NULL, *prev = NULL;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Find the preceding element and the matched element,
|
|
Packit Service |
a1973e |
short circuit if we've seen the head twice */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( tmp = ( CpuInfo_t * ) _papi_hwi_cpu_head;
|
|
Packit Service |
a1973e |
( entry != tmp ) || ( prev == NULL ); tmp = tmp->next ) {
|
|
Packit Service |
a1973e |
prev = tmp;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( tmp != entry ) {
|
|
Packit Service |
a1973e |
THRDBG( "Cpu %d at %p was not found in the cpu list!\n",
|
|
Packit Service |
a1973e |
entry->cpu_num, entry );
|
|
Packit Service |
a1973e |
return PAPI_EBUG;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Only 1 element in list */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( prev == tmp ) {
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head = NULL;
|
|
Packit Service |
a1973e |
tmp->next = NULL;
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head now NULL\n" );
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
prev->next = tmp->next;
|
|
Packit Service |
a1973e |
/* If we're removing the head, better advance it! */
|
|
Packit Service |
a1973e |
if ( _papi_hwi_cpu_head == tmp ) {
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head = tmp->next;
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
THRDBG( "Removed cpu %p from list\n", tmp );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
free_cpu( CpuInfo_t **cpu )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG( "Entry: *cpu: %p, cpu_num: %d, cpu_users: %d\n",
|
|
Packit Service |
a1973e |
*cpu, ( *cpu )->cpu_num, (*cpu)->num_users);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int i,users,retval;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_lock( CPUS_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
(*cpu)->num_users--;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
users=(*cpu)->num_users;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Remove from linked list if no users */
|
|
Packit Service |
a1973e |
if (!users) remove_cpu( *cpu );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( CPUS_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Exit early if still users of this CPU */
|
|
Packit Service |
a1973e |
if (users!=0) return;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
THRDBG( "Shutting down cpu %d at %p\n", (*cpu)->cpu_num, cpu );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit Service |
a1973e |
if (_papi_hwd[i]->cmp_info.disabled) continue;
|
|
Packit Service |
a1973e |
retval = _papi_hwd[i]->shutdown_thread( (*cpu)->context[i] );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK ) {
|
|
Packit Service |
a1973e |
// failure = retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit Service |
a1973e |
if ( ( *cpu )->context[i] ) {
|
|
Packit Service |
a1973e |
papi_free( ( *cpu )->context[i] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( *cpu )->context ) {
|
|
Packit Service |
a1973e |
papi_free( ( *cpu )->context );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( *cpu )->running_eventset ) {
|
|
Packit Service |
a1973e |
papi_free( ( *cpu )->running_eventset );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* why do we clear this? */
|
|
Packit Service |
a1973e |
memset( *cpu, 0x00, sizeof ( CpuInfo_t ) );
|
|
Packit Service |
a1973e |
papi_free( *cpu );
|
|
Packit Service |
a1973e |
*cpu = NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Must be called with CPUS_LOCK held! */
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
insert_cpu( CpuInfo_t * entry )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: entry: %p\n", entry);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( _papi_hwi_cpu_head == NULL ) {
|
|
Packit Service |
a1973e |
/* 0 elements */
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head is NULL\n" );
|
|
Packit Service |
a1973e |
entry->next = entry;
|
|
Packit Service |
a1973e |
} else if ( _papi_hwi_cpu_head->next == _papi_hwi_cpu_head ) {
|
|
Packit Service |
a1973e |
/* 1 element */
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->next = entry;
|
|
Packit Service |
a1973e |
entry->next = ( CpuInfo_t * ) _papi_hwi_cpu_head;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
/* 2+ elements */
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
|
|
Packit Service |
a1973e |
entry->next = _papi_hwi_cpu_head->next;
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->next = entry;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head = entry;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
|
|
Packit Service |
a1973e |
_papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Must be called with CPUS_LOCK held! */
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_initialize_cpu( CpuInfo_t **dest, unsigned int cpu_num )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: dest: %p, *dest: %p, cpu_num: %d\n", dest, *dest, cpu_num);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int retval;
|
|
Packit Service |
a1973e |
CpuInfo_t *cpu;
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( cpu = allocate_cpu(cpu_num) ) == NULL ) {
|
|
Packit Service |
a1973e |
*dest = NULL;
|
|
Packit Service |
a1973e |
return PAPI_ENOMEM;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Call the component to fill in anything special. */
|
|
Packit Service |
a1973e |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit Service |
a1973e |
if (_papi_hwd[i]->cmp_info.disabled) continue;
|
|
Packit Service |
a1973e |
retval = _papi_hwd[i]->init_thread( cpu->context[i] );
|
|
Packit Service |
a1973e |
if ( retval ) {
|
|
Packit Service |
a1973e |
free_cpu( &cpu );
|
|
Packit Service |
a1973e |
*dest = NULL;
|
|
Packit Service |
a1973e |
return retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
insert_cpu( cpu );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
*dest = cpu;
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_shutdown_cpu( CpuInfo_t *cpu )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
APIDBG("Entry: cpu: %p, cpu_num: %d\n", cpu, cpu->cpu_num);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
free_cpu( &cpu );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|