From d441188c15183c9496e44169966112304a1fc915 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 16 Apr 2020 12:05:53 -0700 Subject: [PATCH] [Support][X86] Change getHostNumPhsicalCores() to return number of physical cores enabled by affinity Fixes https://bugs.llvm.org/show_bug.cgi?id=45556 While here, make the x86-64 code available for x86-32. The output has been available and stable since https://git.kernel.org/linus/3dd9d514846cdca1dcef2e4fce666d85e199e844 (2005) ``` processor: ... physical id: siblings: core id: ``` Don't check HAVE_SCHED_GETAFFINITY/HAVE_CPU_COUNT. The interface is simply available in every libc which can build LLVM. Reviewed By: aganea Differential Revision: https://reviews.llvm.org/D78324 --- llvm/lib/Support/Host.cpp | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index f236456..43df31d 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -1277,11 +1277,18 @@ StringRef sys::getHostCPUName() { StringRef sys::getHostCPUName() { return "generic"; } #endif -#if defined(__linux__) && defined(__x86_64__) +#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. 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> Text = @@ -1294,33 +1301,29 @@ int computeHostNumPhysicalCores() { SmallVector strs; (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + int CurProcessor = -1; int CurPhysicalId = -1; + int CurSiblings = -1; int CurCoreId = -1; - SmallSet, 32> UniqueItems; - for (auto &Line : strs) { - Line = Line.trim(); - if (!Line.startswith("physical id") && !Line.startswith("core id")) - continue; + for (StringRef Line : strs) { std::pair Data = Line.split(':'); auto Name = Data.first.trim(); auto Val = Data.second.trim(); - if (Name == "physical id") { - assert(CurPhysicalId == -1 && - "Expected a core id before seeing another physical id"); + // 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); - } - if (Name == "core id") { - assert(CurCoreId == -1 && - "Expected a physical id before seeing another core id"); + else if (Name == "siblings") + Val.getAsInteger(10, CurSiblings); + else if (Name == "core id") { Val.getAsInteger(10, CurCoreId); - } - if (CurPhysicalId != -1 && CurCoreId != -1) { - UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId)); - CurPhysicalId = -1; - CurCoreId = -1; + // The processor id corresponds to an index into cpu_set_t. + if (CPU_ISSET(CurProcessor, &Affinity)) + CPU_SET(CurPhysicalId * CurSiblings + CurCoreId, &Enabled); } } - return UniqueItems.size(); + return CPU_COUNT(&Enabled); } #elif defined(__APPLE__) && defined(__x86_64__) #include -- 2.7.4