From 96ac1149d15743d148c51714b496e389a71fe8f4 Mon Sep 17 00:00:00 2001 From: Jos Dehaes Date: Tue, 21 Dec 2021 23:15:02 +0100 Subject: [PATCH] fix CPU temp fallback on macOS --- src/osx/btop_collect.cpp | 28 ++++++++++++++++++++-------- src/osx/smc.cpp | 33 ++++++++++++++++++++------------- src/osx/smc.hpp | 4 +++- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index f976a55..ae4411a 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -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(); } } } diff --git a/src/osx/smc.cpp b/src/osx/smc.cpp index 7386dbf..54fa422 100644 --- a/src/osx/smc.cpp +++ b/src/osx/smc.cpp @@ -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(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(intValue / 256.0); - } - } - return -1; + return result; } kern_return_t SMCConnection::SMCReadKey(UInt32Char_t key, SMCVal_t *val) { diff --git a/src/osx/smc.hpp b/src/osx/smc.hpp index 6d65c9c..87ed2ef 100644 --- a/src/osx/smc.hpp +++ b/src/osx/smc.hpp @@ -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;