-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcpuinfo.h
148 lines (141 loc) · 3.92 KB
/
cpuinfo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#pragma once
#include <string>
#include <vector>
#include <thread>
#include <atomic>
#include <mutex>
#include <syncstream>
bool initialized = false;
#ifdef _M_AMD64
#define arch "x86"
#elif defined _M_IX86
#define arch "x86"
#elif defined _M_ARM
#define arch "ARM"
#elif defined _M_ARM64
#define arch "ARM"
#else
#error "CPUInfo does not support this archetechure and operating system combination"
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#include <syncstream>
class ProcessorCoreDescriptor {
public:
std::string ar;
int32_t flags0 = 0x0000;
int32_t flags1 = 0x0000;
std::string name;
std::string vendor;
bool getFlag0(int shift) {
return (flags0 & shift) != 0;
}
bool getFlag1(int shift) {
return (flags1 & shift) != 0;
}
private:
void setArch(std::string ar) {
this->ar = ar;
}
};
#ifdef _M_AMD64
#include "cpuinfox86.h"
#define cpuLibIncluded true
#elif defined _M_IX86
#ifndef cpuLibIncluded
#include "cpuinfox86.h"
#define cpuLibIncluded true
#endif
#elif defined _M_ARM
#ifndef cpuLibIncluded
#include "cpuinfoARM.h"
#define cpuLibIncluded true
#endif
#elif defined _M_ARM64
#ifndef cpuLibIncluded
#include "cpuinfoARM.h"
#define cpuLibIncluded true
#endif
#else
#error "SturdyEngine does not support your archetechure, please compile for either x86-64 or for ARM"
#endif
class ProcessorDescriptor {
std::vector<std::shared_ptr<std::mutex>> threadMutexes;
std::vector<ProcessorCoreDescriptor> coreDescriptors;
std::vector<bool> threadsFinished;
public:
int numThreads;
ProcessorDescriptor() {
numThreads = std::thread::hardware_concurrency();
threadMutexes.resize(numThreads);
coreDescriptors.resize(numThreads);
std::osyncstream(std::cout) << "Checking hardware..." << std::endl;
threadsFinished.resize(numThreads);
for (int i = 0; i < numThreads; ++i) {
// Allocate a new mutex for each thread
threadMutexes[i] = std::make_shared<std::mutex>();
coreDescriptors[i] = ProcessorCoreDescriptor();
// Create a thread with specific core affinity
threadsFinished[i] = false;
auto lambd = [this, i]() {
auto lock = std::lock_guard<std::mutex>(*this->threadMutexes[i]);
auto& desc = this->coreDescriptors[i];
initFlags(desc);
threadsFinished[i] = true;
};
{
std::thread t(lambd); // Perfect forwarding of the callable
#ifdef _WIN32
//Windows-specific code to set thread affinity
HANDLE threadHandle = t.native_handle();
DWORD_PTR affinityMask = 1ULL << i;
if (SetThreadAffinityMask(threadHandle, affinityMask) == 0) {
std::cerr << "Failed to set thread affinity on Windows. Error: " << GetLastError() << std::endl;
}
#else
// Linux-specific code to set thread affinity
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(coreId, &cpuset);
int rc = pthread_setaffinity_np(t.native_handle(), sizeof(cpu_set_t), &cpuset);
if (rc != 0) {
std::cerr << "Failed to set thread affinity on Linux. Error: " << strerror(rc) << std::endl;
}
#endif
t.detach();
}
}
for (int i = 0; i < numThreads; ++i) {
while (!threadsFinished[i]) {}
}
}
ProcessorCoreDescriptor getCoreDescriptor(int index) {
return this->coreDescriptors[index];
}
};
namespace CPUInfo {
class CPU {
public:
bool isHybrid = false; //assume non-hybrid
CPU() {
if (!initialized) {
this->proc = ProcessorDescriptor();
for (int i = 0; i < proc.numThreads; ++i) {
auto desc = proc.getCoreDescriptor(i);
for (int j = 0; j < proc.numThreads; ++j) {
auto desc2 = proc.getCoreDescriptor(j);
if (!(desc.flags0 == desc2.flags0 && (desc.flags1 == desc2.flags1))) {
this->isHybrid = true; //if the flags of every core are not the same, tell the struct we are a hybrid CPU
}
}
}
}
}
ProcessorDescriptor& getDescriptor() {
return this->proc;
}
private:
ProcessorDescriptor proc;
};
}