This source file includes following definitions.
- num_processors_via_affinity_mask
- num_processors_ignoring_omp
- parse_omp_threads
- num_processors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21 #include "nproc.h"
22
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #if HAVE_PTHREAD_GETAFFINITY_NP && 0
28 # include <pthread.h>
29 # include <sched.h>
30 #endif
31 #if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP
32 # include <sched.h>
33 #endif
34
35 #include <sys/types.h>
36
37 #if HAVE_SYS_PSTAT_H
38 # include <sys/pstat.h>
39 #endif
40
41 #if HAVE_SYS_SYSMP_H
42 # include <sys/sysmp.h>
43 #endif
44
45 #if HAVE_SYS_PARAM_H
46 # include <sys/param.h>
47 #endif
48
49 #if HAVE_SYS_SYSCTL_H && !(defined __GLIBC__ && defined __linux__)
50 # include <sys/sysctl.h>
51 #endif
52
53 #if defined _WIN32 && ! defined __CYGWIN__
54 # define WIN32_LEAN_AND_MEAN
55 # include <windows.h>
56 #endif
57
58 #include "c-ctype.h"
59
60 #include "minmax.h"
61
62 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
63
64
65
66
67
68 static unsigned long
69 num_processors_via_affinity_mask (void)
70 {
71
72
73
74
75
76 #if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0
77 {
78 cpu_set_t set;
79
80 if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
81 {
82 unsigned long count;
83
84 # ifdef CPU_COUNT
85
86 count = CPU_COUNT (&set);
87 # else
88 size_t i;
89
90 count = 0;
91 for (i = 0; i < CPU_SETSIZE; i++)
92 if (CPU_ISSET (i, &set))
93 count++;
94 # endif
95 if (count > 0)
96 return count;
97 }
98 }
99 #elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0
100 {
101 cpuset_t *set;
102
103 set = cpuset_create ();
104 if (set != NULL)
105 {
106 unsigned long count = 0;
107
108 if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
109 == 0)
110 {
111 cpuid_t i;
112
113 for (i = 0;; i++)
114 {
115 int ret = cpuset_isset (i, set);
116 if (ret < 0)
117 break;
118 if (ret > 0)
119 count++;
120 }
121 }
122 cpuset_destroy (set);
123 if (count > 0)
124 return count;
125 }
126 }
127 #elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC
128 {
129 cpu_set_t set;
130
131 if (sched_getaffinity (0, sizeof (set), &set) == 0)
132 {
133 unsigned long count;
134
135 # ifdef CPU_COUNT
136
137 count = CPU_COUNT (&set);
138 # else
139 size_t i;
140
141 count = 0;
142 for (i = 0; i < CPU_SETSIZE; i++)
143 if (CPU_ISSET (i, &set))
144 count++;
145 # endif
146 if (count > 0)
147 return count;
148 }
149 }
150 #elif HAVE_SCHED_GETAFFINITY_NP
151 {
152 cpuset_t *set;
153
154 set = cpuset_create ();
155 if (set != NULL)
156 {
157 unsigned long count = 0;
158
159 if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
160 {
161 cpuid_t i;
162
163 for (i = 0;; i++)
164 {
165 int ret = cpuset_isset (i, set);
166 if (ret < 0)
167 break;
168 if (ret > 0)
169 count++;
170 }
171 }
172 cpuset_destroy (set);
173 if (count > 0)
174 return count;
175 }
176 }
177 #endif
178
179 #if defined _WIN32 && ! defined __CYGWIN__
180 {
181 DWORD_PTR process_mask;
182 DWORD_PTR system_mask;
183
184 if (GetProcessAffinityMask (GetCurrentProcess (),
185 &process_mask, &system_mask))
186 {
187 DWORD_PTR mask = process_mask;
188 unsigned long count = 0;
189
190 for (; mask != 0; mask = mask >> 1)
191 if (mask & 1)
192 count++;
193 if (count > 0)
194 return count;
195 }
196 }
197 #endif
198
199 return 0;
200 }
201
202
203
204
205 static unsigned long int
206 num_processors_ignoring_omp (enum nproc_query query)
207 {
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223 if (query == NPROC_CURRENT)
224 {
225
226 {
227 unsigned long nprocs = num_processors_via_affinity_mask ();
228
229 if (nprocs > 0)
230 return nprocs;
231 }
232
233 #if defined _SC_NPROCESSORS_ONLN
234 {
235
236 long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
237 if (nprocs > 0)
238 return nprocs;
239 }
240 #endif
241 }
242 else
243 {
244 #if defined _SC_NPROCESSORS_CONF
245 {
246
247 long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
248
249 # if __GLIBC__ >= 2 && defined __linux__
250
251
252
253
254
255 if (nprocs == 1 || nprocs == 2)
256 {
257 unsigned long nprocs_current = num_processors_via_affinity_mask ();
258
259 if ( nprocs_current > nprocs)
260 nprocs = nprocs_current;
261 }
262 # endif
263
264 if (nprocs > 0)
265 return nprocs;
266 }
267 #endif
268 }
269
270 #if HAVE_PSTAT_GETDYNAMIC
271 {
272 struct pst_dynamic psd;
273 if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0)
274 {
275
276
277
278 if (query == NPROC_CURRENT)
279 {
280 if (psd.psd_proc_cnt > 0)
281 return psd.psd_proc_cnt;
282 }
283 else
284 {
285 if (psd.psd_max_proc_cnt > 0)
286 return psd.psd_max_proc_cnt;
287 }
288 }
289 }
290 #endif
291
292 #if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS
293 {
294
295
296
297 int nprocs =
298 sysmp (query == NPROC_CURRENT && getuid () != 0
299 ? MP_NAPROCS
300 : MP_NPROCS);
301 if (nprocs > 0)
302 return nprocs;
303 }
304 #endif
305
306
307
308
309 #if HAVE_SYSCTL && !(defined __GLIBC__ && defined __linux__) && defined HW_NCPU
310 {
311
312 int nprocs;
313 size_t len = sizeof (nprocs);
314 static int mib[][2] = {
315 # ifdef HW_NCPUONLINE
316 { CTL_HW, HW_NCPUONLINE },
317 # endif
318 { CTL_HW, HW_NCPU }
319 };
320 for (int i = 0; i < ARRAY_SIZE (mib); i++)
321 {
322 if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0
323 && len == sizeof (nprocs)
324 && 0 < nprocs)
325 return nprocs;
326 }
327 }
328 #endif
329
330 #if defined _WIN32 && ! defined __CYGWIN__
331 {
332 SYSTEM_INFO system_info;
333 GetSystemInfo (&system_info);
334 if (0 < system_info.dwNumberOfProcessors)
335 return system_info.dwNumberOfProcessors;
336 }
337 #endif
338
339 return 1;
340 }
341
342
343
344 static unsigned long int
345 parse_omp_threads (char const* threads)
346 {
347 unsigned long int ret = 0;
348
349 if (threads == NULL)
350 return ret;
351
352
353
354 while (*threads != '\0' && c_isspace (*threads))
355 threads++;
356
357
358 if (c_isdigit (*threads))
359 {
360 char *endptr = NULL;
361 unsigned long int value = strtoul (threads, &endptr, 10);
362
363 if (endptr != NULL)
364 {
365 while (*endptr != '\0' && c_isspace (*endptr))
366 endptr++;
367 if (*endptr == '\0')
368 return value;
369
370
371 else if (*endptr == ',')
372 return value;
373 }
374 }
375
376 return ret;
377 }
378
379 unsigned long int
380 num_processors (enum nproc_query query)
381 {
382 unsigned long int omp_env_limit = ULONG_MAX;
383
384 if (query == NPROC_CURRENT_OVERRIDABLE)
385 {
386 unsigned long int omp_env_threads;
387
388
389 omp_env_threads = parse_omp_threads (getenv ("OMP_NUM_THREADS"));
390 omp_env_limit = parse_omp_threads (getenv ("OMP_THREAD_LIMIT"));
391 if (! omp_env_limit)
392 omp_env_limit = ULONG_MAX;
393
394 if (omp_env_threads)
395 return MIN (omp_env_threads, omp_env_limit);
396
397 query = NPROC_CURRENT;
398 }
399
400 {
401 unsigned long nprocs = num_processors_ignoring_omp (query);
402 return MIN (nprocs, omp_env_limit);
403 }
404 }