ohmu
·
2026-10-15
1#include "cpucache.h"
2#include "common/debug.h"
3#include "common/sysctl.h"
4#include "common/strutil.h"
5
6const char* ffDetectCPUCache(FFCPUCacheResult* result) {
7 // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities#3901385
8 uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
9 if (nPerfLevels <= 0) {
10 FF_DEBUG("sysctl(hw.nperflevels) failed");
11 return "sysctl(hw.nperflevels) failed";
12 }
13
14 // macOS provides the global system cache line size
15 uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);
16
17 char sysctlKey[128] = "hw.perflevelN.";
18 char* pNum = sysctlKey + strlen("hw.perflevel");
19 char* pSubkey = sysctlKey + strlen("hw.perflevelN.");
20 const size_t lenLeft = ARRAY_SIZE(sysctlKey) - strlen("hw.perflevelN.");
21
22 for (uint32_t i = 0; i < nPerfLevels; ++i) {
23 *pNum = (char) ('0' + i);
24
25 ffStrCopy(pSubkey, "physicalcpu", lenLeft);
26 uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
27 if (ncpu <= 0) {
28 continue;
29 }
30
31 ffStrCopy(pSubkey, "l1icachesize", lenLeft);
32 uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
33 if (size) {
34 ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu;
35 }
36
37 ffStrCopy(pSubkey, "l1dcachesize", lenLeft);
38 size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
39 if (size) {
40 ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu;
41 }
42
43 ffStrCopy(pSubkey, "l2cachesize", lenLeft);
44 size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
45 if (size) {
46 ffStrCopy(pSubkey, "cpusperl2", lenLeft);
47 uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
48 if (cpuSper) {
49 ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
50 }
51 }
52
53 ffStrCopy(pSubkey, "l3cachesize", lenLeft);
54 size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
55 if (size) {
56 ffStrCopy(pSubkey, "cpusperl3", lenLeft);
57 uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
58 if (cpuSper) {
59 ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
60 }
61 }
62 }
63
64 return nullptr;
65}