Source
1
+
/*
2
+
** $Id: threadutil.c,v 1.28 2009/12/31 01:51:59 rosinski Exp $
3
+
**
4
+
** Author: Jim Rosinski
5
+
**
6
+
** Utility functions handle thread-based GPTL needs.
7
+
*/
8
+
9
+
10
+
11
+
12
+
13
+
14
+
/* Max allowable number of threads (used only when THREADED_PTHREADS is true) */
15
+
16
+
17
+
/* VERBOSE is a debugging ifdef local to this file */
18
+
19
+
20
+
/* Ensure that threadinit() is called only once */
21
+
static bool first = true;
22
+
23
+
/**********************************************************************************/
24
+
/*
25
+
** 3 sets of routines: OMP threading, PTHREADS, unthreaded
26
+
*/
27
+
28
+
29
+
30
+
31
+
32
+
/* array of thread ids used to determine if thread has been started (omp only) */
33
+
static int *threadid_omp;
34
+
35
+
/*
36
+
** threadinit: Initialize threadid_omp and set number of threads
37
+
**
38
+
** Output arguments:
39
+
** nthreads: number of threads (set to zero, reset to maxthreads by get_thread_num)
40
+
** maxthreads: max number of threads
41
+
*/
42
+
43
+
int threadinit (int *nthreads, int *maxthreads)
44
+
{
45
+
int t; /* loop index */
46
+
47
+
*maxthreads = MAX ((1), (omp_get_max_threads ()));
48
+
*nthreads = 0;
49
+
50
+
if (omp_get_thread_num () > 0)
51
+
return GPTLerror ("GPTL: threadinit: MUST be called only by master thread");
52
+
53
+
if ( ! first)
54
+
return GPTLerror ("GPTL: threadinit: MUST only be called once");
55
+
56
+
first = false;
57
+
58
+
threadid_omp = GPTLallocate (*maxthreads * sizeof (int));
59
+
for (t = 0; t < *maxthreads; ++t)
60
+
threadid_omp[t] = -1;
61
+
62
+
63
+
printf ("OMP threadinit: Set *maxthreads=%d *nthreads=%d\n", *maxthreads, *nthreads);
64
+
65
+
66
+
return 0;
67
+
}
68
+
69
+
/*
70
+
** threadfinalize: clean up
71
+
*/
72
+
73
+
void threadfinalize ()
74
+
{
75
+
free (threadid_omp);
76
+
first = true;
77
+
}
78
+
79
+
/*
80
+
** get_thread_num: determine thread number of the calling thread
81
+
**
82
+
** Input args:
83
+
** nthreads: number of threads
84
+
** maxthreads: number of threads (unused in OpenMP case)
85
+
**
86
+
** Return value: thread number (success) or GPTLerror (failure)
87
+
*/
88
+
89
+
int get_thread_num (int *nthreads, int *maxthreads)
90
+
{
91
+
int t; /* thread number */
92
+
93
+
if ((t = omp_get_thread_num ()) >= *maxthreads)
94
+
return GPTLerror ("get_thread_num: returned id=%d exceeds maxthreads=%d\n",
95
+
t, *maxthreads);
96
+
97
+
/*
98
+
** The following test is true only once for each thread, so no need to worry
99
+
** about false cache sharing
100
+
*/
101
+
102
+
if (threadid_omp[t] == -1) {
103
+
threadid_omp[t] = t;
104
+
105
+
106
+
printf ("OMP get_thread_num: 1st call t=%d\n", t);
107
+
108
+
109
+
110
+
/*
111
+
** When HAVE_PAPI is true, if 1 or more PAPI events are enabled,
112
+
** create and start an event set for the new thread.
113
+
*/
114
+
115
+
if (GPTLget_npapievents () > 0) {
116
+
117
+
printf ("OMP get_thread_num: Starting EventSet t=%d\n", t);
118
+
119
+
if (GPTLcreate_and_start_events (t) < 0)
120
+
return GPTLerror ("get_thread_num: error from GPTLcreate_and_start_events for thread %d\n",
121
+
t);
122
+
}
123
+
124
+
125
+
*nthreads = *maxthreads;
126
+
}
127
+
return t;
128
+
}
129
+
130
+
void print_threadmapping (int nthreads, FILE *fp)
131
+
{
132
+
int n;
133
+
134
+
fprintf (fp, "\n");
135
+
fprintf (fp, "Thread mapping:\n");
136
+
for (n = 0; n < nthreads; ++n)
137
+
fprintf (fp, "threadid_omp[%d]=%d\n", n, threadid_omp[n]);
138
+
}
139
+
140
+
/**********************************************************************************/
141
+
/*
142
+
** PTHREADS
143
+
*/
144
+
145
+
146
+
147
+
148
+
149
+
static int lock_mutex (void); /* lock a mutex for entry into a critical region */
150
+
static int unlock_mutex (void); /* unlock a mutex for exit from a critical region */
151
+
152
+
static pthread_mutex_t t_mutex = PTHREAD_MUTEX_INITIALIZER;
153
+
static pthread_t *threadid;
154
+
155
+
/*
156
+
** threadinit: Set number of threads and max number of threads
157
+
**
158
+
** Output arguments:
159
+
** nthreads: number of threads (init to zero here, increment in get_thread_num)
160
+
** maxthreads: max number of threads (MAX_THREADS)
161
+
**
162
+
** Return value: 0 (success) or GPTLerror (failure)
163
+
*/
164
+
165
+
int threadinit (int *nthreads, int *maxthreads)
166
+
{
167
+
int nbytes;
168
+
int t;
169
+
170
+
/* Manage the threadid array which maps physical thread IDs to logical IDs */
171
+
172
+
nbytes = MAX_THREADS * sizeof (pthread_t);
173
+
if ( ! (threadid = (pthread_t *) GPTLallocate (nbytes)))
174
+
return GPTLerror ("threadinit: malloc failure for %d items\n", MAX_THREADS);
175
+
176
+
if ( ! first)
177
+
return GPTLerror ("GPTL: threadinit: MUST only be called once");
178
+
179
+
first = false;
180
+
181
+
/*
182
+
** Initialize nthreads to 0 and define the threadid array now that initialization
183
+
** is done. The actual value will be determined as get_thread_num is called.
184
+
*/
185
+
186
+
*nthreads = 0;
187
+
*maxthreads = MAX_THREADS;
188
+
189
+
for (t = 0; t < *maxthreads; ++t)
190
+
threadid[t] = (pthread_t) -1;
191
+
192
+
193
+
printf ("PTHREADS threadinit: Set *maxthreads=%d *nthreads=%d\n", *maxthreads, *nthreads);
194
+
195
+
196
+
return 0;
197
+
}
198
+
199
+
/*
200
+
** threadfinalize: clean up
201
+
*/
202
+
203
+
void threadfinalize ()
204
+
{
205
+
free (threadid);
206
+
first = true;
207
+
}
208
+
209
+
/*
210
+
** get_thread_num: determine zero-based thread number of the calling thread.
211
+
** Also: update nthreads and maxthreads if necessary.
212
+
**
213
+
** Input/output args:
214
+
** nthreads: number of threads
215
+
** maxthreads: max number of threads
216
+
**
217
+
** Return value: thread number (success) or GPTLerror (failure)
218
+
*/
219
+
220
+
int get_thread_num (int *nthreads, int *maxthreads)
221
+
{
222
+
int n; /* return value: loop index over number of threads */
223
+
pthread_t mythreadid; /* thread id from pthreads library */
224
+
225
+
mythreadid = pthread_self ();
226
+
227
+
if (lock_mutex () < 0)
228
+
return GPTLerror ("get_thread_num: mutex lock failure\n");
229
+
230
+
/*
231
+
** Loop over known physical thread IDs. When my id is found, map it
232
+
** to logical thread id for indexing. If not found return a negative
233
+
** number.
234
+
** A critical region is necessary because acess to
235
+
** the array threadid must be by only one thread at a time.
236
+
*/
237
+
238
+
for (n = 0; n < *nthreads; ++n)
239
+
if (pthread_equal (mythreadid, threadid[n]))
240
+
break;
241
+
242
+
/*
243
+
** If our thread id is not in the known list, add to it after checking that
244
+
** we do not have too many threads.
245
+
*/
246
+
247
+
if (n == *nthreads) {
248
+
if (*nthreads >= MAX_THREADS) {
249
+
if (unlock_mutex () < 0)
250
+
fprintf (stderr, "get_thread_num: mutex unlock failure\n");
251
+
252
+
return GPTLerror ("get_thread_num: nthreads=%d is too big Recompile "
253
+
"with larger value of MAX_THREADS\n", *nthreads);
254
+
}
255
+
256
+
threadid[n] = mythreadid;
257
+
258
+
259
+
printf ("PTHREADS get_thread_num: 1st call threadid=%lu maps to location %d\n", (unsigned long) mythreadid, n);
260
+
261
+
262
+
263
+
264
+
/*
265
+
** When HAVE_PAPI is true, if 1 or more PAPI events are enabled,
266
+
** create and start an event set for the new thread.
267
+
*/
268
+
269
+
if (GPTLget_npapievents () > 0) {
270
+
271
+
printf ("PTHREADS get_thread_num: Starting EventSet threadid=%lu location=%d\n",
272
+
(unsigned long) mythreadid, n);
273
+
274
+
if (GPTLcreate_and_start_events (n) < 0) {
275
+
if (unlock_mutex () < 0)
276
+
fprintf (stderr, "get_thread_num: mutex unlock failure\n");
277
+
278
+
return GPTLerror ("get_thread_num: error from GPTLcreate_and_start_events for thread %d\n",
279
+
n);
280
+
}
281
+
}
282
+
283
+
284
+
++*nthreads;
285
+
286
+
printf ("PTHREADS get_thread_num: *nthreads=%d\n", *nthreads);
287
+
288
+
}
289
+
290
+
if (unlock_mutex () < 0)
291
+
return GPTLerror ("get_thread_num: mutex unlock failure\n");
292
+
293
+
return n;
294
+
}
295
+
296
+
/*
297
+
** lock_mutex: lock a mutex for private access
298
+
*/
299
+
300
+
static int lock_mutex ()
301
+
{
302
+
if (pthread_mutex_lock (&t_mutex) != 0)
303
+
return GPTLerror ("pthread_lock_mutex failure\n");
304
+
return 0;
305
+
}
306
+
307
+
/*
308
+
** unlock_mutex: unlock a mutex from private access
309
+
*/
310
+
311
+
static int unlock_mutex ()
312
+
{
313
+
if (pthread_mutex_unlock (&t_mutex) != 0)
314
+
return GPTLerror ("pthread_unlock_mutex failure\n");
315
+
return 0;
316
+
}
317
+
318
+
void print_threadmapping (int nthreads, FILE *fp)
319
+
{
320
+
int n;
321
+
322
+
fprintf (fp, "\n");
323
+
fprintf (fp, "Thread mapping:\n");
324
+
for (n = 0; n < nthreads; ++n)
325
+
fprintf (fp, "threadid[%d]=%d\n", n, (int) threadid[n]);
326
+
}
327
+
328
+
/**********************************************************************************/
329
+
/*
330
+
** Unthreaded case
331
+
*/
332
+
333
+
334
+
335
+
static int threadid = -1;
336
+
337
+
int threadinit (int *nthreads, int *maxthreads)
338
+
{
339
+
if ( ! first)
340
+
return GPTLerror ("GPTL: threadinit: MUST only be called once");
341
+
342
+
first = false;
343
+
*nthreads = 0;
344
+
*maxthreads = 1;
345
+
return 0;
346
+
}
347
+
348
+
void threadfinalize ()
349
+
{
350
+
threadid = -1;
351
+
first = true;
352
+
}
353
+
354
+
int get_thread_num (int *nthreads, int *maxthreads)
355
+
{
356
+
357
+
/*
358
+
** When HAVE_PAPI is true, if 1 or more PAPI events are enabled,
359
+
** create and start an event set for the new thread.
360
+
*/
361
+
362
+
if (threadid == -1 && GPTLget_npapievents () > 0) {
363
+
if (GPTLcreate_and_start_events (0) < 0)
364
+
return GPTLerror ("get_thread_num: error from GPTLcreate_and_start_events for thread %0\n");
365
+
366
+
threadid = 0;
367
+
}
368
+
369
+
370
+
*nthreads = 1;
371
+
return 0;
372
+
}
373
+
374
+
void print_threadmapping (int nthreads, FILE *fp)
375
+
{
376
+
fprintf (fp, "\n");
377
+
fprintf (fp, "threadid[0]=0\n");
378
+
}
379
+
380
+