* ChangeLog-2013: Correct an old entry.
[official-gcc.git] / libgomp / env.c
blob94c72a34fa05540cbee86db1f717ca13d92e6e6e
1 /* Copyright (C) 2005-2014 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU OpenMP Library (libgomp).
6 Libgomp is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 /* This file defines the OpenMP internal control variables, and arranges
26 for them to be initialized from environment variables at startup. */
28 #include "libgomp.h"
29 #include "libgomp_f.h"
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #ifdef HAVE_INTTYPES_H
34 # include <inttypes.h> /* For PRIu64. */
35 #endif
36 #ifdef STRING_WITH_STRINGS
37 # include <string.h>
38 # include <strings.h>
39 #else
40 # ifdef HAVE_STRING_H
41 # include <string.h>
42 # else
43 # ifdef HAVE_STRINGS_H
44 # include <strings.h>
45 # endif
46 # endif
47 #endif
48 #include <limits.h>
49 #include <errno.h>
51 #ifndef HAVE_STRTOULL
52 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
53 #endif
55 struct gomp_task_icv gomp_global_icv = {
56 .nthreads_var = 1,
57 .thread_limit_var = UINT_MAX,
58 .run_sched_var = GFS_DYNAMIC,
59 .run_sched_modifier = 1,
60 .default_device_var = 0,
61 .dyn_var = false,
62 .nest_var = false,
63 .bind_var = omp_proc_bind_false,
64 .target_data = NULL
67 unsigned long gomp_max_active_levels_var = INT_MAX;
68 bool gomp_cancel_var = false;
69 #ifndef HAVE_SYNC_BUILTINS
70 gomp_mutex_t gomp_managed_threads_lock;
71 #endif
72 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
73 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
74 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
75 char *gomp_bind_var_list;
76 unsigned long gomp_bind_var_list_len;
77 void **gomp_places_list;
78 unsigned long gomp_places_list_len;
80 /* Parse the OMP_SCHEDULE environment variable. */
82 static void
83 parse_schedule (void)
85 char *env, *end;
86 unsigned long value;
88 env = getenv ("OMP_SCHEDULE");
89 if (env == NULL)
90 return;
92 while (isspace ((unsigned char) *env))
93 ++env;
94 if (strncasecmp (env, "static", 6) == 0)
96 gomp_global_icv.run_sched_var = GFS_STATIC;
97 env += 6;
99 else if (strncasecmp (env, "dynamic", 7) == 0)
101 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
102 env += 7;
104 else if (strncasecmp (env, "guided", 6) == 0)
106 gomp_global_icv.run_sched_var = GFS_GUIDED;
107 env += 6;
109 else if (strncasecmp (env, "auto", 4) == 0)
111 gomp_global_icv.run_sched_var = GFS_AUTO;
112 env += 4;
114 else
115 goto unknown;
117 while (isspace ((unsigned char) *env))
118 ++env;
119 if (*env == '\0')
121 gomp_global_icv.run_sched_modifier
122 = gomp_global_icv.run_sched_var != GFS_STATIC;
123 return;
125 if (*env++ != ',')
126 goto unknown;
127 while (isspace ((unsigned char) *env))
128 ++env;
129 if (*env == '\0')
130 goto invalid;
132 errno = 0;
133 value = strtoul (env, &end, 10);
134 if (errno)
135 goto invalid;
137 while (isspace ((unsigned char) *end))
138 ++end;
139 if (*end != '\0')
140 goto invalid;
142 if ((int)value != value)
143 goto invalid;
145 if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
146 value = 1;
147 gomp_global_icv.run_sched_modifier = value;
148 return;
150 unknown:
151 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
152 return;
154 invalid:
155 gomp_error ("Invalid value for chunk size in "
156 "environment variable OMP_SCHEDULE");
157 return;
160 /* Parse an unsigned long environment variable. Return true if one was
161 present and it was successfully parsed. */
163 static bool
164 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
166 char *env, *end;
167 unsigned long value;
169 env = getenv (name);
170 if (env == NULL)
171 return false;
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 || (long) value <= 0 - allow_zero)
181 goto invalid;
183 while (isspace ((unsigned char) *end))
184 ++end;
185 if (*end != '\0')
186 goto invalid;
188 *pvalue = value;
189 return true;
191 invalid:
192 gomp_error ("Invalid value for environment variable %s", name);
193 return false;
196 /* Parse a positive int environment variable. Return true if one was
197 present and it was successfully parsed. */
199 static bool
200 parse_int (const char *name, int *pvalue, bool allow_zero)
202 unsigned long value;
203 if (!parse_unsigned_long (name, &value, allow_zero))
204 return false;
205 if (value > INT_MAX)
207 gomp_error ("Invalid value for environment variable %s", name);
208 return false;
210 *pvalue = (int) value;
211 return true;
214 /* Parse an unsigned long list environment variable. Return true if one was
215 present and it was successfully parsed. */
217 static bool
218 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
219 unsigned long **pvalues,
220 unsigned long *pnvalues)
222 char *env, *end;
223 unsigned long value, *values = NULL;
225 env = getenv (name);
226 if (env == NULL)
227 return false;
229 while (isspace ((unsigned char) *env))
230 ++env;
231 if (*env == '\0')
232 goto invalid;
234 errno = 0;
235 value = strtoul (env, &end, 10);
236 if (errno || (long) value <= 0)
237 goto invalid;
239 while (isspace ((unsigned char) *end))
240 ++end;
241 if (*end != '\0')
243 if (*end == ',')
245 unsigned long nvalues = 0, nalloced = 0;
249 env = end + 1;
250 if (nvalues == nalloced)
252 unsigned long *n;
253 nalloced = nalloced ? nalloced * 2 : 16;
254 n = realloc (values, nalloced * sizeof (unsigned long));
255 if (n == NULL)
257 free (values);
258 gomp_error ("Out of memory while trying to parse"
259 " environment variable %s", name);
260 return false;
262 values = n;
263 if (nvalues == 0)
264 values[nvalues++] = value;
267 while (isspace ((unsigned char) *env))
268 ++env;
269 if (*env == '\0')
270 goto invalid;
272 errno = 0;
273 value = strtoul (env, &end, 10);
274 if (errno || (long) value <= 0)
275 goto invalid;
277 values[nvalues++] = value;
278 while (isspace ((unsigned char) *end))
279 ++end;
280 if (*end == '\0')
281 break;
282 if (*end != ',')
283 goto invalid;
285 while (1);
286 *p1stvalue = values[0];
287 *pvalues = values;
288 *pnvalues = nvalues;
289 return true;
291 goto invalid;
294 *p1stvalue = value;
295 return true;
297 invalid:
298 free (values);
299 gomp_error ("Invalid value for environment variable %s", name);
300 return false;
303 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
304 enum values. Return true if one was present and it was successfully
305 parsed. */
307 static bool
308 parse_bind_var (const char *name, char *p1stvalue,
309 char **pvalues, unsigned long *pnvalues)
311 char *env;
312 char value = omp_proc_bind_false, *values = NULL;
313 int i;
314 static struct proc_bind_kinds
316 const char name[7];
317 const char len;
318 omp_proc_bind_t kind;
319 } kinds[] =
321 { "false", 5, omp_proc_bind_false },
322 { "true", 4, omp_proc_bind_true },
323 { "master", 6, omp_proc_bind_master },
324 { "close", 5, omp_proc_bind_close },
325 { "spread", 6, omp_proc_bind_spread }
328 env = getenv (name);
329 if (env == NULL)
330 return false;
332 while (isspace ((unsigned char) *env))
333 ++env;
334 if (*env == '\0')
335 goto invalid;
337 for (i = 0; i < 5; i++)
338 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
340 value = kinds[i].kind;
341 env += kinds[i].len;
342 break;
344 if (i == 5)
345 goto invalid;
347 while (isspace ((unsigned char) *env))
348 ++env;
349 if (*env != '\0')
351 if (*env == ',')
353 unsigned long nvalues = 0, nalloced = 0;
355 if (value == omp_proc_bind_false
356 || value == omp_proc_bind_true)
357 goto invalid;
361 env++;
362 if (nvalues == nalloced)
364 char *n;
365 nalloced = nalloced ? nalloced * 2 : 16;
366 n = realloc (values, nalloced);
367 if (n == NULL)
369 free (values);
370 gomp_error ("Out of memory while trying to parse"
371 " environment variable %s", name);
372 return false;
374 values = n;
375 if (nvalues == 0)
376 values[nvalues++] = value;
379 while (isspace ((unsigned char) *env))
380 ++env;
381 if (*env == '\0')
382 goto invalid;
384 for (i = 2; i < 5; i++)
385 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
387 value = kinds[i].kind;
388 env += kinds[i].len;
389 break;
391 if (i == 5)
392 goto invalid;
394 values[nvalues++] = value;
395 while (isspace ((unsigned char) *env))
396 ++env;
397 if (*env == '\0')
398 break;
399 if (*env != ',')
400 goto invalid;
402 while (1);
403 *p1stvalue = values[0];
404 *pvalues = values;
405 *pnvalues = nvalues;
406 return true;
408 goto invalid;
411 *p1stvalue = value;
412 return true;
414 invalid:
415 free (values);
416 gomp_error ("Invalid value for environment variable %s", name);
417 return false;
420 static bool
421 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
422 long *stridep)
424 char *env = *envp, *start;
425 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
426 unsigned long len = 1;
427 long stride = 1;
428 int pass;
429 bool any_negate = false;
430 *negatep = false;
431 while (isspace ((unsigned char) *env))
432 ++env;
433 if (*env == '!')
435 *negatep = true;
436 ++env;
437 while (isspace ((unsigned char) *env))
438 ++env;
440 if (*env != '{')
441 return false;
442 ++env;
443 while (isspace ((unsigned char) *env))
444 ++env;
445 start = env;
446 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
448 env = start;
451 unsigned long this_num, this_len = 1;
452 long this_stride = 1;
453 bool this_negate = (*env == '!');
454 if (this_negate)
456 if (gomp_places_list)
457 any_negate = true;
458 ++env;
459 while (isspace ((unsigned char) *env))
460 ++env;
463 errno = 0;
464 this_num = strtoul (env, &env, 10);
465 if (errno)
466 return false;
467 while (isspace ((unsigned char) *env))
468 ++env;
469 if (*env == ':')
471 ++env;
472 while (isspace ((unsigned char) *env))
473 ++env;
474 errno = 0;
475 this_len = strtoul (env, &env, 10);
476 if (errno || this_len == 0)
477 return false;
478 while (isspace ((unsigned char) *env))
479 ++env;
480 if (*env == ':')
482 ++env;
483 while (isspace ((unsigned char) *env))
484 ++env;
485 errno = 0;
486 this_stride = strtol (env, &env, 10);
487 if (errno)
488 return false;
489 while (isspace ((unsigned char) *env))
490 ++env;
493 if (this_negate && this_len != 1)
494 return false;
495 if (gomp_places_list && pass == this_negate)
497 if (this_negate)
499 if (!gomp_affinity_remove_cpu (p, this_num))
500 return false;
502 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
503 this_stride, false))
504 return false;
506 if (*env == '}')
507 break;
508 if (*env != ',')
509 return false;
510 ++env;
512 while (1);
515 ++env;
516 while (isspace ((unsigned char) *env))
517 ++env;
518 if (*env == ':')
520 ++env;
521 while (isspace ((unsigned char) *env))
522 ++env;
523 errno = 0;
524 len = strtoul (env, &env, 10);
525 if (errno || len == 0 || len >= 65536)
526 return false;
527 while (isspace ((unsigned char) *env))
528 ++env;
529 if (*env == ':')
531 ++env;
532 while (isspace ((unsigned char) *env))
533 ++env;
534 errno = 0;
535 stride = strtol (env, &env, 10);
536 if (errno)
537 return false;
538 while (isspace ((unsigned char) *env))
539 ++env;
542 if (*negatep && len != 1)
543 return false;
544 *envp = env;
545 *lenp = len;
546 *stridep = stride;
547 return true;
550 static bool
551 parse_places_var (const char *name, bool ignore)
553 char *env = getenv (name), *end;
554 bool any_negate = false;
555 int level = 0;
556 unsigned long count = 0;
557 if (env == NULL)
558 return false;
560 while (isspace ((unsigned char) *env))
561 ++env;
562 if (*env == '\0')
563 goto invalid;
565 if (strncasecmp (env, "threads", 7) == 0)
567 env += 7;
568 level = 1;
570 else if (strncasecmp (env, "cores", 5) == 0)
572 env += 5;
573 level = 2;
575 else if (strncasecmp (env, "sockets", 7) == 0)
577 env += 7;
578 level = 3;
580 if (level)
582 count = ULONG_MAX;
583 while (isspace ((unsigned char) *env))
584 ++env;
585 if (*env != '\0')
587 if (*env++ != '(')
588 goto invalid;
589 while (isspace ((unsigned char) *env))
590 ++env;
592 errno = 0;
593 count = strtoul (env, &end, 10);
594 if (errno)
595 goto invalid;
596 env = end;
597 while (isspace ((unsigned char) *env))
598 ++env;
599 if (*env != ')')
600 goto invalid;
601 ++env;
602 while (isspace ((unsigned char) *env))
603 ++env;
604 if (*env != '\0')
605 goto invalid;
608 if (ignore)
609 return false;
611 return gomp_affinity_init_level (level, count, false);
614 count = 0;
615 end = env;
618 bool negate;
619 unsigned long len;
620 long stride;
621 if (!parse_one_place (&end, &negate, &len, &stride))
622 goto invalid;
623 if (negate)
625 if (!any_negate)
626 count++;
627 any_negate = true;
629 else
630 count += len;
631 if (count > 65536)
632 goto invalid;
633 if (*end == '\0')
634 break;
635 if (*end != ',')
636 goto invalid;
637 end++;
639 while (1);
641 if (ignore)
642 return false;
644 gomp_places_list_len = 0;
645 gomp_places_list = gomp_affinity_alloc (count, false);
646 if (gomp_places_list == NULL)
647 return false;
651 bool negate;
652 unsigned long len;
653 long stride;
654 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
655 if (!parse_one_place (&env, &negate, &len, &stride))
656 goto invalid;
657 if (negate)
659 void *p;
660 for (count = 0; count < gomp_places_list_len; count++)
661 if (gomp_affinity_same_place
662 (gomp_places_list[count],
663 gomp_places_list[gomp_places_list_len]))
664 break;
665 if (count == gomp_places_list_len)
667 gomp_error ("Trying to remove a non-existing place from list "
668 "of places");
669 goto invalid;
671 p = gomp_places_list[count];
672 memmove (&gomp_places_list[count],
673 &gomp_places_list[count + 1],
674 (gomp_places_list_len - count - 1) * sizeof (void *));
675 --gomp_places_list_len;
676 gomp_places_list[gomp_places_list_len] = p;
678 else if (len == 1)
679 ++gomp_places_list_len;
680 else
682 for (count = 0; count < len - 1; count++)
683 if (!gomp_affinity_copy_place
684 (gomp_places_list[gomp_places_list_len + count + 1],
685 gomp_places_list[gomp_places_list_len + count],
686 stride))
687 goto invalid;
688 gomp_places_list_len += len;
690 if (*env == '\0')
691 break;
692 env++;
694 while (1);
696 if (gomp_places_list_len == 0)
698 gomp_error ("All places have been removed");
699 goto invalid;
701 if (!gomp_affinity_finalize_place_list (false))
702 goto invalid;
703 return true;
705 invalid:
706 free (gomp_places_list);
707 gomp_places_list = NULL;
708 gomp_places_list_len = 0;
709 gomp_error ("Invalid value for environment variable %s", name);
710 return false;
713 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
714 present and it was successfully parsed. */
716 static bool
717 parse_stacksize (const char *name, unsigned long *pvalue)
719 char *env, *end;
720 unsigned long value, shift = 10;
722 env = getenv (name);
723 if (env == NULL)
724 return false;
726 while (isspace ((unsigned char) *env))
727 ++env;
728 if (*env == '\0')
729 goto invalid;
731 errno = 0;
732 value = strtoul (env, &end, 10);
733 if (errno)
734 goto invalid;
736 while (isspace ((unsigned char) *end))
737 ++end;
738 if (*end != '\0')
740 switch (tolower ((unsigned char) *end))
742 case 'b':
743 shift = 0;
744 break;
745 case 'k':
746 break;
747 case 'm':
748 shift = 20;
749 break;
750 case 'g':
751 shift = 30;
752 break;
753 default:
754 goto invalid;
756 ++end;
757 while (isspace ((unsigned char) *end))
758 ++end;
759 if (*end != '\0')
760 goto invalid;
763 if (((value << shift) >> shift) != value)
764 goto invalid;
766 *pvalue = value << shift;
767 return true;
769 invalid:
770 gomp_error ("Invalid value for environment variable %s", name);
771 return false;
774 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
775 present and it was successfully parsed. */
777 static bool
778 parse_spincount (const char *name, unsigned long long *pvalue)
780 char *env, *end;
781 unsigned long long value, mult = 1;
783 env = getenv (name);
784 if (env == NULL)
785 return false;
787 while (isspace ((unsigned char) *env))
788 ++env;
789 if (*env == '\0')
790 goto invalid;
792 if (strncasecmp (env, "infinite", 8) == 0
793 || strncasecmp (env, "infinity", 8) == 0)
795 value = ~0ULL;
796 end = env + 8;
797 goto check_tail;
800 errno = 0;
801 value = strtoull (env, &end, 10);
802 if (errno)
803 goto invalid;
805 while (isspace ((unsigned char) *end))
806 ++end;
807 if (*end != '\0')
809 switch (tolower ((unsigned char) *end))
811 case 'k':
812 mult = 1000LL;
813 break;
814 case 'm':
815 mult = 1000LL * 1000LL;
816 break;
817 case 'g':
818 mult = 1000LL * 1000LL * 1000LL;
819 break;
820 case 't':
821 mult = 1000LL * 1000LL * 1000LL * 1000LL;
822 break;
823 default:
824 goto invalid;
826 ++end;
827 check_tail:
828 while (isspace ((unsigned char) *end))
829 ++end;
830 if (*end != '\0')
831 goto invalid;
834 if (value > ~0ULL / mult)
835 value = ~0ULL;
836 else
837 value *= mult;
839 *pvalue = value;
840 return true;
842 invalid:
843 gomp_error ("Invalid value for environment variable %s", name);
844 return false;
847 /* Parse a boolean value for environment variable NAME and store the
848 result in VALUE. */
850 static void
851 parse_boolean (const char *name, bool *value)
853 const char *env;
855 env = getenv (name);
856 if (env == NULL)
857 return;
859 while (isspace ((unsigned char) *env))
860 ++env;
861 if (strncasecmp (env, "true", 4) == 0)
863 *value = true;
864 env += 4;
866 else if (strncasecmp (env, "false", 5) == 0)
868 *value = false;
869 env += 5;
871 else
872 env = "X";
873 while (isspace ((unsigned char) *env))
874 ++env;
875 if (*env != '\0')
876 gomp_error ("Invalid value for environment variable %s", name);
879 /* Parse the OMP_WAIT_POLICY environment variable and store the
880 result in gomp_active_wait_policy. */
882 static int
883 parse_wait_policy (void)
885 const char *env;
886 int ret = -1;
888 env = getenv ("OMP_WAIT_POLICY");
889 if (env == NULL)
890 return -1;
892 while (isspace ((unsigned char) *env))
893 ++env;
894 if (strncasecmp (env, "active", 6) == 0)
896 ret = 1;
897 env += 6;
899 else if (strncasecmp (env, "passive", 7) == 0)
901 ret = 0;
902 env += 7;
904 else
905 env = "X";
906 while (isspace ((unsigned char) *env))
907 ++env;
908 if (*env == '\0')
909 return ret;
910 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
911 return -1;
914 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
915 present and it was successfully parsed. */
917 static bool
918 parse_affinity (bool ignore)
920 char *env, *end, *start;
921 int pass;
922 unsigned long cpu_beg, cpu_end, cpu_stride;
923 size_t count = 0, needed;
925 env = getenv ("GOMP_CPU_AFFINITY");
926 if (env == NULL)
927 return false;
929 start = env;
930 for (pass = 0; pass < 2; pass++)
932 env = start;
933 if (pass == 1)
935 if (ignore)
936 return false;
938 gomp_places_list_len = 0;
939 gomp_places_list = gomp_affinity_alloc (count, true);
940 if (gomp_places_list == NULL)
941 return false;
945 while (isspace ((unsigned char) *env))
946 ++env;
948 errno = 0;
949 cpu_beg = strtoul (env, &end, 0);
950 if (errno || cpu_beg >= 65536)
951 goto invalid;
952 cpu_end = cpu_beg;
953 cpu_stride = 1;
955 env = end;
956 if (*env == '-')
958 errno = 0;
959 cpu_end = strtoul (++env, &end, 0);
960 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
961 goto invalid;
963 env = end;
964 if (*env == ':')
966 errno = 0;
967 cpu_stride = strtoul (++env, &end, 0);
968 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
969 goto invalid;
971 env = end;
975 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
976 if (pass == 0)
977 count += needed;
978 else
980 while (needed--)
982 void *p = gomp_places_list[gomp_places_list_len];
983 gomp_affinity_init_place (p);
984 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
985 ++gomp_places_list_len;
986 cpu_beg += cpu_stride;
990 while (isspace ((unsigned char) *env))
991 ++env;
993 if (*env == ',')
994 env++;
995 else if (*env == '\0')
996 break;
998 while (1);
1001 if (gomp_places_list_len == 0)
1003 free (gomp_places_list);
1004 gomp_places_list = NULL;
1005 return false;
1007 return true;
1009 invalid:
1010 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1011 return false;
1015 static void
1016 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1018 const char *env;
1019 bool display = false;
1020 bool verbose = false;
1021 int i;
1023 env = getenv ("OMP_DISPLAY_ENV");
1024 if (env == NULL)
1025 return;
1027 while (isspace ((unsigned char) *env))
1028 ++env;
1029 if (strncasecmp (env, "true", 4) == 0)
1031 display = true;
1032 env += 4;
1034 else if (strncasecmp (env, "false", 5) == 0)
1036 display = false;
1037 env += 5;
1039 else if (strncasecmp (env, "verbose", 7) == 0)
1041 display = true;
1042 verbose = true;
1043 env += 7;
1045 else
1046 env = "X";
1047 while (isspace ((unsigned char) *env))
1048 ++env;
1049 if (*env != '\0')
1050 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1052 if (!display)
1053 return;
1055 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1057 fputs (" _OPENMP = '201307'\n", stderr);
1058 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1059 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1060 fprintf (stderr, " OMP_NESTED = '%s'\n",
1061 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1063 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1064 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1065 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1066 fputs ("'\n", stderr);
1068 fprintf (stderr, " OMP_SCHEDULE = '");
1069 switch (gomp_global_icv.run_sched_var)
1071 case GFS_RUNTIME:
1072 fputs ("RUNTIME", stderr);
1073 break;
1074 case GFS_STATIC:
1075 fputs ("STATIC", stderr);
1076 break;
1077 case GFS_DYNAMIC:
1078 fputs ("DYNAMIC", stderr);
1079 break;
1080 case GFS_GUIDED:
1081 fputs ("GUIDED", stderr);
1082 break;
1083 case GFS_AUTO:
1084 fputs ("AUTO", stderr);
1085 break;
1087 fputs ("'\n", stderr);
1089 fputs (" OMP_PROC_BIND = '", stderr);
1090 switch (gomp_global_icv.bind_var)
1092 case omp_proc_bind_false:
1093 fputs ("FALSE", stderr);
1094 break;
1095 case omp_proc_bind_true:
1096 fputs ("TRUE", stderr);
1097 break;
1098 case omp_proc_bind_master:
1099 fputs ("MASTER", stderr);
1100 break;
1101 case omp_proc_bind_close:
1102 fputs ("CLOSE", stderr);
1103 break;
1104 case omp_proc_bind_spread:
1105 fputs ("SPREAD", stderr);
1106 break;
1108 for (i = 1; i < gomp_bind_var_list_len; i++)
1109 switch (gomp_bind_var_list[i])
1111 case omp_proc_bind_master:
1112 fputs (",MASTER", stderr);
1113 break;
1114 case omp_proc_bind_close:
1115 fputs (",CLOSE", stderr);
1116 break;
1117 case omp_proc_bind_spread:
1118 fputs (",SPREAD", stderr);
1119 break;
1121 fputs ("'\n", stderr);
1122 fputs (" OMP_PLACES = '", stderr);
1123 for (i = 0; i < gomp_places_list_len; i++)
1125 fputs ("{", stderr);
1126 gomp_affinity_print_place (gomp_places_list[i]);
1127 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1129 fputs ("'\n", stderr);
1131 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1133 /* GOMP's default value is actually neither active nor passive. */
1134 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1135 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1136 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1137 gomp_global_icv.thread_limit_var);
1138 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1139 gomp_max_active_levels_var);
1141 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1142 gomp_cancel_var ? "TRUE" : "FALSE");
1143 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1144 gomp_global_icv.default_device_var);
1146 if (verbose)
1148 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1149 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1150 #ifdef HAVE_INTTYPES_H
1151 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1152 (uint64_t) gomp_spin_count_var);
1153 #else
1154 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1155 (unsigned long) gomp_spin_count_var);
1156 #endif
1159 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1163 static void __attribute__((constructor))
1164 initialize_env (void)
1166 unsigned long thread_limit_var, stacksize;
1167 int wait_policy;
1169 /* Do a compile time check that mkomp_h.pl did good job. */
1170 omp_check_defines ();
1172 parse_schedule ();
1173 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1174 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1175 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1176 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1177 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1178 true);
1179 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1181 gomp_global_icv.thread_limit_var
1182 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1184 #ifndef HAVE_SYNC_BUILTINS
1185 gomp_mutex_init (&gomp_managed_threads_lock);
1186 #endif
1187 gomp_init_num_threads ();
1188 gomp_available_cpus = gomp_global_icv.nthreads_var;
1189 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1190 &gomp_global_icv.nthreads_var,
1191 &gomp_nthreads_var_list,
1192 &gomp_nthreads_var_list_len))
1193 gomp_global_icv.nthreads_var = gomp_available_cpus;
1194 bool ignore = false;
1195 if (parse_bind_var ("OMP_PROC_BIND",
1196 &gomp_global_icv.bind_var,
1197 &gomp_bind_var_list,
1198 &gomp_bind_var_list_len)
1199 && gomp_global_icv.bind_var == omp_proc_bind_false)
1200 ignore = true;
1201 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1202 parsed if present in the environment. If OMP_PROC_BIND was set
1203 explictly to false, don't populate places list though. If places
1204 list was successfully set from OMP_PLACES, only parse but don't process
1205 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1206 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1207 was successfully parsed into a places list, otherwise to
1208 OMP_PROC_BIND=false. */
1209 if (parse_places_var ("OMP_PLACES", ignore))
1211 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1212 gomp_global_icv.bind_var = true;
1213 ignore = true;
1215 if (parse_affinity (ignore))
1217 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1218 gomp_global_icv.bind_var = true;
1219 ignore = true;
1221 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1222 gomp_init_affinity ();
1223 wait_policy = parse_wait_policy ();
1224 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1226 /* Using a rough estimation of 100000 spins per msec,
1227 use 5 min blocking for OMP_WAIT_POLICY=active,
1228 3 msec blocking when OMP_WAIT_POLICY is not specificed
1229 and 0 when OMP_WAIT_POLICY=passive.
1230 Depending on the CPU speed, this can be e.g. 5 times longer
1231 or 5 times shorter. */
1232 if (wait_policy > 0)
1233 gomp_spin_count_var = 30000000000LL;
1234 else if (wait_policy < 0)
1235 gomp_spin_count_var = 300000LL;
1237 /* gomp_throttled_spin_count_var is used when there are more libgomp
1238 managed threads than available CPUs. Use very short spinning. */
1239 if (wait_policy > 0)
1240 gomp_throttled_spin_count_var = 1000LL;
1241 else if (wait_policy < 0)
1242 gomp_throttled_spin_count_var = 100LL;
1243 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1244 gomp_throttled_spin_count_var = gomp_spin_count_var;
1246 /* Not strictly environment related, but ordering constructors is tricky. */
1247 pthread_attr_init (&gomp_thread_attr);
1248 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
1250 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1251 || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
1253 int err;
1255 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1257 #ifdef PTHREAD_STACK_MIN
1258 if (err == EINVAL)
1260 if (stacksize < PTHREAD_STACK_MIN)
1261 gomp_error ("Stack size less than minimum of %luk",
1262 PTHREAD_STACK_MIN / 1024ul
1263 + (PTHREAD_STACK_MIN % 1024 != 0));
1264 else
1265 gomp_error ("Stack size larger than system limit");
1267 else
1268 #endif
1269 if (err != 0)
1270 gomp_error ("Stack size change failed: %s", strerror (err));
1273 handle_omp_display_env (stacksize, wait_policy);
1277 /* The public OpenMP API routines that access these variables. */
1279 void
1280 omp_set_num_threads (int n)
1282 struct gomp_task_icv *icv = gomp_icv (true);
1283 icv->nthreads_var = (n > 0 ? n : 1);
1286 void
1287 omp_set_dynamic (int val)
1289 struct gomp_task_icv *icv = gomp_icv (true);
1290 icv->dyn_var = val;
1294 omp_get_dynamic (void)
1296 struct gomp_task_icv *icv = gomp_icv (false);
1297 return icv->dyn_var;
1300 void
1301 omp_set_nested (int val)
1303 struct gomp_task_icv *icv = gomp_icv (true);
1304 icv->nest_var = val;
1308 omp_get_nested (void)
1310 struct gomp_task_icv *icv = gomp_icv (false);
1311 return icv->nest_var;
1314 void
1315 omp_set_schedule (omp_sched_t kind, int modifier)
1317 struct gomp_task_icv *icv = gomp_icv (true);
1318 switch (kind)
1320 case omp_sched_static:
1321 if (modifier < 1)
1322 modifier = 0;
1323 icv->run_sched_modifier = modifier;
1324 break;
1325 case omp_sched_dynamic:
1326 case omp_sched_guided:
1327 if (modifier < 1)
1328 modifier = 1;
1329 icv->run_sched_modifier = modifier;
1330 break;
1331 case omp_sched_auto:
1332 break;
1333 default:
1334 return;
1336 icv->run_sched_var = kind;
1339 void
1340 omp_get_schedule (omp_sched_t *kind, int *modifier)
1342 struct gomp_task_icv *icv = gomp_icv (false);
1343 *kind = icv->run_sched_var;
1344 *modifier = icv->run_sched_modifier;
1348 omp_get_max_threads (void)
1350 struct gomp_task_icv *icv = gomp_icv (false);
1351 return icv->nthreads_var;
1355 omp_get_thread_limit (void)
1357 struct gomp_task_icv *icv = gomp_icv (false);
1358 return icv->thread_limit_var > INT_MAX ? INT_MAX : icv->thread_limit_var;
1361 void
1362 omp_set_max_active_levels (int max_levels)
1364 if (max_levels >= 0)
1365 gomp_max_active_levels_var = max_levels;
1369 omp_get_max_active_levels (void)
1371 return gomp_max_active_levels_var;
1375 omp_get_cancellation (void)
1377 return gomp_cancel_var;
1380 omp_proc_bind_t
1381 omp_get_proc_bind (void)
1383 struct gomp_task_icv *icv = gomp_icv (false);
1384 return icv->bind_var;
1387 void
1388 omp_set_default_device (int device_num)
1390 struct gomp_task_icv *icv = gomp_icv (true);
1391 icv->default_device_var = device_num >= 0 ? device_num : 0;
1395 omp_get_default_device (void)
1397 struct gomp_task_icv *icv = gomp_icv (false);
1398 return icv->default_device_var;
1402 omp_get_num_devices (void)
1404 return gomp_get_num_devices ();
1408 omp_get_num_teams (void)
1410 /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */
1411 return 1;
1415 omp_get_team_num (void)
1417 /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */
1418 return 0;
1422 omp_is_initial_device (void)
1424 /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */
1425 return 1;
1428 ialias (omp_set_dynamic)
1429 ialias (omp_set_nested)
1430 ialias (omp_set_num_threads)
1431 ialias (omp_get_dynamic)
1432 ialias (omp_get_nested)
1433 ialias (omp_set_schedule)
1434 ialias (omp_get_schedule)
1435 ialias (omp_get_max_threads)
1436 ialias (omp_get_thread_limit)
1437 ialias (omp_set_max_active_levels)
1438 ialias (omp_get_max_active_levels)
1439 ialias (omp_get_cancellation)
1440 ialias (omp_get_proc_bind)
1441 ialias (omp_set_default_device)
1442 ialias (omp_get_default_device)
1443 ialias (omp_get_num_devices)
1444 ialias (omp_get_num_teams)
1445 ialias (omp_get_team_num)
1446 ialias (omp_is_initial_device)