gcc/
[official-gcc.git] / libgomp / env.c
blob6b5e963c4ea300fa12c7d0a73f6903746e6a0b83
1 /* Copyright (C) 2005-2015 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 "libgomp_f.h"
31 #include "oacc-int.h"
32 #include <ctype.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #ifdef HAVE_INTTYPES_H
36 # include <inttypes.h> /* For PRIu64. */
37 #endif
38 #ifdef STRING_WITH_STRINGS
39 # include <string.h>
40 # include <strings.h>
41 #else
42 # ifdef HAVE_STRING_H
43 # include <string.h>
44 # else
45 # ifdef HAVE_STRINGS_H
46 # include <strings.h>
47 # endif
48 # endif
49 #endif
50 #include <limits.h>
51 #include <errno.h>
53 #ifndef HAVE_STRTOULL
54 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
55 #endif
57 struct gomp_task_icv gomp_global_icv = {
58 .nthreads_var = 1,
59 .thread_limit_var = UINT_MAX,
60 .run_sched_var = GFS_DYNAMIC,
61 .run_sched_modifier = 1,
62 .default_device_var = 0,
63 .dyn_var = false,
64 .nest_var = false,
65 .bind_var = omp_proc_bind_false,
66 .target_data = NULL
69 unsigned long gomp_max_active_levels_var = INT_MAX;
70 bool gomp_cancel_var = false;
71 #ifndef HAVE_SYNC_BUILTINS
72 gomp_mutex_t gomp_managed_threads_lock;
73 #endif
74 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
75 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
76 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
77 char *gomp_bind_var_list;
78 unsigned long gomp_bind_var_list_len;
79 void **gomp_places_list;
80 unsigned long gomp_places_list_len;
81 int gomp_debug_var;
82 char *goacc_device_type;
83 int goacc_device_num;
85 /* Parse the OMP_SCHEDULE environment variable. */
87 static void
88 parse_schedule (void)
90 char *env, *end;
91 unsigned long value;
93 env = getenv ("OMP_SCHEDULE");
94 if (env == NULL)
95 return;
97 while (isspace ((unsigned char) *env))
98 ++env;
99 if (strncasecmp (env, "static", 6) == 0)
101 gomp_global_icv.run_sched_var = GFS_STATIC;
102 env += 6;
104 else if (strncasecmp (env, "dynamic", 7) == 0)
106 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
107 env += 7;
109 else if (strncasecmp (env, "guided", 6) == 0)
111 gomp_global_icv.run_sched_var = GFS_GUIDED;
112 env += 6;
114 else if (strncasecmp (env, "auto", 4) == 0)
116 gomp_global_icv.run_sched_var = GFS_AUTO;
117 env += 4;
119 else
120 goto unknown;
122 while (isspace ((unsigned char) *env))
123 ++env;
124 if (*env == '\0')
126 gomp_global_icv.run_sched_modifier
127 = gomp_global_icv.run_sched_var != GFS_STATIC;
128 return;
130 if (*env++ != ',')
131 goto unknown;
132 while (isspace ((unsigned char) *env))
133 ++env;
134 if (*env == '\0')
135 goto invalid;
137 errno = 0;
138 value = strtoul (env, &end, 10);
139 if (errno)
140 goto invalid;
142 while (isspace ((unsigned char) *end))
143 ++end;
144 if (*end != '\0')
145 goto invalid;
147 if ((int)value != value)
148 goto invalid;
150 if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
151 value = 1;
152 gomp_global_icv.run_sched_modifier = value;
153 return;
155 unknown:
156 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
157 return;
159 invalid:
160 gomp_error ("Invalid value for chunk size in "
161 "environment variable OMP_SCHEDULE");
162 return;
165 /* Parse an unsigned long environment variable. Return true if one was
166 present and it was successfully parsed. */
168 static bool
169 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
171 char *env, *end;
172 unsigned long value;
174 env = getenv (name);
175 if (env == NULL)
176 return false;
178 while (isspace ((unsigned char) *env))
179 ++env;
180 if (*env == '\0')
181 goto invalid;
183 errno = 0;
184 value = strtoul (env, &end, 10);
185 if (errno || (long) value <= 0 - allow_zero)
186 goto invalid;
188 while (isspace ((unsigned char) *end))
189 ++end;
190 if (*end != '\0')
191 goto invalid;
193 *pvalue = value;
194 return true;
196 invalid:
197 gomp_error ("Invalid value for environment variable %s", name);
198 return false;
201 /* Parse a positive int environment variable. Return true if one was
202 present and it was successfully parsed. */
204 static bool
205 parse_int (const char *name, int *pvalue, bool allow_zero)
207 unsigned long value;
208 if (!parse_unsigned_long (name, &value, allow_zero))
209 return false;
210 if (value > INT_MAX)
212 gomp_error ("Invalid value for environment variable %s", name);
213 return false;
215 *pvalue = (int) value;
216 return true;
219 /* Parse an unsigned long list environment variable. Return true if one was
220 present and it was successfully parsed. */
222 static bool
223 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
224 unsigned long **pvalues,
225 unsigned long *pnvalues)
227 char *env, *end;
228 unsigned long value, *values = NULL;
230 env = getenv (name);
231 if (env == NULL)
232 return false;
234 while (isspace ((unsigned char) *env))
235 ++env;
236 if (*env == '\0')
237 goto invalid;
239 errno = 0;
240 value = strtoul (env, &end, 10);
241 if (errno || (long) value <= 0)
242 goto invalid;
244 while (isspace ((unsigned char) *end))
245 ++end;
246 if (*end != '\0')
248 if (*end == ',')
250 unsigned long nvalues = 0, nalloced = 0;
254 env = end + 1;
255 if (nvalues == nalloced)
257 unsigned long *n;
258 nalloced = nalloced ? nalloced * 2 : 16;
259 n = realloc (values, nalloced * sizeof (unsigned long));
260 if (n == NULL)
262 free (values);
263 gomp_error ("Out of memory while trying to parse"
264 " environment variable %s", name);
265 return false;
267 values = n;
268 if (nvalues == 0)
269 values[nvalues++] = value;
272 while (isspace ((unsigned char) *env))
273 ++env;
274 if (*env == '\0')
275 goto invalid;
277 errno = 0;
278 value = strtoul (env, &end, 10);
279 if (errno || (long) value <= 0)
280 goto invalid;
282 values[nvalues++] = value;
283 while (isspace ((unsigned char) *end))
284 ++end;
285 if (*end == '\0')
286 break;
287 if (*end != ',')
288 goto invalid;
290 while (1);
291 *p1stvalue = values[0];
292 *pvalues = values;
293 *pnvalues = nvalues;
294 return true;
296 goto invalid;
299 *p1stvalue = value;
300 return true;
302 invalid:
303 free (values);
304 gomp_error ("Invalid value for environment variable %s", name);
305 return false;
308 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
309 enum values. Return true if one was present and it was successfully
310 parsed. */
312 static bool
313 parse_bind_var (const char *name, char *p1stvalue,
314 char **pvalues, unsigned long *pnvalues)
316 char *env;
317 char value = omp_proc_bind_false, *values = NULL;
318 int i;
319 static struct proc_bind_kinds
321 const char name[7];
322 const char len;
323 omp_proc_bind_t kind;
324 } kinds[] =
326 { "false", 5, omp_proc_bind_false },
327 { "true", 4, omp_proc_bind_true },
328 { "master", 6, omp_proc_bind_master },
329 { "close", 5, omp_proc_bind_close },
330 { "spread", 6, omp_proc_bind_spread }
333 env = getenv (name);
334 if (env == NULL)
335 return false;
337 while (isspace ((unsigned char) *env))
338 ++env;
339 if (*env == '\0')
340 goto invalid;
342 for (i = 0; i < 5; i++)
343 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
345 value = kinds[i].kind;
346 env += kinds[i].len;
347 break;
349 if (i == 5)
350 goto invalid;
352 while (isspace ((unsigned char) *env))
353 ++env;
354 if (*env != '\0')
356 if (*env == ',')
358 unsigned long nvalues = 0, nalloced = 0;
360 if (value == omp_proc_bind_false
361 || value == omp_proc_bind_true)
362 goto invalid;
366 env++;
367 if (nvalues == nalloced)
369 char *n;
370 nalloced = nalloced ? nalloced * 2 : 16;
371 n = realloc (values, nalloced);
372 if (n == NULL)
374 free (values);
375 gomp_error ("Out of memory while trying to parse"
376 " environment variable %s", name);
377 return false;
379 values = n;
380 if (nvalues == 0)
381 values[nvalues++] = value;
384 while (isspace ((unsigned char) *env))
385 ++env;
386 if (*env == '\0')
387 goto invalid;
389 for (i = 2; i < 5; i++)
390 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
392 value = kinds[i].kind;
393 env += kinds[i].len;
394 break;
396 if (i == 5)
397 goto invalid;
399 values[nvalues++] = value;
400 while (isspace ((unsigned char) *env))
401 ++env;
402 if (*env == '\0')
403 break;
404 if (*env != ',')
405 goto invalid;
407 while (1);
408 *p1stvalue = values[0];
409 *pvalues = values;
410 *pnvalues = nvalues;
411 return true;
413 goto invalid;
416 *p1stvalue = value;
417 return true;
419 invalid:
420 free (values);
421 gomp_error ("Invalid value for environment variable %s", name);
422 return false;
425 static bool
426 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
427 long *stridep)
429 char *env = *envp, *start;
430 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
431 unsigned long len = 1;
432 long stride = 1;
433 int pass;
434 bool any_negate = false;
435 *negatep = false;
436 while (isspace ((unsigned char) *env))
437 ++env;
438 if (*env == '!')
440 *negatep = true;
441 ++env;
442 while (isspace ((unsigned char) *env))
443 ++env;
445 if (*env != '{')
446 return false;
447 ++env;
448 while (isspace ((unsigned char) *env))
449 ++env;
450 start = env;
451 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
453 env = start;
456 unsigned long this_num, this_len = 1;
457 long this_stride = 1;
458 bool this_negate = (*env == '!');
459 if (this_negate)
461 if (gomp_places_list)
462 any_negate = true;
463 ++env;
464 while (isspace ((unsigned char) *env))
465 ++env;
468 errno = 0;
469 this_num = strtoul (env, &env, 10);
470 if (errno)
471 return false;
472 while (isspace ((unsigned char) *env))
473 ++env;
474 if (*env == ':')
476 ++env;
477 while (isspace ((unsigned char) *env))
478 ++env;
479 errno = 0;
480 this_len = strtoul (env, &env, 10);
481 if (errno || this_len == 0)
482 return false;
483 while (isspace ((unsigned char) *env))
484 ++env;
485 if (*env == ':')
487 ++env;
488 while (isspace ((unsigned char) *env))
489 ++env;
490 errno = 0;
491 this_stride = strtol (env, &env, 10);
492 if (errno)
493 return false;
494 while (isspace ((unsigned char) *env))
495 ++env;
498 if (this_negate && this_len != 1)
499 return false;
500 if (gomp_places_list && pass == this_negate)
502 if (this_negate)
504 if (!gomp_affinity_remove_cpu (p, this_num))
505 return false;
507 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
508 this_stride, false))
509 return false;
511 if (*env == '}')
512 break;
513 if (*env != ',')
514 return false;
515 ++env;
517 while (1);
520 ++env;
521 while (isspace ((unsigned char) *env))
522 ++env;
523 if (*env == ':')
525 ++env;
526 while (isspace ((unsigned char) *env))
527 ++env;
528 errno = 0;
529 len = strtoul (env, &env, 10);
530 if (errno || len == 0 || len >= 65536)
531 return false;
532 while (isspace ((unsigned char) *env))
533 ++env;
534 if (*env == ':')
536 ++env;
537 while (isspace ((unsigned char) *env))
538 ++env;
539 errno = 0;
540 stride = strtol (env, &env, 10);
541 if (errno)
542 return false;
543 while (isspace ((unsigned char) *env))
544 ++env;
547 if (*negatep && len != 1)
548 return false;
549 *envp = env;
550 *lenp = len;
551 *stridep = stride;
552 return true;
555 static bool
556 parse_places_var (const char *name, bool ignore)
558 char *env = getenv (name), *end;
559 bool any_negate = false;
560 int level = 0;
561 unsigned long count = 0;
562 if (env == NULL)
563 return false;
565 while (isspace ((unsigned char) *env))
566 ++env;
567 if (*env == '\0')
568 goto invalid;
570 if (strncasecmp (env, "threads", 7) == 0)
572 env += 7;
573 level = 1;
575 else if (strncasecmp (env, "cores", 5) == 0)
577 env += 5;
578 level = 2;
580 else if (strncasecmp (env, "sockets", 7) == 0)
582 env += 7;
583 level = 3;
585 if (level)
587 count = ULONG_MAX;
588 while (isspace ((unsigned char) *env))
589 ++env;
590 if (*env != '\0')
592 if (*env++ != '(')
593 goto invalid;
594 while (isspace ((unsigned char) *env))
595 ++env;
597 errno = 0;
598 count = strtoul (env, &end, 10);
599 if (errno)
600 goto invalid;
601 env = end;
602 while (isspace ((unsigned char) *env))
603 ++env;
604 if (*env != ')')
605 goto invalid;
606 ++env;
607 while (isspace ((unsigned char) *env))
608 ++env;
609 if (*env != '\0')
610 goto invalid;
613 if (ignore)
614 return false;
616 return gomp_affinity_init_level (level, count, false);
619 count = 0;
620 end = env;
623 bool negate;
624 unsigned long len;
625 long stride;
626 if (!parse_one_place (&end, &negate, &len, &stride))
627 goto invalid;
628 if (negate)
630 if (!any_negate)
631 count++;
632 any_negate = true;
634 else
635 count += len;
636 if (count > 65536)
637 goto invalid;
638 if (*end == '\0')
639 break;
640 if (*end != ',')
641 goto invalid;
642 end++;
644 while (1);
646 if (ignore)
647 return false;
649 gomp_places_list_len = 0;
650 gomp_places_list = gomp_affinity_alloc (count, false);
651 if (gomp_places_list == NULL)
652 return false;
656 bool negate;
657 unsigned long len;
658 long stride;
659 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
660 if (!parse_one_place (&env, &negate, &len, &stride))
661 goto invalid;
662 if (negate)
664 void *p;
665 for (count = 0; count < gomp_places_list_len; count++)
666 if (gomp_affinity_same_place
667 (gomp_places_list[count],
668 gomp_places_list[gomp_places_list_len]))
669 break;
670 if (count == gomp_places_list_len)
672 gomp_error ("Trying to remove a non-existing place from list "
673 "of places");
674 goto invalid;
676 p = gomp_places_list[count];
677 memmove (&gomp_places_list[count],
678 &gomp_places_list[count + 1],
679 (gomp_places_list_len - count - 1) * sizeof (void *));
680 --gomp_places_list_len;
681 gomp_places_list[gomp_places_list_len] = p;
683 else if (len == 1)
684 ++gomp_places_list_len;
685 else
687 for (count = 0; count < len - 1; count++)
688 if (!gomp_affinity_copy_place
689 (gomp_places_list[gomp_places_list_len + count + 1],
690 gomp_places_list[gomp_places_list_len + count],
691 stride))
692 goto invalid;
693 gomp_places_list_len += len;
695 if (*env == '\0')
696 break;
697 env++;
699 while (1);
701 if (gomp_places_list_len == 0)
703 gomp_error ("All places have been removed");
704 goto invalid;
706 if (!gomp_affinity_finalize_place_list (false))
707 goto invalid;
708 return true;
710 invalid:
711 free (gomp_places_list);
712 gomp_places_list = NULL;
713 gomp_places_list_len = 0;
714 gomp_error ("Invalid value for environment variable %s", name);
715 return false;
718 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
719 present and it was successfully parsed. */
721 static bool
722 parse_stacksize (const char *name, unsigned long *pvalue)
724 char *env, *end;
725 unsigned long value, shift = 10;
727 env = getenv (name);
728 if (env == NULL)
729 return false;
731 while (isspace ((unsigned char) *env))
732 ++env;
733 if (*env == '\0')
734 goto invalid;
736 errno = 0;
737 value = strtoul (env, &end, 10);
738 if (errno)
739 goto invalid;
741 while (isspace ((unsigned char) *end))
742 ++end;
743 if (*end != '\0')
745 switch (tolower ((unsigned char) *end))
747 case 'b':
748 shift = 0;
749 break;
750 case 'k':
751 break;
752 case 'm':
753 shift = 20;
754 break;
755 case 'g':
756 shift = 30;
757 break;
758 default:
759 goto invalid;
761 ++end;
762 while (isspace ((unsigned char) *end))
763 ++end;
764 if (*end != '\0')
765 goto invalid;
768 if (((value << shift) >> shift) != value)
769 goto invalid;
771 *pvalue = value << shift;
772 return true;
774 invalid:
775 gomp_error ("Invalid value for environment variable %s", name);
776 return false;
779 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
780 present and it was successfully parsed. */
782 static bool
783 parse_spincount (const char *name, unsigned long long *pvalue)
785 char *env, *end;
786 unsigned long long value, mult = 1;
788 env = getenv (name);
789 if (env == NULL)
790 return false;
792 while (isspace ((unsigned char) *env))
793 ++env;
794 if (*env == '\0')
795 goto invalid;
797 if (strncasecmp (env, "infinite", 8) == 0
798 || strncasecmp (env, "infinity", 8) == 0)
800 value = ~0ULL;
801 end = env + 8;
802 goto check_tail;
805 errno = 0;
806 value = strtoull (env, &end, 10);
807 if (errno)
808 goto invalid;
810 while (isspace ((unsigned char) *end))
811 ++end;
812 if (*end != '\0')
814 switch (tolower ((unsigned char) *end))
816 case 'k':
817 mult = 1000LL;
818 break;
819 case 'm':
820 mult = 1000LL * 1000LL;
821 break;
822 case 'g':
823 mult = 1000LL * 1000LL * 1000LL;
824 break;
825 case 't':
826 mult = 1000LL * 1000LL * 1000LL * 1000LL;
827 break;
828 default:
829 goto invalid;
831 ++end;
832 check_tail:
833 while (isspace ((unsigned char) *end))
834 ++end;
835 if (*end != '\0')
836 goto invalid;
839 if (value > ~0ULL / mult)
840 value = ~0ULL;
841 else
842 value *= mult;
844 *pvalue = value;
845 return true;
847 invalid:
848 gomp_error ("Invalid value for environment variable %s", name);
849 return false;
852 /* Parse a boolean value for environment variable NAME and store the
853 result in VALUE. */
855 static void
856 parse_boolean (const char *name, bool *value)
858 const char *env;
860 env = getenv (name);
861 if (env == NULL)
862 return;
864 while (isspace ((unsigned char) *env))
865 ++env;
866 if (strncasecmp (env, "true", 4) == 0)
868 *value = true;
869 env += 4;
871 else if (strncasecmp (env, "false", 5) == 0)
873 *value = false;
874 env += 5;
876 else
877 env = "X";
878 while (isspace ((unsigned char) *env))
879 ++env;
880 if (*env != '\0')
881 gomp_error ("Invalid value for environment variable %s", name);
884 /* Parse the OMP_WAIT_POLICY environment variable and store the
885 result in gomp_active_wait_policy. */
887 static int
888 parse_wait_policy (void)
890 const char *env;
891 int ret = -1;
893 env = getenv ("OMP_WAIT_POLICY");
894 if (env == NULL)
895 return -1;
897 while (isspace ((unsigned char) *env))
898 ++env;
899 if (strncasecmp (env, "active", 6) == 0)
901 ret = 1;
902 env += 6;
904 else if (strncasecmp (env, "passive", 7) == 0)
906 ret = 0;
907 env += 7;
909 else
910 env = "X";
911 while (isspace ((unsigned char) *env))
912 ++env;
913 if (*env == '\0')
914 return ret;
915 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
916 return -1;
919 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
920 present and it was successfully parsed. */
922 static bool
923 parse_affinity (bool ignore)
925 char *env, *end, *start;
926 int pass;
927 unsigned long cpu_beg, cpu_end, cpu_stride;
928 size_t count = 0, needed;
930 env = getenv ("GOMP_CPU_AFFINITY");
931 if (env == NULL)
932 return false;
934 start = env;
935 for (pass = 0; pass < 2; pass++)
937 env = start;
938 if (pass == 1)
940 if (ignore)
941 return false;
943 gomp_places_list_len = 0;
944 gomp_places_list = gomp_affinity_alloc (count, true);
945 if (gomp_places_list == NULL)
946 return false;
950 while (isspace ((unsigned char) *env))
951 ++env;
953 errno = 0;
954 cpu_beg = strtoul (env, &end, 0);
955 if (errno || cpu_beg >= 65536)
956 goto invalid;
957 cpu_end = cpu_beg;
958 cpu_stride = 1;
960 env = end;
961 if (*env == '-')
963 errno = 0;
964 cpu_end = strtoul (++env, &end, 0);
965 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
966 goto invalid;
968 env = end;
969 if (*env == ':')
971 errno = 0;
972 cpu_stride = strtoul (++env, &end, 0);
973 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
974 goto invalid;
976 env = end;
980 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
981 if (pass == 0)
982 count += needed;
983 else
985 while (needed--)
987 void *p = gomp_places_list[gomp_places_list_len];
988 gomp_affinity_init_place (p);
989 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
990 ++gomp_places_list_len;
991 cpu_beg += cpu_stride;
995 while (isspace ((unsigned char) *env))
996 ++env;
998 if (*env == ',')
999 env++;
1000 else if (*env == '\0')
1001 break;
1003 while (1);
1006 if (gomp_places_list_len == 0)
1008 free (gomp_places_list);
1009 gomp_places_list = NULL;
1010 return false;
1012 return true;
1014 invalid:
1015 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1016 return false;
1019 static void
1020 parse_acc_device_type (void)
1022 const char *env = getenv ("ACC_DEVICE_TYPE");
1024 if (env && *env != '\0')
1025 goacc_device_type = strdup (env);
1026 else
1027 goacc_device_type = NULL;
1030 static void
1031 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1033 const char *env;
1034 bool display = false;
1035 bool verbose = false;
1036 int i;
1038 env = getenv ("OMP_DISPLAY_ENV");
1039 if (env == NULL)
1040 return;
1042 while (isspace ((unsigned char) *env))
1043 ++env;
1044 if (strncasecmp (env, "true", 4) == 0)
1046 display = true;
1047 env += 4;
1049 else if (strncasecmp (env, "false", 5) == 0)
1051 display = false;
1052 env += 5;
1054 else if (strncasecmp (env, "verbose", 7) == 0)
1056 display = true;
1057 verbose = true;
1058 env += 7;
1060 else
1061 env = "X";
1062 while (isspace ((unsigned char) *env))
1063 ++env;
1064 if (*env != '\0')
1065 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1067 if (!display)
1068 return;
1070 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1072 fputs (" _OPENMP = '201307'\n", stderr);
1073 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1074 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1075 fprintf (stderr, " OMP_NESTED = '%s'\n",
1076 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1078 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1079 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1080 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1081 fputs ("'\n", stderr);
1083 fprintf (stderr, " OMP_SCHEDULE = '");
1084 switch (gomp_global_icv.run_sched_var)
1086 case GFS_RUNTIME:
1087 fputs ("RUNTIME", stderr);
1088 break;
1089 case GFS_STATIC:
1090 fputs ("STATIC", stderr);
1091 break;
1092 case GFS_DYNAMIC:
1093 fputs ("DYNAMIC", stderr);
1094 break;
1095 case GFS_GUIDED:
1096 fputs ("GUIDED", stderr);
1097 break;
1098 case GFS_AUTO:
1099 fputs ("AUTO", stderr);
1100 break;
1102 fputs ("'\n", stderr);
1104 fputs (" OMP_PROC_BIND = '", stderr);
1105 switch (gomp_global_icv.bind_var)
1107 case omp_proc_bind_false:
1108 fputs ("FALSE", stderr);
1109 break;
1110 case omp_proc_bind_true:
1111 fputs ("TRUE", stderr);
1112 break;
1113 case omp_proc_bind_master:
1114 fputs ("MASTER", stderr);
1115 break;
1116 case omp_proc_bind_close:
1117 fputs ("CLOSE", stderr);
1118 break;
1119 case omp_proc_bind_spread:
1120 fputs ("SPREAD", stderr);
1121 break;
1123 for (i = 1; i < gomp_bind_var_list_len; i++)
1124 switch (gomp_bind_var_list[i])
1126 case omp_proc_bind_master:
1127 fputs (",MASTER", stderr);
1128 break;
1129 case omp_proc_bind_close:
1130 fputs (",CLOSE", stderr);
1131 break;
1132 case omp_proc_bind_spread:
1133 fputs (",SPREAD", stderr);
1134 break;
1136 fputs ("'\n", stderr);
1137 fputs (" OMP_PLACES = '", stderr);
1138 for (i = 0; i < gomp_places_list_len; i++)
1140 fputs ("{", stderr);
1141 gomp_affinity_print_place (gomp_places_list[i]);
1142 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1144 fputs ("'\n", stderr);
1146 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1148 /* GOMP's default value is actually neither active nor passive. */
1149 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1150 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1151 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1152 gomp_global_icv.thread_limit_var);
1153 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1154 gomp_max_active_levels_var);
1156 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1157 gomp_cancel_var ? "TRUE" : "FALSE");
1158 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1159 gomp_global_icv.default_device_var);
1161 if (verbose)
1163 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1164 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1165 #ifdef HAVE_INTTYPES_H
1166 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1167 (uint64_t) gomp_spin_count_var);
1168 #else
1169 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1170 (unsigned long) gomp_spin_count_var);
1171 #endif
1174 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1178 static void __attribute__((constructor))
1179 initialize_env (void)
1181 unsigned long thread_limit_var, stacksize;
1182 int wait_policy;
1184 /* Do a compile time check that mkomp_h.pl did good job. */
1185 omp_check_defines ();
1187 parse_schedule ();
1188 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1189 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1190 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1191 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1192 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1193 true);
1194 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1196 gomp_global_icv.thread_limit_var
1197 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1199 parse_int ("GOMP_DEBUG", &gomp_debug_var, true);
1200 #ifndef HAVE_SYNC_BUILTINS
1201 gomp_mutex_init (&gomp_managed_threads_lock);
1202 #endif
1203 gomp_init_num_threads ();
1204 gomp_available_cpus = gomp_global_icv.nthreads_var;
1205 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1206 &gomp_global_icv.nthreads_var,
1207 &gomp_nthreads_var_list,
1208 &gomp_nthreads_var_list_len))
1209 gomp_global_icv.nthreads_var = gomp_available_cpus;
1210 bool ignore = false;
1211 if (parse_bind_var ("OMP_PROC_BIND",
1212 &gomp_global_icv.bind_var,
1213 &gomp_bind_var_list,
1214 &gomp_bind_var_list_len)
1215 && gomp_global_icv.bind_var == omp_proc_bind_false)
1216 ignore = true;
1217 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1218 parsed if present in the environment. If OMP_PROC_BIND was set
1219 explictly to false, don't populate places list though. If places
1220 list was successfully set from OMP_PLACES, only parse but don't process
1221 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1222 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1223 was successfully parsed into a places list, otherwise to
1224 OMP_PROC_BIND=false. */
1225 if (parse_places_var ("OMP_PLACES", ignore))
1227 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1228 gomp_global_icv.bind_var = true;
1229 ignore = true;
1231 if (parse_affinity (ignore))
1233 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1234 gomp_global_icv.bind_var = true;
1235 ignore = true;
1237 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1238 gomp_init_affinity ();
1239 wait_policy = parse_wait_policy ();
1240 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1242 /* Using a rough estimation of 100000 spins per msec,
1243 use 5 min blocking for OMP_WAIT_POLICY=active,
1244 3 msec blocking when OMP_WAIT_POLICY is not specificed
1245 and 0 when OMP_WAIT_POLICY=passive.
1246 Depending on the CPU speed, this can be e.g. 5 times longer
1247 or 5 times shorter. */
1248 if (wait_policy > 0)
1249 gomp_spin_count_var = 30000000000LL;
1250 else if (wait_policy < 0)
1251 gomp_spin_count_var = 300000LL;
1253 /* gomp_throttled_spin_count_var is used when there are more libgomp
1254 managed threads than available CPUs. Use very short spinning. */
1255 if (wait_policy > 0)
1256 gomp_throttled_spin_count_var = 1000LL;
1257 else if (wait_policy < 0)
1258 gomp_throttled_spin_count_var = 100LL;
1259 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1260 gomp_throttled_spin_count_var = gomp_spin_count_var;
1262 /* Not strictly environment related, but ordering constructors is tricky. */
1263 pthread_attr_init (&gomp_thread_attr);
1264 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
1266 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1267 || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
1269 int err;
1271 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1273 #ifdef PTHREAD_STACK_MIN
1274 if (err == EINVAL)
1276 if (stacksize < PTHREAD_STACK_MIN)
1277 gomp_error ("Stack size less than minimum of %luk",
1278 PTHREAD_STACK_MIN / 1024ul
1279 + (PTHREAD_STACK_MIN % 1024 != 0));
1280 else
1281 gomp_error ("Stack size larger than system limit");
1283 else
1284 #endif
1285 if (err != 0)
1286 gomp_error ("Stack size change failed: %s", strerror (err));
1289 handle_omp_display_env (stacksize, wait_policy);
1291 /* OpenACC. */
1293 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1294 goacc_device_num = 0;
1296 parse_acc_device_type ();
1298 goacc_runtime_initialize ();
1302 /* The public OpenMP API routines that access these variables. */
1304 void
1305 omp_set_num_threads (int n)
1307 struct gomp_task_icv *icv = gomp_icv (true);
1308 icv->nthreads_var = (n > 0 ? n : 1);
1311 void
1312 omp_set_dynamic (int val)
1314 struct gomp_task_icv *icv = gomp_icv (true);
1315 icv->dyn_var = val;
1319 omp_get_dynamic (void)
1321 struct gomp_task_icv *icv = gomp_icv (false);
1322 return icv->dyn_var;
1325 void
1326 omp_set_nested (int val)
1328 struct gomp_task_icv *icv = gomp_icv (true);
1329 icv->nest_var = val;
1333 omp_get_nested (void)
1335 struct gomp_task_icv *icv = gomp_icv (false);
1336 return icv->nest_var;
1339 void
1340 omp_set_schedule (omp_sched_t kind, int modifier)
1342 struct gomp_task_icv *icv = gomp_icv (true);
1343 switch (kind)
1345 case omp_sched_static:
1346 if (modifier < 1)
1347 modifier = 0;
1348 icv->run_sched_modifier = modifier;
1349 break;
1350 case omp_sched_dynamic:
1351 case omp_sched_guided:
1352 if (modifier < 1)
1353 modifier = 1;
1354 icv->run_sched_modifier = modifier;
1355 break;
1356 case omp_sched_auto:
1357 break;
1358 default:
1359 return;
1361 icv->run_sched_var = kind;
1364 void
1365 omp_get_schedule (omp_sched_t *kind, int *modifier)
1367 struct gomp_task_icv *icv = gomp_icv (false);
1368 *kind = icv->run_sched_var;
1369 *modifier = icv->run_sched_modifier;
1373 omp_get_max_threads (void)
1375 struct gomp_task_icv *icv = gomp_icv (false);
1376 return icv->nthreads_var;
1380 omp_get_thread_limit (void)
1382 struct gomp_task_icv *icv = gomp_icv (false);
1383 return icv->thread_limit_var > INT_MAX ? INT_MAX : icv->thread_limit_var;
1386 void
1387 omp_set_max_active_levels (int max_levels)
1389 if (max_levels >= 0)
1390 gomp_max_active_levels_var = max_levels;
1394 omp_get_max_active_levels (void)
1396 return gomp_max_active_levels_var;
1400 omp_get_cancellation (void)
1402 return gomp_cancel_var;
1405 omp_proc_bind_t
1406 omp_get_proc_bind (void)
1408 struct gomp_task_icv *icv = gomp_icv (false);
1409 return icv->bind_var;
1412 void
1413 omp_set_default_device (int device_num)
1415 struct gomp_task_icv *icv = gomp_icv (true);
1416 icv->default_device_var = device_num >= 0 ? device_num : 0;
1420 omp_get_default_device (void)
1422 struct gomp_task_icv *icv = gomp_icv (false);
1423 return icv->default_device_var;
1427 omp_get_num_devices (void)
1429 return gomp_get_num_devices ();
1433 omp_get_num_teams (void)
1435 /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */
1436 return 1;
1440 omp_get_team_num (void)
1442 /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */
1443 return 0;
1447 omp_is_initial_device (void)
1449 /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */
1450 return 1;
1453 ialias (omp_set_dynamic)
1454 ialias (omp_set_nested)
1455 ialias (omp_set_num_threads)
1456 ialias (omp_get_dynamic)
1457 ialias (omp_get_nested)
1458 ialias (omp_set_schedule)
1459 ialias (omp_get_schedule)
1460 ialias (omp_get_max_threads)
1461 ialias (omp_get_thread_limit)
1462 ialias (omp_set_max_active_levels)
1463 ialias (omp_get_max_active_levels)
1464 ialias (omp_get_cancellation)
1465 ialias (omp_get_proc_bind)
1466 ialias (omp_set_default_device)
1467 ialias (omp_get_default_device)
1468 ialias (omp_get_num_devices)
1469 ialias (omp_get_num_teams)
1470 ialias (omp_get_team_num)
1471 ialias (omp_is_initial_device)