diff options
| author | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
|---|---|---|
| committer | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
| commit | 76424950e373d3b04ac3dd13019151bfba3e8423 (patch) | |
| tree | 4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/cpu/cpu_bsd.c | |
Add the files
Diffstat (limited to 'src/detection/cpu/cpu_bsd.c')
| -rw-r--r-- | src/detection/cpu/cpu_bsd.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c new file mode 100644 index 0000000..4cca30e --- /dev/null +++ b/src/detection/cpu/cpu_bsd.c @@ -0,0 +1,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; +} |