libstdc++: Use std::type_identity_t in <string_view> as per LWG 3950 [PR114400]
[official-gcc.git] / libgomp / env.c
blob47d8c637b66a5509df3a2fdec6c37962e2d0df6c
1 /* Copyright (C) 2005-2024 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"
64 #include "spincount.h"
66 /* Default values of ICVs according to the OpenMP standard,
67 except for default-device-var. */
68 const struct gomp_default_icv gomp_default_icv_values = {
69 .nthreads_var = 1,
70 .thread_limit_var = UINT_MAX,
71 .run_sched_var = GFS_DYNAMIC,
72 .run_sched_chunk_size = 1,
73 .default_device_var = INT_MIN,
74 .max_active_levels_var = 1,
75 .bind_var = omp_proc_bind_false,
76 .nteams_var = 0,
77 .teams_thread_limit_var = 0,
78 .dyn_var = false
81 struct gomp_task_icv gomp_global_icv = {
82 .nthreads_var = gomp_default_icv_values.nthreads_var,
83 .thread_limit_var = gomp_default_icv_values.thread_limit_var,
84 .run_sched_var = gomp_default_icv_values.run_sched_var,
85 .run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size,
86 .default_device_var = gomp_default_icv_values.default_device_var,
87 .dyn_var = gomp_default_icv_values.dyn_var,
88 .max_active_levels_var = gomp_default_icv_values.max_active_levels_var,
89 .bind_var = gomp_default_icv_values.bind_var,
90 .target_data = NULL
93 /* List for initial "_DEV", "_ALL", and "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV,
94 OMP_NUM_TEAMS_ALL, or OMP_NUM_TEAMS_DEV_42. */
95 struct gomp_icv_list *gomp_initial_icv_list = NULL;
97 /* List for "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV_42. This list contains all
98 device-specific ICVs that are copied from host to device and back. */
99 struct gomp_offload_icv_list *gomp_offload_icv_list = NULL;
101 bool gomp_cancel_var = false;
102 enum gomp_target_offload_t gomp_target_offload_var
103 = GOMP_TARGET_OFFLOAD_DEFAULT;
104 int gomp_max_task_priority_var = 0;
105 #ifndef HAVE_SYNC_BUILTINS
106 gomp_mutex_t gomp_managed_threads_lock;
107 #endif
108 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
109 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
110 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
111 char *gomp_bind_var_list;
112 unsigned long gomp_bind_var_list_len;
113 void **gomp_places_list;
114 unsigned long gomp_places_list_len;
115 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
116 char *gomp_def_allocator_envvar = NULL;
117 int gomp_debug_var;
118 unsigned int gomp_num_teams_var;
119 int gomp_nteams_var;
120 int gomp_teams_thread_limit_var;
121 bool gomp_display_affinity_var;
122 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
123 size_t gomp_affinity_format_len;
124 char *goacc_device_type;
125 int goacc_device_num;
126 int goacc_default_dims[GOMP_DIM_MAX];
128 #ifndef LIBGOMP_OFFLOADED_ONLY
130 static int wait_policy = -1;
131 static unsigned long stacksize = GOMP_DEFAULT_STACKSIZE;
133 static void
134 print_env_var_error (const char *env, const char *val)
136 gomp_error ("Invalid value for environment variable %.*s: %s",
137 (int) (val - env - 1), env, val);
140 /* Parse the OMP_SCHEDULE environment variable. */
141 static bool
142 parse_schedule (const char *env, const char *val, void *const params[])
144 enum gomp_schedule_type *schedule = (enum gomp_schedule_type *) params[0];
145 int *chunk_size = (int *) params[1];
146 char *end;
147 unsigned long value;
148 int monotonic = 0;
150 if (val == NULL)
151 return false;
153 while (isspace ((unsigned char) *val))
154 ++val;
155 if (strncasecmp (val, "monotonic", 9) == 0)
157 monotonic = 1;
158 val += 9;
160 else if (strncasecmp (val, "nonmonotonic", 12) == 0)
162 monotonic = -1;
163 val += 12;
165 if (monotonic)
167 while (isspace ((unsigned char) *val))
168 ++val;
169 if (*val != ':')
170 goto unknown;
171 ++val;
172 while (isspace ((unsigned char) *val))
173 ++val;
175 if (strncasecmp (val, "static", 6) == 0)
177 *schedule = GFS_STATIC;
178 val += 6;
180 else if (strncasecmp (val, "dynamic", 7) == 0)
182 *schedule = GFS_DYNAMIC;
183 val += 7;
185 else if (strncasecmp (val, "guided", 6) == 0)
187 *schedule = GFS_GUIDED;
188 val += 6;
190 else if (strncasecmp (val, "auto", 4) == 0)
192 *schedule = GFS_AUTO;
193 val += 4;
195 else
196 goto unknown;
198 if (monotonic == 1
199 || (monotonic == 0 && *schedule == GFS_STATIC))
200 *schedule |= GFS_MONOTONIC;
202 while (isspace ((unsigned char) *val))
203 ++val;
204 if (*val == '\0')
206 *chunk_size = (*schedule & ~GFS_MONOTONIC) != GFS_STATIC;
207 return true;
209 if (*val++ != ',')
210 goto unknown;
211 while (isspace ((unsigned char) *val))
212 ++val;
213 if (*val == '\0')
214 goto invalid;
216 errno = 0;
217 value = strtoul (val, &end, 10);
218 if (errno || end == val)
219 goto invalid;
221 while (isspace ((unsigned char) *end))
222 ++end;
223 if (*end != '\0')
224 goto invalid;
226 if ((int)value != value)
227 goto invalid;
229 if (value == 0 && (*schedule & ~GFS_MONOTONIC) != GFS_STATIC)
230 value = 1;
231 *chunk_size = value;
232 return true;
234 unknown:
235 print_env_var_error (env, val);
236 return false;
238 invalid:
239 char name[val - env];
240 memcpy (name, env, val - env - 1);
241 name[val - env - 1] = '\0';
242 gomp_error ("Invalid value for chunk size in "
243 "environment variable %s: %s", name, val);
244 return false;
247 /* Parse an unsigned long environment variable. Return true if one was
248 present and it was successfully parsed. If SECURE, use secure_getenv to the
249 environment variable. */
251 static bool
252 parse_unsigned_long_1 (const char *env, const char *val, unsigned long *pvalue,
253 bool allow_zero)
255 char *end;
256 unsigned long value;
258 if (val == NULL)
259 return false;
261 while (isspace ((unsigned char) *val))
262 ++val;
263 if (*val == '\0')
264 goto invalid;
266 errno = 0;
267 value = strtoul (val, &end, 10);
268 if (errno || end == val || (long) value <= 0 - allow_zero)
269 goto invalid;
271 while (isspace ((unsigned char) *end))
272 ++end;
273 if (*end != '\0')
274 goto invalid;
276 *pvalue = value;
277 return true;
279 invalid:
280 print_env_var_error (env, val);
281 return false;
284 /* As parse_unsigned_long_1, but always use getenv. */
286 static bool
287 parse_unsigned_long (const char *env, const char *val, void *const params[])
289 unsigned long upper = (uintptr_t) params[2];
290 unsigned long pvalue = 0;
291 bool ret = parse_unsigned_long_1 (env, val, &pvalue, (bool) params[1]);
292 if (!ret)
293 return false;
295 if (upper == 0)
296 *(unsigned long *) params[0] = pvalue;
297 else
299 if (pvalue > upper)
300 pvalue = upper;
301 if (upper <= UCHAR_MAX)
302 *(unsigned char *) params[0] = pvalue;
303 else if (upper <= UINT_MAX)
304 *(unsigned int *) params[0] = pvalue;
305 else
306 *(unsigned long *) params[0] = pvalue;
309 return ret;
312 /* Parse a positive int environment variable. Return true if one was
313 present and it was successfully parsed. If SECURE, use secure_getenv to the
314 environment variable. */
316 static bool
317 parse_int_1 (const char *env, const char *val, int *pvalue, bool allow_zero)
319 unsigned long value;
320 if (!parse_unsigned_long_1 (env, val, &value, allow_zero))
321 return false;
322 if (value > INT_MAX)
324 print_env_var_error (env, val);
325 return false;
327 *pvalue = (int) value;
328 return true;
331 static bool
332 parse_int (const char *env, const char *val, void *const params[])
334 return parse_int_1 (env, val, (int *) params[0], (bool) params[1]);
337 /* As parse_int_1, but use getenv_secure. */
339 static bool
340 parse_int_secure (const char *env, int *pvalue, bool allow_zero)
342 return parse_int_1 (env, secure_getenv (env), pvalue, allow_zero);
345 /* Parse an unsigned long list environment variable. Return true if one was
346 present and it was successfully parsed. */
348 static bool
349 parse_unsigned_long_list (const char *env, const char *val,
350 void *const params[])
352 unsigned long *p1stvalue = (unsigned long *) params[0];
353 unsigned long **pvalues = (unsigned long **) params[1];
354 unsigned long *pnvalues = (unsigned long *) params[2];
355 char *end;
356 unsigned long value, *values = NULL;
358 if (val == NULL)
359 return false;
361 while (isspace ((unsigned char) *val))
362 ++val;
363 if (*val == '\0')
364 goto invalid;
366 errno = 0;
367 value = strtoul (val, &end, 10);
368 if (errno || (long) value <= 0)
369 goto invalid;
371 while (isspace ((unsigned char) *end))
372 ++end;
373 if (*end != '\0')
375 if (*end == ',')
377 unsigned long nvalues = 0, nalloced = 0;
381 val = end + 1;
382 if (nvalues == nalloced)
384 unsigned long *n;
385 nalloced = nalloced ? nalloced * 2 : 16;
386 n = realloc (values, nalloced * sizeof (unsigned long));
387 if (n == NULL)
389 free (values);
390 char name[val - env];
391 memcpy (name, env, val - env - 1);
392 name[val - env - 1] = '\0';
393 gomp_error ("Out of memory while trying to parse"
394 " environment variable %s", name);
395 return false;
397 values = n;
398 if (nvalues == 0)
399 values[nvalues++] = value;
402 while (isspace ((unsigned char) *val))
403 ++val;
404 if (*val == '\0')
405 goto invalid;
407 errno = 0;
408 value = strtoul (val, &end, 10);
409 if (errno || (long) value <= 0)
410 goto invalid;
412 values[nvalues++] = value;
413 while (isspace ((unsigned char) *end))
414 ++end;
415 if (*end == '\0')
416 break;
417 if (*end != ',')
418 goto invalid;
420 while (1);
421 *p1stvalue = values[0];
422 *pvalues = values;
423 *pnvalues = nvalues;
424 return true;
426 goto invalid;
428 else
430 *pnvalues = 0;
431 *pvalues = NULL;
434 *p1stvalue = value;
435 return true;
437 invalid:
438 free (values);
439 print_env_var_error (env, val);
440 return false;
443 static bool
444 parse_target_offload (const char *env, const char *val, void *const params[])
446 int new_offload = -1;
448 if (val == NULL)
449 return false;
451 while (isspace ((unsigned char) *val))
452 ++val;
453 if (strncasecmp (val, "default", 7) == 0)
455 val += 7;
456 new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
458 else if (strncasecmp (val, "mandatory", 9) == 0)
460 val += 9;
461 new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
463 else if (strncasecmp (val, "disabled", 8) == 0)
465 val += 8;
466 new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
468 while (isspace ((unsigned char) *val))
469 ++val;
470 if (new_offload != -1 && *val == '\0')
472 *(enum gomp_target_offload_t *) params[0] = new_offload;
473 return true;
476 print_env_var_error (env, val);
477 return false;
480 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
481 enum values. Return true if one was present and it was successfully
482 parsed. */
484 static bool
485 parse_bind_var (const char *env, const char *val, void *const params[])
487 char *p1stvalue = (char *) params[0];
488 char **pvalues = (char **) params[1];
489 unsigned long *pnvalues = (unsigned long *) params[2];
490 char value = omp_proc_bind_false, *values = NULL;
491 int i;
492 static struct proc_bind_kinds
494 const char name[7];
495 const char len;
496 omp_proc_bind_t kind;
497 } kinds[] =
499 { "false", 5, omp_proc_bind_false },
500 { "true", 4, omp_proc_bind_true },
501 { "master", 6, omp_proc_bind_master },
502 { "primary", 7, omp_proc_bind_primary },
503 { "close", 5, omp_proc_bind_close },
504 { "spread", 6, omp_proc_bind_spread }
507 if (val == NULL)
508 return false;
510 while (isspace ((unsigned char) *val))
511 ++val;
512 if (*val == '\0')
513 goto invalid;
515 for (i = 0; i < 6; i++)
516 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
518 value = kinds[i].kind;
519 val += kinds[i].len;
520 break;
522 if (i == 6)
523 goto invalid;
525 while (isspace ((unsigned char) *val))
526 ++val;
527 if (*val != '\0')
529 if (*val == ',')
531 unsigned long nvalues = 0, nalloced = 0;
533 if (value == omp_proc_bind_false
534 || value == omp_proc_bind_true)
535 goto invalid;
539 val++;
540 if (nvalues == nalloced)
542 char *n;
543 nalloced = nalloced ? nalloced * 2 : 16;
544 n = realloc (values, nalloced);
545 if (n == NULL)
547 free (values);
548 char name[val - env];
549 memcpy (name, env, val - env - 1);
550 name[val - env - 1] = '\0';
551 gomp_error ("Out of memory while trying to parse"
552 " environment variable %s", name);
553 return false;
555 values = n;
556 if (nvalues == 0)
557 values[nvalues++] = value;
560 while (isspace ((unsigned char) *val))
561 ++val;
562 if (*val == '\0')
563 goto invalid;
565 for (i = 2; i < 6; i++)
566 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
568 value = kinds[i].kind;
569 val += kinds[i].len;
570 break;
572 if (i == 6)
573 goto invalid;
575 values[nvalues++] = value;
576 while (isspace ((unsigned char) *val))
577 ++val;
578 if (*val == '\0')
579 break;
580 if (*val != ',')
581 goto invalid;
583 while (1);
584 *p1stvalue = values[0];
585 *pvalues = values;
586 *pnvalues = nvalues;
587 return true;
589 goto invalid;
592 *p1stvalue = value;
593 return true;
595 invalid:
596 free (values);
597 print_env_var_error (env, val);
598 return false;
601 static bool
602 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
603 long *stridep)
605 char *env = *envp, *start;
606 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
607 unsigned long len = 1;
608 long stride = 1;
609 int pass;
610 bool any_negate = false;
611 bool has_braces = true;
612 *negatep = false;
613 while (isspace ((unsigned char) *env))
614 ++env;
615 if (*env == '!')
617 *negatep = true;
618 ++env;
619 while (isspace ((unsigned char) *env))
620 ++env;
622 if (*env != '{')
624 char *end;
625 unsigned long this_num;
627 errno = 0;
628 this_num = strtoul (env, &end, 10);
629 if (errno || end == env)
630 return false;
631 env = end - 1;
632 has_braces = false;
633 if (gomp_places_list
634 && !gomp_affinity_add_cpus (p, this_num, 1, 1, false))
635 return false;
637 else
639 ++env;
640 while (isspace ((unsigned char) *env))
641 ++env;
643 start = env;
644 for (pass = 0; pass < (any_negate ? 2 : has_braces); pass++)
646 env = start;
649 unsigned long this_num, this_len = 1;
650 long this_stride = 1;
651 bool this_negate = (*env == '!');
652 char *end;
653 if (this_negate)
655 if (gomp_places_list)
656 any_negate = true;
657 ++env;
658 while (isspace ((unsigned char) *env))
659 ++env;
662 errno = 0;
663 this_num = strtoul (env, &end, 10);
664 if (errno || end == env)
665 return false;
666 env = end;
667 while (isspace ((unsigned char) *env))
668 ++env;
669 if (*env == ':')
671 ++env;
672 if (this_negate)
673 return false;
674 while (isspace ((unsigned char) *env))
675 ++env;
676 errno = 0;
677 this_len = strtoul (env, &env, 10);
678 if (errno || this_len == 0)
679 return false;
680 while (isspace ((unsigned char) *env))
681 ++env;
682 if (*env == ':')
684 ++env;
685 while (isspace ((unsigned char) *env))
686 ++env;
687 errno = 0;
688 this_stride = strtol (env, &end, 10);
689 if (errno || end == env)
690 return false;
691 env = end;
692 while (isspace ((unsigned char) *env))
693 ++env;
696 if (gomp_places_list && pass == this_negate)
698 if (this_negate)
700 if (!gomp_affinity_remove_cpu (p, this_num))
701 return false;
703 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
704 this_stride, false))
705 return false;
707 if (*env == '}')
708 break;
709 if (*env != ',')
710 return false;
711 ++env;
713 while (1);
716 ++env;
717 while (isspace ((unsigned char) *env))
718 ++env;
719 if (*env == ':')
721 char *end;
722 if (*negatep)
723 return false;
724 ++env;
725 while (isspace ((unsigned char) *env))
726 ++env;
727 errno = 0;
728 len = strtoul (env, &env, 10);
729 if (errno || len == 0 || len >= 65536)
730 return false;
731 while (isspace ((unsigned char) *env))
732 ++env;
733 if (*env == ':')
735 ++env;
736 while (isspace ((unsigned char) *env))
737 ++env;
738 errno = 0;
739 stride = strtol (env, &end, 10);
740 if (errno || end == env)
741 return false;
742 env = end;
743 while (isspace ((unsigned char) *env))
744 ++env;
747 *envp = env;
748 *lenp = len;
749 *stridep = stride;
750 return true;
753 static bool
754 parse_places_var (const char *name, bool ignore)
756 char *env = getenv (name), *end;
757 bool any_negate = false;
758 int level = 0;
759 unsigned long count = 0;
760 if (env == NULL)
761 return false;
763 while (isspace ((unsigned char) *env))
764 ++env;
765 if (*env == '\0')
766 goto invalid;
768 if (strncasecmp (env, "threads", 7) == 0)
770 env += 7;
771 level = 1;
773 else if (strncasecmp (env, "cores", 5) == 0)
775 env += 5;
776 level = 2;
778 else if (strncasecmp (env, "sockets", 7) == 0)
780 env += 7;
781 level = 3;
783 else if (strncasecmp (env, "ll_caches", 9) == 0)
785 env += 9;
786 level = 4;
788 else if (strncasecmp (env, "numa_domains", 12) == 0)
790 env += 12;
791 level = 5;
793 if (level)
795 count = ULONG_MAX;
796 while (isspace ((unsigned char) *env))
797 ++env;
798 if (*env != '\0')
800 if (*env++ != '(')
801 goto invalid;
802 while (isspace ((unsigned char) *env))
803 ++env;
805 errno = 0;
806 count = strtoul (env, &end, 10);
807 if (errno || end == env)
808 goto invalid;
809 env = end;
810 while (isspace ((unsigned char) *env))
811 ++env;
812 if (*env != ')')
813 goto invalid;
814 ++env;
815 while (isspace ((unsigned char) *env))
816 ++env;
817 if (*env != '\0')
818 goto invalid;
821 if (ignore)
822 return false;
824 return gomp_affinity_init_level (level, count, false);
827 count = 0;
828 end = env;
831 bool negate;
832 unsigned long len;
833 long stride;
834 if (!parse_one_place (&end, &negate, &len, &stride))
835 goto invalid;
836 if (negate)
838 if (!any_negate)
839 count++;
840 any_negate = true;
842 else
843 count += len;
844 if (count > 65536)
845 goto invalid;
846 if (*end == '\0')
847 break;
848 if (*end != ',')
849 goto invalid;
850 end++;
852 while (1);
854 if (ignore)
855 return false;
857 gomp_places_list_len = 0;
858 gomp_places_list = gomp_affinity_alloc (count, false);
859 if (gomp_places_list == NULL)
860 return false;
864 bool negate;
865 unsigned long len;
866 long stride;
867 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
868 if (!parse_one_place (&env, &negate, &len, &stride))
869 goto invalid;
870 if (negate)
872 void *p;
873 for (count = 0; count < gomp_places_list_len; count++)
874 if (gomp_affinity_same_place
875 (gomp_places_list[count],
876 gomp_places_list[gomp_places_list_len]))
877 break;
878 if (count == gomp_places_list_len)
880 gomp_error ("Trying to remove a non-existing place from list "
881 "of places");
882 goto invalid;
884 p = gomp_places_list[count];
885 memmove (&gomp_places_list[count],
886 &gomp_places_list[count + 1],
887 (gomp_places_list_len - count - 1) * sizeof (void *));
888 --gomp_places_list_len;
889 gomp_places_list[gomp_places_list_len] = p;
891 else if (len == 1)
892 ++gomp_places_list_len;
893 else
895 for (count = 0; count < len - 1; count++)
896 if (!gomp_affinity_copy_place
897 (gomp_places_list[gomp_places_list_len + count + 1],
898 gomp_places_list[gomp_places_list_len + count],
899 stride))
900 goto invalid;
901 gomp_places_list_len += len;
903 if (*env == '\0')
904 break;
905 env++;
907 while (1);
909 if (gomp_places_list_len == 0)
911 gomp_error ("All places have been removed");
912 goto invalid;
914 if (!gomp_affinity_finalize_place_list (false))
915 goto invalid;
916 return true;
918 invalid:
919 free (gomp_places_list);
920 gomp_places_list = NULL;
921 gomp_places_list_len = 0;
922 gomp_error ("Invalid value for environment variable %s", name);
923 return false;
926 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
927 present and it was successfully parsed. */
929 static bool
930 parse_stacksize (const char *env, const char *val, void *const params[])
932 char *end;
933 unsigned long value, shift = 10;
935 if (val == NULL)
936 return false;
938 while (isspace ((unsigned char) *val))
939 ++val;
940 if (*val == '\0')
941 goto invalid;
943 errno = 0;
944 value = strtoul (val, &end, 10);
945 if (errno || end == val)
946 goto invalid;
948 while (isspace ((unsigned char) *end))
949 ++end;
950 if (*end != '\0')
952 switch (tolower ((unsigned char) *end))
954 case 'b':
955 shift = 0;
956 break;
957 case 'k':
958 break;
959 case 'm':
960 shift = 20;
961 break;
962 case 'g':
963 shift = 30;
964 break;
965 default:
966 goto invalid;
968 ++end;
969 while (isspace ((unsigned char) *end))
970 ++end;
971 if (*end != '\0')
972 goto invalid;
975 if (((value << shift) >> shift) != value)
976 goto invalid;
978 *(unsigned long *) params[0] = value << shift;
979 return true;
981 invalid:
982 print_env_var_error (env, val);
983 return false;
986 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
987 present and it was successfully parsed. */
989 static bool
990 parse_spincount (const char *name, unsigned long long *pvalue)
992 char *env, *end;
993 unsigned long long value, mult = 1;
995 env = getenv (name);
996 if (env == NULL)
997 return false;
999 while (isspace ((unsigned char) *env))
1000 ++env;
1001 if (*env == '\0')
1002 goto invalid;
1004 if (strncasecmp (env, "infinite", 8) == 0
1005 || strncasecmp (env, "infinity", 8) == 0)
1007 value = ~0ULL;
1008 end = env + 8;
1009 goto check_tail;
1012 errno = 0;
1013 value = strtoull (env, &end, 10);
1014 if (errno || end == env)
1015 goto invalid;
1017 while (isspace ((unsigned char) *end))
1018 ++end;
1019 if (*end != '\0')
1021 switch (tolower ((unsigned char) *end))
1023 case 'k':
1024 mult = 1000LL;
1025 break;
1026 case 'm':
1027 mult = 1000LL * 1000LL;
1028 break;
1029 case 'g':
1030 mult = 1000LL * 1000LL * 1000LL;
1031 break;
1032 case 't':
1033 mult = 1000LL * 1000LL * 1000LL * 1000LL;
1034 break;
1035 default:
1036 goto invalid;
1038 ++end;
1039 check_tail:
1040 while (isspace ((unsigned char) *end))
1041 ++end;
1042 if (*end != '\0')
1043 goto invalid;
1046 if (value > ~0ULL / mult)
1047 value = ~0ULL;
1048 else
1049 value *= mult;
1051 *pvalue = value;
1052 return true;
1054 invalid:
1055 gomp_error ("Invalid value for environment variable %s", name);
1056 return false;
1059 /* Parse a boolean value for environment variable NAME and store the
1060 result in VALUE. Return true if one was present and it was
1061 successfully parsed. */
1062 static bool
1063 parse_boolean (const char *env, const char *val, void *const params[])
1065 bool *value = (bool *) params[0];
1067 if (val == NULL)
1068 return false;
1070 while (isspace ((unsigned char) *val))
1071 ++val;
1072 if (strncasecmp (val, "true", 4) == 0)
1074 *value = true;
1075 val += 4;
1077 else if (strncasecmp (val, "false", 5) == 0)
1079 *value = false;
1080 val += 5;
1082 else
1083 val = "X";
1084 while (isspace ((unsigned char) *val))
1085 ++val;
1086 if (*val != '\0')
1088 print_env_var_error (env, val);
1089 return false;
1091 return true;
1094 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1096 static bool
1097 parse_wait_policy (const char *env, const char *val, void *const params[])
1099 int *pvalue = (int *) params[0];
1100 int ret = -1;
1102 if (val == NULL)
1104 *pvalue = -1;
1105 return false;
1108 while (isspace ((unsigned char) *val))
1109 ++val;
1110 if (strncasecmp (val, "active", 6) == 0)
1112 ret = 1;
1113 val += 6;
1115 else if (strncasecmp (val, "passive", 7) == 0)
1117 ret = 0;
1118 val += 7;
1120 else
1121 val = "X";
1122 while (isspace ((unsigned char) *val))
1123 ++val;
1124 if (*val == '\0')
1126 *pvalue = ret;
1127 return true;
1129 print_env_var_error (env, val);
1130 *pvalue = -1;
1131 return false;
1134 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1135 present and it was successfully parsed. */
1137 static bool
1138 parse_affinity (bool ignore)
1140 char *env, *end, *start;
1141 int pass;
1142 unsigned long cpu_beg, cpu_end, cpu_stride;
1143 size_t count = 0, needed;
1145 env = getenv ("GOMP_CPU_AFFINITY");
1146 if (env == NULL)
1147 return false;
1149 start = env;
1150 for (pass = 0; pass < 2; pass++)
1152 env = start;
1153 if (pass == 1)
1155 if (ignore)
1156 return false;
1158 gomp_places_list_len = 0;
1159 gomp_places_list = gomp_affinity_alloc (count, true);
1160 if (gomp_places_list == NULL)
1161 return false;
1165 while (isspace ((unsigned char) *env))
1166 ++env;
1168 errno = 0;
1169 cpu_beg = strtoul (env, &end, 0);
1170 if (errno || end == env || cpu_beg >= 65536)
1171 goto invalid;
1172 cpu_end = cpu_beg;
1173 cpu_stride = 1;
1175 env = end;
1176 if (*env == '-')
1178 errno = 0;
1179 cpu_end = strtoul (++env, &end, 0);
1180 if (errno || end == env || cpu_end >= 65536 || cpu_end < cpu_beg)
1181 goto invalid;
1183 env = end;
1184 if (*env == ':')
1186 errno = 0;
1187 cpu_stride = strtoul (++env, &end, 0);
1188 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1189 goto invalid;
1191 env = end;
1195 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1196 if (pass == 0)
1197 count += needed;
1198 else
1200 while (needed--)
1202 void *p = gomp_places_list[gomp_places_list_len];
1203 gomp_affinity_init_place (p);
1204 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1205 ++gomp_places_list_len;
1206 cpu_beg += cpu_stride;
1210 while (isspace ((unsigned char) *env))
1211 ++env;
1213 if (*env == ',')
1214 env++;
1215 else if (*env == '\0')
1216 break;
1218 while (1);
1221 if (gomp_places_list_len == 0)
1223 free (gomp_places_list);
1224 gomp_places_list = NULL;
1225 return false;
1227 return true;
1229 invalid:
1230 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1231 return false;
1234 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1235 static bool
1236 parse_allocator (const char *env, const char *val, void *const params[])
1238 const char *orig_val = val;
1239 uintptr_t *ret = (uintptr_t *) params[0];
1240 *ret = omp_default_mem_alloc;
1241 bool memspace = false;
1242 size_t ntraits = 0;
1243 omp_alloctrait_t *traits;
1245 if (val == NULL)
1246 return false;
1248 while (isspace ((unsigned char) *val))
1249 ++val;
1250 if (0)
1252 #define C(v, m) \
1253 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1255 *ret = v; \
1256 val += sizeof (#v) - 1; \
1257 memspace = m; \
1259 C (omp_default_mem_alloc, false)
1260 C (omp_large_cap_mem_alloc, false)
1261 C (omp_const_mem_alloc, false)
1262 C (omp_high_bw_mem_alloc, false)
1263 C (omp_low_lat_mem_alloc, false)
1264 C (omp_cgroup_mem_alloc, false)
1265 C (omp_pteam_mem_alloc, false)
1266 C (omp_thread_mem_alloc, false)
1267 C (omp_default_mem_space, true)
1268 C (omp_large_cap_mem_space, true)
1269 C (omp_const_mem_space, true)
1270 C (omp_high_bw_mem_space, true)
1271 C (omp_low_lat_mem_space, true)
1272 #undef C
1273 else
1274 goto invalid;
1275 if (memspace && *val == ':')
1277 ++val;
1278 const char *cp = val;
1279 while (*cp != '\0')
1281 if (*cp == '=')
1282 ++ntraits;
1283 ++cp;
1285 traits = gomp_alloca (ntraits * sizeof (omp_alloctrait_t));
1286 size_t n = 0;
1287 while (*val != '\0')
1289 #define C(v) \
1290 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1292 val += sizeof (#v); \
1293 traits[n].key = omp_atk_ ## v;
1294 #define V(v) \
1295 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1297 val += sizeof (#v) - 1; \
1298 traits[n].value = omp_atv_ ## v; \
1300 if (0)
1302 C (sync_hint)
1303 if (0)
1305 V (contended)
1306 V (uncontended)
1307 V (serialized)
1308 V (private)
1309 else
1310 goto invalid;
1312 C (alignment)
1313 char *end;
1314 errno = 0;
1315 traits[n].value = strtol (val, &end, 10);
1316 if (errno || end == val || traits[n].value <= 0)
1317 goto invalid;
1318 val = end;
1320 C (access)
1321 if (0)
1323 V (all)
1324 V (cgroup)
1325 V (pteam)
1326 V (thread)
1327 else
1328 goto invalid;
1330 C (pool_size)
1331 char *end;
1332 errno = 0;
1333 traits[n].value = strtol (val, &end, 10);
1334 if (errno || end == val || traits[n].value <= 0)
1335 goto invalid;
1336 val = end;
1338 C (fallback)
1339 if (0)
1341 V (default_mem_fb)
1342 V (null_fb)
1343 V (abort_fb)
1344 V (allocator_fb)
1345 else
1346 goto invalid;
1348 /* Ignore fb_data, which expects an allocator handle. */
1349 C (pinned)
1350 if (0)
1352 V (true)
1353 V (false)
1354 else
1355 goto invalid;
1357 C (partition)
1358 if (0)
1360 V (environment)
1361 V (nearest)
1362 V (blocked)
1363 V (interleaved)
1364 else
1365 goto invalid;
1367 else
1368 goto invalid;
1369 if (*val != ',')
1370 break;
1371 ++val;
1372 ++n;
1373 if (*val == '\0')
1374 goto invalid;
1376 #undef C
1377 #undef V
1379 else if (memspace)
1380 switch (*ret)
1382 case omp_default_mem_space: *ret = omp_default_mem_alloc; break;
1383 case omp_large_cap_mem_space: *ret = omp_large_cap_mem_alloc; break;
1384 case omp_const_mem_space: *ret = omp_const_mem_alloc; break;
1385 case omp_high_bw_mem_space: *ret = omp_high_bw_mem_alloc; break;
1386 case omp_low_lat_mem_space: *ret = omp_low_lat_mem_alloc; break;
1387 default: __builtin_unreachable ();
1389 while (isspace ((unsigned char) *val))
1390 ++val;
1391 if (*val == '\0')
1393 if (ntraits)
1395 *ret = omp_init_allocator (*ret, ntraits, traits);
1396 if (*ret == omp_null_allocator)
1398 gomp_error ("Allocator of environment variable %.*s cannot be "
1399 "created, using omp_default_mem_alloc instead",
1400 (int) (orig_val - env - 1), env);
1401 *ret = omp_default_mem_alloc;
1403 else
1404 gomp_def_allocator_envvar = strdup (orig_val);
1406 return true;
1408 invalid:
1409 int len = (orig_val - env - 1);
1410 if (*val == '\0')
1411 gomp_error ("Missing value at the end of environment variable %s", env);
1412 else
1413 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1414 len, env, val);
1415 *ret = omp_default_mem_alloc;
1416 return false;
1419 static void
1420 parse_acc_device_type (void)
1422 const char *env = getenv ("ACC_DEVICE_TYPE");
1424 if (env && *env != '\0')
1425 goacc_device_type = strdup (env);
1426 else
1427 goacc_device_type = NULL;
1430 static void
1431 parse_gomp_openacc_dim (void)
1433 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1434 const char *var_name = "GOMP_OPENACC_DIM";
1435 const char *env_var = getenv (var_name);
1436 const char *pos = env_var;
1437 int i;
1439 if (!env_var)
1440 return;
1442 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1444 char *eptr;
1445 long val;
1447 if (i && *pos++ != ':')
1448 break;
1450 if (*pos == ':')
1451 continue;
1453 errno = 0;
1454 val = strtol (pos, &eptr, 10);
1455 if (errno || eptr == pos || val < 0 || (unsigned)val != val)
1456 break;
1458 goacc_default_dims[i] = (int)val;
1459 pos = (const char *) eptr;
1463 /* Helper function for omp_display_env which prints the values of run_sched_var.
1464 'device' can be 'host', 'dev', 'all' or a particular device number. */
1466 static void
1467 print_schedule (enum gomp_schedule_type run_sched_var, int run_sched_chunk_size,
1468 const char *device)
1470 fprintf (stderr, " [%s] OMP_SCHEDULE = '", device);
1471 if ((run_sched_var & GFS_MONOTONIC))
1473 if (run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1474 fputs ("MONOTONIC:", stderr);
1476 else if (run_sched_var == GFS_STATIC)
1477 fputs ("NONMONOTONIC:", stderr);
1478 switch (run_sched_var & ~GFS_MONOTONIC)
1480 case GFS_RUNTIME:
1481 fputs ("RUNTIME", stderr);
1482 if (run_sched_chunk_size != 1)
1483 fprintf (stderr, ",%d", run_sched_chunk_size);
1484 break;
1485 case GFS_STATIC:
1486 fputs ("STATIC", stderr);
1487 if (run_sched_chunk_size != 0)
1488 fprintf (stderr, ",%d", run_sched_chunk_size);
1489 break;
1490 case GFS_DYNAMIC:
1491 fputs ("DYNAMIC", stderr);
1492 if (run_sched_chunk_size != 1)
1493 fprintf (stderr, ",%d", run_sched_chunk_size);
1494 break;
1495 case GFS_GUIDED:
1496 fputs ("GUIDED", stderr);
1497 if (run_sched_chunk_size != 1)
1498 fprintf (stderr, ",%d", run_sched_chunk_size);
1499 break;
1500 case GFS_AUTO:
1501 fputs ("AUTO", stderr);
1502 break;
1504 fputs ("'\n", stderr);
1507 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1508 'device' can be 'host', 'dev', 'all', or a particular device number. */
1510 static void
1511 print_proc_bind (char proc_bind_var, unsigned long len, char **list,
1512 const char *device)
1514 fprintf (stderr, " [%s] OMP_PROC_BIND = '", device);
1515 switch (proc_bind_var)
1517 case omp_proc_bind_false:
1518 fputs ("FALSE", stderr);
1519 break;
1520 case omp_proc_bind_true:
1521 fputs ("TRUE", stderr);
1522 break;
1523 case omp_proc_bind_master:
1524 fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1525 break;
1526 case omp_proc_bind_close:
1527 fputs ("CLOSE", stderr);
1528 break;
1529 case omp_proc_bind_spread:
1530 fputs ("SPREAD", stderr);
1531 break;
1533 for (int i = 1; i < len; i++)
1534 switch ((*list)[i])
1536 case omp_proc_bind_master:
1537 fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1538 break;
1539 case omp_proc_bind_close:
1540 fputs (",CLOSE", stderr);
1541 break;
1542 case omp_proc_bind_spread:
1543 fputs (",SPREAD", stderr);
1544 break;
1546 fputs ("'\n", stderr);
1549 enum gomp_parse_type
1551 PARSE_INT = 1,
1552 PARSE_BOOL = 2,
1553 PARSE_UINT = 3,
1554 PARSE_ULONG = 4,
1555 PARSE_UCHAR = 5,
1556 PARSE_SCHEDULE =6,
1557 PARSE_BIND = 7
1560 /* The following table contains items that help parsing environment variables
1561 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1562 are affected by the environment variable. FLAGS determine what variant of
1563 environment variable is allowed. */
1565 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1566 static const struct envvar
1568 const char *name;
1569 int name_len;
1570 uint8_t flag_vars[3];
1571 uint8_t flag;
1572 bool (*parse_func) (const char *, const char *, void *const[]);
1573 } envvars[] = {
1574 { ENTRY ("SCHEDULE"),
1575 { GOMP_ICV_SCHEDULE, GOMP_ICV_SCHEDULE_CHUNK_SIZE },
1576 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1577 &parse_schedule },
1578 { ENTRY ("NUM_TEAMS"),
1579 { GOMP_ICV_NTEAMS },
1580 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1581 &parse_int },
1582 { ENTRY ("DYNAMIC"),
1583 { GOMP_ICV_DYNAMIC },
1584 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1585 &parse_boolean },
1586 { ENTRY ("TEAMS_THREAD_LIMIT"),
1587 { GOMP_ICV_TEAMS_THREAD_LIMIT },
1588 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1589 &parse_int },
1590 { ENTRY ("THREAD_LIMIT"),
1591 { GOMP_ICV_THREAD_LIMIT },
1592 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1593 &parse_unsigned_long },
1594 { ENTRY ("NUM_THREADS"),
1595 { GOMP_ICV_NTHREADS, GOMP_ICV_NTHREADS_LIST, GOMP_ICV_NTHREADS_LIST_LEN },
1596 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1597 &parse_unsigned_long_list },
1598 { ENTRY ("PROC_BIND"),
1599 { GOMP_ICV_BIND, GOMP_ICV_BIND_LIST, GOMP_ICV_BIND_LIST_LEN },
1600 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1601 &parse_bind_var },
1602 { ENTRY ("MAX_ACTIVE_LEVELS"),
1603 { GOMP_ICV_MAX_ACTIVE_LEVELS },
1604 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1605 &parse_unsigned_long },
1606 { ENTRY ("WAIT_POLICY"),
1607 { GOMP_ICV_WAIT_POLICY },
1608 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1609 &parse_wait_policy },
1610 { ENTRY ("STACKSIZE"),
1611 { GOMP_ICV_STACKSIZE },
1612 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1613 &parse_stacksize },
1614 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION }, 0, &parse_boolean },
1615 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY }, 0,
1616 &parse_boolean },
1617 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD }, 0,
1618 &parse_target_offload },
1619 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY }, 0,
1620 &parse_int },
1621 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR }, 0, &parse_allocator },
1622 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE },
1623 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1624 &parse_int }
1626 #undef ENTRY
1627 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1629 /* The following table is used to apply the hierarchy of ICV variants for host
1630 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1631 undefined. */
1633 static const struct host_envvar
1635 unsigned char flag_var;
1636 void *dest[3];
1637 int type_code;
1638 } host_envvars[] = {
1639 { GOMP_ICV_NTEAMS, { &gomp_nteams_var }, PARSE_INT },
1640 { GOMP_ICV_DYNAMIC, { &gomp_global_icv.dyn_var }, PARSE_BOOL },
1641 { GOMP_ICV_DEFAULT_DEVICE, { &gomp_global_icv.default_device_var },
1642 PARSE_INT },
1643 { GOMP_ICV_TEAMS_THREAD_LIMIT, { &gomp_teams_thread_limit_var }, PARSE_INT },
1644 { GOMP_ICV_SCHEDULE,
1645 { &gomp_global_icv.run_sched_var, &gomp_global_icv.run_sched_chunk_size },
1646 PARSE_SCHEDULE },
1647 { GOMP_ICV_THREAD_LIMIT, { &gomp_global_icv.thread_limit_var }, PARSE_UINT },
1648 { GOMP_ICV_NTHREADS,
1649 { &gomp_global_icv.nthreads_var, &gomp_nthreads_var_list,
1650 &gomp_nthreads_var_list_len }, PARSE_ULONG },
1651 { GOMP_ICV_BIND,
1652 { &gomp_global_icv.bind_var, &gomp_bind_var_list, &gomp_bind_var_list_len },
1653 PARSE_BIND },
1654 { GOMP_ICV_MAX_ACTIVE_LEVELS, { &gomp_global_icv.max_active_levels_var },
1655 PARSE_UCHAR },
1657 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1659 #define INT_MAX_STR_LEN 10
1661 bool
1662 gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv)
1664 return value & (1 << (icv - 1));
1667 static void
1668 gomp_set_icv_flag (uint32_t *value, enum gomp_icvs icv)
1670 *value |= 1 << (icv - 1);
1673 static void
1674 print_device_specific_icvs (int icv_code)
1676 struct gomp_icv_list *list = gomp_initial_icv_list;
1677 int i;
1678 char dev_num[INT_MAX_STR_LEN + 1];
1680 while (list != NULL)
1682 if (list->device_num < 0)
1684 list = list->next;
1685 continue;
1688 switch (icv_code)
1690 case GOMP_ICV_NTEAMS:
1691 if (gomp_get_icv_flag (list->flags, GOMP_ICV_NTEAMS))
1692 fprintf (stderr, " [%d] OMP_NUM_TEAMS = '%d'\n",
1693 list->device_num, list->icvs.nteams_var);
1694 break;
1695 case GOMP_ICV_DYNAMIC:
1696 if (gomp_get_icv_flag (list->flags, GOMP_ICV_DYNAMIC))
1697 fprintf (stderr, " [%d] OMP_DYNAMIC = '%s'\n",
1698 list->device_num, list->icvs.dyn_var ? "TRUE" : "FALSE");
1699 break;
1700 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1701 if (gomp_get_icv_flag (list->flags, GOMP_ICV_TEAMS_THREAD_LIMIT))
1702 fprintf (stderr, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1703 list->device_num, list->icvs.teams_thread_limit_var);
1704 break;
1705 case GOMP_ICV_SCHEDULE:
1706 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_SCHEDULE)))
1707 break;
1708 sprintf (dev_num, "%d", list->device_num);
1709 print_schedule (list->icvs.run_sched_var,
1710 list->icvs.run_sched_chunk_size,
1711 dev_num);
1712 break;
1713 case GOMP_ICV_THREAD_LIMIT:
1714 if (gomp_get_icv_flag (list->flags, GOMP_ICV_THREAD_LIMIT))
1715 fprintf (stderr, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1716 list->device_num, list->icvs.thread_limit_var);
1717 break;
1718 case GOMP_ICV_NTHREADS:
1719 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_NTHREADS)))
1720 break;
1721 fprintf (stderr, " [%d] OMP_NUM_THREADS = '%lu", list->device_num,
1722 list->icvs.nthreads_var);
1723 for (i = 1; i < list->icvs.nthreads_var_list_len; i++)
1724 fprintf (stderr, ",%lu", list->icvs.nthreads_var_list[i]);
1725 fputs ("'\n", stderr);
1726 break;
1727 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1728 fprintf (stderr, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1729 list->device_num, list->icvs.max_active_levels_var);
1730 break;
1731 case GOMP_ICV_BIND:
1732 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_BIND)))
1733 break;
1734 sprintf (dev_num, "%d", list->device_num);
1735 print_proc_bind (list->icvs.bind_var, list->icvs.bind_var_list_len,
1736 &list->icvs.bind_var_list, dev_num);
1737 break;
1738 case GOMP_ICV_WAIT_POLICY:
1739 if (gomp_get_icv_flag (list->flags, GOMP_ICV_WAIT_POLICY))
1740 fprintf (stderr, " [%d] OMP_WAIT_POLICY = '%s'\n",
1741 list->device_num,
1742 list->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1743 break;
1744 case GOMP_ICV_STACKSIZE:
1745 if (gomp_get_icv_flag (list->flags, GOMP_ICV_STACKSIZE))
1746 fprintf (stderr, " [%d] OMP_STACKSIZE = '%lu'\n",
1747 list->device_num, list->icvs.stacksize);
1748 break;
1750 list = list->next;
1754 void
1755 omp_display_env (int verbose)
1757 int i;
1758 struct gomp_icv_list *dev
1759 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV);
1760 struct gomp_icv_list *all
1761 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
1762 struct gomp_icv_list *none
1763 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
1765 if (none->icvs.default_device_var == INT_MIN)
1766 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1767 gomp_init_targets_once ();
1769 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1771 fputs (" _OPENMP = '201511'\n", stderr);
1773 fprintf (stderr, " [host] OMP_DYNAMIC = '%s'\n",
1774 none->icvs.dyn_var ? "TRUE" : "FALSE");
1775 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_DYNAMIC))
1776 fprintf (stderr, " [all] OMP_DYNAMIC = '%s'\n",
1777 all->icvs.dyn_var ? "TRUE" : "FALSE");
1778 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_DYNAMIC))
1779 fprintf (stderr, " [device] OMP_DYNAMIC = '%s'\n",
1780 dev->icvs.dyn_var ? "TRUE" : "FALSE");
1781 print_device_specific_icvs (GOMP_ICV_DYNAMIC);
1783 /* The OMP_NESTED environment variable has been deprecated. */
1784 fprintf (stderr, " [host] OMP_NESTED = '%s'\n",
1785 none->icvs.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1787 fprintf (stderr, " [host] OMP_NUM_THREADS = '%lu",
1788 none->icvs.nthreads_var);
1789 for (i = 1; i < none->icvs.nthreads_var_list_len; i++)
1790 fprintf (stderr, ",%lu", none->icvs.nthreads_var_list[i]);
1791 fputs ("'\n", stderr);
1792 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTHREADS))
1794 fprintf (stderr, " [all] OMP_NUM_THREADS = '%lu",
1795 all->icvs.nthreads_var);
1796 for (i = 1; i < all->icvs.nthreads_var_list_len; i++)
1797 fprintf (stderr, ",%lu", all->icvs.nthreads_var_list[i]);
1798 fputs ("'\n", stderr);
1800 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTHREADS))
1802 fprintf (stderr, " [device] OMP_NUM_THREADS = '%lu",
1803 dev->icvs.nthreads_var);
1804 for (i = 1; i < dev->icvs.nthreads_var_list_len; i++)
1805 fprintf (stderr, ",%lu", dev->icvs.nthreads_var_list[i]);
1806 fputs ("'\n", stderr);
1808 print_device_specific_icvs (GOMP_ICV_NTHREADS);
1811 print_schedule (none->icvs.run_sched_var,
1812 none->icvs.run_sched_chunk_size, "host");
1813 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_SCHEDULE))
1814 print_schedule (all->icvs.run_sched_var,
1815 all->icvs.run_sched_chunk_size, "all");
1816 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_SCHEDULE))
1817 print_schedule (dev->icvs.run_sched_var,
1818 dev->icvs.run_sched_chunk_size, "device");
1819 print_device_specific_icvs (GOMP_ICV_SCHEDULE);
1821 print_proc_bind (none->icvs.bind_var,
1822 none->icvs.bind_var_list_len,
1823 &none->icvs.bind_var_list, "host");
1824 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND))
1825 print_proc_bind (all->icvs.bind_var,
1826 all->icvs.bind_var_list_len,
1827 &all->icvs.bind_var_list, "all");
1828 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_BIND))
1829 print_proc_bind (dev->icvs.bind_var,
1830 dev->icvs.bind_var_list_len,
1831 &dev->icvs.bind_var_list, "device");
1832 print_device_specific_icvs (GOMP_ICV_BIND);
1834 fputs (" [host] OMP_PLACES = '", stderr);
1835 for (i = 0; i < gomp_places_list_len; i++)
1837 fputs ("{", stderr);
1838 gomp_affinity_print_place (gomp_places_list[i]);
1839 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1841 fputs ("'\n", stderr);
1843 fprintf (stderr, " [host] OMP_STACKSIZE = '%lu'\n",
1844 none->icvs.stacksize);
1845 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
1846 fprintf (stderr, " [all] OMP_STACKSIZE = '%lu'\n",
1847 all->icvs.stacksize);
1848 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_STACKSIZE))
1849 fprintf (stderr, " [device] OMP_STACKSIZE = '%lu'\n",
1850 dev->icvs.stacksize);
1851 print_device_specific_icvs (GOMP_ICV_STACKSIZE);
1853 /* GOMP's default value is actually neither active nor passive. */
1854 fprintf (stderr, " [host] OMP_WAIT_POLICY = '%s'\n",
1855 none->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1856 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
1857 fprintf (stderr, " [all] OMP_WAIT_POLICY = '%s'\n",
1858 all->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1859 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_WAIT_POLICY))
1860 fprintf (stderr, " [device] OMP_WAIT_POLICY = '%s'\n",
1861 dev->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1862 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY);
1864 fprintf (stderr, " [host] OMP_THREAD_LIMIT = '%u'\n",
1865 none->icvs.thread_limit_var);
1866 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_THREAD_LIMIT))
1867 fprintf (stderr, " [all] OMP_THREAD_LIMIT = '%d'\n",
1868 all->icvs.thread_limit_var);
1869 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_THREAD_LIMIT))
1870 fprintf (stderr, " [device] OMP_THREAD_LIMIT = '%d'\n",
1871 dev->icvs.thread_limit_var);
1872 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT);
1874 fprintf (stderr, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1875 none->icvs.max_active_levels_var);
1876 if (all != NULL && gomp_get_icv_flag (all->flags,
1877 GOMP_ICV_MAX_ACTIVE_LEVELS))
1878 fprintf (stderr, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1879 all->icvs.max_active_levels_var);
1880 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1881 GOMP_ICV_MAX_ACTIVE_LEVELS))
1882 fprintf (stderr, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1883 dev->icvs.max_active_levels_var);
1884 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS);
1887 fprintf (stderr, " [host] OMP_NUM_TEAMS = '%d'\n",
1888 none->icvs.nteams_var);
1889 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTEAMS))
1890 fprintf (stderr, " [all] OMP_NUM_TEAMS = '%d'\n",
1891 all->icvs.nteams_var);
1892 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTEAMS))
1893 fprintf (stderr, " [device] OMP_NUM_TEAMS = '%d'\n",
1894 dev->icvs.nteams_var);
1895 print_device_specific_icvs (GOMP_ICV_NTEAMS);
1897 fprintf (stderr, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1898 none->icvs.teams_thread_limit_var);
1899 if (all != NULL && gomp_get_icv_flag (all->flags,
1900 GOMP_ICV_TEAMS_THREAD_LIMIT))
1901 fprintf (stderr, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1902 all->icvs.teams_thread_limit_var);
1903 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1904 GOMP_ICV_TEAMS_THREAD_LIMIT))
1905 fprintf (stderr, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1906 dev->icvs.teams_thread_limit_var);
1907 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT);
1909 fprintf (stderr, " [all] OMP_CANCELLATION = '%s'\n",
1910 gomp_cancel_var ? "TRUE" : "FALSE");
1912 fprintf (stderr, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1913 none->icvs.default_device_var);
1915 fprintf (stderr, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1916 gomp_max_task_priority_var);
1917 fprintf (stderr, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1918 gomp_display_affinity_var ? "TRUE" : "FALSE");
1919 fprintf (stderr, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1920 gomp_affinity_format_var);
1921 fprintf (stderr, " [host] OMP_ALLOCATOR = '");
1922 switch (gomp_def_allocator)
1924 #define C(v) case v: fputs (#v, stderr); break;
1925 C (omp_default_mem_alloc)
1926 C (omp_large_cap_mem_alloc)
1927 C (omp_const_mem_alloc)
1928 C (omp_high_bw_mem_alloc)
1929 C (omp_low_lat_mem_alloc)
1930 C (omp_cgroup_mem_alloc)
1931 C (omp_pteam_mem_alloc)
1932 C (omp_thread_mem_alloc)
1933 #undef C
1934 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1935 default:
1936 if (gomp_def_allocator_envvar)
1937 fputs (gomp_def_allocator_envvar, stderr);
1938 break;
1940 fputs ("'\n", stderr);
1942 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr);
1943 switch (gomp_target_offload_var)
1945 case GOMP_TARGET_OFFLOAD_DEFAULT:
1946 fputs ("DEFAULT", stderr);
1947 break;
1948 case GOMP_TARGET_OFFLOAD_MANDATORY:
1949 fputs ("MANDATORY", stderr);
1950 break;
1951 case GOMP_TARGET_OFFLOAD_DISABLED:
1952 fputs ("DISABLED", stderr);
1953 break;
1955 fputs ("'\n", stderr);
1957 if (verbose)
1959 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr);
1960 fprintf (stderr, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize);
1961 #ifdef HAVE_INTTYPES_H
1962 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%"PRIu64"'\n",
1963 (uint64_t) gomp_spin_count_var);
1964 #else
1965 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%lu'\n",
1966 (unsigned long) gomp_spin_count_var);
1967 #endif
1970 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1972 ialias (omp_display_env)
1974 static void
1975 handle_omp_display_env (void)
1977 const char *env;
1978 bool display = false;
1979 bool verbose = false;
1981 env = getenv ("OMP_DISPLAY_ENV");
1982 if (env == NULL)
1983 return;
1985 while (isspace ((unsigned char) *env))
1986 ++env;
1987 if (strncasecmp (env, "true", 4) == 0)
1989 display = true;
1990 env += 4;
1992 else if (strncasecmp (env, "false", 5) == 0)
1994 display = false;
1995 env += 5;
1997 else if (strncasecmp (env, "verbose", 7) == 0)
1999 display = true;
2000 verbose = true;
2001 env += 7;
2003 else
2004 env = "X";
2005 while (isspace ((unsigned char) *env))
2006 ++env;
2007 if (*env != '\0')
2008 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2010 if (display)
2011 ialias_call (omp_display_env) (verbose);
2014 /* Helper function for initialize_env. Extracts the device number from
2015 an environment variable name. ENV is the complete environment variable.
2016 DEV_NUM_PTR points to the start of the device number in the environment
2017 variable string. DEV_NUM_LEN is the returned length of the device num
2018 string. */
2020 static bool
2021 get_device_num (char *env, char *dev_num_ptr, int *dev_num, int *dev_num_len)
2023 char *end;
2024 unsigned long val = strtoul (dev_num_ptr, &end, 10);
2025 if (val > INT_MAX
2026 || *end != '='
2027 || (dev_num_ptr[0] == '0' && end != dev_num_ptr + 1)
2028 || (dev_num_ptr[0] < '0' || dev_num_ptr[0] > '9'))
2030 gomp_error ("Invalid device number in %s", env);
2031 return false;
2033 *dev_num = val;
2034 *dev_num_len = end - dev_num_ptr;
2035 return true;
2038 static void
2039 get_icv_member_addr (struct gomp_initial_icvs *icvs, int icv_code,
2040 void *icv_addr[3])
2042 if (icv_code == 0 || icv_addr == NULL)
2043 return;
2045 icv_addr[0] = icv_addr[1] = icv_addr[2] = NULL;
2047 switch (icv_code)
2049 case GOMP_ICV_NTEAMS:
2050 icv_addr[0] = &icvs->nteams_var;
2051 /* icv_addr[1] = (void *) false; */
2052 break;
2053 case GOMP_ICV_DYNAMIC:
2054 icv_addr[0] = &(*icvs).dyn_var;
2055 break;
2056 case GOMP_ICV_TEAMS_THREAD_LIMIT:
2057 icv_addr[0] = &icvs->teams_thread_limit_var;
2058 /* icv_addr[1] = (void *) false; */
2059 break;
2060 case GOMP_ICV_SCHEDULE:
2061 icv_addr[0] = &icvs->run_sched_var;
2062 icv_addr[1] = &icvs->run_sched_chunk_size;
2063 break;
2064 case GOMP_ICV_THREAD_LIMIT:
2065 icv_addr[0] = &icvs->thread_limit_var;
2066 /* icv_addr[1] = (void *) false; */
2067 icv_addr[2] = (void *) UINT_MAX;
2068 break;
2069 case GOMP_ICV_NTHREADS:
2070 icv_addr[0] = &icvs->nthreads_var;
2071 icv_addr[1] = &icvs->nthreads_var_list;
2072 icv_addr[2] = &icvs->nthreads_var_list_len;
2073 break;
2074 case GOMP_ICV_MAX_ACTIVE_LEVELS:
2075 icv_addr[0] = &icvs->max_active_levels_var;
2076 icv_addr[1] = (void *) true;
2077 icv_addr[2] = (void *) gomp_supported_active_levels;
2078 break;
2079 case GOMP_ICV_BIND:
2080 icv_addr[0] = &icvs->bind_var;
2081 icv_addr[1] = &icvs->bind_var_list;
2082 icv_addr[2] = &icvs->bind_var_list_len;
2083 break;
2084 case GOMP_ICV_WAIT_POLICY:
2085 icv_addr[0] = &icvs->wait_policy;
2086 break;
2087 case GOMP_ICV_STACKSIZE:
2088 icv_addr[0] = &icvs->stacksize;
2089 break;
2090 case GOMP_ICV_CANCELLATION:
2091 icv_addr[0] = &gomp_cancel_var;
2092 break;
2093 case GOMP_ICV_DISPLAY_AFFINITY:
2094 icv_addr[0] = &gomp_display_affinity_var;
2095 break;
2096 case GOMP_ICV_TARGET_OFFLOAD:
2097 icv_addr[0] = &gomp_target_offload_var;
2098 break;
2099 case GOMP_ICV_MAX_TASK_PRIORITY:
2100 icv_addr[0] = &gomp_max_task_priority_var;
2101 break;
2102 case GOMP_ICV_ALLOCATOR:
2103 icv_addr[0] = &gomp_def_allocator;
2104 break;
2105 case GOMP_ICV_DEFAULT_DEVICE:
2106 icv_addr[0] = &icvs->default_device_var;
2107 icv_addr[1] = (void *) true;
2108 break;
2112 struct gomp_icv_list *
2113 gomp_get_initial_icv_item (int dev_num)
2115 struct gomp_icv_list *l = gomp_initial_icv_list;
2116 while (l != NULL && l->device_num != dev_num)
2117 l = l->next;
2119 return l;
2122 static void
2123 initialize_icvs (struct gomp_initial_icvs *icvs)
2125 icvs->nthreads_var_list = NULL;
2126 icvs->bind_var_list = NULL;
2127 icvs->nthreads_var = gomp_default_icv_values.nthreads_var;
2128 icvs->nthreads_var_list_len = 0;
2129 icvs->bind_var_list_len = 0;
2130 icvs->stacksize = 0;
2131 icvs->thread_limit_var = gomp_default_icv_values.thread_limit_var;
2132 icvs->run_sched_var = gomp_default_icv_values.run_sched_var;
2133 icvs->run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size;
2134 icvs->default_device_var = gomp_default_icv_values.default_device_var;
2135 icvs->dyn_var = gomp_default_icv_values.dyn_var;
2136 icvs->max_active_levels_var = gomp_default_icv_values.max_active_levels_var;
2137 icvs->bind_var = gomp_default_icv_values.bind_var;
2138 icvs->nteams_var = gomp_default_icv_values.nteams_var;
2139 icvs->teams_thread_limit_var = gomp_default_icv_values.teams_thread_limit_var;
2140 icvs->wait_policy = -1;
2143 /* Helper function for initialize_env to add a device specific ICV value
2144 to gomp_initial_icv_list. */
2146 static uint32_t *
2147 add_initial_icv_to_list (int dev_num, int icv_code, void *icv_addr[3])
2149 struct gomp_icv_list *last = NULL, *l = gomp_initial_icv_list;
2150 while (l != NULL && l->device_num != dev_num)
2152 last = l;
2153 l = l->next;
2156 if (l == NULL)
2158 l = ((struct gomp_icv_list *)
2159 gomp_malloc_cleared (sizeof (struct gomp_icv_list)));
2160 l->device_num = dev_num;
2161 initialize_icvs (&l->icvs);
2162 if (dev_num < 0)
2164 l->next = gomp_initial_icv_list;
2165 gomp_initial_icv_list = l;
2167 else
2169 l->next = NULL;
2170 if (last == NULL)
2171 gomp_initial_icv_list = l;
2172 else
2173 last->next = l;
2177 get_icv_member_addr (&l->icvs, icv_code, icv_addr);
2179 return &l->flags;
2182 /* Return true if STR string starts with PREFIX. */
2184 static inline bool
2185 startswith (const char *str, const char *prefix)
2187 return strncmp (str, prefix, strlen (prefix)) == 0;
2190 static void __attribute__((destructor))
2191 cleanup_env (void)
2193 if (gomp_def_allocator_envvar != NULL)
2195 free (gomp_def_allocator_envvar);
2196 omp_destroy_allocator (gomp_def_allocator);
2200 static void __attribute__((constructor))
2201 initialize_env (void)
2203 char **env;
2204 int omp_var, dev_num = 0, dev_num_len = 0, i;
2205 bool ignore = false;
2206 char *env_val;
2207 void *params[3];
2208 uint32_t *flag_var_addr = NULL;
2209 unsigned pos;
2210 struct gomp_icv_list *all, *none;
2212 /* Do a compile time check that mkomp_h.pl did good job. */
2213 omp_check_defines ();
2215 #ifndef HAVE_SYNC_BUILTINS
2216 gomp_mutex_init (&gomp_managed_threads_lock);
2217 #endif
2218 gomp_init_num_threads ();
2219 gomp_available_cpus = gomp_global_icv.nthreads_var;
2221 /* Initial values for host environment variables should always exist even if
2222 there is no explicitly set host environment variable. Moreover, they are
2223 set to the initial global values. */
2224 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX, 0, NULL);
2225 none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
2226 initialize_icvs (&none->icvs);
2228 if (environ)
2229 for (env = environ; *env != 0; env++)
2231 if (!startswith (*env, "OMP_"))
2232 continue;
2234 /* Name of the environment variable without suffix "OMP_". */
2235 char *name = *env + sizeof ("OMP_") - 1;
2236 for (omp_var = 0; omp_var < OMP_VAR_CNT; omp_var++)
2238 if (startswith (name, envvars[omp_var].name))
2240 pos = envvars[omp_var].name_len;
2241 if (name[pos] == '=')
2243 pos++;
2244 flag_var_addr
2245 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX,
2246 envvars[omp_var].flag_vars[0],
2247 params);
2249 else if (startswith (&name[pos], "_DEV=")
2250 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV)
2252 pos += 5;
2253 flag_var_addr
2254 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV,
2255 envvars[omp_var].flag_vars[0],
2256 params);
2258 else if (startswith (&name[pos], "_ALL=")
2259 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_ALL)
2261 pos += 5;
2262 flag_var_addr
2263 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL,
2264 envvars[omp_var].flag_vars[0],
2265 params);
2267 else if (startswith (&name[pos], "_DEV_")
2268 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV_X)
2270 pos += 5;
2271 if (!get_device_num (*env, &name[pos], &dev_num,
2272 &dev_num_len))
2273 break;
2275 pos += dev_num_len + 1;
2276 flag_var_addr
2277 = add_initial_icv_to_list (dev_num,
2278 envvars[omp_var].flag_vars[0],
2279 params);
2281 else
2283 gomp_error ("Invalid environment variable in %s", *env);
2284 break;
2286 env_val = &name[pos];
2288 if (envvars[omp_var].parse_func (*env, env_val, params))
2290 for (i = 0; i < 3; ++i)
2291 if (envvars[omp_var].flag_vars[i])
2292 gomp_set_icv_flag (flag_var_addr,
2293 envvars[omp_var].flag_vars[i]);
2294 else
2295 break;
2298 break;
2303 all = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
2304 for (omp_var = 0; omp_var < OMP_HOST_VAR_CNT; omp_var++)
2306 if (none != NULL
2307 && gomp_get_icv_flag (none->flags, host_envvars[omp_var].flag_var))
2308 get_icv_member_addr (&none->icvs,
2309 host_envvars[omp_var].flag_var, params);
2310 else if (all != NULL
2311 && gomp_get_icv_flag (all->flags,
2312 host_envvars[omp_var].flag_var))
2313 get_icv_member_addr (&all->icvs, host_envvars[omp_var].flag_var,
2314 params);
2315 else
2316 continue;
2318 switch (host_envvars[omp_var].type_code)
2320 case PARSE_INT:
2321 for (i = 0; i < 3; ++i)
2322 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2323 *(int *) (host_envvars[omp_var].dest[i]) = *(int *) params[i];
2324 break;
2325 case PARSE_BOOL:
2326 for (i = 0; i < 3; ++i)
2327 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2328 *(bool *) (host_envvars[omp_var].dest[i]) = *(bool *) params[i];
2329 break;
2330 case PARSE_UINT:
2331 for (i = 0; i < 3; ++i)
2332 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2333 *(unsigned int *) (host_envvars[omp_var].dest[i])
2334 = *(unsigned int *) params[i];
2335 break;
2336 case PARSE_ULONG:
2337 for (i = 0; i < 3; ++i)
2338 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2339 *(unsigned long *) (host_envvars[omp_var].dest[i])
2340 = *(unsigned long *) params[i];
2341 break;
2342 case PARSE_UCHAR:
2343 for (i = 0; i < 3; ++i)
2344 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2345 *(unsigned char *) (host_envvars[omp_var].dest[i])
2346 = *(unsigned char *) params[i];
2347 break;
2348 case PARSE_SCHEDULE:
2349 *(enum gomp_schedule_type *) (host_envvars[omp_var].dest[0])
2350 = *(enum gomp_schedule_type *) params[0];
2351 *(int *) (host_envvars[omp_var].dest[1]) = *(int *) params[1];
2352 break;
2353 case PARSE_BIND:
2354 *(char *) (host_envvars[omp_var].dest[0]) = *(char *) params[0];
2355 *(char **) (host_envvars[omp_var].dest[1]) = *(char **) params[1];
2356 *(unsigned long *) (host_envvars[omp_var].dest[2])
2357 = *(unsigned long *) params[2];
2358 break;
2362 if (((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_BIND))
2363 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND)))
2364 && gomp_global_icv.bind_var == omp_proc_bind_false)
2365 ignore = true;
2367 if (!((none != NULL
2368 && gomp_get_icv_flag (none->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))
2369 || (all != NULL
2370 && gomp_get_icv_flag (all->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))))
2372 bool nested = true;
2373 const char *env = getenv ("OMP_NESTED");
2375 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2376 if (parse_boolean ("OMP_NESTED", env, (void *[]) {&nested}))
2377 gomp_global_icv.max_active_levels_var
2378 = nested ? gomp_supported_active_levels : 1;
2379 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
2380 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
2383 if (gomp_global_icv.default_device_var == INT_MIN
2384 && gomp_target_offload_var != GOMP_TARGET_OFFLOAD_MANDATORY)
2385 none->icvs.default_device_var = gomp_global_icv.default_device_var = 0;
2387 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2388 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
2390 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2391 parsed if present in the environment. If OMP_PROC_BIND was set
2392 explicitly to false, don't populate places list though. If places
2393 list was successfully set from OMP_PLACES, only parse but don't process
2394 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2395 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2396 was successfully parsed into a places list, otherwise to
2397 OMP_PROC_BIND=false. */
2398 if (parse_places_var ("OMP_PLACES", ignore))
2400 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2401 gomp_global_icv.bind_var = true;
2402 ignore = true;
2404 if (parse_affinity (ignore))
2406 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2407 gomp_global_icv.bind_var = true;
2408 ignore = true;
2410 if (gomp_global_icv.bind_var != omp_proc_bind_false)
2411 gomp_init_affinity ();
2414 const char *env = getenv ("OMP_AFFINITY_FORMAT");
2415 if (env != NULL)
2416 gomp_set_affinity_format (env, strlen (env));
2419 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_WAIT_POLICY))
2420 wait_policy = none->icvs.wait_policy;
2421 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
2422 wait_policy = all->icvs.wait_policy;
2424 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
2426 /* Using a rough estimation of 100000 spins per msec,
2427 use 5 min blocking for OMP_WAIT_POLICY=active,
2428 3 msec blocking when OMP_WAIT_POLICY is not specificed
2429 and 0 when OMP_WAIT_POLICY=passive.
2430 Depending on the CPU speed, this can be e.g. 5 times longer
2431 or 5 times shorter. */
2432 if (wait_policy > 0)
2433 gomp_spin_count_var = 30000000000LL;
2434 else if (wait_policy < 0)
2436 gomp_spin_count_var = 300000LL;
2437 do_adjust_default_spincount ();
2440 /* gomp_throttled_spin_count_var is used when there are more libgomp
2441 managed threads than available CPUs. Use very short spinning. */
2442 if (wait_policy > 0)
2443 gomp_throttled_spin_count_var = 1000LL;
2444 else if (wait_policy < 0)
2445 gomp_throttled_spin_count_var = 100LL;
2446 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
2447 gomp_throttled_spin_count_var = gomp_spin_count_var;
2449 /* Not strictly environment related, but ordering constructors is tricky. */
2450 pthread_attr_init (&gomp_thread_attr);
2452 if (!(none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE)))
2454 const char *env = getenv ("GOMP_STACKSIZE");
2455 if (env != NULL
2456 && parse_stacksize ("GOMP_STACKSIZE", env,
2457 (void *[3]) {&none->icvs.stacksize}))
2458 gomp_set_icv_flag (&none->flags, GOMP_ICV_STACKSIZE);
2460 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2461 stacksize = none->icvs.stacksize;
2462 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2463 stacksize = all->icvs.stacksize;
2465 if ((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2466 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2467 || GOMP_DEFAULT_STACKSIZE)
2469 int err;
2471 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
2473 #ifdef PTHREAD_STACK_MIN
2474 if (err == EINVAL)
2476 if (stacksize < PTHREAD_STACK_MIN)
2477 gomp_error ("Stack size less than minimum of %luk",
2478 PTHREAD_STACK_MIN / 1024ul
2479 + (PTHREAD_STACK_MIN % 1024 != 0));
2480 else
2481 gomp_error ("Stack size larger than system limit");
2483 else
2484 #endif
2485 if (err != 0)
2486 gomp_error ("Stack size change failed: %s", strerror (err));
2489 handle_omp_display_env ();
2491 /* OpenACC. */
2493 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2494 (void *[]) {&goacc_device_num, (void *) true}))
2495 goacc_device_num = 0;
2497 parse_acc_device_type ();
2498 parse_gomp_openacc_dim ();
2500 goacc_runtime_initialize ();
2502 goacc_profiling_initialize ();
2504 #endif /* LIBGOMP_OFFLOADED_ONLY */