d: Merge upstream dmd, druntime 26f049fb26, phobos 330d6a4fd.
[official-gcc.git] / libgomp / env.c
blobf24484d7f7074279ed67dfc9b9eb8534f43d7ba7
1 /* Copyright (C) 2005-2023 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
7 Libgomp is free software; you can redistribute it and/or modify it
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.
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
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
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.
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/>. */
26 /* This file defines the OpenMP internal control variables and arranges
27 for them to be initialized from environment variables at startup. */
29 #define _GNU_SOURCE
30 #include "libgomp.h"
31 #include "gomp-constants.h"
32 #include <limits.h>
33 #ifndef LIBGOMP_OFFLOADED_ONLY
34 #include "libgomp_f.h"
35 #include "oacc-int.h"
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #ifdef HAVE_INTTYPES_H
40 # include <inttypes.h> /* For PRIu64. */
41 #endif
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
54 #include <errno.h>
55 #include "thread-stacksize.h"
57 #ifndef HAVE_STRTOULL
58 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
59 #endif
60 #endif /* LIBGOMP_OFFLOADED_ONLY */
62 #include "secure_getenv.h"
63 #include "environ.h"
65 /* Default values of ICVs according to the OpenMP standard,
66 except for default-device-var. */
67 const struct gomp_default_icv gomp_default_icv_values = {
68 .nthreads_var = 1,
69 .thread_limit_var = UINT_MAX,
70 .run_sched_var = GFS_DYNAMIC,
71 .run_sched_chunk_size = 1,
72 .default_device_var = INT_MIN,
73 .max_active_levels_var = 1,
74 .bind_var = omp_proc_bind_false,
75 .nteams_var = 0,
76 .teams_thread_limit_var = 0,
77 .dyn_var = false
80 struct 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,
89 .target_data = NULL
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. */
94 struct gomp_icv_list *gomp_initial_icv_list = NULL;
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. */
98 struct gomp_offload_icv_list *gomp_offload_icv_list = NULL;
100 bool gomp_cancel_var = false;
101 enum gomp_target_offload_t gomp_target_offload_var
102 = GOMP_TARGET_OFFLOAD_DEFAULT;
103 int gomp_max_task_priority_var = 0;
104 #ifndef HAVE_SYNC_BUILTINS
105 gomp_mutex_t gomp_managed_threads_lock;
106 #endif
107 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
108 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
109 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
110 char *gomp_bind_var_list;
111 unsigned long gomp_bind_var_list_len;
112 void **gomp_places_list;
113 unsigned long gomp_places_list_len;
114 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
115 char *gomp_def_allocator_envvar = NULL;
116 int gomp_debug_var;
117 unsigned int gomp_num_teams_var;
118 int gomp_nteams_var;
119 int gomp_teams_thread_limit_var;
120 bool gomp_display_affinity_var;
121 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
122 size_t gomp_affinity_format_len;
123 char *goacc_device_type;
124 int goacc_device_num;
125 int goacc_default_dims[GOMP_DIM_MAX];
127 #ifndef LIBGOMP_OFFLOADED_ONLY
129 static int wait_policy = -1;
130 static unsigned long stacksize = GOMP_DEFAULT_STACKSIZE;
132 static void
133 print_env_var_error (const char *env, const char *val)
135 gomp_error ("Invalid value for environment variable %.*s: %s",
136 (int) (val - env - 1), env, val);
139 /* Parse the OMP_SCHEDULE environment variable. */
140 static bool
141 parse_schedule (const char *env, const char *val, void *const params[])
143 enum gomp_schedule_type *schedule = (enum gomp_schedule_type *) params[0];
144 int *chunk_size = (int *) params[1];
145 char *end;
146 unsigned long value;
147 int monotonic = 0;
149 if (val == NULL)
150 return false;
152 while (isspace ((unsigned char) *val))
153 ++val;
154 if (strncasecmp (val, "monotonic", 9) == 0)
156 monotonic = 1;
157 val += 9;
159 else if (strncasecmp (val, "nonmonotonic", 12) == 0)
161 monotonic = -1;
162 val += 12;
164 if (monotonic)
166 while (isspace ((unsigned char) *val))
167 ++val;
168 if (*val != ':')
169 goto unknown;
170 ++val;
171 while (isspace ((unsigned char) *val))
172 ++val;
174 if (strncasecmp (val, "static", 6) == 0)
176 *schedule = GFS_STATIC;
177 val += 6;
179 else if (strncasecmp (val, "dynamic", 7) == 0)
181 *schedule = GFS_DYNAMIC;
182 val += 7;
184 else if (strncasecmp (val, "guided", 6) == 0)
186 *schedule = GFS_GUIDED;
187 val += 6;
189 else if (strncasecmp (val, "auto", 4) == 0)
191 *schedule = GFS_AUTO;
192 val += 4;
194 else
195 goto unknown;
197 if (monotonic == 1
198 || (monotonic == 0 && *schedule == GFS_STATIC))
199 *schedule |= GFS_MONOTONIC;
201 while (isspace ((unsigned char) *val))
202 ++val;
203 if (*val == '\0')
205 *chunk_size = (*schedule & ~GFS_MONOTONIC) != GFS_STATIC;
206 return true;
208 if (*val++ != ',')
209 goto unknown;
210 while (isspace ((unsigned char) *val))
211 ++val;
212 if (*val == '\0')
213 goto invalid;
215 errno = 0;
216 value = strtoul (val, &end, 10);
217 if (errno || end == val)
218 goto invalid;
220 while (isspace ((unsigned char) *end))
221 ++end;
222 if (*end != '\0')
223 goto invalid;
225 if ((int)value != value)
226 goto invalid;
228 if (value == 0 && (*schedule & ~GFS_MONOTONIC) != GFS_STATIC)
229 value = 1;
230 *chunk_size = value;
231 return true;
233 unknown:
234 print_env_var_error (env, val);
235 return false;
237 invalid:
238 char name[val - env];
239 memcpy (name, env, val - env - 1);
240 name[val - env - 1] = '\0';
241 gomp_error ("Invalid value for chunk size in "
242 "environment variable %s: %s", name, val);
243 return false;
246 /* Parse an unsigned long environment variable. Return true if one was
247 present and it was successfully parsed. If SECURE, use secure_getenv to the
248 environment variable. */
250 static bool
251 parse_unsigned_long_1 (const char *env, const char *val, unsigned long *pvalue,
252 bool allow_zero)
254 char *end;
255 unsigned long value;
257 if (val == NULL)
258 return false;
260 while (isspace ((unsigned char) *val))
261 ++val;
262 if (*val == '\0')
263 goto invalid;
265 errno = 0;
266 value = strtoul (val, &end, 10);
267 if (errno || end == val || (long) value <= 0 - allow_zero)
268 goto invalid;
270 while (isspace ((unsigned char) *end))
271 ++end;
272 if (*end != '\0')
273 goto invalid;
275 *pvalue = value;
276 return true;
278 invalid:
279 print_env_var_error (env, val);
280 return false;
283 /* As parse_unsigned_long_1, but always use getenv. */
285 static bool
286 parse_unsigned_long (const char *env, const char *val, void *const params[])
288 unsigned long upper = (uintptr_t) params[2];
289 unsigned long pvalue = 0;
290 bool ret = parse_unsigned_long_1 (env, val, &pvalue, (bool) params[1]);
291 if (!ret)
292 return false;
294 if (upper == 0)
295 *(unsigned long *) params[0] = pvalue;
296 else
298 if (pvalue > upper)
299 pvalue = upper;
300 if (upper <= UCHAR_MAX)
301 *(unsigned char *) params[0] = pvalue;
302 else if (upper <= UINT_MAX)
303 *(unsigned int *) params[0] = pvalue;
304 else
305 *(unsigned long *) params[0] = pvalue;
308 return ret;
311 /* Parse a positive int environment variable. Return true if one was
312 present and it was successfully parsed. If SECURE, use secure_getenv to the
313 environment variable. */
315 static bool
316 parse_int_1 (const char *env, const char *val, int *pvalue, bool allow_zero)
318 unsigned long value;
319 if (!parse_unsigned_long_1 (env, val, &value, allow_zero))
320 return false;
321 if (value > INT_MAX)
323 print_env_var_error (env, val);
324 return false;
326 *pvalue = (int) value;
327 return true;
330 static bool
331 parse_int (const char *env, const char *val, void *const params[])
333 return parse_int_1 (env, val, (int *) params[0], (bool) params[1]);
336 /* As parse_int_1, but use getenv_secure. */
338 static bool
339 parse_int_secure (const char *env, int *pvalue, bool allow_zero)
341 return parse_int_1 (env, secure_getenv (env), pvalue, allow_zero);
344 /* Parse an unsigned long list environment variable. Return true if one was
345 present and it was successfully parsed. */
347 static bool
348 parse_unsigned_long_list (const char *env, const char *val,
349 void *const params[])
351 unsigned long *p1stvalue = (unsigned long *) params[0];
352 unsigned long **pvalues = (unsigned long **) params[1];
353 unsigned long *pnvalues = (unsigned long *) params[2];
354 char *end;
355 unsigned long value, *values = NULL;
357 if (val == NULL)
358 return false;
360 while (isspace ((unsigned char) *val))
361 ++val;
362 if (*val == '\0')
363 goto invalid;
365 errno = 0;
366 value = strtoul (val, &end, 10);
367 if (errno || (long) value <= 0)
368 goto invalid;
370 while (isspace ((unsigned char) *end))
371 ++end;
372 if (*end != '\0')
374 if (*end == ',')
376 unsigned long nvalues = 0, nalloced = 0;
380 val = end + 1;
381 if (nvalues == nalloced)
383 unsigned long *n;
384 nalloced = nalloced ? nalloced * 2 : 16;
385 n = realloc (values, nalloced * sizeof (unsigned long));
386 if (n == NULL)
388 free (values);
389 char name[val - env];
390 memcpy (name, env, val - env - 1);
391 name[val - env - 1] = '\0';
392 gomp_error ("Out of memory while trying to parse"
393 " environment variable %s", name);
394 return false;
396 values = n;
397 if (nvalues == 0)
398 values[nvalues++] = value;
401 while (isspace ((unsigned char) *val))
402 ++val;
403 if (*val == '\0')
404 goto invalid;
406 errno = 0;
407 value = strtoul (val, &end, 10);
408 if (errno || (long) value <= 0)
409 goto invalid;
411 values[nvalues++] = value;
412 while (isspace ((unsigned char) *end))
413 ++end;
414 if (*end == '\0')
415 break;
416 if (*end != ',')
417 goto invalid;
419 while (1);
420 *p1stvalue = values[0];
421 *pvalues = values;
422 *pnvalues = nvalues;
423 return true;
425 goto invalid;
427 else
429 *pnvalues = 0;
430 *pvalues = NULL;
433 *p1stvalue = value;
434 return true;
436 invalid:
437 free (values);
438 print_env_var_error (env, val);
439 return false;
442 static bool
443 parse_target_offload (const char *env, const char *val, void *const params[])
445 int new_offload = -1;
447 if (val == NULL)
448 return false;
450 while (isspace ((unsigned char) *val))
451 ++val;
452 if (strncasecmp (val, "default", 7) == 0)
454 val += 7;
455 new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
457 else if (strncasecmp (val, "mandatory", 9) == 0)
459 val += 9;
460 new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
462 else if (strncasecmp (val, "disabled", 8) == 0)
464 val += 8;
465 new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
467 while (isspace ((unsigned char) *val))
468 ++val;
469 if (new_offload != -1 && *val == '\0')
471 *(enum gomp_target_offload_t *) params[0] = new_offload;
472 return true;
475 print_env_var_error (env, val);
476 return false;
479 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
480 enum values. Return true if one was present and it was successfully
481 parsed. */
483 static bool
484 parse_bind_var (const char *env, const char *val, void *const params[])
486 char *p1stvalue = (char *) params[0];
487 char **pvalues = (char **) params[1];
488 unsigned long *pnvalues = (unsigned long *) params[2];
489 char value = omp_proc_bind_false, *values = NULL;
490 int i;
491 static struct proc_bind_kinds
493 const char name[7];
494 const char len;
495 omp_proc_bind_t kind;
496 } kinds[] =
498 { "false", 5, omp_proc_bind_false },
499 { "true", 4, omp_proc_bind_true },
500 { "master", 6, omp_proc_bind_master },
501 { "primary", 7, omp_proc_bind_primary },
502 { "close", 5, omp_proc_bind_close },
503 { "spread", 6, omp_proc_bind_spread }
506 if (val == NULL)
507 return false;
509 while (isspace ((unsigned char) *val))
510 ++val;
511 if (*val == '\0')
512 goto invalid;
514 for (i = 0; i < 6; i++)
515 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
517 value = kinds[i].kind;
518 val += kinds[i].len;
519 break;
521 if (i == 6)
522 goto invalid;
524 while (isspace ((unsigned char) *val))
525 ++val;
526 if (*val != '\0')
528 if (*val == ',')
530 unsigned long nvalues = 0, nalloced = 0;
532 if (value == omp_proc_bind_false
533 || value == omp_proc_bind_true)
534 goto invalid;
538 val++;
539 if (nvalues == nalloced)
541 char *n;
542 nalloced = nalloced ? nalloced * 2 : 16;
543 n = realloc (values, nalloced);
544 if (n == NULL)
546 free (values);
547 char name[val - env];
548 memcpy (name, env, val - env - 1);
549 name[val - env - 1] = '\0';
550 gomp_error ("Out of memory while trying to parse"
551 " environment variable %s", name);
552 return false;
554 values = n;
555 if (nvalues == 0)
556 values[nvalues++] = value;
559 while (isspace ((unsigned char) *val))
560 ++val;
561 if (*val == '\0')
562 goto invalid;
564 for (i = 2; i < 6; i++)
565 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
567 value = kinds[i].kind;
568 val += kinds[i].len;
569 break;
571 if (i == 6)
572 goto invalid;
574 values[nvalues++] = value;
575 while (isspace ((unsigned char) *val))
576 ++val;
577 if (*val == '\0')
578 break;
579 if (*val != ',')
580 goto invalid;
582 while (1);
583 *p1stvalue = values[0];
584 *pvalues = values;
585 *pnvalues = nvalues;
586 return true;
588 goto invalid;
591 *p1stvalue = value;
592 return true;
594 invalid:
595 free (values);
596 print_env_var_error (env, val);
597 return false;
600 static bool
601 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
602 long *stridep)
604 char *env = *envp, *start;
605 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
606 unsigned long len = 1;
607 long stride = 1;
608 int pass;
609 bool any_negate = false;
610 bool has_braces = true;
611 *negatep = false;
612 while (isspace ((unsigned char) *env))
613 ++env;
614 if (*env == '!')
616 *negatep = true;
617 ++env;
618 while (isspace ((unsigned char) *env))
619 ++env;
621 if (*env != '{')
623 char *end;
624 unsigned long this_num;
626 errno = 0;
627 this_num = strtoul (env, &end, 10);
628 if (errno || end == env)
629 return false;
630 env = end - 1;
631 has_braces = false;
632 if (gomp_places_list
633 && !gomp_affinity_add_cpus (p, this_num, 1, 1, false))
634 return false;
636 else
638 ++env;
639 while (isspace ((unsigned char) *env))
640 ++env;
642 start = env;
643 for (pass = 0; pass < (any_negate ? 2 : has_braces); pass++)
645 env = start;
648 unsigned long this_num, this_len = 1;
649 long this_stride = 1;
650 bool this_negate = (*env == '!');
651 char *end;
652 if (this_negate)
654 if (gomp_places_list)
655 any_negate = true;
656 ++env;
657 while (isspace ((unsigned char) *env))
658 ++env;
661 errno = 0;
662 this_num = strtoul (env, &end, 10);
663 if (errno || end == env)
664 return false;
665 env = end;
666 while (isspace ((unsigned char) *env))
667 ++env;
668 if (*env == ':')
670 ++env;
671 if (this_negate)
672 return false;
673 while (isspace ((unsigned char) *env))
674 ++env;
675 errno = 0;
676 this_len = strtoul (env, &env, 10);
677 if (errno || this_len == 0)
678 return false;
679 while (isspace ((unsigned char) *env))
680 ++env;
681 if (*env == ':')
683 ++env;
684 while (isspace ((unsigned char) *env))
685 ++env;
686 errno = 0;
687 this_stride = strtol (env, &end, 10);
688 if (errno || end == env)
689 return false;
690 env = end;
691 while (isspace ((unsigned char) *env))
692 ++env;
695 if (gomp_places_list && pass == this_negate)
697 if (this_negate)
699 if (!gomp_affinity_remove_cpu (p, this_num))
700 return false;
702 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
703 this_stride, false))
704 return false;
706 if (*env == '}')
707 break;
708 if (*env != ',')
709 return false;
710 ++env;
712 while (1);
715 ++env;
716 while (isspace ((unsigned char) *env))
717 ++env;
718 if (*env == ':')
720 char *end;
721 if (*negatep)
722 return false;
723 ++env;
724 while (isspace ((unsigned char) *env))
725 ++env;
726 errno = 0;
727 len = strtoul (env, &env, 10);
728 if (errno || len == 0 || len >= 65536)
729 return false;
730 while (isspace ((unsigned char) *env))
731 ++env;
732 if (*env == ':')
734 ++env;
735 while (isspace ((unsigned char) *env))
736 ++env;
737 errno = 0;
738 stride = strtol (env, &end, 10);
739 if (errno || end == env)
740 return false;
741 env = end;
742 while (isspace ((unsigned char) *env))
743 ++env;
746 *envp = env;
747 *lenp = len;
748 *stridep = stride;
749 return true;
752 static bool
753 parse_places_var (const char *name, bool ignore)
755 char *env = getenv (name), *end;
756 bool any_negate = false;
757 int level = 0;
758 unsigned long count = 0;
759 if (env == NULL)
760 return false;
762 while (isspace ((unsigned char) *env))
763 ++env;
764 if (*env == '\0')
765 goto invalid;
767 if (strncasecmp (env, "threads", 7) == 0)
769 env += 7;
770 level = 1;
772 else if (strncasecmp (env, "cores", 5) == 0)
774 env += 5;
775 level = 2;
777 else if (strncasecmp (env, "sockets", 7) == 0)
779 env += 7;
780 level = 3;
782 else if (strncasecmp (env, "ll_caches", 9) == 0)
784 env += 9;
785 level = 4;
787 else if (strncasecmp (env, "numa_domains", 12) == 0)
789 env += 12;
790 level = 5;
792 if (level)
794 count = ULONG_MAX;
795 while (isspace ((unsigned char) *env))
796 ++env;
797 if (*env != '\0')
799 if (*env++ != '(')
800 goto invalid;
801 while (isspace ((unsigned char) *env))
802 ++env;
804 errno = 0;
805 count = strtoul (env, &end, 10);
806 if (errno || end == env)
807 goto invalid;
808 env = end;
809 while (isspace ((unsigned char) *env))
810 ++env;
811 if (*env != ')')
812 goto invalid;
813 ++env;
814 while (isspace ((unsigned char) *env))
815 ++env;
816 if (*env != '\0')
817 goto invalid;
820 if (ignore)
821 return false;
823 return gomp_affinity_init_level (level, count, false);
826 count = 0;
827 end = env;
830 bool negate;
831 unsigned long len;
832 long stride;
833 if (!parse_one_place (&end, &negate, &len, &stride))
834 goto invalid;
835 if (negate)
837 if (!any_negate)
838 count++;
839 any_negate = true;
841 else
842 count += len;
843 if (count > 65536)
844 goto invalid;
845 if (*end == '\0')
846 break;
847 if (*end != ',')
848 goto invalid;
849 end++;
851 while (1);
853 if (ignore)
854 return false;
856 gomp_places_list_len = 0;
857 gomp_places_list = gomp_affinity_alloc (count, false);
858 if (gomp_places_list == NULL)
859 return false;
863 bool negate;
864 unsigned long len;
865 long stride;
866 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
867 if (!parse_one_place (&env, &negate, &len, &stride))
868 goto invalid;
869 if (negate)
871 void *p;
872 for (count = 0; count < gomp_places_list_len; count++)
873 if (gomp_affinity_same_place
874 (gomp_places_list[count],
875 gomp_places_list[gomp_places_list_len]))
876 break;
877 if (count == gomp_places_list_len)
879 gomp_error ("Trying to remove a non-existing place from list "
880 "of places");
881 goto invalid;
883 p = gomp_places_list[count];
884 memmove (&gomp_places_list[count],
885 &gomp_places_list[count + 1],
886 (gomp_places_list_len - count - 1) * sizeof (void *));
887 --gomp_places_list_len;
888 gomp_places_list[gomp_places_list_len] = p;
890 else if (len == 1)
891 ++gomp_places_list_len;
892 else
894 for (count = 0; count < len - 1; count++)
895 if (!gomp_affinity_copy_place
896 (gomp_places_list[gomp_places_list_len + count + 1],
897 gomp_places_list[gomp_places_list_len + count],
898 stride))
899 goto invalid;
900 gomp_places_list_len += len;
902 if (*env == '\0')
903 break;
904 env++;
906 while (1);
908 if (gomp_places_list_len == 0)
910 gomp_error ("All places have been removed");
911 goto invalid;
913 if (!gomp_affinity_finalize_place_list (false))
914 goto invalid;
915 return true;
917 invalid:
918 free (gomp_places_list);
919 gomp_places_list = NULL;
920 gomp_places_list_len = 0;
921 gomp_error ("Invalid value for environment variable %s", name);
922 return false;
925 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
926 present and it was successfully parsed. */
928 static bool
929 parse_stacksize (const char *env, const char *val, void *const params[])
931 char *end;
932 unsigned long value, shift = 10;
934 if (val == NULL)
935 return false;
937 while (isspace ((unsigned char) *val))
938 ++val;
939 if (*val == '\0')
940 goto invalid;
942 errno = 0;
943 value = strtoul (val, &end, 10);
944 if (errno || end == val)
945 goto invalid;
947 while (isspace ((unsigned char) *end))
948 ++end;
949 if (*end != '\0')
951 switch (tolower ((unsigned char) *end))
953 case 'b':
954 shift = 0;
955 break;
956 case 'k':
957 break;
958 case 'm':
959 shift = 20;
960 break;
961 case 'g':
962 shift = 30;
963 break;
964 default:
965 goto invalid;
967 ++end;
968 while (isspace ((unsigned char) *end))
969 ++end;
970 if (*end != '\0')
971 goto invalid;
974 if (((value << shift) >> shift) != value)
975 goto invalid;
977 *(unsigned long *) params[0] = value << shift;
978 return true;
980 invalid:
981 print_env_var_error (env, val);
982 return false;
985 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
986 present and it was successfully parsed. */
988 static bool
989 parse_spincount (const char *name, unsigned long long *pvalue)
991 char *env, *end;
992 unsigned long long value, mult = 1;
994 env = getenv (name);
995 if (env == NULL)
996 return false;
998 while (isspace ((unsigned char) *env))
999 ++env;
1000 if (*env == '\0')
1001 goto invalid;
1003 if (strncasecmp (env, "infinite", 8) == 0
1004 || strncasecmp (env, "infinity", 8) == 0)
1006 value = ~0ULL;
1007 end = env + 8;
1008 goto check_tail;
1011 errno = 0;
1012 value = strtoull (env, &end, 10);
1013 if (errno || end == env)
1014 goto invalid;
1016 while (isspace ((unsigned char) *end))
1017 ++end;
1018 if (*end != '\0')
1020 switch (tolower ((unsigned char) *end))
1022 case 'k':
1023 mult = 1000LL;
1024 break;
1025 case 'm':
1026 mult = 1000LL * 1000LL;
1027 break;
1028 case 'g':
1029 mult = 1000LL * 1000LL * 1000LL;
1030 break;
1031 case 't':
1032 mult = 1000LL * 1000LL * 1000LL * 1000LL;
1033 break;
1034 default:
1035 goto invalid;
1037 ++end;
1038 check_tail:
1039 while (isspace ((unsigned char) *end))
1040 ++end;
1041 if (*end != '\0')
1042 goto invalid;
1045 if (value > ~0ULL / mult)
1046 value = ~0ULL;
1047 else
1048 value *= mult;
1050 *pvalue = value;
1051 return true;
1053 invalid:
1054 gomp_error ("Invalid value for environment variable %s", name);
1055 return false;
1058 /* Parse a boolean value for environment variable NAME and store the
1059 result in VALUE. Return true if one was present and it was
1060 successfully parsed. */
1061 static bool
1062 parse_boolean (const char *env, const char *val, void *const params[])
1064 bool *value = (bool *) params[0];
1066 if (val == NULL)
1067 return false;
1069 while (isspace ((unsigned char) *val))
1070 ++val;
1071 if (strncasecmp (val, "true", 4) == 0)
1073 *value = true;
1074 val += 4;
1076 else if (strncasecmp (val, "false", 5) == 0)
1078 *value = false;
1079 val += 5;
1081 else
1082 val = "X";
1083 while (isspace ((unsigned char) *val))
1084 ++val;
1085 if (*val != '\0')
1087 print_env_var_error (env, val);
1088 return false;
1090 return true;
1093 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1095 static bool
1096 parse_wait_policy (const char *env, const char *val, void *const params[])
1098 int *pvalue = (int *) params[0];
1099 int ret = -1;
1101 if (val == NULL)
1103 *pvalue = -1;
1104 return false;
1107 while (isspace ((unsigned char) *val))
1108 ++val;
1109 if (strncasecmp (val, "active", 6) == 0)
1111 ret = 1;
1112 val += 6;
1114 else if (strncasecmp (val, "passive", 7) == 0)
1116 ret = 0;
1117 val += 7;
1119 else
1120 val = "X";
1121 while (isspace ((unsigned char) *val))
1122 ++val;
1123 if (*val == '\0')
1125 *pvalue = ret;
1126 return true;
1128 print_env_var_error (env, val);
1129 *pvalue = -1;
1130 return false;
1133 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1134 present and it was successfully parsed. */
1136 static bool
1137 parse_affinity (bool ignore)
1139 char *env, *end, *start;
1140 int pass;
1141 unsigned long cpu_beg, cpu_end, cpu_stride;
1142 size_t count = 0, needed;
1144 env = getenv ("GOMP_CPU_AFFINITY");
1145 if (env == NULL)
1146 return false;
1148 start = env;
1149 for (pass = 0; pass < 2; pass++)
1151 env = start;
1152 if (pass == 1)
1154 if (ignore)
1155 return false;
1157 gomp_places_list_len = 0;
1158 gomp_places_list = gomp_affinity_alloc (count, true);
1159 if (gomp_places_list == NULL)
1160 return false;
1164 while (isspace ((unsigned char) *env))
1165 ++env;
1167 errno = 0;
1168 cpu_beg = strtoul (env, &end, 0);
1169 if (errno || end == env || cpu_beg >= 65536)
1170 goto invalid;
1171 cpu_end = cpu_beg;
1172 cpu_stride = 1;
1174 env = end;
1175 if (*env == '-')
1177 errno = 0;
1178 cpu_end = strtoul (++env, &end, 0);
1179 if (errno || end == env || cpu_end >= 65536 || cpu_end < cpu_beg)
1180 goto invalid;
1182 env = end;
1183 if (*env == ':')
1185 errno = 0;
1186 cpu_stride = strtoul (++env, &end, 0);
1187 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1188 goto invalid;
1190 env = end;
1194 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1195 if (pass == 0)
1196 count += needed;
1197 else
1199 while (needed--)
1201 void *p = gomp_places_list[gomp_places_list_len];
1202 gomp_affinity_init_place (p);
1203 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1204 ++gomp_places_list_len;
1205 cpu_beg += cpu_stride;
1209 while (isspace ((unsigned char) *env))
1210 ++env;
1212 if (*env == ',')
1213 env++;
1214 else if (*env == '\0')
1215 break;
1217 while (1);
1220 if (gomp_places_list_len == 0)
1222 free (gomp_places_list);
1223 gomp_places_list = NULL;
1224 return false;
1226 return true;
1228 invalid:
1229 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1230 return false;
1233 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1234 static bool
1235 parse_allocator (const char *env, const char *val, void *const params[])
1237 const char *orig_val = val;
1238 uintptr_t *ret = (uintptr_t *) params[0];
1239 *ret = omp_default_mem_alloc;
1240 bool memspace = false;
1241 size_t ntraits = 0;
1242 omp_alloctrait_t *traits;
1244 if (val == NULL)
1245 return false;
1247 while (isspace ((unsigned char) *val))
1248 ++val;
1249 if (0)
1251 #define C(v, m) \
1252 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1254 *ret = v; \
1255 val += sizeof (#v) - 1; \
1256 memspace = m; \
1258 C (omp_default_mem_alloc, false)
1259 C (omp_large_cap_mem_alloc, false)
1260 C (omp_const_mem_alloc, false)
1261 C (omp_high_bw_mem_alloc, false)
1262 C (omp_low_lat_mem_alloc, false)
1263 C (omp_cgroup_mem_alloc, false)
1264 C (omp_pteam_mem_alloc, false)
1265 C (omp_thread_mem_alloc, false)
1266 C (omp_default_mem_space, true)
1267 C (omp_large_cap_mem_space, true)
1268 C (omp_const_mem_space, true)
1269 C (omp_high_bw_mem_space, true)
1270 C (omp_low_lat_mem_space, true)
1271 #undef C
1272 else
1273 goto invalid;
1274 if (memspace && *val == ':')
1276 ++val;
1277 const char *cp = val;
1278 while (*cp != '\0')
1280 if (*cp == '=')
1281 ++ntraits;
1282 ++cp;
1284 traits = gomp_alloca (ntraits * sizeof (omp_alloctrait_t));
1285 size_t n = 0;
1286 while (*val != '\0')
1288 #define C(v) \
1289 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1291 val += sizeof (#v); \
1292 traits[n].key = omp_atk_ ## v;
1293 #define V(v) \
1294 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1296 val += sizeof (#v) - 1; \
1297 traits[n].value = omp_atv_ ## v; \
1299 if (0)
1301 C (sync_hint)
1302 if (0)
1304 V (contended)
1305 V (uncontended)
1306 V (serialized)
1307 V (private)
1308 else
1309 goto invalid;
1311 C (alignment)
1312 char *end;
1313 errno = 0;
1314 traits[n].value = strtol (val, &end, 10);
1315 if (errno || end == val || traits[n].value <= 0)
1316 goto invalid;
1317 val = end;
1319 C (access)
1320 if (0)
1322 V (all)
1323 V (cgroup)
1324 V (pteam)
1325 V (thread)
1326 else
1327 goto invalid;
1329 C (pool_size)
1330 char *end;
1331 errno = 0;
1332 traits[n].value = strtol (val, &end, 10);
1333 if (errno || end == val || traits[n].value <= 0)
1334 goto invalid;
1335 val = end;
1337 C (fallback)
1338 if (0)
1340 V (default_mem_fb)
1341 V (null_fb)
1342 V (abort_fb)
1343 V (allocator_fb)
1344 else
1345 goto invalid;
1347 /* Ignore fb_data, which expects an allocator handle. */
1348 C (pinned)
1349 if (0)
1351 V (true)
1352 V (false)
1353 else
1354 goto invalid;
1356 C (partition)
1357 if (0)
1359 V (environment)
1360 V (nearest)
1361 V (blocked)
1362 V (interleaved)
1363 else
1364 goto invalid;
1366 else
1367 goto invalid;
1368 if (*val != ',')
1369 break;
1370 ++val;
1371 ++n;
1372 if (*val == '\0')
1373 goto invalid;
1375 #undef C
1376 #undef V
1378 else if (memspace)
1379 switch (*ret)
1381 case omp_default_mem_space: *ret = omp_default_mem_alloc; break;
1382 case omp_large_cap_mem_space: *ret = omp_large_cap_mem_alloc; break;
1383 case omp_const_mem_space: *ret = omp_const_mem_alloc; break;
1384 case omp_high_bw_mem_space: *ret = omp_high_bw_mem_alloc; break;
1385 case omp_low_lat_mem_space: *ret = omp_low_lat_mem_alloc; break;
1386 default: __builtin_unreachable ();
1388 while (isspace ((unsigned char) *val))
1389 ++val;
1390 if (*val == '\0')
1392 if (ntraits)
1394 *ret = omp_init_allocator (*ret, ntraits, traits);
1395 if (*ret == omp_null_allocator)
1397 gomp_error ("Allocator of environment variable %.*s cannot be "
1398 "created, using omp_default_mem_alloc instead",
1399 (int) (orig_val - env - 1), env);
1400 *ret = omp_default_mem_alloc;
1402 else
1403 gomp_def_allocator_envvar = strdup (orig_val);
1405 return true;
1407 invalid:
1408 int len = (orig_val - env - 1);
1409 if (*val == '\0')
1410 gomp_error ("Missing value at the end of environment variable %s", env);
1411 else
1412 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1413 len, env, val);
1414 *ret = omp_default_mem_alloc;
1415 return false;
1418 static void
1419 parse_acc_device_type (void)
1421 const char *env = getenv ("ACC_DEVICE_TYPE");
1423 if (env && *env != '\0')
1424 goacc_device_type = strdup (env);
1425 else
1426 goacc_device_type = NULL;
1429 static void
1430 parse_gomp_openacc_dim (void)
1432 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1433 const char *var_name = "GOMP_OPENACC_DIM";
1434 const char *env_var = getenv (var_name);
1435 const char *pos = env_var;
1436 int i;
1438 if (!env_var)
1439 return;
1441 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1443 char *eptr;
1444 long val;
1446 if (i && *pos++ != ':')
1447 break;
1449 if (*pos == ':')
1450 continue;
1452 errno = 0;
1453 val = strtol (pos, &eptr, 10);
1454 if (errno || eptr == pos || val < 0 || (unsigned)val != val)
1455 break;
1457 goacc_default_dims[i] = (int)val;
1458 pos = (const char *) eptr;
1462 /* Helper function for omp_display_env which prints the values of run_sched_var.
1463 'device' can be 'host', 'dev', 'all' or a particular device number. */
1465 static void
1466 print_schedule (enum gomp_schedule_type run_sched_var, int run_sched_chunk_size,
1467 const char *device)
1469 fprintf (stderr, " [%s] OMP_SCHEDULE = '", device);
1470 if ((run_sched_var & GFS_MONOTONIC))
1472 if (run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1473 fputs ("MONOTONIC:", stderr);
1475 else if (run_sched_var == GFS_STATIC)
1476 fputs ("NONMONOTONIC:", stderr);
1477 switch (run_sched_var & ~GFS_MONOTONIC)
1479 case GFS_RUNTIME:
1480 fputs ("RUNTIME", stderr);
1481 if (run_sched_chunk_size != 1)
1482 fprintf (stderr, ",%d", run_sched_chunk_size);
1483 break;
1484 case GFS_STATIC:
1485 fputs ("STATIC", stderr);
1486 if (run_sched_chunk_size != 0)
1487 fprintf (stderr, ",%d", run_sched_chunk_size);
1488 break;
1489 case GFS_DYNAMIC:
1490 fputs ("DYNAMIC", stderr);
1491 if (run_sched_chunk_size != 1)
1492 fprintf (stderr, ",%d", run_sched_chunk_size);
1493 break;
1494 case GFS_GUIDED:
1495 fputs ("GUIDED", stderr);
1496 if (run_sched_chunk_size != 1)
1497 fprintf (stderr, ",%d", run_sched_chunk_size);
1498 break;
1499 case GFS_AUTO:
1500 fputs ("AUTO", stderr);
1501 break;
1503 fputs ("'\n", stderr);
1506 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1507 'device' can be 'host', 'dev', 'all', or a particular device number. */
1509 static void
1510 print_proc_bind (char proc_bind_var, unsigned long len, char **list,
1511 const char *device)
1513 fprintf (stderr, " [%s] OMP_PROC_BIND = '", device);
1514 switch (proc_bind_var)
1516 case omp_proc_bind_false:
1517 fputs ("FALSE", stderr);
1518 break;
1519 case omp_proc_bind_true:
1520 fputs ("TRUE", stderr);
1521 break;
1522 case omp_proc_bind_master:
1523 fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1524 break;
1525 case omp_proc_bind_close:
1526 fputs ("CLOSE", stderr);
1527 break;
1528 case omp_proc_bind_spread:
1529 fputs ("SPREAD", stderr);
1530 break;
1532 for (int i = 1; i < len; i++)
1533 switch ((*list)[i])
1535 case omp_proc_bind_master:
1536 fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1537 break;
1538 case omp_proc_bind_close:
1539 fputs (",CLOSE", stderr);
1540 break;
1541 case omp_proc_bind_spread:
1542 fputs (",SPREAD", stderr);
1543 break;
1545 fputs ("'\n", stderr);
1548 enum gomp_parse_type
1550 PARSE_INT = 1,
1551 PARSE_BOOL = 2,
1552 PARSE_UINT = 3,
1553 PARSE_ULONG = 4,
1554 PARSE_UCHAR = 5,
1555 PARSE_SCHEDULE =6,
1556 PARSE_BIND = 7
1559 /* The following table contains items that help parsing environment variables
1560 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1561 are affected by the environment variable. FLAGS determine what variant of
1562 environment variable is allowed. */
1564 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1565 static const struct envvar
1567 const char *name;
1568 int name_len;
1569 uint8_t flag_vars[3];
1570 uint8_t flag;
1571 bool (*parse_func) (const char *, const char *, void *const[]);
1572 } envvars[] = {
1573 { ENTRY ("SCHEDULE"),
1574 { GOMP_ICV_SCHEDULE, GOMP_ICV_SCHEDULE_CHUNK_SIZE },
1575 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1576 &parse_schedule },
1577 { ENTRY ("NUM_TEAMS"),
1578 { GOMP_ICV_NTEAMS },
1579 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1580 &parse_int },
1581 { ENTRY ("DYNAMIC"),
1582 { GOMP_ICV_DYNAMIC },
1583 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1584 &parse_boolean },
1585 { ENTRY ("TEAMS_THREAD_LIMIT"),
1586 { GOMP_ICV_TEAMS_THREAD_LIMIT },
1587 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1588 &parse_int },
1589 { ENTRY ("THREAD_LIMIT"),
1590 { GOMP_ICV_THREAD_LIMIT },
1591 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1592 &parse_unsigned_long },
1593 { ENTRY ("NUM_THREADS"),
1594 { GOMP_ICV_NTHREADS, GOMP_ICV_NTHREADS_LIST, GOMP_ICV_NTHREADS_LIST_LEN },
1595 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1596 &parse_unsigned_long_list },
1597 { ENTRY ("PROC_BIND"),
1598 { GOMP_ICV_BIND, GOMP_ICV_BIND_LIST, GOMP_ICV_BIND_LIST_LEN },
1599 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1600 &parse_bind_var },
1601 { ENTRY ("MAX_ACTIVE_LEVELS"),
1602 { GOMP_ICV_MAX_ACTIVE_LEVELS },
1603 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1604 &parse_unsigned_long },
1605 { ENTRY ("WAIT_POLICY"),
1606 { GOMP_ICV_WAIT_POLICY },
1607 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1608 &parse_wait_policy },
1609 { ENTRY ("STACKSIZE"),
1610 { GOMP_ICV_STACKSIZE },
1611 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1612 &parse_stacksize },
1613 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION }, 0, &parse_boolean },
1614 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY }, 0,
1615 &parse_boolean },
1616 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD }, 0,
1617 &parse_target_offload },
1618 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY }, 0,
1619 &parse_int },
1620 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR }, 0, &parse_allocator },
1621 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE },
1622 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1623 &parse_int }
1625 #undef ENTRY
1626 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1628 /* The following table is used to apply the hierarchy of ICV variants for host
1629 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1630 undefined. */
1632 static const struct host_envvar
1634 unsigned char flag_var;
1635 void *dest[3];
1636 int type_code;
1637 } host_envvars[] = {
1638 { GOMP_ICV_NTEAMS, { &gomp_nteams_var }, PARSE_INT },
1639 { GOMP_ICV_DYNAMIC, { &gomp_global_icv.dyn_var }, PARSE_BOOL },
1640 { GOMP_ICV_DEFAULT_DEVICE, { &gomp_global_icv.default_device_var },
1641 PARSE_INT },
1642 { GOMP_ICV_TEAMS_THREAD_LIMIT, { &gomp_teams_thread_limit_var }, PARSE_INT },
1643 { GOMP_ICV_SCHEDULE,
1644 { &gomp_global_icv.run_sched_var, &gomp_global_icv.run_sched_chunk_size },
1645 PARSE_SCHEDULE },
1646 { GOMP_ICV_THREAD_LIMIT, { &gomp_global_icv.thread_limit_var }, PARSE_UINT },
1647 { GOMP_ICV_NTHREADS,
1648 { &gomp_global_icv.nthreads_var, &gomp_nthreads_var_list,
1649 &gomp_nthreads_var_list_len }, PARSE_ULONG },
1650 { GOMP_ICV_BIND,
1651 { &gomp_global_icv.bind_var, &gomp_bind_var_list, &gomp_bind_var_list_len },
1652 PARSE_BIND },
1653 { GOMP_ICV_MAX_ACTIVE_LEVELS, { &gomp_global_icv.max_active_levels_var },
1654 PARSE_UCHAR },
1656 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1658 #define INT_MAX_STR_LEN 10
1660 bool
1661 gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv)
1663 return value & (1 << (icv - 1));
1666 static void
1667 gomp_set_icv_flag (uint32_t *value, enum gomp_icvs icv)
1669 *value |= 1 << (icv - 1);
1672 static void
1673 print_device_specific_icvs (int icv_code)
1675 struct gomp_icv_list *list = gomp_initial_icv_list;
1676 int i;
1677 char dev_num[INT_MAX_STR_LEN + 1];
1679 while (list != NULL)
1681 if (list->device_num < 0)
1683 list = list->next;
1684 continue;
1687 switch (icv_code)
1689 case GOMP_ICV_NTEAMS:
1690 if (gomp_get_icv_flag (list->flags, GOMP_ICV_NTEAMS))
1691 fprintf (stderr, " [%d] OMP_NUM_TEAMS = '%d'\n",
1692 list->device_num, list->icvs.nteams_var);
1693 break;
1694 case GOMP_ICV_DYNAMIC:
1695 if (gomp_get_icv_flag (list->flags, GOMP_ICV_DYNAMIC))
1696 fprintf (stderr, " [%d] OMP_DYNAMIC = '%s'\n",
1697 list->device_num, list->icvs.dyn_var ? "TRUE" : "FALSE");
1698 break;
1699 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1700 if (gomp_get_icv_flag (list->flags, GOMP_ICV_TEAMS_THREAD_LIMIT))
1701 fprintf (stderr, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1702 list->device_num, list->icvs.teams_thread_limit_var);
1703 break;
1704 case GOMP_ICV_SCHEDULE:
1705 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_SCHEDULE)))
1706 break;
1707 sprintf (dev_num, "%d", list->device_num);
1708 print_schedule (list->icvs.run_sched_var,
1709 list->icvs.run_sched_chunk_size,
1710 dev_num);
1711 break;
1712 case GOMP_ICV_THREAD_LIMIT:
1713 if (gomp_get_icv_flag (list->flags, GOMP_ICV_THREAD_LIMIT))
1714 fprintf (stderr, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1715 list->device_num, list->icvs.thread_limit_var);
1716 break;
1717 case GOMP_ICV_NTHREADS:
1718 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_NTHREADS)))
1719 break;
1720 fprintf (stderr, " [%d] OMP_NUM_THREADS = '%lu", list->device_num,
1721 list->icvs.nthreads_var);
1722 for (i = 1; i < list->icvs.nthreads_var_list_len; i++)
1723 fprintf (stderr, ",%lu", list->icvs.nthreads_var_list[i]);
1724 fputs ("'\n", stderr);
1725 break;
1726 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1727 fprintf (stderr, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1728 list->device_num, list->icvs.max_active_levels_var);
1729 break;
1730 case GOMP_ICV_BIND:
1731 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_BIND)))
1732 break;
1733 sprintf (dev_num, "%d", list->device_num);
1734 print_proc_bind (list->icvs.bind_var, list->icvs.bind_var_list_len,
1735 &list->icvs.bind_var_list, dev_num);
1736 break;
1737 case GOMP_ICV_WAIT_POLICY:
1738 if (gomp_get_icv_flag (list->flags, GOMP_ICV_WAIT_POLICY))
1739 fprintf (stderr, " [%d] OMP_WAIT_POLICY = '%s'\n",
1740 list->device_num,
1741 list->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1742 break;
1743 case GOMP_ICV_STACKSIZE:
1744 if (gomp_get_icv_flag (list->flags, GOMP_ICV_STACKSIZE))
1745 fprintf (stderr, " [%d] OMP_STACKSIZE = '%lu'\n",
1746 list->device_num, list->icvs.stacksize);
1747 break;
1749 list = list->next;
1753 void
1754 omp_display_env (int verbose)
1756 int i;
1757 struct gomp_icv_list *dev
1758 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV);
1759 struct gomp_icv_list *all
1760 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
1761 struct gomp_icv_list *none
1762 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
1764 if (none->icvs.default_device_var == INT_MIN)
1765 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1766 gomp_init_targets_once ();
1768 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1770 fputs (" _OPENMP = '201511'\n", stderr);
1772 fprintf (stderr, " [host] OMP_DYNAMIC = '%s'\n",
1773 none->icvs.dyn_var ? "TRUE" : "FALSE");
1774 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_DYNAMIC))
1775 fprintf (stderr, " [all] OMP_DYNAMIC = '%s'\n",
1776 all->icvs.dyn_var ? "TRUE" : "FALSE");
1777 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_DYNAMIC))
1778 fprintf (stderr, " [device] OMP_DYNAMIC = '%s'\n",
1779 dev->icvs.dyn_var ? "TRUE" : "FALSE");
1780 print_device_specific_icvs (GOMP_ICV_DYNAMIC);
1782 /* The OMP_NESTED environment variable has been deprecated. */
1783 fprintf (stderr, " [host] OMP_NESTED = '%s'\n",
1784 none->icvs.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1786 fprintf (stderr, " [host] OMP_NUM_THREADS = '%lu",
1787 none->icvs.nthreads_var);
1788 for (i = 1; i < none->icvs.nthreads_var_list_len; i++)
1789 fprintf (stderr, ",%lu", none->icvs.nthreads_var_list[i]);
1790 fputs ("'\n", stderr);
1791 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTHREADS))
1793 fprintf (stderr, " [all] OMP_NUM_THREADS = '%lu",
1794 all->icvs.nthreads_var);
1795 for (i = 1; i < all->icvs.nthreads_var_list_len; i++)
1796 fprintf (stderr, ",%lu", all->icvs.nthreads_var_list[i]);
1797 fputs ("'\n", stderr);
1799 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTHREADS))
1801 fprintf (stderr, " [device] OMP_NUM_THREADS = '%lu",
1802 dev->icvs.nthreads_var);
1803 for (i = 1; i < dev->icvs.nthreads_var_list_len; i++)
1804 fprintf (stderr, ",%lu", dev->icvs.nthreads_var_list[i]);
1805 fputs ("'\n", stderr);
1807 print_device_specific_icvs (GOMP_ICV_NTHREADS);
1810 print_schedule (none->icvs.run_sched_var,
1811 none->icvs.run_sched_chunk_size, "host");
1812 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_SCHEDULE))
1813 print_schedule (all->icvs.run_sched_var,
1814 all->icvs.run_sched_chunk_size, "all");
1815 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_SCHEDULE))
1816 print_schedule (dev->icvs.run_sched_var,
1817 dev->icvs.run_sched_chunk_size, "device");
1818 print_device_specific_icvs (GOMP_ICV_SCHEDULE);
1820 print_proc_bind (none->icvs.bind_var,
1821 none->icvs.bind_var_list_len,
1822 &none->icvs.bind_var_list, "host");
1823 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND))
1824 print_proc_bind (all->icvs.bind_var,
1825 all->icvs.bind_var_list_len,
1826 &all->icvs.bind_var_list, "all");
1827 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_BIND))
1828 print_proc_bind (dev->icvs.bind_var,
1829 dev->icvs.bind_var_list_len,
1830 &dev->icvs.bind_var_list, "device");
1831 print_device_specific_icvs (GOMP_ICV_BIND);
1833 fputs (" [host] OMP_PLACES = '", stderr);
1834 for (i = 0; i < gomp_places_list_len; i++)
1836 fputs ("{", stderr);
1837 gomp_affinity_print_place (gomp_places_list[i]);
1838 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1840 fputs ("'\n", stderr);
1842 fprintf (stderr, " [host] OMP_STACKSIZE = '%lu'\n",
1843 none->icvs.stacksize);
1844 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
1845 fprintf (stderr, " [all] OMP_STACKSIZE = '%lu'\n",
1846 all->icvs.stacksize);
1847 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_STACKSIZE))
1848 fprintf (stderr, " [device] OMP_STACKSIZE = '%lu'\n",
1849 dev->icvs.stacksize);
1850 print_device_specific_icvs (GOMP_ICV_STACKSIZE);
1852 /* GOMP's default value is actually neither active nor passive. */
1853 fprintf (stderr, " [host] OMP_WAIT_POLICY = '%s'\n",
1854 none->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1855 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
1856 fprintf (stderr, " [all] OMP_WAIT_POLICY = '%s'\n",
1857 all->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1858 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_WAIT_POLICY))
1859 fprintf (stderr, " [device] OMP_WAIT_POLICY = '%s'\n",
1860 dev->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1861 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY);
1863 fprintf (stderr, " [host] OMP_THREAD_LIMIT = '%u'\n",
1864 none->icvs.thread_limit_var);
1865 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_THREAD_LIMIT))
1866 fprintf (stderr, " [all] OMP_THREAD_LIMIT = '%d'\n",
1867 all->icvs.thread_limit_var);
1868 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_THREAD_LIMIT))
1869 fprintf (stderr, " [device] OMP_THREAD_LIMIT = '%d'\n",
1870 dev->icvs.thread_limit_var);
1871 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT);
1873 fprintf (stderr, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1874 none->icvs.max_active_levels_var);
1875 if (all != NULL && gomp_get_icv_flag (all->flags,
1876 GOMP_ICV_MAX_ACTIVE_LEVELS))
1877 fprintf (stderr, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1878 all->icvs.max_active_levels_var);
1879 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1880 GOMP_ICV_MAX_ACTIVE_LEVELS))
1881 fprintf (stderr, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1882 dev->icvs.max_active_levels_var);
1883 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS);
1886 fprintf (stderr, " [host] OMP_NUM_TEAMS = '%d'\n",
1887 none->icvs.nteams_var);
1888 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTEAMS))
1889 fprintf (stderr, " [all] OMP_NUM_TEAMS = '%d'\n",
1890 all->icvs.nteams_var);
1891 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTEAMS))
1892 fprintf (stderr, " [device] OMP_NUM_TEAMS = '%d'\n",
1893 dev->icvs.nteams_var);
1894 print_device_specific_icvs (GOMP_ICV_NTEAMS);
1896 fprintf (stderr, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1897 none->icvs.teams_thread_limit_var);
1898 if (all != NULL && gomp_get_icv_flag (all->flags,
1899 GOMP_ICV_TEAMS_THREAD_LIMIT))
1900 fprintf (stderr, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1901 all->icvs.teams_thread_limit_var);
1902 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1903 GOMP_ICV_TEAMS_THREAD_LIMIT))
1904 fprintf (stderr, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1905 dev->icvs.teams_thread_limit_var);
1906 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT);
1908 fprintf (stderr, " [all] OMP_CANCELLATION = '%s'\n",
1909 gomp_cancel_var ? "TRUE" : "FALSE");
1911 fprintf (stderr, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1912 none->icvs.default_device_var);
1914 fprintf (stderr, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1915 gomp_max_task_priority_var);
1916 fprintf (stderr, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1917 gomp_display_affinity_var ? "TRUE" : "FALSE");
1918 fprintf (stderr, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1919 gomp_affinity_format_var);
1920 fprintf (stderr, " [host] OMP_ALLOCATOR = '");
1921 switch (gomp_def_allocator)
1923 #define C(v) case v: fputs (#v, stderr); break;
1924 C (omp_default_mem_alloc)
1925 C (omp_large_cap_mem_alloc)
1926 C (omp_const_mem_alloc)
1927 C (omp_high_bw_mem_alloc)
1928 C (omp_low_lat_mem_alloc)
1929 C (omp_cgroup_mem_alloc)
1930 C (omp_pteam_mem_alloc)
1931 C (omp_thread_mem_alloc)
1932 #undef C
1933 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1934 default:
1935 if (gomp_def_allocator_envvar)
1936 fputs (gomp_def_allocator_envvar, stderr);
1937 break;
1939 fputs ("'\n", stderr);
1941 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr);
1942 switch (gomp_target_offload_var)
1944 case GOMP_TARGET_OFFLOAD_DEFAULT:
1945 fputs ("DEFAULT", stderr);
1946 break;
1947 case GOMP_TARGET_OFFLOAD_MANDATORY:
1948 fputs ("MANDATORY", stderr);
1949 break;
1950 case GOMP_TARGET_OFFLOAD_DISABLED:
1951 fputs ("DISABLED", stderr);
1952 break;
1954 fputs ("'\n", stderr);
1956 if (verbose)
1958 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr);
1959 fprintf (stderr, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize);
1960 #ifdef HAVE_INTTYPES_H
1961 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%"PRIu64"'\n",
1962 (uint64_t) gomp_spin_count_var);
1963 #else
1964 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%lu'\n",
1965 (unsigned long) gomp_spin_count_var);
1966 #endif
1969 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1971 ialias (omp_display_env)
1973 static void
1974 handle_omp_display_env (void)
1976 const char *env;
1977 bool display = false;
1978 bool verbose = false;
1980 env = getenv ("OMP_DISPLAY_ENV");
1981 if (env == NULL)
1982 return;
1984 while (isspace ((unsigned char) *env))
1985 ++env;
1986 if (strncasecmp (env, "true", 4) == 0)
1988 display = true;
1989 env += 4;
1991 else if (strncasecmp (env, "false", 5) == 0)
1993 display = false;
1994 env += 5;
1996 else if (strncasecmp (env, "verbose", 7) == 0)
1998 display = true;
1999 verbose = true;
2000 env += 7;
2002 else
2003 env = "X";
2004 while (isspace ((unsigned char) *env))
2005 ++env;
2006 if (*env != '\0')
2007 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2009 if (display)
2010 ialias_call (omp_display_env) (verbose);
2013 /* Helper function for initialize_env. Extracts the device number from
2014 an environment variable name. ENV is the complete environment variable.
2015 DEV_NUM_PTR points to the start of the device number in the environment
2016 variable string. DEV_NUM_LEN is the returned length of the device num
2017 string. */
2019 static bool
2020 get_device_num (char *env, char *dev_num_ptr, int *dev_num, int *dev_num_len)
2022 char *end;
2023 unsigned long val = strtoul (dev_num_ptr, &end, 10);
2024 if (val > INT_MAX
2025 || *end != '='
2026 || (dev_num_ptr[0] == '0' && end != dev_num_ptr + 1)
2027 || (dev_num_ptr[0] < '0' || dev_num_ptr[0] > '9'))
2029 gomp_error ("Invalid device number in %s", env);
2030 return false;
2032 *dev_num = val;
2033 *dev_num_len = end - dev_num_ptr;
2034 return true;
2037 static void
2038 get_icv_member_addr (struct gomp_initial_icvs *icvs, int icv_code,
2039 void *icv_addr[3])
2041 if (icv_code == 0 || icv_addr == NULL)
2042 return;
2044 icv_addr[0] = icv_addr[1] = icv_addr[2] = NULL;
2046 switch (icv_code)
2048 case GOMP_ICV_NTEAMS:
2049 icv_addr[0] = &icvs->nteams_var;
2050 /* icv_addr[1] = (void *) false; */
2051 break;
2052 case GOMP_ICV_DYNAMIC:
2053 icv_addr[0] = &(*icvs).dyn_var;
2054 break;
2055 case GOMP_ICV_TEAMS_THREAD_LIMIT:
2056 icv_addr[0] = &icvs->teams_thread_limit_var;
2057 /* icv_addr[1] = (void *) false; */
2058 break;
2059 case GOMP_ICV_SCHEDULE:
2060 icv_addr[0] = &icvs->run_sched_var;
2061 icv_addr[1] = &icvs->run_sched_chunk_size;
2062 break;
2063 case GOMP_ICV_THREAD_LIMIT:
2064 icv_addr[0] = &icvs->thread_limit_var;
2065 /* icv_addr[1] = (void *) false; */
2066 icv_addr[2] = (void *) UINT_MAX;
2067 break;
2068 case GOMP_ICV_NTHREADS:
2069 icv_addr[0] = &icvs->nthreads_var;
2070 icv_addr[1] = &icvs->nthreads_var_list;
2071 icv_addr[2] = &icvs->nthreads_var_list_len;
2072 break;
2073 case GOMP_ICV_MAX_ACTIVE_LEVELS:
2074 icv_addr[0] = &icvs->max_active_levels_var;
2075 icv_addr[1] = (void *) true;
2076 icv_addr[2] = (void *) gomp_supported_active_levels;
2077 break;
2078 case GOMP_ICV_BIND:
2079 icv_addr[0] = &icvs->bind_var;
2080 icv_addr[1] = &icvs->bind_var_list;
2081 icv_addr[2] = &icvs->bind_var_list_len;
2082 break;
2083 case GOMP_ICV_WAIT_POLICY:
2084 icv_addr[0] = &icvs->wait_policy;
2085 break;
2086 case GOMP_ICV_STACKSIZE:
2087 icv_addr[0] = &icvs->stacksize;
2088 break;
2089 case GOMP_ICV_CANCELLATION:
2090 icv_addr[0] = &gomp_cancel_var;
2091 break;
2092 case GOMP_ICV_DISPLAY_AFFINITY:
2093 icv_addr[0] = &gomp_display_affinity_var;
2094 break;
2095 case GOMP_ICV_TARGET_OFFLOAD:
2096 icv_addr[0] = &gomp_target_offload_var;
2097 break;
2098 case GOMP_ICV_MAX_TASK_PRIORITY:
2099 icv_addr[0] = &gomp_max_task_priority_var;
2100 break;
2101 case GOMP_ICV_ALLOCATOR:
2102 icv_addr[0] = &gomp_def_allocator;
2103 break;
2104 case GOMP_ICV_DEFAULT_DEVICE:
2105 icv_addr[0] = &icvs->default_device_var;
2106 icv_addr[1] = (void *) true;
2107 break;
2111 struct gomp_icv_list *
2112 gomp_get_initial_icv_item (int dev_num)
2114 struct gomp_icv_list *l = gomp_initial_icv_list;
2115 while (l != NULL && l->device_num != dev_num)
2116 l = l->next;
2118 return l;
2121 static void
2122 initialize_icvs (struct gomp_initial_icvs *icvs)
2124 icvs->nthreads_var_list = NULL;
2125 icvs->bind_var_list = NULL;
2126 icvs->nthreads_var = gomp_default_icv_values.nthreads_var;
2127 icvs->nthreads_var_list_len = 0;
2128 icvs->bind_var_list_len = 0;
2129 icvs->stacksize = 0;
2130 icvs->thread_limit_var = gomp_default_icv_values.thread_limit_var;
2131 icvs->run_sched_var = gomp_default_icv_values.run_sched_var;
2132 icvs->run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size;
2133 icvs->default_device_var = gomp_default_icv_values.default_device_var;
2134 icvs->dyn_var = gomp_default_icv_values.dyn_var;
2135 icvs->max_active_levels_var = gomp_default_icv_values.max_active_levels_var;
2136 icvs->bind_var = gomp_default_icv_values.bind_var;
2137 icvs->nteams_var = gomp_default_icv_values.nteams_var;
2138 icvs->teams_thread_limit_var = gomp_default_icv_values.teams_thread_limit_var;
2139 icvs->wait_policy = -1;
2142 /* Helper function for initialize_env to add a device specific ICV value
2143 to gomp_initial_icv_list. */
2145 static uint32_t *
2146 add_initial_icv_to_list (int dev_num, int icv_code, void *icv_addr[3])
2148 struct gomp_icv_list *last = NULL, *l = gomp_initial_icv_list;
2149 while (l != NULL && l->device_num != dev_num)
2151 last = l;
2152 l = l->next;
2155 if (l == NULL)
2157 l = ((struct gomp_icv_list *)
2158 gomp_malloc_cleared (sizeof (struct gomp_icv_list)));
2159 l->device_num = dev_num;
2160 initialize_icvs (&l->icvs);
2161 if (dev_num < 0)
2163 l->next = gomp_initial_icv_list;
2164 gomp_initial_icv_list = l;
2166 else
2168 l->next = NULL;
2169 if (last == NULL)
2170 gomp_initial_icv_list = l;
2171 else
2172 last->next = l;
2176 get_icv_member_addr (&l->icvs, icv_code, icv_addr);
2178 return &l->flags;
2181 /* Return true if STR string starts with PREFIX. */
2183 static inline bool
2184 startswith (const char *str, const char *prefix)
2186 return strncmp (str, prefix, strlen (prefix)) == 0;
2189 static void __attribute__((destructor))
2190 cleanup_env (void)
2192 if (gomp_def_allocator_envvar != NULL)
2194 free (gomp_def_allocator_envvar);
2195 omp_destroy_allocator (gomp_def_allocator);
2199 static void __attribute__((constructor))
2200 initialize_env (void)
2202 char **env;
2203 int omp_var, dev_num = 0, dev_num_len = 0, i;
2204 bool ignore = false;
2205 char *env_val;
2206 void *params[3];
2207 uint32_t *flag_var_addr = NULL;
2208 unsigned pos;
2209 struct gomp_icv_list *all, *none;
2211 /* Do a compile time check that mkomp_h.pl did good job. */
2212 omp_check_defines ();
2214 #ifndef HAVE_SYNC_BUILTINS
2215 gomp_mutex_init (&gomp_managed_threads_lock);
2216 #endif
2217 gomp_init_num_threads ();
2218 gomp_available_cpus = gomp_global_icv.nthreads_var;
2220 /* Initial values for host environment variables should always exist even if
2221 there is no explicitly set host environment variable. Moreover, they are
2222 set to the initial global values. */
2223 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX, 0, NULL);
2224 none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
2225 initialize_icvs (&none->icvs);
2227 for (env = environ; *env != 0; env++)
2229 if (!startswith (*env, "OMP_"))
2230 continue;
2232 /* Name of the environment variable without suffix "OMP_". */
2233 char *name = *env + sizeof ("OMP_") - 1;
2234 for (omp_var = 0; omp_var < OMP_VAR_CNT; omp_var++)
2236 if (startswith (name, envvars[omp_var].name))
2238 pos = envvars[omp_var].name_len;
2239 if (name[pos] == '=')
2241 pos++;
2242 flag_var_addr
2243 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX,
2244 envvars[omp_var].flag_vars[0],
2245 params);
2247 else if (startswith (&name[pos], "_DEV=")
2248 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV)
2250 pos += 5;
2251 flag_var_addr
2252 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV,
2253 envvars[omp_var].flag_vars[0],
2254 params);
2256 else if (startswith (&name[pos], "_ALL=")
2257 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_ALL)
2259 pos += 5;
2260 flag_var_addr
2261 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL,
2262 envvars[omp_var].flag_vars[0],
2263 params);
2265 else if (startswith (&name[pos], "_DEV_")
2266 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV_X)
2268 pos += 5;
2269 if (!get_device_num (*env, &name[pos], &dev_num,
2270 &dev_num_len))
2271 break;
2273 pos += dev_num_len + 1;
2274 flag_var_addr
2275 = add_initial_icv_to_list (dev_num,
2276 envvars[omp_var].flag_vars[0],
2277 params);
2279 else
2281 gomp_error ("Invalid environment variable in %s", *env);
2282 break;
2284 env_val = &name[pos];
2286 if (envvars[omp_var].parse_func (*env, env_val, params))
2288 for (i = 0; i < 3; ++i)
2289 if (envvars[omp_var].flag_vars[i])
2290 gomp_set_icv_flag (flag_var_addr,
2291 envvars[omp_var].flag_vars[i]);
2292 else
2293 break;
2296 break;
2301 all = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
2302 for (omp_var = 0; omp_var < OMP_HOST_VAR_CNT; omp_var++)
2304 if (none != NULL
2305 && gomp_get_icv_flag (none->flags, host_envvars[omp_var].flag_var))
2306 get_icv_member_addr (&none->icvs,
2307 host_envvars[omp_var].flag_var, params);
2308 else if (all != NULL
2309 && gomp_get_icv_flag (all->flags,
2310 host_envvars[omp_var].flag_var))
2311 get_icv_member_addr (&all->icvs, host_envvars[omp_var].flag_var,
2312 params);
2313 else
2314 continue;
2316 switch (host_envvars[omp_var].type_code)
2318 case PARSE_INT:
2319 for (i = 0; i < 3; ++i)
2320 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2321 *(int *) (host_envvars[omp_var].dest[i]) = *(int *) params[i];
2322 break;
2323 case PARSE_BOOL:
2324 for (i = 0; i < 3; ++i)
2325 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2326 *(bool *) (host_envvars[omp_var].dest[i]) = *(bool *) params[i];
2327 break;
2328 case PARSE_UINT:
2329 for (i = 0; i < 3; ++i)
2330 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2331 *(unsigned int *) (host_envvars[omp_var].dest[i])
2332 = *(unsigned int *) params[i];
2333 break;
2334 case PARSE_ULONG:
2335 for (i = 0; i < 3; ++i)
2336 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2337 *(unsigned long *) (host_envvars[omp_var].dest[i])
2338 = *(unsigned long *) params[i];
2339 break;
2340 case PARSE_UCHAR:
2341 for (i = 0; i < 3; ++i)
2342 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2343 *(unsigned char *) (host_envvars[omp_var].dest[i])
2344 = *(unsigned char *) params[i];
2345 break;
2346 case PARSE_SCHEDULE:
2347 *(enum gomp_schedule_type *) (host_envvars[omp_var].dest[0])
2348 = *(enum gomp_schedule_type *) params[0];
2349 *(int *) (host_envvars[omp_var].dest[1]) = *(int *) params[1];
2350 break;
2351 case PARSE_BIND:
2352 *(char *) (host_envvars[omp_var].dest[0]) = *(char *) params[0];
2353 *(char **) (host_envvars[omp_var].dest[1]) = *(char **) params[1];
2354 *(unsigned long *) (host_envvars[omp_var].dest[2])
2355 = *(unsigned long *) params[2];
2356 break;
2360 if (((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_BIND))
2361 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND)))
2362 && gomp_global_icv.bind_var == omp_proc_bind_false)
2363 ignore = true;
2365 if (!((none != NULL
2366 && gomp_get_icv_flag (none->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))
2367 || (all != NULL
2368 && gomp_get_icv_flag (all->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))))
2370 bool nested = true;
2371 const char *env = getenv ("OMP_NESTED");
2373 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2374 if (parse_boolean ("OMP_NESTED", env, (void *[]) {&nested}))
2375 gomp_global_icv.max_active_levels_var
2376 = nested ? gomp_supported_active_levels : 1;
2377 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
2378 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
2381 if (gomp_global_icv.default_device_var == INT_MIN
2382 && gomp_target_offload_var != GOMP_TARGET_OFFLOAD_MANDATORY)
2383 none->icvs.default_device_var = gomp_global_icv.default_device_var = 0;
2385 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2386 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
2388 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2389 parsed if present in the environment. If OMP_PROC_BIND was set
2390 explicitly to false, don't populate places list though. If places
2391 list was successfully set from OMP_PLACES, only parse but don't process
2392 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2393 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2394 was successfully parsed into a places list, otherwise to
2395 OMP_PROC_BIND=false. */
2396 if (parse_places_var ("OMP_PLACES", ignore))
2398 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2399 gomp_global_icv.bind_var = true;
2400 ignore = true;
2402 if (parse_affinity (ignore))
2404 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2405 gomp_global_icv.bind_var = true;
2406 ignore = true;
2408 if (gomp_global_icv.bind_var != omp_proc_bind_false)
2409 gomp_init_affinity ();
2412 const char *env = getenv ("OMP_AFFINITY_FORMAT");
2413 if (env != NULL)
2414 gomp_set_affinity_format (env, strlen (env));
2417 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_WAIT_POLICY))
2418 wait_policy = none->icvs.wait_policy;
2419 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
2420 wait_policy = all->icvs.wait_policy;
2422 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
2424 /* Using a rough estimation of 100000 spins per msec,
2425 use 5 min blocking for OMP_WAIT_POLICY=active,
2426 3 msec blocking when OMP_WAIT_POLICY is not specificed
2427 and 0 when OMP_WAIT_POLICY=passive.
2428 Depending on the CPU speed, this can be e.g. 5 times longer
2429 or 5 times shorter. */
2430 if (wait_policy > 0)
2431 gomp_spin_count_var = 30000000000LL;
2432 else if (wait_policy < 0)
2433 gomp_spin_count_var = 300000LL;
2435 /* gomp_throttled_spin_count_var is used when there are more libgomp
2436 managed threads than available CPUs. Use very short spinning. */
2437 if (wait_policy > 0)
2438 gomp_throttled_spin_count_var = 1000LL;
2439 else if (wait_policy < 0)
2440 gomp_throttled_spin_count_var = 100LL;
2441 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
2442 gomp_throttled_spin_count_var = gomp_spin_count_var;
2444 /* Not strictly environment related, but ordering constructors is tricky. */
2445 pthread_attr_init (&gomp_thread_attr);
2447 if (!(none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE)))
2449 const char *env = getenv ("GOMP_STACKSIZE");
2450 if (env != NULL
2451 && parse_stacksize ("GOMP_STACKSIZE", env,
2452 (void *[3]) {&none->icvs.stacksize}))
2453 gomp_set_icv_flag (&none->flags, GOMP_ICV_STACKSIZE);
2455 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2456 stacksize = none->icvs.stacksize;
2457 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2458 stacksize = all->icvs.stacksize;
2460 if ((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2461 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2462 || GOMP_DEFAULT_STACKSIZE)
2464 int err;
2466 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
2468 #ifdef PTHREAD_STACK_MIN
2469 if (err == EINVAL)
2471 if (stacksize < PTHREAD_STACK_MIN)
2472 gomp_error ("Stack size less than minimum of %luk",
2473 PTHREAD_STACK_MIN / 1024ul
2474 + (PTHREAD_STACK_MIN % 1024 != 0));
2475 else
2476 gomp_error ("Stack size larger than system limit");
2478 else
2479 #endif
2480 if (err != 0)
2481 gomp_error ("Stack size change failed: %s", strerror (err));
2484 handle_omp_display_env ();
2486 /* OpenACC. */
2488 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2489 (void *[]) {&goacc_device_num, (void *) true}))
2490 goacc_device_num = 0;
2492 parse_acc_device_type ();
2493 parse_gomp_openacc_dim ();
2495 goacc_runtime_initialize ();
2497 goacc_profiling_initialize ();
2499 #endif /* LIBGOMP_OFFLOADED_ONLY */