1 /* Detect the number of processors.
3 Copyright (C) 2009 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]))
63 num_processors (enum nproc_query query)
65 if (query == NPROC_CURRENT_OVERRIDABLE)
67 /* Test the environment variable OMP_NUM_THREADS, recognized also by all
68 programs that are based on OpenMP. The OpenMP spec says that the
69 value assigned to the environment variable "may have leading and
70 trailing white space". */
71 const char *envvalue = getenv ("OMP_NUM_THREADS");
75 while (*envvalue != '\0' && c_isspace (*envvalue))
77 /* Convert it from decimal to 'unsigned long'. */
78 if (c_isdigit (*envvalue))
81 unsigned long int value = strtoul (envvalue, &endptr, 10);
85 while (*endptr != '\0' && c_isspace (*endptr))
88 return (value > 0 ? value : 1);
93 query = NPROC_CURRENT;
95 /* Here query is one of NPROC_ALL, NPROC_CURRENT. */
97 if (query == NPROC_CURRENT)
99 /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np,
100 but with different APIs. Also it requires linking with -lpthread.
101 Therefore this code is not enabled.
102 glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has
103 sched_getaffinity_np. */
104 #if HAVE_PTHREAD_AFFINITY_NP && defined __GLIBC__ && 0
108 if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
113 /* glibc >= 2.6 has the CPU_COUNT macro. */
114 count = CPU_COUNT (&set);
119 for (i = 0; i < CPU_SETSIZE; i++)
120 if (CPU_ISSET (i, &set))
127 #elif HAVE_PTHREAD_AFFINITY_NP && defined __NetBSD__ && 0
131 set = cpuset_create ();
134 unsigned long count = 0;
136 if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
143 int ret = cpuset_isset (i, set);
150 cpuset_destroy (set);
155 #elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
159 if (sched_getaffinity (0, sizeof (set), &set) == 0)
164 /* glibc >= 2.6 has the CPU_COUNT macro. */
165 count = CPU_COUNT (&set);
170 for (i = 0; i < CPU_SETSIZE; i++)
171 if (CPU_ISSET (i, &set))
178 #elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */
182 set = cpuset_create ();
185 unsigned long count = 0;
187 if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
193 int ret = cpuset_isset (i, set);
200 cpuset_destroy (set);
207 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
208 { /* This works on native Windows platforms. */
209 DWORD_PTR process_mask;
210 DWORD_PTR system_mask;
212 if (GetProcessAffinityMask (GetCurrentProcess (),
213 &process_mask, &system_mask))
215 DWORD_PTR mask = process_mask;
216 unsigned long count = 0;
218 for (; mask != 0; mask = mask >> 1)
227 #if defined _SC_NPROCESSORS_ONLN
228 { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
230 long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
236 else /* query == NPROC_ALL */
238 #if defined _SC_NPROCESSORS_CONF
239 { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
241 long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
248 #if HAVE_PSTAT_GETDYNAMIC
249 { /* This works on HP-UX. */
250 struct pst_dynamic psd;
251 if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0)
253 /* The field psd_proc_cnt contains the number of active processors.
254 In newer releases of HP-UX 11, the field psd_max_proc_cnt includes
255 deactivated processors. */
256 if (query == NPROC_CURRENT)
258 if (psd.psd_proc_cnt > 0)
259 return psd.psd_proc_cnt;
263 if (psd.psd_max_proc_cnt > 0)
264 return psd.psd_max_proc_cnt;
270 #if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS
271 { /* This works on IRIX. */
272 /* MP_NPROCS yields the number of installed processors.
273 MP_NAPROCS yields the number of processors available to unprivileged
276 sysmp (query == NPROC_CURRENT && getpid () != 0
284 /* Finally, as fallback, use the APIs that don't distinguish between
285 NPROC_CURRENT and NPROC_ALL. */
287 #if HAVE_SYSCTL && defined HW_NCPU
288 { /* This works on MacOS X, FreeBSD, NetBSD, OpenBSD. */
290 size_t len = sizeof (nprocs);
291 static int mib[2] = { CTL_HW, HW_NCPU };
293 if (sysctl (mib, ARRAY_SIZE (mib), &nprocs, &len, NULL, 0) == 0
294 && len == sizeof (nprocs)
300 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
301 { /* This works on native Windows platforms. */
302 SYSTEM_INFO system_info;
303 GetSystemInfo (&system_info);
304 if (0 < system_info.dwNumberOfProcessors)
305 return system_info.dwNumberOfProcessors;