diff options
Diffstat (limited to 'contrib/gcclibs/libgomp/env.c')
-rw-r--r-- | contrib/gcclibs/libgomp/env.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/contrib/gcclibs/libgomp/env.c b/contrib/gcclibs/libgomp/env.c new file mode 100644 index 0000000..f07b31b --- /dev/null +++ b/contrib/gcclibs/libgomp/env.c @@ -0,0 +1,259 @@ +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU OpenMP Library (libgomp). + + Libgomp is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for + more details. + + You should have received a copy of the GNU Lesser General Public License + along with libgomp; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* As a special exception, if you link this library with other files, some + of which are compiled with GCC, to produce an executable, this library + does not by itself cause the resulting executable to be covered by the + GNU General Public License. This exception does not however invalidate + any other reasons why the executable file might be covered by the GNU + General Public License. */ + +/* This file defines the OpenMP internal control variables, and arranges + for them to be initialized from environment variables at startup. */ + +#include "libgomp.h" +#include "libgomp_f.h" +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + + +unsigned long gomp_nthreads_var = 1; +bool gomp_dyn_var = false; +bool gomp_nest_var = false; +enum gomp_schedule_type gomp_run_sched_var = GFS_DYNAMIC; +unsigned long gomp_run_sched_chunk = 1; + +/* Parse the OMP_SCHEDULE environment variable. */ + +static void +parse_schedule (void) +{ + char *env, *end; + unsigned long value; + + env = getenv ("OMP_SCHEDULE"); + if (env == NULL) + return; + + while (isspace ((unsigned char) *env)) + ++env; + if (strncasecmp (env, "static", 6) == 0) + { + gomp_run_sched_var = GFS_STATIC; + env += 6; + } + else if (strncasecmp (env, "dynamic", 7) == 0) + { + gomp_run_sched_var = GFS_DYNAMIC; + env += 7; + } + else if (strncasecmp (env, "guided", 6) == 0) + { + gomp_run_sched_var = GFS_GUIDED; + env += 6; + } + else + goto unknown; + + while (isspace ((unsigned char) *env)) + ++env; + if (*env == '\0') + 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) + goto invalid; + + while (isspace ((unsigned char) *end)) + ++end; + if (*end != '\0') + goto invalid; + + gomp_run_sched_chunk = 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 varible. Return true if one was + present and it was successfully parsed. */ + +static bool +parse_unsigned_long (const char *name, unsigned long *pvalue) +{ + char *env, *end; + unsigned long value; + + 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') + goto invalid; + + *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. */ + +static void +parse_boolean (const char *name, bool *value) +{ + const char *env; + + env = getenv (name); + if (env == NULL) + return; + + 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); +} + +static void __attribute__((constructor)) +initialize_env (void) +{ + unsigned long stacksize; + + /* Do a compile time check that mkomp_h.pl did good job. */ + omp_check_defines (); + + parse_schedule (); + parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var); + parse_boolean ("OMP_NESTED", &gomp_nest_var); + if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var)) + gomp_init_num_threads (); + + /* Not strictly environment related, but ordering constructors is tricky. */ + pthread_attr_init (&gomp_thread_attr); + pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED); + + if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize)) + { + int err; + + stacksize *= 1024; + 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)); + } +} + + +/* The public OpenMP API routines that access these variables. */ + +void +omp_set_num_threads (int n) +{ + gomp_nthreads_var = (n > 0 ? n : 1); +} + +void +omp_set_dynamic (int val) +{ + gomp_dyn_var = val; +} + +int +omp_get_dynamic (void) +{ + return gomp_dyn_var; +} + +void +omp_set_nested (int val) +{ + gomp_nest_var = val; +} + +int +omp_get_nested (void) +{ + return gomp_nest_var; +} + +ialias (omp_set_dynamic) +ialias (omp_set_nested) +ialias (omp_set_num_threads) +ialias (omp_get_dynamic) +ialias (omp_get_nested) |