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
|
#include "cpu.h"
#include "common/sysctl.h"
#include "common/strutil.h"
#include <sys/param.h>
#if __has_include(<sys/cpuset.h>)
#include <sys/cpuset.h>
#define FF_HAVE_CPUSET 1
#endif
static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
int temp;
if (options->tempSensor.length > 0) {
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
if (temp == -999999) {
return "ffSysctlGetInt(options->tempSensor) failed";
}
} else {
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999) {
// Thermal zone temperature
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999) {
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
}
}
}
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
if (ffSysctlGetString("hw.model", &cpu->name) != NULL) {
return "sysctlbyname(hw.model) failed";
}
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("kern.smp.cores", 0);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("kern.smp.cpus", cpu->coresLogical);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0) {
// <groups>
// <group level="1" cache-level="3">
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
// <children>
// <group level="2" cache-level="2">
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// <group level="2" cache-level="2">
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// </children>
// </group>
// </groups>
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p) {
cpu->packages++;
}
}
#if FF_HAVE_CPUSET && (__x86_64__ || __i386__)
// Bind current process to the first two cores, which is *usually* a performance core
cpuset_t currentCPU;
CPU_ZERO(¤tCPU);
CPU_SET(1, ¤tCPU);
CPU_SET(2, ¤tCPU);
cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), ¤tCPU);
#endif
ffCPUDetectByCpuid(cpu);
uint32_t clockrate = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
if (clockrate > cpu->frequencyBase) {
cpu->frequencyBase = clockrate;
}
for (uint16_t i = 0; i < cpu->coresLogical; ++i) {
ffStrbufClear(&buffer);
char key[32];
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
if (ffSysctlGetString(key, &buffer) == NULL) {
if (buffer.length == 0) {
continue;
}
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
if (cpu->frequencyMax < fmax) {
cpu->frequencyMax = fmax;
}
} else {
break;
}
}
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) {
detectCpuTemp(options, &cpu->temperature);
}
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
return NULL;
}
|