|
12 | 12 | //===----------------------------------------------------------------------===//
|
13 | 13 |
|
14 | 14 | #include "llvm/Support/Host.h"
|
| 15 | +#include "llvm/ADT/SmallSet.h" |
15 | 16 | #include "llvm/ADT/SmallVector.h"
|
16 | 17 | #include "llvm/ADT/StringRef.h"
|
17 | 18 | #include "llvm/ADT/StringSwitch.h"
|
18 | 19 | #include "llvm/ADT/Triple.h"
|
19 | 20 | #include "llvm/Config/config.h"
|
20 | 21 | #include "llvm/Support/Debug.h"
|
21 | 22 | #include "llvm/Support/FileSystem.h"
|
| 23 | +#include "llvm/Support/MemoryBuffer.h" |
22 | 24 | #include "llvm/Support/raw_ostream.h"
|
23 |
| -#include <string.h> |
24 | 25 | #include <assert.h>
|
| 26 | +#include <string.h> |
25 | 27 |
|
26 | 28 | // Include the platform-specific parts of this class.
|
27 | 29 | #ifdef LLVM_ON_UNIX
|
@@ -1188,6 +1190,60 @@ StringRef sys::getHostCPUName() {
|
1188 | 1190 | StringRef sys::getHostCPUName() { return "generic"; }
|
1189 | 1191 | #endif
|
1190 | 1192 |
|
| 1193 | +#if defined(__linux__) && defined(__x86_64__) |
| 1194 | +// On Linux, the number of physical cores can be computed from /proc/cpuinfo, |
| 1195 | +// using the number of unique physical/core id pairs. The following |
| 1196 | +// implementation reads the /proc/cpuinfo format on an x86_64 system. |
| 1197 | +int computeHostNumPhysicalCores() { |
| 1198 | + // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be |
| 1199 | + // mmapped because it appears to have 0 size. |
| 1200 | + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = |
| 1201 | + llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); |
| 1202 | + if (std::error_code EC = Text.getError()) { |
| 1203 | + llvm::errs() << "Can't read " |
| 1204 | + << "/proc/cpuinfo: " << EC.message() << "\n"; |
| 1205 | + } |
| 1206 | + SmallVector<StringRef, 8> strs; |
| 1207 | + (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, |
| 1208 | + /*KeepEmpty=*/false); |
| 1209 | + int CurPhysicalId = -1; |
| 1210 | + int CurCoreId = -1; |
| 1211 | + SmallSet<std::pair<int, int>, 32> UniqueItems; |
| 1212 | + for (auto &Line : strs) { |
| 1213 | + Line = Line.trim(); |
| 1214 | + if (!Line.startswith("physical id") && !Line.startswith("core id")) |
| 1215 | + continue; |
| 1216 | + std::pair<StringRef, StringRef> Data = Line.split(':'); |
| 1217 | + auto Name = Data.first.trim(); |
| 1218 | + auto Val = Data.second.trim(); |
| 1219 | + if (Name == "physical id") { |
| 1220 | + assert(CurPhysicalId == -1 && |
| 1221 | + "Expected a core id before seeing another physical id"); |
| 1222 | + Val.getAsInteger(10, CurPhysicalId); |
| 1223 | + } |
| 1224 | + if (Name == "core id") { |
| 1225 | + assert(CurCoreId == -1 && |
| 1226 | + "Expected a physical id before seeing another core id"); |
| 1227 | + Val.getAsInteger(10, CurCoreId); |
| 1228 | + } |
| 1229 | + if (CurPhysicalId != -1 && CurCoreId != -1) { |
| 1230 | + UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId)); |
| 1231 | + CurPhysicalId = -1; |
| 1232 | + CurCoreId = -1; |
| 1233 | + } |
| 1234 | + } |
| 1235 | + return UniqueItems.size(); |
| 1236 | +} |
| 1237 | +#else |
| 1238 | +// On other systems, return -1 to indicate unknown. |
| 1239 | +int computeHostNumPhysicalCores() { return -1; } |
| 1240 | +#endif |
| 1241 | + |
| 1242 | +int sys::getHostNumPhysicalCores() { |
| 1243 | + static int NumCores = computeHostNumPhysicalCores(); |
| 1244 | + return NumCores; |
| 1245 | +} |
| 1246 | + |
1191 | 1247 | #if defined(__i386__) || defined(_M_IX86) || \
|
1192 | 1248 | defined(__x86_64__) || defined(_M_X64)
|
1193 | 1249 | bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
|
|
0 commit comments