d: Add language reference section to documentation files.
[official-gcc.git] / libgomp / env.c
blob279937bb36cbf50fc3b9e7c6f088f7d940d3065f
1 /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This file defines the OpenMP internal control variables and arranges
27 for them to be initialized from environment variables at startup. */
29 #define _GNU_SOURCE
30 #include "libgomp.h"
31 #include "gomp-constants.h"
32 #include <limits.h>
33 #ifndef LIBGOMP_OFFLOADED_ONLY
34 #include "libgomp_f.h"
35 #include "oacc-int.h"
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #ifdef HAVE_INTTYPES_H
40 # include <inttypes.h> /* For PRIu64. */
41 #endif
42 #ifdef STRING_WITH_STRINGS
43 # include <string.h>
44 # include <strings.h>
45 #else
46 # ifdef HAVE_STRING_H
47 # include <string.h>
48 # else
49 # ifdef HAVE_STRINGS_H
50 # include <strings.h>
51 # endif
52 # endif
53 #endif
54 #include <errno.h>
55 #include "thread-stacksize.h"
57 #ifndef HAVE_STRTOULL
58 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
59 #endif
60 #endif /* LIBGOMP_OFFLOADED_ONLY */
62 #include "secure_getenv.h"
63 #include "environ.h"
65 /* Default values of ICVs according to the OpenMP standard. */
66 const struct gomp_default_icv gomp_default_icv_values = {
67 .nthreads_var = 1,
68 .thread_limit_var = UINT_MAX,
69 .run_sched_var = GFS_DYNAMIC,
70 .run_sched_chunk_size = 1,
71 .default_device_var = 0,
72 .max_active_levels_var = 1,
73 .bind_var = omp_proc_bind_false,
74 .nteams_var = 0,
75 .teams_thread_limit_var = 0,
76 .dyn_var = false
79 struct gomp_task_icv gomp_global_icv = {
80 .nthreads_var = gomp_default_icv_values.nthreads_var,
81 .thread_limit_var = gomp_default_icv_values.thread_limit_var,
82 .run_sched_var = gomp_default_icv_values.run_sched_var,
83 .run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size,
84 .default_device_var = gomp_default_icv_values.default_device_var,
85 .dyn_var = gomp_default_icv_values.dyn_var,
86 .max_active_levels_var = gomp_default_icv_values.max_active_levels_var,
87 .bind_var = gomp_default_icv_values.bind_var,
88 .target_data = NULL
91 /* List for initial "_DEV", "_ALL", and "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV,
92 OMP_NUM_TEAMS_ALL, or OMP_NUM_TEAMS_DEV_42. */
93 struct gomp_icv_list *gomp_initial_icv_list = NULL;
95 /* List for "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV_42. This list contains all
96 device-specific ICVs that are copied from host to device and back. */
97 struct gomp_offload_icv_list *gomp_offload_icv_list = NULL;
99 bool gomp_cancel_var = false;
100 enum gomp_target_offload_t gomp_target_offload_var
101 = GOMP_TARGET_OFFLOAD_DEFAULT;
102 int gomp_max_task_priority_var = 0;
103 #ifndef HAVE_SYNC_BUILTINS
104 gomp_mutex_t gomp_managed_threads_lock;
105 #endif
106 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
107 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
108 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
109 char *gomp_bind_var_list;
110 unsigned long gomp_bind_var_list_len;
111 void **gomp_places_list;
112 unsigned long gomp_places_list_len;
113 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
114 int gomp_debug_var;
115 unsigned int gomp_num_teams_var;
116 int gomp_nteams_var;
117 int gomp_teams_thread_limit_var;
118 bool gomp_display_affinity_var;
119 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
120 size_t gomp_affinity_format_len;
121 char *goacc_device_type;
122 int goacc_device_num;
123 int goacc_default_dims[GOMP_DIM_MAX];
125 #ifndef LIBGOMP_OFFLOADED_ONLY
127 static int wait_policy;
128 static unsigned long stacksize = GOMP_DEFAULT_STACKSIZE;
130 static void
131 print_env_var_error (const char *env, const char *val)
133 gomp_error ("Invalid value for environment variable %.*s: %s",
134 (int) (val - env - 1), env, val);
137 /* Parse the OMP_SCHEDULE environment variable. */
138 static bool
139 parse_schedule (const char *env, const char *val, void *const params[])
141 enum gomp_schedule_type *schedule = (enum gomp_schedule_type *) params[0];
142 int *chunk_size = (int *) params[1];
143 char *end;
144 unsigned long value;
145 int monotonic = 0;
147 if (val == NULL)
148 return false;
150 while (isspace ((unsigned char) *val))
151 ++val;
152 if (strncasecmp (val, "monotonic", 9) == 0)
154 monotonic = 1;
155 val += 9;
157 else if (strncasecmp (val, "nonmonotonic", 12) == 0)
159 monotonic = -1;
160 val += 12;
162 if (monotonic)
164 while (isspace ((unsigned char) *val))
165 ++val;
166 if (*val != ':')
167 goto unknown;
168 ++val;
169 while (isspace ((unsigned char) *val))
170 ++val;
172 if (strncasecmp (val, "static", 6) == 0)
174 *schedule = GFS_STATIC;
175 val += 6;
177 else if (strncasecmp (val, "dynamic", 7) == 0)
179 *schedule = GFS_DYNAMIC;
180 val += 7;
182 else if (strncasecmp (val, "guided", 6) == 0)
184 *schedule = GFS_GUIDED;
185 val += 6;
187 else if (strncasecmp (val, "auto", 4) == 0)
189 *schedule = GFS_AUTO;
190 val += 4;
192 else
193 goto unknown;
195 if (monotonic == 1
196 || (monotonic == 0 && *schedule == GFS_STATIC))
197 *schedule |= GFS_MONOTONIC;
199 while (isspace ((unsigned char) *val))
200 ++val;
201 if (*val == '\0')
203 *chunk_size = (*schedule & ~GFS_MONOTONIC) != GFS_STATIC;
204 return true;
206 if (*val++ != ',')
207 goto unknown;
208 while (isspace ((unsigned char) *val))
209 ++val;
210 if (*val == '\0')
211 goto invalid;
213 errno = 0;
214 value = strtoul (val, &end, 10);
215 if (errno || end == val)
216 goto invalid;
218 while (isspace ((unsigned char) *end))
219 ++end;
220 if (*end != '\0')
221 goto invalid;
223 if ((int)value != value)
224 goto invalid;
226 if (value == 0 && (*schedule & ~GFS_MONOTONIC) != GFS_STATIC)
227 value = 1;
228 *chunk_size = value;
229 return true;
231 unknown:
232 print_env_var_error (env, val);
233 return false;
235 invalid:
236 char name[val - env];
237 memcpy (name, env, val - env - 1);
238 name[val - env - 1] = '\0';
239 gomp_error ("Invalid value for chunk size in "
240 "environment variable %s: %s", name, val);
241 return false;
244 /* Parse an unsigned long environment variable. Return true if one was
245 present and it was successfully parsed. If SECURE, use secure_getenv to the
246 environment variable. */
248 static bool
249 parse_unsigned_long_1 (const char *env, const char *val, unsigned long *pvalue,
250 bool allow_zero)
252 char *end;
253 unsigned long value;
255 if (val == NULL)
256 return false;
258 while (isspace ((unsigned char) *val))
259 ++val;
260 if (*val == '\0')
261 goto invalid;
263 errno = 0;
264 value = strtoul (val, &end, 10);
265 if (errno || end == val || (long) value <= 0 - allow_zero)
266 goto invalid;
268 while (isspace ((unsigned char) *end))
269 ++end;
270 if (*end != '\0')
271 goto invalid;
273 *pvalue = value;
274 return true;
276 invalid:
277 print_env_var_error (env, val);
278 return false;
281 /* As parse_unsigned_long_1, but always use getenv. */
283 static bool
284 parse_unsigned_long (const char *env, const char *val, void *const params[])
286 unsigned long upper = (uintptr_t) params[2];
287 unsigned long pvalue = 0;
288 bool ret = parse_unsigned_long_1 (env, val, &pvalue, (bool) params[1]);
289 if (!ret)
290 return false;
292 if (upper == 0)
293 *(unsigned long *) params[0] = pvalue;
294 else
296 if (pvalue > upper)
297 pvalue = upper;
298 if (upper <= UCHAR_MAX)
299 *(unsigned char *) params[0] = pvalue;
300 else if (upper <= UINT_MAX)
301 *(unsigned int *) params[0] = pvalue;
302 else
303 *(unsigned long *) params[0] = pvalue;
306 return ret;
309 /* Parse a positive int environment variable. Return true if one was
310 present and it was successfully parsed. If SECURE, use secure_getenv to the
311 environment variable. */
313 static bool
314 parse_int_1 (const char *env, const char *val, int *pvalue, bool allow_zero)
316 unsigned long value;
317 if (!parse_unsigned_long_1 (env, val, &value, allow_zero))
318 return false;
319 if (value > INT_MAX)
321 print_env_var_error (env, val);
322 return false;
324 *pvalue = (int) value;
325 return true;
328 static bool
329 parse_int (const char *env, const char *val, void *const params[])
331 return parse_int_1 (env, val, (int *) params[0], (bool) params[1]);
334 /* As parse_int_1, but use getenv_secure. */
336 static bool
337 parse_int_secure (const char *env, int *pvalue, bool allow_zero)
339 return parse_int_1 (env, secure_getenv (env), pvalue, allow_zero);
342 /* Parse an unsigned long list environment variable. Return true if one was
343 present and it was successfully parsed. */
345 static bool
346 parse_unsigned_long_list (const char *env, const char *val,
347 void *const params[])
349 unsigned long *p1stvalue = (unsigned long *) params[0];
350 unsigned long **pvalues = (unsigned long **) params[1];
351 unsigned long *pnvalues = (unsigned long *) params[2];
352 char *end;
353 unsigned long value, *values = NULL;
355 if (val == NULL)
356 return false;
358 while (isspace ((unsigned char) *val))
359 ++val;
360 if (*val == '\0')
361 goto invalid;
363 errno = 0;
364 value = strtoul (val, &end, 10);
365 if (errno || (long) value <= 0)
366 goto invalid;
368 while (isspace ((unsigned char) *end))
369 ++end;
370 if (*end != '\0')
372 if (*end == ',')
374 unsigned long nvalues = 0, nalloced = 0;
378 val = end + 1;
379 if (nvalues == nalloced)
381 unsigned long *n;
382 nalloced = nalloced ? nalloced * 2 : 16;
383 n = realloc (values, nalloced * sizeof (unsigned long));
384 if (n == NULL)
386 free (values);
387 char name[val - env];
388 memcpy (name, env, val - env - 1);
389 name[val - env - 1] = '\0';
390 gomp_error ("Out of memory while trying to parse"
391 " environment variable %s", name);
392 return false;
394 values = n;
395 if (nvalues == 0)
396 values[nvalues++] = value;
399 while (isspace ((unsigned char) *val))
400 ++val;
401 if (*val == '\0')
402 goto invalid;
404 errno = 0;
405 value = strtoul (val, &end, 10);
406 if (errno || (long) value <= 0)
407 goto invalid;
409 values[nvalues++] = value;
410 while (isspace ((unsigned char) *end))
411 ++end;
412 if (*end == '\0')
413 break;
414 if (*end != ',')
415 goto invalid;
417 while (1);
418 *p1stvalue = values[0];
419 *pvalues = values;
420 *pnvalues = nvalues;
421 return true;
423 goto invalid;
425 else
427 *pnvalues = 0;
428 *pvalues = NULL;
431 *p1stvalue = value;
432 return true;
434 invalid:
435 free (values);
436 print_env_var_error (env, val);
437 return false;
440 static bool
441 parse_target_offload (const char *env, const char *val, void *const params[])
443 int new_offload = -1;
445 if (val == NULL)
446 return false;
448 while (isspace ((unsigned char) *val))
449 ++val;
450 if (strncasecmp (val, "default", 7) == 0)
452 val += 7;
453 new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
455 else if (strncasecmp (val, "mandatory", 9) == 0)
457 val += 9;
458 new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
460 else if (strncasecmp (val, "disabled", 8) == 0)
462 val += 8;
463 new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
465 while (isspace ((unsigned char) *val))
466 ++val;
467 if (new_offload != -1 && *val == '\0')
469 *(enum gomp_target_offload_t *) params[0] = new_offload;
470 return true;
473 print_env_var_error (env, val);
474 return false;
477 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
478 enum values. Return true if one was present and it was successfully
479 parsed. */
481 static bool
482 parse_bind_var (const char *env, const char *val, void *const params[])
484 char *p1stvalue = (char *) params[0];
485 char **pvalues = (char **) params[1];
486 unsigned long *pnvalues = (unsigned long *) params[2];
487 char value = omp_proc_bind_false, *values = NULL;
488 int i;
489 static struct proc_bind_kinds
491 const char name[7];
492 const char len;
493 omp_proc_bind_t kind;
494 } kinds[] =
496 { "false", 5, omp_proc_bind_false },
497 { "true", 4, omp_proc_bind_true },
498 { "master", 6, omp_proc_bind_master },
499 { "primary", 7, omp_proc_bind_primary },
500 { "close", 5, omp_proc_bind_close },
501 { "spread", 6, omp_proc_bind_spread }
504 if (val == NULL)
505 return false;
507 while (isspace ((unsigned char) *val))
508 ++val;
509 if (*val == '\0')
510 goto invalid;
512 for (i = 0; i < 6; i++)
513 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
515 value = kinds[i].kind;
516 val += kinds[i].len;
517 break;
519 if (i == 6)
520 goto invalid;
522 while (isspace ((unsigned char) *val))
523 ++val;
524 if (*val != '\0')
526 if (*val == ',')
528 unsigned long nvalues = 0, nalloced = 0;
530 if (value == omp_proc_bind_false
531 || value == omp_proc_bind_true)
532 goto invalid;
536 val++;
537 if (nvalues == nalloced)
539 char *n;
540 nalloced = nalloced ? nalloced * 2 : 16;
541 n = realloc (values, nalloced);
542 if (n == NULL)
544 free (values);
545 char name[val - env];
546 memcpy (name, env, val - env - 1);
547 name[val - env - 1] = '\0';
548 gomp_error ("Out of memory while trying to parse"
549 " environment variable %s", name);
550 return false;
552 values = n;
553 if (nvalues == 0)
554 values[nvalues++] = value;
557 while (isspace ((unsigned char) *val))
558 ++val;
559 if (*val == '\0')
560 goto invalid;
562 for (i = 2; i < 6; i++)
563 if (strncasecmp (val, kinds[i].name, kinds[i].len) == 0)
565 value = kinds[i].kind;
566 val += kinds[i].len;
567 break;
569 if (i == 6)
570 goto invalid;
572 values[nvalues++] = value;
573 while (isspace ((unsigned char) *val))
574 ++val;
575 if (*val == '\0')
576 break;
577 if (*val != ',')
578 goto invalid;
580 while (1);
581 *p1stvalue = values[0];
582 *pvalues = values;
583 *pnvalues = nvalues;
584 return true;
586 goto invalid;
589 *p1stvalue = value;
590 return true;
592 invalid:
593 free (values);
594 print_env_var_error (env, val);
595 return false;
598 static bool
599 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
600 long *stridep)
602 char *env = *envp, *start;
603 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
604 unsigned long len = 1;
605 long stride = 1;
606 int pass;
607 bool any_negate = false;
608 bool has_braces = true;
609 *negatep = false;
610 while (isspace ((unsigned char) *env))
611 ++env;
612 if (*env == '!')
614 *negatep = true;
615 ++env;
616 while (isspace ((unsigned char) *env))
617 ++env;
619 if (*env != '{')
621 char *end;
622 unsigned long this_num;
624 errno = 0;
625 this_num = strtoul (env, &end, 10);
626 if (errno || end == env)
627 return false;
628 env = end - 1;
629 has_braces = false;
630 if (gomp_places_list
631 && !gomp_affinity_add_cpus (p, this_num, 1, 1, false))
632 return false;
634 else
636 ++env;
637 while (isspace ((unsigned char) *env))
638 ++env;
640 start = env;
641 for (pass = 0; pass < (any_negate ? 2 : has_braces); pass++)
643 env = start;
646 unsigned long this_num, this_len = 1;
647 long this_stride = 1;
648 bool this_negate = (*env == '!');
649 char *end;
650 if (this_negate)
652 if (gomp_places_list)
653 any_negate = true;
654 ++env;
655 while (isspace ((unsigned char) *env))
656 ++env;
659 errno = 0;
660 this_num = strtoul (env, &end, 10);
661 if (errno || end == env)
662 return false;
663 env = end;
664 while (isspace ((unsigned char) *env))
665 ++env;
666 if (*env == ':')
668 ++env;
669 if (this_negate)
670 return false;
671 while (isspace ((unsigned char) *env))
672 ++env;
673 errno = 0;
674 this_len = strtoul (env, &env, 10);
675 if (errno || this_len == 0)
676 return false;
677 while (isspace ((unsigned char) *env))
678 ++env;
679 if (*env == ':')
681 ++env;
682 while (isspace ((unsigned char) *env))
683 ++env;
684 errno = 0;
685 this_stride = strtol (env, &end, 10);
686 if (errno || end == env)
687 return false;
688 env = end;
689 while (isspace ((unsigned char) *env))
690 ++env;
693 if (gomp_places_list && pass == this_negate)
695 if (this_negate)
697 if (!gomp_affinity_remove_cpu (p, this_num))
698 return false;
700 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
701 this_stride, false))
702 return false;
704 if (*env == '}')
705 break;
706 if (*env != ',')
707 return false;
708 ++env;
710 while (1);
713 ++env;
714 while (isspace ((unsigned char) *env))
715 ++env;
716 if (*env == ':')
718 char *end;
719 if (*negatep)
720 return false;
721 ++env;
722 while (isspace ((unsigned char) *env))
723 ++env;
724 errno = 0;
725 len = strtoul (env, &env, 10);
726 if (errno || len == 0 || len >= 65536)
727 return false;
728 while (isspace ((unsigned char) *env))
729 ++env;
730 if (*env == ':')
732 ++env;
733 while (isspace ((unsigned char) *env))
734 ++env;
735 errno = 0;
736 stride = strtol (env, &end, 10);
737 if (errno || end == env)
738 return false;
739 env = end;
740 while (isspace ((unsigned char) *env))
741 ++env;
744 *envp = env;
745 *lenp = len;
746 *stridep = stride;
747 return true;
750 static bool
751 parse_places_var (const char *name, bool ignore)
753 char *env = getenv (name), *end;
754 bool any_negate = false;
755 int level = 0;
756 unsigned long count = 0;
757 if (env == NULL)
758 return false;
760 while (isspace ((unsigned char) *env))
761 ++env;
762 if (*env == '\0')
763 goto invalid;
765 if (strncasecmp (env, "threads", 7) == 0)
767 env += 7;
768 level = 1;
770 else if (strncasecmp (env, "cores", 5) == 0)
772 env += 5;
773 level = 2;
775 else if (strncasecmp (env, "sockets", 7) == 0)
777 env += 7;
778 level = 3;
780 else if (strncasecmp (env, "ll_caches", 9) == 0)
782 env += 9;
783 level = 4;
785 else if (strncasecmp (env, "numa_domains", 12) == 0)
787 env += 12;
788 level = 5;
790 if (level)
792 count = ULONG_MAX;
793 while (isspace ((unsigned char) *env))
794 ++env;
795 if (*env != '\0')
797 if (*env++ != '(')
798 goto invalid;
799 while (isspace ((unsigned char) *env))
800 ++env;
802 errno = 0;
803 count = strtoul (env, &end, 10);
804 if (errno || end == env)
805 goto invalid;
806 env = end;
807 while (isspace ((unsigned char) *env))
808 ++env;
809 if (*env != ')')
810 goto invalid;
811 ++env;
812 while (isspace ((unsigned char) *env))
813 ++env;
814 if (*env != '\0')
815 goto invalid;
818 if (ignore)
819 return false;
821 return gomp_affinity_init_level (level, count, false);
824 count = 0;
825 end = env;
828 bool negate;
829 unsigned long len;
830 long stride;
831 if (!parse_one_place (&end, &negate, &len, &stride))
832 goto invalid;
833 if (negate)
835 if (!any_negate)
836 count++;
837 any_negate = true;
839 else
840 count += len;
841 if (count > 65536)
842 goto invalid;
843 if (*end == '\0')
844 break;
845 if (*end != ',')
846 goto invalid;
847 end++;
849 while (1);
851 if (ignore)
852 return false;
854 gomp_places_list_len = 0;
855 gomp_places_list = gomp_affinity_alloc (count, false);
856 if (gomp_places_list == NULL)
857 return false;
861 bool negate;
862 unsigned long len;
863 long stride;
864 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
865 if (!parse_one_place (&env, &negate, &len, &stride))
866 goto invalid;
867 if (negate)
869 void *p;
870 for (count = 0; count < gomp_places_list_len; count++)
871 if (gomp_affinity_same_place
872 (gomp_places_list[count],
873 gomp_places_list[gomp_places_list_len]))
874 break;
875 if (count == gomp_places_list_len)
877 gomp_error ("Trying to remove a non-existing place from list "
878 "of places");
879 goto invalid;
881 p = gomp_places_list[count];
882 memmove (&gomp_places_list[count],
883 &gomp_places_list[count + 1],
884 (gomp_places_list_len - count - 1) * sizeof (void *));
885 --gomp_places_list_len;
886 gomp_places_list[gomp_places_list_len] = p;
888 else if (len == 1)
889 ++gomp_places_list_len;
890 else
892 for (count = 0; count < len - 1; count++)
893 if (!gomp_affinity_copy_place
894 (gomp_places_list[gomp_places_list_len + count + 1],
895 gomp_places_list[gomp_places_list_len + count],
896 stride))
897 goto invalid;
898 gomp_places_list_len += len;
900 if (*env == '\0')
901 break;
902 env++;
904 while (1);
906 if (gomp_places_list_len == 0)
908 gomp_error ("All places have been removed");
909 goto invalid;
911 if (!gomp_affinity_finalize_place_list (false))
912 goto invalid;
913 return true;
915 invalid:
916 free (gomp_places_list);
917 gomp_places_list = NULL;
918 gomp_places_list_len = 0;
919 gomp_error ("Invalid value for environment variable %s", name);
920 return false;
923 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
924 present and it was successfully parsed. */
926 static bool
927 parse_stacksize (const char *env, const char *val, void *const params[])
929 char *end;
930 unsigned long value, shift = 10;
932 if (val == NULL)
933 return false;
935 while (isspace ((unsigned char) *val))
936 ++val;
937 if (*val == '\0')
938 goto invalid;
940 errno = 0;
941 value = strtoul (val, &end, 10);
942 if (errno || end == val)
943 goto invalid;
945 while (isspace ((unsigned char) *end))
946 ++end;
947 if (*end != '\0')
949 switch (tolower ((unsigned char) *end))
951 case 'b':
952 shift = 0;
953 break;
954 case 'k':
955 break;
956 case 'm':
957 shift = 20;
958 break;
959 case 'g':
960 shift = 30;
961 break;
962 default:
963 goto invalid;
965 ++end;
966 while (isspace ((unsigned char) *end))
967 ++end;
968 if (*end != '\0')
969 goto invalid;
972 if (((value << shift) >> shift) != value)
973 goto invalid;
975 *(unsigned long *) params[0] = value << shift;
976 return true;
978 invalid:
979 print_env_var_error (env, val);
980 return false;
983 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
984 present and it was successfully parsed. */
986 static bool
987 parse_spincount (const char *name, unsigned long long *pvalue)
989 char *env, *end;
990 unsigned long long value, mult = 1;
992 env = getenv (name);
993 if (env == NULL)
994 return false;
996 while (isspace ((unsigned char) *env))
997 ++env;
998 if (*env == '\0')
999 goto invalid;
1001 if (strncasecmp (env, "infinite", 8) == 0
1002 || strncasecmp (env, "infinity", 8) == 0)
1004 value = ~0ULL;
1005 end = env + 8;
1006 goto check_tail;
1009 errno = 0;
1010 value = strtoull (env, &end, 10);
1011 if (errno || end == env)
1012 goto invalid;
1014 while (isspace ((unsigned char) *end))
1015 ++end;
1016 if (*end != '\0')
1018 switch (tolower ((unsigned char) *end))
1020 case 'k':
1021 mult = 1000LL;
1022 break;
1023 case 'm':
1024 mult = 1000LL * 1000LL;
1025 break;
1026 case 'g':
1027 mult = 1000LL * 1000LL * 1000LL;
1028 break;
1029 case 't':
1030 mult = 1000LL * 1000LL * 1000LL * 1000LL;
1031 break;
1032 default:
1033 goto invalid;
1035 ++end;
1036 check_tail:
1037 while (isspace ((unsigned char) *end))
1038 ++end;
1039 if (*end != '\0')
1040 goto invalid;
1043 if (value > ~0ULL / mult)
1044 value = ~0ULL;
1045 else
1046 value *= mult;
1048 *pvalue = value;
1049 return true;
1051 invalid:
1052 gomp_error ("Invalid value for environment variable %s", name);
1053 return false;
1056 /* Parse a boolean value for environment variable NAME and store the
1057 result in VALUE. Return true if one was present and it was
1058 successfully parsed. */
1059 static bool
1060 parse_boolean (const char *env, const char *val, void *const params[])
1062 bool *value = (bool *) params[0];
1064 if (val == NULL)
1065 return false;
1067 while (isspace ((unsigned char) *val))
1068 ++val;
1069 if (strncasecmp (val, "true", 4) == 0)
1071 *value = true;
1072 val += 4;
1074 else if (strncasecmp (val, "false", 5) == 0)
1076 *value = false;
1077 val += 5;
1079 else
1080 val = "X";
1081 while (isspace ((unsigned char) *val))
1082 ++val;
1083 if (*val != '\0')
1085 print_env_var_error (env, val);
1086 return false;
1088 return true;
1091 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1093 static bool
1094 parse_wait_policy (const char *env, const char *val, void *const params[])
1096 int *pvalue = (int *) params[0];
1097 int ret = -1;
1099 if (val == NULL)
1101 *pvalue = -1;
1102 return false;
1105 while (isspace ((unsigned char) *val))
1106 ++val;
1107 if (strncasecmp (val, "active", 6) == 0)
1109 ret = 1;
1110 val += 6;
1112 else if (strncasecmp (val, "passive", 7) == 0)
1114 ret = 0;
1115 val += 7;
1117 else
1118 val = "X";
1119 while (isspace ((unsigned char) *val))
1120 ++val;
1121 if (*val == '\0')
1123 *pvalue = ret;
1124 return true;
1126 print_env_var_error (env, val);
1127 *pvalue = -1;
1128 return false;
1131 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1132 present and it was successfully parsed. */
1134 static bool
1135 parse_affinity (bool ignore)
1137 char *env, *end, *start;
1138 int pass;
1139 unsigned long cpu_beg, cpu_end, cpu_stride;
1140 size_t count = 0, needed;
1142 env = getenv ("GOMP_CPU_AFFINITY");
1143 if (env == NULL)
1144 return false;
1146 start = env;
1147 for (pass = 0; pass < 2; pass++)
1149 env = start;
1150 if (pass == 1)
1152 if (ignore)
1153 return false;
1155 gomp_places_list_len = 0;
1156 gomp_places_list = gomp_affinity_alloc (count, true);
1157 if (gomp_places_list == NULL)
1158 return false;
1162 while (isspace ((unsigned char) *env))
1163 ++env;
1165 errno = 0;
1166 cpu_beg = strtoul (env, &end, 0);
1167 if (errno || end == env || cpu_beg >= 65536)
1168 goto invalid;
1169 cpu_end = cpu_beg;
1170 cpu_stride = 1;
1172 env = end;
1173 if (*env == '-')
1175 errno = 0;
1176 cpu_end = strtoul (++env, &end, 0);
1177 if (errno || end == env || cpu_end >= 65536 || cpu_end < cpu_beg)
1178 goto invalid;
1180 env = end;
1181 if (*env == ':')
1183 errno = 0;
1184 cpu_stride = strtoul (++env, &end, 0);
1185 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1186 goto invalid;
1188 env = end;
1192 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1193 if (pass == 0)
1194 count += needed;
1195 else
1197 while (needed--)
1199 void *p = gomp_places_list[gomp_places_list_len];
1200 gomp_affinity_init_place (p);
1201 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1202 ++gomp_places_list_len;
1203 cpu_beg += cpu_stride;
1207 while (isspace ((unsigned char) *env))
1208 ++env;
1210 if (*env == ',')
1211 env++;
1212 else if (*env == '\0')
1213 break;
1215 while (1);
1218 if (gomp_places_list_len == 0)
1220 free (gomp_places_list);
1221 gomp_places_list = NULL;
1222 return false;
1224 return true;
1226 invalid:
1227 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1228 return false;
1231 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1232 static bool
1233 parse_allocator (const char *env, const char *val, void *const params[])
1235 uintptr_t *ret = (uintptr_t *) params[0];
1236 *ret = omp_default_mem_alloc;
1238 if (val == NULL)
1239 return false;
1241 while (isspace ((unsigned char) *val))
1242 ++val;
1243 if (0)
1245 #define C(v) \
1246 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1248 *ret = v; \
1249 val += sizeof (#v) - 1; \
1251 C (omp_default_mem_alloc)
1252 C (omp_large_cap_mem_alloc)
1253 C (omp_const_mem_alloc)
1254 C (omp_high_bw_mem_alloc)
1255 C (omp_low_lat_mem_alloc)
1256 C (omp_cgroup_mem_alloc)
1257 C (omp_pteam_mem_alloc)
1258 C (omp_thread_mem_alloc)
1259 #undef C
1260 else
1261 val = "X";
1262 while (isspace ((unsigned char) *val))
1263 ++val;
1264 if (*val == '\0')
1265 return true;
1266 print_env_var_error (env, val);
1267 *ret = omp_default_mem_alloc;
1268 return false;
1271 static void
1272 parse_acc_device_type (void)
1274 const char *env = getenv ("ACC_DEVICE_TYPE");
1276 if (env && *env != '\0')
1277 goacc_device_type = strdup (env);
1278 else
1279 goacc_device_type = NULL;
1282 static void
1283 parse_gomp_openacc_dim (void)
1285 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1286 const char *var_name = "GOMP_OPENACC_DIM";
1287 const char *env_var = getenv (var_name);
1288 const char *pos = env_var;
1289 int i;
1291 if (!env_var)
1292 return;
1294 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1296 char *eptr;
1297 long val;
1299 if (i && *pos++ != ':')
1300 break;
1302 if (*pos == ':')
1303 continue;
1305 errno = 0;
1306 val = strtol (pos, &eptr, 10);
1307 if (errno || eptr == pos || val < 0 || (unsigned)val != val)
1308 break;
1310 goacc_default_dims[i] = (int)val;
1311 pos = (const char *) eptr;
1315 /* Helper function for omp_display_env which prints the values of run_sched_var.
1316 'device' can be 'host', 'dev', 'all' or a particular device number. */
1318 static void
1319 print_schedule (enum gomp_schedule_type run_sched_var, int run_sched_chunk_size,
1320 const char *device)
1322 fprintf (stderr, " [%s] OMP_SCHEDULE = '", device);
1323 if ((run_sched_var & GFS_MONOTONIC))
1325 if (run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1326 fputs ("MONOTONIC:", stderr);
1328 else if (run_sched_var == GFS_STATIC)
1329 fputs ("NONMONOTONIC:", stderr);
1330 switch (run_sched_var & ~GFS_MONOTONIC)
1332 case GFS_RUNTIME:
1333 fputs ("RUNTIME", stderr);
1334 if (run_sched_chunk_size != 1)
1335 fprintf (stderr, ",%d", run_sched_chunk_size);
1336 break;
1337 case GFS_STATIC:
1338 fputs ("STATIC", stderr);
1339 if (run_sched_chunk_size != 0)
1340 fprintf (stderr, ",%d", run_sched_chunk_size);
1341 break;
1342 case GFS_DYNAMIC:
1343 fputs ("DYNAMIC", stderr);
1344 if (run_sched_chunk_size != 1)
1345 fprintf (stderr, ",%d", run_sched_chunk_size);
1346 break;
1347 case GFS_GUIDED:
1348 fputs ("GUIDED", stderr);
1349 if (run_sched_chunk_size != 1)
1350 fprintf (stderr, ",%d", run_sched_chunk_size);
1351 break;
1352 case GFS_AUTO:
1353 fputs ("AUTO", stderr);
1354 break;
1356 fputs ("'\n", stderr);
1359 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1360 'device' can be 'host', 'dev', 'all', or a particular device number. */
1362 static void
1363 print_proc_bind (char proc_bind_var, unsigned long len, char **list,
1364 const char *device)
1366 fprintf (stderr, " [%s] OMP_PROC_BIND = '", device);
1367 switch (proc_bind_var)
1369 case omp_proc_bind_false:
1370 fputs ("FALSE", stderr);
1371 break;
1372 case omp_proc_bind_true:
1373 fputs ("TRUE", stderr);
1374 break;
1375 case omp_proc_bind_master:
1376 fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1377 break;
1378 case omp_proc_bind_close:
1379 fputs ("CLOSE", stderr);
1380 break;
1381 case omp_proc_bind_spread:
1382 fputs ("SPREAD", stderr);
1383 break;
1385 for (int i = 1; i < len; i++)
1386 switch ((*list)[i])
1388 case omp_proc_bind_master:
1389 fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1390 break;
1391 case omp_proc_bind_close:
1392 fputs (",CLOSE", stderr);
1393 break;
1394 case omp_proc_bind_spread:
1395 fputs (",SPREAD", stderr);
1396 break;
1398 fputs ("'\n", stderr);
1401 enum gomp_parse_type
1403 PARSE_INT = 1,
1404 PARSE_BOOL = 2,
1405 PARSE_UINT = 3,
1406 PARSE_ULONG = 4,
1407 PARSE_UCHAR = 5,
1408 PARSE_SCHEDULE =6,
1409 PARSE_BIND = 7
1412 /* The following table contains items that help parsing environment variables
1413 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1414 are affected by the environment variable. FLAGS determine what variant of
1415 environment variable is allowed. */
1417 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1418 static const struct envvar
1420 const char *name;
1421 int name_len;
1422 uint8_t flag_vars[3];
1423 uint8_t flag;
1424 bool (*parse_func) (const char *, const char *, void *const[]);
1425 } envvars[] = {
1426 { ENTRY ("SCHEDULE"),
1427 { GOMP_ICV_SCHEDULE, GOMP_ICV_SCHEDULE_CHUNK_SIZE },
1428 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1429 &parse_schedule },
1430 { ENTRY ("NUM_TEAMS"),
1431 { GOMP_ICV_NTEAMS },
1432 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1433 &parse_int },
1434 { ENTRY ("DYNAMIC"),
1435 { GOMP_ICV_DYNAMIC },
1436 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1437 &parse_boolean },
1438 { ENTRY ("TEAMS_THREAD_LIMIT"),
1439 { GOMP_ICV_TEAMS_THREAD_LIMIT },
1440 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1441 &parse_int },
1442 { ENTRY ("THREAD_LIMIT"),
1443 { GOMP_ICV_THREAD_LIMIT },
1444 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1445 &parse_unsigned_long },
1446 { ENTRY ("NUM_THREADS"),
1447 { GOMP_ICV_NTHREADS, GOMP_ICV_NTHREADS_LIST, GOMP_ICV_NTHREADS_LIST_LEN },
1448 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1449 &parse_unsigned_long_list },
1450 { ENTRY ("PROC_BIND"),
1451 { GOMP_ICV_BIND, GOMP_ICV_BIND_LIST, GOMP_ICV_BIND_LIST_LEN },
1452 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1453 &parse_bind_var },
1454 { ENTRY ("MAX_ACTIVE_LEVELS"),
1455 { GOMP_ICV_MAX_ACTIVE_LEVELS },
1456 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1457 &parse_unsigned_long },
1458 { ENTRY ("WAIT_POLICY"),
1459 { GOMP_ICV_WAIT_POLICY },
1460 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1461 &parse_wait_policy },
1462 { ENTRY ("STACKSIZE"),
1463 { GOMP_ICV_STACKSIZE },
1464 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1465 &parse_stacksize },
1466 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION }, 0, &parse_boolean },
1467 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY }, 0,
1468 &parse_boolean },
1469 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD }, 0,
1470 &parse_target_offload },
1471 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY }, 0,
1472 &parse_int },
1473 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR }, 0, &parse_allocator },
1474 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE },
1475 GOMP_ENV_SUFFIX_DEV | GOMP_ENV_SUFFIX_ALL | GOMP_ENV_SUFFIX_DEV_X,
1476 &parse_int }
1478 #undef ENTRY
1479 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1481 /* The following table is used to apply the hierarchy of ICV variants for host
1482 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1483 undefined. */
1485 static const struct host_envvar
1487 unsigned char flag_var;
1488 void *dest[3];
1489 int type_code;
1490 } host_envvars[] = {
1491 { GOMP_ICV_NTEAMS, { &gomp_nteams_var }, PARSE_INT },
1492 { GOMP_ICV_DYNAMIC, { &gomp_global_icv.dyn_var }, PARSE_BOOL },
1493 { GOMP_ICV_DEFAULT_DEVICE, { &gomp_global_icv.default_device_var },
1494 PARSE_INT },
1495 { GOMP_ICV_TEAMS_THREAD_LIMIT, { &gomp_teams_thread_limit_var }, PARSE_INT },
1496 { GOMP_ICV_SCHEDULE,
1497 { &gomp_global_icv.run_sched_var, &gomp_global_icv.run_sched_chunk_size },
1498 PARSE_SCHEDULE },
1499 { GOMP_ICV_THREAD_LIMIT, { &gomp_global_icv.thread_limit_var }, PARSE_UINT },
1500 { GOMP_ICV_NTHREADS,
1501 { &gomp_global_icv.nthreads_var, &gomp_nthreads_var_list,
1502 &gomp_nthreads_var_list_len }, PARSE_ULONG },
1503 { GOMP_ICV_BIND,
1504 { &gomp_global_icv.bind_var, &gomp_bind_var_list, &gomp_bind_var_list_len },
1505 PARSE_BIND },
1506 { GOMP_ICV_MAX_ACTIVE_LEVELS, { &gomp_global_icv.max_active_levels_var },
1507 PARSE_UCHAR },
1509 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1511 #define INT_MAX_STR_LEN 10
1513 bool
1514 gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv)
1516 return value & (1 << (icv - 1));
1519 static void
1520 gomp_set_icv_flag (uint32_t *value, enum gomp_icvs icv)
1522 *value |= 1 << (icv - 1);
1525 static void
1526 print_device_specific_icvs (int icv_code)
1528 struct gomp_icv_list *list = gomp_initial_icv_list;
1529 int i;
1530 char dev_num[INT_MAX_STR_LEN + 1];
1532 while (list != NULL)
1534 if (list->device_num < 0)
1536 list = list->next;
1537 continue;
1540 switch (icv_code)
1542 case GOMP_ICV_NTEAMS:
1543 if (gomp_get_icv_flag (list->flags, GOMP_ICV_NTEAMS))
1544 fprintf (stderr, " [%d] OMP_NUM_TEAMS = '%d'\n",
1545 list->device_num, list->icvs.nteams_var);
1546 break;
1547 case GOMP_ICV_DYNAMIC:
1548 if (gomp_get_icv_flag (list->flags, GOMP_ICV_DYNAMIC))
1549 fprintf (stderr, " [%d] OMP_DYNAMIC = '%s'\n",
1550 list->device_num, list->icvs.dyn_var ? "TRUE" : "FALSE");
1551 break;
1552 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1553 if (gomp_get_icv_flag (list->flags, GOMP_ICV_TEAMS_THREAD_LIMIT))
1554 fprintf (stderr, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1555 list->device_num, list->icvs.teams_thread_limit_var);
1556 break;
1557 case GOMP_ICV_SCHEDULE:
1558 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_SCHEDULE)))
1559 break;
1560 sprintf (dev_num, "%d", list->device_num);
1561 print_schedule (list->icvs.run_sched_var,
1562 list->icvs.run_sched_chunk_size,
1563 dev_num);
1564 break;
1565 case GOMP_ICV_THREAD_LIMIT:
1566 if (gomp_get_icv_flag (list->flags, GOMP_ICV_THREAD_LIMIT))
1567 fprintf (stderr, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1568 list->device_num, list->icvs.thread_limit_var);
1569 break;
1570 case GOMP_ICV_NTHREADS:
1571 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_NTHREADS)))
1572 break;
1573 fprintf (stderr, " [%d] OMP_NUM_THREADS = '%lu", list->device_num,
1574 list->icvs.nthreads_var);
1575 for (i = 1; i < list->icvs.nthreads_var_list_len; i++)
1576 fprintf (stderr, ",%lu", list->icvs.nthreads_var_list[i]);
1577 fputs ("'\n", stderr);
1578 break;
1579 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1580 fprintf (stderr, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1581 list->device_num, list->icvs.max_active_levels_var);
1582 break;
1583 case GOMP_ICV_BIND:
1584 if (!(gomp_get_icv_flag (list->flags, GOMP_ICV_BIND)))
1585 break;
1586 sprintf (dev_num, "%d", list->device_num);
1587 print_proc_bind (list->icvs.bind_var, list->icvs.bind_var_list_len,
1588 &list->icvs.bind_var_list, dev_num);
1589 break;
1590 case GOMP_ICV_WAIT_POLICY:
1591 if (gomp_get_icv_flag (list->flags, GOMP_ICV_WAIT_POLICY))
1592 fprintf (stderr, " [%d] OMP_WAIT_POLICY = '%s'\n",
1593 list->device_num,
1594 list->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1595 break;
1596 case GOMP_ICV_STACKSIZE:
1597 if (gomp_get_icv_flag (list->flags, GOMP_ICV_STACKSIZE))
1598 fprintf (stderr, " [%d] OMP_STACKSIZE = '%lu'\n",
1599 list->device_num, list->icvs.stacksize);
1600 break;
1602 list = list->next;
1606 void
1607 omp_display_env (int verbose)
1609 int i;
1610 struct gomp_icv_list *dev
1611 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV);
1612 struct gomp_icv_list *all
1613 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
1614 struct gomp_icv_list *none
1615 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
1617 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1619 fputs (" _OPENMP = '201511'\n", stderr);
1621 fprintf (stderr, " [host] OMP_DYNAMIC = '%s'\n",
1622 none->icvs.dyn_var ? "TRUE" : "FALSE");
1623 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_DYNAMIC))
1624 fprintf (stderr, " [all] OMP_DYNAMIC = '%s'\n",
1625 all->icvs.dyn_var ? "TRUE" : "FALSE");
1626 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_DYNAMIC))
1627 fprintf (stderr, " [device] OMP_DYNAMIC = '%s'\n",
1628 dev->icvs.dyn_var ? "TRUE" : "FALSE");
1629 print_device_specific_icvs (GOMP_ICV_DYNAMIC);
1631 /* The OMP_NESTED environment variable has been deprecated. */
1632 fprintf (stderr, " [host] OMP_NESTED = '%s'\n",
1633 none->icvs.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1635 fprintf (stderr, " [host] OMP_NUM_THREADS = '%lu",
1636 none->icvs.nthreads_var);
1637 for (i = 1; i < none->icvs.nthreads_var_list_len; i++)
1638 fprintf (stderr, ",%lu", none->icvs.nthreads_var_list[i]);
1639 fputs ("'\n", stderr);
1640 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTHREADS))
1642 fprintf (stderr, " [all] OMP_NUM_THREADS = '%lu",
1643 all->icvs.nthreads_var);
1644 for (i = 1; i < all->icvs.nthreads_var_list_len; i++)
1645 fprintf (stderr, ",%lu", all->icvs.nthreads_var_list[i]);
1646 fputs ("'\n", stderr);
1648 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTHREADS))
1650 fprintf (stderr, " [device] OMP_NUM_THREADS = '%lu",
1651 dev->icvs.nthreads_var);
1652 for (i = 1; i < dev->icvs.nthreads_var_list_len; i++)
1653 fprintf (stderr, ",%lu", dev->icvs.nthreads_var_list[i]);
1654 fputs ("'\n", stderr);
1656 print_device_specific_icvs (GOMP_ICV_NTHREADS);
1659 print_schedule (none->icvs.run_sched_var,
1660 none->icvs.run_sched_chunk_size, "host");
1661 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_SCHEDULE))
1662 print_schedule (all->icvs.run_sched_var,
1663 all->icvs.run_sched_chunk_size, "all");
1664 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_SCHEDULE))
1665 print_schedule (dev->icvs.run_sched_var,
1666 dev->icvs.run_sched_chunk_size, "device");
1667 print_device_specific_icvs (GOMP_ICV_SCHEDULE);
1669 print_proc_bind (none->icvs.bind_var,
1670 none->icvs.bind_var_list_len,
1671 &none->icvs.bind_var_list, "host");
1672 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND))
1673 print_proc_bind (all->icvs.bind_var,
1674 all->icvs.bind_var_list_len,
1675 &all->icvs.bind_var_list, "all");
1676 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_BIND))
1677 print_proc_bind (dev->icvs.bind_var,
1678 dev->icvs.bind_var_list_len,
1679 &dev->icvs.bind_var_list, "device");
1680 print_device_specific_icvs (GOMP_ICV_BIND);
1682 fputs (" [host] OMP_PLACES = '", stderr);
1683 for (i = 0; i < gomp_places_list_len; i++)
1685 fputs ("{", stderr);
1686 gomp_affinity_print_place (gomp_places_list[i]);
1687 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1689 fputs ("'\n", stderr);
1691 fprintf (stderr, " [host] OMP_STACKSIZE = '%lu'\n",
1692 none->icvs.stacksize);
1693 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
1694 fprintf (stderr, " [all] OMP_STACKSIZE = '%lu'\n",
1695 all->icvs.stacksize);
1696 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_STACKSIZE))
1697 fprintf (stderr, " [device] OMP_STACKSIZE = '%lu'\n",
1698 dev->icvs.stacksize);
1699 print_device_specific_icvs (GOMP_ICV_STACKSIZE);
1701 /* GOMP's default value is actually neither active nor passive. */
1702 fprintf (stderr, " [host] OMP_WAIT_POLICY = '%s'\n",
1703 none->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1704 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
1705 fprintf (stderr, " [all] OMP_WAIT_POLICY = '%s'\n",
1706 all->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1707 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_WAIT_POLICY))
1708 fprintf (stderr, " [device] OMP_WAIT_POLICY = '%s'\n",
1709 dev->icvs.wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1710 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY);
1712 fprintf (stderr, " [host] OMP_THREAD_LIMIT = '%u'\n",
1713 none->icvs.thread_limit_var);
1714 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_THREAD_LIMIT))
1715 fprintf (stderr, " [all] OMP_THREAD_LIMIT = '%d'\n",
1716 all->icvs.thread_limit_var);
1717 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_THREAD_LIMIT))
1718 fprintf (stderr, " [device] OMP_THREAD_LIMIT = '%d'\n",
1719 dev->icvs.thread_limit_var);
1720 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT);
1722 fprintf (stderr, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1723 none->icvs.max_active_levels_var);
1724 if (all != NULL && gomp_get_icv_flag (all->flags,
1725 GOMP_ICV_MAX_ACTIVE_LEVELS))
1726 fprintf (stderr, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1727 all->icvs.max_active_levels_var);
1728 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1729 GOMP_ICV_MAX_ACTIVE_LEVELS))
1730 fprintf (stderr, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1731 dev->icvs.max_active_levels_var);
1732 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS);
1735 fprintf (stderr, " [host] OMP_NUM_TEAMS = '%d'\n",
1736 none->icvs.nteams_var);
1737 if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_NTEAMS))
1738 fprintf (stderr, " [all] OMP_NUM_TEAMS = '%d'\n",
1739 all->icvs.nteams_var);
1740 if (dev != NULL && gomp_get_icv_flag (dev->flags, GOMP_ICV_NTEAMS))
1741 fprintf (stderr, " [device] OMP_NUM_TEAMS = '%d'\n",
1742 dev->icvs.nteams_var);
1743 print_device_specific_icvs (GOMP_ICV_NTEAMS);
1745 fprintf (stderr, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1746 none->icvs.teams_thread_limit_var);
1747 if (all != NULL && gomp_get_icv_flag (all->flags,
1748 GOMP_ICV_TEAMS_THREAD_LIMIT))
1749 fprintf (stderr, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1750 all->icvs.teams_thread_limit_var);
1751 if (dev != NULL && gomp_get_icv_flag (dev->flags,
1752 GOMP_ICV_TEAMS_THREAD_LIMIT))
1753 fprintf (stderr, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1754 dev->icvs.teams_thread_limit_var);
1755 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT);
1757 fprintf (stderr, " [all] OMP_CANCELLATION = '%s'\n",
1758 gomp_cancel_var ? "TRUE" : "FALSE");
1760 fprintf (stderr, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1761 none->icvs.default_device_var);
1763 fprintf (stderr, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1764 gomp_max_task_priority_var);
1765 fprintf (stderr, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1766 gomp_display_affinity_var ? "TRUE" : "FALSE");
1767 fprintf (stderr, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1768 gomp_affinity_format_var);
1769 fprintf (stderr, " [host] OMP_ALLOCATOR = '");
1770 switch (gomp_def_allocator)
1772 #define C(v) case v: fputs (#v, stderr); break;
1773 C (omp_default_mem_alloc)
1774 C (omp_large_cap_mem_alloc)
1775 C (omp_const_mem_alloc)
1776 C (omp_high_bw_mem_alloc)
1777 C (omp_low_lat_mem_alloc)
1778 C (omp_cgroup_mem_alloc)
1779 C (omp_pteam_mem_alloc)
1780 C (omp_thread_mem_alloc)
1781 #undef C
1782 default: break;
1784 fputs ("'\n", stderr);
1786 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr);
1787 switch (gomp_target_offload_var)
1789 case GOMP_TARGET_OFFLOAD_DEFAULT:
1790 fputs ("DEFAULT", stderr);
1791 break;
1792 case GOMP_TARGET_OFFLOAD_MANDATORY:
1793 fputs ("MANDATORY", stderr);
1794 break;
1795 case GOMP_TARGET_OFFLOAD_DISABLED:
1796 fputs ("DISABLED", stderr);
1797 break;
1799 fputs ("'\n", stderr);
1801 if (verbose)
1803 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr);
1804 fprintf (stderr, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize);
1805 #ifdef HAVE_INTTYPES_H
1806 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%"PRIu64"'\n",
1807 (uint64_t) gomp_spin_count_var);
1808 #else
1809 fprintf (stderr, " [host] GOMP_SPINCOUNT = '%lu'\n",
1810 (unsigned long) gomp_spin_count_var);
1811 #endif
1814 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1816 ialias (omp_display_env)
1818 static void
1819 handle_omp_display_env (void)
1821 const char *env;
1822 bool display = false;
1823 bool verbose = false;
1825 env = getenv ("OMP_DISPLAY_ENV");
1826 if (env == NULL)
1827 return;
1829 while (isspace ((unsigned char) *env))
1830 ++env;
1831 if (strncasecmp (env, "true", 4) == 0)
1833 display = true;
1834 env += 4;
1836 else if (strncasecmp (env, "false", 5) == 0)
1838 display = false;
1839 env += 5;
1841 else if (strncasecmp (env, "verbose", 7) == 0)
1843 display = true;
1844 verbose = true;
1845 env += 7;
1847 else
1848 env = "X";
1849 while (isspace ((unsigned char) *env))
1850 ++env;
1851 if (*env != '\0')
1852 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1854 if (display)
1855 ialias_call (omp_display_env) (verbose);
1858 /* Helper function for initialize_env. Extracts the device number from
1859 an environment variable name. ENV is the complete environment variable.
1860 DEV_NUM_PTR points to the start of the device number in the environment
1861 variable string. DEV_NUM_LEN is the returned length of the device num
1862 string. */
1864 static bool
1865 get_device_num (char *env, char *dev_num_ptr, int *dev_num, int *dev_num_len)
1867 char *end;
1868 unsigned long val = strtoul (dev_num_ptr, &end, 10);
1869 if (val > INT_MAX
1870 || *end != '='
1871 || (dev_num_ptr[0] == '0' && end != dev_num_ptr + 1)
1872 || (dev_num_ptr[0] < '0' || dev_num_ptr[0] > '9'))
1874 gomp_error ("Invalid device number in %s", env);
1875 return false;
1877 *dev_num = val;
1878 *dev_num_len = end - dev_num_ptr;
1879 return true;
1882 static void
1883 get_icv_member_addr (struct gomp_initial_icvs *icvs, int icv_code,
1884 void *icv_addr[3])
1886 if (icv_code == 0 || icv_addr == NULL)
1887 return;
1889 icv_addr[0] = icv_addr[1] = icv_addr[2] = NULL;
1891 switch (icv_code)
1893 case GOMP_ICV_NTEAMS:
1894 icv_addr[0] = &icvs->nteams_var;
1895 /* icv_addr[1] = (void *) false; */
1896 break;
1897 case GOMP_ICV_DYNAMIC:
1898 icv_addr[0] = &(*icvs).dyn_var;
1899 break;
1900 case GOMP_ICV_TEAMS_THREAD_LIMIT:
1901 icv_addr[0] = &icvs->teams_thread_limit_var;
1902 /* icv_addr[1] = (void *) false; */
1903 break;
1904 case GOMP_ICV_SCHEDULE:
1905 icv_addr[0] = &icvs->run_sched_var;
1906 icv_addr[1] = &icvs->run_sched_chunk_size;
1907 break;
1908 case GOMP_ICV_THREAD_LIMIT:
1909 icv_addr[0] = &icvs->thread_limit_var;
1910 /* icv_addr[1] = (void *) false; */
1911 icv_addr[2] = (void *) UINT_MAX;
1912 break;
1913 case GOMP_ICV_NTHREADS:
1914 icv_addr[0] = &icvs->nthreads_var;
1915 icv_addr[1] = &icvs->nthreads_var_list;
1916 icv_addr[2] = &icvs->nthreads_var_list_len;
1917 break;
1918 case GOMP_ICV_MAX_ACTIVE_LEVELS:
1919 icv_addr[0] = &icvs->max_active_levels_var;
1920 icv_addr[1] = (void *) true;
1921 icv_addr[2] = (void *) gomp_supported_active_levels;
1922 break;
1923 case GOMP_ICV_BIND:
1924 icv_addr[0] = &icvs->bind_var;
1925 icv_addr[1] = &icvs->bind_var_list;
1926 icv_addr[2] = &icvs->bind_var_list_len;
1927 break;
1928 case GOMP_ICV_WAIT_POLICY:
1929 icv_addr[0] = &icvs->wait_policy;
1930 break;
1931 case GOMP_ICV_STACKSIZE:
1932 icv_addr[0] = &icvs->stacksize;
1933 break;
1934 case GOMP_ICV_CANCELLATION:
1935 icv_addr[0] = &gomp_cancel_var;
1936 break;
1937 case GOMP_ICV_DISPLAY_AFFINITY:
1938 icv_addr[0] = &gomp_display_affinity_var;
1939 break;
1940 case GOMP_ICV_TARGET_OFFLOAD:
1941 icv_addr[0] = &gomp_target_offload_var;
1942 break;
1943 case GOMP_ICV_MAX_TASK_PRIORITY:
1944 icv_addr[0] = &gomp_max_task_priority_var;
1945 break;
1946 case GOMP_ICV_ALLOCATOR:
1947 icv_addr[0] = &gomp_def_allocator;
1948 break;
1949 case GOMP_ICV_DEFAULT_DEVICE:
1950 icv_addr[0] = &icvs->default_device_var;
1951 icv_addr[1] = (void *) true;
1952 break;
1956 struct gomp_icv_list *
1957 gomp_get_initial_icv_item (int dev_num)
1959 struct gomp_icv_list *l = gomp_initial_icv_list;
1960 while (l != NULL && l->device_num != dev_num)
1961 l = l->next;
1963 return l;
1966 static void
1967 initialize_icvs (struct gomp_initial_icvs *icvs)
1969 icvs->nthreads_var_list = NULL;
1970 icvs->bind_var_list = NULL;
1971 icvs->nthreads_var = gomp_default_icv_values.nthreads_var;
1972 icvs->nthreads_var_list_len = 0;
1973 icvs->bind_var_list_len = 0;
1974 icvs->stacksize = 0;
1975 icvs->thread_limit_var = gomp_default_icv_values.thread_limit_var;
1976 icvs->run_sched_var = gomp_default_icv_values.run_sched_var;
1977 icvs->run_sched_chunk_size = gomp_default_icv_values.run_sched_chunk_size;
1978 icvs->default_device_var = gomp_default_icv_values.default_device_var;
1979 icvs->dyn_var = gomp_default_icv_values.dyn_var;
1980 icvs->max_active_levels_var = gomp_default_icv_values.max_active_levels_var;
1981 icvs->bind_var = gomp_default_icv_values.bind_var;
1982 icvs->nteams_var = gomp_default_icv_values.nteams_var;
1983 icvs->teams_thread_limit_var = gomp_default_icv_values.teams_thread_limit_var;
1984 icvs->wait_policy = 0;
1987 /* Helper function for initialize_env to add a device specific ICV value
1988 to gomp_initial_icv_list. */
1990 static uint32_t *
1991 add_initial_icv_to_list (int dev_num, int icv_code, void *icv_addr[3])
1993 struct gomp_icv_list *last = NULL, *l = gomp_initial_icv_list;
1994 while (l != NULL && l->device_num != dev_num)
1996 last = l;
1997 l = l->next;
2000 if (l == NULL)
2002 l = ((struct gomp_icv_list *)
2003 gomp_malloc_cleared (sizeof (struct gomp_icv_list)));
2004 l->device_num = dev_num;
2005 initialize_icvs (&l->icvs);
2006 if (dev_num < 0)
2008 l->next = gomp_initial_icv_list;
2009 gomp_initial_icv_list = l;
2011 else
2013 l->next = NULL;
2014 if (last == NULL)
2015 gomp_initial_icv_list = l;
2016 else
2017 last->next = l;
2021 get_icv_member_addr (&l->icvs, icv_code, icv_addr);
2023 return &l->flags;
2026 /* Return true if STR string starts with PREFIX. */
2028 static inline bool
2029 startswith (const char *str, const char *prefix)
2031 return strncmp (str, prefix, strlen (prefix)) == 0;
2034 static void __attribute__((constructor))
2035 initialize_env (void)
2037 char **env;
2038 int omp_var, dev_num = 0, dev_num_len = 0, i;
2039 bool ignore = false;
2040 char *env_val;
2041 void *params[3];
2042 uint32_t *flag_var_addr = NULL;
2043 unsigned pos;
2044 struct gomp_icv_list *all, *none;
2046 /* Do a compile time check that mkomp_h.pl did good job. */
2047 omp_check_defines ();
2049 #ifndef HAVE_SYNC_BUILTINS
2050 gomp_mutex_init (&gomp_managed_threads_lock);
2051 #endif
2052 gomp_init_num_threads ();
2053 gomp_available_cpus = gomp_global_icv.nthreads_var;
2055 /* Initial values for host environment variables should always exist even if
2056 there is no explicitly set host environment variable. Moreover, they are
2057 set to the initial global values. */
2058 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX, 0, NULL);
2059 none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
2060 initialize_icvs (&none->icvs);
2062 for (env = environ; *env != 0; env++)
2064 if (!startswith (*env, "OMP_"))
2065 continue;
2067 /* Name of the environment variable without suffix "OMP_". */
2068 char *name = *env + sizeof ("OMP_") - 1;
2069 for (omp_var = 0; omp_var < OMP_VAR_CNT; omp_var++)
2071 if (startswith (name, envvars[omp_var].name))
2073 pos = envvars[omp_var].name_len;
2074 if (name[pos] == '=')
2076 pos++;
2077 flag_var_addr
2078 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX,
2079 envvars[omp_var].flag_vars[0],
2080 params);
2082 else if (startswith (&name[pos], "_DEV=")
2083 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV)
2085 pos += 5;
2086 flag_var_addr
2087 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV,
2088 envvars[omp_var].flag_vars[0],
2089 params);
2091 else if (startswith (&name[pos], "_ALL=")
2092 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_ALL)
2094 pos += 5;
2095 flag_var_addr
2096 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL,
2097 envvars[omp_var].flag_vars[0],
2098 params);
2100 else if (startswith (&name[pos], "_DEV_")
2101 && envvars[omp_var].flag & GOMP_ENV_SUFFIX_DEV_X)
2103 pos += 5;
2104 if (!get_device_num (*env, &name[pos], &dev_num,
2105 &dev_num_len))
2106 break;
2108 pos += dev_num_len + 1;
2109 flag_var_addr
2110 = add_initial_icv_to_list (dev_num,
2111 envvars[omp_var].flag_vars[0],
2112 params);
2114 else
2116 gomp_error ("Invalid environment variable in %s", *env);
2117 break;
2119 env_val = &name[pos];
2121 if (envvars[omp_var].parse_func (*env, env_val, params))
2123 for (i = 0; i < 3; ++i)
2124 if (envvars[omp_var].flag_vars[i])
2125 gomp_set_icv_flag (flag_var_addr,
2126 envvars[omp_var].flag_vars[i]);
2127 else
2128 break;
2131 break;
2136 all = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL);
2137 for (omp_var = 0; omp_var < OMP_HOST_VAR_CNT; omp_var++)
2139 if (none != NULL
2140 && gomp_get_icv_flag (none->flags, host_envvars[omp_var].flag_var))
2141 get_icv_member_addr (&none->icvs,
2142 host_envvars[omp_var].flag_var, params);
2143 else if (all != NULL
2144 && gomp_get_icv_flag (all->flags,
2145 host_envvars[omp_var].flag_var))
2146 get_icv_member_addr (&all->icvs, host_envvars[omp_var].flag_var,
2147 params);
2148 else
2149 continue;
2151 switch (host_envvars[omp_var].type_code)
2153 case PARSE_INT:
2154 for (i = 0; i < 3; ++i)
2155 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2156 *(int *) (host_envvars[omp_var].dest[i]) = *(int *) params[i];
2157 break;
2158 case PARSE_BOOL:
2159 for (i = 0; i < 3; ++i)
2160 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2161 *(bool *) (host_envvars[omp_var].dest[i]) = *(bool *) params[i];
2162 break;
2163 case PARSE_UINT:
2164 for (i = 0; i < 3; ++i)
2165 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2166 *(unsigned int *) (host_envvars[omp_var].dest[i])
2167 = *(unsigned int *) params[i];
2168 break;
2169 case PARSE_ULONG:
2170 for (i = 0; i < 3; ++i)
2171 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2172 *(unsigned long *) (host_envvars[omp_var].dest[i])
2173 = *(unsigned long *) params[i];
2174 break;
2175 case PARSE_UCHAR:
2176 for (i = 0; i < 3; ++i)
2177 if (host_envvars[omp_var].dest[i] != NULL && params[i] != NULL)
2178 *(unsigned char *) (host_envvars[omp_var].dest[i])
2179 = *(unsigned char *) params[i];
2180 break;
2181 case PARSE_SCHEDULE:
2182 *(enum gomp_schedule_type *) (host_envvars[omp_var].dest[0])
2183 = *(enum gomp_schedule_type *) params[0];
2184 *(int *) (host_envvars[omp_var].dest[1]) = *(int *) params[1];
2185 break;
2186 case PARSE_BIND:
2187 *(char *) (host_envvars[omp_var].dest[0]) = *(char *) params[0];
2188 *(char **) (host_envvars[omp_var].dest[1]) = *(char **) params[1];
2189 *(unsigned long *) (host_envvars[omp_var].dest[2])
2190 = *(unsigned long *) params[2];
2191 break;
2195 if (((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_BIND))
2196 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_BIND)))
2197 && gomp_global_icv.bind_var == omp_proc_bind_false)
2198 ignore = true;
2200 if (!((none != NULL
2201 && gomp_get_icv_flag (none->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))
2202 || (all != NULL
2203 && gomp_get_icv_flag (all->flags, GOMP_ICV_MAX_ACTIVE_LEVELS))))
2205 bool nested = true;
2206 const char *env = getenv ("OMP_NESTED");
2208 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2209 if (parse_boolean ("OMP_NESTED", env, (void *[]) {&nested}))
2210 gomp_global_icv.max_active_levels_var
2211 = nested ? gomp_supported_active_levels : 1;
2212 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
2213 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
2216 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2217 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
2219 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2220 parsed if present in the environment. If OMP_PROC_BIND was set
2221 explicitly to false, don't populate places list though. If places
2222 list was successfully set from OMP_PLACES, only parse but don't process
2223 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2224 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2225 was successfully parsed into a places list, otherwise to
2226 OMP_PROC_BIND=false. */
2227 if (parse_places_var ("OMP_PLACES", ignore))
2229 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2230 gomp_global_icv.bind_var = true;
2231 ignore = true;
2233 if (parse_affinity (ignore))
2235 if (gomp_global_icv.bind_var == omp_proc_bind_false)
2236 gomp_global_icv.bind_var = true;
2237 ignore = true;
2239 if (gomp_global_icv.bind_var != omp_proc_bind_false)
2240 gomp_init_affinity ();
2243 const char *env = getenv ("OMP_AFFINITY_FORMAT");
2244 if (env != NULL)
2245 gomp_set_affinity_format (env, strlen (env));
2248 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_WAIT_POLICY))
2249 wait_policy = none->icvs.wait_policy;
2250 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_WAIT_POLICY))
2251 wait_policy = all->icvs.wait_policy;
2253 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
2255 /* Using a rough estimation of 100000 spins per msec,
2256 use 5 min blocking for OMP_WAIT_POLICY=active,
2257 3 msec blocking when OMP_WAIT_POLICY is not specificed
2258 and 0 when OMP_WAIT_POLICY=passive.
2259 Depending on the CPU speed, this can be e.g. 5 times longer
2260 or 5 times shorter. */
2261 if (wait_policy > 0)
2262 gomp_spin_count_var = 30000000000LL;
2263 else if (wait_policy < 0)
2264 gomp_spin_count_var = 300000LL;
2266 /* gomp_throttled_spin_count_var is used when there are more libgomp
2267 managed threads than available CPUs. Use very short spinning. */
2268 if (wait_policy > 0)
2269 gomp_throttled_spin_count_var = 1000LL;
2270 else if (wait_policy < 0)
2271 gomp_throttled_spin_count_var = 100LL;
2272 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
2273 gomp_throttled_spin_count_var = gomp_spin_count_var;
2275 /* Not strictly environment related, but ordering constructors is tricky. */
2276 pthread_attr_init (&gomp_thread_attr);
2278 if (!(none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE)))
2280 const char *env = getenv ("GOMP_STACKSIZE");
2281 if (env != NULL
2282 && parse_stacksize ("GOMP_STACKSIZE", env,
2283 (void *[3]) {&none->icvs.stacksize}))
2284 gomp_set_icv_flag (&none->flags, GOMP_ICV_STACKSIZE);
2286 if (none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2287 stacksize = none->icvs.stacksize;
2288 else if (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2289 stacksize = all->icvs.stacksize;
2291 if ((none != NULL && gomp_get_icv_flag (none->flags, GOMP_ICV_STACKSIZE))
2292 || (all != NULL && gomp_get_icv_flag (all->flags, GOMP_ICV_STACKSIZE))
2293 || GOMP_DEFAULT_STACKSIZE)
2295 int err;
2297 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
2299 #ifdef PTHREAD_STACK_MIN
2300 if (err == EINVAL)
2302 if (stacksize < PTHREAD_STACK_MIN)
2303 gomp_error ("Stack size less than minimum of %luk",
2304 PTHREAD_STACK_MIN / 1024ul
2305 + (PTHREAD_STACK_MIN % 1024 != 0));
2306 else
2307 gomp_error ("Stack size larger than system limit");
2309 else
2310 #endif
2311 if (err != 0)
2312 gomp_error ("Stack size change failed: %s", strerror (err));
2315 handle_omp_display_env ();
2317 /* OpenACC. */
2319 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2320 (void *[]) {&goacc_device_num, (void *) true}))
2321 goacc_device_num = 0;
2323 parse_acc_device_type ();
2324 parse_gomp_openacc_dim ();
2326 goacc_runtime_initialize ();
2328 goacc_profiling_initialize ();
2330 #endif /* LIBGOMP_OFFLOADED_ONLY */