#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;
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;
}
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;
}
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;
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 ();
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));
}
}
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)