mirror of https://github.com/xzeldon/htop.git
Linux: fall back to cpuinfo on slow scaling_cur_freq read
On some AMD and Intel CPUs read()ing scaling_cur_freq is quite slow (> 1ms). This delay accumulates for every core. If the read on CPU 0 takes longer than 500us bail out and fall back to reading the frequencies from /proc/cpuinfo. Once the condition has been met, bail out early for the next couple of scans. Closes: #471
This commit is contained in:
parent
b5a5e83470
commit
1f20c0fb3d
|
@ -20,6 +20,7 @@ in the source distribution for its full text.
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
@ -1727,10 +1728,28 @@ static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
|
||||||
int numCPUsWithFrequency = 0;
|
int numCPUsWithFrequency = 0;
|
||||||
unsigned long totalFrequency = 0;
|
unsigned long totalFrequency = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On some AMD and Intel CPUs read()ing scaling_cur_freq is quite slow (> 1ms). This delay
|
||||||
|
* accumulates for every core. For details see issue#471.
|
||||||
|
* If the read on CPU 0 takes longer than 500us bail out and fall back to reading the
|
||||||
|
* frequencies from /proc/cpuinfo.
|
||||||
|
* Once the condition has been met, bail out early for the next couple of scans.
|
||||||
|
*/
|
||||||
|
static int timeout = 0;
|
||||||
|
|
||||||
|
if (timeout > 0) {
|
||||||
|
timeout--;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < cpus; ++i) {
|
for (int i = 0; i < cpus; ++i) {
|
||||||
char pathBuffer[64];
|
char pathBuffer[64];
|
||||||
xSnprintf(pathBuffer, sizeof(pathBuffer), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
|
xSnprintf(pathBuffer, sizeof(pathBuffer), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
|
||||||
|
|
||||||
|
struct timespec start;
|
||||||
|
if (i == 0)
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
|
|
||||||
FILE* file = fopen(pathBuffer, "r");
|
FILE* file = fopen(pathBuffer, "r");
|
||||||
if (!file)
|
if (!file)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
@ -1745,6 +1764,17 @@ static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
struct timespec end;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||||
|
const time_t timeTakenUs = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
||||||
|
if (timeTakenUs > 500) {
|
||||||
|
timeout = 30;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numCPUsWithFrequency > 0)
|
if (numCPUsWithFrequency > 0)
|
||||||
|
|
Loading…
Reference in New Issue