summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2021-01-13 15:44:05 +0100
committercgzones <cgzones@googlemail.com>2021-01-15 20:55:53 +0100
commit1f20c0fb3debf2fa4d4be934d0b4552fdf814caa (patch)
tree609d91468ed9a53fdc3df4a2f8afe6e08ea640d3
parentb5a5e83470ef2db6cace89a5f513b038a96bbff9 (diff)
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
-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)