Home | History | Annotate | Line # | Download | only in libgomp
      1 /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
      2    Contributed by Richard Henderson <rth (at) 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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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 }
   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))
   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