CPU (macOS): support Apple Silicon frequency detection

This commit is contained in:
李通洲
2023-09-07 17:03:12 +08:00
parent 904c9eb3c4
commit d8b2151143
3 changed files with 94 additions and 11 deletions
+72 -11
View File
@@ -20,6 +20,77 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
return result;
}
#ifdef __aarch64__
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice");
if (matchDict == NULL)
return "IOServiceMatching(\"AppleARMIODevice\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
io_name_t name;
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
continue;
if (strcmp(name, "pmgr") != 0)
continue;
uint32_t pMin, eMin, aMax, pCoreLength;
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
CFRelease(properties);
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
#else
static const char* detectFrequency(FFCPUResult* cpu)
{
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
if(cpu->frequencyMax > 0.0)
cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0;
else
{
unsigned current = 0;
size_t size = sizeof(current);
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, &current, &size, NULL, 0) == 0)
cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0;
}
return NULL;
}
#endif
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
@@ -41,17 +112,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
if(cpu->frequencyMax > 0.0)
cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0;
else
{
unsigned current = 0;
size_t size = sizeof(current);
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, &current, &size, NULL, 0) == 0)
cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0;
}
detectFrequency(cpu);
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
+21
View File
@@ -83,6 +83,27 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result)
return "TypeID is neither 'CFNumber' nor 'CFData'";
}
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length)
{
CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
if(cf == NULL)
return "CFDictionaryGetValue() failed";
if(CFGetTypeID(cf) != CFDataGetTypeID())
return "TypeID is not 'CFData'";
CFIndex trueLength = CFDataGetLength((CFDataRef)cf);
if(trueLength < offset + size)
return "Data length is less than offset + size";
if(length)
*length = (uint32_t) trueLength;
CFDataGetBytes((CFDataRef)cf, CFRangeMake(offset, size), result);
return NULL;
}
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result)
{
CFDictionaryRef cf = (CFDictionaryRef)CFDictionaryGetValue(dict, key);
+1
View File
@@ -11,6 +11,7 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result);
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length);
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result);
static inline CFNumberRef ffCfCreateInt(int value)