[clang-tools-extra] 3c97f6c - [Support] Move getHostNumPhysicalCores to Threading.h
Archibald Elliott via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 29 05:14:26 PST 2022
Author: Archibald Elliott
Date: 2022-11-29T13:14:13Z
New Revision: 3c97f6cab92fb3511d72996ac7ca8a8b459ebc88
URL: https://github.com/llvm/llvm-project/commit/3c97f6cab92fb3511d72996ac7ca8a8b459ebc88
DIFF: https://github.com/llvm/llvm-project/commit/3c97f6cab92fb3511d72996ac7ca8a8b459ebc88.diff
LOG: [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.
The big change here is that now if you have threading disabled,
`llvm::get_physical_cores()` will return -1, as if it had not been able
to work out the right info. This is due to how Threading.cpp includes
OS-specific code/headers. This seems ok, as if threading is disabled,
LLVM should not need to know the number of physical cores.
Differential Revision: https://reviews.llvm.org/D137836
Added:
Modified:
clang-tools-extra/clangd/test/Inputs/BenchmarkHeader.h
llvm/include/llvm/Support/Host.h
llvm/include/llvm/Support/Threading.h
llvm/lib/Support/Host.cpp
llvm/lib/Support/Threading.cpp
llvm/lib/Support/Unix/Threading.inc
llvm/lib/Support/Windows/Threading.inc
llvm/unittests/Support/Host.cpp
llvm/unittests/Support/Threading.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/test/Inputs/BenchmarkHeader.h b/clang-tools-extra/clangd/test/Inputs/BenchmarkHeader.h
index 3b7620adafb1..bf760e367ff7 100644
--- a/clang-tools-extra/clangd/test/Inputs/BenchmarkHeader.h
+++ b/clang-tools-extra/clangd/test/Inputs/BenchmarkHeader.h
@@ -7,11 +7,7 @@ class Dex;
} // namespace clang
namespace llvm {
-namespace sys {
-
-int getHostNumPhysicalCores();
-
-} // namespace sys
+int get_physical_cores();
} // namespace llvm
namespace {
diff --git a/llvm/include/llvm/Support/Host.h b/llvm/include/llvm/Support/Host.h
index 369d6745db5a..dcebebdca6cb 100644
--- a/llvm/include/llvm/Support/Host.h
+++ b/llvm/include/llvm/Support/Host.h
@@ -54,11 +54,6 @@ namespace sys {
/// \return - True on success.
bool getHostCPUFeatures(StringMap<bool, MallocAllocator> &Features);
- /// Get the number of physical cores (as opposed to logical cores returned
- /// from thread::hardware_concurrency(), which includes hyperthreads).
- /// Returns -1 if unknown for the current host system.
- int getHostNumPhysicalCores();
-
namespace detail {
/// Helper functions to extract HostCPUName from /proc/cpuinfo on linux.
StringRef getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent);
diff --git a/llvm/include/llvm/Support/Threading.h b/llvm/include/llvm/Support/Threading.h
index 7f2708ddbb46..f3f7c44bd439 100644
--- a/llvm/include/llvm/Support/Threading.h
+++ b/llvm/include/llvm/Support/Threading.h
@@ -231,6 +231,11 @@ constexpr bool llvm_is_multithreaded() { return LLVM_ENABLE_THREADS; }
/// Returns how many physical CPUs or NUMA groups the system has.
unsigned get_cpus();
+ /// Returns how many physical cores (as opposed to logical cores returned from
+ /// thread::hardware_concurrency(), which includes hyperthreads).
+ /// Returns -1 if unknown for the current host system.
+ int get_physical_cores();
+
enum class ThreadPriority {
/// Lower the current thread's priority as much as possible. Can be used
/// for long-running tasks that are not time critical; more energy-
diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp
index 713227c4b088..c87d9644d097 100644
--- a/llvm/lib/Support/Host.cpp
+++ b/llvm/lib/Support/Host.cpp
@@ -1576,128 +1576,6 @@ VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
} // namespace llvm
#endif
-#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 sys::getHostNumPhysicalCores() {
- static int NumCores = computeHostNumPhysicalCores();
- return NumCores;
-}
-
#if defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64__) || defined(_M_X64)
bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp
index bd954fd7c85a..910437cfb70a 100644
--- a/llvm/lib/Support/Threading.cpp
+++ b/llvm/lib/Support/Threading.cpp
@@ -14,7 +14,7 @@
#include "llvm/Support/Threading.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Config/config.h"
-#include "llvm/Support/Host.h"
+#include "llvm/Config/llvm-config.h"
#include <cassert>
#include <errno.h>
@@ -45,13 +45,16 @@ unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
return 1;
}
+// Unknown if threading turned off
+int llvm::get_physical_cores() { return -1; }
+
#else
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)
diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc
index 037470cadb47..def6afad38c7 100644
--- a/llvm/lib/Support/Unix/Threading.inc
+++ b/llvm/lib/Support/Unix/Threading.inc
@@ -13,12 +13,18 @@
#include "Unix.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#if defined(__APPLE__)
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <pthread/qos.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
#endif
#include <pthread.h>
@@ -316,3 +322,122 @@ llvm::BitVector llvm::get_thread_affinity_mask() {
}
unsigned llvm::get_cpus() { return 1; }
+
+#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]);
+}
+#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;
+}
diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc
index 22cc62d0415a..03c055545259 100644
--- a/llvm/lib/Support/Windows/Threading.inc
+++ b/llvm/lib/Support/Windows/Threading.inc
@@ -231,8 +231,7 @@ static unsigned aggregate(R &&Range, UnaryPredicate P) {
return I;
}
-// for sys::getHostNumPhysicalCores
-int computeHostNumPhysicalCores() {
+int llvm::get_physical_cores() {
static unsigned Cores =
aggregate(getProcessorGroups(), [](const ProcessorGroup &G) {
return G.UsableThreads / G.ThreadsPerCore;
diff --git a/llvm/unittests/Support/Host.cpp b/llvm/unittests/Support/Host.cpp
index 7a999094f1ec..2c89971f4f4d 100644
--- a/llvm/unittests/Support/Host.cpp
+++ b/llvm/unittests/Support/Host.cpp
@@ -30,37 +30,6 @@
using namespace llvm;
-class HostTest : public testing::Test {
- Triple Host;
-
-protected:
- bool isSupportedArchAndOS() {
- // Initially this is only testing detection of the number of
- // physical cores, which is currently only supported/tested on
- // some systems.
- return (Host.isOSWindows() && llvm_is_multithreaded()) ||
- Host.isOSDarwin() || (Host.isX86() && Host.isOSLinux()) ||
- (Host.isOSLinux() && !Host.isAndroid()) ||
- (Host.isSystemZ() && Host.isOSzOS());
- }
-
- HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {}
-};
-
-TEST_F(HostTest, NumPhysicalCoresSupported) {
- if (!isSupportedArchAndOS())
- GTEST_SKIP();
- int Num = sys::getHostNumPhysicalCores();
- ASSERT_GT(Num, 0);
-}
-
-TEST_F(HostTest, NumPhysicalCoresUnsupported) {
- if (isSupportedArchAndOS())
- GTEST_SKIP();
- int Num = sys::getHostNumPhysicalCores();
- ASSERT_EQ(Num, -1);
-}
-
TEST(getLinuxHostCPUName, ARM) {
StringRef CortexA9ProcCpuinfo = R"(
processor : 0
@@ -439,13 +408,13 @@ static bool runAndGetCommandOutput(
return Success;
}
-TEST_F(HostTest, DummyRunAndGetCommandOutputUse) {
+TEST(HostTest, DummyRunAndGetCommandOutputUse) {
// Suppress defined-but-not-used warnings when the tests using the helper are
// disabled.
(void)&runAndGetCommandOutput;
}
-TEST_F(HostTest, getMacOSHostVersion) {
+TEST(HostTest, getMacOSHostVersion) {
llvm::Triple HostTriple(llvm::sys::getProcessTriple());
if (!HostTriple.isMacOSX())
GTEST_SKIP();
@@ -491,7 +460,7 @@ static void getAIXSystemVersion(VersionTuple &SystemVersion) {
.getOSVersion();
}
-TEST_F(HostTest, AIXHostVersionDetect) {
+TEST(HostTest, AIXHostVersionDetect) {
llvm::Triple HostTriple(llvm::sys::getProcessTriple());
if (HostTriple.getOS() != Triple::AIX)
GTEST_SKIP();
@@ -517,7 +486,7 @@ TEST_F(HostTest, AIXHostVersionDetect) {
ASSERT_EQ(SysMinor, HostVersion.getMinor());
}
-TEST_F(HostTest, AIXTargetVersionDetect) {
+TEST(HostTest, AIXTargetVersionDetect) {
llvm::Triple TargetTriple(llvm::sys::getDefaultTargetTriple());
if (TargetTriple.getOS() != Triple::AIX)
GTEST_SKIP();
@@ -535,7 +504,7 @@ TEST_F(HostTest, AIXTargetVersionDetect) {
ASSERT_EQ(SystemVersion.getMinor(), TargetVersion.getMinor());
}
-TEST_F(HostTest, AIXHostCPUDetect) {
+TEST(HostTest, AIXHostCPUDetect) {
llvm::Triple HostTriple(llvm::sys::getProcessTriple());
if (HostTriple.getOS() != Triple::AIX)
GTEST_SKIP();
diff --git a/llvm/unittests/Support/Threading.cpp b/llvm/unittests/Support/Threading.cpp
index 87008f17feb6..daa360e90b1f 100644
--- a/llvm/unittests/Support/Threading.cpp
+++ b/llvm/unittests/Support/Threading.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Threading.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/thread.h"
#include "gtest/gtest.h"
@@ -17,6 +19,18 @@ using namespace llvm;
namespace {
+static bool isThreadingSupportedArchAndOS() {
+ Triple Host(Triple::normalize(sys::getProcessTriple()));
+
+ // Initially this is only testing detection of the number of
+ // physical cores, which is currently only supported/tested on
+ // some systems.
+ return (Host.isOSWindows() && llvm_is_multithreaded()) || Host.isOSDarwin() ||
+ (Host.isX86() && Host.isOSLinux()) ||
+ (Host.isOSLinux() && !Host.isAndroid()) ||
+ (Host.isSystemZ() && Host.isOSzOS());
+}
+
TEST(Threading, PhysicalConcurrency) {
auto Num = heavyweight_hardware_concurrency();
// Since Num is unsigned this will also catch us trying to
@@ -25,6 +39,20 @@ TEST(Threading, PhysicalConcurrency) {
hardware_concurrency().compute_thread_count());
}
+TEST(Threading, NumPhysicalCoresSupported) {
+ if (!isThreadingSupportedArchAndOS())
+ GTEST_SKIP();
+ int Num = get_physical_cores();
+ ASSERT_GT(Num, 0);
+}
+
+TEST(Threading, NumPhysicalCoresUnsupported) {
+ if (isThreadingSupportedArchAndOS())
+ GTEST_SKIP();
+ int Num = get_physical_cores();
+ ASSERT_EQ(Num, -1);
+}
+
#if LLVM_ENABLE_THREADS
class Notification {
@@ -91,4 +119,4 @@ TEST(Threading, AppleStackSize) {
#endif
#endif
-} // end anon namespace
+} // namespace
More information about the cfe-commits
mailing list