From 69f439eff387a6ecb52734e400b297a3c85f2285 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Tue, 21 Sep 2021 08:35:19 +0200 Subject: New upstream version 3.1.0 --- linux/LibSensors.c | 218 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 159 insertions(+), 59 deletions(-) (limited to 'linux/LibSensors.c') diff --git a/linux/LibSensors.c b/linux/LibSensors.c index 158829a..9a27fe5 100644 --- a/linux/LibSensors.c +++ b/linux/LibSensors.c @@ -1,27 +1,53 @@ -#include "LibSensors.h" +#include "linux/LibSensors.h" + +#include "config.h" #ifdef HAVE_SENSORS_SENSORS_H +#include #include #include +#include #include +#include +#include +#include #include +#include "Macros.h" #include "XUtils.h" +#include "linux/LinuxProcessList.h" + + +#ifdef BUILD_STATIC +#define sym_sensors_init sensors_init +#define sym_sensors_cleanup sensors_cleanup +#define sym_sensors_get_detected_chips sensors_get_detected_chips +#define sym_sensors_get_features sensors_get_features +#define sym_sensors_get_subfeature sensors_get_subfeature +#define sym_sensors_get_value sensors_get_value + +#else static int (*sym_sensors_init)(FILE*); static void (*sym_sensors_cleanup)(void); static const sensors_chip_name* (*sym_sensors_get_detected_chips)(const sensors_chip_name*, int*); -static int (*sym_sensors_snprintf_chip_name)(char*, size_t, const sensors_chip_name*); static const sensors_feature* (*sym_sensors_get_features)(const sensors_chip_name*, int*); static const sensors_subfeature* (*sym_sensors_get_subfeature)(const sensors_chip_name*, const sensors_feature*, sensors_subfeature_type); static int (*sym_sensors_get_value)(const sensors_chip_name*, int, double*); -static char* (*sym_sensors_get_label)(const sensors_chip_name*, const sensors_feature*); static void* dlopenHandle = NULL; -int LibSensors_init(FILE* input) { +#endif /* BUILD_STATIC */ + +int LibSensors_init(void) { +#ifdef BUILD_STATIC + + return sym_sensors_init(NULL); + +#else + if (!dlopenHandle) { /* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without matching symlinks (unless people install the -dev packages) */ @@ -45,16 +71,15 @@ int LibSensors_init(FILE* input) { resolve(sensors_init); resolve(sensors_cleanup); resolve(sensors_get_detected_chips); - resolve(sensors_snprintf_chip_name); resolve(sensors_get_features); resolve(sensors_get_subfeature); resolve(sensors_get_value); - resolve(sensors_get_label); #undef resolve } - return sym_sensors_init(input); + return sym_sensors_init(NULL); + dlfailure: if (dlopenHandle) { @@ -62,108 +87,183 @@ dlfailure: dlopenHandle = NULL; } return -1; + +#endif /* BUILD_STATIC */ } void LibSensors_cleanup(void) { +#ifdef BUILD_STATIC + + sym_sensors_cleanup(); + +#else + if (dlopenHandle) { sym_sensors_cleanup(); dlclose(dlopenHandle); dlopenHandle = NULL; } + +#endif /* BUILD_STATIC */ } -void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) { - for (unsigned int i = 0; i <= cpuCount; i++) - cpus[i].temperature = NAN; +int LibSensors_reload(void) { +#ifndef BUILD_STATIC + if (!dlopenHandle) { + errno = ENOTSUP; + return -1; + } +#endif /* !BUILD_STATIC */ + + sym_sensors_cleanup(); + return sym_sensors_init(NULL); +} + +static int tempDriverPriority(const sensors_chip_name* chip) { + static const struct TempDriverDefs { + const char* prefix; + int priority; + } tempDrivers[] = { + { "coretemp", 0 }, + { "via_cputemp", 0 }, + { "cpu_thermal", 0 }, + { "k10temp", 0 }, + { "zenpower", 0 }, + /* Low priority drivers */ + { "acpitz", 1 }, + }; + + for (size_t i = 0; i < ARRAYSIZE(tempDrivers); i++) + if (String_eq(chip->prefix, tempDrivers[i].prefix)) + return tempDrivers[i].priority; + + return -1; +} +void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int existingCPUs, unsigned int activeCPUs) { + assert(existingCPUs > 0 && existingCPUs < 16384); + double data[existingCPUs + 1]; + for (size_t i = 0; i < existingCPUs + 1; i++) + data[i] = NAN; + +#ifndef BUILD_STATIC if (!dlopenHandle) - return; + goto out; +#endif /* !BUILD_STATIC */ unsigned int coreTempCount = 0; + int topPriority = 99; int n = 0; - for (const sensors_chip_name *chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) { - char buffer[32]; - sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip); - if (!String_startsWith(buffer, "coretemp") && - !String_startsWith(buffer, "cpu_thermal") && - !String_startsWith(buffer, "k10temp") && - !String_startsWith(buffer, "zenpower")) + for (const sensors_chip_name* chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) { + const int priority = tempDriverPriority(chip); + if (priority < 0) + continue; + + if (priority > topPriority) continue; + if (priority < topPriority) { + /* Clear data from lower priority sensor */ + for (size_t i = 0; i < existingCPUs + 1; i++) + data[i] = NAN; + } + + topPriority = priority; + int m = 0; - for (const sensors_feature *feature = sym_sensors_get_features(chip, &m); feature; feature = sym_sensors_get_features(chip, &m)) { + for (const sensors_feature* feature = sym_sensors_get_features(chip, &m); feature; feature = sym_sensors_get_features(chip, &m)) { if (feature->type != SENSORS_FEATURE_TEMP) continue; - char* label = sym_sensors_get_label(chip, feature); - if (!label) + if (!feature->name || !String_startsWith(feature->name, "temp")) continue; - unsigned int tempId; - if (String_startsWith(label, "Package ")) { - tempId = 0; - } else if (String_startsWith(label, "temp")) { - /* Raspberry Pi has only temp1 */ - tempId = 0; - } else if (String_startsWith(label, "Tdie")) { - tempId = 0; - } else if (String_startsWith(label, "Core ")) { - tempId = 1 + atoi(label + strlen("Core ")); - } else { - tempId = UINT_MAX; - } + unsigned long int tempID = strtoul(feature->name + strlen("temp"), NULL, 10); + if (tempID == 0 || tempID == ULONG_MAX) + continue; - free(label); + /* Feature name IDs start at 1, adjust to start at 0 to match data indices */ + tempID--; - if (tempId > cpuCount) + if (tempID > existingCPUs) continue; - const sensors_subfeature *sub_feature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT); - if (sub_feature) { - double temp; - int r = sym_sensors_get_value(chip, sub_feature->number, &temp); - if (r != 0) - continue; + const sensors_subfeature* subFeature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT); + if (!subFeature) + continue; - cpus[tempId].temperature = temp; - if (tempId > 0) + double temp; + int r = sym_sensors_get_value(chip, subFeature->number, &temp); + if (r != 0) + continue; + + /* If already set, e.g. Ryzen reporting platform temperature for each die, use the bigger one */ + if (isnan(data[tempID])) { + data[tempID] = temp; + if (tempID > 0) coreTempCount++; + } else { + data[tempID] = MAXIMUM(data[tempID], temp); } } } - const double packageTemp = cpus[0].temperature; + /* Adjust data for chips not providing a platform temperature */ + if (coreTempCount + 1 == activeCPUs || coreTempCount + 1 == activeCPUs / 2) { + memmove(&data[1], &data[0], existingCPUs * sizeof(*data)); + data[0] = NAN; + coreTempCount++; - /* Only package temperature - copy to all cpus */ - if (coreTempCount == 0 && !isnan(packageTemp)) { - for (unsigned int i = 1; i <= cpuCount; i++) - cpus[i].temperature = packageTemp; + /* Check for further adjustments */ + } - return; + /* Only package temperature - copy to all cores */ + if (coreTempCount == 0 && !isnan(data[0])) { + for (unsigned int i = 1; i <= existingCPUs; i++) + data[i] = data[0]; + + /* No further adjustments */ + goto out; } /* No package temperature - set to max core temperature */ - if (isnan(packageTemp) && coreTempCount != 0) { + if (isnan(data[0]) && coreTempCount != 0) { double maxTemp = NAN; - for (unsigned int i = 1; i <= cpuCount; i++) { - const double coreTemp = cpus[i].temperature; - if (isnan(coreTemp)) + for (unsigned int i = 1; i <= existingCPUs; i++) { + if (isnan(data[i])) continue; - maxTemp = MAXIMUM(maxTemp, coreTemp); + maxTemp = MAXIMUM(maxTemp, data[i]); } - cpus[0].temperature = maxTemp; + data[0] = maxTemp; + + /* Check for further adjustments */ + } + + /* Only temperature for core 0, maybe Ryzen - copy to all other cores */ + if (coreTempCount == 1 && !isnan(data[1])) { + for (unsigned int i = 2; i <= existingCPUs; i++) + data[i] = data[1]; + + /* No further adjustments */ + goto out; } /* Half the temperatures, probably HT/SMT - copy to second half */ - const unsigned int delta = cpuCount / 2; + const unsigned int delta = activeCPUs / 2; if (coreTempCount == delta) { - for (unsigned int i = 1; i <= delta; i++) - cpus[i + delta].temperature = cpus[i].temperature; + memcpy(&data[delta + 1], &data[1], delta * sizeof(*data)); + + /* No further adjustments */ + goto out; } + +out: + for (unsigned int i = 0; i <= existingCPUs; i++) + cpus[i].temperature = data[i]; } #endif /* HAVE_SENSORS_SENSORS_H */ -- cgit v1.2.3