diff --git a/netbsd/NetBSDProcessList.c b/netbsd/NetBSDProcessList.c index caa8bb0c..3e85f85d 100644 --- a/netbsd/NetBSDProcessList.c +++ b/netbsd/NetBSDProcessList.c @@ -11,6 +11,7 @@ in the source distribution for its full text. #include "netbsd/NetBSDProcessList.h" #include +#include #include #include #include @@ -38,6 +39,22 @@ static long fscale; static int pageSize; static int pageSizeKB; +static char const *freqSysctls[] = { +#if defined(__powerpc__) + "machdep.intrepid.frequency.current", +#endif +#if defined(__mips__) + "machdep.loongson.frequency.current", +#endif +#if defined(__i386__) || defined(__x86_64__) + "machdep.est.frequency.current", + "machdep.powernow.frequency.current", +#endif + "machdep.cpu.frequency.current", + "machdep.frequency.current", + NULL +}; + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { const int mib[] = { CTL_HW, HW_NCPU }; const int fmib[] = { CTL_KERN, KERN_FSCALE }; @@ -361,12 +378,58 @@ static void NetBSDProcessList_scanCPUTime(NetBSDProcessList* this) { kernelCPUTimesToHtop(avg, this->cpus); } +static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) { + unsigned int cpus = this->super.cpuCount; + bool match = false; + char name[64]; + int freq = 0; + size_t freqSize = sizeof(freq); + + for (unsigned int i = 0; i <= cpus; i++) { + this->cpus[i].frequency = NAN; + } + + /* newer hardware supports per-core frequency, for e.g. ARM big.LITTLE */ + for (unsigned int i = 0; i <= cpus; i++) { + snprintf(name, sizeof(name), "machdep.cpufreq.cpu%u.current", i); + if (sysctlbyname(name, &freq, &freqSize, NULL, 0) != -1) { + this->cpus[i].frequency = freq; + match = true; + } + } + + if (match) { + return; + } + + /* + * Iterate through legacy sysctl nodes for single-core frequency until + * we find a match... + */ + for (const char** s = freqSysctls; *s != NULL; ++s) { + if (sysctlbyname(*s, &freq, &freqSize, NULL, 0) != -1) { + match = true; + break; + } + } + + if (match) { + for (unsigned int i = 0; i <= cpus; i++) { + this->cpus[i].frequency = freq; + } + } +} + void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { NetBSDProcessList* npl = (NetBSDProcessList*) super; NetBSDProcessList_scanMemoryInfo(super); NetBSDProcessList_scanCPUTime(npl); + if (super->settings->showCPUFrequency) { + NetBSDProcessList_scanCPUFrequency(npl); + } + // in pause mode only gather global data for meters (CPU/memory/...) if (pauseProcessUpdate) { return; diff --git a/netbsd/NetBSDProcessList.h b/netbsd/NetBSDProcessList.h index 495fd88c..c5e60444 100644 --- a/netbsd/NetBSDProcessList.h +++ b/netbsd/NetBSDProcessList.h @@ -37,6 +37,8 @@ typedef struct CPUData_ { unsigned long long int spinPeriod; unsigned long long int intrPeriod; unsigned long long int idlePeriod; + + double frequency; } CPUData; typedef struct NetBSDProcessList_ { diff --git a/netbsd/Platform.c b/netbsd/Platform.c index c653d1bf..25db2d84 100644 --- a/netbsd/Platform.c +++ b/netbsd/Platform.c @@ -226,6 +226,7 @@ double Platform_setCPUValues(Meter* this, int cpu) { totalPercent = CLAMP(totalPercent, 0.0, 100.0); + v[CPU_METER_FREQUENCY] = cpuData->frequency; v[CPU_METER_TEMPERATURE] = NAN; return totalPercent;