[+] NT 3.5 through Windows 7 specific clock backends

This commit is contained in:
Reece Wilson 2023-10-07 16:57:20 +01:00
parent a7a45aaf4b
commit 795fb3d2d1
3 changed files with 205 additions and 6 deletions

View File

@ -135,7 +135,9 @@ namespace Aurora
ADD_GET_PROC(Kernel32, GetThreadId)
ADD_GET_PROC(Kernel32, VerifyVersionInfoW)
ADD_GET_PROC(Kernel32, VerSetConditionMask)
ADD_GET_PROC(Kernel32, QueryPerformanceCounter)
ADD_GET_PROC(Kernel32, QueryPerformanceFrequency)
ADD_GET_PROC_BI2(Kernel32, PSAPILegacy, K32GetProcessMemoryInfo, GetProcessMemoryInfo)
ADD_GET_PROC(Sync, WaitOnAddress)
@ -190,7 +192,7 @@ namespace Aurora
pNtCreateKeyedEvent(&Threading::Primitives::gKeyedEventHandle, -1, NULL, 0);
}
}
#else
pLoadLibraryW = UWPLibraryW;
pGetProcAddress = UWPProcAddress;
@ -225,6 +227,9 @@ namespace Aurora
pPrefetchVirtualMemory = PrefetchVirtualMemory;
pQueryPerformanceCounter = decltype(pQueryPerformanceCounter)(QueryPerformanceCounter);
pQueryPerformanceFrequency = decltype(pQueryPerformanceFrequency)(QueryPerformanceFrequency);
// https://github.com/LWJGL/lwjgl3/blob/master/modules/lwjgl/remotery/src/main/c/Remotery.c#L1188
// Xbox main SDK has a better API we should use
// So...

View File

@ -373,6 +373,24 @@ namespace Aurora
inline BOOL(__stdcall *pCancelSynchronousIo)(
HANDLE hThread
);
#if 0
inline BOOL(__stdcall *pQueryPerformanceCounter)(
LARGE_INTEGER * lpPerformanceCount
);
inline BOOL(__stdcall *pQueryPerformanceFrequency)(
LARGE_INTEGER * lpPerformanceCount
);
#else // no one will notice
inline BOOL(__stdcall *pQueryPerformanceCounter)(
long long * lpPerformanceCount
);
inline BOOL(__stdcall *pQueryPerformanceFrequency)(
long long * lpPerformanceCount
);
#endif
inline BOOL(__stdcall *pGetProcessMemoryInfo)(
HANDLE Process,

View File

@ -15,11 +15,187 @@
#elif defined(AURORA_IS_MODERNNT_DERIVED)
#include <SWInfo/AuSWInfo.hpp>
static AuUInt8 _gNTClockMode {};
static long long(__cdecl *_gNTQuery)();
static long long(__cdecl *_gNTFreq)();
struct NTSystemTime
{
NTSystemTime(volatile NTSystemTime &dumb)
{
this->LowPart = dumb.LowPart;
this->High1Time = dumb.High1Time;
this->High2Time = dumb.High2Time;
}
unsigned long LowPart;
long High1Time;
long High2Time;
};
struct NTQPCoefficients
{
union
{
UCHAR TscQpcData;
struct
{
UCHAR TscQpcEnabled : 1;
UCHAR TscQpcSpareFlag : 1;
UCHAR TscQpcShift : 6;
};
};
};
static unsigned long long _NT3_Query_Frequency();
static void _NTSetFallbackClock();
static void * kKUSERShardDataOffset = AuReinterpretCast<void *>(0x7ffe0000);
static auto * kKInterruptTime = AuReinterpretCast<volatile NTSystemTime *>(AuReinterpretCast<AuUInt8 *>(kKUSERShardDataOffset) + 8);
static auto * kKQPCData = AuReinterpretCast<NTQPCoefficients *>(AuReinterpretCast<AuUInt8 *>(kKUSERShardDataOffset) + 0x2ED);
static AuUInt64 _gNTTimeShift {};
static AuUInt64 _gNTTimeBias {};
static AuUInt64 _gNTTimeFreq { _NT3_Query_Frequency() };
static unsigned long long _NT3_Query_Frequency()
{
return 1'0000'000ull;
}
static void _NT6_1_Init()
{
NTQPCoefficients now;
now.TscQpcData = AuAtomicLoad(&kKQPCData->TscQpcData);
if (!now.TscQpcEnabled)
{
_NTSetFallbackClock();
return;
}
_gNTTimeShift = now.TscQpcShift;
_gNTTimeBias = *AuReinterpretCast<ULONGLONG *>(AuReinterpretCast<AuUInt8 *>(kKUSERShardDataOffset) + 0x3B8);
long long uvalue {};
SysAssert(Aurora::pQueryPerformanceFrequency &&
Aurora::pQueryPerformanceFrequency(&uvalue), "no perf frequency");
_gNTTimeFreq = uvalue;
_gNTClockMode = 1;
}
static long long _NT6_1_Query_Frequency()
{
return _gNTTimeFreq;
}
static unsigned long long _NT6_1_Query_Counter()
{
#if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86)
AuUInt64 uTimeNow = __rdtsc();
uTimeNow += _gNTTimeBias;
uTimeNow >>= _gNTTimeShift;
return uTimeNow;
#endif
return 0;
}
static long long _NT3_Query_Counter()
{
auto interruptTime = *kKInterruptTime;
return (AuUInt64(kKInterruptTime->High1Time) << 32ull) | interruptTime.LowPart;
}
static void _NTSetFallbackClock()
{
_gNTFreq = []()
{
long long uvalue {};
SysAssert(Aurora::pQueryPerformanceFrequency &&
Aurora::pQueryPerformanceFrequency(&uvalue), "no perf frequency");
return uvalue;
};
_gNTQuery = []()
{
long long uvalue {};
SysAssert(Aurora::pQueryPerformanceCounter &&
Aurora::pQueryPerformanceCounter(&uvalue), "no perf counter");
return uvalue;
};
_gNTClockMode = 2;
}
static void _NTDoClockInit()
{
static AuInitOnce gInitOnce;
gInitOnce.Call([]
{
Aurora::InitNTAddresses();
AuSwInfo::InitSwInfo();
if constexpr (AuBuild::kCurrentPlatform == AuBuild::EPlatform::ePlatformWin32)
{
if (!AuSwInfo::IsWindows7OrGreater())
{
_gNTClockMode = 0;
}
else if (AuSwInfo::IsWindows7Any())
{
_NT6_1_Init();
}
else //if (AuSwInfo::IsWindows8OrGreater())
{
_NTSetFallbackClock();
}
}
else
{
_gNTClockMode = 2;
_gNTFreq = _Query_perf_frequency;
_gNTQuery = _Query_perf_counter;
}
});
}
AUKN_SYM unsigned long long _NTLikeQueryFrequency()
{
_NTDoClockInit();
switch (_gNTClockMode)
{
case 0:
return _NT3_Query_Frequency();
case 1:
return _NT6_1_Query_Frequency();
case 2:
return _gNTFreq();
default:
return 0;
}
}
AUKN_SYM unsigned long long _NTLikeQueryCounter()
{
switch (_gNTClockMode)
{
case 0:
return _NT3_Query_Counter();
case 1:
return _NT6_1_Query_Counter();
case 2:
return _gNTQuery();
default:
return 0;
}
}
// benchmarking: https://github.com/microsoft/STL/issues/2085
static AuUInt64 _GetSteadyTimeNS()
{
static const long long gFreq = _Query_perf_frequency();
const long long uCounter = _Query_perf_counter();
static const long long gFreq = _NTLikeQueryFrequency();
const long long uCounter = _NTLikeQueryCounter();
if (gFreq == 10000000)
{
@ -103,7 +279,7 @@ namespace Aurora::Time
AUKN_SYM AuUInt64 SteadyClock()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
return _Query_perf_counter();
return _NTLikeQueryCounter();
#else
return SteadyClockNS() / (1000000000ull / SteadyClockJiffies());
#endif
@ -156,7 +332,7 @@ namespace Aurora::Time
}
#if defined(AURORA_COMPILER_MSVC)
return gFrequency = _Query_perf_frequency();
return gFrequency = _NTLikeQueryFrequency();
#elif defined(AURORA_IS_POSIX_DERIVED)
::timespec spec {};
if (::clock_getres(CLOCK_MONOTONIC, &spec) == 0)