fix CPU temp fallback on macOS

This commit is contained in:
Jos Dehaes 2021-12-21 23:15:02 +01:00
parent d4f5112d23
commit 96ac1149d1
3 changed files with 43 additions and 22 deletions

View file

@ -68,6 +68,7 @@ namespace Cpu {
cpu_info current_cpu;
fs::path freq_path = "/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq";
bool got_sensors = false, cpu_temp_only = false;
int core_offset = 0;
//* Populate found_sensors map
bool get_sensors();
@ -241,21 +242,34 @@ namespace Cpu {
}
bool get_sensors() {
Logger::debug("get_sensors(): show_coretemp=" + std::to_string(Config::getB("show_coretemp")) + " check_temp=" + std::to_string(Config::getB("check_temp")));
got_sensors = false;
if (Config::getB("show_coretemp") and Config::getB("check_temp")) {
ThermalSensors sensors;
if (sensors.getSensors() > 0) {
Logger::debug("M1 sensors found");
got_sensors = true;
cpu_temp_only = true;
macM1 = true;
} else {
// try SMC (intel)
Logger::debug("checking intel");
SMCConnection smcCon;
try {
long long t = smcCon.getTemp(-1); // check if we have package T
if (t > -1) {
Logger::debug("intel sensors found");
got_sensors = true;
t = smcCon.getTemp(0);
if (t == -1) {
// for some macs the core offset is 1 - check if we get a sane value with 1
if (smcCon.getTemp(1) > -1) {
Logger::debug("intel sensors with offset 1");
core_offset = 1;
}
}
} else {
Logger::debug("no intel sensors found");
got_sensors = false;
}
} catch (std::runtime_error &e) {
@ -282,14 +296,12 @@ namespace Cpu {
long long packageT = smcCon.getTemp(-1); // -1 returns package T
current_cpu.temp.at(0).push_back(packageT);
if (Config::getB("show_coretemp") and not cpu_temp_only) {
for (int core = 0; core < Shared::coreCount; core++) {
long long temp = smcCon.getTemp(core / threadsPerCore); // same temp for all threads of same physical core
if (cmp_less(core + 1, current_cpu.temp.size())) {
current_cpu.temp.at(core + 1).push_back(temp);
if (current_cpu.temp.at(core + 1).size() > 20)
current_cpu.temp.at(core + 1).pop_front();
}
for (int core = 0; core < Shared::coreCount; core++) {
long long temp = smcCon.getTemp((core / threadsPerCore) + core_offset); // same temp for all threads of same physical core
if (cmp_less(core + 1, current_cpu.temp.size())) {
current_cpu.temp.at(core + 1).push_back(temp);
if (current_cpu.temp.at(core + 1).size() > 20)
current_cpu.temp.at(core + 1).pop_front();
}
}
}

View file

@ -50,32 +50,39 @@ namespace Cpu {
IOServiceClose(conn);
}
long long SMCConnection::getSMCTemp(char *key) {
SMCVal_t val;
kern_return_t result;
result = SMCReadKey(key, &val);
if (result == kIOReturnSuccess) {
if (val.dataSize > 0) {
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
// convert sp78 value to temperature
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
return static_cast<long long>(intValue / 256.0);
}
}
}
return -1;
}
// core means physical core in SMC, while in core map it's cpu threads :-/ Only an issue on hackintosh?
// this means we can only get the T per physical core
// another issue with the SMC API is that the key is always 4 chars -> what with systems with more than 9 physical cores?
// no Mac models with more than 18 threads are released, so no problem so far
// according to VirtualSMC docs (hackintosh fake SMC) the enumeration follows with alphabetic chars - not implemented yet here (nor in VirtualSMC)
long long SMCConnection::getTemp(int core) {
SMCVal_t val;
kern_return_t result;
char key[] = SMC_KEY_CPU_TEMP;
if (core >= 0) {
snprintf(key, 5, "TC%1dc", core);
}
result = SMCReadKey(key, &val);
if (result != kIOReturnSuccess) {
long long result = getSMCTemp(key);
if (result == -1) {
// try again with C
snprintf(key, 5, "TC%1dC", core);
result = SMCReadKey(key, &val);
result = getSMCTemp(key);
}
if (result == kIOReturnSuccess) {
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
// convert sp78 value to temperature
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
return static_cast<long long>(intValue / 256.0);
}
}
return -1;
return result;
}
kern_return_t SMCConnection::SMCReadKey(UInt32Char_t key, SMCVal_t *val) {

View file

@ -26,7 +26,8 @@
// key values
#define SMC_KEY_CPU_TEMP "TC0P" // proximity temp?
#define SMC_KEY_CPU_DIE_TEMP "TC0D" // die temp?
#define SMC_KEY_CPU_DIODE_TEMP "TC0D" // diode temp?
#define SMC_KEY_CPU_DIE_TEMP "TC0F" // die temp?
#define SMC_KEY_CPU1_TEMP "TC1C"
#define SMC_KEY_CPU2_TEMP "TC2C" // etc
#define SMC_KEY_FAN0_RPM_CUR "F0Ac"
@ -86,6 +87,7 @@ namespace Cpu {
private:
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val);
long long getSMCTemp(char *key);
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure);
io_connect_t conn;