1 /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
2 Free Software Foundation, Inc.
3 Contributed by Richard Henderson <rth@redhat.com>.
5 This file is part of the GNU OpenMP Library (libgomp).
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)
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
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.
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/>. */
26 /* This file defines the OpenMP internal control variables, and arranges
27 for them to be initialized from environment variables at startup. */
30 #include "libgomp_f.h"
33 #ifdef STRING_WITH_STRINGS
40 # ifdef HAVE_STRINGS_H
49 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
52 struct gomp_task_icv gomp_global_icv = {
54 .run_sched_var = GFS_DYNAMIC,
55 .run_sched_modifier = 1,
60 unsigned short *gomp_cpu_affinity;
61 size_t gomp_cpu_affinity_len;
62 unsigned long gomp_max_active_levels_var = INT_MAX;
63 unsigned long gomp_thread_limit_var = ULONG_MAX;
64 unsigned long gomp_remaining_threads_count;
65 #ifndef HAVE_SYNC_BUILTINS
66 gomp_mutex_t gomp_remaining_threads_lock;
68 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
69 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
71 /* Parse the OMP_SCHEDULE environment variable. */
79 env = getenv ("OMP_SCHEDULE");
83 while (isspace ((unsigned char) *env))
85 if (strncasecmp (env, "static", 6) == 0)
87 gomp_global_icv.run_sched_var = GFS_STATIC;
90 else if (strncasecmp (env, "dynamic", 7) == 0)
92 gomp_global_icv.run_sched_var = GFS_DYNAMIC;
95 else if (strncasecmp (env, "guided", 6) == 0)
97 gomp_global_icv.run_sched_var = GFS_GUIDED;
100 else if (strncasecmp (env, "auto", 4) == 0)
102 gomp_global_icv.run_sched_var = GFS_AUTO;
108 while (isspace ((unsigned char) *env))
112 gomp_global_icv.run_sched_modifier
113 = gomp_global_icv.run_sched_var != GFS_STATIC;
118 while (isspace ((unsigned char) *env))
124 value = strtoul (env, &end, 10);
128 while (isspace ((unsigned char) *end))
133 if ((int)value != value)
136 if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
138 gomp_global_icv.run_sched_modifier = value;
142 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
146 gomp_error ("Invalid value for chunk size in "
147 "environment variable OMP_SCHEDULE");
151 /* Parse an unsigned long environment variable. Return true if one was
152 present and it was successfully parsed. */
155 parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
164 while (isspace ((unsigned char) *env))
170 value = strtoul (env, &end, 10);
171 if (errno || (long) value <= 0 - allow_zero)
174 while (isspace ((unsigned char) *end))
183 gomp_error ("Invalid value for environment variable %s", name);
187 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
188 present and it was successfully parsed. */
191 parse_stacksize (const char *name, unsigned long *pvalue)
194 unsigned long value, shift = 10;
200 while (isspace ((unsigned char) *env))
206 value = strtoul (env, &end, 10);
210 while (isspace ((unsigned char) *end))
214 switch (tolower ((unsigned char) *end))
231 while (isspace ((unsigned char) *end))
237 if (((value << shift) >> shift) != value)
240 *pvalue = value << shift;
244 gomp_error ("Invalid value for environment variable %s", name);
248 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
249 present and it was successfully parsed. */
252 parse_spincount (const char *name, unsigned long long *pvalue)
255 unsigned long long value, mult = 1;
261 while (isspace ((unsigned char) *env))
266 if (strncasecmp (env, "infinite", 8) == 0
267 || strncasecmp (env, "infinity", 8) == 0)
275 value = strtoull (env, &end, 10);
279 while (isspace ((unsigned char) *end))
283 switch (tolower ((unsigned char) *end))
289 mult = 1000LL * 1000LL;
292 mult = 1000LL * 1000LL * 1000LL;
295 mult = 1000LL * 1000LL * 1000LL * 1000LL;
302 while (isspace ((unsigned char) *end))
308 if (value > ~0ULL / mult)
317 gomp_error ("Invalid value for environment variable %s", name);
321 /* Parse a boolean value for environment variable NAME and store the
325 parse_boolean (const char *name, bool *value)
333 while (isspace ((unsigned char) *env))
335 if (strncasecmp (env, "true", 4) == 0)
340 else if (strncasecmp (env, "false", 5) == 0)
347 while (isspace ((unsigned char) *env))
350 gomp_error ("Invalid value for environment variable %s", name);
353 /* Parse the OMP_WAIT_POLICY environment variable and store the
354 result in gomp_active_wait_policy. */
357 parse_wait_policy (void)
362 env = getenv ("OMP_WAIT_POLICY");
366 while (isspace ((unsigned char) *env))
368 if (strncasecmp (env, "active", 6) == 0)
373 else if (strncasecmp (env, "passive", 7) == 0)
380 while (isspace ((unsigned char) *env))
384 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
388 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
389 present and it was successfully parsed. */
392 parse_affinity (void)
395 unsigned long cpu_beg, cpu_end, cpu_stride;
396 unsigned short *cpus = NULL;
397 size_t allocated = 0, used = 0, needed;
399 env = getenv ("GOMP_CPU_AFFINITY");
405 while (*env == ' ' || *env == '\t')
408 cpu_beg = strtoul (env, &end, 0);
411 if (env == end || cpu_beg >= 65536)
417 cpu_end = strtoul (++env, &end, 0);
418 if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
424 cpu_stride = strtoul (++env, &end, 0);
425 if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
432 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
433 if (used + needed >= allocated)
435 unsigned short *new_cpus;
439 if (allocated > needed)
442 allocated += 2 * needed;
443 new_cpus = realloc (cpus, allocated * sizeof (unsigned short));
444 if (new_cpus == NULL)
447 gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
456 cpus[used++] = cpu_beg;
457 cpu_beg += cpu_stride;
460 while (*env == ' ' || *env == '\t')
465 else if (*env == '\0')
470 gomp_cpu_affinity = cpus;
471 gomp_cpu_affinity_len = used;
475 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
479 static void __attribute__((constructor))
480 initialize_env (void)
482 unsigned long stacksize;
485 /* Do a compile time check that mkomp_h.pl did good job. */
486 omp_check_defines ();
489 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
490 parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
491 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
493 parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
494 if (gomp_thread_limit_var != ULONG_MAX)
495 gomp_remaining_threads_count = gomp_thread_limit_var - 1;
496 #ifndef HAVE_SYNC_BUILTINS
497 gomp_mutex_init (&gomp_remaining_threads_lock);
499 gomp_init_num_threads ();
500 gomp_available_cpus = gomp_global_icv.nthreads_var;
501 if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_global_icv.nthreads_var,
503 gomp_global_icv.nthreads_var = gomp_available_cpus;
504 if (parse_affinity ())
505 gomp_init_affinity ();
506 wait_policy = parse_wait_policy ();
507 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
509 /* Using a rough estimation of 100000 spins per msec,
510 use 5 min blocking for OMP_WAIT_POLICY=active,
511 3 msec blocking when OMP_WAIT_POLICY is not specificed
512 and 0 when OMP_WAIT_POLICY=passive.
513 Depending on the CPU speed, this can be e.g. 5 times longer
514 or 5 times shorter. */
516 gomp_spin_count_var = 30000000000LL;
517 else if (wait_policy < 0)
518 gomp_spin_count_var = 300000LL;
520 /* gomp_throttled_spin_count_var is used when there are more libgomp
521 managed threads than available CPUs. Use very short spinning. */
523 gomp_throttled_spin_count_var = 1000LL;
524 else if (wait_policy < 0)
525 gomp_throttled_spin_count_var = 100LL;
526 if (gomp_throttled_spin_count_var > gomp_spin_count_var)
527 gomp_throttled_spin_count_var = gomp_spin_count_var;
529 /* Not strictly environment related, but ordering constructors is tricky. */
530 pthread_attr_init (&gomp_thread_attr);
531 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
533 if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
534 || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
538 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
540 #ifdef PTHREAD_STACK_MIN
543 if (stacksize < PTHREAD_STACK_MIN)
544 gomp_error ("Stack size less than minimum of %luk",
545 PTHREAD_STACK_MIN / 1024ul
546 + (PTHREAD_STACK_MIN % 1024 != 0));
548 gomp_error ("Stack size larger than system limit");
553 gomp_error ("Stack size change failed: %s", strerror (err));
558 /* The public OpenMP API routines that access these variables. */
561 omp_set_num_threads (int n)
563 struct gomp_task_icv *icv = gomp_icv (true);
564 icv->nthreads_var = (n > 0 ? n : 1);
568 omp_set_dynamic (int val)
570 struct gomp_task_icv *icv = gomp_icv (true);
575 omp_get_dynamic (void)
577 struct gomp_task_icv *icv = gomp_icv (false);
582 omp_set_nested (int val)
584 struct gomp_task_icv *icv = gomp_icv (true);
589 omp_get_nested (void)
591 struct gomp_task_icv *icv = gomp_icv (false);
592 return icv->nest_var;
596 omp_set_schedule (omp_sched_t kind, int modifier)
598 struct gomp_task_icv *icv = gomp_icv (true);
601 case omp_sched_static:
604 icv->run_sched_modifier = modifier;
606 case omp_sched_dynamic:
607 case omp_sched_guided:
610 icv->run_sched_modifier = modifier;
617 icv->run_sched_var = kind;
621 omp_get_schedule (omp_sched_t *kind, int *modifier)
623 struct gomp_task_icv *icv = gomp_icv (false);
624 *kind = icv->run_sched_var;
625 *modifier = icv->run_sched_modifier;
629 omp_get_max_threads (void)
631 struct gomp_task_icv *icv = gomp_icv (false);
632 return icv->nthreads_var;
636 omp_get_thread_limit (void)
638 return gomp_thread_limit_var > INT_MAX ? INT_MAX : gomp_thread_limit_var;
642 omp_set_max_active_levels (int max_levels)
645 gomp_max_active_levels_var = max_levels;
649 omp_get_max_active_levels (void)
651 return gomp_max_active_levels_var;
654 ialias (omp_set_dynamic)
655 ialias (omp_set_nested)
656 ialias (omp_set_num_threads)
657 ialias (omp_get_dynamic)
658 ialias (omp_get_nested)
659 ialias (omp_set_schedule)
660 ialias (omp_get_schedule)
661 ialias (omp_get_max_threads)
662 ialias (omp_get_thread_limit)
663 ialias (omp_set_max_active_levels)
664 ialias (omp_get_max_active_levels)