1 # SPDX-License-Identifier: 0BSD
3 #############################################################################
5 # tuklib_cpucores.cmake - see tuklib_cpucores.m4 for description and comments
9 #############################################################################
11 include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake")
12 include(CheckCSourceCompiles)
13 include(CheckIncludeFile)
15 function(tuklib_cpucores_internal_check)
17 # Nothing to do, the tuklib_cpucores.c handles it.
18 set(TUKLIB_CPUCORES_DEFINITIONS "" CACHE INTERNAL "")
22 # glibc-based systems (GNU/Linux and GNU/kFreeBSD) have
23 # sched_getaffinity(). The CPU_COUNT() macro was added in glibc 2.9.
24 # glibc 2.9 is old enough that if someone uses the code on older glibc,
25 # the fallback to sysconf() should be good enough.
27 # NOTE: This required that _GNU_SOURCE is defined. We assume that whatever
28 # feature test macros the caller wants to use are already set in
29 # CMAKE_REQUIRED_DEFINES and in the target defines.
30 check_c_source_compiles("
35 sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask);
36 return CPU_COUNT(&cpu_mask);
39 TUKLIB_CPUCORES_SCHED_GETAFFINITY)
40 if(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
41 set(TUKLIB_CPUCORES_DEFINITIONS
42 "TUKLIB_CPUCORES_SCHED_GETAFFINITY"
47 # FreeBSD has both cpuset and sysctl. Look for cpuset first because
48 # it's a better approach.
50 # This test would match on GNU/kFreeBSD too but it would require
51 # -lfreebsd-glue when linking and thus in the current form this would
52 # fail on GNU/kFreeBSD. The above test for sched_getaffinity() matches
53 # on GNU/kFreeBSD so the test below should never run on that OS.
54 check_c_source_compiles("
55 #include <sys/param.h>
56 #include <sys/cpuset.h>
60 cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
65 TUKLIB_CPUCORES_CPUSET)
66 if(TUKLIB_CPUCORES_CPUSET)
67 set(TUKLIB_CPUCORES_DEFINITIONS "HAVE_PARAM_H;TUKLIB_CPUCORES_CPUSET"
72 # On OS/2, both sysconf() and sysctl() pass the tests in this file,
73 # but only sysctl() works. On QNX it's the opposite: only sysconf() works
74 # (although it assumes that _POSIX_SOURCE, _XOPEN_SOURCE, and
75 # _POSIX_C_SOURCE are undefined or alternatively _QNX_SOURCE is defined).
77 # We test sysctl() first and intentionally break the sysctl() test on QNX
78 # so that sysctl() is never used on QNX.
79 check_include_file(sys/param.h HAVE_SYS_PARAM_H)
81 list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_PARAM_H)
83 check_c_source_compiles("
87 #ifdef HAVE_SYS_PARAM_H
88 # include <sys/param.h>
90 #include <sys/sysctl.h>
94 /* This is preferred on OpenBSD, see tuklib_cpucores.c. */
95 int name[2] = { CTL_HW, HW_NCPUONLINE };
97 int name[2] = { CTL_HW, HW_NCPU };
100 size_t cpus_size = sizeof(cpus);
101 sysctl(name, 2, &cpus, &cpus_size, NULL, 0);
105 TUKLIB_CPUCORES_SYSCTL)
106 if(TUKLIB_CPUCORES_SYSCTL)
108 set(TUKLIB_CPUCORES_DEFINITIONS
109 "HAVE_PARAM_H;TUKLIB_CPUCORES_SYSCTL"
112 set(TUKLIB_CPUCORES_DEFINITIONS
113 "TUKLIB_CPUCORES_SYSCTL"
119 # Many platforms support sysconf().
120 check_c_source_compiles("
125 #ifdef _SC_NPROCESSORS_ONLN
126 /* Many systems using sysconf() */
127 i = sysconf(_SC_NPROCESSORS_ONLN);
130 i = sysconf(_SC_NPROC_ONLN);
135 TUKLIB_CPUCORES_SYSCONF)
136 if(TUKLIB_CPUCORES_SYSCONF)
137 set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_SYSCONF"
143 check_c_source_compiles("
144 #include <sys/param.h>
145 #include <sys/pstat.h>
148 struct pst_dynamic pst;
149 pstat_getdynamic(&pst, sizeof(pst), 1, 0);
150 (void)pst.psd_proc_cnt;
154 TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
155 if(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
156 set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_PSTAT_GETDYNAMIC"
162 function(tuklib_cpucores TARGET_OR_ALL)
163 if(NOT DEFINED TUKLIB_CPUCORES_FOUND)
165 "Checking how to detect the number of available CPU cores")
166 tuklib_cpucores_internal_check()
168 if(DEFINED TUKLIB_CPUCORES_DEFINITIONS)
169 set(TUKLIB_CPUCORES_FOUND 1 CACHE INTERNAL "")
171 set(TUKLIB_CPUCORES_FOUND 0 CACHE INTERNAL "")
173 "No method to detect the number of CPU cores was found")
177 if(TUKLIB_CPUCORES_FOUND)
178 tuklib_add_definitions("${TARGET_OR_ALL}"
179 "${TUKLIB_CPUCORES_DEFINITIONS}")