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