diff options
author | Archibald Elliott <archibald.elliott@arm.com> | 2022-11-25 12:14:48 +0000 |
---|---|---|
committer | Archibald Elliott <archibald.elliott@arm.com> | 2022-11-25 12:51:36 +0000 |
commit | 5577207d6d3e0642ea047a8dfbfcf3ad372a7f25 (patch) | |
tree | 1ae3f7932bef597454d28583ee995d9fb5dd3ca7 /llvm/lib/Support/Threading.cpp | |
parent | b32931c5b32eb0d2cf37d688b34f8548c9674c19 (diff) | |
download | llvm-5577207d6d3e0642ea047a8dfbfcf3ad372a7f25.zip llvm-5577207d6d3e0642ea047a8dfbfcf3ad372a7f25.tar.gz llvm-5577207d6d3e0642ea047a8dfbfcf3ad372a7f25.tar.bz2 |
[Support] Move getHostNumPhysicalCores to Threading.h
This change is focussed on simplifying `Support/Host.h` to only do
target detection. In this case, this function is close in usage to
existing functions in `Support/Threading.h`, so I moved it into there.
The function is also renamed to `llvm::get_physical_cores()` to match
the style of threading's functions.
Differential Revision: https://reviews.llvm.org/D137836
Diffstat (limited to 'llvm/lib/Support/Threading.cpp')
-rw-r--r-- | llvm/lib/Support/Threading.cpp | 132 |
1 files changed, 129 insertions, 3 deletions
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp index bd954fd..6c2ff11 100644 --- a/llvm/lib/Support/Threading.cpp +++ b/llvm/lib/Support/Threading.cpp @@ -13,8 +13,12 @@ #include "llvm/Support/Threading.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" -#include "llvm/Support/Host.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <errno.h> @@ -50,8 +54,8 @@ unsigned llvm::ThreadPoolStrategy::compute_thread_count() const { static int computeHostNumHardwareThreads(); unsigned llvm::ThreadPoolStrategy::compute_thread_count() const { - int MaxThreadCount = UseHyperThreads ? computeHostNumHardwareThreads() - : sys::getHostNumPhysicalCores(); + int MaxThreadCount = + UseHyperThreads ? computeHostNumHardwareThreads() : get_physical_cores(); if (MaxThreadCount <= 0) MaxThreadCount = 1; if (ThreadsRequested == 0) @@ -106,3 +110,125 @@ llvm::get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default) { S.ThreadsRequested = V; return S; } + +#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) +// On Linux, the number of physical cores can be computed from /proc/cpuinfo, +// using the number of unique physical/core id pairs. The following +// implementation reads the /proc/cpuinfo format on an x86_64 system. +static int computeHostNumPhysicalCores() { + // Enabled represents the number of physical id/core id pairs with at least + // one processor id enabled by the CPU affinity mask. + cpu_set_t Affinity, Enabled; + if (sched_getaffinity(0, sizeof(Affinity), &Affinity) != 0) + return -1; + CPU_ZERO(&Enabled); + + // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be + // mmapped because it appears to have 0 size. + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); + if (std::error_code EC = Text.getError()) { + llvm::errs() << "Can't read " + << "/proc/cpuinfo: " << EC.message() << "\n"; + return -1; + } + SmallVector<StringRef, 8> strs; + (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, + /*KeepEmpty=*/false); + int CurProcessor = -1; + int CurPhysicalId = -1; + int CurSiblings = -1; + int CurCoreId = -1; + for (StringRef Line : strs) { + std::pair<StringRef, StringRef> Data = Line.split(':'); + auto Name = Data.first.trim(); + auto Val = Data.second.trim(); + // These fields are available if the kernel is configured with CONFIG_SMP. + if (Name == "processor") + Val.getAsInteger(10, CurProcessor); + else if (Name == "physical id") + Val.getAsInteger(10, CurPhysicalId); + else if (Name == "siblings") + Val.getAsInteger(10, CurSiblings); + else if (Name == "core id") { + Val.getAsInteger(10, CurCoreId); + // The processor id corresponds to an index into cpu_set_t. + if (CPU_ISSET(CurProcessor, &Affinity)) + CPU_SET(CurPhysicalId * CurSiblings + CurCoreId, &Enabled); + } + } + return CPU_COUNT(&Enabled); +} +#elif defined(__linux__) && defined(__s390x__) +static int computeHostNumPhysicalCores() { + return sysconf(_SC_NPROCESSORS_ONLN); +} +#elif defined(__linux__) && !defined(__ANDROID__) +static int computeHostNumPhysicalCores() { + cpu_set_t Affinity; + if (sched_getaffinity(0, sizeof(Affinity), &Affinity) == 0) + return CPU_COUNT(&Affinity); + + // The call to sched_getaffinity() may have failed because the Affinity + // mask is too small for the number of CPU's on the system (i.e. the + // system has more than 1024 CPUs). Allocate a mask large enough for + // twice as many CPUs. + cpu_set_t *DynAffinity; + DynAffinity = CPU_ALLOC(2048); + if (sched_getaffinity(0, CPU_ALLOC_SIZE(2048), DynAffinity) == 0) { + int NumCPUs = CPU_COUNT(DynAffinity); + CPU_FREE(DynAffinity); + return NumCPUs; + } + return -1; +} +#elif defined(__APPLE__) +// Gets the number of *physical cores* on the machine. +static int computeHostNumPhysicalCores() { + uint32_t count; + size_t len = sizeof(count); + sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0); + if (count < 1) { + int nm[2]; + nm[0] = CTL_HW; + nm[1] = HW_AVAILCPU; + sysctl(nm, 2, &count, &len, NULL, 0); + if (count < 1) + return -1; + } + return count; +} +#elif defined(__MVS__) +static int computeHostNumPhysicalCores() { + enum { + // Byte offset of the pointer to the Communications Vector Table (CVT) in + // the Prefixed Save Area (PSA). The table entry is a 31-bit pointer and + // will be zero-extended to uintptr_t. + FLCCVT = 16, + // Byte offset of the pointer to the Common System Data Area (CSD) in the + // CVT. The table entry is a 31-bit pointer and will be zero-extended to + // uintptr_t. + CVTCSD = 660, + // Byte offset to the number of live CPs in the LPAR, stored as a signed + // 32-bit value in the table. + CSD_NUMBER_ONLINE_STANDARD_CPS = 264, + }; + char *PSA = 0; + char *CVT = reinterpret_cast<char *>( + static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(PSA[FLCCVT]))); + char *CSD = reinterpret_cast<char *>( + static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(CVT[CVTCSD]))); + return reinterpret_cast<int &>(CSD[CSD_NUMBER_ONLINE_STANDARD_CPS]); +} +#elif defined(_WIN32) && LLVM_ENABLE_THREADS != 0 +// Defined in llvm/lib/Support/Windows/Threading.inc +int computeHostNumPhysicalCores(); +#else +// On other systems, return -1 to indicate unknown. +static int computeHostNumPhysicalCores() { return -1; } +#endif + +int llvm::get_physical_cores() { + static int NumCores = computeHostNumPhysicalCores(); + return NumCores; +} |