2021-06-27 21:25:29 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
2022-12-17 20:14:19 +00:00
File : AuClock . cpp
2021-06-27 21:25:29 +00:00
Date : 2021 - 6 - 13
Author : Reece
* * */
2021-09-30 14:57:41 +00:00
# include <Source/RuntimeInternal.hpp>
2022-12-17 20:14:19 +00:00
# include "AuClock.hpp"
2023-04-21 21:08:56 +00:00
# include "Time.hpp"
2021-06-27 21:25:29 +00:00
2023-09-18 21:26:19 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
2023-09-18 21:50:38 +00:00
2023-11-02 17:34:46 +00:00
# if defined(AURORA_IS_XNU_DERIVED)
# include <mach/mach_time.h>
AUKN_SYM unsigned long long _NTLikeQueryFrequency ( )
{
static unsigned long long uFrequency { } ;
static AuInitOnce gInitOnce ;
gInitOnce . Call ( [ ]
{
mach_timebase_info_data_t timebase ;
mach_timebase_info ( & timebase ) ;
2023-11-29 07:12:25 +00:00
uFrequency = ( double ( timebase . denom ) * 1'000'000'000 .0 ) / double ( timebase . numer ) ;
2023-11-02 17:34:46 +00:00
} ) ;
return uFrequency ;
}
AUKN_SYM unsigned long long _NTLikeQueryCounter ( )
{
return mach_continuous_time ( ) ;
}
# define GIB__GetSteadyTimeNS
# endif
2023-09-18 21:26:19 +00:00
# include <sys/resource.h>
2022-04-01 17:40:56 +00:00
2023-09-18 21:50:38 +00:00
# elif defined(AURORA_IS_MODERNNT_DERIVED)
2023-09-09 12:58:14 +00:00
2023-10-07 15:57:20 +00:00
# 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 ;
2024-03-12 22:54:03 +00:00
_gNTTimeFreq = _gNTFreq ( ) ;
2023-10-07 15:57:20 +00:00
}
static void _NTDoClockInit ( )
{
static AuInitOnce gInitOnce ;
gInitOnce . Call ( [ ]
{
2023-12-07 19:00:14 +00:00
Aurora : : InitNTAddressesForClock ( ) ;
2023-10-08 13:51:12 +00:00
AuSwInfo : : InitSwInfoEarly ( ) ;
2023-10-07 15:57:20 +00:00
2023-10-17 06:54:43 +00:00
{
// Might be useful for real-time applications under busted motherboards and hypervisors.
// Should the QPC fastpath be invalidated, and the kernel hit each time because of NT HAL retardation,
// this can be used to enforce a userland-only clock query, when Windows would otherwise resort to a
// system call.
// Pretty much every Win32 environment and platform should support this
wchar_t buffer [ 64 ] ;
if ( GetEnvironmentVariableW ( L " AURORA_STEADY_TIME_SHID_CPU_XP_MODE " , buffer , AuArraySize ( buffer ) ) )
{
_gNTClockMode = 0 ;
return ;
}
}
2023-10-07 15:57:20 +00:00
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 :
2024-03-12 22:54:03 +00:00
#if 0
2023-10-07 15:57:20 +00:00
return _gNTFreq ( ) ;
2024-03-12 22:54:03 +00:00
# else
return _gNTTimeFreq ;
# endif
2023-10-07 15:57:20 +00:00
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 ;
}
}
2023-09-18 21:26:19 +00:00
// benchmarking: https://github.com/microsoft/STL/issues/2085
2023-11-02 17:34:46 +00:00
# define GIB__GetSteadyTimeNS
// ~3.0741 seconds
// using high_res_clock = std::chrono::high_resolution_clock;
// ~6.07 seconds
// holy fuck, we're keeping this
// ~2x improvement
# else
using steady_clock = std : : chrono : : steady_clock ;
# endif
# if defined(GIB__GetSteadyTimeNS)
2023-09-18 21:26:19 +00:00
static AuUInt64 _GetSteadyTimeNS ( )
2023-09-10 16:18:31 +00:00
{
2023-10-07 15:57:20 +00:00
static const long long gFreq = _NTLikeQueryFrequency ( ) ;
const long long uCounter = _NTLikeQueryCounter ( ) ;
2023-09-18 21:26:19 +00:00
if ( gFreq = = 10000000 )
{
return uCounter * 100 ;
}
else if ( gFreq = = 1000000 )
{
return uCounter * 1000 ;
}
else if ( gFreq = = 100000 )
{
return uCounter * 10000 ;
}
else if ( gFreq = = 100000000 )
{
return uCounter * 10 ;
}
else if ( gFreq = = 1000000000 )
{
return uCounter ;
}
else
{
// 6 branches: the default threshold for most jit and language compiler backends to decide to pick a jump table, if the values were in a close range
// otherwise, back to a tree of paths. either way, im sure 6 if elses are faster than grug math with large numbers, modulus, division, and multiplication
const long long uWhole = ( uCounter / gFreq ) * 1'000'000'000ull ;
const long long uPart = ( uCounter % gFreq ) * 1'000'000'000ull / gFreq ;
return uWhole + uPart ;
}
2023-09-10 16:18:31 +00:00
}
2022-04-01 17:40:56 +00:00
# endif
2023-09-18 21:26:19 +00:00
using sys_clock = std : : chrono : : system_clock ; // more stds to remove
2021-06-27 21:25:29 +00:00
2023-09-18 21:50:38 +00:00
sys_clock : : duration __NormalizeEpoch ( sys_clock : : duration sysEpoch ) ;
2021-06-27 21:25:29 +00:00
2023-09-18 21:50:38 +00:00
static AuInt64 _CurrentClock ( )
2021-06-27 21:25:29 +00:00
{
2023-09-18 21:50:38 +00:00
return __NormalizeEpoch ( sys_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2021-06-27 21:25:29 +00:00
}
2023-09-10 16:18:31 +00:00
static AuInt64 _CurrentClockMS ( )
{
2023-09-18 21:50:38 +00:00
return std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( __NormalizeEpoch ( sys_clock : : now ( ) . time_since_epoch ( ) ) ) . count ( ) ;
2023-09-10 16:18:31 +00:00
}
static AuInt64 _CurrentClockNS ( )
{
2023-09-18 21:50:38 +00:00
return std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( __NormalizeEpoch ( sys_clock : : now ( ) . time_since_epoch ( ) ) ) . count ( ) ;
2023-09-10 16:18:31 +00:00
}
2021-06-27 21:25:29 +00:00
namespace Aurora : : Time
{
2022-12-06 22:53:37 +00:00
AUKN_SYM AuInt64 CurrentClock ( )
2021-06-27 21:25:29 +00:00
{
2023-09-18 21:50:38 +00:00
return _CurrentClock ( ) ;
2021-06-27 21:25:29 +00:00
}
2022-12-06 22:53:37 +00:00
AUKN_SYM AuInt64 CurrentClockMS ( )
2021-06-27 21:25:29 +00:00
{
2023-09-10 16:18:31 +00:00
return _CurrentClockMS ( ) ;
2021-06-27 21:25:29 +00:00
}
2022-12-06 22:53:37 +00:00
AUKN_SYM AuInt64 CurrentClockNS ( )
2021-06-27 21:25:29 +00:00
{
2023-09-10 16:18:31 +00:00
return _CurrentClockNS ( ) ;
2021-06-27 21:25:29 +00:00
}
2022-12-06 22:53:37 +00:00
AUKN_SYM AuUInt64 SteadyClock ( )
2022-11-28 16:01:08 +00:00
{
2023-11-02 17:34:46 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_XNU_DERIVED)
2023-10-07 15:57:20 +00:00
return _NTLikeQueryCounter ( ) ;
2023-09-10 16:18:31 +00:00
# else
2023-12-01 04:45:29 +00:00
return SteadyClockNS ( ) / ( 1000000000ull / SteadyClockFrequency ( ) ) ;
2023-09-10 16:18:31 +00:00
# endif
2022-11-28 16:01:08 +00:00
}
2022-12-06 22:53:37 +00:00
AUKN_SYM AuUInt64 SteadyClockMS ( )
2022-11-28 16:01:08 +00:00
{
2023-11-02 17:34:46 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_XNU_DERIVED)
return AuNSToMS < AuUInt64 > ( _GetSteadyTimeNS ( ) ) ;
# elif defined(AURORA_IS_POSIX_DERIVED)
2022-11-28 16:01:08 +00:00
: : timespec spec { } ;
2022-12-16 00:41:01 +00:00
if ( : : clock_gettime ( CLOCK_MONOTONIC , & spec ) = = 0 )
2022-11-28 16:01:08 +00:00
{
return AuSToMS < AuUInt64 > ( spec . tv_sec ) + AuNSToMS < AuUInt64 > ( spec . tv_nsec ) ;
}
2023-09-10 16:18:31 +00:00
else
{
return 0 ;
}
# else
2022-11-28 16:01:08 +00:00
return std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( steady_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2023-09-10 16:18:31 +00:00
# endif
2022-11-28 16:01:08 +00:00
}
2022-12-06 22:53:37 +00:00
AUKN_SYM AuUInt64 SteadyClockNS ( )
2022-11-28 16:01:08 +00:00
{
2023-11-02 17:34:46 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_XNU_DERIVED)
return _GetSteadyTimeNS ( ) ;
# elif defined(AURORA_IS_POSIX_DERIVED)
2022-11-28 16:01:08 +00:00
: : timespec spec { } ;
2022-12-16 00:41:01 +00:00
if ( : : clock_gettime ( CLOCK_MONOTONIC , & spec ) = = 0 )
2022-11-28 16:01:08 +00:00
{
return AuMSToNS < AuUInt64 > ( AuSToMS < AuUInt64 > ( spec . tv_sec ) ) + ( AuUInt64 ) spec . tv_nsec ;
}
2023-09-10 16:18:31 +00:00
else
{
return 0 ;
}
# else
return std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( steady_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2022-11-28 16:01:08 +00:00
# endif
2023-09-10 16:18:31 +00:00
}
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 SteadyClockFrequency ( )
2023-09-10 16:18:31 +00:00
{
static AuUInt64 gFrequency = 0 ;
if ( gFrequency ! = 0 )
{
return gFrequency ;
}
2022-11-28 16:01:08 +00:00
2023-11-02 17:34:46 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_XNU_DERIVED)
2023-10-07 15:57:20 +00:00
return gFrequency = _NTLikeQueryFrequency ( ) ;
2023-09-10 16:18:31 +00:00
# elif defined(AURORA_IS_POSIX_DERIVED)
: : timespec spec { } ;
if ( : : clock_getres ( CLOCK_MONOTONIC , & spec ) = = 0 )
{
if ( spec . tv_nsec & & ! spec . tv_sec )
{
return gFrequency = 1000000000ull / spec . tv_nsec ;
}
}
return gFrequency = ( 1000000000ull / 100ull ) ;
# else
return gFrequency = static_cast < double > ( steady_clock : : period : : den ) / static_cast < double > ( steady_clock : : period : : num ) ;
2022-11-28 16:01:08 +00:00
# endif
}
2021-10-02 16:07:33 +00:00
AUKN_SYM AuInt64 CTimeToMS ( time_t time )
{
2023-09-18 21:50:38 +00:00
return std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( __NormalizeEpoch ( sys_clock : : from_time_t ( time ) . time_since_epoch ( ) ) ) . count ( ) ;
2021-10-02 16:07:33 +00:00
}
2023-08-03 22:51:27 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
enum class EPseudoPosixClock
{
eUser ,
eKernel ,
eAll
} ;
static AuUInt64 GetPOSIXTimeEx ( struct rusage * usage , EPseudoPosixClock e )
{
struct timeval * tv { } ;
switch ( e )
{
case EPseudoPosixClock : : eAll :
{
return GetPOSIXTimeEx ( usage , EPseudoPosixClock : : eKernel ) +
GetPOSIXTimeEx ( usage , EPseudoPosixClock : : eUser ) ;
}
case EPseudoPosixClock : : eUser :
{
tv = & usage - > ru_utime ;
break ;
}
case EPseudoPosixClock : : eKernel :
{
tv = & usage - > ru_stime ;
break ;
}
} ;
auto uMS = AuSToMS < AuUInt64 > ( tv - > tv_sec ) ;
auto uNS = AuMSToNS < AuUInt64 > ( uMS ) +
tv - > tv_usec * 1'000ull ;
return uNS ;
}
static AuUInt64 GetPOSIXTime ( bool bThread , EPseudoPosixClock e )
{
struct rusage usage ;
getrusage ( bThread ? RUSAGE_THREAD : RUSAGE_SELF ,
& usage ) ;
return GetPOSIXTimeEx ( & usage , e ) ;
}
2023-09-20 21:51:59 +00:00
static AuPair < AuUInt64 , AuUInt64 > GetPOSIXTimePair ( bool bThread )
{
struct rusage usage ;
getrusage ( bThread ? RUSAGE_THREAD : RUSAGE_SELF ,
& usage ) ;
return {
GetPOSIXTimeEx ( & usage , EPseudoPosixClock : : eKernel ) ,
GetPOSIXTimeEx ( & usage , EPseudoPosixClock : : eUser )
} ;
}
2023-08-03 22:51:27 +00:00
# if !defined(CLOCK_THREAD_CPUTIME_ID)
# define CLOCK_THREAD_CPUTIME_ID 0
# endif
# if !defined(CLOCK_PROCESS_CPUTIME_ID)
# define CLOCK_PROCESS_CPUTIME_ID 0
# endif
# endif
2023-06-19 16:26:41 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2023-08-03 22:51:27 +00:00
# define ADD_CLOCK_FAMILY(fn, type, expr, posixId, posixCall) \
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 fn # # ClockFrequency ( ) ; \
2023-06-19 16:26:41 +00:00
\
AUKN_SYM AuUInt64 fn # # ClockMS ( ) \
{ \
return AuNSToMS < AuUInt64 > ( fn # # ClockNS ( ) ) ; \
} \
\
AUKN_SYM AuUInt64 fn # # ClockNS ( ) \
{ \
FILETIME creation , exit , kernel , user ; \
if ( : : Get # # type # # Times ( GetCurrent # # type ( ) , & creation , & exit , & kernel , & user ) ) \
{ \
ULARGE_INTEGER ullUser ; \
{ \
ullUser . LowPart = user . dwLowDateTime ; \
ullUser . HighPart = user . dwHighDateTime ; \
} \
\
ULARGE_INTEGER ullKernel ; \
{ \
ullKernel . LowPart = kernel . dwLowDateTime ; \
ullKernel . HighPart = kernel . dwHighDateTime ; \
} \
return ( expr ) * 100ull ; \
} \
2023-09-18 21:26:19 +00:00
return 0 ; \
2023-06-19 16:26:41 +00:00
} \
\
AUKN_SYM AuUInt64 fn # # Clock ( ) \
{ \
FILETIME creation , exit , kernel , user ; \
\
if ( : : Get # # type # # Times ( GetCurrent # # type ( ) , & creation , & exit , & kernel , & user ) ) \
{ \
ULARGE_INTEGER ullUser ; \
{ \
ullUser . LowPart = user . dwLowDateTime ; \
ullUser . HighPart = user . dwHighDateTime ; \
} \
\
ULARGE_INTEGER ullKernel ; \
{ \
ullKernel . LowPart = kernel . dwLowDateTime ; \
ullKernel . HighPart = kernel . dwHighDateTime ; \
} \
return expr ; \
} \
\
2023-12-01 04:45:29 +00:00
return fn # # ClockNS ( ) / ( 1000000000ull / fn # # ClockFrequency ( ) ) ; \
2023-06-19 16:26:41 +00:00
} \
\
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 fn # # ClockFrequency ( ) \
2023-06-19 16:26:41 +00:00
{ \
return 1000000000ull / 100u ; \
2021-06-27 21:25:29 +00:00
}
2023-06-19 16:26:41 +00:00
# elif defined(AURORA_IS_POSIX_DERIVED)
2023-08-03 22:51:27 +00:00
# define ADD_CLOCK_FAMILY(fn, type, expr, posixId, posixCall) \
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 fn # # ClockFrequency ( ) ; \
2023-06-19 16:26:41 +00:00
\
AUKN_SYM AuUInt64 fn # # ClockMS ( ) \
{ \
if ( ! posixId ) \
{ \
2023-08-03 22:51:27 +00:00
return AuNSToMS < AuUInt64 > ( GetPOSIXTime AU_WHAT ( posixCall ) ) ; \
2023-06-19 16:26:41 +00:00
} \
return AuNSToMS < AuUInt64 > ( fn # # ClockNS ( ) ) ; \
} \
\
AUKN_SYM AuUInt64 fn # # ClockNS ( ) \
{ \
if ( ! posixId ) \
{ \
2023-08-03 22:51:27 +00:00
return GetPOSIXTime AU_WHAT ( posixCall ) ; \
2023-06-19 16:26:41 +00:00
} \
: : timespec spec { } ; \
if ( : : clock_gettime ( posixId , & spec ) = = 0 ) \
{ \
return AuMSToNS < AuUInt64 > ( AuSToMS < AuUInt64 > ( spec . tv_sec ) ) + ( AuUInt64 ) spec . tv_nsec ; \
} \
2023-09-18 21:26:19 +00:00
return 0 ; \
2023-06-19 16:26:41 +00:00
} \
\
AUKN_SYM AuUInt64 fn # # Clock ( ) \
{ \
if ( ! posixId ) \
{ \
2023-08-03 22:51:27 +00:00
return fn # # ClockNS ( ) / 1000ull ; \
2023-06-19 16:26:41 +00:00
} \
2023-12-01 04:45:29 +00:00
return fn # # ClockNS ( ) / ( 1000000000ull / fn # # ClockFrequency ( ) ) ; \
2023-06-19 16:26:41 +00:00
} \
\
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 fn # # ClockFrequency ( ) \
2023-06-19 16:26:41 +00:00
{ \
if ( ! posixId ) \
{ \
2023-08-03 22:51:27 +00:00
return 1'000'000ull ; \
2023-06-19 16:26:41 +00:00
} \
static AuUInt64 frequency = 0 ; \
if ( frequency ! = 0 ) \
{ \
return frequency ; \
} \
\
: : timespec spec { } ; \
if ( : : clock_getres ( posixId , & spec ) = = 0 ) \
{ \
if ( spec . tv_nsec & & ! spec . tv_sec ) \
{ \
return frequency = 1000000000ull / spec . tv_nsec ; \
} \
else \
{ \
SysUnreachable ( ) ; \
return 0 ; \
} \
} \
\
2023-09-18 21:26:19 +00:00
return 0 ; \
2023-04-21 21:08:56 +00:00
}
2023-06-19 16:26:41 +00:00
# else
2021-06-27 21:25:29 +00:00
2023-06-19 16:26:41 +00:00
AUKN_SYM AuUInt64 fn # # ClockMS ( )
2023-04-21 21:08:56 +00:00
{
2023-06-19 16:26:41 +00:00
return 0 ;
2023-04-21 21:08:56 +00:00
}
2023-06-19 16:26:41 +00:00
AUKN_SYM AuUInt64 fn # # ClockNS ( )
2021-06-27 21:25:29 +00:00
{
2023-06-19 16:26:41 +00:00
return 0 ;
2023-04-21 21:08:56 +00:00
}
2023-06-19 16:26:41 +00:00
AUKN_SYM AuUInt64 fn # # Clock ( )
2023-04-21 21:08:56 +00:00
{
2023-06-19 16:26:41 +00:00
return 0 ;
2023-04-21 21:08:56 +00:00
}
2023-12-01 04:45:29 +00:00
AUKN_SYM AuUInt64 fn # # ClockFrequency ( )
2023-04-21 21:08:56 +00:00
{
2023-06-19 16:26:41 +00:00
return 0 ;
2023-04-21 21:08:56 +00:00
}
2023-06-19 16:26:41 +00:00
# endif
2023-08-03 22:51:27 +00:00
2023-08-28 15:34:21 +00:00
ADD_CLOCK_FAMILY ( Process , Process , ( ullUser . QuadPart + ullKernel . QuadPart ) , /*CLOCK_PROCESS_CPUTIME_ID*/ 0 , ( false , EPseudoPosixClock : : eAll ) ) ;
2023-08-03 22:51:27 +00:00
ADD_CLOCK_FAMILY ( ProcessKernel , Process , ( ullKernel . QuadPart ) , 0 , ( false , EPseudoPosixClock : : eKernel ) ) ;
2023-08-28 15:34:21 +00:00
ADD_CLOCK_FAMILY ( ProcessUser , Process , ( ullUser . QuadPart ) , /*CLOCK_PROCESS_CPUTIME_ID*/ 0 , ( false , EPseudoPosixClock : : eUser ) ) ;
ADD_CLOCK_FAMILY ( Thread , Thread , ( ullUser . QuadPart + ullKernel . QuadPart ) , /*CLOCK_THREAD_CPUTIME_ID*/ 0 , ( true , EPseudoPosixClock : : eAll ) ) ;
2023-08-03 22:51:27 +00:00
ADD_CLOCK_FAMILY ( ThreadKernel , Thread , ( ullKernel . QuadPart ) , 0 , ( true , EPseudoPosixClock : : eKernel ) ) ;
2023-08-28 15:34:21 +00:00
ADD_CLOCK_FAMILY ( ThreadUser , Thread , ( ullUser . QuadPart ) , /*CLOCK_THREAD_CPUTIME_ID*/ 0 , ( true , EPseudoPosixClock : : eUser ) ) ;
2023-09-20 21:51:59 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
# define ADD_CLOCK_FAMILY_PAIR(type, bIsThread, exprA, exprB) \
\
static AuPair < AuUInt64 , AuUInt64 > type # # ClockPairNS ( ) \
{ \
FILETIME creation , exit , kernel , user ; \
if ( : : Get # # type # # Times ( GetCurrent # # type ( ) , & creation , & exit , & kernel , & user ) ) \
{ \
ULARGE_INTEGER ullUser ; \
{ \
ullUser . LowPart = user . dwLowDateTime ; \
ullUser . HighPart = user . dwHighDateTime ; \
} \
\
ULARGE_INTEGER ullKernel ; \
{ \
ullKernel . LowPart = kernel . dwLowDateTime ; \
ullKernel . HighPart = kernel . dwHighDateTime ; \
} \
return AuMakePair ( ( exprA ) * 100ull , ( exprB ) * 100ull ) ; \
} \
return { } ; \
} \
# elif defined(AURORA_IS_POSIX_DERIVED)
# define ADD_CLOCK_FAMILY_PAIR(type, bIsThread, exprA, exprB) \
\
static AuPair < AuUInt64 , AuUInt64 > type # # ClockPairNS ( ) \
{ \
return GetPOSIXTimePair ( bIsThread ) ; \
} \
# else
# define ADD_CLOCK_FAMILY_PAIR(type, bIsThread, exprA, exprB) \
\
static AuPair < AuUInt64 , AuUInt64 > type # # ClockPairNS ( ) \
{ \
return { } ; \
} \
# endif
ADD_CLOCK_FAMILY_PAIR ( Thread , true , ( ullKernel . QuadPart ) ,
( ullUser . QuadPart ) ) ;
ADD_CLOCK_FAMILY_PAIR ( Process , false , ( ullKernel . QuadPart ) ,
( ullUser . QuadPart ) ) ;
AUKN_SYM AuPair < AuUInt64 , AuUInt64 > GetClockUserAndKernelTimeNS ( EClock clock )
{
AuPair < AuUInt64 , AuUInt64 > swizzle ;
switch ( clock )
{
case EClock : : eWall :
case EClock : : eSteady :
SysPushErrorArg ( " Invalid clock " ) ;
return { } ;
case EClock : : eProcessTime :
case EClock : : eProcessUserTime :
case EClock : : eProcessKernelTime :
swizzle = ProcessClockPairNS ( ) ;
break ;
case EClock : : eThreadTime :
case EClock : : eThreadUserTime :
case EClock : : eThreadKernelTime :
swizzle = ThreadClockPairNS ( ) ;
break ;
default :
SysPushErrorArg ( " Invalid clock " ) ;
return { } ;
}
2023-09-23 01:28:06 +00:00
if ( swizzle = = AuPair < AuUInt64 , AuUInt64 > { } )
{
SysPushErrorGeneric ( ) ;
return { } ;
}
2023-09-20 21:51:59 +00:00
return { swizzle . second , swizzle . first } ;
}
2022-03-08 01:36:12 +00:00
}