[+] NT 3.5 through Windows 7 specific clock backends
This commit is contained in:
parent
a7a45aaf4b
commit
795fb3d2d1
@ -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...
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user