1 /* Copyright (C) 2005-2013 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU OpenMP Library (libgomp).
6 Libgomp is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 /* This file defines the OpenMP internal control variables, and arranges
26 for them to be initialized from environment variables at startup. */
29 #include "libgomp_f.h"
32 #ifdef STRING_WITH_STRINGS
39 # ifdef HAVE_STRINGS_H
48 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
51 struct gomp_task_icv gomp_global_icv
= {
53 .run_sched_var
= GFS_DYNAMIC
,
54 .run_sched_modifier
= 1,
59 unsigned short *gomp_cpu_affinity
;
60 size_t gomp_cpu_affinity_len
;
61 unsigned long gomp_max_active_levels_var
= INT_MAX
;
62 unsigned long gomp_thread_limit_var
= ULONG_MAX
;
63 unsigned long gomp_remaining_threads_count
;
64 #ifndef HAVE_SYNC_BUILTINS
65 gomp_mutex_t gomp_remaining_threads_lock
;
67 unsigned long gomp_available_cpus
= 1, gomp_managed_threads
= 1;
68 unsigned long long gomp_spin_count_var
, gomp_throttled_spin_count_var
;
69 unsigned long *gomp_nthreads_var_list
, gomp_nthreads_var_list_len
;
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 an unsigned long list environment variable. Return true if one was
188 present and it was successfully parsed. */
191 parse_unsigned_long_list (const char *name
, unsigned long *p1stvalue
,
192 unsigned long **pvalues
,
193 unsigned long *pnvalues
)
196 unsigned long value
, *values
= NULL
;
202 while (isspace ((unsigned char) *env
))
208 value
= strtoul (env
, &end
, 10);
209 if (errno
|| (long) value
<= 0)
212 while (isspace ((unsigned char) *end
))
218 unsigned long nvalues
= 0, nalloced
= 0;
223 if (nvalues
== nalloced
)
226 nalloced
= nalloced
? nalloced
* 2 : 16;
227 n
= realloc (values
, nalloced
* sizeof (unsigned long));
231 gomp_error ("Out of memory while trying to parse"
232 " environment variable %s", name
);
237 values
[nvalues
++] = value
;
240 while (isspace ((unsigned char) *env
))
246 value
= strtoul (env
, &end
, 10);
247 if (errno
|| (long) value
<= 0)
250 values
[nvalues
++] = value
;
251 while (isspace ((unsigned char) *end
))
259 *p1stvalue
= values
[0];
272 gomp_error ("Invalid value for environment variable %s", name
);
276 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
277 present and it was successfully parsed. */
280 parse_stacksize (const char *name
, unsigned long *pvalue
)
283 unsigned long value
, shift
= 10;
289 while (isspace ((unsigned char) *env
))
295 value
= strtoul (env
, &end
, 10);
299 while (isspace ((unsigned char) *end
))
303 switch (tolower ((unsigned char) *end
))
320 while (isspace ((unsigned char) *end
))
326 if (((value
<< shift
) >> shift
) != value
)
329 *pvalue
= value
<< shift
;
333 gomp_error ("Invalid value for environment variable %s", name
);
337 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
338 present and it was successfully parsed. */
341 parse_spincount (const char *name
, unsigned long long *pvalue
)
344 unsigned long long value
, mult
= 1;
350 while (isspace ((unsigned char) *env
))
355 if (strncasecmp (env
, "infinite", 8) == 0
356 || strncasecmp (env
, "infinity", 8) == 0)
364 value
= strtoull (env
, &end
, 10);
368 while (isspace ((unsigned char) *end
))
372 switch (tolower ((unsigned char) *end
))
378 mult
= 1000LL * 1000LL;
381 mult
= 1000LL * 1000LL * 1000LL;
384 mult
= 1000LL * 1000LL * 1000LL * 1000LL;
391 while (isspace ((unsigned char) *end
))
397 if (value
> ~0ULL / mult
)
406 gomp_error ("Invalid value for environment variable %s", name
);
410 /* Parse a boolean value for environment variable NAME and store the
414 parse_boolean (const char *name
, bool *value
)
422 while (isspace ((unsigned char) *env
))
424 if (strncasecmp (env
, "true", 4) == 0)
429 else if (strncasecmp (env
, "false", 5) == 0)
436 while (isspace ((unsigned char) *env
))
439 gomp_error ("Invalid value for environment variable %s", name
);
442 /* Parse the OMP_WAIT_POLICY environment variable and store the
443 result in gomp_active_wait_policy. */
446 parse_wait_policy (void)
451 env
= getenv ("OMP_WAIT_POLICY");
455 while (isspace ((unsigned char) *env
))
457 if (strncasecmp (env
, "active", 6) == 0)
462 else if (strncasecmp (env
, "passive", 7) == 0)
469 while (isspace ((unsigned char) *env
))
473 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
477 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
478 present and it was successfully parsed. */
481 parse_affinity (void)
484 unsigned long cpu_beg
, cpu_end
, cpu_stride
;
485 unsigned short *cpus
= NULL
;
486 size_t allocated
= 0, used
= 0, needed
;
488 env
= getenv ("GOMP_CPU_AFFINITY");
494 while (*env
== ' ' || *env
== '\t')
497 cpu_beg
= strtoul (env
, &end
, 0);
500 if (env
== end
|| cpu_beg
>= 65536)
506 cpu_end
= strtoul (++env
, &end
, 0);
507 if (env
== end
|| cpu_end
>= 65536 || cpu_end
< cpu_beg
)
513 cpu_stride
= strtoul (++env
, &end
, 0);
514 if (env
== end
|| cpu_stride
== 0 || cpu_stride
>= 65536)
521 needed
= (cpu_end
- cpu_beg
) / cpu_stride
+ 1;
522 if (used
+ needed
>= allocated
)
524 unsigned short *new_cpus
;
528 if (allocated
> needed
)
531 allocated
+= 2 * needed
;
532 new_cpus
= realloc (cpus
, allocated
* sizeof (unsigned short));
533 if (new_cpus
== NULL
)
536 gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
545 cpus
[used
++] = cpu_beg
;
546 cpu_beg
+= cpu_stride
;
549 while (*env
== ' ' || *env
== '\t')
554 else if (*env
== '\0')
559 gomp_cpu_affinity
= cpus
;
560 gomp_cpu_affinity_len
= used
;
564 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
568 static void __attribute__((constructor
))
569 initialize_env (void)
571 unsigned long stacksize
;
573 bool bind_var
= false;
575 /* Do a compile time check that mkomp_h.pl did good job. */
576 omp_check_defines ();
579 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv
.dyn_var
);
580 parse_boolean ("OMP_NESTED", &gomp_global_icv
.nest_var
);
581 parse_boolean ("OMP_PROC_BIND", &bind_var
);
582 parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var
,
584 parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var
, false);
585 if (gomp_thread_limit_var
!= ULONG_MAX
)
586 gomp_remaining_threads_count
= gomp_thread_limit_var
- 1;
587 #ifndef HAVE_SYNC_BUILTINS
588 gomp_mutex_init (&gomp_remaining_threads_lock
);
590 gomp_init_num_threads ();
591 gomp_available_cpus
= gomp_global_icv
.nthreads_var
;
592 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
593 &gomp_global_icv
.nthreads_var
,
594 &gomp_nthreads_var_list
,
595 &gomp_nthreads_var_list_len
))
596 gomp_global_icv
.nthreads_var
= gomp_available_cpus
;
597 if (parse_affinity () || bind_var
)
598 gomp_init_affinity ();
599 wait_policy
= parse_wait_policy ();
600 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var
))
602 /* Using a rough estimation of 100000 spins per msec,
603 use 5 min blocking for OMP_WAIT_POLICY=active,
604 3 msec blocking when OMP_WAIT_POLICY is not specificed
605 and 0 when OMP_WAIT_POLICY=passive.
606 Depending on the CPU speed, this can be e.g. 5 times longer
607 or 5 times shorter. */
609 gomp_spin_count_var
= 30000000000LL;
610 else if (wait_policy
< 0)
611 gomp_spin_count_var
= 300000LL;
613 /* gomp_throttled_spin_count_var is used when there are more libgomp
614 managed threads than available CPUs. Use very short spinning. */
616 gomp_throttled_spin_count_var
= 1000LL;
617 else if (wait_policy
< 0)
618 gomp_throttled_spin_count_var
= 100LL;
619 if (gomp_throttled_spin_count_var
> gomp_spin_count_var
)
620 gomp_throttled_spin_count_var
= gomp_spin_count_var
;
622 /* Not strictly environment related, but ordering constructors is tricky. */
623 pthread_attr_init (&gomp_thread_attr
);
624 pthread_attr_setdetachstate (&gomp_thread_attr
, PTHREAD_CREATE_DETACHED
);
626 if (parse_stacksize ("OMP_STACKSIZE", &stacksize
)
627 || parse_stacksize ("GOMP_STACKSIZE", &stacksize
))
631 err
= pthread_attr_setstacksize (&gomp_thread_attr
, stacksize
);
633 #ifdef PTHREAD_STACK_MIN
636 if (stacksize
< PTHREAD_STACK_MIN
)
637 gomp_error ("Stack size less than minimum of %luk",
638 PTHREAD_STACK_MIN
/ 1024ul
639 + (PTHREAD_STACK_MIN
% 1024 != 0));
641 gomp_error ("Stack size larger than system limit");
646 gomp_error ("Stack size change failed: %s", strerror (err
));
651 /* The public OpenMP API routines that access these variables. */
654 omp_set_num_threads (int n
)
656 struct gomp_task_icv
*icv
= gomp_icv (true);
657 icv
->nthreads_var
= (n
> 0 ? n
: 1);
661 omp_set_dynamic (int val
)
663 struct gomp_task_icv
*icv
= gomp_icv (true);
668 omp_get_dynamic (void)
670 struct gomp_task_icv
*icv
= gomp_icv (false);
675 omp_set_nested (int val
)
677 struct gomp_task_icv
*icv
= gomp_icv (true);
682 omp_get_nested (void)
684 struct gomp_task_icv
*icv
= gomp_icv (false);
685 return icv
->nest_var
;
689 omp_set_schedule (omp_sched_t kind
, int modifier
)
691 struct gomp_task_icv
*icv
= gomp_icv (true);
694 case omp_sched_static
:
697 icv
->run_sched_modifier
= modifier
;
699 case omp_sched_dynamic
:
700 case omp_sched_guided
:
703 icv
->run_sched_modifier
= modifier
;
710 icv
->run_sched_var
= kind
;
714 omp_get_schedule (omp_sched_t
*kind
, int *modifier
)
716 struct gomp_task_icv
*icv
= gomp_icv (false);
717 *kind
= icv
->run_sched_var
;
718 *modifier
= icv
->run_sched_modifier
;
722 omp_get_max_threads (void)
724 struct gomp_task_icv
*icv
= gomp_icv (false);
725 return icv
->nthreads_var
;
729 omp_get_thread_limit (void)
731 return gomp_thread_limit_var
> INT_MAX
? INT_MAX
: gomp_thread_limit_var
;
735 omp_set_max_active_levels (int max_levels
)
738 gomp_max_active_levels_var
= max_levels
;
742 omp_get_max_active_levels (void)
744 return gomp_max_active_levels_var
;
747 ialias (omp_set_dynamic
)
748 ialias (omp_set_nested
)
749 ialias (omp_set_num_threads
)
750 ialias (omp_get_dynamic
)
751 ialias (omp_get_nested
)
752 ialias (omp_set_schedule
)
753 ialias (omp_get_schedule
)
754 ialias (omp_get_max_threads
)
755 ialias (omp_get_thread_limit
)
756 ialias (omp_set_max_active_levels
)
757 ialias (omp_get_max_active_levels
)