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