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