1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmAffinity.h"
4 
5 #include <cm3p/uv.h>
6 
7 #ifndef CMAKE_USE_SYSTEM_LIBUV
8 #  ifdef _WIN32
9 #    define CM_HAVE_CPU_AFFINITY
10 #    include <windows.h>
11 #  elif defined(__linux__) || defined(__FreeBSD__)
12 #    define CM_HAVE_CPU_AFFINITY
13 #    include <pthread.h>
14 #    include <sched.h>
15 // On some platforms CPU_ZERO needs memset but sched.h forgets string.h
16 #    include <cstring> // IWYU pragma: keep
17 #    if defined(__FreeBSD__)
18 #      include <pthread_np.h>
19 
20 #      include <sys/cpuset.h>
21 #      include <sys/param.h>
22 #    endif
23 #    if defined(__linux__)
24 using cm_cpuset_t = cpu_set_t;
25 #    else
26 using cm_cpuset_t = cpuset_t;
27 #    endif
28 #  endif
29 #endif
30 
31 namespace cmAffinity {
32 
GetProcessorsAvailable()33 std::set<size_t> GetProcessorsAvailable()
34 {
35   std::set<size_t> processorsAvailable;
36 #ifdef CM_HAVE_CPU_AFFINITY
37   int cpumask_size = uv_cpumask_size();
38   if (cpumask_size > 0) {
39 #  ifdef _WIN32
40     DWORD_PTR procmask;
41     DWORD_PTR sysmask;
42     if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask) !=
43         0) {
44       for (int i = 0; i < cpumask_size; ++i) {
45         if (procmask & (((DWORD_PTR)1) << i)) {
46           processorsAvailable.insert(i);
47         }
48       }
49     }
50 #  else
51     cm_cpuset_t cpuset;
52     CPU_ZERO(&cpuset); // NOLINT(clang-tidy)
53     if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) == 0) {
54       for (int i = 0; i < cpumask_size; ++i) {
55         if (CPU_ISSET(i, &cpuset)) {
56           processorsAvailable.insert(i);
57         }
58       }
59     }
60 #  endif
61   }
62 #endif
63   return processorsAvailable;
64 }
65 }
66