PR libstdc++/86292 fix exception safety of std::vector<InputIterator> constructor
[official-gcc.git] / libgomp / env.c
blob18c90bb09d096ae2207a6efe413e4fdcd55f8985
1 /* Copyright (C) 2005-2018 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 int gomp_debug_var;
90 unsigned int gomp_num_teams_var;
91 char *goacc_device_type;
92 int goacc_device_num;
93 int goacc_default_dims[GOMP_DIM_MAX];
95 #ifndef LIBGOMP_OFFLOADED_ONLY
97 /* Parse the OMP_SCHEDULE environment variable. */
99 static void
100 parse_schedule (void)
102 char *env, *end;
103 unsigned long value;
105 env = getenv ("OMP_SCHEDULE");
106 if (env == NULL)
107 return;
109 while (isspace ((unsigned char) *env))
110 ++env;
111 if (strncasecmp (env, "static", 6) == 0)
113 gomp_global_icv.run_sched_var = GFS_STATIC;
114 env += 6;
116 else if (strncasecmp (env, "dynamic", 7) == 0)
118 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
119 env += 7;
121 else if (strncasecmp (env, "guided", 6) == 0)
123 gomp_global_icv.run_sched_var = GFS_GUIDED;
124 env += 6;
126 else if (strncasecmp (env, "auto", 4) == 0)
128 gomp_global_icv.run_sched_var = GFS_AUTO;
129 env += 4;
131 else
132 goto unknown;
134 while (isspace ((unsigned char) *env))
135 ++env;
136 if (*env == '\0')
138 gomp_global_icv.run_sched_chunk_size
139 = gomp_global_icv.run_sched_var != GFS_STATIC;
140 return;
142 if (*env++ != ',')
143 goto unknown;
144 while (isspace ((unsigned char) *env))
145 ++env;
146 if (*env == '\0')
147 goto invalid;
149 errno = 0;
150 value = strtoul (env, &end, 10);
151 if (errno)
152 goto invalid;
154 while (isspace ((unsigned char) *end))
155 ++end;
156 if (*end != '\0')
157 goto invalid;
159 if ((int)value != value)
160 goto invalid;
162 if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
163 value = 1;
164 gomp_global_icv.run_sched_chunk_size = value;
165 return;
167 unknown:
168 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
169 return;
171 invalid:
172 gomp_error ("Invalid value for chunk size in "
173 "environment variable OMP_SCHEDULE");
174 return;
177 /* Parse an unsigned long environment variable. Return true if one was
178 present and it was successfully parsed. If SECURE, use secure_getenv to the
179 environment variable. */
181 static bool
182 parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
183 bool secure)
185 char *env, *end;
186 unsigned long value;
188 env = (secure ? secure_getenv (name) : getenv (name));
189 if (env == NULL)
190 return false;
192 while (isspace ((unsigned char) *env))
193 ++env;
194 if (*env == '\0')
195 goto invalid;
197 errno = 0;
198 value = strtoul (env, &end, 10);
199 if (errno || (long) value <= 0 - allow_zero)
200 goto invalid;
202 while (isspace ((unsigned char) *end))
203 ++end;
204 if (*end != '\0')
205 goto invalid;
207 *pvalue = value;
208 return true;
210 invalid:
211 gomp_error ("Invalid value for environment variable %s", name);
212 return false;
215 /* As parse_unsigned_long_1, but always use getenv. */
217 static bool
218 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
220 return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
223 /* Parse a positive int environment variable. Return true if one was
224 present and it was successfully parsed. If SECURE, use secure_getenv to the
225 environment variable. */
227 static bool
228 parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
230 unsigned long value;
231 if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
232 return false;
233 if (value > INT_MAX)
235 gomp_error ("Invalid value for environment variable %s", name);
236 return false;
238 *pvalue = (int) value;
239 return true;
242 /* As parse_int_1, but use getenv. */
244 static bool
245 parse_int (const char *name, int *pvalue, bool allow_zero)
247 return parse_int_1 (name, pvalue, allow_zero, false);
250 /* As parse_int_1, but use getenv_secure. */
252 static bool
253 parse_int_secure (const char *name, int *pvalue, bool allow_zero)
255 return parse_int_1 (name, pvalue, allow_zero, true);
258 /* Parse an unsigned long list environment variable. Return true if one was
259 present and it was successfully parsed. */
261 static bool
262 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
263 unsigned long **pvalues,
264 unsigned long *pnvalues)
266 char *env, *end;
267 unsigned long value, *values = NULL;
269 env = getenv (name);
270 if (env == NULL)
271 return false;
273 while (isspace ((unsigned char) *env))
274 ++env;
275 if (*env == '\0')
276 goto invalid;
278 errno = 0;
279 value = strtoul (env, &end, 10);
280 if (errno || (long) value <= 0)
281 goto invalid;
283 while (isspace ((unsigned char) *end))
284 ++end;
285 if (*end != '\0')
287 if (*end == ',')
289 unsigned long nvalues = 0, nalloced = 0;
293 env = end + 1;
294 if (nvalues == nalloced)
296 unsigned long *n;
297 nalloced = nalloced ? nalloced * 2 : 16;
298 n = realloc (values, nalloced * sizeof (unsigned long));
299 if (n == NULL)
301 free (values);
302 gomp_error ("Out of memory while trying to parse"
303 " environment variable %s", name);
304 return false;
306 values = n;
307 if (nvalues == 0)
308 values[nvalues++] = value;
311 while (isspace ((unsigned char) *env))
312 ++env;
313 if (*env == '\0')
314 goto invalid;
316 errno = 0;
317 value = strtoul (env, &end, 10);
318 if (errno || (long) value <= 0)
319 goto invalid;
321 values[nvalues++] = value;
322 while (isspace ((unsigned char) *end))
323 ++end;
324 if (*end == '\0')
325 break;
326 if (*end != ',')
327 goto invalid;
329 while (1);
330 *p1stvalue = values[0];
331 *pvalues = values;
332 *pnvalues = nvalues;
333 return true;
335 goto invalid;
338 *p1stvalue = value;
339 return true;
341 invalid:
342 free (values);
343 gomp_error ("Invalid value for environment variable %s", name);
344 return false;
347 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
348 enum values. Return true if one was present and it was successfully
349 parsed. */
351 static bool
352 parse_bind_var (const char *name, char *p1stvalue,
353 char **pvalues, unsigned long *pnvalues)
355 char *env;
356 char value = omp_proc_bind_false, *values = NULL;
357 int i;
358 static struct proc_bind_kinds
360 const char name[7];
361 const char len;
362 omp_proc_bind_t kind;
363 } kinds[] =
365 { "false", 5, omp_proc_bind_false },
366 { "true", 4, omp_proc_bind_true },
367 { "master", 6, omp_proc_bind_master },
368 { "close", 5, omp_proc_bind_close },
369 { "spread", 6, omp_proc_bind_spread }
372 env = getenv (name);
373 if (env == NULL)
374 return false;
376 while (isspace ((unsigned char) *env))
377 ++env;
378 if (*env == '\0')
379 goto invalid;
381 for (i = 0; i < 5; i++)
382 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
384 value = kinds[i].kind;
385 env += kinds[i].len;
386 break;
388 if (i == 5)
389 goto invalid;
391 while (isspace ((unsigned char) *env))
392 ++env;
393 if (*env != '\0')
395 if (*env == ',')
397 unsigned long nvalues = 0, nalloced = 0;
399 if (value == omp_proc_bind_false
400 || value == omp_proc_bind_true)
401 goto invalid;
405 env++;
406 if (nvalues == nalloced)
408 char *n;
409 nalloced = nalloced ? nalloced * 2 : 16;
410 n = realloc (values, nalloced);
411 if (n == NULL)
413 free (values);
414 gomp_error ("Out of memory while trying to parse"
415 " environment variable %s", name);
416 return false;
418 values = n;
419 if (nvalues == 0)
420 values[nvalues++] = value;
423 while (isspace ((unsigned char) *env))
424 ++env;
425 if (*env == '\0')
426 goto invalid;
428 for (i = 2; i < 5; i++)
429 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
431 value = kinds[i].kind;
432 env += kinds[i].len;
433 break;
435 if (i == 5)
436 goto invalid;
438 values[nvalues++] = value;
439 while (isspace ((unsigned char) *env))
440 ++env;
441 if (*env == '\0')
442 break;
443 if (*env != ',')
444 goto invalid;
446 while (1);
447 *p1stvalue = values[0];
448 *pvalues = values;
449 *pnvalues = nvalues;
450 return true;
452 goto invalid;
455 *p1stvalue = value;
456 return true;
458 invalid:
459 free (values);
460 gomp_error ("Invalid value for environment variable %s", name);
461 return false;
464 static bool
465 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
466 long *stridep)
468 char *env = *envp, *start;
469 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
470 unsigned long len = 1;
471 long stride = 1;
472 int pass;
473 bool any_negate = false;
474 *negatep = false;
475 while (isspace ((unsigned char) *env))
476 ++env;
477 if (*env == '!')
479 *negatep = true;
480 ++env;
481 while (isspace ((unsigned char) *env))
482 ++env;
484 if (*env != '{')
485 return false;
486 ++env;
487 while (isspace ((unsigned char) *env))
488 ++env;
489 start = env;
490 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
492 env = start;
495 unsigned long this_num, this_len = 1;
496 long this_stride = 1;
497 bool this_negate = (*env == '!');
498 if (this_negate)
500 if (gomp_places_list)
501 any_negate = true;
502 ++env;
503 while (isspace ((unsigned char) *env))
504 ++env;
507 errno = 0;
508 this_num = strtoul (env, &env, 10);
509 if (errno)
510 return false;
511 while (isspace ((unsigned char) *env))
512 ++env;
513 if (*env == ':')
515 ++env;
516 while (isspace ((unsigned char) *env))
517 ++env;
518 errno = 0;
519 this_len = strtoul (env, &env, 10);
520 if (errno || this_len == 0)
521 return false;
522 while (isspace ((unsigned char) *env))
523 ++env;
524 if (*env == ':')
526 ++env;
527 while (isspace ((unsigned char) *env))
528 ++env;
529 errno = 0;
530 this_stride = strtol (env, &env, 10);
531 if (errno)
532 return false;
533 while (isspace ((unsigned char) *env))
534 ++env;
537 if (this_negate && this_len != 1)
538 return false;
539 if (gomp_places_list && pass == this_negate)
541 if (this_negate)
543 if (!gomp_affinity_remove_cpu (p, this_num))
544 return false;
546 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
547 this_stride, false))
548 return false;
550 if (*env == '}')
551 break;
552 if (*env != ',')
553 return false;
554 ++env;
556 while (1);
559 ++env;
560 while (isspace ((unsigned char) *env))
561 ++env;
562 if (*env == ':')
564 ++env;
565 while (isspace ((unsigned char) *env))
566 ++env;
567 errno = 0;
568 len = strtoul (env, &env, 10);
569 if (errno || len == 0 || len >= 65536)
570 return false;
571 while (isspace ((unsigned char) *env))
572 ++env;
573 if (*env == ':')
575 ++env;
576 while (isspace ((unsigned char) *env))
577 ++env;
578 errno = 0;
579 stride = strtol (env, &env, 10);
580 if (errno)
581 return false;
582 while (isspace ((unsigned char) *env))
583 ++env;
586 if (*negatep && len != 1)
587 return false;
588 *envp = env;
589 *lenp = len;
590 *stridep = stride;
591 return true;
594 static bool
595 parse_places_var (const char *name, bool ignore)
597 char *env = getenv (name), *end;
598 bool any_negate = false;
599 int level = 0;
600 unsigned long count = 0;
601 if (env == NULL)
602 return false;
604 while (isspace ((unsigned char) *env))
605 ++env;
606 if (*env == '\0')
607 goto invalid;
609 if (strncasecmp (env, "threads", 7) == 0)
611 env += 7;
612 level = 1;
614 else if (strncasecmp (env, "cores", 5) == 0)
616 env += 5;
617 level = 2;
619 else if (strncasecmp (env, "sockets", 7) == 0)
621 env += 7;
622 level = 3;
624 if (level)
626 count = ULONG_MAX;
627 while (isspace ((unsigned char) *env))
628 ++env;
629 if (*env != '\0')
631 if (*env++ != '(')
632 goto invalid;
633 while (isspace ((unsigned char) *env))
634 ++env;
636 errno = 0;
637 count = strtoul (env, &end, 10);
638 if (errno)
639 goto invalid;
640 env = end;
641 while (isspace ((unsigned char) *env))
642 ++env;
643 if (*env != ')')
644 goto invalid;
645 ++env;
646 while (isspace ((unsigned char) *env))
647 ++env;
648 if (*env != '\0')
649 goto invalid;
652 if (ignore)
653 return false;
655 return gomp_affinity_init_level (level, count, false);
658 count = 0;
659 end = env;
662 bool negate;
663 unsigned long len;
664 long stride;
665 if (!parse_one_place (&end, &negate, &len, &stride))
666 goto invalid;
667 if (negate)
669 if (!any_negate)
670 count++;
671 any_negate = true;
673 else
674 count += len;
675 if (count > 65536)
676 goto invalid;
677 if (*end == '\0')
678 break;
679 if (*end != ',')
680 goto invalid;
681 end++;
683 while (1);
685 if (ignore)
686 return false;
688 gomp_places_list_len = 0;
689 gomp_places_list = gomp_affinity_alloc (count, false);
690 if (gomp_places_list == NULL)
691 return false;
695 bool negate;
696 unsigned long len;
697 long stride;
698 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
699 if (!parse_one_place (&env, &negate, &len, &stride))
700 goto invalid;
701 if (negate)
703 void *p;
704 for (count = 0; count < gomp_places_list_len; count++)
705 if (gomp_affinity_same_place
706 (gomp_places_list[count],
707 gomp_places_list[gomp_places_list_len]))
708 break;
709 if (count == gomp_places_list_len)
711 gomp_error ("Trying to remove a non-existing place from list "
712 "of places");
713 goto invalid;
715 p = gomp_places_list[count];
716 memmove (&gomp_places_list[count],
717 &gomp_places_list[count + 1],
718 (gomp_places_list_len - count - 1) * sizeof (void *));
719 --gomp_places_list_len;
720 gomp_places_list[gomp_places_list_len] = p;
722 else if (len == 1)
723 ++gomp_places_list_len;
724 else
726 for (count = 0; count < len - 1; count++)
727 if (!gomp_affinity_copy_place
728 (gomp_places_list[gomp_places_list_len + count + 1],
729 gomp_places_list[gomp_places_list_len + count],
730 stride))
731 goto invalid;
732 gomp_places_list_len += len;
734 if (*env == '\0')
735 break;
736 env++;
738 while (1);
740 if (gomp_places_list_len == 0)
742 gomp_error ("All places have been removed");
743 goto invalid;
745 if (!gomp_affinity_finalize_place_list (false))
746 goto invalid;
747 return true;
749 invalid:
750 free (gomp_places_list);
751 gomp_places_list = NULL;
752 gomp_places_list_len = 0;
753 gomp_error ("Invalid value for environment variable %s", name);
754 return false;
757 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
758 present and it was successfully parsed. */
760 static bool
761 parse_stacksize (const char *name, unsigned long *pvalue)
763 char *env, *end;
764 unsigned long value, shift = 10;
766 env = getenv (name);
767 if (env == NULL)
768 return false;
770 while (isspace ((unsigned char) *env))
771 ++env;
772 if (*env == '\0')
773 goto invalid;
775 errno = 0;
776 value = strtoul (env, &end, 10);
777 if (errno)
778 goto invalid;
780 while (isspace ((unsigned char) *end))
781 ++end;
782 if (*end != '\0')
784 switch (tolower ((unsigned char) *end))
786 case 'b':
787 shift = 0;
788 break;
789 case 'k':
790 break;
791 case 'm':
792 shift = 20;
793 break;
794 case 'g':
795 shift = 30;
796 break;
797 default:
798 goto invalid;
800 ++end;
801 while (isspace ((unsigned char) *end))
802 ++end;
803 if (*end != '\0')
804 goto invalid;
807 if (((value << shift) >> shift) != value)
808 goto invalid;
810 *pvalue = value << shift;
811 return true;
813 invalid:
814 gomp_error ("Invalid value for environment variable %s", name);
815 return false;
818 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
819 present and it was successfully parsed. */
821 static bool
822 parse_spincount (const char *name, unsigned long long *pvalue)
824 char *env, *end;
825 unsigned long long value, mult = 1;
827 env = getenv (name);
828 if (env == NULL)
829 return false;
831 while (isspace ((unsigned char) *env))
832 ++env;
833 if (*env == '\0')
834 goto invalid;
836 if (strncasecmp (env, "infinite", 8) == 0
837 || strncasecmp (env, "infinity", 8) == 0)
839 value = ~0ULL;
840 end = env + 8;
841 goto check_tail;
844 errno = 0;
845 value = strtoull (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 'k':
856 mult = 1000LL;
857 break;
858 case 'm':
859 mult = 1000LL * 1000LL;
860 break;
861 case 'g':
862 mult = 1000LL * 1000LL * 1000LL;
863 break;
864 case 't':
865 mult = 1000LL * 1000LL * 1000LL * 1000LL;
866 break;
867 default:
868 goto invalid;
870 ++end;
871 check_tail:
872 while (isspace ((unsigned char) *end))
873 ++end;
874 if (*end != '\0')
875 goto invalid;
878 if (value > ~0ULL / mult)
879 value = ~0ULL;
880 else
881 value *= mult;
883 *pvalue = value;
884 return true;
886 invalid:
887 gomp_error ("Invalid value for environment variable %s", name);
888 return false;
891 /* Parse a boolean value for environment variable NAME and store the
892 result in VALUE. */
894 static void
895 parse_boolean (const char *name, bool *value)
897 const char *env;
899 env = getenv (name);
900 if (env == NULL)
901 return;
903 while (isspace ((unsigned char) *env))
904 ++env;
905 if (strncasecmp (env, "true", 4) == 0)
907 *value = true;
908 env += 4;
910 else if (strncasecmp (env, "false", 5) == 0)
912 *value = false;
913 env += 5;
915 else
916 env = "X";
917 while (isspace ((unsigned char) *env))
918 ++env;
919 if (*env != '\0')
920 gomp_error ("Invalid value for environment variable %s", name);
923 /* Parse the OMP_WAIT_POLICY environment variable and store the
924 result in gomp_active_wait_policy. */
926 static int
927 parse_wait_policy (void)
929 const char *env;
930 int ret = -1;
932 env = getenv ("OMP_WAIT_POLICY");
933 if (env == NULL)
934 return -1;
936 while (isspace ((unsigned char) *env))
937 ++env;
938 if (strncasecmp (env, "active", 6) == 0)
940 ret = 1;
941 env += 6;
943 else if (strncasecmp (env, "passive", 7) == 0)
945 ret = 0;
946 env += 7;
948 else
949 env = "X";
950 while (isspace ((unsigned char) *env))
951 ++env;
952 if (*env == '\0')
953 return ret;
954 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
955 return -1;
958 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
959 present and it was successfully parsed. */
961 static bool
962 parse_affinity (bool ignore)
964 char *env, *end, *start;
965 int pass;
966 unsigned long cpu_beg, cpu_end, cpu_stride;
967 size_t count = 0, needed;
969 env = getenv ("GOMP_CPU_AFFINITY");
970 if (env == NULL)
971 return false;
973 start = env;
974 for (pass = 0; pass < 2; pass++)
976 env = start;
977 if (pass == 1)
979 if (ignore)
980 return false;
982 gomp_places_list_len = 0;
983 gomp_places_list = gomp_affinity_alloc (count, true);
984 if (gomp_places_list == NULL)
985 return false;
989 while (isspace ((unsigned char) *env))
990 ++env;
992 errno = 0;
993 cpu_beg = strtoul (env, &end, 0);
994 if (errno || cpu_beg >= 65536)
995 goto invalid;
996 cpu_end = cpu_beg;
997 cpu_stride = 1;
999 env = end;
1000 if (*env == '-')
1002 errno = 0;
1003 cpu_end = strtoul (++env, &end, 0);
1004 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
1005 goto invalid;
1007 env = end;
1008 if (*env == ':')
1010 errno = 0;
1011 cpu_stride = strtoul (++env, &end, 0);
1012 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1013 goto invalid;
1015 env = end;
1019 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1020 if (pass == 0)
1021 count += needed;
1022 else
1024 while (needed--)
1026 void *p = gomp_places_list[gomp_places_list_len];
1027 gomp_affinity_init_place (p);
1028 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1029 ++gomp_places_list_len;
1030 cpu_beg += cpu_stride;
1034 while (isspace ((unsigned char) *env))
1035 ++env;
1037 if (*env == ',')
1038 env++;
1039 else if (*env == '\0')
1040 break;
1042 while (1);
1045 if (gomp_places_list_len == 0)
1047 free (gomp_places_list);
1048 gomp_places_list = NULL;
1049 return false;
1051 return true;
1053 invalid:
1054 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1055 return false;
1058 static void
1059 parse_acc_device_type (void)
1061 const char *env = getenv ("ACC_DEVICE_TYPE");
1063 if (env && *env != '\0')
1064 goacc_device_type = strdup (env);
1065 else
1066 goacc_device_type = NULL;
1069 static void
1070 parse_gomp_openacc_dim (void)
1072 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1073 const char *var_name = "GOMP_OPENACC_DIM";
1074 const char *env_var = getenv (var_name);
1075 if (!env_var)
1076 return;
1078 const char *pos = env_var;
1079 int i;
1080 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1082 if (i && *pos++ != ':')
1083 break;
1085 if (*pos == ':')
1086 continue;
1088 const char *eptr;
1089 errno = 0;
1090 long val = strtol (pos, (char **)&eptr, 10);
1091 if (errno || val < 0 || (unsigned)val != val)
1092 break;
1094 goacc_default_dims[i] = (int)val;
1095 pos = eptr;
1099 static void
1100 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1102 const char *env;
1103 bool display = false;
1104 bool verbose = false;
1105 int i;
1107 env = getenv ("OMP_DISPLAY_ENV");
1108 if (env == NULL)
1109 return;
1111 while (isspace ((unsigned char) *env))
1112 ++env;
1113 if (strncasecmp (env, "true", 4) == 0)
1115 display = true;
1116 env += 4;
1118 else if (strncasecmp (env, "false", 5) == 0)
1120 display = false;
1121 env += 5;
1123 else if (strncasecmp (env, "verbose", 7) == 0)
1125 display = true;
1126 verbose = true;
1127 env += 7;
1129 else
1130 env = "X";
1131 while (isspace ((unsigned char) *env))
1132 ++env;
1133 if (*env != '\0')
1134 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1136 if (!display)
1137 return;
1139 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1141 fputs (" _OPENMP = '201511'\n", stderr);
1142 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1143 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1144 fprintf (stderr, " OMP_NESTED = '%s'\n",
1145 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1147 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1148 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1149 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1150 fputs ("'\n", stderr);
1152 fprintf (stderr, " OMP_SCHEDULE = '");
1153 switch (gomp_global_icv.run_sched_var)
1155 case GFS_RUNTIME:
1156 fputs ("RUNTIME", stderr);
1157 break;
1158 case GFS_STATIC:
1159 fputs ("STATIC", stderr);
1160 break;
1161 case GFS_DYNAMIC:
1162 fputs ("DYNAMIC", stderr);
1163 break;
1164 case GFS_GUIDED:
1165 fputs ("GUIDED", stderr);
1166 break;
1167 case GFS_AUTO:
1168 fputs ("AUTO", stderr);
1169 break;
1171 fputs ("'\n", stderr);
1173 fputs (" OMP_PROC_BIND = '", stderr);
1174 switch (gomp_global_icv.bind_var)
1176 case omp_proc_bind_false:
1177 fputs ("FALSE", stderr);
1178 break;
1179 case omp_proc_bind_true:
1180 fputs ("TRUE", stderr);
1181 break;
1182 case omp_proc_bind_master:
1183 fputs ("MASTER", stderr);
1184 break;
1185 case omp_proc_bind_close:
1186 fputs ("CLOSE", stderr);
1187 break;
1188 case omp_proc_bind_spread:
1189 fputs ("SPREAD", stderr);
1190 break;
1192 for (i = 1; i < gomp_bind_var_list_len; i++)
1193 switch (gomp_bind_var_list[i])
1195 case omp_proc_bind_master:
1196 fputs (",MASTER", stderr);
1197 break;
1198 case omp_proc_bind_close:
1199 fputs (",CLOSE", stderr);
1200 break;
1201 case omp_proc_bind_spread:
1202 fputs (",SPREAD", stderr);
1203 break;
1205 fputs ("'\n", stderr);
1206 fputs (" OMP_PLACES = '", stderr);
1207 for (i = 0; i < gomp_places_list_len; i++)
1209 fputs ("{", stderr);
1210 gomp_affinity_print_place (gomp_places_list[i]);
1211 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1213 fputs ("'\n", stderr);
1215 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1217 /* GOMP's default value is actually neither active nor passive. */
1218 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1219 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1220 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1221 gomp_global_icv.thread_limit_var);
1222 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1223 gomp_max_active_levels_var);
1225 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1226 gomp_cancel_var ? "TRUE" : "FALSE");
1227 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1228 gomp_global_icv.default_device_var);
1229 fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1230 gomp_max_task_priority_var);
1232 if (verbose)
1234 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1235 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1236 #ifdef HAVE_INTTYPES_H
1237 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1238 (uint64_t) gomp_spin_count_var);
1239 #else
1240 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1241 (unsigned long) gomp_spin_count_var);
1242 #endif
1245 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1249 static void __attribute__((constructor))
1250 initialize_env (void)
1252 unsigned long thread_limit_var, stacksize = GOMP_DEFAULT_STACKSIZE;
1253 int wait_policy;
1255 /* Do a compile time check that mkomp_h.pl did good job. */
1256 omp_check_defines ();
1258 parse_schedule ();
1259 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1260 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1261 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1262 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1263 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
1264 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1265 true);
1266 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1268 gomp_global_icv.thread_limit_var
1269 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1271 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
1272 #ifndef HAVE_SYNC_BUILTINS
1273 gomp_mutex_init (&gomp_managed_threads_lock);
1274 #endif
1275 gomp_init_num_threads ();
1276 gomp_available_cpus = gomp_global_icv.nthreads_var;
1277 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1278 &gomp_global_icv.nthreads_var,
1279 &gomp_nthreads_var_list,
1280 &gomp_nthreads_var_list_len))
1281 gomp_global_icv.nthreads_var = gomp_available_cpus;
1282 bool ignore = false;
1283 if (parse_bind_var ("OMP_PROC_BIND",
1284 &gomp_global_icv.bind_var,
1285 &gomp_bind_var_list,
1286 &gomp_bind_var_list_len)
1287 && gomp_global_icv.bind_var == omp_proc_bind_false)
1288 ignore = true;
1289 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1290 parsed if present in the environment. If OMP_PROC_BIND was set
1291 explictly to false, don't populate places list though. If places
1292 list was successfully set from OMP_PLACES, only parse but don't process
1293 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1294 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1295 was successfully parsed into a places list, otherwise to
1296 OMP_PROC_BIND=false. */
1297 if (parse_places_var ("OMP_PLACES", ignore))
1299 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1300 gomp_global_icv.bind_var = true;
1301 ignore = true;
1303 if (parse_affinity (ignore))
1305 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1306 gomp_global_icv.bind_var = true;
1307 ignore = true;
1309 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1310 gomp_init_affinity ();
1311 wait_policy = parse_wait_policy ();
1312 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1314 /* Using a rough estimation of 100000 spins per msec,
1315 use 5 min blocking for OMP_WAIT_POLICY=active,
1316 3 msec blocking when OMP_WAIT_POLICY is not specificed
1317 and 0 when OMP_WAIT_POLICY=passive.
1318 Depending on the CPU speed, this can be e.g. 5 times longer
1319 or 5 times shorter. */
1320 if (wait_policy > 0)
1321 gomp_spin_count_var = 30000000000LL;
1322 else if (wait_policy < 0)
1323 gomp_spin_count_var = 300000LL;
1325 /* gomp_throttled_spin_count_var is used when there are more libgomp
1326 managed threads than available CPUs. Use very short spinning. */
1327 if (wait_policy > 0)
1328 gomp_throttled_spin_count_var = 1000LL;
1329 else if (wait_policy < 0)
1330 gomp_throttled_spin_count_var = 100LL;
1331 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1332 gomp_throttled_spin_count_var = gomp_spin_count_var;
1334 /* Not strictly environment related, but ordering constructors is tricky. */
1335 pthread_attr_init (&gomp_thread_attr);
1336 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
1338 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1339 || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
1340 || GOMP_DEFAULT_STACKSIZE)
1342 int err;
1344 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1346 #ifdef PTHREAD_STACK_MIN
1347 if (err == EINVAL)
1349 if (stacksize < PTHREAD_STACK_MIN)
1350 gomp_error ("Stack size less than minimum of %luk",
1351 PTHREAD_STACK_MIN / 1024ul
1352 + (PTHREAD_STACK_MIN % 1024 != 0));
1353 else
1354 gomp_error ("Stack size larger than system limit");
1356 else
1357 #endif
1358 if (err != 0)
1359 gomp_error ("Stack size change failed: %s", strerror (err));
1362 handle_omp_display_env (stacksize, wait_policy);
1364 /* OpenACC. */
1366 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1367 goacc_device_num = 0;
1369 parse_acc_device_type ();
1370 parse_gomp_openacc_dim ();
1372 goacc_runtime_initialize ();
1374 #endif /* LIBGOMP_OFFLOADED_ONLY */