Dynamically load libsensors at runtime

This commit is contained in:
Christian Göttsche
2020-12-01 13:59:19 +01:00
committed by BenBE
parent f7a8952933
commit b76eaf187a
11 changed files with 147 additions and 59 deletions

105
linux/LibSensors.c Normal file
View File

@ -0,0 +1,105 @@
#include "LibSensors.h"
#ifdef HAVE_SENSORS_SENSORS_H
#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#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 void* dlopenHandle = NULL;
int LibSensors_init(FILE* input) {
if (!dlopenHandle) {
dlopenHandle = dlopen("libsensors.so", RTLD_LAZY);
if (!dlopenHandle)
goto dlfailure;
/* 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);
#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;
}
}
int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount) {
if (!dlopenHandle)
return -ENOTSUP;
int tempCount = 0;
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;
if (feature->number > cpuCount)
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[feature->number].temperature = temp;
tempCount++;
}
}
}
return tempCount;
}
#endif /* HAVE_SENSORS_SENSORS_H */

16
linux/LibSensors.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef HEADER_LibSensors
#define HEADER_LibSensors
#include "config.h" // IWYU pragma: keep
#include <stdio.h>
#include "LinuxProcessList.h"
int LibSensors_init(FILE* input);
void LibSensors_cleanup(void);
int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount);
#endif /* HEADER_LibSensors */

View File

@ -53,8 +53,8 @@ in the source distribution for its full text.
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_LIBSENSORS
#include <sensors/sensors.h>
#ifdef HAVE_SENSORS_SENSORS_H
#include "LibSensors.h"
#endif
@ -1794,41 +1794,7 @@ static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
scanCPUFreqencyFromCPUinfo(this);
}
#ifdef HAVE_LIBSENSORS
static int getCPUTemperatures(CPUData* cpus, int cpuCount) {
int tempCount = 0;
int n = 0;
for (const sensors_chip_name *chip = sensors_get_detected_chips(NULL, &n); chip; chip = sensors_get_detected_chips(NULL, &n)) {
char buffer[32];
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 = sensors_get_features(chip, &m); feature; feature = sensors_get_features(chip, &m)) {
if (feature->type != SENSORS_FEATURE_TEMP)
continue;
if (feature->number > cpuCount)
continue;
const sensors_subfeature *sub_feature = sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
if (sub_feature) {
double temp;
int r = sensors_get_value(chip, sub_feature->number, &temp);
if (r != 0)
continue;
cpus[feature->number].temperature = temp;
tempCount++;
}
}
}
return tempCount;
}
#ifdef HAVE_SENSORS_SENSORS_H
static void LinuxProcessList_scanCPUTemperature(LinuxProcessList* this) {
const int cpuCount = this->super.cpuCount;
@ -1836,10 +1802,10 @@ static void LinuxProcessList_scanCPUTemperature(LinuxProcessList* this) {
this->cpus[i].temperature = NAN;
}
int r = getCPUTemperatures(this->cpus, cpuCount);
int r = LibSensors_getCPUTemperatures(this->cpus, cpuCount);
/* No temperature - nothing to do */
if (r == 0)
if (r <= 0)
return;
/* Only package temperature - copy to all cpus */
@ -1878,7 +1844,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
LinuxProcessList_scanCPUFrequency(this);
}
#ifdef HAVE_LIBSENSORS
#ifdef HAVE_SENSORS_SENSORS_H
if (settings->showCPUTemperature)
LinuxProcessList_scanCPUTemperature(this);
#endif

View File

@ -48,7 +48,7 @@ typedef struct CPUData_ {
double frequency;
#ifdef HAVE_LIBSENSORS
#ifdef HAVE_SENSORS_SENSORS_H
double temperature;
#endif
} CPUData;

View File

@ -61,10 +61,11 @@ in the source distribution for its full text.
#include "zfs/ZfsArcStats.h"
#include "zfs/ZfsCompressedArcMeter.h"
#ifdef HAVE_LIBSENSORS
#include <sensors/sensors.h>
#ifdef HAVE_SENSORS_SENSORS_H
#include "LibSensors.h"
#endif
ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, (int)M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
int Platform_numberOfFields = LAST_PROCESSFIELD;
@ -119,14 +120,14 @@ void Platform_init(void) {
exit(1);
}
#ifdef HAVE_LIBSENSORS
sensors_init(NULL);
#ifdef HAVE_SENSORS_SENSORS_H
LibSensors_init(NULL);
#endif
}
void Platform_done(void) {
#ifdef HAVE_LIBSENSORS
sensors_cleanup();
#ifdef HAVE_SENSORS_SENSORS_H
LibSensors_cleanup();
#endif
}
@ -271,7 +272,7 @@ double Platform_setCPUValues(Meter* this, int cpu) {
v[CPU_METER_FREQUENCY] = cpuData->frequency;
#ifdef HAVE_LIBSENSORS
#ifdef HAVE_SENSORS_SENSORS_H
v[CPU_METER_TEMPERATURE] = cpuData->temperature;
#else
v[CPU_METER_TEMPERATURE] = NAN;