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