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