1*629ff9f7SJohn Marino /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
2*629ff9f7SJohn Marino Free Software Foundation, Inc.
3*629ff9f7SJohn Marino Contributed by Richard Henderson <rth@redhat.com>.
4*629ff9f7SJohn Marino
5*629ff9f7SJohn Marino This file is part of the GNU OpenMP Library (libgomp).
6*629ff9f7SJohn Marino
7*629ff9f7SJohn Marino Libgomp is free software; you can redistribute it and/or modify it
8*629ff9f7SJohn Marino under the terms of the GNU General Public License as published by
9*629ff9f7SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10*629ff9f7SJohn Marino any later version.
11*629ff9f7SJohn Marino
12*629ff9f7SJohn Marino Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13*629ff9f7SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14*629ff9f7SJohn Marino FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15*629ff9f7SJohn Marino more details.
16*629ff9f7SJohn Marino
17*629ff9f7SJohn Marino Under Section 7 of GPL version 3, you are granted additional
18*629ff9f7SJohn Marino permissions described in the GCC Runtime Library Exception, version
19*629ff9f7SJohn Marino 3.1, as published by the Free Software Foundation.
20*629ff9f7SJohn Marino
21*629ff9f7SJohn Marino You should have received a copy of the GNU General Public License and
22*629ff9f7SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
23*629ff9f7SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24*629ff9f7SJohn Marino <http://www.gnu.org/licenses/>. */
25*629ff9f7SJohn Marino
26*629ff9f7SJohn Marino /* This file defines the OpenMP internal control variables, and arranges
27*629ff9f7SJohn Marino for them to be initialized from environment variables at startup. */
28*629ff9f7SJohn Marino
29*629ff9f7SJohn Marino #include "libgomp.h"
30*629ff9f7SJohn Marino #include "libgomp_f.h"
31*629ff9f7SJohn Marino #include <ctype.h>
32*629ff9f7SJohn Marino #include <stdlib.h>
33*629ff9f7SJohn Marino #ifdef STRING_WITH_STRINGS
34*629ff9f7SJohn Marino # include <string.h>
35*629ff9f7SJohn Marino # include <strings.h>
36*629ff9f7SJohn Marino #else
37*629ff9f7SJohn Marino # ifdef HAVE_STRING_H
38*629ff9f7SJohn Marino # include <string.h>
39*629ff9f7SJohn Marino # else
40*629ff9f7SJohn Marino # ifdef HAVE_STRINGS_H
41*629ff9f7SJohn Marino # include <strings.h>
42*629ff9f7SJohn Marino # endif
43*629ff9f7SJohn Marino # endif
44*629ff9f7SJohn Marino #endif
45*629ff9f7SJohn Marino #include <limits.h>
46*629ff9f7SJohn Marino #include <errno.h>
47*629ff9f7SJohn Marino
48*629ff9f7SJohn Marino #ifndef HAVE_STRTOULL
49*629ff9f7SJohn Marino # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
50*629ff9f7SJohn Marino #endif
51*629ff9f7SJohn Marino
52*629ff9f7SJohn Marino struct gomp_task_icv gomp_global_icv = {
53*629ff9f7SJohn Marino .nthreads_var = 1,
54*629ff9f7SJohn Marino .run_sched_var = GFS_DYNAMIC,
55*629ff9f7SJohn Marino .run_sched_modifier = 1,
56*629ff9f7SJohn Marino .dyn_var = false,
57*629ff9f7SJohn Marino .nest_var = false
58*629ff9f7SJohn Marino };
59*629ff9f7SJohn Marino
60*629ff9f7SJohn Marino unsigned short *gomp_cpu_affinity;
61*629ff9f7SJohn Marino size_t gomp_cpu_affinity_len;
62*629ff9f7SJohn Marino unsigned long gomp_max_active_levels_var = INT_MAX;
63*629ff9f7SJohn Marino unsigned long gomp_thread_limit_var = ULONG_MAX;
64*629ff9f7SJohn Marino unsigned long gomp_remaining_threads_count;
65*629ff9f7SJohn Marino #ifndef HAVE_SYNC_BUILTINS
66*629ff9f7SJohn Marino gomp_mutex_t gomp_remaining_threads_lock;
67*629ff9f7SJohn Marino #endif
68*629ff9f7SJohn Marino unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
69*629ff9f7SJohn Marino unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
70*629ff9f7SJohn Marino unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
71*629ff9f7SJohn Marino
72*629ff9f7SJohn Marino /* Parse the OMP_SCHEDULE environment variable. */
73*629ff9f7SJohn Marino
74*629ff9f7SJohn Marino static void
parse_schedule(void)75*629ff9f7SJohn Marino parse_schedule (void)
76*629ff9f7SJohn Marino {
77*629ff9f7SJohn Marino char *env, *end;
78*629ff9f7SJohn Marino unsigned long value;
79*629ff9f7SJohn Marino
80*629ff9f7SJohn Marino env = getenv ("OMP_SCHEDULE");
81*629ff9f7SJohn Marino if (env == NULL)
82*629ff9f7SJohn Marino return;
83*629ff9f7SJohn Marino
84*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
85*629ff9f7SJohn Marino ++env;
86*629ff9f7SJohn Marino if (strncasecmp (env, "static", 6) == 0)
87*629ff9f7SJohn Marino {
88*629ff9f7SJohn Marino gomp_global_icv.run_sched_var = GFS_STATIC;
89*629ff9f7SJohn Marino env += 6;
90*629ff9f7SJohn Marino }
91*629ff9f7SJohn Marino else if (strncasecmp (env, "dynamic", 7) == 0)
92*629ff9f7SJohn Marino {
93*629ff9f7SJohn Marino gomp_global_icv.run_sched_var = GFS_DYNAMIC;
94*629ff9f7SJohn Marino env += 7;
95*629ff9f7SJohn Marino }
96*629ff9f7SJohn Marino else if (strncasecmp (env, "guided", 6) == 0)
97*629ff9f7SJohn Marino {
98*629ff9f7SJohn Marino gomp_global_icv.run_sched_var = GFS_GUIDED;
99*629ff9f7SJohn Marino env += 6;
100*629ff9f7SJohn Marino }
101*629ff9f7SJohn Marino else if (strncasecmp (env, "auto", 4) == 0)
102*629ff9f7SJohn Marino {
103*629ff9f7SJohn Marino gomp_global_icv.run_sched_var = GFS_AUTO;
104*629ff9f7SJohn Marino env += 4;
105*629ff9f7SJohn Marino }
106*629ff9f7SJohn Marino else
107*629ff9f7SJohn Marino goto unknown;
108*629ff9f7SJohn Marino
109*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
110*629ff9f7SJohn Marino ++env;
111*629ff9f7SJohn Marino if (*env == '\0')
112*629ff9f7SJohn Marino {
113*629ff9f7SJohn Marino gomp_global_icv.run_sched_modifier
114*629ff9f7SJohn Marino = gomp_global_icv.run_sched_var != GFS_STATIC;
115*629ff9f7SJohn Marino return;
116*629ff9f7SJohn Marino }
117*629ff9f7SJohn Marino if (*env++ != ',')
118*629ff9f7SJohn Marino goto unknown;
119*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
120*629ff9f7SJohn Marino ++env;
121*629ff9f7SJohn Marino if (*env == '\0')
122*629ff9f7SJohn Marino goto invalid;
123*629ff9f7SJohn Marino
124*629ff9f7SJohn Marino errno = 0;
125*629ff9f7SJohn Marino value = strtoul (env, &end, 10);
126*629ff9f7SJohn Marino if (errno)
127*629ff9f7SJohn Marino goto invalid;
128*629ff9f7SJohn Marino
129*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
130*629ff9f7SJohn Marino ++end;
131*629ff9f7SJohn Marino if (*end != '\0')
132*629ff9f7SJohn Marino goto invalid;
133*629ff9f7SJohn Marino
134*629ff9f7SJohn Marino if ((int)value != value)
135*629ff9f7SJohn Marino goto invalid;
136*629ff9f7SJohn Marino
137*629ff9f7SJohn Marino if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
138*629ff9f7SJohn Marino value = 1;
139*629ff9f7SJohn Marino gomp_global_icv.run_sched_modifier = value;
140*629ff9f7SJohn Marino return;
141*629ff9f7SJohn Marino
142*629ff9f7SJohn Marino unknown:
143*629ff9f7SJohn Marino gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
144*629ff9f7SJohn Marino return;
145*629ff9f7SJohn Marino
146*629ff9f7SJohn Marino invalid:
147*629ff9f7SJohn Marino gomp_error ("Invalid value for chunk size in "
148*629ff9f7SJohn Marino "environment variable OMP_SCHEDULE");
149*629ff9f7SJohn Marino return;
150*629ff9f7SJohn Marino }
151*629ff9f7SJohn Marino
152*629ff9f7SJohn Marino /* Parse an unsigned long environment variable. Return true if one was
153*629ff9f7SJohn Marino present and it was successfully parsed. */
154*629ff9f7SJohn Marino
155*629ff9f7SJohn Marino static bool
parse_unsigned_long(const char * name,unsigned long * pvalue,bool allow_zero)156*629ff9f7SJohn Marino parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
157*629ff9f7SJohn Marino {
158*629ff9f7SJohn Marino char *env, *end;
159*629ff9f7SJohn Marino unsigned long value;
160*629ff9f7SJohn Marino
161*629ff9f7SJohn Marino env = getenv (name);
162*629ff9f7SJohn Marino if (env == NULL)
163*629ff9f7SJohn Marino return false;
164*629ff9f7SJohn Marino
165*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
166*629ff9f7SJohn Marino ++env;
167*629ff9f7SJohn Marino if (*env == '\0')
168*629ff9f7SJohn Marino goto invalid;
169*629ff9f7SJohn Marino
170*629ff9f7SJohn Marino errno = 0;
171*629ff9f7SJohn Marino value = strtoul (env, &end, 10);
172*629ff9f7SJohn Marino if (errno || (long) value <= 0 - allow_zero)
173*629ff9f7SJohn Marino goto invalid;
174*629ff9f7SJohn Marino
175*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
176*629ff9f7SJohn Marino ++end;
177*629ff9f7SJohn Marino if (*end != '\0')
178*629ff9f7SJohn Marino goto invalid;
179*629ff9f7SJohn Marino
180*629ff9f7SJohn Marino *pvalue = value;
181*629ff9f7SJohn Marino return true;
182*629ff9f7SJohn Marino
183*629ff9f7SJohn Marino invalid:
184*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable %s", name);
185*629ff9f7SJohn Marino return false;
186*629ff9f7SJohn Marino }
187*629ff9f7SJohn Marino
188*629ff9f7SJohn Marino /* Parse an unsigned long list environment variable. Return true if one was
189*629ff9f7SJohn Marino present and it was successfully parsed. */
190*629ff9f7SJohn Marino
191*629ff9f7SJohn Marino static bool
parse_unsigned_long_list(const char * name,unsigned long * p1stvalue,unsigned long ** pvalues,unsigned long * pnvalues)192*629ff9f7SJohn Marino parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
193*629ff9f7SJohn Marino unsigned long **pvalues,
194*629ff9f7SJohn Marino unsigned long *pnvalues)
195*629ff9f7SJohn Marino {
196*629ff9f7SJohn Marino char *env, *end;
197*629ff9f7SJohn Marino unsigned long value, *values = NULL;
198*629ff9f7SJohn Marino
199*629ff9f7SJohn Marino env = getenv (name);
200*629ff9f7SJohn Marino if (env == NULL)
201*629ff9f7SJohn Marino return false;
202*629ff9f7SJohn Marino
203*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
204*629ff9f7SJohn Marino ++env;
205*629ff9f7SJohn Marino if (*env == '\0')
206*629ff9f7SJohn Marino goto invalid;
207*629ff9f7SJohn Marino
208*629ff9f7SJohn Marino errno = 0;
209*629ff9f7SJohn Marino value = strtoul (env, &end, 10);
210*629ff9f7SJohn Marino if (errno || (long) value <= 0)
211*629ff9f7SJohn Marino goto invalid;
212*629ff9f7SJohn Marino
213*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
214*629ff9f7SJohn Marino ++end;
215*629ff9f7SJohn Marino if (*end != '\0')
216*629ff9f7SJohn Marino {
217*629ff9f7SJohn Marino if (*end == ',')
218*629ff9f7SJohn Marino {
219*629ff9f7SJohn Marino unsigned long nvalues = 0, nalloced = 0;
220*629ff9f7SJohn Marino
221*629ff9f7SJohn Marino do
222*629ff9f7SJohn Marino {
223*629ff9f7SJohn Marino env = end + 1;
224*629ff9f7SJohn Marino if (nvalues == nalloced)
225*629ff9f7SJohn Marino {
226*629ff9f7SJohn Marino unsigned long *n;
227*629ff9f7SJohn Marino nalloced = nalloced ? nalloced * 2 : 16;
228*629ff9f7SJohn Marino n = realloc (values, nalloced * sizeof (unsigned long));
229*629ff9f7SJohn Marino if (n == NULL)
230*629ff9f7SJohn Marino {
231*629ff9f7SJohn Marino free (values);
232*629ff9f7SJohn Marino gomp_error ("Out of memory while trying to parse"
233*629ff9f7SJohn Marino " environment variable %s", name);
234*629ff9f7SJohn Marino return false;
235*629ff9f7SJohn Marino }
236*629ff9f7SJohn Marino values = n;
237*629ff9f7SJohn Marino if (nvalues == 0)
238*629ff9f7SJohn Marino values[nvalues++] = value;
239*629ff9f7SJohn Marino }
240*629ff9f7SJohn Marino
241*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
242*629ff9f7SJohn Marino ++env;
243*629ff9f7SJohn Marino if (*env == '\0')
244*629ff9f7SJohn Marino goto invalid;
245*629ff9f7SJohn Marino
246*629ff9f7SJohn Marino errno = 0;
247*629ff9f7SJohn Marino value = strtoul (env, &end, 10);
248*629ff9f7SJohn Marino if (errno || (long) value <= 0)
249*629ff9f7SJohn Marino goto invalid;
250*629ff9f7SJohn Marino
251*629ff9f7SJohn Marino values[nvalues++] = value;
252*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
253*629ff9f7SJohn Marino ++end;
254*629ff9f7SJohn Marino if (*end == '\0')
255*629ff9f7SJohn Marino break;
256*629ff9f7SJohn Marino if (*end != ',')
257*629ff9f7SJohn Marino goto invalid;
258*629ff9f7SJohn Marino }
259*629ff9f7SJohn Marino while (1);
260*629ff9f7SJohn Marino *p1stvalue = values[0];
261*629ff9f7SJohn Marino *pvalues = values;
262*629ff9f7SJohn Marino *pnvalues = nvalues;
263*629ff9f7SJohn Marino return true;
264*629ff9f7SJohn Marino }
265*629ff9f7SJohn Marino goto invalid;
266*629ff9f7SJohn Marino }
267*629ff9f7SJohn Marino
268*629ff9f7SJohn Marino *p1stvalue = value;
269*629ff9f7SJohn Marino return true;
270*629ff9f7SJohn Marino
271*629ff9f7SJohn Marino invalid:
272*629ff9f7SJohn Marino free (values);
273*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable %s", name);
274*629ff9f7SJohn Marino return false;
275*629ff9f7SJohn Marino }
276*629ff9f7SJohn Marino
277*629ff9f7SJohn Marino /* Parse the OMP_STACKSIZE environment varible. Return true if one was
278*629ff9f7SJohn Marino present and it was successfully parsed. */
279*629ff9f7SJohn Marino
280*629ff9f7SJohn Marino static bool
parse_stacksize(const char * name,unsigned long * pvalue)281*629ff9f7SJohn Marino parse_stacksize (const char *name, unsigned long *pvalue)
282*629ff9f7SJohn Marino {
283*629ff9f7SJohn Marino char *env, *end;
284*629ff9f7SJohn Marino unsigned long value, shift = 10;
285*629ff9f7SJohn Marino
286*629ff9f7SJohn Marino env = getenv (name);
287*629ff9f7SJohn Marino if (env == NULL)
288*629ff9f7SJohn Marino return false;
289*629ff9f7SJohn Marino
290*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
291*629ff9f7SJohn Marino ++env;
292*629ff9f7SJohn Marino if (*env == '\0')
293*629ff9f7SJohn Marino goto invalid;
294*629ff9f7SJohn Marino
295*629ff9f7SJohn Marino errno = 0;
296*629ff9f7SJohn Marino value = strtoul (env, &end, 10);
297*629ff9f7SJohn Marino if (errno)
298*629ff9f7SJohn Marino goto invalid;
299*629ff9f7SJohn Marino
300*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
301*629ff9f7SJohn Marino ++end;
302*629ff9f7SJohn Marino if (*end != '\0')
303*629ff9f7SJohn Marino {
304*629ff9f7SJohn Marino switch (tolower ((unsigned char) *end))
305*629ff9f7SJohn Marino {
306*629ff9f7SJohn Marino case 'b':
307*629ff9f7SJohn Marino shift = 0;
308*629ff9f7SJohn Marino break;
309*629ff9f7SJohn Marino case 'k':
310*629ff9f7SJohn Marino break;
311*629ff9f7SJohn Marino case 'm':
312*629ff9f7SJohn Marino shift = 20;
313*629ff9f7SJohn Marino break;
314*629ff9f7SJohn Marino case 'g':
315*629ff9f7SJohn Marino shift = 30;
316*629ff9f7SJohn Marino break;
317*629ff9f7SJohn Marino default:
318*629ff9f7SJohn Marino goto invalid;
319*629ff9f7SJohn Marino }
320*629ff9f7SJohn Marino ++end;
321*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
322*629ff9f7SJohn Marino ++end;
323*629ff9f7SJohn Marino if (*end != '\0')
324*629ff9f7SJohn Marino goto invalid;
325*629ff9f7SJohn Marino }
326*629ff9f7SJohn Marino
327*629ff9f7SJohn Marino if (((value << shift) >> shift) != value)
328*629ff9f7SJohn Marino goto invalid;
329*629ff9f7SJohn Marino
330*629ff9f7SJohn Marino *pvalue = value << shift;
331*629ff9f7SJohn Marino return true;
332*629ff9f7SJohn Marino
333*629ff9f7SJohn Marino invalid:
334*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable %s", name);
335*629ff9f7SJohn Marino return false;
336*629ff9f7SJohn Marino }
337*629ff9f7SJohn Marino
338*629ff9f7SJohn Marino /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
339*629ff9f7SJohn Marino present and it was successfully parsed. */
340*629ff9f7SJohn Marino
341*629ff9f7SJohn Marino static bool
parse_spincount(const char * name,unsigned long long * pvalue)342*629ff9f7SJohn Marino parse_spincount (const char *name, unsigned long long *pvalue)
343*629ff9f7SJohn Marino {
344*629ff9f7SJohn Marino char *env, *end;
345*629ff9f7SJohn Marino unsigned long long value, mult = 1;
346*629ff9f7SJohn Marino
347*629ff9f7SJohn Marino env = getenv (name);
348*629ff9f7SJohn Marino if (env == NULL)
349*629ff9f7SJohn Marino return false;
350*629ff9f7SJohn Marino
351*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
352*629ff9f7SJohn Marino ++env;
353*629ff9f7SJohn Marino if (*env == '\0')
354*629ff9f7SJohn Marino goto invalid;
355*629ff9f7SJohn Marino
356*629ff9f7SJohn Marino if (strncasecmp (env, "infinite", 8) == 0
357*629ff9f7SJohn Marino || strncasecmp (env, "infinity", 8) == 0)
358*629ff9f7SJohn Marino {
359*629ff9f7SJohn Marino value = ~0ULL;
360*629ff9f7SJohn Marino end = env + 8;
361*629ff9f7SJohn Marino goto check_tail;
362*629ff9f7SJohn Marino }
363*629ff9f7SJohn Marino
364*629ff9f7SJohn Marino errno = 0;
365*629ff9f7SJohn Marino value = strtoull (env, &end, 10);
366*629ff9f7SJohn Marino if (errno)
367*629ff9f7SJohn Marino goto invalid;
368*629ff9f7SJohn Marino
369*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
370*629ff9f7SJohn Marino ++end;
371*629ff9f7SJohn Marino if (*end != '\0')
372*629ff9f7SJohn Marino {
373*629ff9f7SJohn Marino switch (tolower ((unsigned char) *end))
374*629ff9f7SJohn Marino {
375*629ff9f7SJohn Marino case 'k':
376*629ff9f7SJohn Marino mult = 1000LL;
377*629ff9f7SJohn Marino break;
378*629ff9f7SJohn Marino case 'm':
379*629ff9f7SJohn Marino mult = 1000LL * 1000LL;
380*629ff9f7SJohn Marino break;
381*629ff9f7SJohn Marino case 'g':
382*629ff9f7SJohn Marino mult = 1000LL * 1000LL * 1000LL;
383*629ff9f7SJohn Marino break;
384*629ff9f7SJohn Marino case 't':
385*629ff9f7SJohn Marino mult = 1000LL * 1000LL * 1000LL * 1000LL;
386*629ff9f7SJohn Marino break;
387*629ff9f7SJohn Marino default:
388*629ff9f7SJohn Marino goto invalid;
389*629ff9f7SJohn Marino }
390*629ff9f7SJohn Marino ++end;
391*629ff9f7SJohn Marino check_tail:
392*629ff9f7SJohn Marino while (isspace ((unsigned char) *end))
393*629ff9f7SJohn Marino ++end;
394*629ff9f7SJohn Marino if (*end != '\0')
395*629ff9f7SJohn Marino goto invalid;
396*629ff9f7SJohn Marino }
397*629ff9f7SJohn Marino
398*629ff9f7SJohn Marino if (value > ~0ULL / mult)
399*629ff9f7SJohn Marino value = ~0ULL;
400*629ff9f7SJohn Marino else
401*629ff9f7SJohn Marino value *= mult;
402*629ff9f7SJohn Marino
403*629ff9f7SJohn Marino *pvalue = value;
404*629ff9f7SJohn Marino return true;
405*629ff9f7SJohn Marino
406*629ff9f7SJohn Marino invalid:
407*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable %s", name);
408*629ff9f7SJohn Marino return false;
409*629ff9f7SJohn Marino }
410*629ff9f7SJohn Marino
411*629ff9f7SJohn Marino /* Parse a boolean value for environment variable NAME and store the
412*629ff9f7SJohn Marino result in VALUE. */
413*629ff9f7SJohn Marino
414*629ff9f7SJohn Marino static void
parse_boolean(const char * name,bool * value)415*629ff9f7SJohn Marino parse_boolean (const char *name, bool *value)
416*629ff9f7SJohn Marino {
417*629ff9f7SJohn Marino const char *env;
418*629ff9f7SJohn Marino
419*629ff9f7SJohn Marino env = getenv (name);
420*629ff9f7SJohn Marino if (env == NULL)
421*629ff9f7SJohn Marino return;
422*629ff9f7SJohn Marino
423*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
424*629ff9f7SJohn Marino ++env;
425*629ff9f7SJohn Marino if (strncasecmp (env, "true", 4) == 0)
426*629ff9f7SJohn Marino {
427*629ff9f7SJohn Marino *value = true;
428*629ff9f7SJohn Marino env += 4;
429*629ff9f7SJohn Marino }
430*629ff9f7SJohn Marino else if (strncasecmp (env, "false", 5) == 0)
431*629ff9f7SJohn Marino {
432*629ff9f7SJohn Marino *value = false;
433*629ff9f7SJohn Marino env += 5;
434*629ff9f7SJohn Marino }
435*629ff9f7SJohn Marino else
436*629ff9f7SJohn Marino env = "X";
437*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
438*629ff9f7SJohn Marino ++env;
439*629ff9f7SJohn Marino if (*env != '\0')
440*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable %s", name);
441*629ff9f7SJohn Marino }
442*629ff9f7SJohn Marino
443*629ff9f7SJohn Marino /* Parse the OMP_WAIT_POLICY environment variable and store the
444*629ff9f7SJohn Marino result in gomp_active_wait_policy. */
445*629ff9f7SJohn Marino
446*629ff9f7SJohn Marino static int
parse_wait_policy(void)447*629ff9f7SJohn Marino parse_wait_policy (void)
448*629ff9f7SJohn Marino {
449*629ff9f7SJohn Marino const char *env;
450*629ff9f7SJohn Marino int ret = -1;
451*629ff9f7SJohn Marino
452*629ff9f7SJohn Marino env = getenv ("OMP_WAIT_POLICY");
453*629ff9f7SJohn Marino if (env == NULL)
454*629ff9f7SJohn Marino return -1;
455*629ff9f7SJohn Marino
456*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
457*629ff9f7SJohn Marino ++env;
458*629ff9f7SJohn Marino if (strncasecmp (env, "active", 6) == 0)
459*629ff9f7SJohn Marino {
460*629ff9f7SJohn Marino ret = 1;
461*629ff9f7SJohn Marino env += 6;
462*629ff9f7SJohn Marino }
463*629ff9f7SJohn Marino else if (strncasecmp (env, "passive", 7) == 0)
464*629ff9f7SJohn Marino {
465*629ff9f7SJohn Marino ret = 0;
466*629ff9f7SJohn Marino env += 7;
467*629ff9f7SJohn Marino }
468*629ff9f7SJohn Marino else
469*629ff9f7SJohn Marino env = "X";
470*629ff9f7SJohn Marino while (isspace ((unsigned char) *env))
471*629ff9f7SJohn Marino ++env;
472*629ff9f7SJohn Marino if (*env == '\0')
473*629ff9f7SJohn Marino return ret;
474*629ff9f7SJohn Marino gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
475*629ff9f7SJohn Marino return -1;
476*629ff9f7SJohn Marino }
477*629ff9f7SJohn Marino
478*629ff9f7SJohn Marino /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
479*629ff9f7SJohn Marino present and it was successfully parsed. */
480*629ff9f7SJohn Marino
481*629ff9f7SJohn Marino static bool
parse_affinity(void)482*629ff9f7SJohn Marino parse_affinity (void)
483*629ff9f7SJohn Marino {
484*629ff9f7SJohn Marino char *env, *end;
485*629ff9f7SJohn Marino unsigned long cpu_beg, cpu_end, cpu_stride;
486*629ff9f7SJohn Marino unsigned short *cpus = NULL;
487*629ff9f7SJohn Marino size_t allocated = 0, used = 0, needed;
488*629ff9f7SJohn Marino
489*629ff9f7SJohn Marino env = getenv ("GOMP_CPU_AFFINITY");
490*629ff9f7SJohn Marino if (env == NULL)
491*629ff9f7SJohn Marino return false;
492*629ff9f7SJohn Marino
493*629ff9f7SJohn Marino do
494*629ff9f7SJohn Marino {
495*629ff9f7SJohn Marino while (*env == ' ' || *env == '\t')
496*629ff9f7SJohn Marino env++;
497*629ff9f7SJohn Marino
498*629ff9f7SJohn Marino cpu_beg = strtoul (env, &end, 0);
499*629ff9f7SJohn Marino cpu_end = cpu_beg;
500*629ff9f7SJohn Marino cpu_stride = 1;
501*629ff9f7SJohn Marino if (env == end || cpu_beg >= 65536)
502*629ff9f7SJohn Marino goto invalid;
503*629ff9f7SJohn Marino
504*629ff9f7SJohn Marino env = end;
505*629ff9f7SJohn Marino if (*env == '-')
506*629ff9f7SJohn Marino {
507*629ff9f7SJohn Marino cpu_end = strtoul (++env, &end, 0);
508*629ff9f7SJohn Marino if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
509*629ff9f7SJohn Marino goto invalid;
510*629ff9f7SJohn Marino
511*629ff9f7SJohn Marino env = end;
512*629ff9f7SJohn Marino if (*env == ':')
513*629ff9f7SJohn Marino {
514*629ff9f7SJohn Marino cpu_stride = strtoul (++env, &end, 0);
515*629ff9f7SJohn Marino if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
516*629ff9f7SJohn Marino goto invalid;
517*629ff9f7SJohn Marino
518*629ff9f7SJohn Marino env = end;
519*629ff9f7SJohn Marino }
520*629ff9f7SJohn Marino }
521*629ff9f7SJohn Marino
522*629ff9f7SJohn Marino needed = (cpu_end - cpu_beg) / cpu_stride + 1;
523*629ff9f7SJohn Marino if (used + needed >= allocated)
524*629ff9f7SJohn Marino {
525*629ff9f7SJohn Marino unsigned short *new_cpus;
526*629ff9f7SJohn Marino
527*629ff9f7SJohn Marino if (allocated < 64)
528*629ff9f7SJohn Marino allocated = 64;
529*629ff9f7SJohn Marino if (allocated > needed)
530*629ff9f7SJohn Marino allocated <<= 1;
531*629ff9f7SJohn Marino else
532*629ff9f7SJohn Marino allocated += 2 * needed;
533*629ff9f7SJohn Marino new_cpus = realloc (cpus, allocated * sizeof (unsigned short));
534*629ff9f7SJohn Marino if (new_cpus == NULL)
535*629ff9f7SJohn Marino {
536*629ff9f7SJohn Marino free (cpus);
537*629ff9f7SJohn Marino gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
538*629ff9f7SJohn Marino return false;
539*629ff9f7SJohn Marino }
540*629ff9f7SJohn Marino
541*629ff9f7SJohn Marino cpus = new_cpus;
542*629ff9f7SJohn Marino }
543*629ff9f7SJohn Marino
544*629ff9f7SJohn Marino while (needed--)
545*629ff9f7SJohn Marino {
546*629ff9f7SJohn Marino cpus[used++] = cpu_beg;
547*629ff9f7SJohn Marino cpu_beg += cpu_stride;
548*629ff9f7SJohn Marino }
549*629ff9f7SJohn Marino
550*629ff9f7SJohn Marino while (*env == ' ' || *env == '\t')
551*629ff9f7SJohn Marino env++;
552*629ff9f7SJohn Marino
553*629ff9f7SJohn Marino if (*env == ',')
554*629ff9f7SJohn Marino env++;
555*629ff9f7SJohn Marino else if (*env == '\0')
556*629ff9f7SJohn Marino break;
557*629ff9f7SJohn Marino }
558*629ff9f7SJohn Marino while (1);
559*629ff9f7SJohn Marino
560*629ff9f7SJohn Marino gomp_cpu_affinity = cpus;
561*629ff9f7SJohn Marino gomp_cpu_affinity_len = used;
562*629ff9f7SJohn Marino return true;
563*629ff9f7SJohn Marino
564*629ff9f7SJohn Marino invalid:
565*629ff9f7SJohn Marino gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
566*629ff9f7SJohn Marino return false;
567*629ff9f7SJohn Marino }
568*629ff9f7SJohn Marino
569*629ff9f7SJohn Marino static void __attribute__((constructor))
initialize_env(void)570*629ff9f7SJohn Marino initialize_env (void)
571*629ff9f7SJohn Marino {
572*629ff9f7SJohn Marino unsigned long stacksize;
573*629ff9f7SJohn Marino int wait_policy;
574*629ff9f7SJohn Marino bool bind_var = false;
575*629ff9f7SJohn Marino
576*629ff9f7SJohn Marino /* Do a compile time check that mkomp_h.pl did good job. */
577*629ff9f7SJohn Marino omp_check_defines ();
578*629ff9f7SJohn Marino
579*629ff9f7SJohn Marino parse_schedule ();
580*629ff9f7SJohn Marino parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
581*629ff9f7SJohn Marino parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
582*629ff9f7SJohn Marino parse_boolean ("OMP_PROC_BIND", &bind_var);
583*629ff9f7SJohn Marino parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
584*629ff9f7SJohn Marino true);
585*629ff9f7SJohn Marino parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
586*629ff9f7SJohn Marino if (gomp_thread_limit_var != ULONG_MAX)
587*629ff9f7SJohn Marino gomp_remaining_threads_count = gomp_thread_limit_var - 1;
588*629ff9f7SJohn Marino #ifndef HAVE_SYNC_BUILTINS
589*629ff9f7SJohn Marino gomp_mutex_init (&gomp_remaining_threads_lock);
590*629ff9f7SJohn Marino #endif
591*629ff9f7SJohn Marino gomp_init_num_threads ();
592*629ff9f7SJohn Marino gomp_available_cpus = gomp_global_icv.nthreads_var;
593*629ff9f7SJohn Marino if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
594*629ff9f7SJohn Marino &gomp_global_icv.nthreads_var,
595*629ff9f7SJohn Marino &gomp_nthreads_var_list,
596*629ff9f7SJohn Marino &gomp_nthreads_var_list_len))
597*629ff9f7SJohn Marino gomp_global_icv.nthreads_var = gomp_available_cpus;
598*629ff9f7SJohn Marino if (parse_affinity () || bind_var)
599*629ff9f7SJohn Marino gomp_init_affinity ();
600*629ff9f7SJohn Marino wait_policy = parse_wait_policy ();
601*629ff9f7SJohn Marino if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
602*629ff9f7SJohn Marino {
603*629ff9f7SJohn Marino /* Using a rough estimation of 100000 spins per msec,
604*629ff9f7SJohn Marino use 5 min blocking for OMP_WAIT_POLICY=active,
605*629ff9f7SJohn Marino 3 msec blocking when OMP_WAIT_POLICY is not specificed
606*629ff9f7SJohn Marino and 0 when OMP_WAIT_POLICY=passive.
607*629ff9f7SJohn Marino Depending on the CPU speed, this can be e.g. 5 times longer
608*629ff9f7SJohn Marino or 5 times shorter. */
609*629ff9f7SJohn Marino if (wait_policy > 0)
610*629ff9f7SJohn Marino gomp_spin_count_var = 30000000000LL;
611*629ff9f7SJohn Marino else if (wait_policy < 0)
612*629ff9f7SJohn Marino gomp_spin_count_var = 300000LL;
613*629ff9f7SJohn Marino }
614*629ff9f7SJohn Marino /* gomp_throttled_spin_count_var is used when there are more libgomp
615*629ff9f7SJohn Marino managed threads than available CPUs. Use very short spinning. */
616*629ff9f7SJohn Marino if (wait_policy > 0)
617*629ff9f7SJohn Marino gomp_throttled_spin_count_var = 1000LL;
618*629ff9f7SJohn Marino else if (wait_policy < 0)
619*629ff9f7SJohn Marino gomp_throttled_spin_count_var = 100LL;
620*629ff9f7SJohn Marino if (gomp_throttled_spin_count_var > gomp_spin_count_var)
621*629ff9f7SJohn Marino gomp_throttled_spin_count_var = gomp_spin_count_var;
622*629ff9f7SJohn Marino
623*629ff9f7SJohn Marino /* Not strictly environment related, but ordering constructors is tricky. */
624*629ff9f7SJohn Marino pthread_attr_init (&gomp_thread_attr);
625*629ff9f7SJohn Marino pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
626*629ff9f7SJohn Marino
627*629ff9f7SJohn Marino if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
628*629ff9f7SJohn Marino || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
629*629ff9f7SJohn Marino {
630*629ff9f7SJohn Marino int err;
631*629ff9f7SJohn Marino
632*629ff9f7SJohn Marino err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
633*629ff9f7SJohn Marino
634*629ff9f7SJohn Marino #ifdef PTHREAD_STACK_MIN
635*629ff9f7SJohn Marino if (err == EINVAL)
636*629ff9f7SJohn Marino {
637*629ff9f7SJohn Marino if (stacksize < PTHREAD_STACK_MIN)
638*629ff9f7SJohn Marino gomp_error ("Stack size less than minimum of %luk",
639*629ff9f7SJohn Marino PTHREAD_STACK_MIN / 1024ul
640*629ff9f7SJohn Marino + (PTHREAD_STACK_MIN % 1024 != 0));
641*629ff9f7SJohn Marino else
642*629ff9f7SJohn Marino gomp_error ("Stack size larger than system limit");
643*629ff9f7SJohn Marino }
644*629ff9f7SJohn Marino else
645*629ff9f7SJohn Marino #endif
646*629ff9f7SJohn Marino if (err != 0)
647*629ff9f7SJohn Marino gomp_error ("Stack size change failed: %s", strerror (err));
648*629ff9f7SJohn Marino }
649*629ff9f7SJohn Marino }
650*629ff9f7SJohn Marino
651*629ff9f7SJohn Marino
652*629ff9f7SJohn Marino /* The public OpenMP API routines that access these variables. */
653*629ff9f7SJohn Marino
654*629ff9f7SJohn Marino void
omp_set_num_threads(int n)655*629ff9f7SJohn Marino omp_set_num_threads (int n)
656*629ff9f7SJohn Marino {
657*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (true);
658*629ff9f7SJohn Marino icv->nthreads_var = (n > 0 ? n : 1);
659*629ff9f7SJohn Marino }
660*629ff9f7SJohn Marino
661*629ff9f7SJohn Marino void
omp_set_dynamic(int val)662*629ff9f7SJohn Marino omp_set_dynamic (int val)
663*629ff9f7SJohn Marino {
664*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (true);
665*629ff9f7SJohn Marino icv->dyn_var = val;
666*629ff9f7SJohn Marino }
667*629ff9f7SJohn Marino
668*629ff9f7SJohn Marino int
omp_get_dynamic(void)669*629ff9f7SJohn Marino omp_get_dynamic (void)
670*629ff9f7SJohn Marino {
671*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (false);
672*629ff9f7SJohn Marino return icv->dyn_var;
673*629ff9f7SJohn Marino }
674*629ff9f7SJohn Marino
675*629ff9f7SJohn Marino void
omp_set_nested(int val)676*629ff9f7SJohn Marino omp_set_nested (int val)
677*629ff9f7SJohn Marino {
678*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (true);
679*629ff9f7SJohn Marino icv->nest_var = val;
680*629ff9f7SJohn Marino }
681*629ff9f7SJohn Marino
682*629ff9f7SJohn Marino int
omp_get_nested(void)683*629ff9f7SJohn Marino omp_get_nested (void)
684*629ff9f7SJohn Marino {
685*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (false);
686*629ff9f7SJohn Marino return icv->nest_var;
687*629ff9f7SJohn Marino }
688*629ff9f7SJohn Marino
689*629ff9f7SJohn Marino void
omp_set_schedule(omp_sched_t kind,int modifier)690*629ff9f7SJohn Marino omp_set_schedule (omp_sched_t kind, int modifier)
691*629ff9f7SJohn Marino {
692*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (true);
693*629ff9f7SJohn Marino switch (kind)
694*629ff9f7SJohn Marino {
695*629ff9f7SJohn Marino case omp_sched_static:
696*629ff9f7SJohn Marino if (modifier < 1)
697*629ff9f7SJohn Marino modifier = 0;
698*629ff9f7SJohn Marino icv->run_sched_modifier = modifier;
699*629ff9f7SJohn Marino break;
700*629ff9f7SJohn Marino case omp_sched_dynamic:
701*629ff9f7SJohn Marino case omp_sched_guided:
702*629ff9f7SJohn Marino if (modifier < 1)
703*629ff9f7SJohn Marino modifier = 1;
704*629ff9f7SJohn Marino icv->run_sched_modifier = modifier;
705*629ff9f7SJohn Marino break;
706*629ff9f7SJohn Marino case omp_sched_auto:
707*629ff9f7SJohn Marino break;
708*629ff9f7SJohn Marino default:
709*629ff9f7SJohn Marino return;
710*629ff9f7SJohn Marino }
711*629ff9f7SJohn Marino icv->run_sched_var = kind;
712*629ff9f7SJohn Marino }
713*629ff9f7SJohn Marino
714*629ff9f7SJohn Marino void
omp_get_schedule(omp_sched_t * kind,int * modifier)715*629ff9f7SJohn Marino omp_get_schedule (omp_sched_t *kind, int *modifier)
716*629ff9f7SJohn Marino {
717*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (false);
718*629ff9f7SJohn Marino *kind = icv->run_sched_var;
719*629ff9f7SJohn Marino *modifier = icv->run_sched_modifier;
720*629ff9f7SJohn Marino }
721*629ff9f7SJohn Marino
722*629ff9f7SJohn Marino int
omp_get_max_threads(void)723*629ff9f7SJohn Marino omp_get_max_threads (void)
724*629ff9f7SJohn Marino {
725*629ff9f7SJohn Marino struct gomp_task_icv *icv = gomp_icv (false);
726*629ff9f7SJohn Marino return icv->nthreads_var;
727*629ff9f7SJohn Marino }
728*629ff9f7SJohn Marino
729*629ff9f7SJohn Marino int
omp_get_thread_limit(void)730*629ff9f7SJohn Marino omp_get_thread_limit (void)
731*629ff9f7SJohn Marino {
732*629ff9f7SJohn Marino return gomp_thread_limit_var > INT_MAX ? INT_MAX : gomp_thread_limit_var;
733*629ff9f7SJohn Marino }
734*629ff9f7SJohn Marino
735*629ff9f7SJohn Marino void
omp_set_max_active_levels(int max_levels)736*629ff9f7SJohn Marino omp_set_max_active_levels (int max_levels)
737*629ff9f7SJohn Marino {
738*629ff9f7SJohn Marino if (max_levels >= 0)
739*629ff9f7SJohn Marino gomp_max_active_levels_var = max_levels;
740*629ff9f7SJohn Marino }
741*629ff9f7SJohn Marino
742*629ff9f7SJohn Marino int
omp_get_max_active_levels(void)743*629ff9f7SJohn Marino omp_get_max_active_levels (void)
744*629ff9f7SJohn Marino {
745*629ff9f7SJohn Marino return gomp_max_active_levels_var;
746*629ff9f7SJohn Marino }
747*629ff9f7SJohn Marino
748*629ff9f7SJohn Marino ialias (omp_set_dynamic)
749*629ff9f7SJohn Marino ialias (omp_set_nested)
750*629ff9f7SJohn Marino ialias (omp_set_num_threads)
751*629ff9f7SJohn Marino ialias (omp_get_dynamic)
752*629ff9f7SJohn Marino ialias (omp_get_nested)
753*629ff9f7SJohn Marino ialias (omp_set_schedule)
754*629ff9f7SJohn Marino ialias (omp_get_schedule)
755*629ff9f7SJohn Marino ialias (omp_get_max_threads)
756*629ff9f7SJohn Marino ialias (omp_get_thread_limit)
757*629ff9f7SJohn Marino ialias (omp_set_max_active_levels)
758*629ff9f7SJohn Marino ialias (omp_get_max_active_levels)
759