summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--linux/LinuxProcessList.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 49b2d0e1..96e8de6e 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -20,6 +20,7 @@ in the source distribution for its full text.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -1727,10 +1728,28 @@ static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
int numCPUsWithFrequency = 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) {
char pathBuffer[64];
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");
if (!file)
return -errno;
@@ -1745,6 +1764,17 @@ static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
}
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)