summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2020-09-22 14:50:50 +0200
committercgzones <cgzones@googlemail.com>2020-09-24 20:11:28 +0200
commitedf1b10d2c3fa94c23a23cfc947490cf1ebf66d1 (patch)
tree09571af36c5d969795a188604db164bfce1fd3cd
parentf4e1f4619f3761382d5e97ddf92237085a7bd443 (diff)
Read CPU frequency from sysfs by default
Use the more portable sysfs node /sys/devices/system/cpu/cpuX/cpufreq/scaling_cur_freq to get the CPU frequency. In case of an error fall back to /proc/cpuinfo . Also use a fixed width of 4 for the frequency to avoid position jumps in case the frequency moves in the range 900-1100 MHz.
-rw-r--r--CPUMeter.c2
-rw-r--r--linux/LinuxProcessList.c128
2 files changed, 78 insertions, 52 deletions
diff --git a/CPUMeter.c b/CPUMeter.c
index badca940..482565ee 100644
--- a/CPUMeter.c
+++ b/CPUMeter.c
@@ -45,7 +45,7 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, int size) {
if (isnan(cpuFrequency)) {
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
} else {
- xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%.0fMHz", cpuFrequency);
+ xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency);
}
if (this->pl->settings->showCPUUsage) {
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 318a94b9..807cc8a6 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -1145,79 +1145,105 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
return period;
}
-static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
- ProcessList* pl = (ProcessList*) this;
- Settings* settings = pl->settings;
-
+static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
int cpus = this->super.cpuCount;
- assert(cpus > 0);
+ int numCPUsWithFrequency = 0;
+ unsigned long totalFrequency = 0;
+
+ for (int i = 0; i < cpus; ++i) {
+ char pathBuffer[64];
+ xSnprintf(pathBuffer, sizeof(pathBuffer), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
+
+ FILE* file = fopen(pathBuffer, "r");
+ if (!file)
+ return -errno;
+
+ unsigned long frequency;
+ if (fscanf(file, "%lu", &frequency) == 1) {
+ /* convert kHz to MHz */
+ frequency = frequency / 1000;
+ this->cpus[i + 1].frequency = frequency;
+ numCPUsWithFrequency++;
+ totalFrequency += frequency;
+ }
- for (int i = 0; i <= cpus; i++) {
- CPUData* cpuData = &(this->cpus[i]);
- cpuData->frequency = NAN;
+ fclose(file);
}
+ if (numCPUsWithFrequency > 0)
+ this->cpus[0].frequency = (double)totalFrequency / numCPUsWithFrequency;
+
+ return 0;
+}
+
+static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) {
+ FILE* file = fopen(PROCCPUINFOFILE, "r");
+ if (file == NULL)
+ return;
+
+ int cpus = this->super.cpuCount;
int numCPUsWithFrequency = 0;
double totalFrequency = 0;
+ int cpuid = -1;
- if (settings->showCPUFrequency) {
- FILE* file = fopen(PROCCPUINFOFILE, "r");
- if (file == NULL) {
- CRT_fatalError("Cannot open " PROCCPUINFOFILE);
- }
-
- int cpuid = -1;
+ while (!feof(file)) {
double frequency;
- while (!feof(file)) {
- char buffer[PROC_LINE_LENGTH];
- char *ok = fgets(buffer, PROC_LINE_LENGTH, file);
- if (!ok) break;
-
- if (
- (sscanf(buffer, "processor : %d", &cpuid) == 1) ||
- (sscanf(buffer, "processor: %d", &cpuid) == 1)
- ) {
- if (cpuid < 0 || cpuid > (cpus - 1)) {
- char tmpbuffer[64];
- xSnprintf(tmpbuffer, sizeof(tmpbuffer), PROCCPUINFOFILE " contains out-of-range CPU number %d", cpuid);
- CRT_fatalError(tmpbuffer);
- }
- } else if (
- (sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
- (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
- ) {
- if (cpuid < 0 || cpuid > (cpus - 1)) {
- CRT_fatalError(PROCCPUINFOFILE " is malformed: cpu MHz line without corresponding processor line");
- }
+ char buffer[PROC_LINE_LENGTH];
- int cpu = cpuid + 1;
- CPUData* cpuData = &(this->cpus[cpu]);
- cpuData->frequency = frequency;
- numCPUsWithFrequency++;
- totalFrequency += frequency;
- } else if (buffer[0] == '\n') {
- cpuid = -1;
- }
- }
- fclose(file);
+ if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL)
+ break;
- if (numCPUsWithFrequency > 0) {
- this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency;
+ if (
+ (sscanf(buffer, "processor : %d", &cpuid) == 1) ||
+ (sscanf(buffer, "processor: %d", &cpuid) == 1)
+ ) {
+ continue;
+ } else if (
+ (sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
+ (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
+ ) {
+ if (cpuid < 0 || cpuid > (cpus - 1))
+ continue;
+
+ CPUData* cpuData = &(this->cpus[cpuid + 1]);
+ /* do not override sysfs data */
+ if (isnan(cpuData->frequency))
+ cpuData->frequency = frequency;
+ numCPUsWithFrequency++;
+ totalFrequency += frequency;
+ } else if (buffer[0] == '\n') {
+ cpuid = -1;
}
}
+ fclose(file);
- double period = (double)this->cpus[0].totalPeriod / cpus;
- return period;
+ if (numCPUsWithFrequency > 0)
+ this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency;
+}
+
+static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
+ int cpus = this->super.cpuCount;
+ assert(cpus > 0);
+
+ for (int i = 0; i <= cpus; i++)
+ this->cpus[i].frequency = NAN;
+
+ if (scanCPUFreqencyFromSysCPUFreq(this) == 0)
+ return;
+
+ scanCPUFreqencyFromCPUinfo(this);
}
void ProcessList_goThroughEntries(ProcessList* super) {
LinuxProcessList* this = (LinuxProcessList*) super;
+ const Settings* settings = super->settings;
LinuxProcessList_scanMemoryInfo(super);
LinuxProcessList_scanZfsArcstats(this);
double period = LinuxProcessList_scanCPUTime(this);
- LinuxProcessList_scanCPUFrequency(this);
+ if (settings->showCPUFrequency)
+ LinuxProcessList_scanCPUFrequency(this);
struct timeval tv;
gettimeofday(&tv, NULL);

© 2014-2024 Faster IT GmbH | imprint | privacy policy