123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614 |
- /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
- This file is part of the GNU Offloading and Multi Processing Library
- (libgomp).
- Libgomp is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- /* This file defines the OpenMP internal control variables and arranges
- for them to be initialized from environment variables at startup. */
- #define _GNU_SOURCE
- #include "libgomp.h"
- #include "gomp-constants.h"
- #include <limits.h>
- #ifndef LIBGOMP_OFFLOADED_ONLY
- #include "libgomp_f.h"
- #include "oacc-int.h"
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #ifdef HAVE_INTTYPES_H
- # include <inttypes.h> /* For PRIu64. */
- #endif
- #ifdef STRING_WITH_STRINGS
- # include <string.h>
- # include <strings.h>
- #else
- # ifdef HAVE_STRING_H
- # include <string.h>
- # else
- # ifdef HAVE_STRINGS_H
- # include <strings.h>
- # endif
- # endif
- #endif
- #include <errno.h>
- #include "thread-stacksize.h"
- #ifndef HAVE_STRTOULL
- # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
- #endif
- #endif /* LIBGOMP_OFFLOADED_ONLY */
- #include "secure_getenv.h"
- struct gomp_task_icv gomp_global_icv = {
- .nthreads_var = 1,
- .thread_limit_var = UINT_MAX,
- .run_sched_var = GFS_DYNAMIC,
- .run_sched_chunk_size = 1,
- .default_device_var = 0,
- .dyn_var = false,
- .max_active_levels_var = 1,
- .bind_var = omp_proc_bind_false,
- .target_data = NULL
- };
- bool gomp_cancel_var = false;
- enum gomp_target_offload_t gomp_target_offload_var
- = GOMP_TARGET_OFFLOAD_DEFAULT;
- int gomp_max_task_priority_var = 0;
- #ifndef HAVE_SYNC_BUILTINS
- gomp_mutex_t gomp_managed_threads_lock;
- #endif
- unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
- unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
- unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
- char *gomp_bind_var_list;
- unsigned long gomp_bind_var_list_len;
- void **gomp_places_list;
- unsigned long gomp_places_list_len;
- uintptr_t gomp_def_allocator = omp_default_mem_alloc;
- int gomp_debug_var;
- unsigned int gomp_num_teams_var;
- int gomp_nteams_var;
- int gomp_teams_thread_limit_var;
- bool gomp_display_affinity_var;
- char *gomp_affinity_format_var = "level %L thread %i affinity %A";
- size_t gomp_affinity_format_len;
- char *goacc_device_type;
- int goacc_device_num;
- int goacc_default_dims[GOMP_DIM_MAX];
- #ifndef LIBGOMP_OFFLOADED_ONLY
- static int wait_policy;
- static unsigned long stacksize = GOMP_DEFAULT_STACKSIZE;
- /* Parse the OMP_SCHEDULE environment variable. */
- static void
- parse_schedule (void)
- {
- char *env, *end;
- unsigned long value;
- int monotonic = 0;
- env = getenv ("OMP_SCHEDULE");
- if (env == NULL)
- return;
- while (isspace ((unsigned char) *env))
- ++env;
- if (strncasecmp (env, "monotonic", 9) == 0)
- {
- monotonic = 1;
- env += 9;
- }
- else if (strncasecmp (env, "nonmonotonic", 12) == 0)
- {
- monotonic = -1;
- env += 12;
- }
- if (monotonic)
- {
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != ':')
- goto unknown;
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- if (strncasecmp (env, "static", 6) == 0)
- {
- gomp_global_icv.run_sched_var = GFS_STATIC;
- env += 6;
- }
- else if (strncasecmp (env, "dynamic", 7) == 0)
- {
- gomp_global_icv.run_sched_var = GFS_DYNAMIC;
- env += 7;
- }
- else if (strncasecmp (env, "guided", 6) == 0)
- {
- gomp_global_icv.run_sched_var = GFS_GUIDED;
- env += 6;
- }
- else if (strncasecmp (env, "auto", 4) == 0)
- {
- gomp_global_icv.run_sched_var = GFS_AUTO;
- env += 4;
- }
- else
- goto unknown;
- if (monotonic == 1
- || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC))
- gomp_global_icv.run_sched_var |= GFS_MONOTONIC;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- {
- gomp_global_icv.run_sched_chunk_size
- = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC;
- return;
- }
- if (*env++ != ',')
- goto unknown;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- errno = 0;
- value = strtoul (env, &end, 10);
- if (errno || end == env)
- goto invalid;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- goto invalid;
- if ((int)value != value)
- goto invalid;
- if (value == 0
- && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC)
- value = 1;
- gomp_global_icv.run_sched_chunk_size = value;
- return;
- unknown:
- gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
- return;
- invalid:
- gomp_error ("Invalid value for chunk size in "
- "environment variable OMP_SCHEDULE");
- return;
- }
- /* Parse an unsigned long environment variable. Return true if one was
- present and it was successfully parsed. If SECURE, use secure_getenv to the
- environment variable. */
- static bool
- parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
- bool secure)
- {
- char *env, *end;
- unsigned long value;
- env = (secure ? secure_getenv (name) : getenv (name));
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- errno = 0;
- value = strtoul (env, &end, 10);
- if (errno || end == env || (long) value <= 0 - allow_zero)
- goto invalid;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- goto invalid;
- *pvalue = value;
- return true;
- invalid:
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- /* As parse_unsigned_long_1, but always use getenv. */
- static bool
- parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
- {
- return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
- }
- /* Parse a positive int environment variable. Return true if one was
- present and it was successfully parsed. If SECURE, use secure_getenv to the
- environment variable. */
- static bool
- parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
- {
- unsigned long value;
- if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
- return false;
- if (value > INT_MAX)
- {
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- *pvalue = (int) value;
- return true;
- }
- /* As parse_int_1, but use getenv. */
- static bool
- parse_int (const char *name, int *pvalue, bool allow_zero)
- {
- return parse_int_1 (name, pvalue, allow_zero, false);
- }
- /* As parse_int_1, but use getenv_secure. */
- static bool
- parse_int_secure (const char *name, int *pvalue, bool allow_zero)
- {
- return parse_int_1 (name, pvalue, allow_zero, true);
- }
- /* Parse an unsigned long list environment variable. Return true if one was
- present and it was successfully parsed. */
- static bool
- parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
- unsigned long **pvalues,
- unsigned long *pnvalues)
- {
- char *env, *end;
- unsigned long value, *values = NULL;
- env = getenv (name);
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- errno = 0;
- value = strtoul (env, &end, 10);
- if (errno || (long) value <= 0)
- goto invalid;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- {
- if (*end == ',')
- {
- unsigned long nvalues = 0, nalloced = 0;
- do
- {
- env = end + 1;
- if (nvalues == nalloced)
- {
- unsigned long *n;
- nalloced = nalloced ? nalloced * 2 : 16;
- n = realloc (values, nalloced * sizeof (unsigned long));
- if (n == NULL)
- {
- free (values);
- gomp_error ("Out of memory while trying to parse"
- " environment variable %s", name);
- return false;
- }
- values = n;
- if (nvalues == 0)
- values[nvalues++] = value;
- }
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- errno = 0;
- value = strtoul (env, &end, 10);
- if (errno || (long) value <= 0)
- goto invalid;
- values[nvalues++] = value;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end == '\0')
- break;
- if (*end != ',')
- goto invalid;
- }
- while (1);
- *p1stvalue = values[0];
- *pvalues = values;
- *pnvalues = nvalues;
- return true;
- }
- goto invalid;
- }
- *p1stvalue = value;
- return true;
- invalid:
- free (values);
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- static void
- parse_target_offload (const char *name, enum gomp_target_offload_t *offload)
- {
- const char *env;
- int new_offload = -1;
- env = getenv (name);
- if (env == NULL)
- return;
- while (isspace ((unsigned char) *env))
- ++env;
- if (strncasecmp (env, "default", 7) == 0)
- {
- env += 7;
- new_offload = GOMP_TARGET_OFFLOAD_DEFAULT;
- }
- else if (strncasecmp (env, "mandatory", 9) == 0)
- {
- env += 9;
- new_offload = GOMP_TARGET_OFFLOAD_MANDATORY;
- }
- else if (strncasecmp (env, "disabled", 8) == 0)
- {
- env += 8;
- new_offload = GOMP_TARGET_OFFLOAD_DISABLED;
- }
- while (isspace ((unsigned char) *env))
- ++env;
- if (new_offload != -1 && *env == '\0')
- {
- *offload = new_offload;
- return;
- }
- gomp_error ("Invalid value for environment variable OMP_TARGET_OFFLOAD");
- }
- /* Parse environment variable set to a boolean or list of omp_proc_bind_t
- enum values. Return true if one was present and it was successfully
- parsed. */
- static bool
- parse_bind_var (const char *name, char *p1stvalue,
- char **pvalues, unsigned long *pnvalues)
- {
- char *env;
- char value = omp_proc_bind_false, *values = NULL;
- int i;
- static struct proc_bind_kinds
- {
- const char name[7];
- const char len;
- omp_proc_bind_t kind;
- } kinds[] =
- {
- { "false", 5, omp_proc_bind_false },
- { "true", 4, omp_proc_bind_true },
- { "master", 6, omp_proc_bind_master },
- { "primary", 7, omp_proc_bind_primary },
- { "close", 5, omp_proc_bind_close },
- { "spread", 6, omp_proc_bind_spread }
- };
- env = getenv (name);
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- for (i = 0; i < 6; i++)
- if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
- {
- value = kinds[i].kind;
- env += kinds[i].len;
- break;
- }
- if (i == 6)
- goto invalid;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != '\0')
- {
- if (*env == ',')
- {
- unsigned long nvalues = 0, nalloced = 0;
- if (value == omp_proc_bind_false
- || value == omp_proc_bind_true)
- goto invalid;
- do
- {
- env++;
- if (nvalues == nalloced)
- {
- char *n;
- nalloced = nalloced ? nalloced * 2 : 16;
- n = realloc (values, nalloced);
- if (n == NULL)
- {
- free (values);
- gomp_error ("Out of memory while trying to parse"
- " environment variable %s", name);
- return false;
- }
- values = n;
- if (nvalues == 0)
- values[nvalues++] = value;
- }
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- for (i = 2; i < 6; i++)
- if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
- {
- value = kinds[i].kind;
- env += kinds[i].len;
- break;
- }
- if (i == 6)
- goto invalid;
- values[nvalues++] = value;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- break;
- if (*env != ',')
- goto invalid;
- }
- while (1);
- *p1stvalue = values[0];
- *pvalues = values;
- *pnvalues = nvalues;
- return true;
- }
- goto invalid;
- }
- *p1stvalue = value;
- return true;
- invalid:
- free (values);
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- static bool
- parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
- long *stridep)
- {
- char *env = *envp, *start;
- void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
- unsigned long len = 1;
- long stride = 1;
- int pass;
- bool any_negate = false;
- bool has_braces = true;
- *negatep = false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '!')
- {
- *negatep = true;
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- if (*env != '{')
- {
- char *end;
- unsigned long this_num;
- errno = 0;
- this_num = strtoul (env, &end, 10);
- if (errno || end == env)
- return false;
- env = end - 1;
- has_braces = false;
- if (gomp_places_list
- && !gomp_affinity_add_cpus (p, this_num, 1, 1, false))
- return false;
- }
- else
- {
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- start = env;
- for (pass = 0; pass < (any_negate ? 2 : has_braces); pass++)
- {
- env = start;
- do
- {
- unsigned long this_num, this_len = 1;
- long this_stride = 1;
- bool this_negate = (*env == '!');
- char *end;
- if (this_negate)
- {
- if (gomp_places_list)
- any_negate = true;
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- errno = 0;
- this_num = strtoul (env, &end, 10);
- if (errno || end == env)
- return false;
- env = end;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == ':')
- {
- ++env;
- if (this_negate)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- this_len = strtoul (env, &env, 10);
- if (errno || this_len == 0)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == ':')
- {
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- this_stride = strtol (env, &end, 10);
- if (errno || end == env)
- return false;
- env = end;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- }
- if (gomp_places_list && pass == this_negate)
- {
- if (this_negate)
- {
- if (!gomp_affinity_remove_cpu (p, this_num))
- return false;
- }
- else if (!gomp_affinity_add_cpus (p, this_num, this_len,
- this_stride, false))
- return false;
- }
- if (*env == '}')
- break;
- if (*env != ',')
- return false;
- ++env;
- }
- while (1);
- }
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == ':')
- {
- char *end;
- if (*negatep)
- return false;
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- len = strtoul (env, &env, 10);
- if (errno || len == 0 || len >= 65536)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == ':')
- {
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- stride = strtol (env, &end, 10);
- if (errno || end == env)
- return false;
- env = end;
- while (isspace ((unsigned char) *env))
- ++env;
- }
- }
- *envp = env;
- *lenp = len;
- *stridep = stride;
- return true;
- }
- static bool
- parse_places_var (const char *name, bool ignore)
- {
- char *env = getenv (name), *end;
- bool any_negate = false;
- int level = 0;
- unsigned long count = 0;
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- if (strncasecmp (env, "threads", 7) == 0)
- {
- env += 7;
- level = 1;
- }
- else if (strncasecmp (env, "cores", 5) == 0)
- {
- env += 5;
- level = 2;
- }
- else if (strncasecmp (env, "sockets", 7) == 0)
- {
- env += 7;
- level = 3;
- }
- else if (strncasecmp (env, "ll_caches", 9) == 0)
- {
- env += 9;
- level = 4;
- }
- else if (strncasecmp (env, "numa_domains", 12) == 0)
- {
- env += 12;
- level = 5;
- }
- if (level)
- {
- count = ULONG_MAX;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != '\0')
- {
- if (*env++ != '(')
- goto invalid;
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- count = strtoul (env, &end, 10);
- if (errno || end == env)
- goto invalid;
- env = end;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != ')')
- goto invalid;
- ++env;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != '\0')
- goto invalid;
- }
- if (ignore)
- return false;
- return gomp_affinity_init_level (level, count, false);
- }
- count = 0;
- end = env;
- do
- {
- bool negate;
- unsigned long len;
- long stride;
- if (!parse_one_place (&end, &negate, &len, &stride))
- goto invalid;
- if (negate)
- {
- if (!any_negate)
- count++;
- any_negate = true;
- }
- else
- count += len;
- if (count > 65536)
- goto invalid;
- if (*end == '\0')
- break;
- if (*end != ',')
- goto invalid;
- end++;
- }
- while (1);
- if (ignore)
- return false;
- gomp_places_list_len = 0;
- gomp_places_list = gomp_affinity_alloc (count, false);
- if (gomp_places_list == NULL)
- return false;
- do
- {
- bool negate;
- unsigned long len;
- long stride;
- gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
- if (!parse_one_place (&env, &negate, &len, &stride))
- goto invalid;
- if (negate)
- {
- void *p;
- for (count = 0; count < gomp_places_list_len; count++)
- if (gomp_affinity_same_place
- (gomp_places_list[count],
- gomp_places_list[gomp_places_list_len]))
- break;
- if (count == gomp_places_list_len)
- {
- gomp_error ("Trying to remove a non-existing place from list "
- "of places");
- goto invalid;
- }
- p = gomp_places_list[count];
- memmove (&gomp_places_list[count],
- &gomp_places_list[count + 1],
- (gomp_places_list_len - count - 1) * sizeof (void *));
- --gomp_places_list_len;
- gomp_places_list[gomp_places_list_len] = p;
- }
- else if (len == 1)
- ++gomp_places_list_len;
- else
- {
- for (count = 0; count < len - 1; count++)
- if (!gomp_affinity_copy_place
- (gomp_places_list[gomp_places_list_len + count + 1],
- gomp_places_list[gomp_places_list_len + count],
- stride))
- goto invalid;
- gomp_places_list_len += len;
- }
- if (*env == '\0')
- break;
- env++;
- }
- while (1);
- if (gomp_places_list_len == 0)
- {
- gomp_error ("All places have been removed");
- goto invalid;
- }
- if (!gomp_affinity_finalize_place_list (false))
- goto invalid;
- return true;
- invalid:
- free (gomp_places_list);
- gomp_places_list = NULL;
- gomp_places_list_len = 0;
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- /* Parse the OMP_STACKSIZE environment varible. Return true if one was
- present and it was successfully parsed. */
- static bool
- parse_stacksize (const char *name, unsigned long *pvalue)
- {
- char *env, *end;
- unsigned long value, shift = 10;
- env = getenv (name);
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- errno = 0;
- value = strtoul (env, &end, 10);
- if (errno || end == env)
- goto invalid;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- {
- switch (tolower ((unsigned char) *end))
- {
- case 'b':
- shift = 0;
- break;
- case 'k':
- break;
- case 'm':
- shift = 20;
- break;
- case 'g':
- shift = 30;
- break;
- default:
- goto invalid;
- }
- ++end;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- goto invalid;
- }
- if (((value << shift) >> shift) != value)
- goto invalid;
- *pvalue = value << shift;
- return true;
- invalid:
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
- present and it was successfully parsed. */
- static bool
- parse_spincount (const char *name, unsigned long long *pvalue)
- {
- char *env, *end;
- unsigned long long value, mult = 1;
- env = getenv (name);
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- goto invalid;
- if (strncasecmp (env, "infinite", 8) == 0
- || strncasecmp (env, "infinity", 8) == 0)
- {
- value = ~0ULL;
- end = env + 8;
- goto check_tail;
- }
- errno = 0;
- value = strtoull (env, &end, 10);
- if (errno || end == env)
- goto invalid;
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- {
- switch (tolower ((unsigned char) *end))
- {
- case 'k':
- mult = 1000LL;
- break;
- case 'm':
- mult = 1000LL * 1000LL;
- break;
- case 'g':
- mult = 1000LL * 1000LL * 1000LL;
- break;
- case 't':
- mult = 1000LL * 1000LL * 1000LL * 1000LL;
- break;
- default:
- goto invalid;
- }
- ++end;
- check_tail:
- while (isspace ((unsigned char) *end))
- ++end;
- if (*end != '\0')
- goto invalid;
- }
- if (value > ~0ULL / mult)
- value = ~0ULL;
- else
- value *= mult;
- *pvalue = value;
- return true;
- invalid:
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- /* Parse a boolean value for environment variable NAME and store the
- result in VALUE. Return true if one was present and it was
- successfully parsed. */
- static bool
- parse_boolean (const char *name, bool *value)
- {
- const char *env;
- env = getenv (name);
- if (env == NULL)
- return false;
- while (isspace ((unsigned char) *env))
- ++env;
- if (strncasecmp (env, "true", 4) == 0)
- {
- *value = true;
- env += 4;
- }
- else if (strncasecmp (env, "false", 5) == 0)
- {
- *value = false;
- env += 5;
- }
- else
- env = "X";
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != '\0')
- {
- gomp_error ("Invalid value for environment variable %s", name);
- return false;
- }
- return true;
- }
- /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
- static int
- parse_wait_policy (void)
- {
- const char *env;
- int ret = -1;
- env = getenv ("OMP_WAIT_POLICY");
- if (env == NULL)
- return -1;
- while (isspace ((unsigned char) *env))
- ++env;
- if (strncasecmp (env, "active", 6) == 0)
- {
- ret = 1;
- env += 6;
- }
- else if (strncasecmp (env, "passive", 7) == 0)
- {
- ret = 0;
- env += 7;
- }
- else
- env = "X";
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- return ret;
- gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
- return -1;
- }
- /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
- present and it was successfully parsed. */
- static bool
- parse_affinity (bool ignore)
- {
- char *env, *end, *start;
- int pass;
- unsigned long cpu_beg, cpu_end, cpu_stride;
- size_t count = 0, needed;
- env = getenv ("GOMP_CPU_AFFINITY");
- if (env == NULL)
- return false;
- start = env;
- for (pass = 0; pass < 2; pass++)
- {
- env = start;
- if (pass == 1)
- {
- if (ignore)
- return false;
- gomp_places_list_len = 0;
- gomp_places_list = gomp_affinity_alloc (count, true);
- if (gomp_places_list == NULL)
- return false;
- }
- do
- {
- while (isspace ((unsigned char) *env))
- ++env;
- errno = 0;
- cpu_beg = strtoul (env, &end, 0);
- if (errno || end == env || cpu_beg >= 65536)
- goto invalid;
- cpu_end = cpu_beg;
- cpu_stride = 1;
- env = end;
- if (*env == '-')
- {
- errno = 0;
- cpu_end = strtoul (++env, &end, 0);
- if (errno || end == env || cpu_end >= 65536 || cpu_end < cpu_beg)
- goto invalid;
- env = end;
- if (*env == ':')
- {
- errno = 0;
- cpu_stride = strtoul (++env, &end, 0);
- if (errno || cpu_stride == 0 || cpu_stride >= 65536)
- goto invalid;
- env = end;
- }
- }
- needed = (cpu_end - cpu_beg) / cpu_stride + 1;
- if (pass == 0)
- count += needed;
- else
- {
- while (needed--)
- {
- void *p = gomp_places_list[gomp_places_list_len];
- gomp_affinity_init_place (p);
- if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
- ++gomp_places_list_len;
- cpu_beg += cpu_stride;
- }
- }
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == ',')
- env++;
- else if (*env == '\0')
- break;
- }
- while (1);
- }
- if (gomp_places_list_len == 0)
- {
- free (gomp_places_list);
- gomp_places_list = NULL;
- return false;
- }
- return true;
- invalid:
- gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
- return false;
- }
- /* Parse the OMP_ALLOCATOR environment variable and return the value. */
- static uintptr_t
- parse_allocator (void)
- {
- const char *env;
- uintptr_t ret = omp_default_mem_alloc;
- env = getenv ("OMP_ALLOCATOR");
- if (env == NULL)
- return ret;
- while (isspace ((unsigned char) *env))
- ++env;
- if (0)
- ;
- #define C(v) \
- else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
- { \
- ret = v; \
- env += sizeof (#v) - 1; \
- }
- C (omp_default_mem_alloc)
- C (omp_large_cap_mem_alloc)
- C (omp_const_mem_alloc)
- C (omp_high_bw_mem_alloc)
- C (omp_low_lat_mem_alloc)
- C (omp_cgroup_mem_alloc)
- C (omp_pteam_mem_alloc)
- C (omp_thread_mem_alloc)
- #undef C
- else
- env = "X";
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env == '\0')
- return ret;
- gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
- return omp_default_mem_alloc;
- }
- static void
- parse_acc_device_type (void)
- {
- const char *env = getenv ("ACC_DEVICE_TYPE");
- if (env && *env != '\0')
- goacc_device_type = strdup (env);
- else
- goacc_device_type = NULL;
- }
- static void
- parse_gomp_openacc_dim (void)
- {
- /* The syntax is the same as for the -fopenacc-dim compilation option. */
- const char *var_name = "GOMP_OPENACC_DIM";
- const char *env_var = getenv (var_name);
- const char *pos = env_var;
- int i;
- if (!env_var)
- return;
- for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
- {
- char *eptr;
- long val;
- if (i && *pos++ != ':')
- break;
- if (*pos == ':')
- continue;
- errno = 0;
- val = strtol (pos, &eptr, 10);
- if (errno || eptr == pos || val < 0 || (unsigned)val != val)
- break;
- goacc_default_dims[i] = (int)val;
- pos = (const char *) eptr;
- }
- }
- void
- omp_display_env (int verbose)
- {
- int i;
- fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
- fputs (" _OPENMP = '201511'\n", stderr);
- fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
- gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
- fprintf (stderr, " OMP_NESTED = '%s'\n",
- gomp_global_icv.max_active_levels_var > 1 ? "TRUE" : "FALSE");
- fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
- for (i = 1; i < gomp_nthreads_var_list_len; i++)
- fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
- fputs ("'\n", stderr);
- fprintf (stderr, " OMP_SCHEDULE = '");
- if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
- {
- if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
- fputs ("MONOTONIC:", stderr);
- }
- else if (gomp_global_icv.run_sched_var == GFS_STATIC)
- fputs ("NONMONOTONIC:", stderr);
- switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
- {
- case GFS_RUNTIME:
- fputs ("RUNTIME", stderr);
- if (gomp_global_icv.run_sched_chunk_size != 1)
- fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
- break;
- case GFS_STATIC:
- fputs ("STATIC", stderr);
- if (gomp_global_icv.run_sched_chunk_size != 0)
- fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
- break;
- case GFS_DYNAMIC:
- fputs ("DYNAMIC", stderr);
- if (gomp_global_icv.run_sched_chunk_size != 1)
- fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
- break;
- case GFS_GUIDED:
- fputs ("GUIDED", stderr);
- if (gomp_global_icv.run_sched_chunk_size != 1)
- fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
- break;
- case GFS_AUTO:
- fputs ("AUTO", stderr);
- break;
- }
- fputs ("'\n", stderr);
- fputs (" OMP_PROC_BIND = '", stderr);
- switch (gomp_global_icv.bind_var)
- {
- case omp_proc_bind_false:
- fputs ("FALSE", stderr);
- break;
- case omp_proc_bind_true:
- fputs ("TRUE", stderr);
- break;
- case omp_proc_bind_master:
- fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
- break;
- case omp_proc_bind_close:
- fputs ("CLOSE", stderr);
- break;
- case omp_proc_bind_spread:
- fputs ("SPREAD", stderr);
- break;
- }
- for (i = 1; i < gomp_bind_var_list_len; i++)
- switch (gomp_bind_var_list[i])
- {
- case omp_proc_bind_master:
- fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
- break;
- case omp_proc_bind_close:
- fputs (",CLOSE", stderr);
- break;
- case omp_proc_bind_spread:
- fputs (",SPREAD", stderr);
- break;
- }
- fputs ("'\n", stderr);
- fputs (" OMP_PLACES = '", stderr);
- for (i = 0; i < gomp_places_list_len; i++)
- {
- fputs ("{", stderr);
- gomp_affinity_print_place (gomp_places_list[i]);
- fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
- }
- fputs ("'\n", stderr);
- fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
- /* GOMP's default value is actually neither active nor passive. */
- fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
- wait_policy > 0 ? "ACTIVE" : "PASSIVE");
- fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
- gomp_global_icv.thread_limit_var);
- fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%u'\n",
- gomp_global_icv.max_active_levels_var);
- fprintf (stderr, " OMP_NUM_TEAMS = '%u'\n", gomp_nteams_var);
- fprintf (stderr, " OMP_TEAMS_THREAD_LIMIT = '%u'\n",
- gomp_teams_thread_limit_var);
- fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
- gomp_cancel_var ? "TRUE" : "FALSE");
- fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
- gomp_global_icv.default_device_var);
- fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
- gomp_max_task_priority_var);
- fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n",
- gomp_display_affinity_var ? "TRUE" : "FALSE");
- fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
- gomp_affinity_format_var);
- fprintf (stderr, " OMP_ALLOCATOR = '");
- switch (gomp_def_allocator)
- {
- #define C(v) case v: fputs (#v, stderr); break;
- C (omp_default_mem_alloc)
- C (omp_large_cap_mem_alloc)
- C (omp_const_mem_alloc)
- C (omp_high_bw_mem_alloc)
- C (omp_low_lat_mem_alloc)
- C (omp_cgroup_mem_alloc)
- C (omp_pteam_mem_alloc)
- C (omp_thread_mem_alloc)
- #undef C
- default: break;
- }
- fputs ("'\n", stderr);
- fputs (" OMP_TARGET_OFFLOAD = '", stderr);
- switch (gomp_target_offload_var)
- {
- case GOMP_TARGET_OFFLOAD_DEFAULT:
- fputs ("DEFAULT", stderr);
- break;
- case GOMP_TARGET_OFFLOAD_MANDATORY:
- fputs ("MANDATORY", stderr);
- break;
- case GOMP_TARGET_OFFLOAD_DISABLED:
- fputs ("DISABLED", stderr);
- break;
- }
- fputs ("'\n", stderr);
- if (verbose)
- {
- fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
- fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
- #ifdef HAVE_INTTYPES_H
- fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
- (uint64_t) gomp_spin_count_var);
- #else
- fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
- (unsigned long) gomp_spin_count_var);
- #endif
- }
- fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
- }
- ialias (omp_display_env)
- static void
- handle_omp_display_env (void)
- {
- const char *env;
- bool display = false;
- bool verbose = false;
- env = getenv ("OMP_DISPLAY_ENV");
- if (env == NULL)
- return;
- while (isspace ((unsigned char) *env))
- ++env;
- if (strncasecmp (env, "true", 4) == 0)
- {
- display = true;
- env += 4;
- }
- else if (strncasecmp (env, "false", 5) == 0)
- {
- display = false;
- env += 5;
- }
- else if (strncasecmp (env, "verbose", 7) == 0)
- {
- display = true;
- verbose = true;
- env += 7;
- }
- else
- env = "X";
- while (isspace ((unsigned char) *env))
- ++env;
- if (*env != '\0')
- gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
- if (display)
- ialias_call (omp_display_env) (verbose);
- }
- static void __attribute__((constructor))
- initialize_env (void)
- {
- unsigned long thread_limit_var;
- unsigned long max_active_levels_var;
- /* Do a compile time check that mkomp_h.pl did good job. */
- omp_check_defines ();
- parse_schedule ();
- parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
- parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
- parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var);
- parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
- parse_target_offload ("OMP_TARGET_OFFLOAD", &gomp_target_offload_var);
- parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
- gomp_def_allocator = parse_allocator ();
- if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
- {
- gomp_global_icv.thread_limit_var
- = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
- }
- parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
- #ifndef HAVE_SYNC_BUILTINS
- gomp_mutex_init (&gomp_managed_threads_lock);
- #endif
- gomp_init_num_threads ();
- gomp_available_cpus = gomp_global_icv.nthreads_var;
- if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
- &gomp_global_icv.nthreads_var,
- &gomp_nthreads_var_list,
- &gomp_nthreads_var_list_len))
- gomp_global_icv.nthreads_var = gomp_available_cpus;
- parse_int ("OMP_NUM_TEAMS", &gomp_nteams_var, false);
- parse_int ("OMP_TEAMS_THREAD_LIMIT", &gomp_teams_thread_limit_var, false);
- bool ignore = false;
- if (parse_bind_var ("OMP_PROC_BIND",
- &gomp_global_icv.bind_var,
- &gomp_bind_var_list,
- &gomp_bind_var_list_len)
- && gomp_global_icv.bind_var == omp_proc_bind_false)
- ignore = true;
- if (parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS",
- &max_active_levels_var, true))
- gomp_global_icv.max_active_levels_var
- = (max_active_levels_var > gomp_supported_active_levels)
- ? gomp_supported_active_levels : max_active_levels_var;
- else
- {
- bool nested = true;
- /* OMP_NESTED is deprecated in OpenMP 5.0. */
- if (parse_boolean ("OMP_NESTED", &nested))
- gomp_global_icv.max_active_levels_var
- = nested ? gomp_supported_active_levels : 1;
- else if (gomp_nthreads_var_list_len > 1 || gomp_bind_var_list_len > 1)
- gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
- }
- /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
- parsed if present in the environment. If OMP_PROC_BIND was set
- explicitly to false, don't populate places list though. If places
- list was successfully set from OMP_PLACES, only parse but don't process
- GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
- default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
- was successfully parsed into a places list, otherwise to
- OMP_PROC_BIND=false. */
- if (parse_places_var ("OMP_PLACES", ignore))
- {
- if (gomp_global_icv.bind_var == omp_proc_bind_false)
- gomp_global_icv.bind_var = true;
- ignore = true;
- }
- if (parse_affinity (ignore))
- {
- if (gomp_global_icv.bind_var == omp_proc_bind_false)
- gomp_global_icv.bind_var = true;
- ignore = true;
- }
- if (gomp_global_icv.bind_var != omp_proc_bind_false)
- gomp_init_affinity ();
- {
- const char *env = getenv ("OMP_AFFINITY_FORMAT");
- if (env != NULL)
- gomp_set_affinity_format (env, strlen (env));
- }
- wait_policy = parse_wait_policy ();
- if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
- {
- /* Using a rough estimation of 100000 spins per msec,
- use 5 min blocking for OMP_WAIT_POLICY=active,
- 3 msec blocking when OMP_WAIT_POLICY is not specificed
- and 0 when OMP_WAIT_POLICY=passive.
- Depending on the CPU speed, this can be e.g. 5 times longer
- or 5 times shorter. */
- if (wait_policy > 0)
- gomp_spin_count_var = 30000000000LL;
- else if (wait_policy < 0)
- gomp_spin_count_var = 300000LL;
- }
- /* gomp_throttled_spin_count_var is used when there are more libgomp
- managed threads than available CPUs. Use very short spinning. */
- if (wait_policy > 0)
- gomp_throttled_spin_count_var = 1000LL;
- else if (wait_policy < 0)
- gomp_throttled_spin_count_var = 100LL;
- if (gomp_throttled_spin_count_var > gomp_spin_count_var)
- gomp_throttled_spin_count_var = gomp_spin_count_var;
- /* Not strictly environment related, but ordering constructors is tricky. */
- pthread_attr_init (&gomp_thread_attr);
- if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
- || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
- || GOMP_DEFAULT_STACKSIZE)
- {
- int err;
- err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
- #ifdef PTHREAD_STACK_MIN
- if (err == EINVAL)
- {
- if (stacksize < PTHREAD_STACK_MIN)
- gomp_error ("Stack size less than minimum of %luk",
- PTHREAD_STACK_MIN / 1024ul
- + (PTHREAD_STACK_MIN % 1024 != 0));
- else
- gomp_error ("Stack size larger than system limit");
- }
- else
- #endif
- if (err != 0)
- gomp_error ("Stack size change failed: %s", strerror (err));
- }
- handle_omp_display_env ();
- /* OpenACC. */
- if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
- goacc_device_num = 0;
- parse_acc_device_type ();
- parse_gomp_openacc_dim ();
- goacc_runtime_initialize ();
- goacc_profiling_initialize ();
- }
- #endif /* LIBGOMP_OFFLOADED_ONLY */
|