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