From fd2a0cf4219ac6b000e3ef46e1958edd2ff41a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 22 Dec 2020 20:02:01 +0100 Subject: [PATCH] FreeBSD: add support for CPU frequency and temperature --- CPUMeter.c | 4 +-- DisplayOptionsPanel.c | 12 +++++-- Settings.c | 6 ++-- Settings.h | 2 +- configure.ac | 3 ++ freebsd/FreeBSDProcessList.c | 66 ++++++++++++++++++++++++++++++++++-- freebsd/FreeBSDProcessList.h | 3 ++ freebsd/Platform.c | 4 +-- 8 files changed, 88 insertions(+), 12 deletions(-) diff --git a/CPUMeter.c b/CPUMeter.c index a39a3cb9..707eec16 100644 --- a/CPUMeter.c +++ b/CPUMeter.c @@ -79,7 +79,7 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, size_t size) { } } - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP if (this->pl->settings->showCPUTemperature) { double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; if (isnan(cpuTemperature)) @@ -150,7 +150,7 @@ static void CPUMeter_display(const Object* cast, RichString* out) { } } - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP if (this->pl->settings->showCPUTemperature) { char cpuTemperatureBuffer[10]; double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c index 7e02b231..8f938fd6 100644 --- a/DisplayOptionsPanel.c +++ b/DisplayOptionsPanel.c @@ -116,8 +116,16 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* Panel_add(super, (Object*) CheckItem_newByRef("Add guest time in CPU meter percentage", &(settings->accountGuestInCPUMeter))); Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU percentage numerically", &(settings->showCPUUsage))); Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU frequency", &(settings->showCPUFrequency))); - #ifdef HAVE_SENSORS_SENSORS_H - Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU temperature (requires libsensors)", &(settings->showCPUTemperature))); + #ifdef BUILD_WITH_CPU_TEMP + Panel_add(super, (Object*) CheckItem_newByRef( + #ifdef HTOP_LINUX + "Also show CPU temperature (requires libsensors)", + #elif defined(HTOP_FREEBSD) + "Also show CPU temperature", + #else + #error Unknown temperature implementation! + #endif + &(settings->showCPUTemperature))); Panel_add(super, (Object*) CheckItem_newByRef("- Show temperature in degree Fahrenheit instead of Celsius", &(settings->degreeFahrenheit))); #endif Panel_add(super, (Object*) CheckItem_newByRef("Enable the mouse", &(settings->enableMouse))); diff --git a/Settings.c b/Settings.c index f12a51f4..421ec552 100644 --- a/Settings.c +++ b/Settings.c @@ -205,7 +205,7 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo this->showCPUUsage = atoi(option[1]); } else if (String_eq(option[0], "show_cpu_frequency")) { this->showCPUFrequency = atoi(option[1]); - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP } else if (String_eq(option[0], "show_cpu_temperature")) { this->showCPUTemperature = atoi(option[1]); } else if (String_eq(option[0], "degree_fahrenheit")) { @@ -319,7 +319,7 @@ bool Settings_write(Settings* this) { fprintf(fd, "cpu_count_from_one=%d\n", (int) this->countCPUsFromOne); fprintf(fd, "show_cpu_usage=%d\n", (int) this->showCPUUsage); fprintf(fd, "show_cpu_frequency=%d\n", (int) this->showCPUFrequency); - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP fprintf(fd, "show_cpu_temperature=%d\n", (int) this->showCPUTemperature); fprintf(fd, "degree_fahrenheit=%d\n", (int) this->degreeFahrenheit); #endif @@ -358,7 +358,7 @@ Settings* Settings_new(int initialCpuCount) { this->countCPUsFromOne = false; this->showCPUUsage = true; this->showCPUFrequency = false; - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP this->showCPUTemperature = false; this->degreeFahrenheit = false; #endif diff --git a/Settings.h b/Settings.h index fdaf3e37..00bcfd50 100644 --- a/Settings.h +++ b/Settings.h @@ -41,7 +41,7 @@ typedef struct Settings_ { bool detailedCPUTime; bool showCPUUsage; bool showCPUFrequency; - #ifdef HAVE_SENSORS_SENSORS_H + #ifdef BUILD_WITH_CPU_TEMP bool showCPUTemperature; bool degreeFahrenheit; #endif diff --git a/configure.ac b/configure.ac index 7bac0426..01a9b266 100644 --- a/configure.ac +++ b/configure.ac @@ -505,6 +505,9 @@ case "$enable_sensors" in AC_MSG_ERROR([bad value '$enable_sensors' for --enable-sensors]) ;; esac +if test "$enable_sensors" = yes || test "$my_htop_platform" = freebsd; then + AC_DEFINE([BUILD_WITH_CPU_TEMP], [1], [Define if CPU temperature option should be enabled.]) +fi # ---------------------------------------------------------------------- diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 91e1d4ca..cee8ec52 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -12,6 +12,7 @@ in the source distribution for its full text. #include #include #include +#include #include #include #include @@ -171,7 +172,7 @@ void ProcessList_delete(ProcessList* this) { free(this); } -static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) { +static inline void FreeBSDProcessList_scanCPU(ProcessList* pl) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; int cpus = pl->cpuCount; // actual CPU count @@ -250,6 +251,67 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) { cpuData->systemAllPercent = cp_time_p[CP_SYS] + cp_time_p[CP_INTR]; // this one is not really used //cpuData->idlePercent = cp_time_p[CP_IDLE]; + + cpuData->temperature = NAN; + cpuData->frequency = NAN; + + const int coreId = (cpus == 1) ? 0 : (i - 1); + if (coreId < 0) + continue; + + // TODO: test with hyperthreading and multi-cpu systems + if (pl->settings->showCPUTemperature) { + int temperature; + size_t len = sizeof(temperature); + char mibBuffer[32]; + xSnprintf(mibBuffer, sizeof(mibBuffer), "dev.cpu.%d.temperature", coreId); + int r = sysctlbyname(mibBuffer, &temperature, &len, NULL, 0); + if (r == 0) + cpuData->temperature = (double)(temperature - 2732) / 10.0; // convert from deci-Kelvin to Celsius + } + + // TODO: test with hyperthreading and multi-cpu systems + if (pl->settings->showCPUFrequency) { + int frequency; + size_t len = sizeof(frequency); + char mibBuffer[32]; + xSnprintf(mibBuffer, sizeof(mibBuffer), "dev.cpu.%d.freq", coreId); + int r = sysctlbyname(mibBuffer, &frequency, &len, NULL, 0); + if (r == 0) + cpuData->frequency = frequency; // keep in MHz + } + } + + // calculate max temperature and avg frequency for average meter and + // propagate frequency to all cores if only supplied for CPU 0 + if (cpus > 1) { + if (pl->settings->showCPUTemperature) { + double maxTemp = NAN; + for (int i = 1; i < maxcpu; i++) { + const double coreTemp = fpl->cpus[i].temperature; + if (isnan(coreTemp)) + continue; + + maxTemp = MAXIMUM(maxTemp, coreTemp); + } + + fpl->cpus[0].temperature = maxTemp; + } + + if (pl->settings->showCPUFrequency) { + const double coreZeroFreq = fpl->cpus[1].frequency; + double freqSum = coreZeroFreq; + if (!isnan(coreZeroFreq)) { + for (int i = 2; i < maxcpu; i++) { + if (isnan(fpl->cpus[i].frequency)) + fpl->cpus[i].frequency = coreZeroFreq; + + freqSum += fpl->cpus[i].frequency; + } + + fpl->cpus[0].frequency = freqSum / (maxcpu - 1); + } + } } } @@ -443,7 +505,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { openzfs_sysctl_updateArcStats(&fpl->zfs); FreeBSDProcessList_scanMemoryInfo(super); - FreeBSDProcessList_scanCPUTime(super); + FreeBSDProcessList_scanCPU(super); // in pause mode only gather global data for meters (CPU/memory/...) if (pauseProcessUpdate) { diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h index 44d26912..398bb827 100644 --- a/freebsd/FreeBSDProcessList.h +++ b/freebsd/FreeBSDProcessList.h @@ -23,6 +23,9 @@ typedef struct CPUData_ { double systemPercent; double irqPercent; double systemAllPercent; + + double frequency; + double temperature; } CPUData; typedef struct FreeBSDProcessList_ { diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 9f8c051f..1f6189ef 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -209,8 +209,8 @@ double Platform_setCPUValues(Meter* this, int cpu) { percent = CLAMP(percent, 0.0, 100.0); - v[CPU_METER_FREQUENCY] = NAN; - v[CPU_METER_TEMPERATURE] = NAN; + v[CPU_METER_FREQUENCY] = cpuData->frequency; + v[CPU_METER_TEMPERATURE] = cpuData->temperature; return percent; }