summaryrefslogtreecommitdiffstats
path: root/src/detection/cpucache/cpucache_apple.c
blob: 3d1562cef2cef2d856f2a47b3c924f9cf44353eb (plain) (blame)
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
#include "cpucache.h"
#include "common/sysctl.h"
#include "common/strutil.h"

const char* ffDetectCPUCache(FFCPUCacheResult* result) {
    // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities#3901385
    uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
    if (nPerfLevels <= 0) {
        return "sysctl(hw.nperflevels) failed";
    }

    // macOS provides the global system cache line size
    uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);

    char sysctlKey[128] = "hw.perflevelN.";
    char* pNum = sysctlKey + strlen("hw.perflevel");
    char* pSubkey = sysctlKey + strlen("hw.perflevelN.");
    const size_t lenLeft = ARRAY_SIZE(sysctlKey) - strlen("hw.perflevelN.");

    for (uint32_t i = 0; i < nPerfLevels; ++i) {
        *pNum = (char) ('0' + i);

        ffStrCopy(pSubkey, "physicalcpu", lenLeft);
        uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
        if (ncpu <= 0) {
            continue;
        }

        ffStrCopy(pSubkey, "l1icachesize", lenLeft);
        uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
        if (size) {
            ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu;
        }

        ffStrCopy(pSubkey, "l1dcachesize", lenLeft);
        size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
        if (size) {
            ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu;
        }

        ffStrCopy(pSubkey, "l2cachesize", lenLeft);
        size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
        if (size) {
            ffStrCopy(pSubkey, "cpusperl2", lenLeft);
            uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
            if (cpuSper) {
                ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
            }
        }

        ffStrCopy(pSubkey, "l3cachesize", lenLeft);
        size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
        if (size) {
            ffStrCopy(pSubkey, "cpusperl3", lenLeft);
            uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
            if (cpuSper) {
                ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
            }
        }
    }

    return NULL;
}