htop/linux/LibSensors.c

163 lines
4.9 KiB
C
Raw Normal View History

2020-12-01 12:59:19 +00:00
#include "LibSensors.h"
#ifdef HAVE_SENSORS_SENSORS_H
#include <dlfcn.h>
#include <errno.h>
#include <math.h>
2020-12-01 12:59:19 +00:00
#include <sensors/sensors.h>
#include "XUtils.h"
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*);
2020-12-01 12:59:19 +00:00
static void* dlopenHandle = NULL;
int LibSensors_init(FILE* input) {
if (!dlopenHandle) {
dlopenHandle = dlopen("libsensors.so.", RTLD_LAZY);
if (!dlopenHandle) {
/* Debian contains no unversioned .so in libsensors5, only in the -dev package, so work around that: */
dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY);
if (!dlopenHandle)
goto dlfailure;
}
2020-12-01 12:59:19 +00:00
/* Clear any errors */
dlerror();
#define resolve(symbolname) do { \
*(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \
if (!sym_##symbolname || dlerror() != NULL) \
goto dlfailure; \
} while(0)
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);
2020-12-01 12:59:19 +00:00
#undef resolve
}
return sym_sensors_init(input);
dlfailure:
if (dlopenHandle) {
dlclose(dlopenHandle);
dlopenHandle = NULL;
}
return -1;
}
void LibSensors_cleanup(void) {
if (dlopenHandle) {
sym_sensors_cleanup();
dlclose(dlopenHandle);
dlopenHandle = NULL;
}
}
void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
for (unsigned int i = 0; i <= cpuCount; i++)
cpus[i].temperature = NAN;
2020-12-01 12:59:19 +00:00
if (!dlopenHandle)
return;
2020-12-01 12:59:19 +00:00
unsigned int coreTempCount = 0;
2020-12-01 12:59:19 +00:00
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"))
continue;
int m = 0;
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)
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, "Core ")) {
tempId = 1 + atoi(label + strlen("Core "));
} else {
tempId = UINT_MAX;
}
free(label);
if (tempId > cpuCount)
2020-12-01 12:59:19 +00:00
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;
cpus[tempId].temperature = temp;
if (tempId > 0)
coreTempCount++;
2020-12-01 12:59:19 +00:00
}
}
}
const double packageTemp = cpus[0].temperature;
/* Only package temperature - copy to all cpus */
if (coreTempCount == 0 && !isnan(packageTemp)) {
for (unsigned int i = 1; i <= cpuCount; i++)
cpus[i].temperature = packageTemp;
return;
}
/* No package temperature - set to max core temperature */
if (isnan(packageTemp) && coreTempCount != 0) {
double maxTemp = NAN;
for (unsigned int i = 1; i <= cpuCount; i++) {
const double coreTemp = cpus[i].temperature;
if (isnan(coreTemp))
continue;
maxTemp = MAXIMUM(maxTemp, coreTemp);
}
cpus[0].temperature = maxTemp;
}
/* Half the temperatures, probably HT/SMT - copy to second half */
const unsigned int delta = cpuCount / 2;
if (coreTempCount == delta) {
for (unsigned int i = 1; i <= delta; i++)
cpus[i + delta].temperature = cpus[i].temperature;
}
2020-12-01 12:59:19 +00:00
}
#endif /* HAVE_SENSORS_SENSORS_H */