|
PAPI
5.0.1.0
|
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 }