CPU (Linux): detect core count for different core types

This commit is contained in:
Carter Li
2024-05-17 16:14:35 +08:00
committed by 李通洲
parent 02e5232bda
commit 1421627a47
3 changed files with 64 additions and 22 deletions
+2
View File
@@ -17,6 +17,8 @@ typedef struct FFCPUResult
double frequencyMax; // GHz
double frequencyMin; // GHz
uint8_t coreCounts[8]; // number of P cores, E cores, etc.
double temperature;
} FFCPUResult;
+42 -10
View File
@@ -88,14 +88,14 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
return NULL;
}
static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
{
uint32_t baseLen = basePath->length;
ffStrbufAppendS(basePath, cpuinfoFileName);
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return ffStrbufToDouble(buffer) / 1e6;
return (uint32_t) ffStrbufToUInt(buffer, 0);
if (scalingFileName)
{
@@ -103,10 +103,28 @@ static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, cons
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return ffStrbufToDouble(buffer) / 1e6;
return (uint32_t) ffStrbufToUInt(buffer, 0);
}
return 0.0/0.0;
return 0;
}
static uint8_t getNumCores(FFstrbuf* basePath, FFstrbuf* buffer)
{
uint32_t baseLen = basePath->length;
ffStrbufAppendS(basePath, "/affected_cpus");
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return (uint8_t) ffStrbufCountC(buffer, ' ') + 1;
ffStrbufAppendS(basePath, "/related_cpus");
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return (uint8_t) ffStrbufCountC(buffer, ' ') + 1;
return 0;
}
static bool detectFrequency(FFCPUResult* cpu)
@@ -118,30 +136,41 @@ static bool detectFrequency(FFCPUResult* cpu)
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
uint32_t baseLen = path.length;
uint64_t freq = (uint64_t) -1;
uint32_t ifreq = (uint32_t) -1;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if (ffStrStartsWith(entry->d_name, "policy") && isdigit(entry->d_name[strlen("policy")]))
{
ffStrbufAppendS(&path, entry->d_name);
double fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
if (fbase == fbase)
uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
if (fbase > 0)
{
if (cpu->frequencyBase == cpu->frequencyBase)
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
else
cpu->frequencyBase = fbase;
}
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
if (fmax == fmax)
uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
if (fmax > 0)
{
if (cpu->frequencyMax == cpu->frequencyMax)
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
else
cpu->frequencyMax = fmax;
if (fmax != freq)
{
freq = fmax;
++ifreq;
}
if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true))
cpu->coreCounts[ifreq] += getNumCores(&path, &buffer);
}
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
if (fmin == fmin)
uint32_t fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
if (fmin > 0)
{
if (cpu->frequencyMin == cpu->frequencyMin)
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
@@ -151,6 +180,9 @@ static bool detectFrequency(FFCPUResult* cpu)
ffStrbufSubstrBefore(&path, baseLen);
}
}
cpu->frequencyBase /= 1e6;
cpu->frequencyMax /= 1e6;
cpu->frequencyMin /= 1e6;
return true;
}
+20 -12
View File
@@ -10,12 +10,14 @@
void ffPrintCPU(FFCPUOptions* options)
{
FFCPUResult cpu;
cpu.temperature = FF_CPU_TEMP_UNSET;
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
ffStrbufInit(&cpu.name);
ffStrbufInit(&cpu.vendor);
FFCPUResult cpu = {
.temperature = FF_CPU_TEMP_UNSET,
.frequencyMin = 0.0/0.0,
.frequencyMax = 0.0/0.0,
.frequencyBase = 0.0/0.0,
.name = ffStrbufCreate(),
.vendor = ffStrbufCreate()
};
const char* error = ffDetectCPU(options, &cpu);
@@ -143,12 +145,14 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FFCPUResult cpu;
cpu.temperature = FF_CPU_TEMP_UNSET;
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
ffStrbufInit(&cpu.name);
ffStrbufInit(&cpu.vendor);
FFCPUResult cpu = {
.temperature = FF_CPU_TEMP_UNSET,
.frequencyMin = 0.0/0.0,
.frequencyMax = 0.0/0.0,
.frequencyBase = 0.0/0.0,
.name = ffStrbufCreate(),
.vendor = ffStrbufCreate()
};
const char* error = ffDetectCPU(options, &cpu);
@@ -176,6 +180,10 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax);
yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin);
yyjson_mut_val* coreCounts = yyjson_mut_obj_add_arr(doc, obj, "coreCounts");
for (uint32_t i = 0; i < sizeof (cpu.coreCounts) && cpu.coreCounts[i] > 0; i++)
yyjson_mut_arr_add_uint(doc, coreCounts, cpu.coreCounts[i]);
yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature);
}