1 // SPDX-License-Identifier: 0BSD
2
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file tuklib_cpucores.c
6 /// \brief Get the number of CPU cores online
7 //
8 // Author: Lasse Collin
9 //
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #include "tuklib_cpucores.h"
13
14 #if defined(_WIN32) || defined(__CYGWIN__)
15 # ifndef _WIN32_WINNT
16 # define _WIN32_WINNT 0x0500
17 # endif
18 # include <windows.h>
19
20 // glibc >= 2.9
21 #elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
22 # include <sched.h>
23
24 // FreeBSD
25 #elif defined(TUKLIB_CPUCORES_CPUSET)
26 # include <sys/param.h>
27 # include <sys/cpuset.h>
28
29 #elif defined(TUKLIB_CPUCORES_SYSCTL)
30 # ifdef HAVE_SYS_PARAM_H
31 # include <sys/param.h>
32 # endif
33 # include <sys/sysctl.h>
34
35 #elif defined(TUKLIB_CPUCORES_SYSCONF)
36 # include <unistd.h>
37
38 // HP-UX
39 #elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
40 # include <sys/param.h>
41 # include <sys/pstat.h>
42 #endif
43
44
45 extern uint32_t
tuklib_cpucores(void)46 tuklib_cpucores(void)
47 {
48 uint32_t ret = 0;
49
50 #if defined(_WIN32) || defined(__CYGWIN__)
51 SYSTEM_INFO sysinfo;
52 GetSystemInfo(&sysinfo);
53 ret = sysinfo.dwNumberOfProcessors;
54
55 #elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
56 cpu_set_t cpu_mask;
57 if (sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask) == 0)
58 ret = (uint32_t)CPU_COUNT(&cpu_mask);
59
60 #elif defined(TUKLIB_CPUCORES_CPUSET)
61 cpuset_t set;
62 if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
63 sizeof(set), &set) == 0) {
64 # ifdef CPU_COUNT
65 ret = (uint32_t)CPU_COUNT(&set);
66 # else
67 for (unsigned i = 0; i < CPU_SETSIZE; ++i)
68 if (CPU_ISSET(i, &set))
69 ++ret;
70 # endif
71 }
72
73 #elif defined(TUKLIB_CPUCORES_SYSCTL)
74 // On OpenBSD HW_NCPUONLINE tells the number of processor cores that
75 // are online so it is preferred over HW_NCPU which also counts cores
76 // that aren't currently available. The number of cores online is
77 // often less than HW_NCPU because OpenBSD disables simultaneous
78 // multi-threading (SMT) by default.
79 # ifdef HW_NCPUONLINE
80 int name[2] = { CTL_HW, HW_NCPUONLINE };
81 # else
82 int name[2] = { CTL_HW, HW_NCPU };
83 # endif
84 int cpus;
85 size_t cpus_size = sizeof(cpus);
86 if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
87 && cpus_size == sizeof(cpus) && cpus > 0)
88 ret = (uint32_t)cpus;
89
90 #elif defined(TUKLIB_CPUCORES_SYSCONF)
91 # ifdef _SC_NPROCESSORS_ONLN
92 // Most systems
93 const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
94 # else
95 // IRIX
96 const long cpus = sysconf(_SC_NPROC_ONLN);
97 # endif
98 if (cpus > 0)
99 ret = (uint32_t)cpus;
100
101 #elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
102 struct pst_dynamic pst;
103 if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1)
104 ret = (uint32_t)pst.psd_proc_cnt;
105 #endif
106
107 return ret;
108 }
109