Linux: Rework libsensors parsing

Do not read driver depended labels, just count the number of
temperatures given:

  on #CPU:
    platform temp = max cpu temp
    CPU temps = first to last
  on #CPU + 1:
    platform temp = first temp
    CPU temps = second to last
  on #CPU / 2:
    platform temp = max cpu temp
    CPU temps = first to last concat first to last
      (with SMT core x + cpu count is the logical core of the physical
      core x)
  on #CPU / 2 + 1:
    platform temp = first temp
    CPU temps = second to last concat second to last
      (with SMT core x + cpu count is the logical core of the physical
      core x)

Closes: #529
Closes: #538
This commit is contained in:
Christian Göttsche 2021-02-19 22:28:01 +01:00
parent 53bcc5cbff
commit f46fcf094e
1 changed files with 101 additions and 56 deletions

View File

@ -15,22 +15,18 @@
#define sym_sensors_init sensors_init #define sym_sensors_init sensors_init
#define sym_sensors_cleanup sensors_cleanup #define sym_sensors_cleanup sensors_cleanup
#define sym_sensors_get_detected_chips sensors_get_detected_chips #define sym_sensors_get_detected_chips sensors_get_detected_chips
#define sym_sensors_snprintf_chip_name sensors_snprintf_chip_name
#define sym_sensors_get_features sensors_get_features #define sym_sensors_get_features sensors_get_features
#define sym_sensors_get_subfeature sensors_get_subfeature #define sym_sensors_get_subfeature sensors_get_subfeature
#define sym_sensors_get_value sensors_get_value #define sym_sensors_get_value sensors_get_value
#define sym_sensors_get_label sensors_get_label
#else #else
static int (*sym_sensors_init)(FILE*); static int (*sym_sensors_init)(FILE*);
static void (*sym_sensors_cleanup)(void); static void (*sym_sensors_cleanup)(void);
static const sensors_chip_name* (*sym_sensors_get_detected_chips)(const sensors_chip_name*, int*); 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_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 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 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; static void* dlopenHandle = NULL;
@ -66,11 +62,9 @@ int LibSensors_init(FILE* input) {
resolve(sensors_init); resolve(sensors_init);
resolve(sensors_cleanup); resolve(sensors_cleanup);
resolve(sensors_get_detected_chips); resolve(sensors_get_detected_chips);
resolve(sensors_snprintf_chip_name);
resolve(sensors_get_features); resolve(sensors_get_features);
resolve(sensors_get_subfeature); resolve(sensors_get_subfeature);
resolve(sensors_get_value); resolve(sensors_get_value);
resolve(sensors_get_label);
#undef resolve #undef resolve
} }
@ -105,99 +99,150 @@ void LibSensors_cleanup(void) {
#endif /* BUILD_STATIC */ #endif /* BUILD_STATIC */
} }
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 cpuCount) { void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
for (unsigned int i = 0; i <= cpuCount; i++) assert(cpuCount > 0 && cpuCount < 16384);
cpus[i].temperature = NAN; double data[cpuCount + 1];
for (size_t i = 0; i < cpuCount + 1; i++)
data[i] = NAN;
#ifndef BUILD_STATIC #ifndef BUILD_STATIC
if (!dlopenHandle) if (!dlopenHandle)
return; goto out;
#endif /* !BUILD_STATIC */ #endif /* !BUILD_STATIC */
unsigned int coreTempCount = 0; unsigned int coreTempCount = 0;
int topPriority = 99;
int n = 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)) { 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]; const int priority = tempDriverPriority(chip);
sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip); if (priority < 0)
if (!String_startsWith(buffer, "coretemp") &&
!String_startsWith(buffer, "cpu_thermal") &&
!String_startsWith(buffer, "k10temp") &&
!String_startsWith(buffer, "zenpower"))
continue; continue;
if (priority > topPriority)
continue;
if (priority < topPriority) {
/* Clear data from lower priority sensor */
for (size_t i = 0; i < cpuCount + 1; i++)
data[i] = NAN;
}
topPriority = priority;
int m = 0; 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) if (feature->type != SENSORS_FEATURE_TEMP)
continue; continue;
char* label = sym_sensors_get_label(chip, feature); if (!feature->name || !String_startsWith(feature->name, "temp"))
if (!label)
continue; continue;
unsigned int tempId; unsigned long int tempID = strtoul(feature->name + strlen("temp"), NULL, 10);
if (String_startsWith(label, "Package ")) { if (tempID == 0 || tempID == ULONG_MAX)
tempId = 0; continue;
} else if (String_startsWith(label, "temp")) {
/* Raspberry Pi has only temp1 */ /* Feature name IDs start at 1, adjust to start at 0 to match data indicies */
tempId = 0; tempID--;
} else if (String_startsWith(label, "Tdie")) {
tempId = 0; if (tempID > cpuCount)
} else if (String_startsWith(label, "Core ")) { continue;
tempId = 1 + atoi(label + strlen("Core "));
} else { const sensors_subfeature* subFeature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
tempId = UINT_MAX; if (!subFeature)
}
free(label);
if (tempId > cpuCount)
continue; continue;
const sensors_subfeature *sub_feature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
if (sub_feature) {
double temp; double temp;
int r = sym_sensors_get_value(chip, sub_feature->number, &temp); int r = sym_sensors_get_value(chip, subFeature->number, &temp);
if (r != 0) if (r != 0)
continue; continue;
cpus[tempId].temperature = temp; /* If already set, e.g. Ryzen reporting platform temperature for each die, use the bigger one */
if (tempId > 0) if (isnan(data[tempID])) {
data[tempID] = temp;
if (tempID > 0)
coreTempCount++; 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 == cpuCount || coreTempCount + 1 == cpuCount / 2) {
memmove(&data[1], &data[0], cpuCount * sizeof(*data));
data[0] = NAN;
coreTempCount++;
/* Only package temperature - copy to all cpus */ /* Check for further adjustments */
if (coreTempCount == 0 && !isnan(packageTemp)) { }
/* Only package temperature - copy to all cores */
if (coreTempCount == 0 && !isnan(data[0])) {
for (unsigned int i = 1; i <= cpuCount; i++) for (unsigned int i = 1; i <= cpuCount; i++)
cpus[i].temperature = packageTemp; data[i] = data[0];
return; /* No further adjustments */
goto out;
} }
/* No package temperature - set to max core temperature */ /* No package temperature - set to max core temperature */
if (isnan(packageTemp) && coreTempCount != 0) { if (isnan(data[0]) && coreTempCount != 0) {
double maxTemp = NAN; double maxTemp = NAN;
for (unsigned int i = 1; i <= cpuCount; i++) { for (unsigned int i = 1; i <= cpuCount; i++) {
const double coreTemp = cpus[i].temperature; if (isnan(data[i]))
if (isnan(coreTemp))
continue; 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 <= cpuCount; i++)
data[i] = data[1];
/* No further adjustments */
goto out;
} }
/* Half the temperatures, probably HT/SMT - copy to second half */ /* Half the temperatures, probably HT/SMT - copy to second half */
const unsigned int delta = cpuCount / 2; const unsigned int delta = cpuCount / 2;
if (coreTempCount == delta) { if (coreTempCount == delta) {
for (unsigned int i = 1; i <= delta; i++) memcpy(&data[delta + 1], &data[1], delta * sizeof(*data));
cpus[i + delta].temperature = cpus[i].temperature;
/* No further adjustments */
goto out;
} }
out:
for (unsigned int i = 0; i <= cpuCount; i++)
cpus[i].temperature = data[i];
} }
#endif /* HAVE_SENSORS_SENSORS_H */ #endif /* HAVE_SENSORS_SENSORS_H */