| # |
| # tuklib_cpucores.cmake - see tuklib_cpucores.m4 for description and comments |
| # |
| # Author: Lasse Collin |
| # |
| # This file has been put into the public domain. |
| # You can do whatever you want with this file. |
| # |
| |
| include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") |
| include(CheckCSourceCompiles) |
| include(CheckIncludeFile) |
| |
| function(tuklib_cpucores_internal_check) |
| if(WIN32 OR CYGWIN) |
| # Nothing to do, the tuklib_cpucores.c handles it. |
| set(TUKLIB_CPUCORES_DEFINITIONS "" CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # glibc-based systems (GNU/Linux and GNU/kFreeBSD) have |
| # sched_getaffinity(). The CPU_COUNT() macro was added in glibc 2.9. |
| # glibc 2.9 is old enough that if someone uses the code on older glibc, |
| # the fallback to sysconf() should be good enough. |
| # |
| # NOTE: This required that _GNU_SOURCE is defined. We assume that whatever |
| # feature test macros the caller wants to use are already set in |
| # CMAKE_REQUIRED_DEFINES and in the target defines. |
| check_c_source_compiles(" |
| #include <sched.h> |
| int main(void) |
| { |
| cpu_set_t cpu_mask; |
| sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask); |
| return CPU_COUNT(&cpu_mask); |
| } |
| " |
| TUKLIB_CPUCORES_SCHED_GETAFFINITY) |
| if(TUKLIB_CPUCORES_SCHED_GETAFFINITY) |
| set(TUKLIB_CPUCORES_DEFINITIONS |
| "TUKLIB_CPUCORES_SCHED_GETAFFINITY" |
| CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # FreeBSD has both cpuset and sysctl. Look for cpuset first because |
| # it's a better approach. |
| # |
| # This test would match on GNU/kFreeBSD too but it would require |
| # -lfreebsd-glue when linking and thus in the current form this would |
| # fail on GNU/kFreeBSD. The above test for sched_getaffinity() matches |
| # on GNU/kFreeBSD so the test below should never run on that OS. |
| check_c_source_compiles(" |
| #include <sys/param.h> |
| #include <sys/cpuset.h> |
| int main(void) |
| { |
| cpuset_t set; |
| cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, |
| sizeof(set), &set); |
| return 0; |
| } |
| " |
| TUKLIB_CPUCORES_CPUSET) |
| if(TUKLIB_CPUCORES_CPUSET) |
| set(TUKLIB_CPUCORES_DEFINITIONS "HAVE_PARAM_H;TUKLIB_CPUCORES_CPUSET" |
| CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # On OS/2, both sysconf() and sysctl() pass the tests in this file, |
| # but only sysctl() works. On QNX it's the opposite: only sysconf() works |
| # (although it assumes that _POSIX_SOURCE, _XOPEN_SOURCE, and |
| # _POSIX_C_SOURCE are undefined or alternatively _QNX_SOURCE is defined). |
| # |
| # We test sysctl() first and intentionally break the sysctl() test on QNX |
| # so that sysctl() is never used on QNX. |
| check_include_file(sys/param.h HAVE_SYS_PARAM_H) |
| if(HAVE_SYS_PARAM_H) |
| list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_PARAM_H) |
| endif() |
| check_c_source_compiles(" |
| #ifdef __QNX__ |
| compile error |
| #endif |
| #ifdef HAVE_SYS_PARAM_H |
| # include <sys/param.h> |
| #endif |
| #include <sys/sysctl.h> |
| int main(void) |
| { |
| #ifdef HW_NCPUONLINE |
| /* This is preferred on OpenBSD, see tuklib_cpucores.c. */ |
| int name[2] = { CTL_HW, HW_NCPUONLINE }; |
| #else |
| int name[2] = { CTL_HW, HW_NCPU }; |
| #endif |
| int cpus; |
| size_t cpus_size = sizeof(cpus); |
| sysctl(name, 2, &cpus, &cpus_size, NULL, 0); |
| return 0; |
| } |
| " |
| TUKLIB_CPUCORES_SYSCTL) |
| if(TUKLIB_CPUCORES_SYSCTL) |
| if(HAVE_SYS_PARAM_H) |
| set(TUKLIB_CPUCORES_DEFINITIONS |
| "HAVE_PARAM_H;TUKLIB_CPUCORES_SYSCTL" |
| CACHE INTERNAL "") |
| else() |
| set(TUKLIB_CPUCORES_DEFINITIONS |
| "TUKLIB_CPUCORES_SYSCTL" |
| CACHE INTERNAL "") |
| endif() |
| return() |
| endif() |
| |
| # Many platforms support sysconf(). |
| check_c_source_compiles(" |
| #include <unistd.h> |
| int main(void) |
| { |
| long i; |
| #ifdef _SC_NPROCESSORS_ONLN |
| /* Many systems using sysconf() */ |
| i = sysconf(_SC_NPROCESSORS_ONLN); |
| #else |
| /* IRIX */ |
| i = sysconf(_SC_NPROC_ONLN); |
| #endif |
| return 0; |
| } |
| " |
| TUKLIB_CPUCORES_SYSCONF) |
| if(TUKLIB_CPUCORES_SYSCONF) |
| set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_SYSCONF" |
| CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # HP-UX |
| check_c_source_compiles(" |
| #include <sys/param.h> |
| #include <sys/pstat.h> |
| int main(void) |
| { |
| struct pst_dynamic pst; |
| pstat_getdynamic(&pst, sizeof(pst), 1, 0); |
| (void)pst.psd_proc_cnt; |
| return 0; |
| } |
| " |
| TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) |
| if(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) |
| set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_PSTAT_GETDYNAMIC" |
| CACHE INTERNAL "") |
| return() |
| endif() |
| endfunction() |
| |
| function(tuklib_cpucores TARGET_OR_ALL) |
| if(NOT DEFINED TUKLIB_CPUCORES_FOUND) |
| message(STATUS |
| "Checking how to detect the number of available CPU cores") |
| tuklib_cpucores_internal_check() |
| |
| if(DEFINED TUKLIB_CPUCORES_DEFINITIONS) |
| set(TUKLIB_CPUCORES_FOUND 1 CACHE INTERNAL "") |
| else() |
| set(TUKLIB_CPUCORES_FOUND 0 CACHE INTERNAL "") |
| message(WARNING |
| "No method to detect the number of CPU cores was found") |
| endif() |
| endif() |
| |
| if(TUKLIB_CPUCORES_FOUND) |
| tuklib_add_definitions("${TARGET_OR_ALL}" |
| "${TUKLIB_CPUCORES_DEFINITIONS}") |
| endif() |
| endfunction() |