Skip to content

Commit

Permalink
Merge pull request #14 from enen92/apple_m2
Browse files Browse the repository at this point in the history
Add support for Apple M2
  • Loading branch information
narugit authored Sep 5, 2023
2 parents da1fe79 + 76c24fa commit 4f469f1
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 39 deletions.
28 changes: 25 additions & 3 deletions main.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <charconv>
#include <iomanip>
#include <iostream>

Expand All @@ -11,22 +12,33 @@ void usage(char* prog) {
std::cout << " -h : help" << std::endl;
std::cout << " -l : list all keys and values" << std::endl;
std::cout << " -v : version" << std::endl;
std::cout << " -n : tries to query the temperature sensors for n times (e.g. -n3)";
std::cout << " (1 second interval) until a valid value is returned" << std::endl;
}

int main(int argc, char *argv[]) {
int c;
extern char *optarg;
unsigned int attempts = 1;

kern_return_t result;
int op = smctemp::kOpNone;
smctemp::UInt32Char_t key = { 0 };
smctemp::SmcVal_t val;

while ((c = getopt(argc, argv, "clvh")) != -1) {
while ((c = getopt(argc, argv, "clvhn:")) != -1) {
switch(c) {
case 'c':
op = smctemp::kOpReadCpuTemp;
break;
case 'n':
if (optarg) {
auto [ptr, ec] = std::from_chars(optarg, optarg + strlen(optarg), attempts);
if (ec != std::errc()) {
std::cerr << "Invalid argument provided for -n (integer is required)" << std::endl;
return 1;
}
}
break;
case 'l':
op = smctemp::kOpList;
break;
Expand Down Expand Up @@ -60,7 +72,17 @@ int main(int argc, char *argv[]) {
}
break;
case smctemp::kOpReadCpuTemp:
std::cout << std::fixed << std::setprecision(1) << smc_temp.GetCpuTemp();
double temp = 0.0;
while (attempts > 0) {
temp = smc_temp.GetCpuTemp();
if (temp > 0.0) {
break;
} else {
usleep(1'000'000);
attempts--;
}
}
std::cout << std::fixed << std::setprecision(1) << temp;
break;
}

Expand Down
116 changes: 90 additions & 26 deletions smctemp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,26 @@
#include <iostream>
#include <limits>
#include <string>
#include <vector>

#include "smctemp_string.h"

#if defined(ARCH_TYPE_ARM64)
#include <sys/sysctl.h>
#include <algorithm>
#include <array>

namespace {
std::string getCPUModel() {
std::array<char, 512> buffer;
size_t bufferLength = buffer.size();
sysctlbyname("machdep.cpu.brand_string", buffer.data(), &bufferLength, nullptr, 0);
std::string cpuModel = buffer.data();
std::transform(cpuModel.begin(), cpuModel.end(), cpuModel.begin(), ::tolower);
return cpuModel;
}
}
#endif

// Cache the keyInfo to lower the energy impact of SmcReadKey() / SmcReadKey2()
#define KEY_INFO_CACHE_SIZE 100
namespace smctemp {
Expand Down Expand Up @@ -366,6 +382,24 @@ kern_return_t SmcAccessor::PrintAll() {
return kIOReturnSuccess;
}

double SmcTemp::CalculateAverageTemperature(const std::vector<std::string>& sensors,
const std::pair<unsigned int, unsigned int>& limits) {
double temp = 0.0;
size_t valid_sensor_count = 0;
for (auto sensor : sensors) {
auto sensor_value = smc_accessor_.ReadValue(sensor.c_str());
if (sensor_value >= limits.first &&
sensor_value <= limits.second) {
temp += sensor_value;
valid_sensor_count++;
}
}
if (valid_sensor_count > 0) {
temp /= valid_sensor_count;
}
return temp;
}

double SmcTemp::GetCpuTemp() {
double temp = 0.0;
#if defined(ARCH_TYPE_X86_64)
Expand All @@ -388,35 +422,65 @@ double SmcTemp::GetCpuTemp() {
return temp;
}
#elif defined(ARCH_TYPE_ARM64)
std::vector<std::string> sensors{
static_cast<std::string>(kSensorTp01),
static_cast<std::string>(kSensorTp05),
static_cast<std::string>(kSensorTp0d),
static_cast<std::string>(kSensorTp0h),
static_cast<std::string>(kSensorTp0l),
static_cast<std::string>(kSensorTp0p),
static_cast<std::string>(kSensorTp0x),
static_cast<std::string>(kSensorTp0b),
static_cast<std::string>(kSensorTp09),
static_cast<std::string>(kSensorTp0t),
};
for (auto sensor : sensors) {
temp += smc_accessor_.ReadValue(sensor.c_str());
std::vector<std::string> sensors;
std::vector<std::string> aux_sensors;
const std::pair<unsigned int, unsigned int> valid_temperature_limits{10, 120};

const std::string cpumodel = getCPUModel();
if (cpumodel.find("m2") != std::string::npos) { // Apple M2
// CPU core 1
sensors.emplace_back(static_cast<std::string>(kSensorTp01));
// CPU core 2
sensors.emplace_back(static_cast<std::string>(kSensorTp09));
// CPU core 3
sensors.emplace_back(static_cast<std::string>(kSensorTp0f));
// CPU core 4
sensors.emplace_back(static_cast<std::string>(kSensorTp0n));
// CPU core 5
sensors.emplace_back(static_cast<std::string>(kSensorTp05));
// CPU core 6
sensors.emplace_back(static_cast<std::string>(kSensorTp0d));
// CPU core 7
sensors.emplace_back(static_cast<std::string>(kSensorTp0j));
// CPU core 8
sensors.emplace_back(static_cast<std::string>(kSensorTp0r));
} else if (cpumodel.find("m1") != std::string::npos) { // Apple M1
// CPU performance core 1 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp01));
// CPU performance core 2 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp05));
// CPU performance core 3 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0d));
// CPU performance core 4 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0h));
// CPU performance core 5 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0l));
// CPU performance core 6 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0p));
// CPU performance core 7 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0x));
// CPU performance core 8 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0b));
// CPU efficient core 1 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp09));
// CPU efficient core 2 temperature
sensors.emplace_back(static_cast<std::string>(kSensorTp0t));

aux_sensors.emplace_back(static_cast<std::string>(kSensorTc0a));
aux_sensors.emplace_back(static_cast<std::string>(kSensorTc0b));
aux_sensors.emplace_back(static_cast<std::string>(kSensorTc0x));
aux_sensors.emplace_back(static_cast<std::string>(kSensorTc0z));
} else {
// not supported
return temp;
}
temp /= sensors.size();

temp = CalculateAverageTemperature(sensors, valid_temperature_limits);
if (temp > std::numeric_limits<double>::epsilon()) {
return temp;
}
std::vector<std::string> aux_sensors{
static_cast<std::string>(kSensorTc0a),
static_cast<std::string>(kSensorTc0b),
static_cast<std::string>(kSensorTc0x),
static_cast<std::string>(kSensorTc0z),
};
for (auto sensor : aux_sensors) {
temp += smc_accessor_.ReadValue(sensor.c_str());
}
temp /= aux_sensors.size();

temp += CalculateAverageTemperature(aux_sensors, valid_temperature_limits);
#endif
return temp;
}
Expand Down
28 changes: 18 additions & 10 deletions smctemp.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#include <IOKit/IOKitLib.h>
#include <string>
#include <utility>
#include <vector>

#include "smctemp_types.h"

Expand Down Expand Up @@ -54,16 +56,20 @@ constexpr UInt32Char_t kSensorTc0a = "Tc0a";
constexpr UInt32Char_t kSensorTc0b = "Tc0b";
constexpr UInt32Char_t kSensorTc0x = "Tc0x";
constexpr UInt32Char_t kSensorTc0z = "Tc0z";
constexpr UInt32Char_t kSensorTp01 = "Tp01"; // CPU performance core 1 temperature
constexpr UInt32Char_t kSensorTp05 = "Tp05"; // CPU performance core 2 temperature
constexpr UInt32Char_t kSensorTp0d = "Tp0D"; // CPU performance core 3 temperature
constexpr UInt32Char_t kSensorTp0h = "Tp0H"; // CPU performance core 4 temperature
constexpr UInt32Char_t kSensorTp0l = "Tp0L"; // CPU performance core 5 temperature
constexpr UInt32Char_t kSensorTp0p = "Tp0P"; // CPU performance core 6 temperature
constexpr UInt32Char_t kSensorTp0x = "Tp0X"; // CPU performance core 7 temperature
constexpr UInt32Char_t kSensorTp0b = "Tp0b"; // CPU performance core 8 temperature
constexpr UInt32Char_t kSensorTp09 = "Tp09"; // CPU efficient core 1 temperature
constexpr UInt32Char_t kSensorTp0t = "Tp0T"; // CPU efficient core 2 temperature
constexpr UInt32Char_t kSensorTp01 = "Tp01";
constexpr UInt32Char_t kSensorTp05 = "Tp05";
constexpr UInt32Char_t kSensorTp0d = "Tp0D";
constexpr UInt32Char_t kSensorTp0h = "Tp0H";
constexpr UInt32Char_t kSensorTp0l = "Tp0L";
constexpr UInt32Char_t kSensorTp0p = "Tp0P";
constexpr UInt32Char_t kSensorTp0x = "Tp0X";
constexpr UInt32Char_t kSensorTp0b = "Tp0b";
constexpr UInt32Char_t kSensorTp09 = "Tp09";
constexpr UInt32Char_t kSensorTp0t = "Tp0T";
constexpr UInt32Char_t kSensorTp0j = "Tp0j";
constexpr UInt32Char_t kSensorTp0r = "Tp0r";
constexpr UInt32Char_t kSensorTp0f = "Tp0f";
constexpr UInt32Char_t kSensorTp0n = "Tp0n";
#endif

class SmcAccessor {
Expand All @@ -88,6 +94,8 @@ class SmcAccessor {

class SmcTemp {
private:
double CalculateAverageTemperature(const std::vector<std::string>& sensors,
const std::pair<unsigned int, unsigned int>& limits);
SmcAccessor smc_accessor_;

public:
Expand Down

0 comments on commit 4f469f1

Please sign in to comment.