CPU: support display frequency in MHz

This commit is contained in:
李通洲
2024-07-17 10:56:30 +08:00
committed by Carter Li
parent c0de618177
commit d282050130
13 changed files with 84 additions and 89 deletions
+2 -2
View File
@@ -1104,9 +1104,9 @@
"$ref": "#/$defs/temperature"
},
"freqNdigits": {
"description": "Set the number of digits to keep after the decimal point when printing CPU frequency",
"description": "Set the number of digits to keep after the decimal point when printing frequency in GHz, or MHz if set to -1",
"type": "integer",
"minimum": 0,
"minimum": -1,
"maximum": 9,
"default": 2
},
+12
View File
@@ -96,6 +96,18 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
}
}
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits)
{
if (mhz == 0)
return false;
if (freqNdigits >= 0)
ffStrbufAppendF(result, "%.*f GHz", freqNdigits, mhz / 1000.);
else
ffStrbufAppendF(result, "%u MHz", (unsigned) mhz);
return true;
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
+1
View File
@@ -26,3 +26,4 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
void ffParseSize(uint64_t bytes, FFstrbuf* result);
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits);
+1 -1
View File
@@ -1179,7 +1179,7 @@
},
{
"long": "cpu-freq-ndigits",
"desc": "Set the number of digits to keep after the decimal point when printing CPU frequency",
"desc": "Set the number of digits to keep after the decimal point when printing CPU frequency in GHz",
"arg": {
"type": "num",
"default": 2
+3 -3
View File
@@ -19,9 +19,9 @@ typedef struct FFCPUResult
uint16_t coresLogical;
uint16_t coresOnline;
double frequencyBase; // GHz
double frequencyMax; // GHz
double frequencyBiosLimit; // GHz
uint32_t frequencyBase; // GHz
uint32_t frequencyMax; // GHz
uint32_t frequencyBiosLimit; // GHz
FFCPUCore coreTypes[16]; // number of P cores, E cores, etc.
+5 -5
View File
@@ -56,21 +56,21 @@ static const char* detectFrequency(FFCPUResult* cpu)
pMax = pMax > pStart[i] ? pMax : pStart[i];
if (pMax > 0)
cpu->frequencyMax = pMax / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyMax = pMax / 1000 / 1000;
return NULL;
}
#else
static const char* detectFrequency(FFCPUResult* cpu)
{
cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000.0 / 1000.0 / 1000.0;
if(cpu->frequencyBase != cpu->frequencyBase)
cpu->frequencyBase = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency", 0) / 1000 / 1000);
cpu->frequencyMax = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000 / 1000);
if(cpu->frequencyBase == 0)
{
unsigned current = 0;
size_t size = sizeof(current);
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, &current, &size, NULL, 0) == 0)
cpu->frequencyBase = (double) current / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyBase = (uint32_t) (current / 1000 / 1000);
}
return NULL;
}
+7 -5
View File
@@ -44,11 +44,13 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffStrbufClear(&buffer);
char key[32];
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
if (ffSysctlGetString(key, &buffer) == NULL && buffer.length > 0)
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;
if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax;
if (options->showPeCoreCount)
{
@@ -60,11 +62,11 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coreTypes[ifreq].count++;
}
}
else
break;
}
cpu->frequencyMax /= 1000;
int clockRate = ffSysctlGetInt("hw.clockrate", 0);
cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0;
cpu->frequencyBase = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
+9 -25
View File
@@ -94,7 +94,7 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return (uint32_t) ffStrbufToUInt(buffer, 0);
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
if (scalingFileName)
{
@@ -102,7 +102,7 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return (uint32_t) ffStrbufToUInt(buffer, 0);
return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000);
}
return 0;
@@ -143,28 +143,15 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options)
ffStrbufAppendS(&path, entry->d_name);
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;
}
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
uint32_t fbioslimit = getFrequency(&path, "/bios_limit", NULL, &buffer);
if (fbioslimit > 0)
{
if (cpu->frequencyBiosLimit == cpu->frequencyBiosLimit)
cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit;
else
cpu->frequencyBiosLimit = fbioslimit;
}
cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit;
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;
}
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
if (options->showPeCoreCount)
{
@@ -179,9 +166,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options)
ffStrbufSubstrBefore(&path, baseLen);
}
}
cpu->frequencyBase /= 1e6;
cpu->frequencyMax /= 1e6;
cpu->frequencyBiosLimit /= 1e6;
return true;
}
@@ -263,8 +247,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coresOnline = (uint16_t) get_nprocs();
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
if (!detectFrequency(cpu, options) || cpu->frequencyBase != cpu->frequencyBase)
cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000;
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
if(cpuUarch.length > 0)
{
+1 -1
View File
@@ -31,7 +31,7 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
}
{
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
cpu->frequencyBase = kn->value.ui32 / 1000.;
cpu->frequencyBase = kn->value.ui32;
}
ks = kstat_lookup(kc, "unix", -1, "system_misc");
+7 -7
View File
@@ -65,8 +65,8 @@ inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
return "Unsupported instruction";
// cpuid returns 0 MHz when hyper-v is enabled
if (base) cpu->frequencyBase = base / 1000.0;
if (max) cpu->frequencyMax = max / 1000.0;
if (base) cpu->frequencyBase = base;
if (max) cpu->frequencyMax = max;
return NULL;
}
@@ -97,7 +97,7 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
return "No active CPU is found in SMBIOS data";
}
double speed = data->MaxSpeed / 1000.0;
uint32_t speed = data->MaxSpeed;
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
return "Possible invalid CPU max speed in SMBIOS data. See #800";
@@ -159,7 +159,7 @@ static const char* detectByRegistry(FFCPUResult* cpu)
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
cpu->frequencyBase = mhz / 1000.0;
cpu->frequencyBase = mhz;
return NULL;
}
@@ -180,8 +180,8 @@ static const char* detectCoreTypes(FFCPUResult* cpu)
++cpu->coreTypes[ifreq].count;
}
if (cpu->frequencyBase != cpu->frequencyBase)
cpu->frequencyBase = pinfo->MaxMhz / 1000.0;
if (cpu->frequencyBase == 0)
cpu->frequencyBase = pinfo->MaxMhz;
return NULL;
}
@@ -196,7 +196,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectSpeedByCpuid(cpu);
if (options->showPeCoreCount) detectCoreTypes(cpu);
if (cpu->frequencyMax != cpu->frequencyMax)
if (cpu->frequencyMax == 0)
detectMaxSpeedBySmbios(cpu);
if(options->temp)
+32 -36
View File
@@ -17,9 +17,9 @@ void ffPrintCPU(FFCPUOptions* options)
{
FFCPUResult cpu = {
.temperature = FF_CPU_TEMP_UNSET,
.frequencyMax = 0.0/0.0,
.frequencyBase = 0.0/0.0,
.frequencyBiosLimit = 0.0/0.0,
.frequencyMax = 0,
.frequencyBase = 0,
.frequencyBiosLimit = 0,
.name = ffStrbufCreate(),
.vendor = ffStrbufCreate(),
};
@@ -71,13 +71,16 @@ void ffPrintCPU(FFCPUOptions* options)
else if(cpu.coresOnline > 1)
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
double freq = cpu.frequencyBiosLimit;
if(!(freq > 0.0000001))
uint32_t freq = cpu.frequencyBiosLimit;
if(freq == 0)
freq = cpu.frequencyMax;
if(!(freq > 0.0000001))
if(freq == 0)
freq = cpu.frequencyBase;
if(freq > 0.0000001)
ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, freq);
if(freq > 0)
{
ffStrbufAppendS(&str, " @ ");
ffParseFrequency(freq, &str, options->freqNdigits);
}
if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET
{
@@ -89,19 +92,12 @@ void ffPrintCPU(FFCPUOptions* options)
}
else
{
char freqBase[32], freqMax[32], freqBioslimit[32];
if (cpu.frequencyBase > 0)
snprintf(freqBase, sizeof(freqBase), "%.*f", options->freqNdigits, cpu.frequencyBase);
else
freqBase[0] = 0;
if (cpu.frequencyMax > 0)
snprintf(freqMax, sizeof(freqMax), "%.*f", options->freqNdigits, cpu.frequencyMax);
else
freqMax[0] = 0;
if (cpu.frequencyBiosLimit > 0)
snprintf(freqBioslimit, sizeof(freqBioslimit), "%.*f", options->freqNdigits, cpu.frequencyBiosLimit);
else
freqBioslimit[0] = 0;
FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits);
FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits);
FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit, options->freqNdigits);
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs);
@@ -111,11 +107,11 @@ void ffPrintCPU(FFCPUOptions* options)
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical, "cores-physical"},
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical, "cores-logical"},
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline, "cores-online"},
{FF_FORMAT_ARG_TYPE_STRING, freqBase, "freq-base"},
{FF_FORMAT_ARG_TYPE_STRING, freqMax, "freq-max"},
{FF_FORMAT_ARG_TYPE_STRBUF, &freqBase, "freq-base"},
{FF_FORMAT_ARG_TYPE_STRBUF, &freqMax, "freq-max"},
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr, "temperature"},
{FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes, "core-types"},
{FF_FORMAT_ARG_TYPE_STRING, freqBioslimit, "freq-bios-limit"},
{FF_FORMAT_ARG_TYPE_STRBUF, &freqBioslimit, "freq-bios-limit"},
}));
}
}
@@ -136,7 +132,7 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char
if (ffStrEqualsIgnCase(subKey, "freq-ndigits"))
{
options->freqNdigits = (uint8_t) ffOptionParseUInt32(key, value);
options->freqNdigits = (int8_t) ffOptionParseInt32(key, value);
return true;
}
@@ -167,7 +163,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "freqNdigits"))
{
options->freqNdigits = (uint8_t) yyjson_get_uint(val);
options->freqNdigits = (int8_t) yyjson_get_int(val);
continue;
}
@@ -191,7 +187,7 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig);
if (defaultOptions.freqNdigits != options->freqNdigits)
yyjson_mut_obj_add_uint(doc, module, "freqNdigits", options->freqNdigits);
yyjson_mut_obj_add_int(doc, module, "freqNdigits", options->freqNdigits);
if (defaultOptions.showPeCoreCount != options->showPeCoreCount)
yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount);
@@ -201,9 +197,9 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
{
FFCPUResult cpu = {
.temperature = FF_CPU_TEMP_UNSET,
.frequencyMax = 0.0/0.0,
.frequencyBase = 0.0/0.0,
.frequencyBiosLimit = 0.0/0.0,
.frequencyMax = 0,
.frequencyBase = 0,
.frequencyBiosLimit = 0,
.name = ffStrbufCreate(),
.vendor = ffStrbufCreate(),
};
@@ -230,9 +226,9 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
yyjson_mut_obj_add_uint(doc, cores, "online", cpu.coresOnline);
yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency");
yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase);
yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax);
yyjson_mut_obj_add_real(doc, frequency, "biosLimit", cpu.frequencyBiosLimit);
yyjson_mut_obj_add_uint(doc, frequency, "base", cpu.frequencyBase);
yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax);
yyjson_mut_obj_add_uint(doc, frequency, "biosLimit", cpu.frequencyBiosLimit);
yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes");
for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++)
@@ -257,11 +253,11 @@ void ffPrintCPUHelpFormat(void)
"Physical core count - cores-physical",
"Logical core count - cores-logical",
"Online core count - cores-online",
"Base frequency - freq-base",
"Max frequency - freq-max",
"Base frequency (formatted) - freq-base",
"Max frequency (formatted) - freq-max",
"Temperature (formatted) - temperature",
"Logical core count grouped by frequency - core-types",
"Bios limited frequency - freq-bios-limit",
"Bios limited frequency (formatted) - freq-bios-limit",
}));
}
+1 -1
View File
@@ -11,6 +11,6 @@ typedef struct FFCPUOptions
bool temp;
FFColorRangeConfig tempConfig;
uint8_t freqNdigits;
int8_t freqNdigits;
bool showPeCoreCount;
} FFCPUOptions;
+3 -3
View File
@@ -30,9 +30,9 @@ void ffPrintLoadavg(FFLoadavgOptions* options)
{
FFCPUResult cpu = {
.temperature = FF_CPU_TEMP_UNSET,
.frequencyMax = 0.0/0.0,
.frequencyBase = 0.0/0.0,
.frequencyBiosLimit = 0.0/0.0,
.frequencyMax = 0,
.frequencyBase = 0,
.frequencyBiosLimit = 0,
.name = ffStrbufCreate(),
.vendor = ffStrbufCreate(),
};