Fix timer support on macOS under ARM64

meow-7.2.2
Rye 2025-02-03 11:48:18 -05:00
parent 594a7afce6
commit 9fef2a114e
3 changed files with 84 additions and 39 deletions

View File

@ -64,7 +64,7 @@ bool BlockTimer::sLog = false;
std::string BlockTimer::sLogName = "";
bool BlockTimer::sMetricLog = false;
#if LL_LINUX
#if LL_LINUX || (LL_DARWIN && LL_ARM64)
U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
#else
U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution

View File

@ -30,9 +30,14 @@
#include "llinstancetracker.h"
#include "lltrace.h"
#include "lltreeiterators.h"
#include "llprocessor.h"
#if LL_X86 || LL_X86_64
#if LL_WINDOWS
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#endif
#define LL_FAST_TIMER_ON 1
@ -68,35 +73,10 @@ public:
//
// Windows implementation of CPU clock
//
//
// NOTE: put back in when we aren't using platform sdk anymore
//
// because MS has different signatures for these functions in winnt.h
// need to rename them to avoid conflicts
//#define _interlockedbittestandset _renamed_interlockedbittestandset
//#define _interlockedbittestandreset _renamed_interlockedbittestandreset
//#include <intrin.h>
//#undef _interlockedbittestandset
//#undef _interlockedbittestandreset
//inline U32 getCPUClockCount32()
//{
// U64 time_stamp = __rdtsc();
// return (U32)(time_stamp >> 8);
//}
//
//// return full timer value, *not* shifted by 8 bits
//inline U64 getCPUClockCount64()
//{
// return __rdtsc();
//}
#if LL_FASTTIMER_USE_RDTSC
// shift off lower 8 bits for lower resolution but longer term timing
// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
#if LL_FASTTIMER_USE_RDTSC
static U32 getCPUClockCount32()
{
unsigned __int64 val = __rdtsc();
@ -159,23 +139,37 @@ public:
#endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
#if LL_DARWIN && LL_ARM64
//
// Mac+Linux FAST x86 implementation of CPU clock
// Mac implementation of CPU clock - non-x86.
//
static U64 getCPUClockCount64()
{
return clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
}
static U32 getCPUClockCount32()
{
U32 low(0),high(0);
__asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
return (low>>8) | (high<<24);
return (U32)(getCPUClockCount64() >> 8);
}
#endif // LL_DARWIN && LL_ARM64
#if (LL_LINUX || LL_DARWIN) && (LL_X86 || LL_X86_64)
//
// Mac+Linux FAST x86 implementation of CPU clock
//
#if LL_FASTTIMER_USE_RDTSC
static U32 getCPUClockCount32()
{
U64 time_stamp = __rdtsc() >> 8U;
return static_cast<U32>(time_stamp);
}
static U64 getCPUClockCount64()
{
U32 low(0),high(0);
__asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
return (U64)low | ( ((U64)high) << 32);
return static_cast<U64>(__rdtsc());
}
#endif
#endif
static BlockTimerStatHandle& getRootTimeBlock();

View File

@ -628,6 +628,8 @@ private:
#elif LL_DARWIN
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <mach/machine.h>
#include <sys/sysctl.h>
@ -638,17 +640,58 @@ public:
{
getCPUIDInfo();
uint64_t frequency = getSysctlInt64("hw.cpufrequency");
if(frequency == 0) // Attempt to query IO Services for pcore frequency
{
CFMutableDictionaryRef arm_io_matching = IOServiceMatching("AppleARMIODevice");
io_iterator_t iter;
kern_return_t ret = IOServiceGetMatchingServices(kIOMasterPortDefault, arm_io_matching, &iter);
if(ret == KERN_SUCCESS)
{
io_object_t obj;
while ((obj = IOIteratorNext(iter)))
{
io_name_t obj_class;
ret = IOObjectGetClass(obj, obj_class);
if(ret == KERN_SUCCESS)
{
io_name_t obj_name;
ret = IORegistryEntryGetName(obj, obj_name);
if(ret == KERN_SUCCESS)
{
if (strncmp(obj_name, "pmgr", sizeof(obj_name)) == 0)
{
CFTypeRef cfData = IORegistryEntryCreateCFProperty(obj, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, 0); // pcore frequency
if(cfData)
{
CFIndex size = CFDataGetLength((CFDataRef)cfData);
std::vector<U8> databuf(size);
CFDataGetBytes((CFDataRef)cfData, CFRangeMake(0, size), databuf.data());
frequency = 0x00000000FFFFFFFF & ((databuf[size-5] << 24) | (databuf[size-6] << 16) | (databuf[size-7] << 8) | (databuf[size-8]));
CFRelease(cfData);
}
break;
}
}
}
}
}
}
if (frequency == 0) // fallback to clockrate and tbfrequency
{
frequency = getSysctlClockrate() * getSysctlInt64("hw.tbfrequency");
}
setInfo(eFrequency, (F64)frequency / (F64)1000000);
}
virtual ~LLProcessorInfoDarwinImpl() {}
virtual ~LLProcessorInfoDarwinImpl() = default;
private:
int getSysctlInt(const char* name)
{
int result = 0;
size_t len = sizeof(int);
int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
int error = sysctlbyname(name, (void*)&result, &len, nullptr, 0);
return error == -1 ? 0 : result;
}
@ -656,7 +699,7 @@ private:
{
uint64_t value = 0;
size_t size = sizeof(value);
int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
int result = sysctlbyname(name, (void*)&value, &size, nullptr, 0);
if ( result == 0 )
{
if ( size == sizeof( uint64_t ) )
@ -676,6 +719,14 @@ private:
return result == -1 ? 0 : value;
}
uint64_t getSysctlClockrate()
{
struct clockinfo clockrate{};
size_t size = sizeof(clockrate);
int error = sysctlbyname("kern.clockrate", &clockrate, &size, nullptr, 0);
return error == -1 ? 0 : clockrate.hz;
}
void getCPUIDInfo()
{
size_t len = 0;