getFile(const Twine &Filename, int64_t FileSize = -1,
bool RequiresNullTerminator = true, bool IsVolatileSize = false);
+ /// Read all of the specified file into a MemoryBuffer as a stream
+ /// (i.e. until EOF reached). This is useful for special files that
+ /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ getFileAsStream(const Twine &Filename);
+
/// Given an already-open file descriptor, map some slice of it into a
/// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
/// Since this is in the middle of a file, the buffer is not null terminated.
//===----------------------------------------------------------------------===//
#include "llvm/Support/Host.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include <string.h>
#include <assert.h>
+#include <string.h>
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
StringRef sys::getHostCPUName() { return "generic"; }
#endif
+#if defined(__linux__) && 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() {
+ // 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";
+ }
+ SmallVector<StringRef, 8> strs;
+ (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
+ /*KeepEmpty=*/false);
+ int CurPhysicalId = -1;
+ int CurCoreId = -1;
+ SmallSet<std::pair<int, int>, 32> UniqueItems;
+ for (auto &Line : strs) {
+ Line = Line.trim();
+ if (!Line.startswith("physical id") && !Line.startswith("core id"))
+ continue;
+ std::pair<StringRef, StringRef> 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");
+ Val.getAsInteger(10, CurPhysicalId);
+ }
+ if (Name == "core id") {
+ assert(CurCoreId == -1 &&
+ "Expected a physical id before seeing another core id");
+ Val.getAsInteger(10, CurCoreId);
+ }
+ if (CurPhysicalId != -1 && CurCoreId != -1) {
+ UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
+ CurPhysicalId = -1;
+ CurCoreId = -1;
+ }
+ }
+ return UniqueItems.size();
+}
+#else
+// On other systems, return -1 to indicate unknown.
+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) {
--- /dev/null
+//========- unittests/Support/Host.cpp - Host.cpp tests --------------========//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Host.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+class HostTest : public testing::Test {
+ Triple Host;
+ SmallVector<std::pair<Triple::ArchType, Triple::OSType>, 4> SupportedArchAndOSs;
+
+protected:
+ bool isSupportedArchAndOS() {
+ if (is_contained(SupportedArchAndOSs, std::make_pair(Host.getArch(), Host.getOS())))
+ return true;
+
+ return false;
+ }
+
+ HostTest() {
+ Host.setTriple(Triple::normalize(sys::getProcessTriple()));
+
+ // Initially this is only testing detection of the number of
+ // physical cores, which is currently only supported for
+ // x86_64 Linux.
+ SupportedArchAndOSs.push_back(std::make_pair(Triple::x86_64, Triple::Linux));
+ }
+};
+
+TEST_F(HostTest, NumPhysicalCores) {
+ int Num = sys::getHostNumPhysicalCores();
+
+ if (isSupportedArchAndOS())
+ ASSERT_GT(Num, 0);
+ else
+ ASSERT_EQ(Num, -1);
+}