[PR testsuite/116860] Testsuite adjustment for recently added tests
[gcc.git] / libgomp / env.c
blob626a753ca71b265dac8db00973f033a2bcca5f15
1 /* Copyright (C) 2005-2025 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 (ompx_gnu_pinned_mem_alloc, false)
1268 C (omp_default_mem_space, true)
1269 C (omp_large_cap_mem_space, true)
1270 C (omp_const_mem_space, true)
1271 C (omp_high_bw_mem_space, true)
1272 C (omp_low_lat_mem_space, true)
1273 #undef C
1274 else
1275 goto invalid;
1276 if (memspace && *val == ':')
1278 ++val;
1279 const char *cp = val;
1280 while (*cp != '\0')
1282 if (*cp == '=')
1283 ++ntraits;
1284 ++cp;
1286 traits = gomp_alloca (ntraits * sizeof (omp_alloctrait_t));
1287 size_t n = 0;
1288 while (*val != '\0')
1290 #define C(v) \
1291 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1293 val += sizeof (#v); \
1294 traits[n].key = omp_atk_ ## v;
1295 #define V(v) \
1296 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1298 val += sizeof (#v) - 1; \
1299 traits[n].value = omp_atv_ ## v; \
1301 if (0)
1303 C (sync_hint)
1304 if (0)
1306 V (contended)
1307 V (uncontended)
1308 V (serialized)
1309 V (private)
1310 else
1311 goto invalid;
1313 C (alignment)
1314 char *end;
1315 errno = 0;
1316 traits[n].value = strtol (val, &end, 10);
1317 if (errno || end == val || traits[n].value <= 0)
1318 goto invalid;
1319 val = end;
1321 C (access)
1322 if (0)
1324 V (all)
1325 V (cgroup)
1326 V (pteam)
1327 V (thread)
1328 else
1329 goto invalid;
1331 C (pool_size)
1332 char *end;
1333 errno = 0;
1334 traits[n].value = strtol (val, &end, 10);
1335 if (errno || end == val || traits[n].value <= 0)
1336 goto invalid;
1337 val = end;
1339 C (fallback)
1340 if (0)
1342 V (default_mem_fb)
1343 V (null_fb)
1344 V (abort_fb)
1345 V (allocator_fb)
1346 else
1347 goto invalid;
1349 /* Ignore fb_data, which expects an allocator handle. */
1350 C (pinned)
1351 if (0)
1353 V (true)
1354 V (false)
1355 else
1356 goto invalid;
1358 C (partition)
1359 if (0)
1361 V (environment)
1362 V (nearest)
1363 V (blocked)
1364 V (interleaved)
1365 else
1366 goto invalid;
1368 else
1369 goto invalid;
1370 if (*val != ',')
1371 break;
1372 ++val;
1373 ++n;
1374 if (*val == '\0')
1375 goto invalid;
1377 #undef C
1378 #undef V
1380 else if (memspace)
1381 switch (*ret)
1383 case omp_default_mem_space: *ret = omp_default_mem_alloc; break;
1384 case omp_large_cap_mem_space: *ret = omp_large_cap_mem_alloc; break;
1385 case omp_const_mem_space: *ret = omp_const_mem_alloc; break;
1386 case omp_high_bw_mem_space: *ret = omp_high_bw_mem_alloc; break;
1387 case omp_low_lat_mem_space: *ret = omp_low_lat_mem_alloc; break;
1388 default: __builtin_unreachable ();
1390 while (isspace ((unsigned char) *val))
1391 ++val;
1392 if (*val == '\0')
1394 if (ntraits)
1396 *ret = omp_init_allocator (*ret, ntraits, traits);
1397 if (*ret == omp_null_allocator)
1399 gomp_error ("Allocator of environment variable %.*s cannot be "
1400 "created, using omp_default_mem_alloc instead",
1401 (int) (orig_val - env - 1), env);
1402 *ret = omp_default_mem_alloc;
1404 else
1405 gomp_def_allocator_envvar = strdup (orig_val);
1407 return true;
1409 invalid:
1410 int len = (orig_val - env - 1);
1411 if (*val == '\0')
1412 gomp_error ("Missing value at the end of environment variable %s", env);
1413 else
1414 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1415 len, env, val);
1416 *ret = omp_default_mem_alloc;
1417 return false;
1420 static void
1421 parse_acc_device_type (void)
1423 const char *env = getenv ("ACC_DEVICE_TYPE");
1425 if (env && *env != '\0')
1426 goacc_device_type = strdup (env);
1427 else
1428 goacc_device_type = NULL;
1431 static void
1432 parse_gomp_openacc_dim (void)
1434 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1435 const char *var_name = "GOMP_OPENACC_DIM";
1436 const char *env_var = getenv (var_name);
1437 const char *pos = env_var;
1438 int i;
1440 if (!env_var)
1441 return;
1443 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1445 char *eptr;
1446 long val;
1448 if (i && *pos++ != ':')
1449 break;
1451 if (*pos == ':')
1452 continue;
1454 errno = 0;
1455 val = strtol (pos, &eptr, 10);
1456 if (errno || eptr == pos || val < 0 || (unsigned)val != val)
1457 break;
1459 goacc_default_dims[i] = (int)val;
1460 pos = (const char *) eptr;
1464 /* Helper function for omp_display_env which prints the values of run_sched_var.
1465 'device' can be 'host', 'dev', 'all' or a particular device number. */
1467 static void
1468 print_schedule (enum gomp_schedule_type run_sched_var, int run_sched_chunk_size,
1469 const char *device)
1471 fprintf (stderr, " [%s] OMP_SCHEDULE = '", device);
1472 if ((run_sched_var & GFS_MONOTONIC))
1474 if (run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1475 fputs ("MONOTONIC:", stderr);
1477 else if (run_sched_var == GFS_STATIC)
1478 fputs ("NONMONOTONIC:", stderr);
1479 switch (run_sched_var & ~GFS_MONOTONIC)
1481 case GFS_RUNTIME:
1482 fputs ("RUNTIME", stderr);
1483 if (run_sched_chunk_size != 1)
1484 fprintf (stderr, ",%d", run_sched_chunk_size);
1485 break;
1486 case GFS_STATIC:
1487 fputs ("STATIC", stderr);
1488 if (run_sched_chunk_size != 0)
1489 fprintf (stderr, ",%d", run_sched_chunk_size);
1490 break;
1491 case GFS_DYNAMIC:
1492 fputs ("DYNAMIC", stderr);
1493 if (run_sched_chunk_size != 1)
1494 fprintf (stderr, ",%d", run_sched_chunk_size);
1495 break;
1496 case GFS_GUIDED:
1497 fputs ("GUIDED", stderr);
1498 if (run_sched_chunk_size != 1)
1499 fprintf (stderr, ",%d", run_sched_chunk_size);
1500 break;
1501 case GFS_AUTO:
1502 fputs ("AUTO", stderr);
1503 break;
1505 fputs ("'\n", stderr);
1508 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1509 'device' can be 'host', 'dev', 'all', or a particular device number. */
1511 static void
1512 print_proc_bind (char proc_bind_var, unsigned long len, char **list,
1513 const char *device)
1515 fprintf (stderr, " [%s] OMP_PROC_BIND = '", device);
1516 switch (proc_bind_var)
1518 case omp_proc_bind_false:
1519 fputs ("FALSE", stderr);
1520 break;
1521 case omp_proc_bind_true:
1522 fputs ("TRUE", stderr);
1523 break;
1524 case omp_proc_bind_master:
1525 fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1526 break;
1527 case omp_proc_bind_close:
1528 fputs ("CLOSE", stderr);
1529 break;
1530 case omp_proc_bind_spread:
1531 fputs ("SPREAD", stderr);
1532 break;
1534 for (int i = 1; i < len; i++)
1535 switch ((*list)[i])
1537 case omp_proc_bind_master:
1538 fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1539 break;
1540 case omp_proc_bind_close:
1541 fputs (",CLOSE", stderr);
1542 break;
1543 case omp_proc_bind_spread:
1544 fputs (",SPREAD", stderr);
1545 break;
1547 fputs ("'\n", stderr);
1550 enum gomp_parse_type
1552 PARSE_INT = 1,
1553 PARSE_BOOL = 2,
1554 PARSE_UINT = 3,
1555 PARSE_ULONG = 4,
1556 PARSE_UCHAR = 5,
1557 PARSE_SCHEDULE =6,
1558 PARSE_BIND = 7
1561 /* The following table contains items that help parsing environment variables
1562 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1563 are affected by the environment variable. FLAGS determine what variant of
1564 environment variable is allowed. */
1566 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1567 static const struct envvar
1569 const char *name;
1570 int name_len;
1571 uint8_t flag_vars[3];
1572 uint8_t flag;
1573 bool (*parse_func) (const char *, const char *, void *const[]);
1574 } envvars[] = {
1575 { ENTRY ("SCHEDULE"),
1576 { GOMP_ICV_SCHEDULE, GOMP_ICV_SCHEDULE_CHUNK_SIZE },
1577 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1578 &parse_schedule },
1579 { ENTRY ("NUM_TEAMS"),
1580 { GOMP_ICV_NTEAMS },
1581 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1582 &parse_int },
1583 { ENTRY ("DYNAMIC"),
1584 { GOMP_ICV_DYNAMIC },
1585 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1586 &parse_boolean },
1587 { ENTRY ("TEAMS_THREAD_LIMIT"),
1588 { GOMP_ICV_TEAMS_THREAD_LIMIT },
1589 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1590 &parse_int },
1591 { ENTRY ("THREAD_LIMIT"),
1592 { GOMP_ICV_THREAD_LIMIT },
1593 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1594 &parse_unsigned_long },
1595 { ENTRY ("NUM_THREADS"),
1596 { GOMP_ICV_NTHREADS, GOMP_ICV_NTHREADS_LIST, GOMP_ICV_NTHREADS_LIST_LEN },
1597 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1598 &parse_unsigned_long_list },
1599 { ENTRY ("PROC_BIND"),
1600 { GOMP_ICV_BIND, GOMP_ICV_BIND_LIST, GOMP_ICV_BIND_LIST_LEN },
1601 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1602 &parse_bind_var },
1603 { ENTRY ("MAX_ACTIVE_LEVELS"),
1604 { GOMP_ICV_MAX_ACTIVE_LEVELS },
1605 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1606 &parse_unsigned_long },
1607 { ENTRY ("WAIT_POLICY"),
1608 { GOMP_ICV_WAIT_POLICY },
1609 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1610 &parse_wait_policy },
1611 { ENTRY ("STACKSIZE"),
1612 { GOMP_ICV_STACKSIZE },
1613 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1614 &parse_stacksize },
1615 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION }, 0, &parse_boolean },
1616 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY }, 0,
1617 &parse_boolean },
1618 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD }, 0,
1619 &parse_target_offload },
1620 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY }, 0,
1621 &parse_int },
1622 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR }, 0, &parse_allocator },
1623 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE },
1624 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1625 &parse_int }
1627 #undef ENTRY
1628 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1630 /* The following table is used to apply the hierarchy of ICV variants for host
1631 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1632 undefined. */
1634 static const struct host_envvar
1636 unsigned char flag_var;
1637 void *dest[3];
1638 int type_code;
1639 } host_envvars[] = {
1640 { GOMP_ICV_NTEAMS, { &gomp_nteams_var }, PARSE_INT },
1641 { GOMP_ICV_DYNAMIC, { &gomp_global_icv.dyn_var }, PARSE_BOOL },
1642 { GOMP_ICV_DEFAULT_DEVICE, { &gomp_global_icv.default_device_var },
1643 PARSE_INT },
1644 { GOMP_ICV_TEAMS_THREAD_LIMIT, { &gomp_teams_thread_limit_var }, PARSE_INT },
1645 { GOMP_ICV_SCHEDULE,
1646 { &gomp_global_icv.run_sched_var, &gomp_global_icv.run_sched_chunk_size },
1647 PARSE_SCHEDULE },
1648 { GOMP_ICV_THREAD_LIMIT, { &gomp_global_icv.thread_limit_var }, PARSE_UINT },
1649 { GOMP_ICV_NTHREADS,
1650 { &gomp_global_icv.nthreads_var, &gomp_nthreads_var_list,
1651 &gomp_nthreads_var_list_len }, PARSE_ULONG },
1652 { GOMP_ICV_BIND,
1653 { &gomp_global_icv.bind_var, &gomp_bind_var_list, &gomp_bind_var_list_len },
1654 PARSE_BIND },
1655 { GOMP_ICV_MAX_ACTIVE_LEVELS, { &gomp_global_icv.max_active_levels_var },
1656 PARSE_UCHAR },
1658 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1660 #define INT_MAX_STR_LEN 10
1662 bool
1663 gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv)
1665 return value & (1 << (icv - 1));
1668 static void
1669 gomp_set_icv_flag (uint32_t *value, enum gomp_icvs icv)
1671 *value |= 1 << (icv - 1);
1674 static void
1675 print_device_specific_icvs (int icv_code)
1677 struct gomp_icv_list *list = gomp_initial_icv_list;
1678 int i;
1679 char dev_num[INT_MAX_STR_LEN + 1];
1681 while (list != NULL)
1683 if (list->device_num < 0)
1685 list = list->next;
1686 continue;
1689 switch (icv_code)
1691 case GOMP_ICV_NTEAMS:
1692 if (gomp_get_icv_flag (list->flags, GOMP_ICV_NTEAMS))
1693 fprintf (stderr, " [%d] OMP_NUM_TEAMS = '%d'\n",
1694 list->device_num, list->icvs.nteams_var);
1695 break;
1696 case GOMP_ICV_DYNAMIC:
1697 if (gomp_get_icv_flag (list->flags, GOMP_ICV_DYNAMIC))
1698 fprintf (stderr, " [%d] OMP_DYNAMIC = '%s'\n",
1699 list->device_num, list->icvs.dyn_var ? "TRUE" : "FALSE");
1700 break;
1701 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1702 if (gomp_get_icv_flag (list->flags, GOMP_ICV_TEAMS_THREAD_LIMIT))
1703 fprintf (stderr, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1704 list->device_num, list->icvs.teams_thread_limit_var);
1705 break;
1706 case GOMP_ICV_SCHEDULE:
1707 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_SCHEDULE)))
1708 break;
1709 sprintf (dev_num, "%d", list->device_num);
1710 print_schedule (list->icvs.run_sched_var,
1711 list->icvs.run_sched_chunk_size,
1712 dev_num);
1713 break;
1714 case GOMP_ICV_THREAD_LIMIT:
1715 if (gomp_get_icv_flag (list->flags, GOMP_ICV_THREAD_LIMIT))
1716 fprintf (stderr, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1717 list->device_num, list->icvs.thread_limit_var);
1718 break;
1719 case GOMP_ICV_NTHREADS:
1720 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_NTHREADS)))
1721 break;
1722 fprintf (stderr, " [%d] OMP_NUM_THREADS = '%lu", list->device_num,
1723 list->icvs.nthreads_var);
1724 for (i = 1; i < list->icvs.nthreads_var_list_len; i++)
1725 fprintf (stderr, ",%lu", list->icvs.nthreads_var_list[i]);
1726 fputs ("'\n", stderr);
1727 break;
1728 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1729 fprintf (stderr, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1730 list->device_num, list->icvs.max_active_levels_var);
1731 break;
1732 case GOMP_ICV_BIND:
1733 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_BIND)))
1734 break;
1735 sprintf (dev_num, "%d", list->device_num);
1736 print_proc_bind (list->icvs.bind_var, list->icvs.bind_var_list_len,
1737 &list->icvs.bind_var_list, dev_num);
1738 break;
1739 case GOMP_ICV_WAIT_POLICY:
1740 if (gomp_get_icv_flag (list->flags, GOMP_ICV_WAIT_POLICY))
1741 fprintf (stderr, " [%d] OMP_WAIT_POLICY = '%s'\n",
1742 list->device_num,
1743 list->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1744 break;
1745 case GOMP_ICV_STACKSIZE:
1746 if (gomp_get_icv_flag (list->flags, GOMP_ICV_STACKSIZE))
1747 fprintf (stderr, " [%d] OMP_STACKSIZE = '%lu'\n",
1748 list->device_num, list->icvs.stacksize);
1749 break;
1751 list = list->next;
1755 void
1756 omp_display_env (int verbose)
1758 int i;
1759 struct gomp_icv_list *dev
1760 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV);
1761 struct gomp_icv_list *all
1762 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
1763 struct gomp_icv_list *none
1764 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
1766 if (none->icvs.default_device_var == INT_MIN)
1767 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1768 gomp_init_targets_once ();
1770 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1772 fputs (" _OPENMP = '201511'\n", stderr);
1774 fprintf (stderr, " [host] OMP_DYNAMIC = '%s'\n",
1775 none->icvs.dyn_var ? "TRUE" : "FALSE");
1776 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_DYNAMIC))
1777 fprintf (stderr, " [all] OMP_DYNAMIC = '%s'\n",
1778 all->icvs.dyn_var ? "TRUE" : "FALSE");
1779 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_DYNAMIC))
1780 fprintf (stderr, " [device] OMP_DYNAMIC = '%s'\n",
1781 dev->icvs.dyn_var ? "TRUE" : "FALSE");
1782 print_device_specific_icvs (GOMP_ICV_DYNAMIC);
1784 /* The OMP_NESTED environment variable has been deprecated. */
1785 fprintf (stderr, " [host] OMP_NESTED = '%s'\n",
1786 none->icvs.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1788 fprintf (stderr, " [host] OMP_NUM_THREADS = '%lu",
1789 none->icvs.nthreads_var);
1790 for (i = 1; i < none->icvs.nthreads_var_list_len; i++)
1791 fprintf (stderr, ",%lu", none->icvs.nthreads_var_list[i]);
1792 fputs ("'\n", stderr);
1793 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTHREADS))
1795 fprintf (stderr, " [all] OMP_NUM_THREADS = '%lu",
1796 all->icvs.nthreads_var);
1797 for (i = 1; i < all->icvs.nthreads_var_list_len; i++)
1798 fprintf (stderr, ",%lu", all->icvs.nthreads_var_list[i]);
1799 fputs ("'\n", stderr);
1801 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTHREADS))
1803 fprintf (stderr, " [device] OMP_NUM_THREADS = '%lu",
1804 dev->icvs.nthreads_var);
1805 for (i = 1; i < dev->icvs.nthreads_var_list_len; i++)
1806 fprintf (stderr, ",%lu", dev->icvs.nthreads_var_list[i]);
1807 fputs ("'\n", stderr);
1809 print_device_specific_icvs (GOMP_ICV_NTHREADS);
1812 print_schedule (none->icvs.run_sched_var,
1813 none->icvs.run_sched_chunk_size, "host");
1814 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_SCHEDULE))
1815 print_schedule (all->icvs.run_sched_var,
1816 all->icvs.run_sched_chunk_size, "all");
1817 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_SCHEDULE))
1818 print_schedule (dev->icvs.run_sched_var,
1819 dev->icvs.run_sched_chunk_size, "device");
1820 print_device_specific_icvs (GOMP_ICV_SCHEDULE);
1822 print_proc_bind (none->icvs.bind_var,
1823 none->icvs.bind_var_list_len,
1824 &none->icvs.bind_var_list, "host");
1825 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND))
1826 print_proc_bind (all->icvs.bind_var,
1827 all->icvs.bind_var_list_len,
1828 &all->icvs.bind_var_list, "all");
1829 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_BIND))
1830 print_proc_bind (dev->icvs.bind_var,
1831 dev->icvs.bind_var_list_len,
1832 &dev->icvs.bind_var_list, "device");
1833 print_device_specific_icvs (GOMP_ICV_BIND);
1835 fputs (" [host] OMP_PLACES = '", stderr);
1836 for (i = 0; i < gomp_places_list_len; i++)
1838 fputs ("{", stderr);
1839 gomp_affinity_print_place (gomp_places_list[i]);
1840 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1842 fputs ("'\n", stderr);
1844 fprintf (stderr, " [host] OMP_STACKSIZE = '%lu'\n",
1845 none->icvs.stacksize);
1846 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
1847 fprintf (stderr, " [all] OMP_STACKSIZE = '%lu'\n",
1848 all->icvs.stacksize);
1849 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_STACKSIZE))
1850 fprintf (stderr, " [device] OMP_STACKSIZE = '%lu'\n",
1851 dev->icvs.stacksize);
1852 print_device_specific_icvs (GOMP_ICV_STACKSIZE);
1854 /* GOMP's default value is actually neither active nor passive. */
1855 fprintf (stderr, " [host] OMP_WAIT_POLICY = '%s'\n",
1856 none->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1857 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
1858 fprintf (stderr, " [all] OMP_WAIT_POLICY = '%s'\n",
1859 all->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1860 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_WAIT_POLICY))
1861 fprintf (stderr, " [device] OMP_WAIT_POLICY = '%s'\n",
1862 dev->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1863 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY);
1865 fprintf (stderr, " [host] OMP_THREAD_LIMIT = '%u'\n",
1866 none->icvs.thread_limit_var);
1867 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_THREAD_LIMIT))
1868 fprintf (stderr, " [all] OMP_THREAD_LIMIT = '%d'\n",
1869 all->icvs.thread_limit_var);
1870 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_THREAD_LIMIT))
1871 fprintf (stderr, " [device] OMP_THREAD_LIMIT = '%d'\n",
1872 dev->icvs.thread_limit_var);
1873 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT);
1875 fprintf (stderr, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1876 none->icvs.max_active_levels_var);
1877 if (all != NULL && gomp_get_icv_flag (all->flags,
1878 GOMP_ICV_MAX_ACTIVE_LEVELS))
1879 fprintf (stderr, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1880 all->icvs.max_active_levels_var);
1881 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1882 GOMP_ICV_MAX_ACTIVE_LEVELS))
1883 fprintf (stderr, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1884 dev->icvs.max_active_levels_var);
1885 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS);
1888 fprintf (stderr, " [host] OMP_NUM_TEAMS = '%d'\n",
1889 none->icvs.nteams_var);
1890 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTEAMS))
1891 fprintf (stderr, " [all] OMP_NUM_TEAMS = '%d'\n",
1892 all->icvs.nteams_var);
1893 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTEAMS))
1894 fprintf (stderr, " [device] OMP_NUM_TEAMS = '%d'\n",
1895 dev->icvs.nteams_var);
1896 print_device_specific_icvs (GOMP_ICV_NTEAMS);
1898 fprintf (stderr, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1899 none->icvs.teams_thread_limit_var);
1900 if (all != NULL && gomp_get_icv_flag (all->flags,
1901 GOMP_ICV_TEAMS_THREAD_LIMIT))
1902 fprintf (stderr, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1903 all->icvs.teams_thread_limit_var);
1904 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1905 GOMP_ICV_TEAMS_THREAD_LIMIT))
1906 fprintf (stderr, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1907 dev->icvs.teams_thread_limit_var);
1908 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT);
1910 fprintf (stderr, " [all] OMP_CANCELLATION = '%s'\n",
1911 gomp_cancel_var ? "TRUE" : "FALSE");
1913 fprintf (stderr, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1914 none->icvs.default_device_var);
1916 fprintf (stderr, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1917 gomp_max_task_priority_var);
1918 fprintf (stderr, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1919 gomp_display_affinity_var ? "TRUE" : "FALSE");
1920 fprintf (stderr, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1921 gomp_affinity_format_var);
1922 fprintf (stderr, " [host] OMP_ALLOCATOR = '");
1923 switch (gomp_def_allocator)
1925 #define C(v) case v: fputs (#v, stderr); break;
1926 C (omp_default_mem_alloc)
1927 C (omp_large_cap_mem_alloc)
1928 C (omp_const_mem_alloc)
1929 C (omp_high_bw_mem_alloc)
1930 C (omp_low_lat_mem_alloc)
1931 C (omp_cgroup_mem_alloc)
1932 C (omp_pteam_mem_alloc)
1933 C (omp_thread_mem_alloc)
1934 #undef C
1935 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1936 default:
1937 if (gomp_def_allocator_envvar)
1938 fputs (gomp_def_allocator_envvar, stderr);
1939 break;
1941 fputs ("'\n", stderr);
1943 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr);
1944 switch (gomp_target_offload_var)
1946 case GOMP_TARGET_OFFLOAD_DEFAULT:
1947 fputs ("DEFAULT", stderr);
1948 break;
1949 case GOMP_TARGET_OFFLOAD_MANDATORY:
1950 fputs ("MANDATORY", stderr);
1951 break;
1952 case GOMP_TARGET_OFFLOAD_DISABLED:
1953 fputs ("DISABLED", stderr);
1954 break;
1956 fputs ("'\n", stderr);
1958 if (verbose)
1960 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr);
1961 fprintf (stderr, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize);
1962 #ifdef HAVE_INTTYPES_H
1963 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%"PRIu64"'\n",
1964 (uint64_t) gomp_spin_count_var);
1965 #else
1966 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%lu'\n",
1967 (unsigned long) gomp_spin_count_var);
1968 #endif
1971 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1973 ialias (omp_display_env)
1975 static void
1976 handle_omp_display_env (void)
1978 const char *env;
1979 bool display = false;
1980 bool verbose = false;
1982 env = getenv ("OMP_DISPLAY_ENV");
1983 if (env == NULL)
1984 return;
1986 while (isspace ((unsigned char) *env))
1987 ++env;
1988 if (strncasecmp (env, "true", 4) == 0)
1990 display = true;
1991 env += 4;
1993 else if (strncasecmp (env, "false", 5) == 0)
1995 display = false;
1996 env += 5;
1998 else if (strncasecmp (env, "verbose", 7) == 0)
2000 display = true;
2001 verbose = true;
2002 env += 7;
2004 else
2005 env = "X";
2006 while (isspace ((unsigned char) *env))
2007 ++env;
2008 if (*env != '\0')
2009 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2011 if (display)
2012 ialias_call (omp_display_env) (verbose);
2015 /* Helper function for initialize_env. Extracts the device number from
2016 an environment variable name. ENV is the complete environment variable.
2017 DEV_NUM_PTR points to the start of the device number in the environment
2018 variable string. DEV_NUM_LEN is the returned length of the device num
2019 string. */
2021 static bool
2022 get_device_num (char *env, char *dev_num_ptr, int *dev_num, int *dev_num_len)
2024 char *end;
2025 unsigned long val = strtoul (dev_num_ptr, &end, 10);
2026 if (val > INT_MAX
2027 || *end != '='
2028 || (dev_num_ptr[0] == '0' && end != dev_num_ptr + 1)
2029 || (dev_num_ptr[0] < '0' || dev_num_ptr[0] > '9'))
2031 gomp_error ("Invalid device number in %s", env);
2032 return false;
2034 *dev_num = val;
2035 *dev_num_len = end - dev_num_ptr;
2036 return true;
2039 static void
2040 get_icv_member_addr (struct gomp_initial_icvs *icvs, int icv_code,
2041 void *icv_addr[3])
2043 if (icv_code == 0 || icv_addr == NULL)
2044 return;
2046 icv_addr[0] = icv_addr[1] = icv_addr[2] = NULL;
2048 switch (icv_code)
2050 case GOMP_ICV_NTEAMS:
2051 icv_addr[0] = &icvs->nteams_var;
2052 /* icv_addr[1] = (void *) false; */
2053 break;
2054 case GOMP_ICV_DYNAMIC:
2055 icv_addr[0] = &(*icvs).dyn_var;
2056 break;
2057 case GOMP_ICV_TEAMS_THREAD_LIMIT:
2058 icv_addr[0] = &icvs->teams_thread_limit_var;
2059 /* icv_addr[1] = (void *) false; */
2060 break;
2061 case GOMP_ICV_SCHEDULE:
2062 icv_addr[0] = &icvs->run_sched_var;
2063 icv_addr[1] = &icvs->run_sched_chunk_size;
2064 break;
2065 case GOMP_ICV_THREAD_LIMIT:
2066 icv_addr[0] = &icvs->thread_limit_var;
2067 /* icv_addr[1] = (void *) false; */
2068 icv_addr[2] = (void *) UINT_MAX;
2069 break;
2070 case GOMP_ICV_NTHREADS:
2071 icv_addr[0] = &icvs->nthreads_var;
2072 icv_addr[1] = &icvs->nthreads_var_list;
2073 icv_addr[2] = &icvs->nthreads_var_list_len;
2074 break;
2075 case GOMP_ICV_MAX_ACTIVE_LEVELS:
2076 icv_addr[0] = &icvs->max_active_levels_var;
2077 icv_addr[1] = (void *) true;
2078 icv_addr[2] = (void *) gomp_supported_active_levels;
2079 break;
2080 case GOMP_ICV_BIND:
2081 icv_addr[0] = &icvs->bind_var;
2082 icv_addr[1] = &icvs->bind_var_list;
2083 icv_addr[2] = &icvs->bind_var_list_len;
2084 break;
2085 case GOMP_ICV_WAIT_POLICY:
2086 icv_addr[0] = &icvs->wait_policy;
2087 break;
2088 case GOMP_ICV_STACKSIZE:
2089 icv_addr[0] = &icvs->stacksize;
2090 break;
2091 case GOMP_ICV_CANCELLATION:
2092 icv_addr[0] = &gomp_cancel_var;
2093 break;
2094 case GOMP_ICV_DISPLAY_AFFINITY:
2095 icv_addr[0] = &gomp_display_affinity_var;
2096 break;
2097 case GOMP_ICV_TARGET_OFFLOAD:
2098 icv_addr[0] = &gomp_target_offload_var;
2099 break;
2100 case GOMP_ICV_MAX_TASK_PRIORITY:
2101 icv_addr[0] = &gomp_max_task_priority_var;
2102 break;
2103 case GOMP_ICV_ALLOCATOR:
2104 icv_addr[0] = &gomp_def_allocator;
2105 break;
2106 case GOMP_ICV_DEFAULT_DEVICE:
2107 icv_addr[0] = &icvs->default_device_var;
2108 icv_addr[1] = (void *) true;
2109 break;
2113 struct gomp_icv_list *
2114 gomp_get_initial_icv_item (int dev_num)
2116 struct gomp_icv_list *l = gomp_initial_icv_list;
2117 while (l != NULL && l->device_num != dev_num)
2118 l = l->next;
2120 return l;
2123 static void
2124 initialize_icvs (struct gomp_initial_icvs *icvs)
2126 icvs->nthreads_var_list = NULL;
2127 icvs->bind_var_list = NULL;
2128 icvs->nthreads_var = gomp_default_icv_values.nthreads_var;
2129 icvs->nthreads_var_list_len = 0;
2130 icvs->bind_var_list_len = 0;
2131 icvs->stacksize = 0;
2132 icvs->thread_limit_var = gomp_default_icv_values.thread_limit_var;
2133 icvs->run_sched_var = gomp_default_icv_values.run_sched_var;
2134 icvs->run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size;
2135 icvs->default_device_var = gomp_default_icv_values.default_device_var;
2136 icvs->dyn_var = gomp_default_icv_values.dyn_var;
2137 icvs->max_active_levels_var = gomp_default_icv_values.max_active_levels_var;
2138 icvs->bind_var = gomp_default_icv_values.bind_var;
2139 icvs->nteams_var = gomp_default_icv_values.nteams_var;
2140 icvs->teams_thread_limit_var = gomp_default_icv_values.teams_thread_limit_var;
2141 icvs->wait_policy = -1;
2144 /* Helper function for initialize_env to add a device specific ICV value
2145 to gomp_initial_icv_list. */
2147 static uint32_t *
2148 add_initial_icv_to_list (int dev_num, int icv_code, void *icv_addr[3])
2150 struct gomp_icv_list *last = NULL, *l = gomp_initial_icv_list;
2151 while (l != NULL && l->device_num != dev_num)
2153 last = l;
2154 l = l->next;
2157 if (l == NULL)
2159 l = ((struct gomp_icv_list *)
2160 gomp_malloc_cleared (sizeof (struct gomp_icv_list)));
2161 l->device_num = dev_num;
2162 initialize_icvs (&l->icvs);
2163 if (dev_num < 0)
2165 l->next = gomp_initial_icv_list;
2166 gomp_initial_icv_list = l;
2168 else
2170 l->next = NULL;
2171 if (last == NULL)
2172 gomp_initial_icv_list = l;
2173 else
2174 last->next = l;
2178 get_icv_member_addr (&l->icvs, icv_code, icv_addr);
2180 return &l->flags;
2183 /* Return true if STR string starts with PREFIX. */
2185 static inline bool
2186 startswith (const char *str, const char *prefix)
2188 return strncmp (str, prefix, strlen (prefix)) == 0;
2191 static void __attribute__((destructor))
2192 cleanup_env (void)
2194 if (gomp_def_allocator_envvar != NULL)
2196 free (gomp_def_allocator_envvar);
2197 omp_destroy_allocator (gomp_def_allocator);
2201 static void __attribute__((constructor))
2202 initialize_env (void)
2204 char **env;
2205 int omp_var, dev_num = 0, dev_num_len = 0, i;
2206 bool ignore = false;
2207 char *env_val;
2208 void *params[3];
2209 uint32_t *flag_var_addr = NULL;
2210 unsigned pos;
2211 struct gomp_icv_list *all, *none;
2213 /* Do a compile time check that mkomp_h.pl did good job. */
2214 omp_check_defines ();
2216 #ifndef HAVE_SYNC_BUILTINS
2217 gomp_mutex_init (&gomp_managed_threads_lock);
2218 #endif
2219 gomp_init_num_threads ();
2220 gomp_available_cpus = gomp_global_icv.nthreads_var;
2222 /* Initial values for host environment variables should always exist even if
2223 there is no explicitly set host environment variable. Moreover, they are
2224 set to the initial global values. */
2225 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX, 0, NULL);
2226 none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
2227 initialize_icvs (&none->icvs);
2229 if (environ)
2230 for (env = environ; *env != 0; env++)
2232 if (!startswith (*env, "OMP_"))
2233 continue;
2235 /* Name of the environment variable without suffix "OMP_". */
2236 char *name = *env + sizeof ("OMP_") - 1;
2237 for (omp_var = 0; omp_var < OMP_VAR_CNT; omp_var++)
2239 if (startswith (name, envvars[omp_var].name))
2241 pos = envvars[omp_var].name_len;
2242 if (name[pos] == '=')
2244 pos++;
2245 flag_var_addr
2246 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX,
2247 envvars[omp_var].flag_vars[0],
2248 params);
2250 else if (startswith (&name[pos], "_DEV=")
2251 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV)
2253 pos += 5;
2254 flag_var_addr
2255 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV,
2256 envvars[omp_var].flag_vars[0],
2257 params);
2259 else if (startswith (&name[pos], "_ALL=")
2260 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_ALL)
2262 pos += 5;
2263 flag_var_addr
2264 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL,
2265 envvars[omp_var].flag_vars[0],
2266 params);
2268 else if (startswith (&name[pos], "_DEV_")
2269 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV_X)
2271 pos += 5;
2272 if (!get_device_num (*env, &name[pos], &dev_num,
2273 &dev_num_len))
2274 break;
2276 pos += dev_num_len + 1;
2277 flag_var_addr
2278 = add_initial_icv_to_list (dev_num,
2279 envvars[omp_var].flag_vars[0],
2280 params);
2282 else
2284 gomp_error ("Invalid environment variable in %s", *env);
2285 break;
2287 env_val = &name[pos];
2289 if (envvars[omp_var].parse_func (*env, env_val, params))
2291 for (i = 0; i < 3; ++i)
2292 if (envvars[omp_var].flag_vars[i])
2293 gomp_set_icv_flag (flag_var_addr,
2294 envvars[omp_var].flag_vars[i]);
2295 else
2296 break;
2299 break;
2304 all = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
2305 for (omp_var = 0; omp_var < OMP_HOST_VAR_CNT; omp_var++)
2307 if (none != NULL
2308 && gomp_get_icv_flag (none->flags, host_envvars[omp_var].flag_var))
2309 get_icv_member_addr (&none->icvs,
2310 host_envvars[omp_var].flag_var, params);
2311 else if (all != NULL
2312 && gomp_get_icv_flag (all->flags,
2313 host_envvars[omp_var].flag_var))
2314 get_icv_member_addr (&all->icvs, host_envvars[omp_var].flag_var,
2315 params);
2316 else
2317 continue;
2319 switch (host_envvars[omp_var].type_code)
2321 case PARSE_INT:
2322 for (i = 0; i < 3; ++i)
2323 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2324 *(int *) (host_envvars[omp_var].dest[i]) = *(int *) params[i];
2325 break;
2326 case PARSE_BOOL:
2327 for (i = 0; i < 3; ++i)
2328 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2329 *(bool *) (host_envvars[omp_var].dest[i]) = *(bool *) params[i];
2330 break;
2331 case PARSE_UINT:
2332 for (i = 0; i < 3; ++i)
2333 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2334 *(unsigned int *) (host_envvars[omp_var].dest[i])
2335 = *(unsigned int *) params[i];
2336 break;
2337 case PARSE_ULONG:
2338 for (i = 0; i < 3; ++i)
2339 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2340 *(unsigned long *) (host_envvars[omp_var].dest[i])
2341 = *(unsigned long *) params[i];
2342 break;
2343 case PARSE_UCHAR:
2344 for (i = 0; i < 3; ++i)
2345 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2346 *(unsigned char *) (host_envvars[omp_var].dest[i])
2347 = *(unsigned char *) params[i];
2348 break;
2349 case PARSE_SCHEDULE:
2350 *(enum gomp_schedule_type *) (host_envvars[omp_var].dest[0])
2351 = *(enum gomp_schedule_type *) params[0];
2352 *(int *) (host_envvars[omp_var].dest[1]) = *(int *) params[1];
2353 break;
2354 case PARSE_BIND:
2355 *(char *) (host_envvars[omp_var].dest[0]) = *(char *) params[0];
2356 *(char **) (host_envvars[omp_var].dest[1]) = *(char **) params[1];
2357 *(unsigned long *) (host_envvars[omp_var].dest[2])
2358 = *(unsigned long *) params[2];
2359 break;
2363 if (((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_BIND))
2364 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND)))
2365 && gomp_global_icv.bind_var == omp_proc_bind_false)
2366 ignore = true;
2368 if (!((none != NULL
2369 && gomp_get_icv_flag (none->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))
2370 || (all != NULL
2371 && gomp_get_icv_flag (all->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))))
2373 bool nested = true;
2374 const char *env = getenv ("OMP_NESTED");
2376 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2377 if (parse_boolean ("OMP_NESTED", env, (void *[]) {&nested}))
2378 gomp_global_icv.max_active_levels_var
2379 = nested ? gomp_supported_active_levels : 1;
2380 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
2381 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
2384 if (gomp_global_icv.default_device_var == INT_MIN
2385 && gomp_target_offload_var != GOMP_TARGET_OFFLOAD_MANDATORY)
2386 none->icvs.default_device_var = gomp_global_icv.default_device_var = 0;
2388 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2389 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
2391 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2392 parsed if present in the environment. If OMP_PROC_BIND was set
2393 explicitly to false, don't populate places list though. If places
2394 list was successfully set from OMP_PLACES, only parse but don't process
2395 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2396 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2397 was successfully parsed into a places list, otherwise to
2398 OMP_PROC_BIND=false. */
2399 if (parse_places_var ("OMP_PLACES", ignore))
2401 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2402 gomp_global_icv.bind_var = true;
2403 ignore = true;
2405 if (parse_affinity (ignore))
2407 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2408 gomp_global_icv.bind_var = true;
2409 ignore = true;
2411 if (gomp_global_icv.bind_var != omp_proc_bind_false)
2412 gomp_init_affinity ();
2415 const char *env = getenv ("OMP_AFFINITY_FORMAT");
2416 if (env != NULL)
2417 gomp_set_affinity_format (env, strlen (env));
2420 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_WAIT_POLICY))
2421 wait_policy = none->icvs.wait_policy;
2422 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
2423 wait_policy = all->icvs.wait_policy;
2425 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
2427 /* Using a rough estimation of 100000 spins per msec,
2428 use 5 min blocking for OMP_WAIT_POLICY=active,
2429 3 msec blocking when OMP_WAIT_POLICY is not specificed
2430 and 0 when OMP_WAIT_POLICY=passive.
2431 Depending on the CPU speed, this can be e.g. 5 times longer
2432 or 5 times shorter. */
2433 if (wait_policy > 0)
2434 gomp_spin_count_var = 30000000000LL;
2435 else if (wait_policy < 0)
2437 gomp_spin_count_var = 300000LL;
2438 do_adjust_default_spincount ();
2441 /* gomp_throttled_spin_count_var is used when there are more libgomp
2442 managed threads than available CPUs. Use very short spinning. */
2443 if (wait_policy > 0)
2444 gomp_throttled_spin_count_var = 1000LL;
2445 else if (wait_policy < 0)
2446 gomp_throttled_spin_count_var = 100LL;
2447 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
2448 gomp_throttled_spin_count_var = gomp_spin_count_var;
2450 /* Not strictly environment related, but ordering constructors is tricky. */
2451 pthread_attr_init (&gomp_thread_attr);
2453 if (!(none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE)))
2455 const char *env = getenv ("GOMP_STACKSIZE");
2456 if (env != NULL
2457 && parse_stacksize ("GOMP_STACKSIZE", env,
2458 (void *[3]) {&none->icvs.stacksize}))
2459 gomp_set_icv_flag (&none->flags, GOMP_ICV_STACKSIZE);
2461 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2462 stacksize = none->icvs.stacksize;
2463 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2464 stacksize = all->icvs.stacksize;
2466 if ((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2467 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2468 || GOMP_DEFAULT_STACKSIZE)
2470 int err;
2472 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
2474 #ifdef PTHREAD_STACK_MIN
2475 if (err == EINVAL)
2477 if (stacksize < PTHREAD_STACK_MIN)
2478 gomp_error ("Stack size less than minimum of %luk",
2479 PTHREAD_STACK_MIN / 1024ul
2480 + (PTHREAD_STACK_MIN % 1024 != 0));
2481 else
2482 gomp_error ("Stack size larger than system limit");
2484 else
2485 #endif
2486 if (err != 0)
2487 gomp_error ("Stack size change failed: %s", strerror (err));
2490 handle_omp_display_env ();
2492 /* OpenACC. */
2494 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2495 (void *[]) {&goacc_device_num, (void *) true}))
2496 goacc_device_num = 0;
2498 parse_acc_device_type ();
2499 parse_gomp_openacc_dim ();
2501 goacc_runtime_initialize ();
2503 goacc_profiling_initialize ();
2505 #endif /* LIBGOMP_OFFLOADED_ONLY */