2017-02-20 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgomp / env.c
blob74dc6f38530a06f68372fa2a4c8793c6cae62bb3
1 /* Copyright (C) 2005-2017 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 #include "libgomp.h"
30 #include "gomp-constants.h"
31 #include <limits.h>
32 #ifndef LIBGOMP_OFFLOADED_ONLY
33 #include "libgomp_f.h"
34 #include "oacc-int.h"
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #ifdef HAVE_INTTYPES_H
39 # include <inttypes.h> /* For PRIu64. */
40 #endif
41 #ifdef STRING_WITH_STRINGS
42 # include <string.h>
43 # include <strings.h>
44 #else
45 # ifdef HAVE_STRING_H
46 # include <string.h>
47 # else
48 # ifdef HAVE_STRINGS_H
49 # include <strings.h>
50 # endif
51 # endif
52 #endif
53 #include <errno.h>
55 #ifndef HAVE_STRTOULL
56 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
57 #endif
58 #endif /* LIBGOMP_OFFLOADED_ONLY */
60 struct gomp_task_icv gomp_global_icv = {
61 .nthreads_var = 1,
62 .thread_limit_var = UINT_MAX,
63 .run_sched_var = GFS_DYNAMIC,
64 .run_sched_chunk_size = 1,
65 .default_device_var = 0,
66 .dyn_var = false,
67 .nest_var = false,
68 .bind_var = omp_proc_bind_false,
69 .target_data = NULL
72 unsigned long gomp_max_active_levels_var = INT_MAX;
73 bool gomp_cancel_var = false;
74 int gomp_max_task_priority_var = 0;
75 #ifndef HAVE_SYNC_BUILTINS
76 gomp_mutex_t gomp_managed_threads_lock;
77 #endif
78 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
79 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
80 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
81 char *gomp_bind_var_list;
82 unsigned long gomp_bind_var_list_len;
83 void **gomp_places_list;
84 unsigned long gomp_places_list_len;
85 int gomp_debug_var;
86 unsigned int gomp_num_teams_var;
87 char *goacc_device_type;
88 int goacc_device_num;
90 #ifndef LIBGOMP_OFFLOADED_ONLY
92 /* Parse the OMP_SCHEDULE environment variable. */
94 static void
95 parse_schedule (void)
97 char *env, *end;
98 unsigned long value;
100 env = getenv ("OMP_SCHEDULE");
101 if (env == NULL)
102 return;
104 while (isspace ((unsigned char) *env))
105 ++env;
106 if (strncasecmp (env, "static", 6) == 0)
108 gomp_global_icv.run_sched_var = GFS_STATIC;
109 env += 6;
111 else if (strncasecmp (env, "dynamic", 7) == 0)
113 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
114 env += 7;
116 else if (strncasecmp (env, "guided", 6) == 0)
118 gomp_global_icv.run_sched_var = GFS_GUIDED;
119 env += 6;
121 else if (strncasecmp (env, "auto", 4) == 0)
123 gomp_global_icv.run_sched_var = GFS_AUTO;
124 env += 4;
126 else
127 goto unknown;
129 while (isspace ((unsigned char) *env))
130 ++env;
131 if (*env == '\0')
133 gomp_global_icv.run_sched_chunk_size
134 = gomp_global_icv.run_sched_var != GFS_STATIC;
135 return;
137 if (*env++ != ',')
138 goto unknown;
139 while (isspace ((unsigned char) *env))
140 ++env;
141 if (*env == '\0')
142 goto invalid;
144 errno = 0;
145 value = strtoul (env, &end, 10);
146 if (errno)
147 goto invalid;
149 while (isspace ((unsigned char) *end))
150 ++end;
151 if (*end != '\0')
152 goto invalid;
154 if ((int)value != value)
155 goto invalid;
157 if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
158 value = 1;
159 gomp_global_icv.run_sched_chunk_size = value;
160 return;
162 unknown:
163 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
164 return;
166 invalid:
167 gomp_error ("Invalid value for chunk size in "
168 "environment variable OMP_SCHEDULE");
169 return;
172 /* Parse an unsigned long environment variable. Return true if one was
173 present and it was successfully parsed. */
175 static bool
176 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
178 char *env, *end;
179 unsigned long value;
181 env = getenv (name);
182 if (env == NULL)
183 return false;
185 while (isspace ((unsigned char) *env))
186 ++env;
187 if (*env == '\0')
188 goto invalid;
190 errno = 0;
191 value = strtoul (env, &end, 10);
192 if (errno || (long) value <= 0 - allow_zero)
193 goto invalid;
195 while (isspace ((unsigned char) *end))
196 ++end;
197 if (*end != '\0')
198 goto invalid;
200 *pvalue = value;
201 return true;
203 invalid:
204 gomp_error ("Invalid value for environment variable %s", name);
205 return false;
208 /* Parse a positive int environment variable. Return true if one was
209 present and it was successfully parsed. */
211 static bool
212 parse_int (const char *name, int *pvalue, bool allow_zero)
214 unsigned long value;
215 if (!parse_unsigned_long (name, &value, allow_zero))
216 return false;
217 if (value > INT_MAX)
219 gomp_error ("Invalid value for environment variable %s", name);
220 return false;
222 *pvalue = (int) value;
223 return true;
226 /* Parse an unsigned long list environment variable. Return true if one was
227 present and it was successfully parsed. */
229 static bool
230 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
231 unsigned long **pvalues,
232 unsigned long *pnvalues)
234 char *env, *end;
235 unsigned long value, *values = NULL;
237 env = getenv (name);
238 if (env == NULL)
239 return false;
241 while (isspace ((unsigned char) *env))
242 ++env;
243 if (*env == '\0')
244 goto invalid;
246 errno = 0;
247 value = strtoul (env, &end, 10);
248 if (errno || (long) value <= 0)
249 goto invalid;
251 while (isspace ((unsigned char) *end))
252 ++end;
253 if (*end != '\0')
255 if (*end == ',')
257 unsigned long nvalues = 0, nalloced = 0;
261 env = end + 1;
262 if (nvalues == nalloced)
264 unsigned long *n;
265 nalloced = nalloced ? nalloced * 2 : 16;
266 n = realloc (values, nalloced * sizeof (unsigned long));
267 if (n == NULL)
269 free (values);
270 gomp_error ("Out of memory while trying to parse"
271 " environment variable %s", name);
272 return false;
274 values = n;
275 if (nvalues == 0)
276 values[nvalues++] = value;
279 while (isspace ((unsigned char) *env))
280 ++env;
281 if (*env == '\0')
282 goto invalid;
284 errno = 0;
285 value = strtoul (env, &end, 10);
286 if (errno || (long) value <= 0)
287 goto invalid;
289 values[nvalues++] = value;
290 while (isspace ((unsigned char) *end))
291 ++end;
292 if (*end == '\0')
293 break;
294 if (*end != ',')
295 goto invalid;
297 while (1);
298 *p1stvalue = values[0];
299 *pvalues = values;
300 *pnvalues = nvalues;
301 return true;
303 goto invalid;
306 *p1stvalue = value;
307 return true;
309 invalid:
310 free (values);
311 gomp_error ("Invalid value for environment variable %s", name);
312 return false;
315 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
316 enum values. Return true if one was present and it was successfully
317 parsed. */
319 static bool
320 parse_bind_var (const char *name, char *p1stvalue,
321 char **pvalues, unsigned long *pnvalues)
323 char *env;
324 char value = omp_proc_bind_false, *values = NULL;
325 int i;
326 static struct proc_bind_kinds
328 const char name[7];
329 const char len;
330 omp_proc_bind_t kind;
331 } kinds[] =
333 { "false", 5, omp_proc_bind_false },
334 { "true", 4, omp_proc_bind_true },
335 { "master", 6, omp_proc_bind_master },
336 { "close", 5, omp_proc_bind_close },
337 { "spread", 6, omp_proc_bind_spread }
340 env = getenv (name);
341 if (env == NULL)
342 return false;
344 while (isspace ((unsigned char) *env))
345 ++env;
346 if (*env == '\0')
347 goto invalid;
349 for (i = 0; i < 5; i++)
350 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
352 value = kinds[i].kind;
353 env += kinds[i].len;
354 break;
356 if (i == 5)
357 goto invalid;
359 while (isspace ((unsigned char) *env))
360 ++env;
361 if (*env != '\0')
363 if (*env == ',')
365 unsigned long nvalues = 0, nalloced = 0;
367 if (value == omp_proc_bind_false
368 || value == omp_proc_bind_true)
369 goto invalid;
373 env++;
374 if (nvalues == nalloced)
376 char *n;
377 nalloced = nalloced ? nalloced * 2 : 16;
378 n = realloc (values, nalloced);
379 if (n == NULL)
381 free (values);
382 gomp_error ("Out of memory while trying to parse"
383 " environment variable %s", name);
384 return false;
386 values = n;
387 if (nvalues == 0)
388 values[nvalues++] = value;
391 while (isspace ((unsigned char) *env))
392 ++env;
393 if (*env == '\0')
394 goto invalid;
396 for (i = 2; i < 5; i++)
397 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
399 value = kinds[i].kind;
400 env += kinds[i].len;
401 break;
403 if (i == 5)
404 goto invalid;
406 values[nvalues++] = value;
407 while (isspace ((unsigned char) *env))
408 ++env;
409 if (*env == '\0')
410 break;
411 if (*env != ',')
412 goto invalid;
414 while (1);
415 *p1stvalue = values[0];
416 *pvalues = values;
417 *pnvalues = nvalues;
418 return true;
420 goto invalid;
423 *p1stvalue = value;
424 return true;
426 invalid:
427 free (values);
428 gomp_error ("Invalid value for environment variable %s", name);
429 return false;
432 static bool
433 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
434 long *stridep)
436 char *env = *envp, *start;
437 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
438 unsigned long len = 1;
439 long stride = 1;
440 int pass;
441 bool any_negate = false;
442 *negatep = false;
443 while (isspace ((unsigned char) *env))
444 ++env;
445 if (*env == '!')
447 *negatep = true;
448 ++env;
449 while (isspace ((unsigned char) *env))
450 ++env;
452 if (*env != '{')
453 return false;
454 ++env;
455 while (isspace ((unsigned char) *env))
456 ++env;
457 start = env;
458 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
460 env = start;
463 unsigned long this_num, this_len = 1;
464 long this_stride = 1;
465 bool this_negate = (*env == '!');
466 if (this_negate)
468 if (gomp_places_list)
469 any_negate = true;
470 ++env;
471 while (isspace ((unsigned char) *env))
472 ++env;
475 errno = 0;
476 this_num = strtoul (env, &env, 10);
477 if (errno)
478 return false;
479 while (isspace ((unsigned char) *env))
480 ++env;
481 if (*env == ':')
483 ++env;
484 while (isspace ((unsigned char) *env))
485 ++env;
486 errno = 0;
487 this_len = strtoul (env, &env, 10);
488 if (errno || this_len == 0)
489 return false;
490 while (isspace ((unsigned char) *env))
491 ++env;
492 if (*env == ':')
494 ++env;
495 while (isspace ((unsigned char) *env))
496 ++env;
497 errno = 0;
498 this_stride = strtol (env, &env, 10);
499 if (errno)
500 return false;
501 while (isspace ((unsigned char) *env))
502 ++env;
505 if (this_negate && this_len != 1)
506 return false;
507 if (gomp_places_list && pass == this_negate)
509 if (this_negate)
511 if (!gomp_affinity_remove_cpu (p, this_num))
512 return false;
514 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
515 this_stride, false))
516 return false;
518 if (*env == '}')
519 break;
520 if (*env != ',')
521 return false;
522 ++env;
524 while (1);
527 ++env;
528 while (isspace ((unsigned char) *env))
529 ++env;
530 if (*env == ':')
532 ++env;
533 while (isspace ((unsigned char) *env))
534 ++env;
535 errno = 0;
536 len = strtoul (env, &env, 10);
537 if (errno || len == 0 || len >= 65536)
538 return false;
539 while (isspace ((unsigned char) *env))
540 ++env;
541 if (*env == ':')
543 ++env;
544 while (isspace ((unsigned char) *env))
545 ++env;
546 errno = 0;
547 stride = strtol (env, &env, 10);
548 if (errno)
549 return false;
550 while (isspace ((unsigned char) *env))
551 ++env;
554 if (*negatep && len != 1)
555 return false;
556 *envp = env;
557 *lenp = len;
558 *stridep = stride;
559 return true;
562 static bool
563 parse_places_var (const char *name, bool ignore)
565 char *env = getenv (name), *end;
566 bool any_negate = false;
567 int level = 0;
568 unsigned long count = 0;
569 if (env == NULL)
570 return false;
572 while (isspace ((unsigned char) *env))
573 ++env;
574 if (*env == '\0')
575 goto invalid;
577 if (strncasecmp (env, "threads", 7) == 0)
579 env += 7;
580 level = 1;
582 else if (strncasecmp (env, "cores", 5) == 0)
584 env += 5;
585 level = 2;
587 else if (strncasecmp (env, "sockets", 7) == 0)
589 env += 7;
590 level = 3;
592 if (level)
594 count = ULONG_MAX;
595 while (isspace ((unsigned char) *env))
596 ++env;
597 if (*env != '\0')
599 if (*env++ != '(')
600 goto invalid;
601 while (isspace ((unsigned char) *env))
602 ++env;
604 errno = 0;
605 count = strtoul (env, &end, 10);
606 if (errno)
607 goto invalid;
608 env = end;
609 while (isspace ((unsigned char) *env))
610 ++env;
611 if (*env != ')')
612 goto invalid;
613 ++env;
614 while (isspace ((unsigned char) *env))
615 ++env;
616 if (*env != '\0')
617 goto invalid;
620 if (ignore)
621 return false;
623 return gomp_affinity_init_level (level, count, false);
626 count = 0;
627 end = env;
630 bool negate;
631 unsigned long len;
632 long stride;
633 if (!parse_one_place (&end, &negate, &len, &stride))
634 goto invalid;
635 if (negate)
637 if (!any_negate)
638 count++;
639 any_negate = true;
641 else
642 count += len;
643 if (count > 65536)
644 goto invalid;
645 if (*end == '\0')
646 break;
647 if (*end != ',')
648 goto invalid;
649 end++;
651 while (1);
653 if (ignore)
654 return false;
656 gomp_places_list_len = 0;
657 gomp_places_list = gomp_affinity_alloc (count, false);
658 if (gomp_places_list == NULL)
659 return false;
663 bool negate;
664 unsigned long len;
665 long stride;
666 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
667 if (!parse_one_place (&env, &negate, &len, &stride))
668 goto invalid;
669 if (negate)
671 void *p;
672 for (count = 0; count < gomp_places_list_len; count++)
673 if (gomp_affinity_same_place
674 (gomp_places_list[count],
675 gomp_places_list[gomp_places_list_len]))
676 break;
677 if (count == gomp_places_list_len)
679 gomp_error ("Trying to remove a non-existing place from list "
680 "of places");
681 goto invalid;
683 p = gomp_places_list[count];
684 memmove (&gomp_places_list[count],
685 &gomp_places_list[count + 1],
686 (gomp_places_list_len - count - 1) * sizeof (void *));
687 --gomp_places_list_len;
688 gomp_places_list[gomp_places_list_len] = p;
690 else if (len == 1)
691 ++gomp_places_list_len;
692 else
694 for (count = 0; count < len - 1; count++)
695 if (!gomp_affinity_copy_place
696 (gomp_places_list[gomp_places_list_len + count + 1],
697 gomp_places_list[gomp_places_list_len + count],
698 stride))
699 goto invalid;
700 gomp_places_list_len += len;
702 if (*env == '\0')
703 break;
704 env++;
706 while (1);
708 if (gomp_places_list_len == 0)
710 gomp_error ("All places have been removed");
711 goto invalid;
713 if (!gomp_affinity_finalize_place_list (false))
714 goto invalid;
715 return true;
717 invalid:
718 free (gomp_places_list);
719 gomp_places_list = NULL;
720 gomp_places_list_len = 0;
721 gomp_error ("Invalid value for environment variable %s", name);
722 return false;
725 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
726 present and it was successfully parsed. */
728 static bool
729 parse_stacksize (const char *name, unsigned long *pvalue)
731 char *env, *end;
732 unsigned long value, shift = 10;
734 env = getenv (name);
735 if (env == NULL)
736 return false;
738 while (isspace ((unsigned char) *env))
739 ++env;
740 if (*env == '\0')
741 goto invalid;
743 errno = 0;
744 value = strtoul (env, &end, 10);
745 if (errno)
746 goto invalid;
748 while (isspace ((unsigned char) *end))
749 ++end;
750 if (*end != '\0')
752 switch (tolower ((unsigned char) *end))
754 case 'b':
755 shift = 0;
756 break;
757 case 'k':
758 break;
759 case 'm':
760 shift = 20;
761 break;
762 case 'g':
763 shift = 30;
764 break;
765 default:
766 goto invalid;
768 ++end;
769 while (isspace ((unsigned char) *end))
770 ++end;
771 if (*end != '\0')
772 goto invalid;
775 if (((value << shift) >> shift) != value)
776 goto invalid;
778 *pvalue = value << shift;
779 return true;
781 invalid:
782 gomp_error ("Invalid value for environment variable %s", name);
783 return false;
786 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
787 present and it was successfully parsed. */
789 static bool
790 parse_spincount (const char *name, unsigned long long *pvalue)
792 char *env, *end;
793 unsigned long long value, mult = 1;
795 env = getenv (name);
796 if (env == NULL)
797 return false;
799 while (isspace ((unsigned char) *env))
800 ++env;
801 if (*env == '\0')
802 goto invalid;
804 if (strncasecmp (env, "infinite", 8) == 0
805 || strncasecmp (env, "infinity", 8) == 0)
807 value = ~0ULL;
808 end = env + 8;
809 goto check_tail;
812 errno = 0;
813 value = strtoull (env, &end, 10);
814 if (errno)
815 goto invalid;
817 while (isspace ((unsigned char) *end))
818 ++end;
819 if (*end != '\0')
821 switch (tolower ((unsigned char) *end))
823 case 'k':
824 mult = 1000LL;
825 break;
826 case 'm':
827 mult = 1000LL * 1000LL;
828 break;
829 case 'g':
830 mult = 1000LL * 1000LL * 1000LL;
831 break;
832 case 't':
833 mult = 1000LL * 1000LL * 1000LL * 1000LL;
834 break;
835 default:
836 goto invalid;
838 ++end;
839 check_tail:
840 while (isspace ((unsigned char) *end))
841 ++end;
842 if (*end != '\0')
843 goto invalid;
846 if (value > ~0ULL / mult)
847 value = ~0ULL;
848 else
849 value *= mult;
851 *pvalue = value;
852 return true;
854 invalid:
855 gomp_error ("Invalid value for environment variable %s", name);
856 return false;
859 /* Parse a boolean value for environment variable NAME and store the
860 result in VALUE. */
862 static void
863 parse_boolean (const char *name, bool *value)
865 const char *env;
867 env = getenv (name);
868 if (env == NULL)
869 return;
871 while (isspace ((unsigned char) *env))
872 ++env;
873 if (strncasecmp (env, "true", 4) == 0)
875 *value = true;
876 env += 4;
878 else if (strncasecmp (env, "false", 5) == 0)
880 *value = false;
881 env += 5;
883 else
884 env = "X";
885 while (isspace ((unsigned char) *env))
886 ++env;
887 if (*env != '\0')
888 gomp_error ("Invalid value for environment variable %s", name);
891 /* Parse the OMP_WAIT_POLICY environment variable and store the
892 result in gomp_active_wait_policy. */
894 static int
895 parse_wait_policy (void)
897 const char *env;
898 int ret = -1;
900 env = getenv ("OMP_WAIT_POLICY");
901 if (env == NULL)
902 return -1;
904 while (isspace ((unsigned char) *env))
905 ++env;
906 if (strncasecmp (env, "active", 6) == 0)
908 ret = 1;
909 env += 6;
911 else if (strncasecmp (env, "passive", 7) == 0)
913 ret = 0;
914 env += 7;
916 else
917 env = "X";
918 while (isspace ((unsigned char) *env))
919 ++env;
920 if (*env == '\0')
921 return ret;
922 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
923 return -1;
926 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
927 present and it was successfully parsed. */
929 static bool
930 parse_affinity (bool ignore)
932 char *env, *end, *start;
933 int pass;
934 unsigned long cpu_beg, cpu_end, cpu_stride;
935 size_t count = 0, needed;
937 env = getenv ("GOMP_CPU_AFFINITY");
938 if (env == NULL)
939 return false;
941 start = env;
942 for (pass = 0; pass < 2; pass++)
944 env = start;
945 if (pass == 1)
947 if (ignore)
948 return false;
950 gomp_places_list_len = 0;
951 gomp_places_list = gomp_affinity_alloc (count, true);
952 if (gomp_places_list == NULL)
953 return false;
957 while (isspace ((unsigned char) *env))
958 ++env;
960 errno = 0;
961 cpu_beg = strtoul (env, &end, 0);
962 if (errno || cpu_beg >= 65536)
963 goto invalid;
964 cpu_end = cpu_beg;
965 cpu_stride = 1;
967 env = end;
968 if (*env == '-')
970 errno = 0;
971 cpu_end = strtoul (++env, &end, 0);
972 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
973 goto invalid;
975 env = end;
976 if (*env == ':')
978 errno = 0;
979 cpu_stride = strtoul (++env, &end, 0);
980 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
981 goto invalid;
983 env = end;
987 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
988 if (pass == 0)
989 count += needed;
990 else
992 while (needed--)
994 void *p = gomp_places_list[gomp_places_list_len];
995 gomp_affinity_init_place (p);
996 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
997 ++gomp_places_list_len;
998 cpu_beg += cpu_stride;
1002 while (isspace ((unsigned char) *env))
1003 ++env;
1005 if (*env == ',')
1006 env++;
1007 else if (*env == '\0')
1008 break;
1010 while (1);
1013 if (gomp_places_list_len == 0)
1015 free (gomp_places_list);
1016 gomp_places_list = NULL;
1017 return false;
1019 return true;
1021 invalid:
1022 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1023 return false;
1026 static void
1027 parse_acc_device_type (void)
1029 const char *env = getenv ("ACC_DEVICE_TYPE");
1031 if (env && *env != '\0')
1032 goacc_device_type = strdup (env);
1033 else
1034 goacc_device_type = NULL;
1037 static void
1038 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1040 const char *env;
1041 bool display = false;
1042 bool verbose = false;
1043 int i;
1045 env = getenv ("OMP_DISPLAY_ENV");
1046 if (env == NULL)
1047 return;
1049 while (isspace ((unsigned char) *env))
1050 ++env;
1051 if (strncasecmp (env, "true", 4) == 0)
1053 display = true;
1054 env += 4;
1056 else if (strncasecmp (env, "false", 5) == 0)
1058 display = false;
1059 env += 5;
1061 else if (strncasecmp (env, "verbose", 7) == 0)
1063 display = true;
1064 verbose = true;
1065 env += 7;
1067 else
1068 env = "X";
1069 while (isspace ((unsigned char) *env))
1070 ++env;
1071 if (*env != '\0')
1072 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1074 if (!display)
1075 return;
1077 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1079 fputs (" _OPENMP = '201511'\n", stderr);
1080 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1081 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1082 fprintf (stderr, " OMP_NESTED = '%s'\n",
1083 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1085 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1086 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1087 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1088 fputs ("'\n", stderr);
1090 fprintf (stderr, " OMP_SCHEDULE = '");
1091 switch (gomp_global_icv.run_sched_var)
1093 case GFS_RUNTIME:
1094 fputs ("RUNTIME", stderr);
1095 break;
1096 case GFS_STATIC:
1097 fputs ("STATIC", stderr);
1098 break;
1099 case GFS_DYNAMIC:
1100 fputs ("DYNAMIC", stderr);
1101 break;
1102 case GFS_GUIDED:
1103 fputs ("GUIDED", stderr);
1104 break;
1105 case GFS_AUTO:
1106 fputs ("AUTO", stderr);
1107 break;
1109 fputs ("'\n", stderr);
1111 fputs (" OMP_PROC_BIND = '", stderr);
1112 switch (gomp_global_icv.bind_var)
1114 case omp_proc_bind_false:
1115 fputs ("FALSE", stderr);
1116 break;
1117 case omp_proc_bind_true:
1118 fputs ("TRUE", stderr);
1119 break;
1120 case omp_proc_bind_master:
1121 fputs ("MASTER", stderr);
1122 break;
1123 case omp_proc_bind_close:
1124 fputs ("CLOSE", stderr);
1125 break;
1126 case omp_proc_bind_spread:
1127 fputs ("SPREAD", stderr);
1128 break;
1130 for (i = 1; i < gomp_bind_var_list_len; i++)
1131 switch (gomp_bind_var_list[i])
1133 case omp_proc_bind_master:
1134 fputs (",MASTER", stderr);
1135 break;
1136 case omp_proc_bind_close:
1137 fputs (",CLOSE", stderr);
1138 break;
1139 case omp_proc_bind_spread:
1140 fputs (",SPREAD", stderr);
1141 break;
1143 fputs ("'\n", stderr);
1144 fputs (" OMP_PLACES = '", stderr);
1145 for (i = 0; i < gomp_places_list_len; i++)
1147 fputs ("{", stderr);
1148 gomp_affinity_print_place (gomp_places_list[i]);
1149 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1151 fputs ("'\n", stderr);
1153 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1155 /* GOMP's default value is actually neither active nor passive. */
1156 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1157 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1158 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1159 gomp_global_icv.thread_limit_var);
1160 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1161 gomp_max_active_levels_var);
1163 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1164 gomp_cancel_var ? "TRUE" : "FALSE");
1165 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1166 gomp_global_icv.default_device_var);
1167 fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1168 gomp_max_task_priority_var);
1170 if (verbose)
1172 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1173 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1174 #ifdef HAVE_INTTYPES_H
1175 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1176 (uint64_t) gomp_spin_count_var);
1177 #else
1178 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1179 (unsigned long) gomp_spin_count_var);
1180 #endif
1183 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1187 static void __attribute__((constructor))
1188 initialize_env (void)
1190 unsigned long thread_limit_var, stacksize;
1191 int wait_policy;
1193 /* Do a compile time check that mkomp_h.pl did good job. */
1194 omp_check_defines ();
1196 parse_schedule ();
1197 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1198 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1199 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1200 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1201 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
1202 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1203 true);
1204 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1206 gomp_global_icv.thread_limit_var
1207 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1209 parse_int ("GOMP_DEBUG", &gomp_debug_var, true);
1210 #ifndef HAVE_SYNC_BUILTINS
1211 gomp_mutex_init (&gomp_managed_threads_lock);
1212 #endif
1213 gomp_init_num_threads ();
1214 gomp_available_cpus = gomp_global_icv.nthreads_var;
1215 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1216 &gomp_global_icv.nthreads_var,
1217 &gomp_nthreads_var_list,
1218 &gomp_nthreads_var_list_len))
1219 gomp_global_icv.nthreads_var = gomp_available_cpus;
1220 bool ignore = false;
1221 if (parse_bind_var ("OMP_PROC_BIND",
1222 &gomp_global_icv.bind_var,
1223 &gomp_bind_var_list,
1224 &gomp_bind_var_list_len)
1225 && gomp_global_icv.bind_var == omp_proc_bind_false)
1226 ignore = true;
1227 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1228 parsed if present in the environment. If OMP_PROC_BIND was set
1229 explictly to false, don't populate places list though. If places
1230 list was successfully set from OMP_PLACES, only parse but don't process
1231 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1232 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1233 was successfully parsed into a places list, otherwise to
1234 OMP_PROC_BIND=false. */
1235 if (parse_places_var ("OMP_PLACES", ignore))
1237 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1238 gomp_global_icv.bind_var = true;
1239 ignore = true;
1241 if (parse_affinity (ignore))
1243 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1244 gomp_global_icv.bind_var = true;
1245 ignore = true;
1247 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1248 gomp_init_affinity ();
1249 wait_policy = parse_wait_policy ();
1250 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1252 /* Using a rough estimation of 100000 spins per msec,
1253 use 5 min blocking for OMP_WAIT_POLICY=active,
1254 3 msec blocking when OMP_WAIT_POLICY is not specificed
1255 and 0 when OMP_WAIT_POLICY=passive.
1256 Depending on the CPU speed, this can be e.g. 5 times longer
1257 or 5 times shorter. */
1258 if (wait_policy > 0)
1259 gomp_spin_count_var = 30000000000LL;
1260 else if (wait_policy < 0)
1261 gomp_spin_count_var = 300000LL;
1263 /* gomp_throttled_spin_count_var is used when there are more libgomp
1264 managed threads than available CPUs. Use very short spinning. */
1265 if (wait_policy > 0)
1266 gomp_throttled_spin_count_var = 1000LL;
1267 else if (wait_policy < 0)
1268 gomp_throttled_spin_count_var = 100LL;
1269 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1270 gomp_throttled_spin_count_var = gomp_spin_count_var;
1272 /* Not strictly environment related, but ordering constructors is tricky. */
1273 pthread_attr_init (&gomp_thread_attr);
1274 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
1276 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1277 || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
1279 int err;
1281 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1283 #ifdef PTHREAD_STACK_MIN
1284 if (err == EINVAL)
1286 if (stacksize < PTHREAD_STACK_MIN)
1287 gomp_error ("Stack size less than minimum of %luk",
1288 PTHREAD_STACK_MIN / 1024ul
1289 + (PTHREAD_STACK_MIN % 1024 != 0));
1290 else
1291 gomp_error ("Stack size larger than system limit");
1293 else
1294 #endif
1295 if (err != 0)
1296 gomp_error ("Stack size change failed: %s", strerror (err));
1299 handle_omp_display_env (stacksize, wait_policy);
1301 /* OpenACC. */
1303 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1304 goacc_device_num = 0;
1306 parse_acc_device_type ();
1308 goacc_runtime_initialize ();
1310 #endif /* LIBGOMP_OFFLOADED_ONLY */