PAPI  5.0.1.0
cpus.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00005 /* 
00006 * File:    cpus.c
00007 * Author:  Gary Mohr
00008 *          gary.mohr@bull.com
00009 *          - based on threads.c by Philip Mucci -
00010 */
00011 
00012 /* This file contains cpu allocation and bookkeeping functions */
00013 
00014 #include "papi.h"
00015 #include "papi_internal.h"
00016 #include "papi_vector.h"
00017 #include "papi_memory.h"
00018 #include <string.h>
00019 #include <unistd.h>
00020 
00021 /*****************/
00022 /* BEGIN GLOBALS */
00023 /*****************/
00024 
00025 /* The following globals get initialized and cleared by:
00026    extern int _papi_hwi_init_global_cpus(void);
00027    extern int _papi_hwi_shutdown_cpu(CpuInfo_t *cpu); */
00028 
00029 volatile CpuInfo_t *_papi_hwi_cpu_head;
00030 
00031 /*****************/
00032 /*  END  GLOBALS */
00033 /*****************/
00034 
00035 static CpuInfo_t *
00036 allocate_cpu( unsigned int cpu_num )
00037 {
00038    THRDBG("Entry: cpu_num: %d\n", cpu_num);
00039     CpuInfo_t *cpu;
00040     int i;
00041 
00042     cpu = ( CpuInfo_t * ) papi_malloc( sizeof ( CpuInfo_t ) );
00043     if ( cpu == NULL )
00044         return ( NULL );
00045     memset( cpu, 0x00, sizeof ( CpuInfo_t ) );
00046     
00047     /* identify the cpu this info structure represents */
00048     cpu->cpu_num = cpu_num;
00049 
00050     cpu->context = ( hwd_context_t ** ) papi_malloc( sizeof ( hwd_context_t * ) *
00051                                           ( size_t ) papi_num_components );
00052     if ( !cpu->context ) {
00053         papi_free( cpu );
00054         return ( NULL );
00055     }
00056     
00057     cpu->running_eventset =
00058         ( EventSetInfo_t ** ) papi_malloc( sizeof ( EventSetInfo_t * ) *
00059                                            ( size_t ) papi_num_components );
00060     if ( !cpu->running_eventset ) {
00061         papi_free( cpu->context );
00062         papi_free( cpu );
00063         return ( NULL );
00064     }
00065 
00066     for ( i = 0; i < papi_num_components; i++ ) {
00067         cpu->context[i] =
00068             ( void * ) papi_malloc( ( size_t ) _papi_hwd[i]->size.context );
00069         cpu->running_eventset[i] = NULL;
00070         if ( cpu->context[i] == NULL ) {
00071             for ( i--; i >= 0; i-- )
00072                 papi_free( cpu->context[i] );
00073             papi_free( cpu->context );
00074             papi_free( cpu );
00075             return ( NULL );
00076         }
00077         memset( cpu->context[i], 0x00,
00078                 ( size_t ) _papi_hwd[i]->size.context );
00079     }
00080 
00081     THRDBG( "Allocated CpuInfo: %p\n", cpu );
00082     return ( cpu );
00083 }
00084 
00085 static void
00086 free_cpu( CpuInfo_t ** cpu )
00087 {
00088    THRDBG( "Entry: *cpu: %p, cpu_num: 0x%x\n", *cpu, ( *cpu )->cpu_num);
00089     int i;
00090     for ( i = 0; i < papi_num_components; i++ ) {
00091         if ( ( *cpu )->context[i] )
00092             papi_free( ( *cpu )->context[i] );
00093     }
00094 
00095     if ( ( *cpu )->context )
00096         papi_free( ( *cpu )->context );
00097 
00098     if ( ( *cpu )->running_eventset )
00099         papi_free( ( *cpu )->running_eventset );
00100 
00101     memset( *cpu, 0x00, sizeof ( CpuInfo_t ) );
00102     papi_free( *cpu );
00103     *cpu = NULL;
00104 }
00105 
00106 static void
00107 insert_cpu( CpuInfo_t * entry )
00108 {
00109    THRDBG("Entry: entry: %p\n", entry);
00110     _papi_hwi_lock( CPUS_LOCK );
00111 
00112     if ( _papi_hwi_cpu_head == NULL ) { /* 0 elements */
00113         THRDBG( "_papi_hwi_cpu_head is NULL\n" );
00114         entry->next = entry;
00115     } else if ( _papi_hwi_cpu_head->next == _papi_hwi_cpu_head ) {  /* 1 elements */
00116         THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
00117                 _papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
00118         _papi_hwi_cpu_head->next = entry;
00119         entry->next = ( CpuInfo_t * ) _papi_hwi_cpu_head;
00120     } else {                 /* 2+ elements */
00121 
00122         THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
00123                 _papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
00124         entry->next = _papi_hwi_cpu_head->next;
00125         _papi_hwi_cpu_head->next = entry;
00126     }
00127 
00128     _papi_hwi_cpu_head = entry;
00129 
00130     THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
00131             _papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
00132 
00133     _papi_hwi_unlock( CPUS_LOCK );
00134 
00135 }
00136 
00137 static int
00138 remove_cpu( CpuInfo_t * entry )
00139 {
00140    THRDBG("Entry: entry: %p\n", entry);
00141     CpuInfo_t *tmp = NULL, *prev = NULL;
00142 
00143     _papi_hwi_lock( CPUS_LOCK );
00144 
00145     THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
00146             _papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
00147 
00148     /* Find the preceding element and the matched element,
00149        short circuit if we've seen the head twice */
00150 
00151     for ( tmp = ( CpuInfo_t * ) _papi_hwi_cpu_head;
00152           ( entry != tmp ) || ( prev == NULL ); tmp = tmp->next ) {
00153         prev = tmp;
00154     }
00155 
00156     if ( tmp != entry ) {
00157         THRDBG( "Cpu %d at %p was not found in the cpu list!\n",
00158                 entry->cpu_num, entry );
00159         return ( PAPI_EBUG );
00160     }
00161 
00162     /* Only 1 element in list */
00163 
00164     if ( prev == tmp ) {
00165         _papi_hwi_cpu_head = NULL;
00166         tmp->next = NULL;
00167         THRDBG( "_papi_hwi_cpu_head now NULL\n" );
00168     } else {
00169         prev->next = tmp->next;
00170         /* If we're removing the head, better advance it! */
00171         if ( _papi_hwi_cpu_head == tmp ) {
00172             _papi_hwi_cpu_head = tmp->next;
00173             THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
00174                     _papi_hwi_cpu_head->cpu_num, _papi_hwi_cpu_head );
00175         }
00176         THRDBG( "Removed cpu %p from list\n", tmp );
00177     }
00178 
00179     _papi_hwi_unlock( CPUS_LOCK );
00180 
00181     return ( PAPI_OK );
00182 }
00183 
00184 int
00185 _papi_hwi_initialize_cpu( CpuInfo_t ** dest, unsigned int cpu_num )
00186 {
00187    THRDBG("Entry: dest: %p, *dest: %p, cpu_num: %d\n", dest, *dest, cpu_num);
00188     int retval;
00189     CpuInfo_t *cpu;
00190     int i;
00191 
00192     if ( ( cpu = allocate_cpu(cpu_num) ) == NULL ) {
00193         *dest = NULL;
00194         return ( PAPI_ENOMEM );
00195     }
00196 
00197     /* Call the component to fill in anything special. */
00198     for ( i = 0; i < papi_num_components; i++ ) {
00199         retval = _papi_hwd[i]->init_thread( cpu->context[i] );
00200         if ( retval ) {
00201             free_cpu( &cpu );
00202             *dest = NULL;
00203             return ( retval );
00204         }
00205     }
00206 
00207     insert_cpu( cpu );
00208 
00209     *dest = cpu;
00210     return ( PAPI_OK );
00211 }
00212 
00213 int
00214 _papi_hwi_shutdown_cpu( CpuInfo_t * cpu )
00215 {
00216    THRDBG("Entry: cpu: %p, cpu_num: %d\n", cpu, cpu->cpu_num);
00217     int retval = PAPI_OK;
00218     int i, failure = 0;
00219 
00220     remove_cpu( cpu );
00221     THRDBG( "Shutting down cpu %d at %p\n", cpu->cpu_num, cpu );
00222     for ( i = 0; i < papi_num_components; i++ ) {
00223         retval = _papi_hwd[i]->shutdown_thread( cpu->context[i] );
00224         if ( retval != PAPI_OK )
00225             failure = retval;
00226     }
00227     free_cpu( &cpu );
00228     return ( failure );
00229 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines