Fix hashing of prestreamed nodes
[gcc.git] / libgomp / env.c
1 /* Copyright (C) 2005-2020 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
3
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
6
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.
11
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.
16
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.
20
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/>. */
25
26 /* This file defines the OpenMP internal control variables and arranges
27 for them to be initialized from environment variables at startup. */
28
29 #define _GNU_SOURCE
30 #include "libgomp.h"
31 #include "gomp-constants.h"
32 #include <limits.h>
33 #ifndef LIBGOMP_OFFLOADED_ONLY
34 #include "libgomp_f.h"
35 #include "oacc-int.h"
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #ifdef HAVE_INTTYPES_H
40 # include <inttypes.h> /* For PRIu64. */
41 #endif
42 #ifdef STRING_WITH_STRINGS
43 # include <string.h>
44 # include <strings.h>
45 #else
46 # ifdef HAVE_STRING_H
47 # include <string.h>
48 # else
49 # ifdef HAVE_STRINGS_H
50 # include <strings.h>
51 # endif
52 # endif
53 #endif
54 #include <errno.h>
55 #include "thread-stacksize.h"
56
57 #ifndef HAVE_STRTOULL
58 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
59 #endif
60 #endif /* LIBGOMP_OFFLOADED_ONLY */
61
62 #include "secure_getenv.h"
63
64 struct gomp_task_icv gomp_global_icv = {
65 .nthreads_var = 1,
66 .thread_limit_var = UINT_MAX,
67 .run_sched_var = GFS_DYNAMIC,
68 .run_sched_chunk_size = 1,
69 .default_device_var = 0,
70 .dyn_var = false,
71 .nest_var = false,
72 .bind_var = omp_proc_bind_false,
73 .target_data = NULL
74 };
75
76 unsigned long gomp_max_active_levels_var = INT_MAX;
77 bool gomp_cancel_var = false;
78 int gomp_max_task_priority_var = 0;
79 #ifndef HAVE_SYNC_BUILTINS
80 gomp_mutex_t gomp_managed_threads_lock;
81 #endif
82 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
83 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
84 unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
85 char *gomp_bind_var_list;
86 unsigned long gomp_bind_var_list_len;
87 void **gomp_places_list;
88 unsigned long gomp_places_list_len;
89 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
90 int gomp_debug_var;
91 unsigned int gomp_num_teams_var;
92 bool gomp_display_affinity_var;
93 char *gomp_affinity_format_var = "level %L thread %i affinity %A";
94 size_t gomp_affinity_format_len;
95 char *goacc_device_type;
96 int goacc_device_num;
97 int goacc_default_dims[GOMP_DIM_MAX];
98
99 #ifndef LIBGOMP_OFFLOADED_ONLY
100
101 /* Parse the OMP_SCHEDULE environment variable. */
102
103 static void
104 parse_schedule (void)
105 {
106 char *env, *end;
107 unsigned long value;
108 int monotonic = 0;
109
110 env = getenv ("OMP_SCHEDULE");
111 if (env == NULL)
112 return;
113
114 while (isspace ((unsigned char) *env))
115 ++env;
116 if (strncasecmp (env, "monotonic", 9) == 0)
117 {
118 monotonic = 1;
119 env += 9;
120 }
121 else if (strncasecmp (env, "nonmonotonic", 12) == 0)
122 {
123 monotonic = -1;
124 env += 12;
125 }
126 if (monotonic)
127 {
128 while (isspace ((unsigned char) *env))
129 ++env;
130 if (*env != ':')
131 goto unknown;
132 ++env;
133 while (isspace ((unsigned char) *env))
134 ++env;
135 }
136 if (strncasecmp (env, "static", 6) == 0)
137 {
138 gomp_global_icv.run_sched_var = GFS_STATIC;
139 env += 6;
140 }
141 else if (strncasecmp (env, "dynamic", 7) == 0)
142 {
143 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
144 env += 7;
145 }
146 else if (strncasecmp (env, "guided", 6) == 0)
147 {
148 gomp_global_icv.run_sched_var = GFS_GUIDED;
149 env += 6;
150 }
151 else if (strncasecmp (env, "auto", 4) == 0)
152 {
153 gomp_global_icv.run_sched_var = GFS_AUTO;
154 env += 4;
155 }
156 else
157 goto unknown;
158
159 if (monotonic == 1
160 || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC))
161 gomp_global_icv.run_sched_var |= GFS_MONOTONIC;
162
163 while (isspace ((unsigned char) *env))
164 ++env;
165 if (*env == '\0')
166 {
167 gomp_global_icv.run_sched_chunk_size
168 = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC;
169 return;
170 }
171 if (*env++ != ',')
172 goto unknown;
173 while (isspace ((unsigned char) *env))
174 ++env;
175 if (*env == '\0')
176 goto invalid;
177
178 errno = 0;
179 value = strtoul (env, &end, 10);
180 if (errno)
181 goto invalid;
182
183 while (isspace ((unsigned char) *end))
184 ++end;
185 if (*end != '\0')
186 goto invalid;
187
188 if ((int)value != value)
189 goto invalid;
190
191 if (value == 0
192 && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC)
193 value = 1;
194 gomp_global_icv.run_sched_chunk_size = value;
195 return;
196
197 unknown:
198 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
199 return;
200
201 invalid:
202 gomp_error ("Invalid value for chunk size in "
203 "environment variable OMP_SCHEDULE");
204 return;
205 }
206
207 /* Parse an unsigned long environment variable. Return true if one was
208 present and it was successfully parsed. If SECURE, use secure_getenv to the
209 environment variable. */
210
211 static bool
212 parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
213 bool secure)
214 {
215 char *env, *end;
216 unsigned long value;
217
218 env = (secure ? secure_getenv (name) : getenv (name));
219 if (env == NULL)
220 return false;
221
222 while (isspace ((unsigned char) *env))
223 ++env;
224 if (*env == '\0')
225 goto invalid;
226
227 errno = 0;
228 value = strtoul (env, &end, 10);
229 if (errno || (long) value <= 0 - allow_zero)
230 goto invalid;
231
232 while (isspace ((unsigned char) *end))
233 ++end;
234 if (*end != '\0')
235 goto invalid;
236
237 *pvalue = value;
238 return true;
239
240 invalid:
241 gomp_error ("Invalid value for environment variable %s", name);
242 return false;
243 }
244
245 /* As parse_unsigned_long_1, but always use getenv. */
246
247 static bool
248 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
249 {
250 return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
251 }
252
253 /* Parse a positive int environment variable. Return true if one was
254 present and it was successfully parsed. If SECURE, use secure_getenv to the
255 environment variable. */
256
257 static bool
258 parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
259 {
260 unsigned long value;
261 if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
262 return false;
263 if (value > INT_MAX)
264 {
265 gomp_error ("Invalid value for environment variable %s", name);
266 return false;
267 }
268 *pvalue = (int) value;
269 return true;
270 }
271
272 /* As parse_int_1, but use getenv. */
273
274 static bool
275 parse_int (const char *name, int *pvalue, bool allow_zero)
276 {
277 return parse_int_1 (name, pvalue, allow_zero, false);
278 }
279
280 /* As parse_int_1, but use getenv_secure. */
281
282 static bool
283 parse_int_secure (const char *name, int *pvalue, bool allow_zero)
284 {
285 return parse_int_1 (name, pvalue, allow_zero, true);
286 }
287
288 /* Parse an unsigned long list environment variable. Return true if one was
289 present and it was successfully parsed. */
290
291 static bool
292 parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
293 unsigned long **pvalues,
294 unsigned long *pnvalues)
295 {
296 char *env, *end;
297 unsigned long value, *values = NULL;
298
299 env = getenv (name);
300 if (env == NULL)
301 return false;
302
303 while (isspace ((unsigned char) *env))
304 ++env;
305 if (*env == '\0')
306 goto invalid;
307
308 errno = 0;
309 value = strtoul (env, &end, 10);
310 if (errno || (long) value <= 0)
311 goto invalid;
312
313 while (isspace ((unsigned char) *end))
314 ++end;
315 if (*end != '\0')
316 {
317 if (*end == ',')
318 {
319 unsigned long nvalues = 0, nalloced = 0;
320
321 do
322 {
323 env = end + 1;
324 if (nvalues == nalloced)
325 {
326 unsigned long *n;
327 nalloced = nalloced ? nalloced * 2 : 16;
328 n = realloc (values, nalloced * sizeof (unsigned long));
329 if (n == NULL)
330 {
331 free (values);
332 gomp_error ("Out of memory while trying to parse"
333 " environment variable %s", name);
334 return false;
335 }
336 values = n;
337 if (nvalues == 0)
338 values[nvalues++] = value;
339 }
340
341 while (isspace ((unsigned char) *env))
342 ++env;
343 if (*env == '\0')
344 goto invalid;
345
346 errno = 0;
347 value = strtoul (env, &end, 10);
348 if (errno || (long) value <= 0)
349 goto invalid;
350
351 values[nvalues++] = value;
352 while (isspace ((unsigned char) *end))
353 ++end;
354 if (*end == '\0')
355 break;
356 if (*end != ',')
357 goto invalid;
358 }
359 while (1);
360 *p1stvalue = values[0];
361 *pvalues = values;
362 *pnvalues = nvalues;
363 return true;
364 }
365 goto invalid;
366 }
367
368 *p1stvalue = value;
369 return true;
370
371 invalid:
372 free (values);
373 gomp_error ("Invalid value for environment variable %s", name);
374 return false;
375 }
376
377 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
378 enum values. Return true if one was present and it was successfully
379 parsed. */
380
381 static bool
382 parse_bind_var (const char *name, char *p1stvalue,
383 char **pvalues, unsigned long *pnvalues)
384 {
385 char *env;
386 char value = omp_proc_bind_false, *values = NULL;
387 int i;
388 static struct proc_bind_kinds
389 {
390 const char name[7];
391 const char len;
392 omp_proc_bind_t kind;
393 } kinds[] =
394 {
395 { "false", 5, omp_proc_bind_false },
396 { "true", 4, omp_proc_bind_true },
397 { "master", 6, omp_proc_bind_master },
398 { "close", 5, omp_proc_bind_close },
399 { "spread", 6, omp_proc_bind_spread }
400 };
401
402 env = getenv (name);
403 if (env == NULL)
404 return false;
405
406 while (isspace ((unsigned char) *env))
407 ++env;
408 if (*env == '\0')
409 goto invalid;
410
411 for (i = 0; i < 5; i++)
412 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
413 {
414 value = kinds[i].kind;
415 env += kinds[i].len;
416 break;
417 }
418 if (i == 5)
419 goto invalid;
420
421 while (isspace ((unsigned char) *env))
422 ++env;
423 if (*env != '\0')
424 {
425 if (*env == ',')
426 {
427 unsigned long nvalues = 0, nalloced = 0;
428
429 if (value == omp_proc_bind_false
430 || value == omp_proc_bind_true)
431 goto invalid;
432
433 do
434 {
435 env++;
436 if (nvalues == nalloced)
437 {
438 char *n;
439 nalloced = nalloced ? nalloced * 2 : 16;
440 n = realloc (values, nalloced);
441 if (n == NULL)
442 {
443 free (values);
444 gomp_error ("Out of memory while trying to parse"
445 " environment variable %s", name);
446 return false;
447 }
448 values = n;
449 if (nvalues == 0)
450 values[nvalues++] = value;
451 }
452
453 while (isspace ((unsigned char) *env))
454 ++env;
455 if (*env == '\0')
456 goto invalid;
457
458 for (i = 2; i < 5; i++)
459 if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
460 {
461 value = kinds[i].kind;
462 env += kinds[i].len;
463 break;
464 }
465 if (i == 5)
466 goto invalid;
467
468 values[nvalues++] = value;
469 while (isspace ((unsigned char) *env))
470 ++env;
471 if (*env == '\0')
472 break;
473 if (*env != ',')
474 goto invalid;
475 }
476 while (1);
477 *p1stvalue = values[0];
478 *pvalues = values;
479 *pnvalues = nvalues;
480 return true;
481 }
482 goto invalid;
483 }
484
485 *p1stvalue = value;
486 return true;
487
488 invalid:
489 free (values);
490 gomp_error ("Invalid value for environment variable %s", name);
491 return false;
492 }
493
494 static bool
495 parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
496 long *stridep)
497 {
498 char *env = *envp, *start;
499 void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
500 unsigned long len = 1;
501 long stride = 1;
502 int pass;
503 bool any_negate = false;
504 *negatep = false;
505 while (isspace ((unsigned char) *env))
506 ++env;
507 if (*env == '!')
508 {
509 *negatep = true;
510 ++env;
511 while (isspace ((unsigned char) *env))
512 ++env;
513 }
514 if (*env != '{')
515 return false;
516 ++env;
517 while (isspace ((unsigned char) *env))
518 ++env;
519 start = env;
520 for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
521 {
522 env = start;
523 do
524 {
525 unsigned long this_num, this_len = 1;
526 long this_stride = 1;
527 bool this_negate = (*env == '!');
528 if (this_negate)
529 {
530 if (gomp_places_list)
531 any_negate = true;
532 ++env;
533 while (isspace ((unsigned char) *env))
534 ++env;
535 }
536
537 errno = 0;
538 this_num = strtoul (env, &env, 10);
539 if (errno)
540 return false;
541 while (isspace ((unsigned char) *env))
542 ++env;
543 if (*env == ':')
544 {
545 ++env;
546 while (isspace ((unsigned char) *env))
547 ++env;
548 errno = 0;
549 this_len = strtoul (env, &env, 10);
550 if (errno || this_len == 0)
551 return false;
552 while (isspace ((unsigned char) *env))
553 ++env;
554 if (*env == ':')
555 {
556 ++env;
557 while (isspace ((unsigned char) *env))
558 ++env;
559 errno = 0;
560 this_stride = strtol (env, &env, 10);
561 if (errno)
562 return false;
563 while (isspace ((unsigned char) *env))
564 ++env;
565 }
566 }
567 if (this_negate && this_len != 1)
568 return false;
569 if (gomp_places_list && pass == this_negate)
570 {
571 if (this_negate)
572 {
573 if (!gomp_affinity_remove_cpu (p, this_num))
574 return false;
575 }
576 else if (!gomp_affinity_add_cpus (p, this_num, this_len,
577 this_stride, false))
578 return false;
579 }
580 if (*env == '}')
581 break;
582 if (*env != ',')
583 return false;
584 ++env;
585 }
586 while (1);
587 }
588
589 ++env;
590 while (isspace ((unsigned char) *env))
591 ++env;
592 if (*env == ':')
593 {
594 ++env;
595 while (isspace ((unsigned char) *env))
596 ++env;
597 errno = 0;
598 len = strtoul (env, &env, 10);
599 if (errno || len == 0 || len >= 65536)
600 return false;
601 while (isspace ((unsigned char) *env))
602 ++env;
603 if (*env == ':')
604 {
605 ++env;
606 while (isspace ((unsigned char) *env))
607 ++env;
608 errno = 0;
609 stride = strtol (env, &env, 10);
610 if (errno)
611 return false;
612 while (isspace ((unsigned char) *env))
613 ++env;
614 }
615 }
616 if (*negatep && len != 1)
617 return false;
618 *envp = env;
619 *lenp = len;
620 *stridep = stride;
621 return true;
622 }
623
624 static bool
625 parse_places_var (const char *name, bool ignore)
626 {
627 char *env = getenv (name), *end;
628 bool any_negate = false;
629 int level = 0;
630 unsigned long count = 0;
631 if (env == NULL)
632 return false;
633
634 while (isspace ((unsigned char) *env))
635 ++env;
636 if (*env == '\0')
637 goto invalid;
638
639 if (strncasecmp (env, "threads", 7) == 0)
640 {
641 env += 7;
642 level = 1;
643 }
644 else if (strncasecmp (env, "cores", 5) == 0)
645 {
646 env += 5;
647 level = 2;
648 }
649 else if (strncasecmp (env, "sockets", 7) == 0)
650 {
651 env += 7;
652 level = 3;
653 }
654 if (level)
655 {
656 count = ULONG_MAX;
657 while (isspace ((unsigned char) *env))
658 ++env;
659 if (*env != '\0')
660 {
661 if (*env++ != '(')
662 goto invalid;
663 while (isspace ((unsigned char) *env))
664 ++env;
665
666 errno = 0;
667 count = strtoul (env, &end, 10);
668 if (errno)
669 goto invalid;
670 env = end;
671 while (isspace ((unsigned char) *env))
672 ++env;
673 if (*env != ')')
674 goto invalid;
675 ++env;
676 while (isspace ((unsigned char) *env))
677 ++env;
678 if (*env != '\0')
679 goto invalid;
680 }
681
682 if (ignore)
683 return false;
684
685 return gomp_affinity_init_level (level, count, false);
686 }
687
688 count = 0;
689 end = env;
690 do
691 {
692 bool negate;
693 unsigned long len;
694 long stride;
695 if (!parse_one_place (&end, &negate, &len, &stride))
696 goto invalid;
697 if (negate)
698 {
699 if (!any_negate)
700 count++;
701 any_negate = true;
702 }
703 else
704 count += len;
705 if (count > 65536)
706 goto invalid;
707 if (*end == '\0')
708 break;
709 if (*end != ',')
710 goto invalid;
711 end++;
712 }
713 while (1);
714
715 if (ignore)
716 return false;
717
718 gomp_places_list_len = 0;
719 gomp_places_list = gomp_affinity_alloc (count, false);
720 if (gomp_places_list == NULL)
721 return false;
722
723 do
724 {
725 bool negate;
726 unsigned long len;
727 long stride;
728 gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
729 if (!parse_one_place (&env, &negate, &len, &stride))
730 goto invalid;
731 if (negate)
732 {
733 void *p;
734 for (count = 0; count < gomp_places_list_len; count++)
735 if (gomp_affinity_same_place
736 (gomp_places_list[count],
737 gomp_places_list[gomp_places_list_len]))
738 break;
739 if (count == gomp_places_list_len)
740 {
741 gomp_error ("Trying to remove a non-existing place from list "
742 "of places");
743 goto invalid;
744 }
745 p = gomp_places_list[count];
746 memmove (&gomp_places_list[count],
747 &gomp_places_list[count + 1],
748 (gomp_places_list_len - count - 1) * sizeof (void *));
749 --gomp_places_list_len;
750 gomp_places_list[gomp_places_list_len] = p;
751 }
752 else if (len == 1)
753 ++gomp_places_list_len;
754 else
755 {
756 for (count = 0; count < len - 1; count++)
757 if (!gomp_affinity_copy_place
758 (gomp_places_list[gomp_places_list_len + count + 1],
759 gomp_places_list[gomp_places_list_len + count],
760 stride))
761 goto invalid;
762 gomp_places_list_len += len;
763 }
764 if (*env == '\0')
765 break;
766 env++;
767 }
768 while (1);
769
770 if (gomp_places_list_len == 0)
771 {
772 gomp_error ("All places have been removed");
773 goto invalid;
774 }
775 if (!gomp_affinity_finalize_place_list (false))
776 goto invalid;
777 return true;
778
779 invalid:
780 free (gomp_places_list);
781 gomp_places_list = NULL;
782 gomp_places_list_len = 0;
783 gomp_error ("Invalid value for environment variable %s", name);
784 return false;
785 }
786
787 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
788 present and it was successfully parsed. */
789
790 static bool
791 parse_stacksize (const char *name, unsigned long *pvalue)
792 {
793 char *env, *end;
794 unsigned long value, shift = 10;
795
796 env = getenv (name);
797 if (env == NULL)
798 return false;
799
800 while (isspace ((unsigned char) *env))
801 ++env;
802 if (*env == '\0')
803 goto invalid;
804
805 errno = 0;
806 value = strtoul (env, &end, 10);
807 if (errno)
808 goto invalid;
809
810 while (isspace ((unsigned char) *end))
811 ++end;
812 if (*end != '\0')
813 {
814 switch (tolower ((unsigned char) *end))
815 {
816 case 'b':
817 shift = 0;
818 break;
819 case 'k':
820 break;
821 case 'm':
822 shift = 20;
823 break;
824 case 'g':
825 shift = 30;
826 break;
827 default:
828 goto invalid;
829 }
830 ++end;
831 while (isspace ((unsigned char) *end))
832 ++end;
833 if (*end != '\0')
834 goto invalid;
835 }
836
837 if (((value << shift) >> shift) != value)
838 goto invalid;
839
840 *pvalue = value << shift;
841 return true;
842
843 invalid:
844 gomp_error ("Invalid value for environment variable %s", name);
845 return false;
846 }
847
848 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
849 present and it was successfully parsed. */
850
851 static bool
852 parse_spincount (const char *name, unsigned long long *pvalue)
853 {
854 char *env, *end;
855 unsigned long long value, mult = 1;
856
857 env = getenv (name);
858 if (env == NULL)
859 return false;
860
861 while (isspace ((unsigned char) *env))
862 ++env;
863 if (*env == '\0')
864 goto invalid;
865
866 if (strncasecmp (env, "infinite", 8) == 0
867 || strncasecmp (env, "infinity", 8) == 0)
868 {
869 value = ~0ULL;
870 end = env + 8;
871 goto check_tail;
872 }
873
874 errno = 0;
875 value = strtoull (env, &end, 10);
876 if (errno)
877 goto invalid;
878
879 while (isspace ((unsigned char) *end))
880 ++end;
881 if (*end != '\0')
882 {
883 switch (tolower ((unsigned char) *end))
884 {
885 case 'k':
886 mult = 1000LL;
887 break;
888 case 'm':
889 mult = 1000LL * 1000LL;
890 break;
891 case 'g':
892 mult = 1000LL * 1000LL * 1000LL;
893 break;
894 case 't':
895 mult = 1000LL * 1000LL * 1000LL * 1000LL;
896 break;
897 default:
898 goto invalid;
899 }
900 ++end;
901 check_tail:
902 while (isspace ((unsigned char) *end))
903 ++end;
904 if (*end != '\0')
905 goto invalid;
906 }
907
908 if (value > ~0ULL / mult)
909 value = ~0ULL;
910 else
911 value *= mult;
912
913 *pvalue = value;
914 return true;
915
916 invalid:
917 gomp_error ("Invalid value for environment variable %s", name);
918 return false;
919 }
920
921 /* Parse a boolean value for environment variable NAME and store the
922 result in VALUE. */
923
924 static void
925 parse_boolean (const char *name, bool *value)
926 {
927 const char *env;
928
929 env = getenv (name);
930 if (env == NULL)
931 return;
932
933 while (isspace ((unsigned char) *env))
934 ++env;
935 if (strncasecmp (env, "true", 4) == 0)
936 {
937 *value = true;
938 env += 4;
939 }
940 else if (strncasecmp (env, "false", 5) == 0)
941 {
942 *value = false;
943 env += 5;
944 }
945 else
946 env = "X";
947 while (isspace ((unsigned char) *env))
948 ++env;
949 if (*env != '\0')
950 gomp_error ("Invalid value for environment variable %s", name);
951 }
952
953 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
954
955 static int
956 parse_wait_policy (void)
957 {
958 const char *env;
959 int ret = -1;
960
961 env = getenv ("OMP_WAIT_POLICY");
962 if (env == NULL)
963 return -1;
964
965 while (isspace ((unsigned char) *env))
966 ++env;
967 if (strncasecmp (env, "active", 6) == 0)
968 {
969 ret = 1;
970 env += 6;
971 }
972 else if (strncasecmp (env, "passive", 7) == 0)
973 {
974 ret = 0;
975 env += 7;
976 }
977 else
978 env = "X";
979 while (isspace ((unsigned char) *env))
980 ++env;
981 if (*env == '\0')
982 return ret;
983 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
984 return -1;
985 }
986
987 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
988 present and it was successfully parsed. */
989
990 static bool
991 parse_affinity (bool ignore)
992 {
993 char *env, *end, *start;
994 int pass;
995 unsigned long cpu_beg, cpu_end, cpu_stride;
996 size_t count = 0, needed;
997
998 env = getenv ("GOMP_CPU_AFFINITY");
999 if (env == NULL)
1000 return false;
1001
1002 start = env;
1003 for (pass = 0; pass < 2; pass++)
1004 {
1005 env = start;
1006 if (pass == 1)
1007 {
1008 if (ignore)
1009 return false;
1010
1011 gomp_places_list_len = 0;
1012 gomp_places_list = gomp_affinity_alloc (count, true);
1013 if (gomp_places_list == NULL)
1014 return false;
1015 }
1016 do
1017 {
1018 while (isspace ((unsigned char) *env))
1019 ++env;
1020
1021 errno = 0;
1022 cpu_beg = strtoul (env, &end, 0);
1023 if (errno || cpu_beg >= 65536)
1024 goto invalid;
1025 cpu_end = cpu_beg;
1026 cpu_stride = 1;
1027
1028 env = end;
1029 if (*env == '-')
1030 {
1031 errno = 0;
1032 cpu_end = strtoul (++env, &end, 0);
1033 if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
1034 goto invalid;
1035
1036 env = end;
1037 if (*env == ':')
1038 {
1039 errno = 0;
1040 cpu_stride = strtoul (++env, &end, 0);
1041 if (errno || cpu_stride == 0 || cpu_stride >= 65536)
1042 goto invalid;
1043
1044 env = end;
1045 }
1046 }
1047
1048 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
1049 if (pass == 0)
1050 count += needed;
1051 else
1052 {
1053 while (needed--)
1054 {
1055 void *p = gomp_places_list[gomp_places_list_len];
1056 gomp_affinity_init_place (p);
1057 if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
1058 ++gomp_places_list_len;
1059 cpu_beg += cpu_stride;
1060 }
1061 }
1062
1063 while (isspace ((unsigned char) *env))
1064 ++env;
1065
1066 if (*env == ',')
1067 env++;
1068 else if (*env == '\0')
1069 break;
1070 }
1071 while (1);
1072 }
1073
1074 if (gomp_places_list_len == 0)
1075 {
1076 free (gomp_places_list);
1077 gomp_places_list = NULL;
1078 return false;
1079 }
1080 return true;
1081
1082 invalid:
1083 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1084 return false;
1085 }
1086
1087 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1088
1089 static uintptr_t
1090 parse_allocator (void)
1091 {
1092 const char *env;
1093 uintptr_t ret = omp_default_mem_alloc;
1094
1095 env = getenv ("OMP_ALLOCATOR");
1096 if (env == NULL)
1097 return ret;
1098
1099 while (isspace ((unsigned char) *env))
1100 ++env;
1101 if (0)
1102 ;
1103 #define C(v) \
1104 else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
1105 { \
1106 ret = v; \
1107 env += sizeof (#v) - 1; \
1108 }
1109 C (omp_default_mem_alloc)
1110 C (omp_large_cap_mem_alloc)
1111 C (omp_const_mem_alloc)
1112 C (omp_high_bw_mem_alloc)
1113 C (omp_low_lat_mem_alloc)
1114 C (omp_cgroup_mem_alloc)
1115 C (omp_pteam_mem_alloc)
1116 C (omp_thread_mem_alloc)
1117 #undef C
1118 else
1119 env = "X";
1120 while (isspace ((unsigned char) *env))
1121 ++env;
1122 if (*env == '\0')
1123 return ret;
1124 gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
1125 return omp_default_mem_alloc;
1126 }
1127
1128 static void
1129 parse_acc_device_type (void)
1130 {
1131 const char *env = getenv ("ACC_DEVICE_TYPE");
1132
1133 if (env && *env != '\0')
1134 goacc_device_type = strdup (env);
1135 else
1136 goacc_device_type = NULL;
1137 }
1138
1139 static void
1140 parse_gomp_openacc_dim (void)
1141 {
1142 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1143 const char *var_name = "GOMP_OPENACC_DIM";
1144 const char *env_var = getenv (var_name);
1145 if (!env_var)
1146 return;
1147
1148 const char *pos = env_var;
1149 int i;
1150 for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
1151 {
1152 if (i && *pos++ != ':')
1153 break;
1154
1155 if (*pos == ':')
1156 continue;
1157
1158 const char *eptr;
1159 errno = 0;
1160 long val = strtol (pos, (char **)&eptr, 10);
1161 if (errno || val < 0 || (unsigned)val != val)
1162 break;
1163
1164 goacc_default_dims[i] = (int)val;
1165 pos = eptr;
1166 }
1167 }
1168
1169 static void
1170 handle_omp_display_env (unsigned long stacksize, int wait_policy)
1171 {
1172 const char *env;
1173 bool display = false;
1174 bool verbose = false;
1175 int i;
1176
1177 env = getenv ("OMP_DISPLAY_ENV");
1178 if (env == NULL)
1179 return;
1180
1181 while (isspace ((unsigned char) *env))
1182 ++env;
1183 if (strncasecmp (env, "true", 4) == 0)
1184 {
1185 display = true;
1186 env += 4;
1187 }
1188 else if (strncasecmp (env, "false", 5) == 0)
1189 {
1190 display = false;
1191 env += 5;
1192 }
1193 else if (strncasecmp (env, "verbose", 7) == 0)
1194 {
1195 display = true;
1196 verbose = true;
1197 env += 7;
1198 }
1199 else
1200 env = "X";
1201 while (isspace ((unsigned char) *env))
1202 ++env;
1203 if (*env != '\0')
1204 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1205
1206 if (!display)
1207 return;
1208
1209 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
1210
1211 fputs (" _OPENMP = '201511'\n", stderr);
1212 fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
1213 gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
1214 fprintf (stderr, " OMP_NESTED = '%s'\n",
1215 gomp_global_icv.nest_var ? "TRUE" : "FALSE");
1216
1217 fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
1218 for (i = 1; i < gomp_nthreads_var_list_len; i++)
1219 fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
1220 fputs ("'\n", stderr);
1221
1222 fprintf (stderr, " OMP_SCHEDULE = '");
1223 if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
1224 {
1225 if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
1226 fputs ("MONOTONIC:", stderr);
1227 }
1228 else if (gomp_global_icv.run_sched_var == GFS_STATIC)
1229 fputs ("NONMONOTONIC:", stderr);
1230 switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
1231 {
1232 case GFS_RUNTIME:
1233 fputs ("RUNTIME", stderr);
1234 if (gomp_global_icv.run_sched_chunk_size != 1)
1235 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1236 break;
1237 case GFS_STATIC:
1238 fputs ("STATIC", stderr);
1239 if (gomp_global_icv.run_sched_chunk_size != 0)
1240 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1241 break;
1242 case GFS_DYNAMIC:
1243 fputs ("DYNAMIC", stderr);
1244 if (gomp_global_icv.run_sched_chunk_size != 1)
1245 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1246 break;
1247 case GFS_GUIDED:
1248 fputs ("GUIDED", stderr);
1249 if (gomp_global_icv.run_sched_chunk_size != 1)
1250 fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
1251 break;
1252 case GFS_AUTO:
1253 fputs ("AUTO", stderr);
1254 break;
1255 }
1256 fputs ("'\n", stderr);
1257
1258 fputs (" OMP_PROC_BIND = '", stderr);
1259 switch (gomp_global_icv.bind_var)
1260 {
1261 case omp_proc_bind_false:
1262 fputs ("FALSE", stderr);
1263 break;
1264 case omp_proc_bind_true:
1265 fputs ("TRUE", stderr);
1266 break;
1267 case omp_proc_bind_master:
1268 fputs ("MASTER", stderr);
1269 break;
1270 case omp_proc_bind_close:
1271 fputs ("CLOSE", stderr);
1272 break;
1273 case omp_proc_bind_spread:
1274 fputs ("SPREAD", stderr);
1275 break;
1276 }
1277 for (i = 1; i < gomp_bind_var_list_len; i++)
1278 switch (gomp_bind_var_list[i])
1279 {
1280 case omp_proc_bind_master:
1281 fputs (",MASTER", stderr);
1282 break;
1283 case omp_proc_bind_close:
1284 fputs (",CLOSE", stderr);
1285 break;
1286 case omp_proc_bind_spread:
1287 fputs (",SPREAD", stderr);
1288 break;
1289 }
1290 fputs ("'\n", stderr);
1291 fputs (" OMP_PLACES = '", stderr);
1292 for (i = 0; i < gomp_places_list_len; i++)
1293 {
1294 fputs ("{", stderr);
1295 gomp_affinity_print_place (gomp_places_list[i]);
1296 fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
1297 }
1298 fputs ("'\n", stderr);
1299
1300 fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
1301
1302 /* GOMP's default value is actually neither active nor passive. */
1303 fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
1304 wait_policy > 0 ? "ACTIVE" : "PASSIVE");
1305 fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
1306 gomp_global_icv.thread_limit_var);
1307 fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
1308 gomp_max_active_levels_var);
1309
1310 fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
1311 gomp_cancel_var ? "TRUE" : "FALSE");
1312 fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
1313 gomp_global_icv.default_device_var);
1314 fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1315 gomp_max_task_priority_var);
1316 fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n",
1317 gomp_display_affinity_var ? "TRUE" : "FALSE");
1318 fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
1319 gomp_affinity_format_var);
1320 fprintf (stderr, " OMP_ALLOCATOR = '");
1321 switch (gomp_def_allocator)
1322 {
1323 #define C(v) case v: fputs (#v, stderr); break;
1324 C (omp_default_mem_alloc)
1325 C (omp_large_cap_mem_alloc)
1326 C (omp_const_mem_alloc)
1327 C (omp_high_bw_mem_alloc)
1328 C (omp_low_lat_mem_alloc)
1329 C (omp_cgroup_mem_alloc)
1330 C (omp_pteam_mem_alloc)
1331 C (omp_thread_mem_alloc)
1332 #undef C
1333 default: break;
1334 }
1335 fputs ("'\n", stderr);
1336
1337 if (verbose)
1338 {
1339 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
1340 fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
1341 #ifdef HAVE_INTTYPES_H
1342 fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
1343 (uint64_t) gomp_spin_count_var);
1344 #else
1345 fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
1346 (unsigned long) gomp_spin_count_var);
1347 #endif
1348 }
1349
1350 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
1351 }
1352
1353
1354 static void __attribute__((constructor))
1355 initialize_env (void)
1356 {
1357 unsigned long thread_limit_var, stacksize = GOMP_DEFAULT_STACKSIZE;
1358 int wait_policy;
1359
1360 /* Do a compile time check that mkomp_h.pl did good job. */
1361 omp_check_defines ();
1362
1363 parse_schedule ();
1364 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
1365 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
1366 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
1367 parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var);
1368 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
1369 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
1370 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
1371 true);
1372 gomp_def_allocator = parse_allocator ();
1373 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
1374 {
1375 gomp_global_icv.thread_limit_var
1376 = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
1377 }
1378 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
1379 #ifndef HAVE_SYNC_BUILTINS
1380 gomp_mutex_init (&gomp_managed_threads_lock);
1381 #endif
1382 gomp_init_num_threads ();
1383 gomp_available_cpus = gomp_global_icv.nthreads_var;
1384 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1385 &gomp_global_icv.nthreads_var,
1386 &gomp_nthreads_var_list,
1387 &gomp_nthreads_var_list_len))
1388 gomp_global_icv.nthreads_var = gomp_available_cpus;
1389 bool ignore = false;
1390 if (parse_bind_var ("OMP_PROC_BIND",
1391 &gomp_global_icv.bind_var,
1392 &gomp_bind_var_list,
1393 &gomp_bind_var_list_len)
1394 && gomp_global_icv.bind_var == omp_proc_bind_false)
1395 ignore = true;
1396 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1397 parsed if present in the environment. If OMP_PROC_BIND was set
1398 explicitly to false, don't populate places list though. If places
1399 list was successfully set from OMP_PLACES, only parse but don't process
1400 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1401 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1402 was successfully parsed into a places list, otherwise to
1403 OMP_PROC_BIND=false. */
1404 if (parse_places_var ("OMP_PLACES", ignore))
1405 {
1406 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1407 gomp_global_icv.bind_var = true;
1408 ignore = true;
1409 }
1410 if (parse_affinity (ignore))
1411 {
1412 if (gomp_global_icv.bind_var == omp_proc_bind_false)
1413 gomp_global_icv.bind_var = true;
1414 ignore = true;
1415 }
1416 if (gomp_global_icv.bind_var != omp_proc_bind_false)
1417 gomp_init_affinity ();
1418
1419 {
1420 const char *env = getenv ("OMP_AFFINITY_FORMAT");
1421 if (env != NULL)
1422 gomp_set_affinity_format (env, strlen (env));
1423 }
1424
1425 wait_policy = parse_wait_policy ();
1426 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
1427 {
1428 /* Using a rough estimation of 100000 spins per msec,
1429 use 5 min blocking for OMP_WAIT_POLICY=active,
1430 3 msec blocking when OMP_WAIT_POLICY is not specificed
1431 and 0 when OMP_WAIT_POLICY=passive.
1432 Depending on the CPU speed, this can be e.g. 5 times longer
1433 or 5 times shorter. */
1434 if (wait_policy > 0)
1435 gomp_spin_count_var = 30000000000LL;
1436 else if (wait_policy < 0)
1437 gomp_spin_count_var = 300000LL;
1438 }
1439 /* gomp_throttled_spin_count_var is used when there are more libgomp
1440 managed threads than available CPUs. Use very short spinning. */
1441 if (wait_policy > 0)
1442 gomp_throttled_spin_count_var = 1000LL;
1443 else if (wait_policy < 0)
1444 gomp_throttled_spin_count_var = 100LL;
1445 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
1446 gomp_throttled_spin_count_var = gomp_spin_count_var;
1447
1448 /* Not strictly environment related, but ordering constructors is tricky. */
1449 pthread_attr_init (&gomp_thread_attr);
1450
1451 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
1452 || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
1453 || GOMP_DEFAULT_STACKSIZE)
1454 {
1455 int err;
1456
1457 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
1458
1459 #ifdef PTHREAD_STACK_MIN
1460 if (err == EINVAL)
1461 {
1462 if (stacksize < PTHREAD_STACK_MIN)
1463 gomp_error ("Stack size less than minimum of %luk",
1464 PTHREAD_STACK_MIN / 1024ul
1465 + (PTHREAD_STACK_MIN % 1024 != 0));
1466 else
1467 gomp_error ("Stack size larger than system limit");
1468 }
1469 else
1470 #endif
1471 if (err != 0)
1472 gomp_error ("Stack size change failed: %s", strerror (err));
1473 }
1474
1475 handle_omp_display_env (stacksize, wait_policy);
1476
1477 /* OpenACC. */
1478
1479 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
1480 goacc_device_num = 0;
1481
1482 parse_acc_device_type ();
1483 parse_gomp_openacc_dim ();
1484
1485 goacc_runtime_initialize ();
1486
1487 goacc_profiling_initialize ();
1488 }
1489 #endif /* LIBGOMP_OFFLOADED_ONLY */