Permalink
Browse files

x86: Use OS to detect core count.

On Windows and Linux, at least.  This should be more reliable than what we
used before.
  • Loading branch information...
unknownbrackets committed Sep 14, 2018
1 parent 6d0ed4a commit 9351146a28d86daf4271a3adfb47894ef0856950
Showing with 117 additions and 2 deletions.
  1. +112 −0 Common/CPUDetect.cpp
  2. +5 −2 Common/FileUtil.cpp
View
@@ -23,11 +23,14 @@
#endif
#include <memory.h>
#include <set>
#include "base/logging.h"
#include "base/basictypes.h"
#include "file/file_util.h"
#include "Common.h"
#include "CPUDetect.h"
#include "FileUtil.h"
#include "StringUtils.h"
#if defined(_WIN32) && !defined(__MINGW32__)
@@ -97,6 +100,28 @@ CPUInfo::CPUInfo() {
Detect();
}
static std::vector<int> ParseCPUList(const std::string &filename) {
std::string data;
std::vector<int> results;
if (readFileToString(true, filename.c_str(), data)) {
std::vector<std::string> ranges;
SplitString(data, ',', ranges);
for (auto range : ranges) {
int low = 0, high = 0;
int parts = sscanf(range.c_str(), "%d-%d", &low, &high);
if (parts == 1) {
high = low;
}
for (int i = low; i <= high; ++i) {
results.push_back(i);
}
}
}
return results;
}
// Detects the various cpu features
void CPUInfo::Detect() {
memset(this, 0, sizeof(*this));
@@ -260,6 +285,93 @@ void CPUInfo::Detect() {
num_cores = (cpu_id[2] & 0xFF) + 1;
}
}
// The above only gets valid info for the active processor.
// Let's rely on OS APIs for accurate information, if available, below.
#if PPSSPP_PLATFORM(WINDOWS)
#if !PPSSPP_PLATFORM(UWP)
typedef BOOL (WINAPI *getLogicalProcessorInformationEx_f)(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, PDWORD ReturnedLength);
auto getLogicalProcessorInformationEx = (getLogicalProcessorInformationEx_f)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetLogicalProcessorInformationEx");
#else
void *getLogicalProcessorInformationEx = nullptr;
#endif
if (getLogicalProcessorInformationEx) {
#if !PPSSPP_PLATFORM(UWP)
DWORD len = 0;
getLogicalProcessorInformationEx(RelationAll, nullptr, &len);
auto processors = new uint8_t[len];
if (getLogicalProcessorInformationEx(RelationAll, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)processors, &len)) {
num_cores = 0;
logical_cpu_count = 0;
auto p = processors;
while (p < processors + len) {
const auto &processor = *(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)p;
if (processor.Relationship == RelationProcessorCore) {
num_cores++;
for (int j = 0; j < processor.Processor.GroupCount; ++j) {
const auto &mask = processor.Processor.GroupMask[j].Mask;
for (int i = 0; i < sizeof(mask) * 8; ++i) {
logical_cpu_count += (mask >> i) & 1;
}
}
}
p += processor.Size;
}
}
delete [] processors;
#endif
} else {
DWORD len = 0;
const DWORD sz = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
GetLogicalProcessorInformation(nullptr, &len);
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> processors;
processors.resize((len + sz - 1) / sz);
if (GetLogicalProcessorInformation(&processors[0], &len)) {
num_cores = 0;
logical_cpu_count = 0;
for (auto processor : processors) {
if (processor.Relationship == RelationProcessorCore) {
num_cores++;
for (int i = 0; i < sizeof(processor.ProcessorMask) * 8; ++i) {
logical_cpu_count += (processor.ProcessorMask >> i) & 1;
}
}
}
}
}
// This seems to be the count per core. Hopefully all cores are the same, but we counted each above.
logical_cpu_count /= num_cores;
#elif PPSSPP_PLATFORM(LINUX)
if (File::Exists("/sys/devices/system/cpu/present")) {
// This may not count unplugged cores, but at least it's a best guess.
// Also, this assumes the CPU cores are heterogeneous (e.g. all cores could be active simultaneously.)
num_cores = 0;
logical_cpu_count = 0;
std::set<int> counted_cores;
auto present = ParseCPUList("/sys/devices/system/cpu/present");
for (int id : present) {
logical_cpu_count++;
if (counted_cores.count(id) == 0) {
num_cores++;
counted_cores.insert(id);
// Also count any thread siblings as counted.
auto threads = ParseCPUList(StringFromFormat("/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", id));
for (int mark_id : threads) {
counted_cores.insert(mark_id);
}
}
}
}
// This seems to be the count per core. Hopefully all cores are the same, but we counted each above.
logical_cpu_count /= num_cores;
#endif
}
// Turn the cpu info into a string we can show
View
@@ -106,11 +106,14 @@ std::string ResolvePath(const std::string &path) {
typedef DWORD (WINAPI *getFinalPathNameByHandleW_f)(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags);
static getFinalPathNameByHandleW_f getFinalPathNameByHandleW = nullptr;
#if PPSSPP_PLATFORM(UWP)
getFinalPathNameByHandleW = &GetFinalPathNameByHandleW;
#else
if (!getFinalPathNameByHandleW) {
// We leak this, but that's okay since the process should hold onto this DLL for the entire lifetime anyway.
HMODULE kernel32 = LoadLibraryW(L"kernel32.dll");
HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
getFinalPathNameByHandleW = (getFinalPathNameByHandleW_f)GetProcAddress(kernel32, "GetFinalPathNameByHandleW");
}
#endif
static const int BUF_SIZE = 32768;
wchar_t *buf = new wchar_t[BUF_SIZE];

0 comments on commit 9351146

Please sign in to comment.