2
* SPDX-License-Identifier: LGPL-2.1-only
4
* Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5
* Copyright (C) 2019 Michael Jeanson <mjeanson@efficios.com>
13
int __num_possible_cpus;
15
#if (defined(__GLIBC__) || defined( __UCLIBC__))
16
void _get_num_possible_cpus(void)
20
/* On Linux, when some processors are offline
21
* _SC_NPROCESSORS_CONF counts the offline
22
* processors, whereas _SC_NPROCESSORS_ONLN
23
* does not. If we used _SC_NPROCESSORS_ONLN,
24
* getcpu() could return a value greater than
25
* this sysconf, in which case the arrays
26
* indexed by processor would overflow.
28
result = sysconf(_SC_NPROCESSORS_CONF);
31
__num_possible_cpus = result;
37
* The MUSL libc implementation of the _SC_NPROCESSORS_CONF sysconf does not
38
* return the number of configured CPUs in the system but relies on the cpu
39
* affinity mask of the current task.
41
* So instead we use a strategy similar to GLIBC's, counting the cpu
42
* directories in "/sys/devices/system/cpu" and fallback on the value from
43
* sysconf if it fails.
50
#include <sys/types.h>
52
#define __max(a,b) ((a)>(b)?(a):(b))
54
void _get_num_possible_cpus(void)
56
int result, count = 0;
60
cpudir = opendir("/sys/devices/system/cpu");
65
* Count the number of directories named "cpu" followed by and
66
* integer. This is the same strategy as glibc uses.
68
while ((entry = readdir(cpudir))) {
69
if (entry->d_type == DT_DIR &&
70
strncmp(entry->d_name, "cpu", 3) == 0) {
73
unsigned long cpu_num;
75
cpu_num = strtoul(entry->d_name + 3, &endptr, 10);
76
if ((cpu_num < ULONG_MAX) && (endptr != entry->d_name + 3)
77
&& (*endptr == '\0')) {
85
* Get the sysconf value as a fallback. Keep the highest number.
87
result = __max(sysconf(_SC_NPROCESSORS_CONF), count);
90
* If both methods failed, don't store the value.
94
__num_possible_cpus = result;