-rw-r--r-- 5140 lib25519-20220726/cpucycles/wrapper.c raw
#include <stdio.h> #include <stdlib.h> #include "cpucycles.h" static double osfreq(void) { FILE *f; char *x; double result; int s; f = fopen("/etc/cpucyclespersecond", "r"); if (f) { s = fscanf(f,"%lf",&result); fclose(f); if (s > 0) return result; } f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "r"); if (f) { s = fscanf(f,"%lf",&result); fclose(f); if (s > 0) return 1000.0 * result; } f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); if (f) { s = fscanf(f,"%lf",&result); fclose(f); if (s > 0) return 1000.0 * result; } f = fopen("/sys/devices/system/cpu/cpu0/clock_tick", "r"); if (f) { s = fscanf(f,"%lf",&result); fclose(f); if (s > 0) return result; } f = fopen("/proc/cpuinfo","r"); if (f) { for (;;) { s = fscanf(f,"cpu MHz : %lf",&result); if (s > 0) break; if (s == 0) s = fscanf(f,"%*[^\n]\n"); if (s < 0) { result = 0; break; } } fclose(f); if (result) return 1000000.0 * result; } f = fopen("/proc/cpuinfo","r"); if (f) { for (;;) { s = fscanf(f,"clock : %lf",&result); if (s > 0) break; if (s == 0) s = fscanf(f,"%*[^\n]\n"); if (s < 0) { result = 0; break; } } fclose(f); if (result) return 1000000.0 * result; } f = popen("sysctl hw.cpufrequency 2>/dev/null","r"); if (f) { s = fscanf(f,"hw.cpufrequency: %lf",&result); pclose(f); if (s > 0) if (result > 0) return result; } f = popen("/usr/sbin/lsattr -E -l proc0 -a frequency 2>/dev/null","r"); if (f) { s = fscanf(f,"frequency %lf",&result); pclose(f); if (s > 0) return result; } f = popen("/usr/sbin/psrinfo -v 2>/dev/null","r"); if (f) { for (;;) { s = fscanf(f," The %*s processor operates at %lf MHz",&result); if (s > 0) break; if (s == 0) s = fscanf(f,"%*[^\n]\n"); if (s < 0) { result = 0; break; } } pclose(f); if (result) return 1000000.0 * result; } x = getenv("cpucyclespersecond"); if (x) { s = sscanf(x,"%lf",&result); if (s > 0) return result; } return 0; } static long long persecond = 0; const char *implementation = "none"; long long (*cpucycles)(void) = cpucycles_init; const char *cpucycles_implementation(void) { cpucycles(); return implementation; } long long cpucycles_persecond(void) { cpucycles(); return persecond; } static double cpucycles_scaled_scaling = 0; static long long (*cpucycles_scaled_from)(void) = 0; static long long cpucycles_scaled(void) { return cpucycles_scaled_from()*cpucycles_scaled_scaling; } #include "options.inc" #define CALLS 1000 long long cpucycles_init(void) { long long precision[NUMOPTIONS]; long long scaling[NUMOPTIONS]; long long bestprecision; long long bestopt; persecond = osfreq(); for (long long opt = 0;opt < NUMOPTIONS;++opt) { long long freq = options[opt].ticks_setup(); // freq > 0: freq ticks per second // freq == 0: do not use // freq == -1: cycle counter (e.g., rdpmc) // freq == -2: probably cycle counter (e.g., rdtsc) // freq == -3: tick counter every N cycles for some unknown N precision[opt] = 0; if (freq > 0) { // means: freq ticks per second scaling[opt] = persecond*1.0/freq; } else if (freq == -1) { // means: cycle counter; e.g., rdpmc scaling[opt] = 1.0; } else if (freq == -2) { // means: probably cycle counter; e.g., rdtsc scaling[opt] = 1.0; } else { continue; } for (long long tries = 0;tries < 10;++tries) { long long t[CALLS+1]; long long ok = 1; if (scaling[opt] == 1.0) { for (long long i = 0;i <= CALLS;++i) t[i] = options[opt].ticks(); } else { double scalingopt = scaling[opt]; for (long long i = 0;i <= CALLS;++i) t[i] = options[opt].ticks()*scalingopt; } for (long long i = 0;i < CALLS;++i) if (t[i] > t[i+1]) ok = 0; if (t[0] == t[CALLS]) ok = 0; if (ok) { long long smallestdiff = 0; for (long long i = 0;i < CALLS;++i) { long long diff = t[i+1]-t[i]; if (diff <= 0) continue; if (smallestdiff == 0 || diff < smallestdiff) smallestdiff = diff; } precision[opt] = smallestdiff; if (freq != -1) precision[opt] += 100; break; } // otherwise keep trying // since !ok can be caused by overflow // or by core swap } } bestopt = DEFAULTOPTION; bestprecision = 0; for (long long opt = 0;opt < NUMOPTIONS;++opt) if (precision[opt] > 0) if (!bestprecision || precision[opt] < bestprecision) { bestopt = opt; bestprecision = precision[opt]; } implementation = options[bestopt].implementation; if (scaling[bestopt] == 1.0) { cpucycles = options[bestopt].ticks; } else { cpucycles_scaled_scaling = scaling[bestopt]; cpucycles_scaled_from = options[bestopt].ticks; cpucycles = cpucycles_scaled; } return cpucycles(); }