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