1 /* Copyright (C) 2005-2013 Free Software Foundation, Inc.
2 Contributed by Jakub Jelinek <jakub@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 contains system specific routines related to counting
26 online processors and dynamic load balancing. */
36 #ifdef HAVE_GETLOADAVG
37 # ifdef HAVE_SYS_LOADAVG_H
38 # include <sys/loadavg.h>
42 #ifdef HAVE_PTHREAD_AFFINITY_NP
43 unsigned long gomp_cpuset_size
;
44 static unsigned long gomp_get_cpuset_size
;
45 cpu_set_t
*gomp_cpusetp
;
48 gomp_cpuset_popcount (unsigned long cpusetsize
, cpu_set_t
*cpusetp
)
51 /* glibc 2.7 and above provide a macro for this. */
52 return CPU_COUNT_S (cpusetsize
, cpusetp
);
55 if (cpusetsize
== sizeof (cpu_set_t
))
56 /* glibc 2.6 and above provide a macro for this. */
57 return CPU_COUNT (cpusetp
);
60 unsigned long ret
= 0;
61 extern int check
[sizeof (cpusetp
->__bits
[0]) == sizeof (unsigned long int)
62 ? 1 : -1] __attribute__((unused
));
64 for (i
= 0; i
< cpusetsize
/ sizeof (cpusetp
->__bits
[0]); i
++)
66 unsigned long int mask
= cpusetp
->__bits
[i
];
69 ret
+= __builtin_popcountl (mask
);
76 /* At startup, determine the default number of threads. It would seem
77 this should be related to the number of cpus online. */
80 gomp_init_num_threads (void)
82 #ifdef HAVE_PTHREAD_AFFINITY_NP
83 #if defined (_SC_NPROCESSORS_CONF) && defined (CPU_ALLOC_SIZE)
84 gomp_cpuset_size
= sysconf (_SC_NPROCESSORS_CONF
);
85 gomp_cpuset_size
= CPU_ALLOC_SIZE (gomp_cpuset_size
);
87 gomp_cpuset_size
= sizeof (cpu_set_t
);
90 gomp_cpusetp
= (cpu_set_t
*) gomp_malloc (gomp_cpuset_size
);
93 int ret
= pthread_getaffinity_np (pthread_self (), gomp_cpuset_size
,
97 /* Count only the CPUs this process can use. */
98 gomp_global_icv
.nthreads_var
99 = gomp_cpuset_popcount (gomp_cpuset_size
, gomp_cpusetp
);
100 if (gomp_global_icv
.nthreads_var
== 0)
102 gomp_get_cpuset_size
= gomp_cpuset_size
;
103 #ifdef CPU_ALLOC_SIZE
105 for (i
= gomp_cpuset_size
* 8; i
; i
--)
106 if (CPU_ISSET_S (i
- 1, gomp_cpuset_size
, gomp_cpusetp
))
108 gomp_cpuset_size
= CPU_ALLOC_SIZE (i
);
114 #ifdef CPU_ALLOC_SIZE
115 if (gomp_cpuset_size
< sizeof (cpu_set_t
))
116 gomp_cpuset_size
= sizeof (cpu_set_t
);
118 gomp_cpuset_size
= gomp_cpuset_size
* 2;
119 if (gomp_cpuset_size
< 8 * sizeof (cpu_set_t
))
121 = (cpu_set_t
*) gomp_realloc (gomp_cpusetp
, gomp_cpuset_size
);
124 /* Avoid gomp_fatal if too large memory allocation would be
125 requested, e.g. kernel returning EINVAL all the time. */
126 void *p
= realloc (gomp_cpusetp
, gomp_cpuset_size
);
129 gomp_cpusetp
= (cpu_set_t
*) p
;
136 gomp_cpuset_size
= 0;
137 gomp_global_icv
.nthreads_var
= 1;
141 #ifdef _SC_NPROCESSORS_ONLN
142 gomp_global_icv
.nthreads_var
= sysconf (_SC_NPROCESSORS_ONLN
);
149 #ifdef HAVE_PTHREAD_AFFINITY_NP
150 if (gomp_places_list
== NULL
)
152 /* Count only the CPUs this process can use. */
154 && pthread_getaffinity_np (pthread_self (), gomp_get_cpuset_size
,
157 int ret
= gomp_cpuset_popcount (gomp_get_cpuset_size
, gomp_cpusetp
);
158 return ret
!= 0 ? ret
: 1;
163 /* We can't use pthread_getaffinity_np in this case
164 (we have changed it ourselves, it binds to just one CPU).
165 Count instead the number of different CPUs we are
166 using. gomp_init_affinity updated gomp_available_cpus to
167 the number of CPUs in the GOMP_AFFINITY mask that we are
168 allowed to use though. */
169 return gomp_available_cpus
;
172 #ifdef _SC_NPROCESSORS_ONLN
173 return sysconf (_SC_NPROCESSORS_ONLN
);
175 return gomp_icv (false)->nthreads_var
;
179 /* When OMP_DYNAMIC is set, at thread launch determine the number of
180 threads we should spawn for this team. */
181 /* ??? I have no idea what best practice for this is. Surely some
182 function of the number of processors that are *still* online and
183 the load average. Here I use the number of processors online
184 minus the 15 minute load average. */
187 gomp_dynamic_max_threads (void)
189 unsigned n_onln
, loadavg
, nthreads_var
= gomp_icv (false)->nthreads_var
;
191 n_onln
= get_num_procs ();
192 if (n_onln
> nthreads_var
)
193 n_onln
= nthreads_var
;
196 #ifdef HAVE_GETLOADAVG
199 if (getloadavg (dloadavg
, 3) == 3)
201 /* Add 0.1 to get a kind of biased rounding. */
202 loadavg
= dloadavg
[2] + 0.1;
207 if (loadavg
>= n_onln
)
210 return n_onln
- loadavg
;
214 omp_get_num_procs (void)
216 return get_num_procs ();
219 ialias (omp_get_num_procs
)