testsuite: Properly quote dejagnu negative line numbers
[official-gcc.git] / libgomp / env.c
blobc0c4730d47c7d0b8320206bb62a60bc1f8043f2d
1 /* Copyright (C) 2005-2020 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 .nest_var = false,
72 .bind_var = omp_proc_bind_false,
73 .target_data = NULL
76 unsigned long gomp_max_active_levels_var = INT_MAX;
77 bool gomp_cancel_var = false;
78 int gomp_max_task_priority_var = 0;
79 #ifndef HAVE_SYNC_BUILTINS
80 gomp_mutex_t gomp_managed_threads_lock;
81 #endif
82 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
83 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
84 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
85 char *gomp_bind_var_list;
86 unsigned long gomp_bind_var_list_len;
87 void **gomp_places_list;
88 unsigned long gomp_places_list_len;
89 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
90 int gomp_debug_var;
91 unsigned int gomp_num_teams_var;
92 bool gomp_display_affinity_var;
93 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
94 size_t gomp_affinity_format_len;
95 char *goacc_device_type;
96 int goacc_device_num;
97 int goacc_default_dims[GOMP_DIM_MAX];
99 #ifndef LIBGOMP_OFFLOADED_ONLY
101 /* Parse the OMP_SCHEDULE environment variable. */
103 static void
104 parse_schedule (void)
106 char *env, *end;
107 unsigned long value;
108 int monotonic = 0;
110 env = getenv ("OMP_SCHEDULE");
111 if (env == NULL)
112 return;
114 while (isspace ((unsigned char) *env))
115 ++env;
116 if (strncasecmp (env, "monotonic", 9) == 0)
118 monotonic = 1;
119 env += 9;
121 else if (strncasecmp (env, "nonmonotonic", 12) == 0)
123 monotonic = -1;
124 env += 12;
126 if (monotonic)
128 while (isspace ((unsigned char) *env))
129 ++env;
130 if (*env != ':')
131 goto unknown;
132 ++env;
133 while (isspace ((unsigned char) *env))
134 ++env;
136 if (strncasecmp (env, "static", 6) == 0)
138 gomp_global_icv.run_sched_var = GFS_STATIC;
139 env += 6;
141 else if (strncasecmp (env, "dynamic", 7) == 0)
143 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
144 env += 7;
146 else if (strncasecmp (env, "guided", 6) == 0)
148 gomp_global_icv.run_sched_var = GFS_GUIDED;
149 env += 6;
151 else if (strncasecmp (env, "auto", 4) == 0)
153 gomp_global_icv.run_sched_var = GFS_AUTO;
154 env += 4;
156 else
157 goto unknown;
159 if (monotonic == 1
160 || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC))
161 gomp_global_icv.run_sched_var |= GFS_MONOTONIC;
163 while (isspace ((unsigned char) *env))
164 ++env;
165 if (*env == '\0')
167 gomp_global_icv.run_sched_chunk_size
168 = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC;
169 return;
171 if (*env++ != ',')
172 goto unknown;
173 while (isspace ((unsigned char) *env))
174 ++env;
175 if (*env == '\0')
176 goto invalid;
178 errno = 0;
179 value = strtoul (env, &end, 10);
180 if (errno)
181 goto invalid;
183 while (isspace ((unsigned char) *end))
184 ++end;
185 if (*end != '\0')
186 goto invalid;
188 if ((int)value != value)
189 goto invalid;
191 if (value == 0
192 && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC)
193 value = 1;
194 gomp_global_icv.run_sched_chunk_size = value;
195 return;
197 unknown:
198 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
199 return;
201 invalid:
202 gomp_error ("Invalid value for chunk size in "
203 "environment variable OMP_SCHEDULE");
204 return;
207 /* Parse an unsigned long environment variable. Return true if one was
208 present and it was successfully parsed. If SECURE, use secure_getenv to the
209 environment variable. */
211 static bool
212 parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
213 bool secure)
215 char *env, *end;
216 unsigned long value;
218 env = (secure ? secure_getenv (name) : getenv (name));
219 if (env == NULL)
220 return false;
222 while (isspace ((unsigned char) *env))
223 ++env;
224 if (*env == '\0')
225 goto invalid;
227 errno = 0;
228 value = strtoul (env, &end, 10);
229 if (errno || (long) value <= 0 - allow_zero)
230 goto invalid;
232 while (isspace ((unsigned char) *end))
233 ++end;
234 if (*end != '\0')
235 goto invalid;
237 *pvalue = value;
238 return true;
240 invalid:
241 gomp_error ("Invalid value for environment variable %s", name);
242 return false;
245 /* As parse_unsigned_long_1, but always use getenv. */
247 static bool
248 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
250 return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
253 /* Parse a positive int environment variable. Return true if one was
254 present and it was successfully parsed. If SECURE, use secure_getenv to the
255 environment variable. */
257 static bool
258 parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
260 unsigned long value;
261 if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
262 return false;
263 if (value > INT_MAX)
265 gomp_error ("Invalid value for environment variable %s", name);
266 return false;
268 *pvalue = (int) value;
269 return true;
272 /* As parse_int_1, but use getenv. */
274 static bool
275 parse_int (const char *name, int *pvalue, bool allow_zero)
277 return parse_int_1 (name, pvalue, allow_zero, false);
280 /* As parse_int_1, but use getenv_secure. */
282 static bool
283 parse_int_secure (const char *name, int *pvalue, bool allow_zero)
285 return parse_int_1 (name, pvalue, allow_zero, true);
288 /* Parse an unsigned long list environment variable. Return true if one was
289 present and it was successfully parsed. */
291 static bool
292 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
293 unsigned long **pvalues,
294 unsigned long *pnvalues)
296 char *env, *end;
297 unsigned long value, *values = NULL;
299 env = getenv (name);
300 if (env == NULL)
301 return false;
303 while (isspace ((unsigned char) *env))
304 ++env;
305 if (*env == '\0')
306 goto invalid;
308 errno = 0;
309 value = strtoul (env, &end, 10);
310 if (errno || (long) value <= 0)
311 goto invalid;
313 while (isspace ((unsigned char) *end))
314 ++end;
315 if (*end != '\0')
317 if (*end == ',')
319 unsigned long nvalues = 0, nalloced = 0;
323 env = end + 1;
324 if (nvalues == nalloced)
326 unsigned long *n;
327 nalloced = nalloced ? nalloced * 2 : 16;
328 n = realloc (values, nalloced * sizeof (unsigned long));
329 if (n == NULL)
331 free (values);
332 gomp_error ("Out of memory while trying to parse"
333 " environment variable %s", name);
334 return false;
336 values = n;
337 if (nvalues == 0)
338 values[nvalues++] = value;
341 while (isspace ((unsigned char) *env))
342 ++env;
343 if (*env == '\0')
344 goto invalid;
346 errno = 0;
347 value = strtoul (env, &end, 10);
348 if (errno || (long) value <= 0)
349 goto invalid;
351 values[nvalues++] = value;
352 while (isspace ((unsigned char) *end))
353 ++end;
354 if (*end == '\0')
355 break;
356 if (*end != ',')
357 goto invalid;
359 while (1);
360 *p1stvalue = values[0];
361 *pvalues = values;
362 *pnvalues = nvalues;
363 return true;
365 goto invalid;
368 *p1stvalue = value;
369 return true;
371 invalid:
372 free (values);
373 gomp_error ("Invalid value for environment variable %s", name);
374 return false;
377 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
378 enum values. Return true if one was present and it was successfully
379 parsed. */
381 static bool
382 parse_bind_var (const char *name, char *p1stvalue,
383 char **pvalues, unsigned long *pnvalues)
385 char *env;
386 char value = omp_proc_bind_false, *values = NULL;
387 int i;
388 static struct proc_bind_kinds
390 const char name[7];
391 const char len;
392 omp_proc_bind_t kind;
393 } kinds[] =
395 { "false", 5, omp_proc_bind_false },
396 { "true", 4, omp_proc_bind_true },
397 { "master", 6, omp_proc_bind_master },
398 { "close", 5, omp_proc_bind_close },
399 { "spread", 6, omp_proc_bind_spread }
402 env = getenv (name);
403 if (env == NULL)
404 return false;
406 while (isspace ((unsigned char) *env))
407 ++env;
408 if (*env == '\0')
409 goto invalid;
411 for (i = 0; i < 5; i++)
412 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
414 value = kinds[i].kind;
415 env += kinds[i].len;
416 break;
418 if (i == 5)
419 goto invalid;
421 while (isspace ((unsigned char) *env))
422 ++env;
423 if (*env != '\0')
425 if (*env == ',')
427 unsigned long nvalues = 0, nalloced = 0;
429 if (value == omp_proc_bind_false
430 || value == omp_proc_bind_true)
431 goto invalid;
435 env++;
436 if (nvalues == nalloced)
438 char *n;
439 nalloced = nalloced ? nalloced * 2 : 16;
440 n = realloc (values, nalloced);
441 if (n == NULL)
443 free (values);
444 gomp_error ("Out of memory while trying to parse"
445 " environment variable %s", name);
446 return false;
448 values = n;
449 if (nvalues == 0)
450 values[nvalues++] = value;
453 while (isspace ((unsigned char) *env))
454 ++env;
455 if (*env == '\0')
456 goto invalid;
458 for (i = 2; i < 5; i++)
459 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
461 value = kinds[i].kind;
462 env += kinds[i].len;
463 break;
465 if (i == 5)
466 goto invalid;
468 values[nvalues++] = value;
469 while (isspace ((unsigned char) *env))
470 ++env;
471 if (*env == '\0')
472 break;
473 if (*env != ',')
474 goto invalid;
476 while (1);
477 *p1stvalue = values[0];
478 *pvalues = values;
479 *pnvalues = nvalues;
480 return true;
482 goto invalid;
485 *p1stvalue = value;
486 return true;
488 invalid:
489 free (values);
490 gomp_error ("Invalid value for environment variable %s", name);
491 return false;
494 static bool
495 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
496 long *stridep)
498 char *env = *envp, *start;
499 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
500 unsigned long len = 1;
501 long stride = 1;
502 int pass;
503 bool any_negate = false;
504 *negatep = false;
505 while (isspace ((unsigned char) *env))
506 ++env;
507 if (*env == '!')
509 *negatep = true;
510 ++env;
511 while (isspace ((unsigned char) *env))
512 ++env;
514 if (*env != '{')
515 return false;
516 ++env;
517 while (isspace ((unsigned char) *env))
518 ++env;
519 start = env;
520 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
522 env = start;
525 unsigned long this_num, this_len = 1;
526 long this_stride = 1;
527 bool this_negate = (*env == '!');
528 if (this_negate)
530 if (gomp_places_list)
531 any_negate = true;
532 ++env;
533 while (isspace ((unsigned char) *env))
534 ++env;
537 errno = 0;
538 this_num = strtoul (env, &env, 10);
539 if (errno)
540 return false;
541 while (isspace ((unsigned char) *env))
542 ++env;
543 if (*env == ':')
545 ++env;
546 while (isspace ((unsigned char) *env))
547 ++env;
548 errno = 0;
549 this_len = strtoul (env, &env, 10);
550 if (errno || this_len == 0)
551 return false;
552 while (isspace ((unsigned char) *env))
553 ++env;
554 if (*env == ':')
556 ++env;
557 while (isspace ((unsigned char) *env))
558 ++env;
559 errno = 0;
560 this_stride = strtol (env, &env, 10);
561 if (errno)
562 return false;
563 while (isspace ((unsigned char) *env))
564 ++env;
567 if (this_negate && this_len != 1)
568 return false;
569 if (gomp_places_list && pass == this_negate)
571 if (this_negate)
573 if (!gomp_affinity_remove_cpu (p, this_num))
574 return false;
576 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
577 this_stride, false))
578 return false;
580 if (*env == '}')
581 break;
582 if (*env != ',')
583 return false;
584 ++env;
586 while (1);
589 ++env;
590 while (isspace ((unsigned char) *env))
591 ++env;
592 if (*env == ':')
594 ++env;
595 while (isspace ((unsigned char) *env))
596 ++env;
597 errno = 0;
598 len = strtoul (env, &env, 10);
599 if (errno || len == 0 || len >= 65536)
600 return false;
601 while (isspace ((unsigned char) *env))
602 ++env;
603 if (*env == ':')
605 ++env;
606 while (isspace ((unsigned char) *env))
607 ++env;
608 errno = 0;
609 stride = strtol (env, &env, 10);
610 if (errno)
611 return false;
612 while (isspace ((unsigned char) *env))
613 ++env;
616 if (*negatep && len != 1)
617 return false;
618 *envp = env;
619 *lenp = len;
620 *stridep = stride;
621 return true;
624 static bool
625 parse_places_var (const char *name, bool ignore)
627 char *env = getenv (name), *end;
628 bool any_negate = false;
629 int level = 0;
630 unsigned long count = 0;
631 if (env == NULL)
632 return false;
634 while (isspace ((unsigned char) *env))
635 ++env;
636 if (*env == '\0')
637 goto invalid;
639 if (strncasecmp (env, "threads", 7) == 0)
641 env += 7;
642 level = 1;
644 else if (strncasecmp (env, "cores", 5) == 0)
646 env += 5;
647 level = 2;
649 else if (strncasecmp (env, "sockets", 7) == 0)
651 env += 7;
652 level = 3;
654 if (level)
656 count = ULONG_MAX;
657 while (isspace ((unsigned char) *env))
658 ++env;
659 if (*env != '\0')
661 if (*env++ != '(')
662 goto invalid;
663 while (isspace ((unsigned char) *env))
664 ++env;
666 errno = 0;
667 count = strtoul (env, &end, 10);
668 if (errno)
669 goto invalid;
670 env = end;
671 while (isspace ((unsigned char) *env))
672 ++env;
673 if (*env != ')')
674 goto invalid;
675 ++env;
676 while (isspace ((unsigned char) *env))
677 ++env;
678 if (*env != '\0')
679 goto invalid;
682 if (ignore)
683 return false;
685 return gomp_affinity_init_level (level, count, false);
688 count = 0;
689 end = env;
692 bool negate;
693 unsigned long len;
694 long stride;
695 if (!parse_one_place (&end, &negate, &len, &stride))
696 goto invalid;
697 if (negate)
699 if (!any_negate)
700 count++;
701 any_negate = true;
703 else
704 count += len;
705 if (count > 65536)
706 goto invalid;
707 if (*end == '\0')
708 break;
709 if (*end != ',')
710 goto invalid;
711 end++;
713 while (1);
715 if (ignore)
716 return false;
718 gomp_places_list_len = 0;
719 gomp_places_list = gomp_affinity_alloc (count, false);
720 if (gomp_places_list == NULL)
721 return false;
725 bool negate;
726 unsigned long len;
727 long stride;
728 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
729 if (!parse_one_place (&env, &negate, &len, &stride))
730 goto invalid;
731 if (negate)
733 void *p;
734 for (count = 0; count < gomp_places_list_len; count++)
735 if (gomp_affinity_same_place
736 (gomp_places_list[count],
737 gomp_places_list[gomp_places_list_len]))
738 break;
739 if (count == gomp_places_list_len)
741 gomp_error ("Trying to remove a non-existing place from list "
742 "of places");
743 goto invalid;
745 p = gomp_places_list[count];
746 memmove (&gomp_places_list[count],
747 &gomp_places_list[count + 1],
748 (gomp_places_list_len - count - 1) * sizeof (void *));
749 --gomp_places_list_len;
750 gomp_places_list[gomp_places_list_len] = p;
752 else if (len == 1)
753 ++gomp_places_list_len;
754 else
756 for (count = 0; count < len - 1; count++)
757 if (!gomp_affinity_copy_place
758 (gomp_places_list[gomp_places_list_len + count + 1],
759 gomp_places_list[gomp_places_list_len + count],
760 stride))
761 goto invalid;
762 gomp_places_list_len += len;
764 if (*env == '\0')
765 break;
766 env++;
768 while (1);
770 if (gomp_places_list_len == 0)
772 gomp_error ("All places have been removed");
773 goto invalid;
775 if (!gomp_affinity_finalize_place_list (false))
776 goto invalid;
777 return true;
779 invalid:
780 free (gomp_places_list);
781 gomp_places_list = NULL;
782 gomp_places_list_len = 0;
783 gomp_error ("Invalid value for environment variable %s", name);
784 return false;
787 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
788 present and it was successfully parsed. */
790 static bool
791 parse_stacksize (const char *name, unsigned long *pvalue)
793 char *env, *end;
794 unsigned long value, shift = 10;
796 env = getenv (name);
797 if (env == NULL)
798 return false;
800 while (isspace ((unsigned char) *env))
801 ++env;
802 if (*env == '\0')
803 goto invalid;
805 errno = 0;
806 value = strtoul (env, &end, 10);
807 if (errno)
808 goto invalid;
810 while (isspace ((unsigned char) *end))
811 ++end;
812 if (*end != '\0')
814 switch (tolower ((unsigned char) *end))
816 case 'b':
817 shift = 0;
818 break;
819 case 'k':
820 break;
821 case 'm':
822 shift = 20;
823 break;
824 case 'g':
825 shift = 30;
826 break;
827 default:
828 goto invalid;
830 ++end;
831 while (isspace ((unsigned char) *end))
832 ++end;
833 if (*end != '\0')
834 goto invalid;
837 if (((value << shift) >> shift) != value)
838 goto invalid;
840 *pvalue = value << shift;
841 return true;
843 invalid:
844 gomp_error ("Invalid value for environment variable %s", name);
845 return false;
848 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
849 present and it was successfully parsed. */
851 static bool
852 parse_spincount (const char *name, unsigned long long *pvalue)
854 char *env, *end;
855 unsigned long long value, mult = 1;
857 env = getenv (name);
858 if (env == NULL)
859 return false;
861 while (isspace ((unsigned char) *env))
862 ++env;
863 if (*env == '\0')
864 goto invalid;
866 if (strncasecmp (env, "infinite", 8) == 0
867 || strncasecmp (env, "infinity", 8) == 0)
869 value = ~0ULL;
870 end = env + 8;
871 goto check_tail;
874 errno = 0;
875 value = strtoull (env, &end, 10);
876 if (errno)
877 goto invalid;
879 while (isspace ((unsigned char) *end))
880 ++end;
881 if (*end != '\0')
883 switch (tolower ((unsigned char) *end))
885 case 'k':
886 mult = 1000LL;
887 break;
888 case 'm':
889 mult = 1000LL * 1000LL;
890 break;
891 case 'g':
892 mult = 1000LL * 1000LL * 1000LL;
893 break;
894 case 't':
895 mult = 1000LL * 1000LL * 1000LL * 1000LL;
896 break;
897 default:
898 goto invalid;
900 ++end;
901 check_tail:
902 while (isspace ((unsigned char) *end))
903 ++end;
904 if (*end != '\0')
905 goto invalid;
908 if (value > ~0ULL / mult)
909 value = ~0ULL;
910 else
911 value *= mult;
913 *pvalue = value;
914 return true;
916 invalid:
917 gomp_error ("Invalid value for environment variable %s", name);
918 return false;
921 /* Parse a boolean value for environment variable NAME and store the
922 result in VALUE. */
924 static void
925 parse_boolean (const char *name, bool *value)
927 const char *env;
929 env = getenv (name);
930 if (env == NULL)
931 return;
933 while (isspace ((unsigned char) *env))
934 ++env;
935 if (strncasecmp (env, "true", 4) == 0)
937 *value = true;
938 env += 4;
940 else if (strncasecmp (env, "false", 5) == 0)
942 *value = false;
943 env += 5;
945 else
946 env = "X";
947 while (isspace ((unsigned char) *env))
948 ++env;
949 if (*env != '\0')
950 gomp_error ("Invalid value for environment variable %s", name);
953 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
955 static int
956 parse_wait_policy (void)
958 const char *env;
959 int ret = -1;
961 env = getenv ("OMP_WAIT_POLICY");
962 if (env == NULL)
963 return -1;
965 while (isspace ((unsigned char) *env))
966 ++env;
967 if (strncasecmp (env, "active", 6) == 0)
969 ret = 1;
970 env += 6;
972 else if (strncasecmp (env, "passive", 7) == 0)
974 ret = 0;
975 env += 7;
977 else
978 env = "X";
979 while (isspace ((unsigned char) *env))
980 ++env;
981 if (*env == '\0')
982 return ret;
983 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
984 return -1;
987 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
988 present and it was successfully parsed. */
990 static bool
991 parse_affinity (bool ignore)
993 char *env, *end, *start;
994 int pass;
995 unsigned long cpu_beg, cpu_end, cpu_stride;
996 size_t count = 0, needed;
998 env = getenv ("GOMP_CPU_AFFINITY");
999 if (env == NULL)
1000 return false;
1002 start = env;
1003 for (pass = 0; pass < 2; pass++)
1005 env = start;
1006 if (pass == 1)
1008 if (ignore)
1009 return false;
1011 gomp_places_list_len = 0;
1012 gomp_places_list = gomp_affinity_alloc (count, true);
1013 if (gomp_places_list == NULL)
1014 return false;
1018 while (isspace ((unsigned char) *env))
1019 ++env;
1021 errno = 0;
1022 cpu_beg = strtoul (env, &end, 0);
1023 if (errno || cpu_beg >= 65536)
1024 goto invalid;
1025 cpu_end = cpu_beg;
1026 cpu_stride = 1;
1028 env = end;
1029 if (*env == '-')
1031 errno = 0;
1032 cpu_end = strtoul (++env, &end, 0);
1033 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
1034 goto invalid;
1036 env = end;
1037 if (*env == ':')
1039 errno = 0;
1040 cpu_stride = strtoul (++env, &end, 0);
1041 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1042 goto invalid;
1044 env = end;
1048 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1049 if (pass == 0)
1050 count += needed;
1051 else
1053 while (needed--)
1055 void *p = gomp_places_list[gomp_places_list_len];
1056 gomp_affinity_init_place (p);
1057 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1058 ++gomp_places_list_len;
1059 cpu_beg += cpu_stride;
1063 while (isspace ((unsigned char) *env))
1064 ++env;
1066 if (*env == ',')
1067 env++;
1068 else if (*env == '\0')
1069 break;
1071 while (1);
1074 if (gomp_places_list_len == 0)
1076 free (gomp_places_list);
1077 gomp_places_list = NULL;
1078 return false;
1080 return true;
1082 invalid:
1083 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1084 return false;
1087 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1089 static uintptr_t
1090 parse_allocator (void)
1092 const char *env;
1093 uintptr_t ret = omp_default_mem_alloc;
1095 env = getenv ("OMP_ALLOCATOR");
1096 if (env == NULL)
1097 return ret;
1099 while (isspace ((unsigned char) *env))
1100 ++env;
1101 if (0)
1103 #define C(v) \
1104 else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
1106 ret = v; \
1107 env += sizeof (#v) - 1; \
1109 C (omp_default_mem_alloc)
1110 C (omp_large_cap_mem_alloc)
1111 C (omp_const_mem_alloc)
1112 C (omp_high_bw_mem_alloc)
1113 C (omp_low_lat_mem_alloc)
1114 C (omp_cgroup_mem_alloc)
1115 C (omp_pteam_mem_alloc)
1116 C (omp_thread_mem_alloc)
1117 #undef C
1118 else
1119 env = "X";
1120 while (isspace ((unsigned char) *env))
1121 ++env;
1122 if (*env == '\0')
1123 return ret;
1124 gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
1125 return omp_default_mem_alloc;
1128 static void
1129 parse_acc_device_type (void)
1131 const char *env = getenv ("ACC_DEVICE_TYPE");
1133 if (env && *env != '\0')
1134 goacc_device_type = strdup (env);
1135 else
1136 goacc_device_type = NULL;
1139 static void
1140 parse_gomp_openacc_dim (void)
1142 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1143 const char *var_name = "GOMP_OPENACC_DIM";
1144 const char *env_var = getenv (var_name);
1145 if (!env_var)
1146 return;
1148 const char *pos = env_var;
1149 int i;
1150 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1152 if (i && *pos++ != ':')
1153 break;
1155 if (*pos == ':')
1156 continue;
1158 const char *eptr;
1159 errno = 0;
1160 long val = strtol (pos, (char **)&eptr, 10);
1161 if (errno || val < 0 || (unsigned)val != val)
1162 break;
1164 goacc_default_dims[i] = (int)val;
1165 pos = eptr;
1169 static void
1170 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1172 const char *env;
1173 bool display = false;
1174 bool verbose = false;
1175 int i;
1177 env = getenv ("OMP_DISPLAY_ENV");
1178 if (env == NULL)
1179 return;
1181 while (isspace ((unsigned char) *env))
1182 ++env;
1183 if (strncasecmp (env, "true", 4) == 0)
1185 display = true;
1186 env += 4;
1188 else if (strncasecmp (env, "false", 5) == 0)
1190 display = false;
1191 env += 5;
1193 else if (strncasecmp (env, "verbose", 7) == 0)
1195 display = true;
1196 verbose = true;
1197 env += 7;
1199 else
1200 env = "X";
1201 while (isspace ((unsigned char) *env))
1202 ++env;
1203 if (*env != '\0')
1204 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1206 if (!display)
1207 return;
1209 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1211 fputs (" _OPENMP = '201511'\n", stderr);
1212 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1213 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1214 fprintf (stderr, " OMP_NESTED = '%s'\n",
1215 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1217 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1218 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1219 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1220 fputs ("'\n", stderr);
1222 fprintf (stderr, " OMP_SCHEDULE = '");
1223 if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
1225 if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1226 fputs ("MONOTONIC:", stderr);
1228 else if (gomp_global_icv.run_sched_var == GFS_STATIC)
1229 fputs ("NONMONOTONIC:", stderr);
1230 switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
1232 case GFS_RUNTIME:
1233 fputs ("RUNTIME", stderr);
1234 if (gomp_global_icv.run_sched_chunk_size != 1)
1235 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1236 break;
1237 case GFS_STATIC:
1238 fputs ("STATIC", stderr);
1239 if (gomp_global_icv.run_sched_chunk_size != 0)
1240 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1241 break;
1242 case GFS_DYNAMIC:
1243 fputs ("DYNAMIC", stderr);
1244 if (gomp_global_icv.run_sched_chunk_size != 1)
1245 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1246 break;
1247 case GFS_GUIDED:
1248 fputs ("GUIDED", stderr);
1249 if (gomp_global_icv.run_sched_chunk_size != 1)
1250 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1251 break;
1252 case GFS_AUTO:
1253 fputs ("AUTO", stderr);
1254 break;
1256 fputs ("'\n", stderr);
1258 fputs (" OMP_PROC_BIND = '", stderr);
1259 switch (gomp_global_icv.bind_var)
1261 case omp_proc_bind_false:
1262 fputs ("FALSE", stderr);
1263 break;
1264 case omp_proc_bind_true:
1265 fputs ("TRUE", stderr);
1266 break;
1267 case omp_proc_bind_master:
1268 fputs ("MASTER", stderr);
1269 break;
1270 case omp_proc_bind_close:
1271 fputs ("CLOSE", stderr);
1272 break;
1273 case omp_proc_bind_spread:
1274 fputs ("SPREAD", stderr);
1275 break;
1277 for (i = 1; i < gomp_bind_var_list_len; i++)
1278 switch (gomp_bind_var_list[i])
1280 case omp_proc_bind_master:
1281 fputs (",MASTER", stderr);
1282 break;
1283 case omp_proc_bind_close:
1284 fputs (",CLOSE", stderr);
1285 break;
1286 case omp_proc_bind_spread:
1287 fputs (",SPREAD", stderr);
1288 break;
1290 fputs ("'\n", stderr);
1291 fputs (" OMP_PLACES = '", stderr);
1292 for (i = 0; i < gomp_places_list_len; i++)
1294 fputs ("{", stderr);
1295 gomp_affinity_print_place (gomp_places_list[i]);
1296 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1298 fputs ("'\n", stderr);
1300 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1302 /* GOMP's default value is actually neither active nor passive. */
1303 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1304 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1305 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1306 gomp_global_icv.thread_limit_var);
1307 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1308 gomp_max_active_levels_var);
1310 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1311 gomp_cancel_var ? "TRUE" : "FALSE");
1312 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1313 gomp_global_icv.default_device_var);
1314 fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1315 gomp_max_task_priority_var);
1316 fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n",
1317 gomp_display_affinity_var ? "TRUE" : "FALSE");
1318 fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
1319 gomp_affinity_format_var);
1320 fprintf (stderr, " OMP_ALLOCATOR = '");
1321 switch (gomp_def_allocator)
1323 #define C(v) case v: fputs (#v, stderr); break;
1324 C (omp_default_mem_alloc)
1325 C (omp_large_cap_mem_alloc)
1326 C (omp_const_mem_alloc)
1327 C (omp_high_bw_mem_alloc)
1328 C (omp_low_lat_mem_alloc)
1329 C (omp_cgroup_mem_alloc)
1330 C (omp_pteam_mem_alloc)
1331 C (omp_thread_mem_alloc)
1332 #undef C
1333 default: break;
1335 fputs ("'\n", stderr);
1337 if (verbose)
1339 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1340 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1341 #ifdef HAVE_INTTYPES_H
1342 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1343 (uint64_t) gomp_spin_count_var);
1344 #else
1345 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1346 (unsigned long) gomp_spin_count_var);
1347 #endif
1350 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1354 static void __attribute__((constructor))
1355 initialize_env (void)
1357 unsigned long thread_limit_var, stacksize = GOMP_DEFAULT_STACKSIZE;
1358 int wait_policy;
1360 /* Do a compile time check that mkomp_h.pl did good job. */
1361 omp_check_defines ();
1363 parse_schedule ();
1364 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1365 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1366 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1367 parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var);
1368 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1369 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
1370 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1371 true);
1372 gomp_def_allocator = parse_allocator ();
1373 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1375 gomp_global_icv.thread_limit_var
1376 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1378 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
1379 #ifndef HAVE_SYNC_BUILTINS
1380 gomp_mutex_init (&gomp_managed_threads_lock);
1381 #endif
1382 gomp_init_num_threads ();
1383 gomp_available_cpus = gomp_global_icv.nthreads_var;
1384 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1385 &gomp_global_icv.nthreads_var,
1386 &gomp_nthreads_var_list,
1387 &gomp_nthreads_var_list_len))
1388 gomp_global_icv.nthreads_var = gomp_available_cpus;
1389 bool ignore = false;
1390 if (parse_bind_var ("OMP_PROC_BIND",
1391 &gomp_global_icv.bind_var,
1392 &gomp_bind_var_list,
1393 &gomp_bind_var_list_len)
1394 && gomp_global_icv.bind_var == omp_proc_bind_false)
1395 ignore = true;
1396 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1397 parsed if present in the environment. If OMP_PROC_BIND was set
1398 explicitly to false, don't populate places list though. If places
1399 list was successfully set from OMP_PLACES, only parse but don't process
1400 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1401 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1402 was successfully parsed into a places list, otherwise to
1403 OMP_PROC_BIND=false. */
1404 if (parse_places_var ("OMP_PLACES", ignore))
1406 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1407 gomp_global_icv.bind_var = true;
1408 ignore = true;
1410 if (parse_affinity (ignore))
1412 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1413 gomp_global_icv.bind_var = true;
1414 ignore = true;
1416 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1417 gomp_init_affinity ();
1420 const char *env = getenv ("OMP_AFFINITY_FORMAT");
1421 if (env != NULL)
1422 gomp_set_affinity_format (env, strlen (env));
1425 wait_policy = parse_wait_policy ();
1426 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1428 /* Using a rough estimation of 100000 spins per msec,
1429 use 5 min blocking for OMP_WAIT_POLICY=active,
1430 3 msec blocking when OMP_WAIT_POLICY is not specificed
1431 and 0 when OMP_WAIT_POLICY=passive.
1432 Depending on the CPU speed, this can be e.g. 5 times longer
1433 or 5 times shorter. */
1434 if (wait_policy > 0)
1435 gomp_spin_count_var = 30000000000LL;
1436 else if (wait_policy < 0)
1437 gomp_spin_count_var = 300000LL;
1439 /* gomp_throttled_spin_count_var is used when there are more libgomp
1440 managed threads than available CPUs. Use very short spinning. */
1441 if (wait_policy > 0)
1442 gomp_throttled_spin_count_var = 1000LL;
1443 else if (wait_policy < 0)
1444 gomp_throttled_spin_count_var = 100LL;
1445 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1446 gomp_throttled_spin_count_var = gomp_spin_count_var;
1448 /* Not strictly environment related, but ordering constructors is tricky. */
1449 pthread_attr_init (&gomp_thread_attr);
1451 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1452 || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
1453 || GOMP_DEFAULT_STACKSIZE)
1455 int err;
1457 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1459 #ifdef PTHREAD_STACK_MIN
1460 if (err == EINVAL)
1462 if (stacksize < PTHREAD_STACK_MIN)
1463 gomp_error ("Stack size less than minimum of %luk",
1464 PTHREAD_STACK_MIN / 1024ul
1465 + (PTHREAD_STACK_MIN % 1024 != 0));
1466 else
1467 gomp_error ("Stack size larger than system limit");
1469 else
1470 #endif
1471 if (err != 0)
1472 gomp_error ("Stack size change failed: %s", strerror (err));
1475 handle_omp_display_env (stacksize, wait_policy);
1477 /* OpenACC. */
1479 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1480 goacc_device_num = 0;
1482 parse_acc_device_type ();
1483 parse_gomp_openacc_dim ();
1485 goacc_runtime_initialize ();
1487 goacc_profiling_initialize ();
1489 #endif /* LIBGOMP_OFFLOADED_ONLY */