diff --git a/src/support/ticks.c b/src/support/ticks.c index a8d26c30..c77878fe 100644 --- a/src/support/ticks.c +++ b/src/support/ticks.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include #include "vfn/support/align.h" @@ -29,6 +32,53 @@ uint64_t __vfn_ticks_freq; +static uint64_t read_cpu_freq_from_sys(void) +{ + uint64_t hz = 0; + char buf[256]; + double mhz; + FILE *f; + int cpu; + + cpu = sched_getcpu(); + if (cpu < 0) + cpu = 0; + + sprintf(buf, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu); + f = fopen(buf, "r"); + if (f) { + if (fgets(buf, sizeof(buf), f)) + /* Convert KHz -> Hz */ + hz = strtoull(buf, NULL, 10) * 1000; + fclose(f); + if (hz) + return ROUND(hz, TICKS_PER_10MHZ); + } + + /* Second chance from procfs */ + f = fopen("/proc/cpuinfo", "r"); + if (f) { + int current_cpu = 0; + int proc_cpu; + + while (fgets(buf, sizeof(buf), f)) { + if (sscanf(buf, "processor : %d", &proc_cpu) == 1) + current_cpu = proc_cpu; + else if (current_cpu == cpu) { + if (sscanf(buf, "cpu MHz : %lf", &mhz) == 1) { + hz = (uint64_t)(mhz * 1000000); + break; + } + } + } + fclose(f); + if (hz) + return ROUND(hz, TICKS_PER_10MHZ); + } + + return 0; +} + static uint64_t measure_ticks_freq(void) { struct timemono t_start, t_end; @@ -78,6 +128,9 @@ static void __attribute__((constructor)) init_ticks_freq(void) uint64_t freq; freq = get_ticks_freq_arch(); + if (!freq) + freq = read_cpu_freq_from_sys(); + if (!freq) freq = measure_ticks_freq();