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