Blame src/cpus.c

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