diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index bac4aa3e5..906173cae 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -21,6 +21,7 @@ typedef struct FFCPUResult uint16_t coresPhysical; uint16_t coresLogical; uint16_t coresOnline; + uint16_t numaNodes; uint32_t frequencyBase; // GHz uint32_t frequencyMax; // GHz diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 9d8329aa0..1ba7bf846 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -100,5 +100,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectThermalTemp(&cpu->temperature); } + cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0); + return NULL; } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index b799700cd..ccf5d99b5 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -138,6 +138,21 @@ static double detectCPUTemp(void) return FF_CPU_TEMP_UNSET; } +static void detectNumaNodes(FFCPUResult* cpu) +{ + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/sys/devices/system/node/"); + if (!dir) return; + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) + { + if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN) + continue; + if (ffStrStartsWith(entry->d_name, "node") && ffCharIsDigit(entry->d_name[strlen("node")])) + cpu->numaNodes++; + } +} + #ifdef __ANDROID__ #include "common/settings.h" @@ -568,6 +583,8 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0) cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0); + detectNumaNodes(cpu); + return NULL; } @@ -877,6 +894,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options, detectPhysicalCores(cpu); ffCPUDetectByCpuid(cpu); + detectNumaNodes(cpu); return NULL; } diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index d742a702c..fe18c21a9 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -230,6 +230,8 @@ static const char* detectNCores(FFCPUResult* cpu) ++cpu->coresPhysical; else if (ptr->Relationship == RelationProcessorPackage) ++cpu->packages; + else if (ptr->Relationship == RelationNumaNode) + ++cpu->numaNodes; } return NULL; diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 9a9911e33..3d14cdb5a 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -217,6 +217,11 @@ bool ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ else yyjson_mut_obj_add_null(doc, obj, "march"); + if (cpu.numaNodes > 0) + yyjson_mut_obj_add_uint(doc, obj, "numaNodes", cpu.numaNodes); + else + yyjson_mut_obj_add_null(doc, obj, "numaNodes"); + success = true; } @@ -259,6 +264,6 @@ FFModuleBaseInfo ffCPUModuleInfo = { {"Temperature (formatted)", "temperature"}, {"Logical core count grouped by frequency", "core-types"}, {"Processor package count", "packages"}, - {"X86-64 CPU microarchitecture", "march"}, + {"CPU microarchitecture", "march"}, })) };