1 /* Detect the number of processors.
3 Copyright (C) 2009-2010 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /* Written by Glen Lenker and Bruno Haible. */
27 #if HAVE_PTHREAD_AFFINITY_NP && 0
31 #if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP
35 #include <sys/types.h>
38 # include <sys/pstat.h>
42 # include <sys/sysmp.h>
46 # include <sys/param.h>
50 # include <sys/sysctl.h>
53 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
54 # define WIN32_LEAN_AND_MEAN
60 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
62 /* Return the number of processors available to the current process, based
63 on a modern system call that returns the "affinity" between the current
64 process and each CPU. Return 0 if unknown or if such a system call does
67 num_processors_via_affinity_mask (void)
69 /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np,
70 but with different APIs. Also it requires linking with -lpthread.
71 Therefore this code is not enabled.
72 glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has
73 sched_getaffinity_np. */
74 #if HAVE_PTHREAD_AFFINITY_NP && defined __GLIBC__ && 0
78 if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
83 /* glibc >= 2.6 has the CPU_COUNT macro. */
84 count = CPU_COUNT (&set);
89 for (i = 0; i < CPU_SETSIZE; i++)
90 if (CPU_ISSET (i, &set))
97 #elif HAVE_PTHREAD_AFFINITY_NP && defined __NetBSD__ && 0
101 set = cpuset_create ();
104 unsigned long count = 0;
106 if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
113 int ret = cpuset_isset (i, set);
120 cpuset_destroy (set);
125 #elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
129 if (sched_getaffinity (0, sizeof (set), &set) == 0)
134 /* glibc >= 2.6 has the CPU_COUNT macro. */
135 count = CPU_COUNT (&set);
140 for (i = 0; i < CPU_SETSIZE; i++)
141 if (CPU_ISSET (i, &set))
148 #elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */
152 set = cpuset_create ();
155 unsigned long count = 0;
157 if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
163 int ret = cpuset_isset (i, set);
170 cpuset_destroy (set);
177 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
178 { /* This works on native Windows platforms. */
179 DWORD_PTR process_mask;
180 DWORD_PTR system_mask;
182 if (GetProcessAffinityMask (GetCurrentProcess (),
183 &process_mask, &system_mask))
185 DWORD_PTR mask = process_mask;
186 unsigned long count = 0;
188 for (; mask != 0; mask = mask >> 1)
201 num_processors (enum nproc_query query)
203 if (query == NPROC_CURRENT_OVERRIDABLE)
205 /* Test the environment variable OMP_NUM_THREADS, recognized also by all
206 programs that are based on OpenMP. The OpenMP spec says that the
207 value assigned to the environment variable "may have leading and
208 trailing white space". */
209 const char *envvalue = getenv ("OMP_NUM_THREADS");
211 if (envvalue != NULL)
213 while (*envvalue != '\0' && c_isspace (*envvalue))
215 /* Convert it from decimal to 'unsigned long'. */
216 if (c_isdigit (*envvalue))
219 unsigned long int value = strtoul (envvalue, &endptr, 10);
223 while (*endptr != '\0' && c_isspace (*endptr))
226 return (value > 0 ? value : 1);
231 query = NPROC_CURRENT;
233 /* Here query is one of NPROC_ALL, NPROC_CURRENT. */
235 /* On systems with a modern affinity mask system call, we have
236 sysconf (_SC_NPROCESSORS_CONF)
237 >= sysconf (_SC_NPROCESSORS_ONLN)
238 >= num_processors_via_affinity_mask ()
239 The first number is the number of CPUs configured in the system.
240 The second number is the number of CPUs available to the scheduler.
241 The third number is the number of CPUs available to the current process.
244 if (query == NPROC_CURRENT)
246 /* Try the modern affinity mask system call. */
248 unsigned long nprocs = num_processors_via_affinity_mask ();
254 #if defined _SC_NPROCESSORS_ONLN
255 { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
257 long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
263 else /* query == NPROC_ALL */
265 #if defined _SC_NPROCESSORS_CONF
266 { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
268 long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
275 #if HAVE_PSTAT_GETDYNAMIC
276 { /* This works on HP-UX. */
277 struct pst_dynamic psd;
278 if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0)
280 /* The field psd_proc_cnt contains the number of active processors.
281 In newer releases of HP-UX 11, the field psd_max_proc_cnt includes
282 deactivated processors. */
283 if (query == NPROC_CURRENT)
285 if (psd.psd_proc_cnt > 0)
286 return psd.psd_proc_cnt;
290 if (psd.psd_max_proc_cnt > 0)
291 return psd.psd_max_proc_cnt;
297 #if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS
298 { /* This works on IRIX. */
299 /* MP_NPROCS yields the number of installed processors.
300 MP_NAPROCS yields the number of processors available to unprivileged
303 sysmp (query == NPROC_CURRENT && getpid () != 0
311 /* Finally, as fallback, use the APIs that don't distinguish between
312 NPROC_CURRENT and NPROC_ALL. */
314 #if HAVE_SYSCTL && defined HW_NCPU
315 { /* This works on MacOS X, FreeBSD, NetBSD, OpenBSD. */
317 size_t len = sizeof (nprocs);
318 static int mib[2] = { CTL_HW, HW_NCPU };
320 if (sysctl (mib, ARRAY_SIZE (mib), &nprocs, &len, NULL, 0) == 0
321 && len == sizeof (nprocs)
327 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
328 { /* This works on native Windows platforms. */
329 SYSTEM_INFO system_info;
330 GetSystemInfo (&system_info);
331 if (0 < system_info.dwNumberOfProcessors)
332 return system_info.dwNumberOfProcessors;