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