xref: /freebsd/contrib/xz/src/common/tuklib_cpucores.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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
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