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