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