PAPI 7.1.0.0
Loading...
Searching...
No Matches
cpus.c
Go to the documentation of this file.
1/****************************/
2/* THIS IS OPEN SOURCE CODE */
3/****************************/
4
5/*
6* File: cpus.c
7* Author: Gary Mohr
8* gary.mohr@bull.com
9* - based on threads.c by Philip Mucci -
10*/
11
12/* This file contains cpu allocation and bookkeeping functions */
13
14#include "papi.h"
15#include "papi_internal.h"
16#include "papi_vector.h"
17#include "papi_memory.h"
18#include "cpus.h"
19#include <string.h>
20#include <unistd.h>
21
22/* The list of cpus; this gets built as user apps set the cpu papi */
23/* option on an event set */
24
26
27
28static CpuInfo_t *
29_papi_hwi_lookup_cpu( unsigned int cpu_num )
30{
31 APIDBG("Entry:\n");
32
34
36 while ( tmp != NULL ) {
37 THRDBG( "Examining cpu %#x at %p\n", tmp->cpu_num, tmp );
38 if ( tmp->cpu_num == cpu_num ) {
39 break;
40 }
41 tmp = tmp->next;
42 if ( tmp == _papi_hwi_cpu_head ) {
43 tmp = NULL;
44 break;
45 }
46 }
47
48 if ( tmp ) {
50 THRDBG( "Found cpu %#x at %p\n", cpu_num, tmp );
51 } else {
52 THRDBG( "Did not find cpu %#x\n", cpu_num );
53 }
54
55 return tmp;
56}
57
58int
59_papi_hwi_lookup_or_create_cpu( CpuInfo_t **here, unsigned int cpu_num )
60{
61 APIDBG("Entry: here: %p\n", here);
62
63 CpuInfo_t *tmp = NULL;
64 int retval = PAPI_OK;
65
67
68 tmp = _papi_hwi_lookup_cpu(cpu_num);
69 if ( tmp == NULL ) {
70 retval = _papi_hwi_initialize_cpu( &tmp, cpu_num );
71 }
72
73 /* Increment use count */
74 tmp->num_users++;
75
76 if ( retval == PAPI_OK ) {
77 *here = tmp;
78 }
79
81
82 return retval;
83}
84
85
86static CpuInfo_t *
87allocate_cpu( unsigned int cpu_num )
88{
89 APIDBG("Entry: cpu_num: %d\n", cpu_num);
90
91 CpuInfo_t *cpu;
92 int i;
93
94 /* Allocate new CpuInfo structure */
95 cpu = ( CpuInfo_t * ) papi_calloc( 1, sizeof ( CpuInfo_t ) );
96 if ( cpu == NULL ) {
97 goto allocate_error;
98 }
99
100 /* identify the cpu this info structure represents */
101 cpu->cpu_num = cpu_num;
102 cpu->context = ( hwd_context_t ** )
103 papi_calloc( ( size_t ) papi_num_components ,
104 sizeof ( hwd_context_t * ) );
105 if ( !cpu->context ) {
106 goto error_free_cpu;
107 }
108
109 /* Allocate an eventset per component per cpu? Why? */
110
111 cpu->running_eventset = ( EventSetInfo_t ** )
113 sizeof ( EventSetInfo_t * ) );
114 if ( !cpu->running_eventset ) {
115 goto error_free_context;
116 }
117
118 for ( i = 0; i < papi_num_components; i++ ) {
119 cpu->context[i] =
120 ( void * ) papi_calloc( 1, ( size_t ) _papi_hwd[i]->size.context );
121 cpu->running_eventset[i] = NULL;
122 if ( cpu->context[i] == NULL ) {
123 goto error_free_contexts;
124 }
125 }
126
127 cpu->num_users=0;
128
129 THRDBG( "Allocated CpuInfo: %p\n", cpu );
130
131 return cpu;
132
133error_free_contexts:
134 for ( i--; i >= 0; i-- ) papi_free( cpu->context[i] );
135error_free_context:
136 papi_free( cpu->context );
137error_free_cpu:
138 papi_free( cpu );
139allocate_error:
140 return NULL;
141}
142
143/* Must be called with CPUS_LOCK held! */
144static int
146{
147 APIDBG("Entry: entry: %p\n", entry);
148
149 CpuInfo_t *tmp = NULL, *prev = NULL;
150
151 THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
153
154 /* Find the preceding element and the matched element,
155 short circuit if we've seen the head twice */
156
157 for ( tmp = ( CpuInfo_t * ) _papi_hwi_cpu_head;
158 ( entry != tmp ) || ( prev == NULL ); tmp = tmp->next ) {
159 prev = tmp;
160 }
161
162 if ( tmp != entry ) {
163 THRDBG( "Cpu %d at %p was not found in the cpu list!\n",
164 entry->cpu_num, entry );
165 return PAPI_EBUG;
166 }
167
168 /* Only 1 element in list */
169
170 if ( prev == tmp ) {
171 _papi_hwi_cpu_head = NULL;
172 tmp->next = NULL;
173 THRDBG( "_papi_hwi_cpu_head now NULL\n" );
174 } else {
175 prev->next = tmp->next;
176 /* If we're removing the head, better advance it! */
177 if ( _papi_hwi_cpu_head == tmp ) {
178 _papi_hwi_cpu_head = tmp->next;
179 THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
181 }
182 THRDBG( "Removed cpu %p from list\n", tmp );
183 }
184
185 return PAPI_OK;
186}
187
188
189static void
191{
192 APIDBG( "Entry: *cpu: %p, cpu_num: %d, cpu_users: %d\n",
193 *cpu, ( *cpu )->cpu_num, (*cpu)->num_users);
194
195 int i,users,retval;
196
198
199 (*cpu)->num_users--;
200
201 users=(*cpu)->num_users;
202
203 /* Remove from linked list if no users */
204 if (!users) remove_cpu( *cpu );
205
207
208 /* Exit early if still users of this CPU */
209 if (users!=0) return;
210
211 THRDBG( "Shutting down cpu %d at %p\n", (*cpu)->cpu_num, cpu );
212
213 for ( i = 0; i < papi_num_components; i++ ) {
214 if (_papi_hwd[i]->cmp_info.disabled) continue;
215 retval = _papi_hwd[i]->shutdown_thread( (*cpu)->context[i] );
216 if ( retval != PAPI_OK ) {
217 // failure = retval;
218 }
219 }
220
221 for ( i = 0; i < papi_num_components; i++ ) {
222 if ( ( *cpu )->context[i] ) {
223 papi_free( ( *cpu )->context[i] );
224 }
225 }
226
227 if ( ( *cpu )->context ) {
228 papi_free( ( *cpu )->context );
229 }
230
231 if ( ( *cpu )->running_eventset ) {
232 papi_free( ( *cpu )->running_eventset );
233 }
234
235 /* why do we clear this? */
236 memset( *cpu, 0x00, sizeof ( CpuInfo_t ) );
237 papi_free( *cpu );
238 *cpu = NULL;
239}
240
241/* Must be called with CPUS_LOCK held! */
242static void
244{
245 APIDBG("Entry: entry: %p\n", entry);
246
247 if ( _papi_hwi_cpu_head == NULL ) {
248 /* 0 elements */
249 THRDBG( "_papi_hwi_cpu_head is NULL\n" );
250 entry->next = entry;
251 } else if ( _papi_hwi_cpu_head->next == _papi_hwi_cpu_head ) {
252 /* 1 element */
253 THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
255 _papi_hwi_cpu_head->next = entry;
256 entry->next = ( CpuInfo_t * ) _papi_hwi_cpu_head;
257 } else {
258 /* 2+ elements */
259 THRDBG( "_papi_hwi_cpu_head was cpu %d at %p\n",
261 entry->next = _papi_hwi_cpu_head->next;
262 _papi_hwi_cpu_head->next = entry;
263 }
264
265 _papi_hwi_cpu_head = entry;
266
267 THRDBG( "_papi_hwi_cpu_head now cpu %d at %p\n",
269}
270
271
272
273/* Must be called with CPUS_LOCK held! */
274int
275_papi_hwi_initialize_cpu( CpuInfo_t **dest, unsigned int cpu_num )
276{
277 APIDBG("Entry: dest: %p, *dest: %p, cpu_num: %d\n", dest, *dest, cpu_num);
278
279 int retval;
280 CpuInfo_t *cpu;
281 int i;
282
283 if ( ( cpu = allocate_cpu(cpu_num) ) == NULL ) {
284 *dest = NULL;
285 return PAPI_ENOMEM;
286 }
287
288 /* Call the component to fill in anything special. */
289 for ( i = 0; i < papi_num_components; i++ ) {
290 if (_papi_hwd[i]->cmp_info.disabled &&
291 _papi_hwd[i]->cmp_info.disabled != PAPI_EDELAY_INIT)
292 continue;
293 retval = _papi_hwd[i]->init_thread( cpu->context[i] );
294 if ( retval ) {
295 free_cpu( &cpu );
296 *dest = NULL;
297 return retval;
298 }
299 }
300
301 insert_cpu( cpu );
302
303 *dest = cpu;
304 return PAPI_OK;
305}
306
307int
309{
310 APIDBG("Entry: cpu: %p, cpu_num: %d\n", cpu, cpu->cpu_num);
311
312 free_cpu( &cpu );
313
314 return PAPI_OK;
315}
double tmp
int i
struct papi_vectors * _papi_hwd[]
static int remove_cpu(CpuInfo_t *entry)
Definition: cpus.c:145
int _papi_hwi_initialize_cpu(CpuInfo_t **dest, unsigned int cpu_num)
Definition: cpus.c:275
static CpuInfo_t * allocate_cpu(unsigned int cpu_num)
Definition: cpus.c:87
int _papi_hwi_lookup_or_create_cpu(CpuInfo_t **here, unsigned int cpu_num)
Definition: cpus.c:59
static CpuInfo_t * _papi_hwi_cpu_head
Definition: cpus.c:25
static CpuInfo_t * _papi_hwi_lookup_cpu(unsigned int cpu_num)
Definition: cpus.c:29
static void insert_cpu(CpuInfo_t *entry)
Definition: cpus.c:243
int _papi_hwi_shutdown_cpu(CpuInfo_t *cpu)
Definition: cpus.c:308
static void free_cpu(CpuInfo_t **cpu)
Definition: cpus.c:190
#define PAPI_EBUG
Definition: f90papi.h:176
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_EDELAY_INIT
Definition: f90papi.h:271
#define PAPI_ENOMEM
Definition: f90papi.h:16
Return codes and api definitions.
#define THRDBG(format, args...)
Definition: papi_debug.h:67
#define APIDBG(format, args...)
Definition: papi_debug.h:65
int papi_num_components
#define CPUS_LOCK
Definition: papi_internal.h:92
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define papi_free(a)
Definition: papi_memory.h:35
Definition: cpus.h:11
struct _CpuInfo * next
Definition: cpus.h:13
unsigned int cpu_num
Definition: cpus.h:12
EventSetInfo_t ** running_eventset
Definition: cpus.h:15
hwd_context_t ** context
Definition: cpus.h:14
int num_users
Definition: cpus.h:17
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
int retval
Definition: zero_fork.c:53