Reset prologue_location before calling code_end
[official-gcc.git] / libgomp / env.c
bloba24deabcd58cf2d66280f02e0cb6c7df11d2aac0
1 /* Copyright (C) 2005-2021 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"
64 struct gomp_task_icv gomp_global_icv = {
65 .nthreads_var = 1,
66 .thread_limit_var = UINT_MAX,
67 .run_sched_var = GFS_DYNAMIC,
68 .run_sched_chunk_size = 1,
69 .default_device_var = 0,
70 .dyn_var = false,
71 .max_active_levels_var = 1,
72 .bind_var = omp_proc_bind_false,
73 .target_data = NULL
76 bool gomp_cancel_var = false;
77 enum gomp_target_offload_t gomp_target_offload_var
78 = GOMP_TARGET_OFFLOAD_DEFAULT;
79 int gomp_max_task_priority_var = 0;
80 #ifndef HAVE_SYNC_BUILTINS
81 gomp_mutex_t gomp_managed_threads_lock;
82 #endif
83 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
84 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
85 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
86 char *gomp_bind_var_list;
87 unsigned long gomp_bind_var_list_len;
88 void **gomp_places_list;
89 unsigned long gomp_places_list_len;
90 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
91 int gomp_debug_var;
92 unsigned int gomp_num_teams_var;
93 bool gomp_display_affinity_var;
94 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
95 size_t gomp_affinity_format_len;
96 char *goacc_device_type;
97 int goacc_device_num;
98 int goacc_default_dims[GOMP_DIM_MAX];
100 #ifndef LIBGOMP_OFFLOADED_ONLY
102 /* Parse the OMP_SCHEDULE environment variable. */
104 static void
105 parse_schedule (void)
107 char *env, *end;
108 unsigned long value;
109 int monotonic = 0;
111 env = getenv ("OMP_SCHEDULE");
112 if (env == NULL)
113 return;
115 while (isspace ((unsigned char) *env))
116 ++env;
117 if (strncasecmp (env, "monotonic", 9) == 0)
119 monotonic = 1;
120 env += 9;
122 else if (strncasecmp (env, "nonmonotonic", 12) == 0)
124 monotonic = -1;
125 env += 12;
127 if (monotonic)
129 while (isspace ((unsigned char) *env))
130 ++env;
131 if (*env != ':')
132 goto unknown;
133 ++env;
134 while (isspace ((unsigned char) *env))
135 ++env;
137 if (strncasecmp (env, "static", 6) == 0)
139 gomp_global_icv.run_sched_var = GFS_STATIC;
140 env += 6;
142 else if (strncasecmp (env, "dynamic", 7) == 0)
144 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
145 env += 7;
147 else if (strncasecmp (env, "guided", 6) == 0)
149 gomp_global_icv.run_sched_var = GFS_GUIDED;
150 env += 6;
152 else if (strncasecmp (env, "auto", 4) == 0)
154 gomp_global_icv.run_sched_var = GFS_AUTO;
155 env += 4;
157 else
158 goto unknown;
160 if (monotonic == 1
161 || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC))
162 gomp_global_icv.run_sched_var |= GFS_MONOTONIC;
164 while (isspace ((unsigned char) *env))
165 ++env;
166 if (*env == '\0')
168 gomp_global_icv.run_sched_chunk_size
169 = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC;
170 return;
172 if (*env++ != ',')
173 goto unknown;
174 while (isspace ((unsigned char) *env))
175 ++env;
176 if (*env == '\0')
177 goto invalid;
179 errno = 0;
180 value = strtoul (env, &end, 10);
181 if (errno)
182 goto invalid;
184 while (isspace ((unsigned char) *end))
185 ++end;
186 if (*end != '\0')
187 goto invalid;
189 if ((int)value != value)
190 goto invalid;
192 if (value == 0
193 && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC)
194 value = 1;
195 gomp_global_icv.run_sched_chunk_size = value;
196 return;
198 unknown:
199 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
200 return;
202 invalid:
203 gomp_error ("Invalid value for chunk size in "
204 "environment variable OMP_SCHEDULE");
205 return;
208 /* Parse an unsigned long environment variable. Return true if one was
209 present and it was successfully parsed. If SECURE, use secure_getenv to the
210 environment variable. */
212 static bool
213 parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
214 bool secure)
216 char *env, *end;
217 unsigned long value;
219 env = (secure ? secure_getenv (name) : getenv (name));
220 if (env == NULL)
221 return false;
223 while (isspace ((unsigned char) *env))
224 ++env;
225 if (*env == '\0')
226 goto invalid;
228 errno = 0;
229 value = strtoul (env, &end, 10);
230 if (errno || (long) value <= 0 - allow_zero)
231 goto invalid;
233 while (isspace ((unsigned char) *end))
234 ++end;
235 if (*end != '\0')
236 goto invalid;
238 *pvalue = value;
239 return true;
241 invalid:
242 gomp_error ("Invalid value for environment variable %s", name);
243 return false;
246 /* As parse_unsigned_long_1, but always use getenv. */
248 static bool
249 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
251 return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
254 /* Parse a positive int environment variable. Return true if one was
255 present and it was successfully parsed. If SECURE, use secure_getenv to the
256 environment variable. */
258 static bool
259 parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
261 unsigned long value;
262 if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
263 return false;
264 if (value > INT_MAX)
266 gomp_error ("Invalid value for environment variable %s", name);
267 return false;
269 *pvalue = (int) value;
270 return true;
273 /* As parse_int_1, but use getenv. */
275 static bool
276 parse_int (const char *name, int *pvalue, bool allow_zero)
278 return parse_int_1 (name, pvalue, allow_zero, false);
281 /* As parse_int_1, but use getenv_secure. */
283 static bool
284 parse_int_secure (const char *name, int *pvalue, bool allow_zero)
286 return parse_int_1 (name, pvalue, allow_zero, true);
289 /* Parse an unsigned long list environment variable. Return true if one was
290 present and it was successfully parsed. */
292 static bool
293 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
294 unsigned long **pvalues,
295 unsigned long *pnvalues)
297 char *env, *end;
298 unsigned long value, *values = NULL;
300 env = getenv (name);
301 if (env == NULL)
302 return false;
304 while (isspace ((unsigned char) *env))
305 ++env;
306 if (*env == '\0')
307 goto invalid;
309 errno = 0;
310 value = strtoul (env, &end, 10);
311 if (errno || (long) value <= 0)
312 goto invalid;
314 while (isspace ((unsigned char) *end))
315 ++end;
316 if (*end != '\0')
318 if (*end == ',')
320 unsigned long nvalues = 0, nalloced = 0;
324 env = end + 1;
325 if (nvalues == nalloced)
327 unsigned long *n;
328 nalloced = nalloced ? nalloced * 2 : 16;
329 n = realloc (values, nalloced * sizeof (unsigned long));
330 if (n == NULL)
332 free (values);
333 gomp_error ("Out of memory while trying to parse"
334 " environment variable %s", name);
335 return false;
337 values = n;
338 if (nvalues == 0)
339 values[nvalues++] = value;
342 while (isspace ((unsigned char) *env))
343 ++env;
344 if (*env == '\0')
345 goto invalid;
347 errno = 0;
348 value = strtoul (env, &end, 10);
349 if (errno || (long) value <= 0)
350 goto invalid;
352 values[nvalues++] = value;
353 while (isspace ((unsigned char) *end))
354 ++end;
355 if (*end == '\0')
356 break;
357 if (*end != ',')
358 goto invalid;
360 while (1);
361 *p1stvalue = values[0];
362 *pvalues = values;
363 *pnvalues = nvalues;
364 return true;
366 goto invalid;
369 *p1stvalue = value;
370 return true;
372 invalid:
373 free (values);
374 gomp_error ("Invalid value for environment variable %s", name);
375 return false;
378 static void
379 parse_target_offload (const char *name, enum gomp_target_offload_t *offload)
381 const char *env;
382 int new_offload = -1;
384 env = getenv (name);
385 if (env == NULL)
386 return;
388 while (isspace ((unsigned char) *env))
389 ++env;
390 if (strncasecmp (env, "default", 7) == 0)
392 env += 7;
393 new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
395 else if (strncasecmp (env, "mandatory", 9) == 0)
397 env += 9;
398 new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
400 else if (strncasecmp (env, "disabled", 8) == 0)
402 env += 8;
403 new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
405 while (isspace ((unsigned char) *env))
406 ++env;
407 if (new_offload != -1 && *env == '\0')
409 *offload = new_offload;
410 return;
413 gomp_error ("Invalid value for environment variable OMP_TARGET_OFFLOAD");
416 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
417 enum values. Return true if one was present and it was successfully
418 parsed. */
420 static bool
421 parse_bind_var (const char *name, char *p1stvalue,
422 char **pvalues, unsigned long *pnvalues)
424 char *env;
425 char value = omp_proc_bind_false, *values = NULL;
426 int i;
427 static struct proc_bind_kinds
429 const char name[7];
430 const char len;
431 omp_proc_bind_t kind;
432 } kinds[] =
434 { "false", 5, omp_proc_bind_false },
435 { "true", 4, omp_proc_bind_true },
436 { "master", 6, omp_proc_bind_master },
437 { "close", 5, omp_proc_bind_close },
438 { "spread", 6, omp_proc_bind_spread }
441 env = getenv (name);
442 if (env == NULL)
443 return false;
445 while (isspace ((unsigned char) *env))
446 ++env;
447 if (*env == '\0')
448 goto invalid;
450 for (i = 0; i < 5; i++)
451 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
453 value = kinds[i].kind;
454 env += kinds[i].len;
455 break;
457 if (i == 5)
458 goto invalid;
460 while (isspace ((unsigned char) *env))
461 ++env;
462 if (*env != '\0')
464 if (*env == ',')
466 unsigned long nvalues = 0, nalloced = 0;
468 if (value == omp_proc_bind_false
469 || value == omp_proc_bind_true)
470 goto invalid;
474 env++;
475 if (nvalues == nalloced)
477 char *n;
478 nalloced = nalloced ? nalloced * 2 : 16;
479 n = realloc (values, nalloced);
480 if (n == NULL)
482 free (values);
483 gomp_error ("Out of memory while trying to parse"
484 " environment variable %s", name);
485 return false;
487 values = n;
488 if (nvalues == 0)
489 values[nvalues++] = value;
492 while (isspace ((unsigned char) *env))
493 ++env;
494 if (*env == '\0')
495 goto invalid;
497 for (i = 2; i < 5; i++)
498 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
500 value = kinds[i].kind;
501 env += kinds[i].len;
502 break;
504 if (i == 5)
505 goto invalid;
507 values[nvalues++] = value;
508 while (isspace ((unsigned char) *env))
509 ++env;
510 if (*env == '\0')
511 break;
512 if (*env != ',')
513 goto invalid;
515 while (1);
516 *p1stvalue = values[0];
517 *pvalues = values;
518 *pnvalues = nvalues;
519 return true;
521 goto invalid;
524 *p1stvalue = value;
525 return true;
527 invalid:
528 free (values);
529 gomp_error ("Invalid value for environment variable %s", name);
530 return false;
533 static bool
534 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
535 long *stridep)
537 char *env = *envp, *start;
538 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
539 unsigned long len = 1;
540 long stride = 1;
541 int pass;
542 bool any_negate = false;
543 *negatep = false;
544 while (isspace ((unsigned char) *env))
545 ++env;
546 if (*env == '!')
548 *negatep = true;
549 ++env;
550 while (isspace ((unsigned char) *env))
551 ++env;
553 if (*env != '{')
554 return false;
555 ++env;
556 while (isspace ((unsigned char) *env))
557 ++env;
558 start = env;
559 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
561 env = start;
564 unsigned long this_num, this_len = 1;
565 long this_stride = 1;
566 bool this_negate = (*env == '!');
567 if (this_negate)
569 if (gomp_places_list)
570 any_negate = true;
571 ++env;
572 while (isspace ((unsigned char) *env))
573 ++env;
576 errno = 0;
577 this_num = strtoul (env, &env, 10);
578 if (errno)
579 return false;
580 while (isspace ((unsigned char) *env))
581 ++env;
582 if (*env == ':')
584 ++env;
585 while (isspace ((unsigned char) *env))
586 ++env;
587 errno = 0;
588 this_len = strtoul (env, &env, 10);
589 if (errno || this_len == 0)
590 return false;
591 while (isspace ((unsigned char) *env))
592 ++env;
593 if (*env == ':')
595 ++env;
596 while (isspace ((unsigned char) *env))
597 ++env;
598 errno = 0;
599 this_stride = strtol (env, &env, 10);
600 if (errno)
601 return false;
602 while (isspace ((unsigned char) *env))
603 ++env;
606 if (this_negate && this_len != 1)
607 return false;
608 if (gomp_places_list && pass == this_negate)
610 if (this_negate)
612 if (!gomp_affinity_remove_cpu (p, this_num))
613 return false;
615 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
616 this_stride, false))
617 return false;
619 if (*env == '}')
620 break;
621 if (*env != ',')
622 return false;
623 ++env;
625 while (1);
628 ++env;
629 while (isspace ((unsigned char) *env))
630 ++env;
631 if (*env == ':')
633 ++env;
634 while (isspace ((unsigned char) *env))
635 ++env;
636 errno = 0;
637 len = strtoul (env, &env, 10);
638 if (errno || len == 0 || len >= 65536)
639 return false;
640 while (isspace ((unsigned char) *env))
641 ++env;
642 if (*env == ':')
644 ++env;
645 while (isspace ((unsigned char) *env))
646 ++env;
647 errno = 0;
648 stride = strtol (env, &env, 10);
649 if (errno)
650 return false;
651 while (isspace ((unsigned char) *env))
652 ++env;
655 if (*negatep && len != 1)
656 return false;
657 *envp = env;
658 *lenp = len;
659 *stridep = stride;
660 return true;
663 static bool
664 parse_places_var (const char *name, bool ignore)
666 char *env = getenv (name), *end;
667 bool any_negate = false;
668 int level = 0;
669 unsigned long count = 0;
670 if (env == NULL)
671 return false;
673 while (isspace ((unsigned char) *env))
674 ++env;
675 if (*env == '\0')
676 goto invalid;
678 if (strncasecmp (env, "threads", 7) == 0)
680 env += 7;
681 level = 1;
683 else if (strncasecmp (env, "cores", 5) == 0)
685 env += 5;
686 level = 2;
688 else if (strncasecmp (env, "sockets", 7) == 0)
690 env += 7;
691 level = 3;
693 if (level)
695 count = ULONG_MAX;
696 while (isspace ((unsigned char) *env))
697 ++env;
698 if (*env != '\0')
700 if (*env++ != '(')
701 goto invalid;
702 while (isspace ((unsigned char) *env))
703 ++env;
705 errno = 0;
706 count = strtoul (env, &end, 10);
707 if (errno)
708 goto invalid;
709 env = end;
710 while (isspace ((unsigned char) *env))
711 ++env;
712 if (*env != ')')
713 goto invalid;
714 ++env;
715 while (isspace ((unsigned char) *env))
716 ++env;
717 if (*env != '\0')
718 goto invalid;
721 if (ignore)
722 return false;
724 return gomp_affinity_init_level (level, count, false);
727 count = 0;
728 end = env;
731 bool negate;
732 unsigned long len;
733 long stride;
734 if (!parse_one_place (&end, &negate, &len, &stride))
735 goto invalid;
736 if (negate)
738 if (!any_negate)
739 count++;
740 any_negate = true;
742 else
743 count += len;
744 if (count > 65536)
745 goto invalid;
746 if (*end == '\0')
747 break;
748 if (*end != ',')
749 goto invalid;
750 end++;
752 while (1);
754 if (ignore)
755 return false;
757 gomp_places_list_len = 0;
758 gomp_places_list = gomp_affinity_alloc (count, false);
759 if (gomp_places_list == NULL)
760 return false;
764 bool negate;
765 unsigned long len;
766 long stride;
767 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
768 if (!parse_one_place (&env, &negate, &len, &stride))
769 goto invalid;
770 if (negate)
772 void *p;
773 for (count = 0; count < gomp_places_list_len; count++)
774 if (gomp_affinity_same_place
775 (gomp_places_list[count],
776 gomp_places_list[gomp_places_list_len]))
777 break;
778 if (count == gomp_places_list_len)
780 gomp_error ("Trying to remove a non-existing place from list "
781 "of places");
782 goto invalid;
784 p = gomp_places_list[count];
785 memmove (&gomp_places_list[count],
786 &gomp_places_list[count + 1],
787 (gomp_places_list_len - count - 1) * sizeof (void *));
788 --gomp_places_list_len;
789 gomp_places_list[gomp_places_list_len] = p;
791 else if (len == 1)
792 ++gomp_places_list_len;
793 else
795 for (count = 0; count < len - 1; count++)
796 if (!gomp_affinity_copy_place
797 (gomp_places_list[gomp_places_list_len + count + 1],
798 gomp_places_list[gomp_places_list_len + count],
799 stride))
800 goto invalid;
801 gomp_places_list_len += len;
803 if (*env == '\0')
804 break;
805 env++;
807 while (1);
809 if (gomp_places_list_len == 0)
811 gomp_error ("All places have been removed");
812 goto invalid;
814 if (!gomp_affinity_finalize_place_list (false))
815 goto invalid;
816 return true;
818 invalid:
819 free (gomp_places_list);
820 gomp_places_list = NULL;
821 gomp_places_list_len = 0;
822 gomp_error ("Invalid value for environment variable %s", name);
823 return false;
826 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
827 present and it was successfully parsed. */
829 static bool
830 parse_stacksize (const char *name, unsigned long *pvalue)
832 char *env, *end;
833 unsigned long value, shift = 10;
835 env = getenv (name);
836 if (env == NULL)
837 return false;
839 while (isspace ((unsigned char) *env))
840 ++env;
841 if (*env == '\0')
842 goto invalid;
844 errno = 0;
845 value = strtoul (env, &end, 10);
846 if (errno)
847 goto invalid;
849 while (isspace ((unsigned char) *end))
850 ++end;
851 if (*end != '\0')
853 switch (tolower ((unsigned char) *end))
855 case 'b':
856 shift = 0;
857 break;
858 case 'k':
859 break;
860 case 'm':
861 shift = 20;
862 break;
863 case 'g':
864 shift = 30;
865 break;
866 default:
867 goto invalid;
869 ++end;
870 while (isspace ((unsigned char) *end))
871 ++end;
872 if (*end != '\0')
873 goto invalid;
876 if (((value << shift) >> shift) != value)
877 goto invalid;
879 *pvalue = value << shift;
880 return true;
882 invalid:
883 gomp_error ("Invalid value for environment variable %s", name);
884 return false;
887 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
888 present and it was successfully parsed. */
890 static bool
891 parse_spincount (const char *name, unsigned long long *pvalue)
893 char *env, *end;
894 unsigned long long value, mult = 1;
896 env = getenv (name);
897 if (env == NULL)
898 return false;
900 while (isspace ((unsigned char) *env))
901 ++env;
902 if (*env == '\0')
903 goto invalid;
905 if (strncasecmp (env, "infinite", 8) == 0
906 || strncasecmp (env, "infinity", 8) == 0)
908 value = ~0ULL;
909 end = env + 8;
910 goto check_tail;
913 errno = 0;
914 value = strtoull (env, &end, 10);
915 if (errno)
916 goto invalid;
918 while (isspace ((unsigned char) *end))
919 ++end;
920 if (*end != '\0')
922 switch (tolower ((unsigned char) *end))
924 case 'k':
925 mult = 1000LL;
926 break;
927 case 'm':
928 mult = 1000LL * 1000LL;
929 break;
930 case 'g':
931 mult = 1000LL * 1000LL * 1000LL;
932 break;
933 case 't':
934 mult = 1000LL * 1000LL * 1000LL * 1000LL;
935 break;
936 default:
937 goto invalid;
939 ++end;
940 check_tail:
941 while (isspace ((unsigned char) *end))
942 ++end;
943 if (*end != '\0')
944 goto invalid;
947 if (value > ~0ULL / mult)
948 value = ~0ULL;
949 else
950 value *= mult;
952 *pvalue = value;
953 return true;
955 invalid:
956 gomp_error ("Invalid value for environment variable %s", name);
957 return false;
960 /* Parse a boolean value for environment variable NAME and store the
961 result in VALUE. Return true if one was present and it was
962 successfully parsed. */
964 static bool
965 parse_boolean (const char *name, bool *value)
967 const char *env;
969 env = getenv (name);
970 if (env == NULL)
971 return false;
973 while (isspace ((unsigned char) *env))
974 ++env;
975 if (strncasecmp (env, "true", 4) == 0)
977 *value = true;
978 env += 4;
980 else if (strncasecmp (env, "false", 5) == 0)
982 *value = false;
983 env += 5;
985 else
986 env = "X";
987 while (isspace ((unsigned char) *env))
988 ++env;
989 if (*env != '\0')
991 gomp_error ("Invalid value for environment variable %s", name);
992 return false;
994 return true;
997 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
999 static int
1000 parse_wait_policy (void)
1002 const char *env;
1003 int ret = -1;
1005 env = getenv ("OMP_WAIT_POLICY");
1006 if (env == NULL)
1007 return -1;
1009 while (isspace ((unsigned char) *env))
1010 ++env;
1011 if (strncasecmp (env, "active", 6) == 0)
1013 ret = 1;
1014 env += 6;
1016 else if (strncasecmp (env, "passive", 7) == 0)
1018 ret = 0;
1019 env += 7;
1021 else
1022 env = "X";
1023 while (isspace ((unsigned char) *env))
1024 ++env;
1025 if (*env == '\0')
1026 return ret;
1027 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
1028 return -1;
1031 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1032 present and it was successfully parsed. */
1034 static bool
1035 parse_affinity (bool ignore)
1037 char *env, *end, *start;
1038 int pass;
1039 unsigned long cpu_beg, cpu_end, cpu_stride;
1040 size_t count = 0, needed;
1042 env = getenv ("GOMP_CPU_AFFINITY");
1043 if (env == NULL)
1044 return false;
1046 start = env;
1047 for (pass = 0; pass < 2; pass++)
1049 env = start;
1050 if (pass == 1)
1052 if (ignore)
1053 return false;
1055 gomp_places_list_len = 0;
1056 gomp_places_list = gomp_affinity_alloc (count, true);
1057 if (gomp_places_list == NULL)
1058 return false;
1062 while (isspace ((unsigned char) *env))
1063 ++env;
1065 errno = 0;
1066 cpu_beg = strtoul (env, &end, 0);
1067 if (errno || cpu_beg >= 65536)
1068 goto invalid;
1069 cpu_end = cpu_beg;
1070 cpu_stride = 1;
1072 env = end;
1073 if (*env == '-')
1075 errno = 0;
1076 cpu_end = strtoul (++env, &end, 0);
1077 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
1078 goto invalid;
1080 env = end;
1081 if (*env == ':')
1083 errno = 0;
1084 cpu_stride = strtoul (++env, &end, 0);
1085 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1086 goto invalid;
1088 env = end;
1092 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1093 if (pass == 0)
1094 count += needed;
1095 else
1097 while (needed--)
1099 void *p = gomp_places_list[gomp_places_list_len];
1100 gomp_affinity_init_place (p);
1101 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1102 ++gomp_places_list_len;
1103 cpu_beg += cpu_stride;
1107 while (isspace ((unsigned char) *env))
1108 ++env;
1110 if (*env == ',')
1111 env++;
1112 else if (*env == '\0')
1113 break;
1115 while (1);
1118 if (gomp_places_list_len == 0)
1120 free (gomp_places_list);
1121 gomp_places_list = NULL;
1122 return false;
1124 return true;
1126 invalid:
1127 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1128 return false;
1131 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1133 static uintptr_t
1134 parse_allocator (void)
1136 const char *env;
1137 uintptr_t ret = omp_default_mem_alloc;
1139 env = getenv ("OMP_ALLOCATOR");
1140 if (env == NULL)
1141 return ret;
1143 while (isspace ((unsigned char) *env))
1144 ++env;
1145 if (0)
1147 #define C(v) \
1148 else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
1150 ret = v; \
1151 env += sizeof (#v) - 1; \
1153 C (omp_default_mem_alloc)
1154 C (omp_large_cap_mem_alloc)
1155 C (omp_const_mem_alloc)
1156 C (omp_high_bw_mem_alloc)
1157 C (omp_low_lat_mem_alloc)
1158 C (omp_cgroup_mem_alloc)
1159 C (omp_pteam_mem_alloc)
1160 C (omp_thread_mem_alloc)
1161 #undef C
1162 else
1163 env = "X";
1164 while (isspace ((unsigned char) *env))
1165 ++env;
1166 if (*env == '\0')
1167 return ret;
1168 gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
1169 return omp_default_mem_alloc;
1172 static void
1173 parse_acc_device_type (void)
1175 const char *env = getenv ("ACC_DEVICE_TYPE");
1177 if (env && *env != '\0')
1178 goacc_device_type = strdup (env);
1179 else
1180 goacc_device_type = NULL;
1183 static void
1184 parse_gomp_openacc_dim (void)
1186 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1187 const char *var_name = "GOMP_OPENACC_DIM";
1188 const char *env_var = getenv (var_name);
1189 if (!env_var)
1190 return;
1192 const char *pos = env_var;
1193 int i;
1194 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1196 if (i && *pos++ != ':')
1197 break;
1199 if (*pos == ':')
1200 continue;
1202 const char *eptr;
1203 errno = 0;
1204 long val = strtol (pos, (char **)&eptr, 10);
1205 if (errno || val < 0 || (unsigned)val != val)
1206 break;
1208 goacc_default_dims[i] = (int)val;
1209 pos = eptr;
1213 static void
1214 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1216 const char *env;
1217 bool display = false;
1218 bool verbose = false;
1219 int i;
1221 env = getenv ("OMP_DISPLAY_ENV");
1222 if (env == NULL)
1223 return;
1225 while (isspace ((unsigned char) *env))
1226 ++env;
1227 if (strncasecmp (env, "true", 4) == 0)
1229 display = true;
1230 env += 4;
1232 else if (strncasecmp (env, "false", 5) == 0)
1234 display = false;
1235 env += 5;
1237 else if (strncasecmp (env, "verbose", 7) == 0)
1239 display = true;
1240 verbose = true;
1241 env += 7;
1243 else
1244 env = "X";
1245 while (isspace ((unsigned char) *env))
1246 ++env;
1247 if (*env != '\0')
1248 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1250 if (!display)
1251 return;
1253 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1255 fputs (" _OPENMP = '201511'\n", stderr);
1256 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1257 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1258 fprintf (stderr, " OMP_NESTED = '%s'\n",
1259 gomp_global_icv.max_active_levels_var > 1 ? "TRUE" : "FALSE");
1261 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1262 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1263 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1264 fputs ("'\n", stderr);
1266 fprintf (stderr, " OMP_SCHEDULE = '");
1267 if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
1269 if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1270 fputs ("MONOTONIC:", stderr);
1272 else if (gomp_global_icv.run_sched_var == GFS_STATIC)
1273 fputs ("NONMONOTONIC:", stderr);
1274 switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
1276 case GFS_RUNTIME:
1277 fputs ("RUNTIME", stderr);
1278 if (gomp_global_icv.run_sched_chunk_size != 1)
1279 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1280 break;
1281 case GFS_STATIC:
1282 fputs ("STATIC", stderr);
1283 if (gomp_global_icv.run_sched_chunk_size != 0)
1284 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1285 break;
1286 case GFS_DYNAMIC:
1287 fputs ("DYNAMIC", stderr);
1288 if (gomp_global_icv.run_sched_chunk_size != 1)
1289 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1290 break;
1291 case GFS_GUIDED:
1292 fputs ("GUIDED", stderr);
1293 if (gomp_global_icv.run_sched_chunk_size != 1)
1294 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1295 break;
1296 case GFS_AUTO:
1297 fputs ("AUTO", stderr);
1298 break;
1300 fputs ("'\n", stderr);
1302 fputs (" OMP_PROC_BIND = '", stderr);
1303 switch (gomp_global_icv.bind_var)
1305 case omp_proc_bind_false:
1306 fputs ("FALSE", stderr);
1307 break;
1308 case omp_proc_bind_true:
1309 fputs ("TRUE", stderr);
1310 break;
1311 case omp_proc_bind_master:
1312 fputs ("MASTER", stderr);
1313 break;
1314 case omp_proc_bind_close:
1315 fputs ("CLOSE", stderr);
1316 break;
1317 case omp_proc_bind_spread:
1318 fputs ("SPREAD", stderr);
1319 break;
1321 for (i = 1; i < gomp_bind_var_list_len; i++)
1322 switch (gomp_bind_var_list[i])
1324 case omp_proc_bind_master:
1325 fputs (",MASTER", stderr);
1326 break;
1327 case omp_proc_bind_close:
1328 fputs (",CLOSE", stderr);
1329 break;
1330 case omp_proc_bind_spread:
1331 fputs (",SPREAD", stderr);
1332 break;
1334 fputs ("'\n", stderr);
1335 fputs (" OMP_PLACES = '", stderr);
1336 for (i = 0; i < gomp_places_list_len; i++)
1338 fputs ("{", stderr);
1339 gomp_affinity_print_place (gomp_places_list[i]);
1340 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1342 fputs ("'\n", stderr);
1344 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1346 /* GOMP's default value is actually neither active nor passive. */
1347 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1348 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1349 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1350 gomp_global_icv.thread_limit_var);
1351 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1352 gomp_global_icv.max_active_levels_var);
1354 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1355 gomp_cancel_var ? "TRUE" : "FALSE");
1356 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1357 gomp_global_icv.default_device_var);
1358 fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1359 gomp_max_task_priority_var);
1360 fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n",
1361 gomp_display_affinity_var ? "TRUE" : "FALSE");
1362 fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
1363 gomp_affinity_format_var);
1364 fprintf (stderr, " OMP_ALLOCATOR = '");
1365 switch (gomp_def_allocator)
1367 #define C(v) case v: fputs (#v, stderr); break;
1368 C (omp_default_mem_alloc)
1369 C (omp_large_cap_mem_alloc)
1370 C (omp_const_mem_alloc)
1371 C (omp_high_bw_mem_alloc)
1372 C (omp_low_lat_mem_alloc)
1373 C (omp_cgroup_mem_alloc)
1374 C (omp_pteam_mem_alloc)
1375 C (omp_thread_mem_alloc)
1376 #undef C
1377 default: break;
1379 fputs ("'\n", stderr);
1381 fputs (" OMP_TARGET_OFFLOAD = '", stderr);
1382 switch (gomp_target_offload_var)
1384 case GOMP_TARGET_OFFLOAD_DEFAULT:
1385 fputs ("DEFAULT", stderr);
1386 break;
1387 case GOMP_TARGET_OFFLOAD_MANDATORY:
1388 fputs ("MANDATORY", stderr);
1389 break;
1390 case GOMP_TARGET_OFFLOAD_DISABLED:
1391 fputs ("DISABLED", stderr);
1392 break;
1394 fputs ("'\n", stderr);
1396 if (verbose)
1398 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1399 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1400 #ifdef HAVE_INTTYPES_H
1401 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1402 (uint64_t) gomp_spin_count_var);
1403 #else
1404 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1405 (unsigned long) gomp_spin_count_var);
1406 #endif
1409 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1413 static void __attribute__((constructor))
1414 initialize_env (void)
1416 unsigned long thread_limit_var, stacksize = GOMP_DEFAULT_STACKSIZE;
1417 unsigned long max_active_levels_var;
1418 int wait_policy;
1420 /* Do a compile time check that mkomp_h.pl did good job. */
1421 omp_check_defines ();
1423 parse_schedule ();
1424 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1425 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1426 parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var);
1427 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1428 parse_target_offload ("OMP_TARGET_OFFLOAD", &gomp_target_offload_var);
1429 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
1430 gomp_def_allocator = parse_allocator ();
1431 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1433 gomp_global_icv.thread_limit_var
1434 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1436 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
1437 #ifndef HAVE_SYNC_BUILTINS
1438 gomp_mutex_init (&gomp_managed_threads_lock);
1439 #endif
1440 gomp_init_num_threads ();
1441 gomp_available_cpus = gomp_global_icv.nthreads_var;
1442 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1443 &gomp_global_icv.nthreads_var,
1444 &gomp_nthreads_var_list,
1445 &gomp_nthreads_var_list_len))
1446 gomp_global_icv.nthreads_var = gomp_available_cpus;
1447 bool ignore = false;
1448 if (parse_bind_var ("OMP_PROC_BIND",
1449 &gomp_global_icv.bind_var,
1450 &gomp_bind_var_list,
1451 &gomp_bind_var_list_len)
1452 && gomp_global_icv.bind_var == omp_proc_bind_false)
1453 ignore = true;
1454 if (parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS",
1455 &max_active_levels_var, true))
1456 gomp_global_icv.max_active_levels_var
1457 = (max_active_levels_var > gomp_supported_active_levels)
1458 ? gomp_supported_active_levels : max_active_levels_var;
1459 else
1461 bool nested = true;
1463 /* OMP_NESTED is deprecated in OpenMP 5.0. */
1464 if (parse_boolean ("OMP_NESTED", &nested))
1465 gomp_global_icv.max_active_levels_var
1466 = nested ? gomp_supported_active_levels : 1;
1467 else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
1468 gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
1470 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1471 parsed if present in the environment. If OMP_PROC_BIND was set
1472 explicitly to false, don't populate places list though. If places
1473 list was successfully set from OMP_PLACES, only parse but don't process
1474 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1475 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1476 was successfully parsed into a places list, otherwise to
1477 OMP_PROC_BIND=false. */
1478 if (parse_places_var ("OMP_PLACES", ignore))
1480 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1481 gomp_global_icv.bind_var = true;
1482 ignore = true;
1484 if (parse_affinity (ignore))
1486 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1487 gomp_global_icv.bind_var = true;
1488 ignore = true;
1490 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1491 gomp_init_affinity ();
1494 const char *env = getenv ("OMP_AFFINITY_FORMAT");
1495 if (env != NULL)
1496 gomp_set_affinity_format (env, strlen (env));
1499 wait_policy = parse_wait_policy ();
1500 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1502 /* Using a rough estimation of 100000 spins per msec,
1503 use 5 min blocking for OMP_WAIT_POLICY=active,
1504 3 msec blocking when OMP_WAIT_POLICY is not specificed
1505 and 0 when OMP_WAIT_POLICY=passive.
1506 Depending on the CPU speed, this can be e.g. 5 times longer
1507 or 5 times shorter. */
1508 if (wait_policy > 0)
1509 gomp_spin_count_var = 30000000000LL;
1510 else if (wait_policy < 0)
1511 gomp_spin_count_var = 300000LL;
1513 /* gomp_throttled_spin_count_var is used when there are more libgomp
1514 managed threads than available CPUs. Use very short spinning. */
1515 if (wait_policy > 0)
1516 gomp_throttled_spin_count_var = 1000LL;
1517 else if (wait_policy < 0)
1518 gomp_throttled_spin_count_var = 100LL;
1519 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1520 gomp_throttled_spin_count_var = gomp_spin_count_var;
1522 /* Not strictly environment related, but ordering constructors is tricky. */
1523 pthread_attr_init (&gomp_thread_attr);
1525 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1526 || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
1527 || GOMP_DEFAULT_STACKSIZE)
1529 int err;
1531 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1533 #ifdef PTHREAD_STACK_MIN
1534 if (err == EINVAL)
1536 if (stacksize < PTHREAD_STACK_MIN)
1537 gomp_error ("Stack size less than minimum of %luk",
1538 PTHREAD_STACK_MIN / 1024ul
1539 + (PTHREAD_STACK_MIN % 1024 != 0));
1540 else
1541 gomp_error ("Stack size larger than system limit");
1543 else
1544 #endif
1545 if (err != 0)
1546 gomp_error ("Stack size change failed: %s", strerror (err));
1549 handle_omp_display_env (stacksize, wait_policy);
1551 /* OpenACC. */
1553 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1554 goacc_device_num = 0;
1556 parse_acc_device_type ();
1557 parse_gomp_openacc_dim ();
1559 goacc_runtime_initialize ();
1561 goacc_profiling_initialize ();
1563 #endif /* LIBGOMP_OFFLOADED_ONLY */