aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/Threading.cpp
diff options
context:
space:
mode:
authorArchibald Elliott <archibald.elliott@arm.com>2022-11-25 12:14:48 +0000
committerArchibald Elliott <archibald.elliott@arm.com>2022-11-25 12:51:36 +0000
commit5577207d6d3e0642ea047a8dfbfcf3ad372a7f25 (patch)
tree1ae3f7932bef597454d28583ee995d9fb5dd3ca7 /llvm/lib/Support/Threading.cpp
parentb32931c5b32eb0d2cf37d688b34f8548c9674c19 (diff)
downloadllvm-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.cpp132
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;
+}