]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgomp/env.c
libstdc++: Implement ranges::slide_view from P2442R1
[thirdparty/gcc.git] / libgomp / env.c
CommitLineData
7adcbafe 1/* Copyright (C) 2005-2022 Free Software Foundation, Inc.
953ff289
DN
2 Contributed by Richard Henderson <rth@redhat.com>.
3
f1f3453e
TS
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
953ff289
DN
6
7 Libgomp is free software; you can redistribute it and/or modify it
748086b7
JJ
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
953ff289
DN
11
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
748086b7 14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
953ff289
DN
15 more details.
16
748086b7
JJ
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
953ff289 20
748086b7
JJ
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
953ff289 25
630e3c3a
AM
26/* This file defines the OpenMP internal control variables and arranges
27 for them to be initialized from environment variables at startup. */
953ff289 28
22f1a037 29#define _GNU_SOURCE
953ff289 30#include "libgomp.h"
630e3c3a
AM
31#include "gomp-constants.h"
32#include <limits.h>
33#ifndef LIBGOMP_OFFLOADED_ONLY
953ff289 34#include "libgomp_f.h"
41dbbb37 35#include "oacc-int.h"
89b3e3cd 36#include <ctype.h>
953ff289 37#include <stdlib.h>
acf0174b
JJ
38#include <stdio.h>
39#ifdef HAVE_INTTYPES_H
40# include <inttypes.h> /* For PRIu64. */
41#endif
a1b25e49
PG
42#ifdef STRING_WITH_STRINGS
43# include <string.h>
44# include <strings.h>
45#else
46# ifdef HAVE_STRING_H
47# include <string.h>
48# else
49# ifdef HAVE_STRINGS_H
50# include <strings.h>
51# endif
52# endif
53#endif
d0d1b24d 54#include <errno.h>
c4060df4 55#include "thread-stacksize.h"
953ff289 56
976e44e3
JJ
57#ifndef HAVE_STRTOULL
58# define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
59#endif
630e3c3a
AM
60#endif /* LIBGOMP_OFFLOADED_ONLY */
61
22f1a037 62#include "secure_getenv.h"
7d37c7f6 63#include "environ.h"
22f1a037 64
9f2fca56
MV
65/* Default values of ICVs according to the OpenMP standard. */
66const struct gomp_default_icv gomp_default_icv_values = {
630e3c3a
AM
67 .nthreads_var = 1,
68 .thread_limit_var = UINT_MAX,
69 .run_sched_var = GFS_DYNAMIC,
70 .run_sched_chunk_size = 1,
71 .default_device_var = 0,
6fae7eda 72 .max_active_levels_var = 1,
630e3c3a 73 .bind_var = omp_proc_bind_false,
9f2fca56
MV
74 .nteams_var = 0,
75 .teams_thread_limit_var = 0,
76 .dyn_var = false
77};
78
79struct gomp_task_icv gomp_global_icv = {
80 .nthreads_var = gomp_default_icv_values.nthreads_var,
81 .thread_limit_var = gomp_default_icv_values.thread_limit_var,
82 .run_sched_var = gomp_default_icv_values.run_sched_var,
83 .run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size,
84 .default_device_var = gomp_default_icv_values.default_device_var,
85 .dyn_var = gomp_default_icv_values.dyn_var,
86 .max_active_levels_var = gomp_default_icv_values.max_active_levels_var,
87 .bind_var = gomp_default_icv_values.bind_var,
630e3c3a
AM
88 .target_data = NULL
89};
90
9f2fca56
MV
91/* List for initial "_DEV", "_ALL", and "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV,
92 OMP_NUM_TEAMS_ALL, or OMP_NUM_TEAMS_DEV_42. */
93struct gomp_icv_list *gomp_initial_icv_list = NULL;
94
95/* List for "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV_42. This list contains all
96 device-specific ICVs that are copied from host to device and back. */
97struct gomp_offload_icv_list *gomp_offload_icv_list = NULL;
98
630e3c3a 99bool gomp_cancel_var = false;
1bfc07d1
KCY
100enum gomp_target_offload_t gomp_target_offload_var
101 = GOMP_TARGET_OFFLOAD_DEFAULT;
630e3c3a
AM
102int gomp_max_task_priority_var = 0;
103#ifndef HAVE_SYNC_BUILTINS
104gomp_mutex_t gomp_managed_threads_lock;
105#endif
106unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
107unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
108unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
109char *gomp_bind_var_list;
110unsigned long gomp_bind_var_list_len;
111void **gomp_places_list;
112unsigned long gomp_places_list_len;
800bcc8c 113uintptr_t gomp_def_allocator = omp_default_mem_alloc;
630e3c3a
AM
114int gomp_debug_var;
115unsigned int gomp_num_teams_var;
07dd3bcd
JJ
116int gomp_nteams_var;
117int gomp_teams_thread_limit_var;
28567c40
JJ
118bool gomp_display_affinity_var;
119char *gomp_affinity_format_var = "level %L thread %i affinity %A";
120size_t gomp_affinity_format_len;
630e3c3a
AM
121char *goacc_device_type;
122int goacc_device_num;
ec00d3fa 123int goacc_default_dims[GOMP_DIM_MAX];
630e3c3a
AM
124
125#ifndef LIBGOMP_OFFLOADED_ONLY
953ff289 126
7123ae24
UD
127static int wait_policy;
128static unsigned long stacksize = GOMP_DEFAULT_STACKSIZE;
129
953ff289 130static void
9f2fca56 131print_env_var_error (const char *env, const char *val)
953ff289 132{
9f2fca56
MV
133 gomp_error ("Invalid value for environment variable %.*s: %s",
134 (int) (val - env - 1), env, val);
135}
136
137/* Parse the OMP_SCHEDULE environment variable. */
138static bool
139parse_schedule (const char *env, const char *val, void *const params[])
140{
141 enum gomp_schedule_type *schedule = (enum gomp_schedule_type *) params[0];
142 int *chunk_size = (int *) params[1];
143 char *end;
6acf0b38 144 unsigned long value;
28567c40 145 int monotonic = 0;
953ff289 146
9f2fca56
MV
147 if (val == NULL)
148 return false;
953ff289 149
9f2fca56
MV
150 while (isspace ((unsigned char) *val))
151 ++val;
152 if (strncasecmp (val, "monotonic", 9) == 0)
28567c40
JJ
153 {
154 monotonic = 1;
9f2fca56 155 val += 9;
28567c40 156 }
9f2fca56 157 else if (strncasecmp (val, "nonmonotonic", 12) == 0)
28567c40
JJ
158 {
159 monotonic = -1;
9f2fca56 160 val += 12;
28567c40
JJ
161 }
162 if (monotonic)
163 {
9f2fca56
MV
164 while (isspace ((unsigned char) *val))
165 ++val;
166 if (*val != ':')
28567c40 167 goto unknown;
9f2fca56
MV
168 ++val;
169 while (isspace ((unsigned char) *val))
170 ++val;
28567c40 171 }
9f2fca56 172 if (strncasecmp (val, "static", 6) == 0)
953ff289 173 {
9f2fca56
MV
174 *schedule = GFS_STATIC;
175 val += 6;
953ff289 176 }
9f2fca56 177 else if (strncasecmp (val, "dynamic", 7) == 0)
953ff289 178 {
9f2fca56
MV
179 *schedule = GFS_DYNAMIC;
180 val += 7;
953ff289 181 }
9f2fca56 182 else if (strncasecmp (val, "guided", 6) == 0)
953ff289 183 {
9f2fca56
MV
184 *schedule = GFS_GUIDED;
185 val += 6;
953ff289 186 }
9f2fca56 187 else if (strncasecmp (val, "auto", 4) == 0)
a68ab351 188 {
9f2fca56
MV
189 *schedule = GFS_AUTO;
190 val += 4;
a68ab351 191 }
953ff289
DN
192 else
193 goto unknown;
194
28567c40 195 if (monotonic == 1
9f2fca56
MV
196 || (monotonic == 0 && *schedule == GFS_STATIC))
197 *schedule |= GFS_MONOTONIC;
28567c40 198
9f2fca56
MV
199 while (isspace ((unsigned char) *val))
200 ++val;
201 if (*val == '\0')
fb79f500 202 {
9f2fca56
MV
203 *chunk_size = (*schedule & ~GFS_MONOTONIC) != GFS_STATIC;
204 return true;
fb79f500 205 }
9f2fca56 206 if (*val++ != ',')
953ff289 207 goto unknown;
9f2fca56
MV
208 while (isspace ((unsigned char) *val))
209 ++val;
210 if (*val == '\0')
953ff289
DN
211 goto invalid;
212
6acf0b38 213 errno = 0;
9f2fca56
MV
214 value = strtoul (val, &end, 10);
215 if (errno || end == val)
6acf0b38
UB
216 goto invalid;
217
89b3e3cd
JJ
218 while (isspace ((unsigned char) *end))
219 ++end;
953ff289
DN
220 if (*end != '\0')
221 goto invalid;
6acf0b38 222
a68ab351
JJ
223 if ((int)value != value)
224 goto invalid;
225
9f2fca56 226 if (value == 0 && (*schedule & ~GFS_MONOTONIC) != GFS_STATIC)
fb79f500 227 value = 1;
9f2fca56
MV
228 *chunk_size = value;
229 return true;
953ff289
DN
230
231 unknown:
9f2fca56
MV
232 print_env_var_error (env, val);
233 return false;
953ff289
DN
234
235 invalid:
9f2fca56
MV
236 char name[val - env];
237 memcpy (name, env, val - env - 1);
238 name[val - env - 1] = '\0';
953ff289 239 gomp_error ("Invalid value for chunk size in "
9f2fca56
MV
240 "environment variable %s: %s", name, val);
241 return false;
953ff289
DN
242}
243
a68ab351 244/* Parse an unsigned long environment variable. Return true if one was
22f1a037
TV
245 present and it was successfully parsed. If SECURE, use secure_getenv to the
246 environment variable. */
953ff289
DN
247
248static bool
9f2fca56
MV
249parse_unsigned_long_1 (const char *env, const char *val, unsigned long *pvalue,
250 bool allow_zero)
953ff289 251{
9f2fca56 252 char *end;
d0d1b24d 253 unsigned long value;
953ff289 254
9f2fca56 255 if (val == NULL)
953ff289
DN
256 return false;
257
9f2fca56
MV
258 while (isspace ((unsigned char) *val))
259 ++val;
260 if (*val == '\0')
953ff289
DN
261 goto invalid;
262
6acf0b38 263 errno = 0;
9f2fca56
MV
264 value = strtoul (val, &end, 10);
265 if (errno || end == val || (long) value <= 0 - allow_zero)
6acf0b38
UB
266 goto invalid;
267
89b3e3cd
JJ
268 while (isspace ((unsigned char) *end))
269 ++end;
953ff289
DN
270 if (*end != '\0')
271 goto invalid;
d0d1b24d
RH
272
273 *pvalue = value;
953ff289
DN
274 return true;
275
276 invalid:
9f2fca56 277 print_env_var_error (env, val);
953ff289
DN
278 return false;
279}
280
22f1a037
TV
281/* As parse_unsigned_long_1, but always use getenv. */
282
283static bool
9f2fca56 284parse_unsigned_long (const char *env, const char *val, void *const params[])
22f1a037 285{
9f2fca56
MV
286 unsigned upper = (unsigned long) params[2];
287 unsigned long pvalue = 0;
288 bool ret = parse_unsigned_long_1 (env, val, &pvalue, (bool) params[1]);
289 if (!ret)
290 return false;
291
292 if (upper == 0)
293 *(unsigned long *) params[0] = pvalue;
294 else
295 {
296 if (pvalue > upper)
297 pvalue = upper;
298 if (upper <= UCHAR_MAX)
299 *(unsigned char *) params[0] = pvalue;
300 else if (upper <= UINT_MAX)
301 *(unsigned int *) params[0] = pvalue;
302 else
303 *(unsigned long *) params[0] = pvalue;
304 }
305
306 return ret;
22f1a037
TV
307}
308
acf0174b 309/* Parse a positive int environment variable. Return true if one was
22f1a037
TV
310 present and it was successfully parsed. If SECURE, use secure_getenv to the
311 environment variable. */
acf0174b
JJ
312
313static bool
9f2fca56 314parse_int_1 (const char *env, const char *val, int *pvalue, bool allow_zero)
acf0174b
JJ
315{
316 unsigned long value;
9f2fca56 317 if (!parse_unsigned_long_1 (env, val, &value, allow_zero))
acf0174b
JJ
318 return false;
319 if (value > INT_MAX)
320 {
9f2fca56 321 print_env_var_error (env, val);
acf0174b
JJ
322 return false;
323 }
324 *pvalue = (int) value;
325 return true;
326}
327
22f1a037 328static bool
9f2fca56 329parse_int (const char *env, const char *val, void *const params[])
22f1a037 330{
9f2fca56 331 return parse_int_1 (env, val, (int *) params[0], (bool) params[1]);
22f1a037
TV
332}
333
334/* As parse_int_1, but use getenv_secure. */
335
336static bool
9f2fca56 337parse_int_secure (const char *env, int *pvalue, bool allow_zero)
22f1a037 338{
9f2fca56 339 return parse_int_1 (env, secure_getenv (env), pvalue, allow_zero);
22f1a037
TV
340}
341
20906c66
JJ
342/* Parse an unsigned long list environment variable. Return true if one was
343 present and it was successfully parsed. */
344
345static bool
9f2fca56
MV
346parse_unsigned_long_list (const char *env, const char *val,
347 void *const params[])
20906c66 348{
9f2fca56
MV
349 unsigned long *p1stvalue = (unsigned long *) params[0];
350 unsigned long **pvalues = (unsigned long **) params[1];
351 unsigned long *pnvalues = (unsigned long *) params[2];
352 char *end;
20906c66
JJ
353 unsigned long value, *values = NULL;
354
9f2fca56 355 if (val == NULL)
20906c66
JJ
356 return false;
357
9f2fca56
MV
358 while (isspace ((unsigned char) *val))
359 ++val;
360 if (*val == '\0')
20906c66
JJ
361 goto invalid;
362
363 errno = 0;
9f2fca56 364 value = strtoul (val, &end, 10);
20906c66
JJ
365 if (errno || (long) value <= 0)
366 goto invalid;
367
368 while (isspace ((unsigned char) *end))
369 ++end;
370 if (*end != '\0')
371 {
372 if (*end == ',')
373 {
374 unsigned long nvalues = 0, nalloced = 0;
375
376 do
377 {
9f2fca56 378 val = end + 1;
20906c66
JJ
379 if (nvalues == nalloced)
380 {
381 unsigned long *n;
382 nalloced = nalloced ? nalloced * 2 : 16;
383 n = realloc (values, nalloced * sizeof (unsigned long));
384 if (n == NULL)
385 {
386 free (values);
9f2fca56
MV
387 char name[val - env];
388 memcpy (name, env, val - env - 1);
389 name[val - env - 1] = '\0';
20906c66
JJ
390 gomp_error ("Out of memory while trying to parse"
391 " environment variable %s", name);
392 return false;
393 }
394 values = n;
395 if (nvalues == 0)
396 values[nvalues++] = value;
397 }
398
9f2fca56
MV
399 while (isspace ((unsigned char) *val))
400 ++val;
401 if (*val == '\0')
20906c66
JJ
402 goto invalid;
403
404 errno = 0;
9f2fca56 405 value = strtoul (val, &end, 10);
20906c66
JJ
406 if (errno || (long) value <= 0)
407 goto invalid;
408
409 values[nvalues++] = value;
410 while (isspace ((unsigned char) *end))
411 ++end;
412 if (*end == '\0')
413 break;
414 if (*end != ',')
415 goto invalid;
416 }
417 while (1);
418 *p1stvalue = values[0];
419 *pvalues = values;
420 *pnvalues = nvalues;
421 return true;
422 }
423 goto invalid;
424 }
9f2fca56
MV
425 else
426 {
427 *pnvalues = 0;
428 *pvalues = NULL;
429 }
20906c66
JJ
430
431 *p1stvalue = value;
432 return true;
433
434 invalid:
435 free (values);
9f2fca56 436 print_env_var_error (env, val);
20906c66
JJ
437 return false;
438}
439
9f2fca56
MV
440static bool
441parse_target_offload (const char *env, const char *val, void *const params[])
1bfc07d1 442{
121a8812 443 int new_offload = -1;
1bfc07d1 444
9f2fca56
MV
445 if (val == NULL)
446 return false;
1bfc07d1 447
9f2fca56
MV
448 while (isspace ((unsigned char) *val))
449 ++val;
450 if (strncasecmp (val, "default", 7) == 0)
1bfc07d1 451 {
9f2fca56 452 val += 7;
1bfc07d1
KCY
453 new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
454 }
9f2fca56 455 else if (strncasecmp (val, "mandatory", 9) == 0)
1bfc07d1 456 {
9f2fca56 457 val += 9;
1bfc07d1
KCY
458 new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
459 }
9f2fca56 460 else if (strncasecmp (val, "disabled", 8) == 0)
1bfc07d1 461 {
9f2fca56 462 val += 8;
1bfc07d1
KCY
463 new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
464 }
9f2fca56
MV
465 while (isspace ((unsigned char) *val))
466 ++val;
467 if (new_offload != -1 && *val == '\0')
1bfc07d1 468 {
9f2fca56
MV
469 *(enum gomp_target_offload_t *) params[0] = new_offload;
470 return true;
1bfc07d1
KCY
471 }
472
9f2fca56
MV
473 print_env_var_error (env, val);
474 return false;
1bfc07d1
KCY
475}
476
acf0174b
JJ
477/* Parse environment variable set to a boolean or list of omp_proc_bind_t
478 enum values. Return true if one was present and it was successfully
479 parsed. */
480
481static bool
9f2fca56 482parse_bind_var (const char *env, const char *val, void *const params[])
acf0174b 483{
9f2fca56
MV
484 char *p1stvalue = (char *) params[0];
485 char **pvalues = (char **) params[1];
486 unsigned long *pnvalues = (unsigned long *) params[2];
c8673881 487 char value = omp_proc_bind_false, *values = NULL;
acf0174b
JJ
488 int i;
489 static struct proc_bind_kinds
490 {
491 const char name[7];
492 const char len;
493 omp_proc_bind_t kind;
494 } kinds[] =
495 {
496 { "false", 5, omp_proc_bind_false },
497 { "true", 4, omp_proc_bind_true },
498 { "master", 6, omp_proc_bind_master },
432de084 499 { "primary", 7, omp_proc_bind_primary },
acf0174b
JJ
500 { "close", 5, omp_proc_bind_close },
501 { "spread", 6, omp_proc_bind_spread }
502 };
503
9f2fca56 504 if (val == NULL)
acf0174b
JJ
505 return false;
506
9f2fca56
MV
507 while (isspace ((unsigned char) *val))
508 ++val;
509 if (*val == '\0')
acf0174b
JJ
510 goto invalid;
511
432de084 512 for (i = 0; i < 6; i++)
9f2fca56 513 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
acf0174b
JJ
514 {
515 value = kinds[i].kind;
9f2fca56 516 val += kinds[i].len;
acf0174b
JJ
517 break;
518 }
432de084 519 if (i == 6)
acf0174b
JJ
520 goto invalid;
521
9f2fca56
MV
522 while (isspace ((unsigned char) *val))
523 ++val;
524 if (*val != '\0')
acf0174b 525 {
9f2fca56 526 if (*val == ',')
acf0174b
JJ
527 {
528 unsigned long nvalues = 0, nalloced = 0;
529
530 if (value == omp_proc_bind_false
531 || value == omp_proc_bind_true)
532 goto invalid;
533
534 do
535 {
9f2fca56 536 val++;
acf0174b
JJ
537 if (nvalues == nalloced)
538 {
539 char *n;
540 nalloced = nalloced ? nalloced * 2 : 16;
541 n = realloc (values, nalloced);
542 if (n == NULL)
543 {
544 free (values);
9f2fca56
MV
545 char name[val - env];
546 memcpy (name, env, val - env - 1);
547 name[val - env - 1] = '\0';
acf0174b
JJ
548 gomp_error ("Out of memory while trying to parse"
549 " environment variable %s", name);
550 return false;
551 }
552 values = n;
553 if (nvalues == 0)
554 values[nvalues++] = value;
555 }
556
9f2fca56
MV
557 while (isspace ((unsigned char) *val))
558 ++val;
559 if (*val == '\0')
acf0174b
JJ
560 goto invalid;
561
432de084 562 for (i = 2; i < 6; i++)
9f2fca56 563 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
acf0174b
JJ
564 {
565 value = kinds[i].kind;
9f2fca56 566 val += kinds[i].len;
acf0174b
JJ
567 break;
568 }
432de084 569 if (i == 6)
acf0174b
JJ
570 goto invalid;
571
572 values[nvalues++] = value;
9f2fca56
MV
573 while (isspace ((unsigned char) *val))
574 ++val;
575 if (*val == '\0')
acf0174b 576 break;
9f2fca56 577 if (*val != ',')
acf0174b
JJ
578 goto invalid;
579 }
580 while (1);
581 *p1stvalue = values[0];
582 *pvalues = values;
583 *pnvalues = nvalues;
584 return true;
585 }
586 goto invalid;
587 }
588
589 *p1stvalue = value;
590 return true;
591
592 invalid:
593 free (values);
9f2fca56 594 print_env_var_error (env, val);
acf0174b
JJ
595 return false;
596}
597
598static bool
599parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
600 long *stridep)
601{
602 char *env = *envp, *start;
603 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
604 unsigned long len = 1;
605 long stride = 1;
606 int pass;
607 bool any_negate = false;
4a0fed0c 608 bool has_braces = true;
acf0174b
JJ
609 *negatep = false;
610 while (isspace ((unsigned char) *env))
611 ++env;
612 if (*env == '!')
613 {
614 *negatep = true;
615 ++env;
616 while (isspace ((unsigned char) *env))
617 ++env;
618 }
619 if (*env != '{')
4a0fed0c
JJ
620 {
621 char *end;
622 unsigned long this_num;
623
624 errno = 0;
625 this_num = strtoul (env, &end, 10);
626 if (errno || end == env)
627 return false;
628 env = end - 1;
629 has_braces = false;
630 if (gomp_places_list
631 && !gomp_affinity_add_cpus (p, this_num, 1, 1, false))
632 return false;
633 }
634 else
635 {
636 ++env;
637 while (isspace ((unsigned char) *env))
638 ++env;
639 }
acf0174b 640 start = env;
4a0fed0c 641 for (pass = 0; pass < (any_negate ? 2 : has_braces); pass++)
acf0174b
JJ
642 {
643 env = start;
644 do
645 {
646 unsigned long this_num, this_len = 1;
647 long this_stride = 1;
648 bool this_negate = (*env == '!');
c057ed9c 649 char *end;
acf0174b
JJ
650 if (this_negate)
651 {
652 if (gomp_places_list)
653 any_negate = true;
654 ++env;
655 while (isspace ((unsigned char) *env))
656 ++env;
657 }
658
659 errno = 0;
c057ed9c
JJ
660 this_num = strtoul (env, &end, 10);
661 if (errno || end == env)
acf0174b 662 return false;
c057ed9c 663 env = end;
acf0174b
JJ
664 while (isspace ((unsigned char) *env))
665 ++env;
666 if (*env == ':')
667 {
668 ++env;
4a0fed0c
JJ
669 if (this_negate)
670 return false;
acf0174b
JJ
671 while (isspace ((unsigned char) *env))
672 ++env;
673 errno = 0;
674 this_len = strtoul (env, &env, 10);
675 if (errno || this_len == 0)
676 return false;
677 while (isspace ((unsigned char) *env))
678 ++env;
679 if (*env == ':')
680 {
681 ++env;
682 while (isspace ((unsigned char) *env))
683 ++env;
684 errno = 0;
c057ed9c
JJ
685 this_stride = strtol (env, &end, 10);
686 if (errno || end == env)
acf0174b 687 return false;
c057ed9c 688 env = end;
acf0174b
JJ
689 while (isspace ((unsigned char) *env))
690 ++env;
691 }
692 }
acf0174b
JJ
693 if (gomp_places_list && pass == this_negate)
694 {
695 if (this_negate)
696 {
697 if (!gomp_affinity_remove_cpu (p, this_num))
698 return false;
699 }
700 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
701 this_stride, false))
702 return false;
703 }
704 if (*env == '}')
705 break;
706 if (*env != ',')
707 return false;
708 ++env;
709 }
710 while (1);
711 }
712
713 ++env;
714 while (isspace ((unsigned char) *env))
715 ++env;
716 if (*env == ':')
717 {
c057ed9c 718 char *end;
4a0fed0c
JJ
719 if (*negatep)
720 return false;
acf0174b
JJ
721 ++env;
722 while (isspace ((unsigned char) *env))
723 ++env;
724 errno = 0;
725 len = strtoul (env, &env, 10);
726 if (errno || len == 0 || len >= 65536)
727 return false;
728 while (isspace ((unsigned char) *env))
729 ++env;
730 if (*env == ':')
731 {
732 ++env;
733 while (isspace ((unsigned char) *env))
734 ++env;
735 errno = 0;
c057ed9c
JJ
736 stride = strtol (env, &end, 10);
737 if (errno || end == env)
acf0174b 738 return false;
c057ed9c 739 env = end;
acf0174b
JJ
740 while (isspace ((unsigned char) *env))
741 ++env;
742 }
743 }
acf0174b
JJ
744 *envp = env;
745 *lenp = len;
746 *stridep = stride;
747 return true;
748}
749
750static bool
f89163fd 751parse_places_var (const char *name, bool ignore)
acf0174b
JJ
752{
753 char *env = getenv (name), *end;
754 bool any_negate = false;
755 int level = 0;
756 unsigned long count = 0;
757 if (env == NULL)
758 return false;
759
760 while (isspace ((unsigned char) *env))
761 ++env;
762 if (*env == '\0')
763 goto invalid;
764
765 if (strncasecmp (env, "threads", 7) == 0)
766 {
767 env += 7;
768 level = 1;
769 }
770 else if (strncasecmp (env, "cores", 5) == 0)
771 {
772 env += 5;
773 level = 2;
774 }
775 else if (strncasecmp (env, "sockets", 7) == 0)
776 {
777 env += 7;
778 level = 3;
779 }
5809be05
JJ
780 else if (strncasecmp (env, "ll_caches", 9) == 0)
781 {
782 env += 9;
783 level = 4;
784 }
e7ce32c7
JJ
785 else if (strncasecmp (env, "numa_domains", 12) == 0)
786 {
787 env += 12;
788 level = 5;
789 }
acf0174b
JJ
790 if (level)
791 {
792 count = ULONG_MAX;
793 while (isspace ((unsigned char) *env))
794 ++env;
795 if (*env != '\0')
796 {
797 if (*env++ != '(')
798 goto invalid;
799 while (isspace ((unsigned char) *env))
800 ++env;
801
802 errno = 0;
803 count = strtoul (env, &end, 10);
c057ed9c 804 if (errno || end == env)
acf0174b
JJ
805 goto invalid;
806 env = end;
807 while (isspace ((unsigned char) *env))
808 ++env;
809 if (*env != ')')
810 goto invalid;
811 ++env;
812 while (isspace ((unsigned char) *env))
813 ++env;
814 if (*env != '\0')
815 goto invalid;
816 }
f89163fd
JJ
817
818 if (ignore)
819 return false;
820
acf0174b
JJ
821 return gomp_affinity_init_level (level, count, false);
822 }
823
824 count = 0;
825 end = env;
826 do
827 {
828 bool negate;
829 unsigned long len;
830 long stride;
831 if (!parse_one_place (&end, &negate, &len, &stride))
832 goto invalid;
833 if (negate)
834 {
835 if (!any_negate)
836 count++;
837 any_negate = true;
838 }
839 else
840 count += len;
841 if (count > 65536)
842 goto invalid;
843 if (*end == '\0')
844 break;
845 if (*end != ',')
846 goto invalid;
847 end++;
848 }
849 while (1);
850
f89163fd 851 if (ignore)
acf0174b
JJ
852 return false;
853
854 gomp_places_list_len = 0;
855 gomp_places_list = gomp_affinity_alloc (count, false);
856 if (gomp_places_list == NULL)
857 return false;
858
859 do
860 {
861 bool negate;
862 unsigned long len;
863 long stride;
864 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
865 if (!parse_one_place (&env, &negate, &len, &stride))
866 goto invalid;
867 if (negate)
868 {
869 void *p;
870 for (count = 0; count < gomp_places_list_len; count++)
871 if (gomp_affinity_same_place
872 (gomp_places_list[count],
873 gomp_places_list[gomp_places_list_len]))
874 break;
875 if (count == gomp_places_list_len)
876 {
877 gomp_error ("Trying to remove a non-existing place from list "
878 "of places");
879 goto invalid;
880 }
881 p = gomp_places_list[count];
882 memmove (&gomp_places_list[count],
883 &gomp_places_list[count + 1],
884 (gomp_places_list_len - count - 1) * sizeof (void *));
885 --gomp_places_list_len;
886 gomp_places_list[gomp_places_list_len] = p;
887 }
888 else if (len == 1)
889 ++gomp_places_list_len;
890 else
891 {
892 for (count = 0; count < len - 1; count++)
893 if (!gomp_affinity_copy_place
894 (gomp_places_list[gomp_places_list_len + count + 1],
895 gomp_places_list[gomp_places_list_len + count],
896 stride))
897 goto invalid;
898 gomp_places_list_len += len;
899 }
900 if (*env == '\0')
901 break;
902 env++;
903 }
904 while (1);
905
906 if (gomp_places_list_len == 0)
907 {
908 gomp_error ("All places have been removed");
909 goto invalid;
910 }
911 if (!gomp_affinity_finalize_place_list (false))
912 goto invalid;
913 return true;
914
915 invalid:
916 free (gomp_places_list);
917 gomp_places_list = NULL;
918 gomp_places_list_len = 0;
919 gomp_error ("Invalid value for environment variable %s", name);
920 return false;
921}
922
a68ab351
JJ
923/* Parse the OMP_STACKSIZE environment varible. Return true if one was
924 present and it was successfully parsed. */
925
926static bool
9f2fca56 927parse_stacksize (const char *env, const char *val, void *const params[])
a68ab351 928{
9f2fca56 929 char *end;
a68ab351
JJ
930 unsigned long value, shift = 10;
931
9f2fca56 932 if (val == NULL)
a68ab351
JJ
933 return false;
934
9f2fca56
MV
935 while (isspace ((unsigned char) *val))
936 ++val;
937 if (*val == '\0')
a68ab351
JJ
938 goto invalid;
939
940 errno = 0;
9f2fca56
MV
941 value = strtoul (val, &end, 10);
942 if (errno || end == val)
a68ab351
JJ
943 goto invalid;
944
945 while (isspace ((unsigned char) *end))
946 ++end;
947 if (*end != '\0')
948 {
323ff903 949 switch (tolower ((unsigned char) *end))
a68ab351
JJ
950 {
951 case 'b':
952 shift = 0;
953 break;
954 case 'k':
955 break;
956 case 'm':
957 shift = 20;
958 break;
959 case 'g':
960 shift = 30;
961 break;
962 default:
963 goto invalid;
964 }
965 ++end;
966 while (isspace ((unsigned char) *end))
967 ++end;
968 if (*end != '\0')
969 goto invalid;
970 }
971
972 if (((value << shift) >> shift) != value)
973 goto invalid;
974
9f2fca56 975 *(unsigned long *) params[0] = value << shift;
a68ab351
JJ
976 return true;
977
978 invalid:
9f2fca56 979 print_env_var_error (env, val);
a68ab351
JJ
980 return false;
981}
982
983/* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
984 present and it was successfully parsed. */
985
986static bool
987parse_spincount (const char *name, unsigned long long *pvalue)
988{
989 char *env, *end;
990 unsigned long long value, mult = 1;
991
992 env = getenv (name);
993 if (env == NULL)
994 return false;
995
996 while (isspace ((unsigned char) *env))
997 ++env;
998 if (*env == '\0')
999 goto invalid;
1000
1001 if (strncasecmp (env, "infinite", 8) == 0
1002 || strncasecmp (env, "infinity", 8) == 0)
1003 {
1004 value = ~0ULL;
1005 end = env + 8;
1006 goto check_tail;
1007 }
1008
1009 errno = 0;
1010 value = strtoull (env, &end, 10);
c057ed9c 1011 if (errno || end == env)
a68ab351
JJ
1012 goto invalid;
1013
1014 while (isspace ((unsigned char) *end))
1015 ++end;
1016 if (*end != '\0')
1017 {
323ff903 1018 switch (tolower ((unsigned char) *end))
a68ab351
JJ
1019 {
1020 case 'k':
1021 mult = 1000LL;
1022 break;
1023 case 'm':
1024 mult = 1000LL * 1000LL;
1025 break;
1026 case 'g':
1027 mult = 1000LL * 1000LL * 1000LL;
1028 break;
1029 case 't':
1030 mult = 1000LL * 1000LL * 1000LL * 1000LL;
1031 break;
1032 default:
1033 goto invalid;
1034 }
1035 ++end;
1036 check_tail:
1037 while (isspace ((unsigned char) *end))
1038 ++end;
1039 if (*end != '\0')
1040 goto invalid;
1041 }
1042
1043 if (value > ~0ULL / mult)
1044 value = ~0ULL;
1045 else
1046 value *= mult;
1047
1048 *pvalue = value;
1049 return true;
1050
1051 invalid:
1052 gomp_error ("Invalid value for environment variable %s", name);
1053 return false;
1054}
1055
1056/* Parse a boolean value for environment variable NAME and store the
6fae7eda
KCY
1057 result in VALUE. Return true if one was present and it was
1058 successfully parsed. */
6fae7eda 1059static bool
9f2fca56 1060parse_boolean (const char *env, const char *val, void *const params[])
953ff289 1061{
9f2fca56 1062 bool *value = (bool *) params[0];
953ff289 1063
9f2fca56 1064 if (val == NULL)
6fae7eda 1065 return false;
953ff289 1066
9f2fca56
MV
1067 while (isspace ((unsigned char) *val))
1068 ++val;
1069 if (strncasecmp (val, "true", 4) == 0)
89b3e3cd
JJ
1070 {
1071 *value = true;
9f2fca56 1072 val += 4;
89b3e3cd 1073 }
9f2fca56 1074 else if (strncasecmp (val, "false", 5) == 0)
89b3e3cd
JJ
1075 {
1076 *value = false;
9f2fca56 1077 val += 5;
89b3e3cd 1078 }
953ff289 1079 else
9f2fca56
MV
1080 val = "X";
1081 while (isspace ((unsigned char) *val))
1082 ++val;
1083 if (*val != '\0')
6fae7eda 1084 {
9f2fca56 1085 print_env_var_error (env, val);
6fae7eda
KCY
1086 return false;
1087 }
1088 return true;
953ff289
DN
1089}
1090
800bcc8c 1091/* Parse the OMP_WAIT_POLICY environment variable and return the value. */
a68ab351 1092
9f2fca56
MV
1093static bool
1094parse_wait_policy (const char *env, const char *val, void *const params[])
a68ab351 1095{
9f2fca56 1096 int *pvalue = (int *) params[0];
a68ab351
JJ
1097 int ret = -1;
1098
9f2fca56
MV
1099 if (val == NULL)
1100 {
1101 *pvalue = -1;
1102 return false;
1103 }
a68ab351 1104
9f2fca56
MV
1105 while (isspace ((unsigned char) *val))
1106 ++val;
1107 if (strncasecmp (val, "active", 6) == 0)
a68ab351
JJ
1108 {
1109 ret = 1;
9f2fca56 1110 val += 6;
a68ab351 1111 }
9f2fca56 1112 else if (strncasecmp (val, "passive", 7) == 0)
a68ab351
JJ
1113 {
1114 ret = 0;
9f2fca56 1115 val += 7;
a68ab351
JJ
1116 }
1117 else
9f2fca56
MV
1118 val = "X";
1119 while (isspace ((unsigned char) *val))
1120 ++val;
1121 if (*val == '\0')
1122 {
1123 *pvalue = ret;
1124 return true;
1125 }
1126 print_env_var_error (env, val);
1127 *pvalue = -1;
1128 return false;
a68ab351
JJ
1129}
1130
a0884cf0
JJ
1131/* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1132 present and it was successfully parsed. */
1133
1134static bool
f89163fd 1135parse_affinity (bool ignore)
a0884cf0 1136{
acf0174b
JJ
1137 char *env, *end, *start;
1138 int pass;
a0884cf0 1139 unsigned long cpu_beg, cpu_end, cpu_stride;
acf0174b 1140 size_t count = 0, needed;
a0884cf0
JJ
1141
1142 env = getenv ("GOMP_CPU_AFFINITY");
1143 if (env == NULL)
1144 return false;
1145
acf0174b
JJ
1146 start = env;
1147 for (pass = 0; pass < 2; pass++)
a0884cf0 1148 {
acf0174b
JJ
1149 env = start;
1150 if (pass == 1)
a0884cf0 1151 {
f89163fd
JJ
1152 if (ignore)
1153 return false;
1154
acf0174b
JJ
1155 gomp_places_list_len = 0;
1156 gomp_places_list = gomp_affinity_alloc (count, true);
1157 if (gomp_places_list == NULL)
1158 return false;
1159 }
1160 do
1161 {
1162 while (isspace ((unsigned char) *env))
1163 ++env;
1164
1165 errno = 0;
1166 cpu_beg = strtoul (env, &end, 0);
c057ed9c 1167 if (errno || end == env || cpu_beg >= 65536)
a0884cf0 1168 goto invalid;
acf0174b
JJ
1169 cpu_end = cpu_beg;
1170 cpu_stride = 1;
a0884cf0
JJ
1171
1172 env = end;
acf0174b 1173 if (*env == '-')
a0884cf0 1174 {
acf0174b
JJ
1175 errno = 0;
1176 cpu_end = strtoul (++env, &end, 0);
c057ed9c 1177 if (errno || end == env || cpu_end >= 65536 || cpu_end < cpu_beg)
a0884cf0
JJ
1178 goto invalid;
1179
1180 env = end;
acf0174b
JJ
1181 if (*env == ':')
1182 {
1183 errno = 0;
1184 cpu_stride = strtoul (++env, &end, 0);
1185 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1186 goto invalid;
a0884cf0 1187
acf0174b
JJ
1188 env = end;
1189 }
1190 }
a0884cf0 1191
acf0174b
JJ
1192 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1193 if (pass == 0)
1194 count += needed;
a0884cf0 1195 else
a0884cf0 1196 {
acf0174b
JJ
1197 while (needed--)
1198 {
1199 void *p = gomp_places_list[gomp_places_list_len];
1200 gomp_affinity_init_place (p);
1201 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1202 ++gomp_places_list_len;
1203 cpu_beg += cpu_stride;
1204 }
a0884cf0
JJ
1205 }
1206
acf0174b
JJ
1207 while (isspace ((unsigned char) *env))
1208 ++env;
a0884cf0 1209
acf0174b
JJ
1210 if (*env == ',')
1211 env++;
1212 else if (*env == '\0')
1213 break;
a0884cf0 1214 }
acf0174b 1215 while (1);
a0884cf0 1216 }
a0884cf0 1217
acf0174b
JJ
1218 if (gomp_places_list_len == 0)
1219 {
1220 free (gomp_places_list);
1221 gomp_places_list = NULL;
f89163fd 1222 return false;
acf0174b 1223 }
a0884cf0
JJ
1224 return true;
1225
1226 invalid:
1227 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1228 return false;
1229}
1230
800bcc8c 1231/* Parse the OMP_ALLOCATOR environment variable and return the value. */
9f2fca56
MV
1232static bool
1233parse_allocator (const char *env, const char *val, void *const params[])
800bcc8c 1234{
9f2fca56
MV
1235 uintptr_t *ret = (uintptr_t *) params[0];
1236 *ret = omp_default_mem_alloc;
800bcc8c 1237
9f2fca56
MV
1238 if (val == NULL)
1239 return false;
800bcc8c 1240
9f2fca56
MV
1241 while (isspace ((unsigned char) *val))
1242 ++val;
800bcc8c
JJ
1243 if (0)
1244 ;
1245#define C(v) \
9f2fca56 1246 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
800bcc8c 1247 { \
9f2fca56
MV
1248 *ret = v; \
1249 val += sizeof (#v) - 1; \
800bcc8c
JJ
1250 }
1251 C (omp_default_mem_alloc)
1252 C (omp_large_cap_mem_alloc)
1253 C (omp_const_mem_alloc)
1254 C (omp_high_bw_mem_alloc)
1255 C (omp_low_lat_mem_alloc)
1256 C (omp_cgroup_mem_alloc)
1257 C (omp_pteam_mem_alloc)
1258 C (omp_thread_mem_alloc)
1259#undef C
1260 else
9f2fca56
MV
1261 val = "X";
1262 while (isspace ((unsigned char) *val))
1263 ++val;
1264 if (*val == '\0')
1265 return true;
1266 print_env_var_error (env, val);
1267 *ret = omp_default_mem_alloc;
1268 return false;
800bcc8c
JJ
1269}
1270
41dbbb37
TS
1271static void
1272parse_acc_device_type (void)
1273{
1274 const char *env = getenv ("ACC_DEVICE_TYPE");
1275
1276 if (env && *env != '\0')
1277 goacc_device_type = strdup (env);
1278 else
1279 goacc_device_type = NULL;
1280}
acf0174b 1281
ec00d3fa
TV
1282static void
1283parse_gomp_openacc_dim (void)
1284{
1285 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1286 const char *var_name = "GOMP_OPENACC_DIM";
1287 const char *env_var = getenv (var_name);
c057ed9c
JJ
1288 const char *pos = env_var;
1289 int i;
1290
ec00d3fa
TV
1291 if (!env_var)
1292 return;
1293
ec00d3fa
TV
1294 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1295 {
c057ed9c
JJ
1296 char *eptr;
1297 long val;
1298
ec00d3fa
TV
1299 if (i && *pos++ != ':')
1300 break;
1301
1302 if (*pos == ':')
1303 continue;
1304
ec00d3fa 1305 errno = 0;
c057ed9c 1306 val = strtol (pos, &eptr, 10);
00c9ce13 1307 if (errno || eptr == pos || val < 0 || (unsigned)val != val)
ec00d3fa
TV
1308 break;
1309
1310 goacc_default_dims[i] = (int)val;
c057ed9c 1311 pos = (const char *) eptr;
ec00d3fa
TV
1312 }
1313}
1314
9f2fca56
MV
1315/* Helper function for omp_display_env which prints the values of run_sched_var.
1316 'device' can be 'host', 'dev', 'all' or a particular device number. */
acf0174b 1317
9f2fca56
MV
1318static void
1319print_schedule (enum gomp_schedule_type run_sched_var, int run_sched_chunk_size,
1320 const char *device)
1321{
1322 fprintf (stderr, " [%s] OMP_SCHEDULE = '", device);
1323 if ((run_sched_var & GFS_MONOTONIC))
28567c40 1324 {
9f2fca56 1325 if (run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
28567c40
JJ
1326 fputs ("MONOTONIC:", stderr);
1327 }
9f2fca56 1328 else if (run_sched_var == GFS_STATIC)
28567c40 1329 fputs ("NONMONOTONIC:", stderr);
9f2fca56 1330 switch (run_sched_var & ~GFS_MONOTONIC)
acf0174b
JJ
1331 {
1332 case GFS_RUNTIME:
1333 fputs ("RUNTIME", stderr);
9f2fca56
MV
1334 if (run_sched_chunk_size != 1)
1335 fprintf (stderr, ",%d", run_sched_chunk_size);
acf0174b
JJ
1336 break;
1337 case GFS_STATIC:
1338 fputs ("STATIC", stderr);
9f2fca56
MV
1339 if (run_sched_chunk_size != 0)
1340 fprintf (stderr, ",%d", run_sched_chunk_size);
acf0174b
JJ
1341 break;
1342 case GFS_DYNAMIC:
1343 fputs ("DYNAMIC", stderr);
9f2fca56
MV
1344 if (run_sched_chunk_size != 1)
1345 fprintf (stderr, ",%d", run_sched_chunk_size);
acf0174b
JJ
1346 break;
1347 case GFS_GUIDED:
1348 fputs ("GUIDED", stderr);
9f2fca56
MV
1349 if (run_sched_chunk_size != 1)
1350 fprintf (stderr, ",%d", run_sched_chunk_size);
acf0174b
JJ
1351 break;
1352 case GFS_AUTO:
1353 fputs ("AUTO", stderr);
1354 break;
1355 }
1356 fputs ("'\n", stderr);
9f2fca56
MV
1357}
1358
1359/* Helper function for omp_display_env which prints the values of proc_bind_var.
1360 'device' can be 'host', 'dev', 'all', or a particular device number. */
acf0174b 1361
9f2fca56
MV
1362static void
1363print_proc_bind (char proc_bind_var, unsigned long len, char **list,
1364 const char *device)
1365{
1366 fprintf (stderr, " [%s] OMP_PROC_BIND = '", device);
1367 switch (proc_bind_var)
acf0174b
JJ
1368 {
1369 case omp_proc_bind_false:
1370 fputs ("FALSE", stderr);
1371 break;
1372 case omp_proc_bind_true:
1373 fputs ("TRUE", stderr);
1374 break;
1375 case omp_proc_bind_master:
432de084 1376 fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
acf0174b
JJ
1377 break;
1378 case omp_proc_bind_close:
1379 fputs ("CLOSE", stderr);
1380 break;
1381 case omp_proc_bind_spread:
1382 fputs ("SPREAD", stderr);
1383 break;
1384 }
9f2fca56
MV
1385 for (int i = 1; i < len; i++)
1386 switch ((*list)[i])
acf0174b
JJ
1387 {
1388 case omp_proc_bind_master:
432de084 1389 fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
acf0174b
JJ
1390 break;
1391 case omp_proc_bind_close:
1392 fputs (",CLOSE", stderr);
1393 break;
1394 case omp_proc_bind_spread:
1395 fputs (",SPREAD", stderr);
1396 break;
1397 }
1398 fputs ("'\n", stderr);
9f2fca56
MV
1399}
1400
1401enum gomp_parse_type
1402{
1403 PARSE_INT = 1,
1404 PARSE_BOOL = 2,
1405 PARSE_UINT = 3,
1406 PARSE_ULONG = 4,
1407 PARSE_UCHAR = 5,
1408 PARSE_SCHEDULE =6,
1409 PARSE_BIND = 7
1410};
1411
1412/* The following table contains items that help parsing environment variables
1413 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1414 are affected by the environment variable. FLAGS determine what variant of
1415 environment variable is allowed. */
1416
1417#define ENTRY(NAME) NAME, sizeof (NAME) - 1
1418static const struct envvar
1419{
1420 const char *name;
1421 int name_len;
1422 uint8_t flag_vars[3];
1423 uint8_t flag;
1424 bool (*parse_func) (const char *, const char *, void *const[]);
1425} envvars[] = {
1426 { ENTRY ("SCHEDULE"),
1427 { GOMP_ICV_SCHEDULE, GOMP_ICV_SCHEDULE_CHUNK_SIZE },
1428 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1429 &parse_schedule },
1430 { ENTRY ("NUM_TEAMS"),
1431 { GOMP_ICV_NTEAMS },
1432 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1433 &parse_int },
1434 { ENTRY ("DYNAMIC"),
1435 { GOMP_ICV_DYNAMIC },
1436 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1437 &parse_boolean },
1438 { ENTRY ("TEAMS_THREAD_LIMIT"),
1439 { GOMP_ICV_TEAMS_THREAD_LIMIT },
1440 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1441 &parse_int },
1442 { ENTRY ("THREAD_LIMIT"),
1443 { GOMP_ICV_THREAD_LIMIT },
1444 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1445 &parse_unsigned_long },
1446 { ENTRY ("NUM_THREADS"),
1447 { GOMP_ICV_NTHREADS, GOMP_ICV_NTHREADS_LIST, GOMP_ICV_NTHREADS_LIST_LEN },
1448 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1449 &parse_unsigned_long_list },
1450 { ENTRY ("PROC_BIND"),
1451 { GOMP_ICV_BIND, GOMP_ICV_BIND_LIST, GOMP_ICV_BIND_LIST_LEN },
1452 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1453 &parse_bind_var },
1454 { ENTRY ("MAX_ACTIVE_LEVELS"),
1455 { GOMP_ICV_MAX_ACTIVE_LEVELS },
1456 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1457 &parse_unsigned_long },
1458 { ENTRY ("WAIT_POLICY"),
1459 { GOMP_ICV_WAIT_POLICY },
1460 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1461 &parse_wait_policy },
1462 { ENTRY ("STACKSIZE"),
1463 { GOMP_ICV_STACKSIZE },
1464 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1465 &parse_stacksize },
1466 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION }, 0, &parse_boolean },
1467 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY }, 0,
1468 &parse_boolean },
1469 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD }, 0,
1470 &parse_target_offload },
1471 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY }, 0,
1472 &parse_int },
1473 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR }, 0, &parse_allocator },
1474 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE },
1475 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1476 &parse_int }
1477};
1478#undef ENTRY
1479#define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1480
1481/* The following table is used to apply the hierarchy of ICV variants for host
1482 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1483 undefined. */
1484
1485static const struct host_envvar
1486{
1487 unsigned char flag_var;
1488 void *dest[3];
1489 int type_code;
1490} host_envvars[] = {
1491 { GOMP_ICV_NTEAMS, { &gomp_nteams_var }, PARSE_INT },
1492 { GOMP_ICV_DYNAMIC, { &gomp_global_icv.dyn_var }, PARSE_BOOL },
1493 { GOMP_ICV_DEFAULT_DEVICE, { &gomp_global_icv.default_device_var },
1494 PARSE_INT },
1495 { GOMP_ICV_TEAMS_THREAD_LIMIT, { &gomp_teams_thread_limit_var }, PARSE_INT },
1496 { GOMP_ICV_SCHEDULE,
1497 { &gomp_global_icv.run_sched_var, &gomp_global_icv.run_sched_chunk_size },
1498 PARSE_SCHEDULE },
1499 { GOMP_ICV_THREAD_LIMIT, { &gomp_global_icv.thread_limit_var }, PARSE_UINT },
1500 { GOMP_ICV_NTHREADS,
1501 { &gomp_global_icv.nthreads_var, &gomp_nthreads_var_list,
1502 &gomp_nthreads_var_list_len }, PARSE_ULONG },
1503 { GOMP_ICV_BIND,
1504 { &gomp_global_icv.bind_var, &gomp_bind_var_list, &gomp_bind_var_list_len },
1505 PARSE_BIND },
1506 { GOMP_ICV_MAX_ACTIVE_LEVELS, { &gomp_global_icv.max_active_levels_var },
1507 PARSE_UCHAR },
1508};
1509#define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1510
1511#define INT_MAX_STR_LEN 10
1512
1513bool
1514gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv)
1515{
1516 return value & (1 << (icv - 1));
1517}
1518
1519static void
1520gomp_set_icv_flag (uint32_t *value, enum gomp_icvs icv)
1521{
1522 *value |= 1 << (icv - 1);
1523}
1524
1525static void
1526print_device_specific_icvs (int icv_code)
1527{
1528 struct gomp_icv_list *list = gomp_initial_icv_list;
1529 int i;
1530 char dev_num[INT_MAX_STR_LEN + 1];
1531
1532 while (list != NULL)
1533 {
1534 if (list->device_num < 0)
1535 {
1536 list = list->next;
1537 continue;
1538 }
1539
1540 switch (icv_code)
1541 {
1542 case GOMP_ICV_NTEAMS:
1543 if (gomp_get_icv_flag (list->flags, GOMP_ICV_NTEAMS))
1544 fprintf (stderr, " [%d] OMP_NUM_TEAMS = '%d'\n",
1545 list->device_num, list->icvs.nteams_var);
1546 break;
1547 case GOMP_ICV_DYNAMIC:
1548 if (gomp_get_icv_flag (list->flags, GOMP_ICV_DYNAMIC))
1549 fprintf (stderr, " [%d] OMP_DYNAMIC = '%s'\n",
1550 list->device_num, list->icvs.dyn_var ? "TRUE" : "FALSE");
1551 break;
1552 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1553 if (gomp_get_icv_flag (list->flags, GOMP_ICV_TEAMS_THREAD_LIMIT))
1554 fprintf (stderr, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1555 list->device_num, list->icvs.teams_thread_limit_var);
1556 break;
1557 case GOMP_ICV_SCHEDULE:
1558 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_SCHEDULE)))
1559 break;
1560 sprintf (dev_num, "%d", list->device_num);
1561 print_schedule (list->icvs.run_sched_var,
1562 list->icvs.run_sched_chunk_size,
1563 dev_num);
1564 break;
1565 case GOMP_ICV_THREAD_LIMIT:
1566 if (gomp_get_icv_flag (list->flags, GOMP_ICV_THREAD_LIMIT))
1567 fprintf (stderr, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1568 list->device_num, list->icvs.thread_limit_var);
1569 break;
1570 case GOMP_ICV_NTHREADS:
1571 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_NTHREADS)))
1572 break;
1573 fprintf (stderr, " [%d] OMP_NUM_THREADS = '%lu", list->device_num,
1574 list->icvs.nthreads_var);
1575 for (i = 1; i < list->icvs.nthreads_var_list_len; i++)
1576 fprintf (stderr, ",%lu", list->icvs.nthreads_var_list[i]);
1577 fputs ("'\n", stderr);
1578 break;
1579 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1580 fprintf (stderr, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1581 list->device_num, list->icvs.max_active_levels_var);
1582 break;
1583 case GOMP_ICV_BIND:
1584 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_BIND)))
1585 break;
1586 sprintf (dev_num, "%d", list->device_num);
1587 print_proc_bind (list->icvs.bind_var, list->icvs.bind_var_list_len,
1588 &list->icvs.bind_var_list, dev_num);
1589 break;
1590 case GOMP_ICV_WAIT_POLICY:
1591 if (gomp_get_icv_flag (list->flags, GOMP_ICV_WAIT_POLICY))
1592 fprintf (stderr, " [%d] OMP_WAIT_POLICY = '%s'\n",
1593 list->device_num,
1594 list->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1595 break;
1596 case GOMP_ICV_STACKSIZE:
1597 if (gomp_get_icv_flag (list->flags, GOMP_ICV_STACKSIZE))
1598 fprintf (stderr, " [%d] OMP_STACKSIZE = '%lu'\n",
1599 list->device_num, list->icvs.stacksize);
1600 break;
1601 }
1602 list = list->next;
1603 }
1604}
1605
1606void
1607omp_display_env (int verbose)
1608{
1609 int i;
1610 struct gomp_icv_list *dev
1611 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV);
1612 struct gomp_icv_list *all
1613 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
1614 struct gomp_icv_list *none
1615 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
1616
1617 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1618
1619 fputs (" _OPENMP = '201511'\n", stderr);
1620
1621 fprintf (stderr, " [host] OMP_DYNAMIC = '%s'\n",
1622 none->icvs.dyn_var ? "TRUE" : "FALSE");
1623 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_DYNAMIC))
1624 fprintf (stderr, " [all] OMP_DYNAMIC = '%s'\n",
1625 all->icvs.dyn_var ? "TRUE" : "FALSE");
1626 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_DYNAMIC))
1627 fprintf (stderr, " [device] OMP_DYNAMIC = '%s'\n",
1628 dev->icvs.dyn_var ? "TRUE" : "FALSE");
1629 print_device_specific_icvs (GOMP_ICV_DYNAMIC);
1630
1631 /* The OMP_NESTED environment variable has been deprecated. */
1632 fprintf (stderr, " [host] OMP_NESTED = '%s'\n",
1633 none->icvs.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1634
1635 fprintf (stderr, " [host] OMP_NUM_THREADS = '%lu",
1636 none->icvs.nthreads_var);
1637 for (i = 1; i < none->icvs.nthreads_var_list_len; i++)
1638 fprintf (stderr, ",%lu", none->icvs.nthreads_var_list[i]);
1639 fputs ("'\n", stderr);
1640 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTHREADS))
1641 {
1642 fprintf (stderr, " [all] OMP_NUM_THREADS = '%lu",
1643 all->icvs.nthreads_var);
1644 for (i = 1; i < all->icvs.nthreads_var_list_len; i++)
1645 fprintf (stderr, ",%lu", all->icvs.nthreads_var_list[i]);
1646 fputs ("'\n", stderr);
1647 }
1648 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTHREADS))
1649 {
1650 fprintf (stderr, " [device] OMP_NUM_THREADS = '%lu",
1651 dev->icvs.nthreads_var);
1652 for (i = 1; i < dev->icvs.nthreads_var_list_len; i++)
1653 fprintf (stderr, ",%lu", dev->icvs.nthreads_var_list[i]);
1654 fputs ("'\n", stderr);
1655 }
1656 print_device_specific_icvs (GOMP_ICV_NTHREADS);
1657
1658
1659 print_schedule (none->icvs.run_sched_var,
1660 none->icvs.run_sched_chunk_size, "host");
1661 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_SCHEDULE))
1662 print_schedule (all->icvs.run_sched_var,
1663 all->icvs.run_sched_chunk_size, "all");
1664 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_SCHEDULE))
1665 print_schedule (dev->icvs.run_sched_var,
1666 dev->icvs.run_sched_chunk_size, "device");
1667 print_device_specific_icvs (GOMP_ICV_SCHEDULE);
1668
1669 print_proc_bind (none->icvs.bind_var,
1670 none->icvs.bind_var_list_len,
1671 &none->icvs.bind_var_list, "host");
1672 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND))
1673 print_proc_bind (all->icvs.bind_var,
1674 all->icvs.bind_var_list_len,
1675 &all->icvs.bind_var_list, "all");
1676 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_BIND))
1677 print_proc_bind (dev->icvs.bind_var,
1678 dev->icvs.bind_var_list_len,
1679 &dev->icvs.bind_var_list, "device");
1680 print_device_specific_icvs (GOMP_ICV_BIND);
1681
1682 fputs (" [host] OMP_PLACES = '", stderr);
acf0174b
JJ
1683 for (i = 0; i < gomp_places_list_len; i++)
1684 {
1685 fputs ("{", stderr);
1686 gomp_affinity_print_place (gomp_places_list[i]);
1687 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1688 }
1689 fputs ("'\n", stderr);
1690
9f2fca56
MV
1691 fprintf (stderr, " [host] OMP_STACKSIZE = '%lu'\n",
1692 none->icvs.stacksize);
1693 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
1694 fprintf (stderr, " [all] OMP_STACKSIZE = '%lu'\n",
1695 all->icvs.stacksize);
1696 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_STACKSIZE))
1697 fprintf (stderr, " [device] OMP_STACKSIZE = '%lu'\n",
1698 dev->icvs.stacksize);
1699 print_device_specific_icvs (GOMP_ICV_STACKSIZE);
acf0174b
JJ
1700
1701 /* GOMP's default value is actually neither active nor passive. */
9f2fca56
MV
1702 fprintf (stderr, " [host] OMP_WAIT_POLICY = '%s'\n",
1703 none->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1704 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
1705 fprintf (stderr, " [all] OMP_WAIT_POLICY = '%s'\n",
1706 all->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1707 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_WAIT_POLICY))
1708 fprintf (stderr, " [device] OMP_WAIT_POLICY = '%s'\n",
1709 dev->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1710 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY);
1711
1712 fprintf (stderr, " [host] OMP_THREAD_LIMIT = '%u'\n",
1713 none->icvs.thread_limit_var);
1714 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_THREAD_LIMIT))
1715 fprintf (stderr, " [all] OMP_THREAD_LIMIT = '%d'\n",
1716 all->icvs.thread_limit_var);
1717 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_THREAD_LIMIT))
1718 fprintf (stderr, " [device] OMP_THREAD_LIMIT = '%d'\n",
1719 dev->icvs.thread_limit_var);
1720 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT);
1721
1722 fprintf (stderr, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1723 none->icvs.max_active_levels_var);
1724 if (all != NULL && gomp_get_icv_flag (all->flags,
1725 GOMP_ICV_MAX_ACTIVE_LEVELS))
1726 fprintf (stderr, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1727 all->icvs.max_active_levels_var);
1728 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1729 GOMP_ICV_MAX_ACTIVE_LEVELS))
1730 fprintf (stderr, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1731 dev->icvs.max_active_levels_var);
1732 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS);
1733
1734
1735 fprintf (stderr, " [host] OMP_NUM_TEAMS = '%d'\n",
1736 none->icvs.nteams_var);
1737 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTEAMS))
1738 fprintf (stderr, " [all] OMP_NUM_TEAMS = '%d'\n",
1739 all->icvs.nteams_var);
1740 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTEAMS))
1741 fprintf (stderr, " [device] OMP_NUM_TEAMS = '%d'\n",
1742 dev->icvs.nteams_var);
1743 print_device_specific_icvs (GOMP_ICV_NTEAMS);
1744
1745 fprintf (stderr, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1746 none->icvs.teams_thread_limit_var);
1747 if (all != NULL && gomp_get_icv_flag (all->flags,
1748 GOMP_ICV_TEAMS_THREAD_LIMIT))
1749 fprintf (stderr, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1750 all->icvs.teams_thread_limit_var);
1751 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1752 GOMP_ICV_TEAMS_THREAD_LIMIT))
1753 fprintf (stderr, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1754 dev->icvs.teams_thread_limit_var);
1755 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT);
1756
1757 fprintf (stderr, " [all] OMP_CANCELLATION = '%s'\n",
acf0174b 1758 gomp_cancel_var ? "TRUE" : "FALSE");
9f2fca56
MV
1759
1760 fprintf (stderr, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1761 none->icvs.default_device_var);
1762
1763 fprintf (stderr, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
d9a6bd32 1764 gomp_max_task_priority_var);
9f2fca56 1765 fprintf (stderr, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
28567c40 1766 gomp_display_affinity_var ? "TRUE" : "FALSE");
9f2fca56 1767 fprintf (stderr, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
28567c40 1768 gomp_affinity_format_var);
9f2fca56 1769 fprintf (stderr, " [host] OMP_ALLOCATOR = '");
800bcc8c
JJ
1770 switch (gomp_def_allocator)
1771 {
1772#define C(v) case v: fputs (#v, stderr); break;
1773 C (omp_default_mem_alloc)
1774 C (omp_large_cap_mem_alloc)
1775 C (omp_const_mem_alloc)
1776 C (omp_high_bw_mem_alloc)
1777 C (omp_low_lat_mem_alloc)
1778 C (omp_cgroup_mem_alloc)
1779 C (omp_pteam_mem_alloc)
1780 C (omp_thread_mem_alloc)
1781#undef C
1782 default: break;
1783 }
1784 fputs ("'\n", stderr);
acf0174b 1785
9f2fca56 1786 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr);
1bfc07d1
KCY
1787 switch (gomp_target_offload_var)
1788 {
1789 case GOMP_TARGET_OFFLOAD_DEFAULT:
1790 fputs ("DEFAULT", stderr);
1791 break;
1792 case GOMP_TARGET_OFFLOAD_MANDATORY:
1793 fputs ("MANDATORY", stderr);
1794 break;
1795 case GOMP_TARGET_OFFLOAD_DISABLED:
1796 fputs ("DISABLED", stderr);
1797 break;
1798 }
1799 fputs ("'\n", stderr);
1800
acf0174b
JJ
1801 if (verbose)
1802 {
9f2fca56
MV
1803 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr);
1804 fprintf (stderr, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize);
acf0174b 1805#ifdef HAVE_INTTYPES_H
9f2fca56 1806 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%"PRIu64"'\n",
acf0174b
JJ
1807 (uint64_t) gomp_spin_count_var);
1808#else
9f2fca56 1809 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%lu'\n",
acf0174b
JJ
1810 (unsigned long) gomp_spin_count_var);
1811#endif
1812 }
1813
1814 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1815}
7123ae24
UD
1816ialias (omp_display_env)
1817
1818static void
1819handle_omp_display_env (void)
1820{
1821 const char *env;
1822 bool display = false;
1823 bool verbose = false;
1824
1825 env = getenv ("OMP_DISPLAY_ENV");
1826 if (env == NULL)
1827 return;
1828
1829 while (isspace ((unsigned char) *env))
1830 ++env;
1831 if (strncasecmp (env, "true", 4) == 0)
1832 {
1833 display = true;
1834 env += 4;
1835 }
1836 else if (strncasecmp (env, "false", 5) == 0)
1837 {
1838 display = false;
1839 env += 5;
1840 }
1841 else if (strncasecmp (env, "verbose", 7) == 0)
1842 {
1843 display = true;
1844 verbose = true;
1845 env += 7;
1846 }
1847 else
1848 env = "X";
1849 while (isspace ((unsigned char) *env))
1850 ++env;
1851 if (*env != '\0')
1852 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1853
1854 if (display)
3749c3af 1855 ialias_call (omp_display_env) (verbose);
7123ae24 1856}
acf0174b 1857
9f2fca56
MV
1858/* Helper function for initialize_env. Extracts the device number from
1859 an environment variable name. ENV is the complete environment variable.
1860 DEV_NUM_PTR points to the start of the device number in the environment
1861 variable string. DEV_NUM_LEN is the returned length of the device num
1862 string. */
1863
1864static bool
1865get_device_num (char *env, char *dev_num_ptr, int *dev_num, int *dev_num_len)
1866{
1867 char *end;
1868 unsigned long val = strtoul (dev_num_ptr, &end, 10);
1869 if (val > INT_MAX
1870 || *end != '='
1871 || (dev_num_ptr[0] == '0' && end != dev_num_ptr + 1)
1872 || (dev_num_ptr[0] < '0' || dev_num_ptr[0] > '9'))
1873 {
1874 gomp_error ("Invalid device number in %s", env);
1875 return false;
1876 }
1877 *dev_num = val;
1878 *dev_num_len = end - dev_num_ptr;
1879 return true;
1880}
1881
1882static void
1883get_icv_member_addr (struct gomp_initial_icvs *icvs, int icv_code,
1884 void *icv_addr[3])
1885{
1886 if (icv_code == 0 || icv_addr == NULL)
1887 return;
1888
1889 icv_addr[0] = icv_addr[1] = icv_addr[2] = NULL;
1890
1891 switch (icv_code)
1892 {
1893 case GOMP_ICV_NTEAMS:
1894 icv_addr[0] = &icvs->nteams_var;
1895 icv_addr[1] = false;
1896 break;
1897 case GOMP_ICV_DYNAMIC:
1898 icv_addr[0] = &(*icvs).dyn_var;
1899 break;
1900 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1901 icv_addr[0] = &icvs->teams_thread_limit_var;
1902 icv_addr[1] = false;
1903 break;
1904 case GOMP_ICV_SCHEDULE:
1905 icv_addr[0] = &icvs->run_sched_var;
1906 icv_addr[1] = &icvs->run_sched_chunk_size;
1907 break;
1908 case GOMP_ICV_THREAD_LIMIT:
1909 icv_addr[0] = &icvs->thread_limit_var;
1910 icv_addr[1] = false;
1911 icv_addr[2] = (void *) UINT_MAX;
1912 break;
1913 case GOMP_ICV_NTHREADS:
1914 icv_addr[0] = &icvs->nthreads_var;
1915 icv_addr[1] = &icvs->nthreads_var_list;
1916 icv_addr[2] = &icvs->nthreads_var_list_len;
1917 break;
1918 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1919 icv_addr[0] = &icvs->max_active_levels_var;
1920 icv_addr[1] = (void *) true;
1921 icv_addr[2] = (void *) gomp_supported_active_levels;
1922 break;
1923 case GOMP_ICV_BIND:
1924 icv_addr[0] = &icvs->bind_var;
1925 icv_addr[1] = &icvs->bind_var_list;
1926 icv_addr[2] = &icvs->bind_var_list_len;
1927 break;
1928 case GOMP_ICV_WAIT_POLICY:
1929 icv_addr[0] = &icvs->wait_policy;
1930 break;
1931 case GOMP_ICV_STACKSIZE:
1932 icv_addr[0] = &icvs->stacksize;
1933 break;
1934 case GOMP_ICV_CANCELLATION:
1935 icv_addr[0] = &gomp_cancel_var;
1936 break;
1937 case GOMP_ICV_DISPLAY_AFFINITY:
1938 icv_addr[0] = &gomp_display_affinity_var;
1939 break;
1940 case GOMP_ICV_TARGET_OFFLOAD:
1941 icv_addr[0] = &gomp_target_offload_var;
1942 break;
1943 case GOMP_ICV_MAX_TASK_PRIORITY:
1944 icv_addr[0] = &gomp_max_task_priority_var;
1945 break;
1946 case GOMP_ICV_ALLOCATOR:
1947 icv_addr[0] = &gomp_def_allocator;
1948 break;
1949 case GOMP_ICV_DEFAULT_DEVICE:
1950 icv_addr[0] = &icvs->default_device_var;
1951 icv_addr[1] = (void *) true;
1952 break;
1953 }
1954}
1955
1956struct gomp_icv_list *
1957gomp_get_initial_icv_item (int dev_num)
1958{
1959 struct gomp_icv_list *l = gomp_initial_icv_list;
1960 while (l != NULL && l->device_num != dev_num)
1961 l = l->next;
1962
1963 return l;
1964}
1965
1966static void
1967initialize_icvs (struct gomp_initial_icvs *icvs)
1968{
1969 icvs->nthreads_var_list = NULL;
1970 icvs->bind_var_list = NULL;
1971 icvs->nthreads_var = gomp_default_icv_values.nthreads_var;
1972 icvs->nthreads_var_list_len = 0;
1973 icvs->bind_var_list_len = 0;
1974 icvs->stacksize = 0;
1975 icvs->thread_limit_var = gomp_default_icv_values.thread_limit_var;
1976 icvs->run_sched_var = gomp_default_icv_values.run_sched_var;
1977 icvs->run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size;
1978 icvs->default_device_var = gomp_default_icv_values.default_device_var;
1979 icvs->dyn_var = gomp_default_icv_values.dyn_var;
1980 icvs->max_active_levels_var = gomp_default_icv_values.max_active_levels_var;
1981 icvs->bind_var = gomp_default_icv_values.bind_var;
1982 icvs->nteams_var = gomp_default_icv_values.nteams_var;
1983 icvs->teams_thread_limit_var = gomp_default_icv_values.teams_thread_limit_var;
1984 icvs->wait_policy = 0;
1985}
1986
1987/* Helper function for initialize_env to add a device specific ICV value
1988 to gomp_initial_icv_list. */
1989
1990static uint32_t *
1991add_initial_icv_to_list (int dev_num, int icv_code, void *icv_addr[3])
1992{
1993 struct gomp_icv_list *last = NULL, *l = gomp_initial_icv_list;
1994 while (l != NULL && l->device_num != dev_num)
1995 {
1996 last = l;
1997 l = l->next;
1998 }
1999
2000 if (l == NULL)
2001 {
2002 l = ((struct gomp_icv_list *)
2003 gomp_malloc_cleared (sizeof (struct gomp_icv_list)));
2004 l->device_num = dev_num;
2005 initialize_icvs (&l->icvs);
2006 if (dev_num < 0)
2007 {
2008 l->next = gomp_initial_icv_list;
2009 gomp_initial_icv_list = l;
2010 }
2011 else
2012 {
2013 l->next = NULL;
2014 if (last == NULL)
2015 gomp_initial_icv_list = l;
2016 else
2017 last->next = l;
2018 }
2019 }
2020
2021 get_icv_member_addr (&l->icvs, icv_code, icv_addr);
2022
2023 return &l->flags;
2024}
2025
2026/* Return true if STR string starts with PREFIX. */
2027
2028static inline bool
2029startswith (const char *str, const char *prefix)
2030{
2031 return strncmp (str, prefix, strlen (prefix)) == 0;
2032}
acf0174b 2033
953ff289
DN
2034static void __attribute__((constructor))
2035initialize_env (void)
2036{
9f2fca56
MV
2037 char **env;
2038 int omp_var, dev_num = 0, dev_num_len = 0, i;
2039 bool ignore = false;
2040 char *env_val;
2041 void *params[3];
2042 uint32_t *flag_var_addr = NULL;
2043 unsigned pos;
2044 struct gomp_icv_list *all, *none;
d0d1b24d 2045
953ff289
DN
2046 /* Do a compile time check that mkomp_h.pl did good job. */
2047 omp_check_defines ();
2048
a68ab351 2049#ifndef HAVE_SYNC_BUILTINS
acf0174b 2050 gomp_mutex_init (&gomp_managed_threads_lock);
a68ab351 2051#endif
a68ab351
JJ
2052 gomp_init_num_threads ();
2053 gomp_available_cpus = gomp_global_icv.nthreads_var;
9f2fca56
MV
2054
2055 /* Initial values for host environment variables should always exist even if
2056 there is no explicitly set host environment variable. Moreover, they are
2057 set to the initial global values. */
2058 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX, 0, NULL);
2059 none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
2060 initialize_icvs (&none->icvs);
2061
2062 for (env = environ; *env != 0; env++)
2063 {
2064 if (!startswith (*env, "OMP_"))
2065 continue;
2066
2067 /* Name of the environment variable without suffix "OMP_". */
2068 char *name = *env + sizeof ("OMP_") - 1;
2069 for (omp_var = 0; omp_var < OMP_VAR_CNT; omp_var++)
2070 {
2071 if (startswith (name, envvars[omp_var].name))
2072 {
2073 pos = envvars[omp_var].name_len;
2074 if (name[pos] == '=')
2075 {
2076 pos++;
2077 flag_var_addr
2078 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX,
2079 envvars[omp_var].flag_vars[0],
2080 params);
2081 }
2082 else if (startswith (&name[pos], "_DEV=")
2083 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV)
2084 {
2085 pos += 5;
2086 flag_var_addr
2087 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV,
2088 envvars[omp_var].flag_vars[0],
2089 params);
2090 }
2091 else if (startswith (&name[pos], "_ALL=")
2092 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_ALL)
2093 {
2094 pos += 5;
2095 flag_var_addr
2096 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL,
2097 envvars[omp_var].flag_vars[0],
2098 params);
2099 }
2100 else if (startswith (&name[pos], "_DEV_")
2101 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV_X)
2102 {
2103 pos += 5;
2104 if (!get_device_num (*env, &name[pos], &dev_num,
2105 &dev_num_len))
2106 break;
2107
2108 pos += dev_num_len + 1;
2109 flag_var_addr
2110 = add_initial_icv_to_list (dev_num,
2111 envvars[omp_var].flag_vars[0],
2112 params);
2113 }
2114 else
2115 {
2116 gomp_error ("Invalid environment variable in %s", *env);
2117 break;
2118 }
2119 env_val = &name[pos];
2120
2121 if (envvars[omp_var].parse_func (*env, env_val, params))
2122 {
2123 for (i = 0; i < 3; ++i)
2124 if (envvars[omp_var].flag_vars[i])
2125 gomp_set_icv_flag (flag_var_addr,
2126 envvars[omp_var].flag_vars[i]);
2127 else
2128 break;
2129 }
2130
2131 break;
2132 }
2133 }
2134 }
2135
2136 all = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
2137 for (omp_var = 0; omp_var < OMP_HOST_VAR_CNT; omp_var++)
2138 {
2139 if (none != NULL
2140 && gomp_get_icv_flag (none->flags, host_envvars[omp_var].flag_var))
2141 get_icv_member_addr (&none->icvs,
2142 host_envvars[omp_var].flag_var, params);
2143 else if (all != NULL
2144 && gomp_get_icv_flag (all->flags,
2145 host_envvars[omp_var].flag_var))
2146 get_icv_member_addr (&all->icvs, host_envvars[omp_var].flag_var,
2147 params);
2148 else
2149 continue;
2150
2151 switch (host_envvars[omp_var].type_code)
2152 {
2153 case PARSE_INT:
2154 for (i = 0; i < 3; ++i)
2155 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2156 *(int *) (host_envvars[omp_var].dest[i]) = *(int *) params[i];
2157 break;
2158 case PARSE_BOOL:
2159 for (i = 0; i < 3; ++i)
2160 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2161 *(bool *) (host_envvars[omp_var].dest[i]) = *(bool *) params[i];
2162 break;
2163 case PARSE_UINT:
2164 for (i = 0; i < 3; ++i)
2165 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2166 *(unsigned int *) (host_envvars[omp_var].dest[i])
2167 = *(unsigned int *) params[i];
2168 break;
2169 case PARSE_ULONG:
2170 for (i = 0; i < 3; ++i)
2171 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2172 *(unsigned long *) (host_envvars[omp_var].dest[i])
2173 = *(unsigned long *) params[i];
2174 break;
2175 case PARSE_UCHAR:
2176 for (i = 0; i < 3; ++i)
2177 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2178 *(unsigned char *) (host_envvars[omp_var].dest[i])
2179 = *(unsigned char *) params[i];
2180 break;
2181 case PARSE_SCHEDULE:
2182 *(enum gomp_schedule_type *) (host_envvars[omp_var].dest[0])
2183 = *(enum gomp_schedule_type *) params[0];
2184 *(int *) (host_envvars[omp_var].dest[1]) = *(int *) params[1];
2185 break;
2186 case PARSE_BIND:
26a1f4fc
JJ
2187 *(char *) (host_envvars[omp_var].dest[0]) = *(char *) params[0];
2188 *(char **) (host_envvars[omp_var].dest[1]) = *(char **) params[1];
9f2fca56 2189 *(unsigned long *) (host_envvars[omp_var].dest[2])
26a1f4fc 2190 = *(unsigned long *) params[2];
9f2fca56
MV
2191 break;
2192 }
2193 }
2194
2195 if (((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_BIND))
2196 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND)))
f89163fd
JJ
2197 && gomp_global_icv.bind_var == omp_proc_bind_false)
2198 ignore = true;
9f2fca56
MV
2199
2200 if (!((none != NULL
2201 && gomp_get_icv_flag (none->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))
2202 || (all != NULL
2203 && gomp_get_icv_flag (all->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))))
6fae7eda
KCY
2204 {
2205 bool nested = true;
9f2fca56 2206 const char *env = getenv ("OMP_NESTED");
6fae7eda
KCY
2207
2208 /* OMP_NESTED is deprecated in OpenMP 5.0. */
9f2fca56 2209 if (parse_boolean ("OMP_NESTED", env, (void *[]) {&nested}))
6fae7eda
KCY
2210 gomp_global_icv.max_active_levels_var
2211 = nested ? gomp_supported_active_levels : 1;
2212 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
2213 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
2214 }
9f2fca56
MV
2215
2216 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2217 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
2218
f89163fd
JJ
2219 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2220 parsed if present in the environment. If OMP_PROC_BIND was set
93d90219 2221 explicitly to false, don't populate places list though. If places
f89163fd
JJ
2222 list was successfully set from OMP_PLACES, only parse but don't process
2223 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2224 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2225 was successfully parsed into a places list, otherwise to
2226 OMP_PROC_BIND=false. */
2227 if (parse_places_var ("OMP_PLACES", ignore))
2228 {
2229 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2230 gomp_global_icv.bind_var = true;
2231 ignore = true;
2232 }
2233 if (parse_affinity (ignore))
2234 {
2235 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2236 gomp_global_icv.bind_var = true;
2237 ignore = true;
2238 }
2239 if (gomp_global_icv.bind_var != omp_proc_bind_false)
a0884cf0 2240 gomp_init_affinity ();
28567c40
JJ
2241
2242 {
2243 const char *env = getenv ("OMP_AFFINITY_FORMAT");
2244 if (env != NULL)
2245 gomp_set_affinity_format (env, strlen (env));
2246 }
2247
9f2fca56
MV
2248 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_WAIT_POLICY))
2249 wait_policy = none->icvs.wait_policy;
2250 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
2251 wait_policy = all->icvs.wait_policy;
2252
a68ab351
JJ
2253 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
2254 {
2255 /* Using a rough estimation of 100000 spins per msec,
2256 use 5 min blocking for OMP_WAIT_POLICY=active,
4c698cf8 2257 3 msec blocking when OMP_WAIT_POLICY is not specificed
a68ab351
JJ
2258 and 0 when OMP_WAIT_POLICY=passive.
2259 Depending on the CPU speed, this can be e.g. 5 times longer
2260 or 5 times shorter. */
2261 if (wait_policy > 0)
2262 gomp_spin_count_var = 30000000000LL;
2263 else if (wait_policy < 0)
4c698cf8 2264 gomp_spin_count_var = 300000LL;
a68ab351
JJ
2265 }
2266 /* gomp_throttled_spin_count_var is used when there are more libgomp
2267 managed threads than available CPUs. Use very short spinning. */
2268 if (wait_policy > 0)
2269 gomp_throttled_spin_count_var = 1000LL;
2270 else if (wait_policy < 0)
2271 gomp_throttled_spin_count_var = 100LL;
2272 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
2273 gomp_throttled_spin_count_var = gomp_spin_count_var;
d0d1b24d
RH
2274
2275 /* Not strictly environment related, but ordering constructors is tricky. */
2276 pthread_attr_init (&gomp_thread_attr);
d0d1b24d 2277
9f2fca56
MV
2278 if (!(none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE)))
2279 {
2280 const char *env = getenv ("GOMP_STACKSIZE");
2281 if (env != NULL
2282 && parse_stacksize ("GOMP_STACKSIZE", env,
2283 (void *[3]) {&none->icvs.stacksize}))
2284 gomp_set_icv_flag (&none->flags, GOMP_ICV_STACKSIZE);
2285 }
2286 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2287 stacksize = none->icvs.stacksize;
2288 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2289 stacksize = all->icvs.stacksize;
2290
2291 if ((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2292 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
c4060df4 2293 || GOMP_DEFAULT_STACKSIZE)
d0d1b24d 2294 {
c3b11a40
RH
2295 int err;
2296
c3b11a40
RH
2297 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
2298
2299#ifdef PTHREAD_STACK_MIN
2300 if (err == EINVAL)
d0d1b24d 2301 {
c3b11a40
RH
2302 if (stacksize < PTHREAD_STACK_MIN)
2303 gomp_error ("Stack size less than minimum of %luk",
2304 PTHREAD_STACK_MIN / 1024ul
2305 + (PTHREAD_STACK_MIN % 1024 != 0));
2306 else
d0d1b24d 2307 gomp_error ("Stack size larger than system limit");
d0d1b24d 2308 }
c3b11a40
RH
2309 else
2310#endif
2311 if (err != 0)
2312 gomp_error ("Stack size change failed: %s", strerror (err));
d0d1b24d 2313 }
acf0174b 2314
7123ae24 2315 handle_omp_display_env ();
41dbbb37
TS
2316
2317 /* OpenACC. */
2318
9f2fca56
MV
2319 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2320 (void *[]) {&goacc_device_num, (void *) true}))
41dbbb37
TS
2321 goacc_device_num = 0;
2322
2323 parse_acc_device_type ();
ec00d3fa 2324 parse_gomp_openacc_dim ();
41dbbb37
TS
2325
2326 goacc_runtime_initialize ();
5fae049d
TS
2327
2328 goacc_profiling_initialize ();
953ff289 2329}
630e3c3a 2330#endif /* LIBGOMP_OFFLOADED_ONLY */