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