- Timestamp:
- Dec 6, 2014 3:57:52 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/nt/nt.h
r53445 r53471 71 71 #define PEB_LDR_DATA Incomplete_PEB_LDR_DATA 72 72 #define PPEB_LDR_DATA Incomplete_PPEB_LDR_DATA 73 #define _KUSER_SHARED_DATA Incomplete__KUSER_SHARED_DATA 74 #define KUSER_SHARED_DATA Incomplete_KUSER_SHARED_DATA 75 #define PKUSER_SHARED_DATA Incomplete_PKUSER_SHARED_DATA 73 76 74 77 … … 208 211 #undef PEB_LDR_DATA 209 212 #undef PPEB_LDR_DATA 213 #undef _KUSER_SHARED_DATA 214 #undef KUSER_SHARED_DATA 215 #undef PKUSER_SHARED_DATA 210 216 211 217 … … 438 444 typedef XSTATE_CONFIGURATION *PXSTATE_CONFIGURATION; 439 445 # endif 446 #endif /* IPRT_NT_USE_WINTERNL */ 440 447 441 448 typedef struct _KUSER_SHARED_DATA … … 559 566 } KUSER_SHARED_DATA; 560 567 typedef KUSER_SHARED_DATA *PKUSER_SHARED_DATA; 561 #endif /* IPRT_NT_USE_WINTERNL */562 568 AssertCompileMemberOffset(KUSER_SHARED_DATA, InterruptTime, 0x008); 563 569 AssertCompileMemberOffset(KUSER_SHARED_DATA, SystemTime, 0x014); … … 568 574 AssertCompileMemberOffset(KUSER_SHARED_DATA, Cookie, 0x330); 569 575 AssertCompileMemberOffset(KUSER_SHARED_DATA, ImageFileExecutionOptions, 0x3a0); 570 #ifdef IPRT_NT_USE_WINTERNL571 576 AssertCompileMemberOffset(KUSER_SHARED_DATA, XState, 0x3d8); 572 #endif /* IPRT_NT_USE_WINTERNL */ 577 /** @def MM_SHARED_USER_DATA_VA 578 * Read only userland mapping of KUSER_SHARED_DATA. */ 579 #ifndef MM_SHARED_USER_DATA_VA 580 # if ARCH_BITS == 32 581 # define MM_SHARED_USER_DATA_VA UINT32_C(0x7ffe0000) 582 # elif ARCH_BITS == 64 583 # define MM_SHARED_USER_DATA_VA UINT64_C(0x7ffe0000) 584 # else 585 # error "Unsupported/undefined ARCH_BITS value." 586 # endif 587 #endif 588 /** @def KI_USER_SHARED_DATA 589 * Read write kernel mapping of KUSER_SHARED_DATA. */ 590 #ifndef KI_USER_SHARED_DATA 591 # ifdef RT_ARCH_X86 592 # define KI_USER_SHARED_DATA UINT32_C(0xffdf0000) 593 # elif defined(RT_ARCH_AMD64) 594 # define KI_USER_SHARED_DATA UINT64_C(0xfffff78000000000) 595 # else 596 # error "PORT ME - KI_USER_SHARED_DATA" 597 # endif 598 #endif 573 599 /** @} */ 574 600 … … 2299 2325 NTSYSAPI VOID NTAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS rcNt); 2300 2326 NTSYSAPI VOID NTAPI RtlRestoreLastWin32Error(ULONG uError); 2327 NTSYSAPI BOOLEAN NTAPI RtlQueryPerformanceCounter(PLARGE_INTEGER); 2328 NTSYSAPI uint64_t NTAPI RtlGetSystemTimePrecise(VOID); 2329 typedef uint64_t (NTAPI * PFNRTLGETSYSTEMTIMEPRECISE)(VOID); 2301 2330 2302 2331 RT_C_DECLS_END -
trunk/src/VBox/Runtime/Makefile.kmk
r53278 r53471 752 752 r3/win/thread-win.cpp \ 753 753 r3/win/thread2-win.cpp \ 754 r3/win/time-win.cpp \ 754 $(if-expr 1,r3/win/time-win.cpp,r3/nt/time-nt.cpp) \ 755 r3/win/time2-win.cpp \ 755 756 r3/win/timer-win.cpp \ 756 757 r3/win/tls-win.cpp \ -
trunk/src/VBox/Runtime/r3/nt/time-nt.cpp
r53467 r53471 30 30 *******************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_TIME 32 #include <Windows.h>32 #include "internal-r3-nt.h" 33 33 34 34 #include <iprt/time.h> 35 #include "internal/iprt.h"36 37 35 #include <iprt/asm.h> 38 36 #include <iprt/assert.h> 39 37 #include <iprt/err.h> 38 #include <iprt/ldr.h> 39 #include <iprt/uint128.h> 40 40 #include "internal/time.h" 41 41 42 /* 43 * Note! The selected time source be the exact same one as we use in kernel land! 42 43 /******************************************************************************* 44 * Global Variables * 45 *******************************************************************************/ 46 /** Whether we've tried to resolve g_pfnRtlGetSystemTimePrecise or not. */ 47 static bool g_fInitialized = false; 48 /** Pointer to RtlGetSystemTimePrecise, added in 6.2 (windows 8). */ 49 static PFNRTLGETSYSTEMTIMEPRECISE g_pfnRtlGetSystemTimePrecise = NULL; 50 51 52 /** 53 * Initializes globals. 44 54 */ 45 //#define USE_TICK_COUNT 46 //#define USE_PERFORMANCE_COUNTER 47 //# define USE_FILE_TIME 48 //#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) 49 # define USE_INTERRUPT_TIME 50 //#else 51 //# define USE_TICK_COUNT 52 //#endif 53 54 55 #ifdef USE_INTERRUPT_TIME 56 57 typedef struct _MY_KSYSTEM_TIME 58 { 59 ULONG LowPart; 60 LONG High1Time; 61 LONG High2Time; 62 } MY_KSYSTEM_TIME; 63 64 typedef struct _MY_KUSER_SHARED_DATA 65 { 66 ULONG TickCountLowDeprecated; 67 ULONG TickCountMultiplier; 68 volatile MY_KSYSTEM_TIME InterruptTime; 69 /* The rest is not relevant. */ 70 } MY_KUSER_SHARED_DATA, *PMY_KUSER_SHARED_DATA; 71 72 #endif /* USE_INTERRUPT_TIME */ 73 74 75 DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void) 76 { 77 #if defined USE_TICK_COUNT 78 /* 79 * This would work if it didn't flip over every 49 (or so) days. 80 */ 81 return (uint64_t)GetTickCount() * RT_NS_1MS_64; 82 83 #elif defined USE_PERFORMANCE_COUNTER 84 /* 85 * Slow and not derived from InterruptTime. 86 */ 87 static LARGE_INTEGER llFreq; 88 static unsigned uMult; 89 if (!llFreq.QuadPart) 90 { 91 if (!QueryPerformanceFrequency(&llFreq)) 92 return (uint64_t)GetTickCount() * RT_NS_1MS_64; 93 llFreq.QuadPart /= 1000; 94 uMult = 1000000; /* no math genius, but this seemed to help avoiding floating point. */ 55 static void rtTimeNtInitialize(void) 56 { 57 /* 58 * Make sure we don't recurse here when calling into RTLdr. 59 */ 60 if (ASMAtomicCmpXchgBool(&g_fInitialized, true, false)) 61 { 62 void *pvFunc = RTLdrGetSystemSymbol("ntdll.dll", "RtlGetSystemTimePrecise"); 63 if (pvFunc) 64 ASMAtomicWritePtr((void * volatile *)&g_pfnRtlGetSystemTimePrecise, pvFunc); 65 ASMCompilerBarrier(); 95 66 } 96 97 LARGE_INTEGER ll; 98 if (QueryPerformanceCounter(&ll)) 99 return (ll.QuadPart * uMult) / llFreq.QuadPart; 100 return (uint64_t)GetTickCount() * RT_NS_1MS_64; 101 102 #elif defined USE_FILE_TIME 103 /* 104 * This is SystemTime not InterruptTime. 105 */ 106 uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */ 107 GetSystemTimeAsFileTime((LPFILETIME)&u64); 108 return u64 * 100; 109 110 #elif defined USE_INTERRUPT_TIME 111 # if 0 /* ASSUME 0x7ffe0000 is set in stone */ 112 /* 113 * This is exactly what we want, but we have to obtain it by non-official 114 * means. 115 */ 116 static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL; 117 if (!s_pUserSharedData) 118 { 119 /** @todo find official way of getting this or some more clever 120 * detection algorithm if necessary. The com debugger class 121 * exports this too, windbg knows it too... */ 122 s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000; 123 } 124 # endif 125 PMY_KUSER_SHARED_DATA pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000; 126 127 /* use interrupt time */ 128 LARGE_INTEGER Time; 129 do 130 { 131 Time.HighPart = pUserSharedData->InterruptTime.High1Time; 132 Time.LowPart = pUserSharedData->InterruptTime.LowPart; 133 } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart); 134 135 return (uint64_t)Time.QuadPart * 100; 136 137 #else 138 # error "Must select a method bright guy!" 139 #endif 140 } 141 142 143 RTDECL(uint64_t) RTTimeSystemNanoTS(void) 144 { 145 return rtTimeGetSystemNanoTS(); 146 } 147 148 149 RTDECL(uint64_t) RTTimeSystemMilliTS(void) 150 { 151 return rtTimeGetSystemNanoTS() / RT_NS_1MS; 152 } 153 154 155 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime) 156 { 157 uint64_t u64; 158 AssertCompile(sizeof(u64) == sizeof(FILETIME)); 159 GetSystemTimeAsFileTime((LPFILETIME)&u64); 160 return RTTimeSpecSetNtTime(pTime, u64); 161 } 162 163 164 RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime) 165 { 166 FILETIME FileTime; 167 SYSTEMTIME SysTime; 168 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime)) 169 { 170 if (SetSystemTime(&SysTime)) 171 return VINF_SUCCESS; 172 } 173 return RTErrConvertFromWin32(GetLastError()); 174 } 175 176 177 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime) 178 { 179 uint64_t u64; 180 AssertCompile(sizeof(u64) == sizeof(FILETIME)); 181 GetSystemTimeAsFileTime((LPFILETIME)&u64); 182 uint64_t u64Local; 183 if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local)) 184 u64Local = u64; 185 return RTTimeSpecSetNtTime(pTime, u64Local); 186 } 187 188 189 RTDECL(int64_t) RTTimeLocalDeltaNano(void) 190 { 191 /* 192 * UTC = local + Tzi.Bias; 193 * The bias is given in minutes. 194 */ 195 TIME_ZONE_INFORMATION Tzi; 196 Tzi.Bias = 0; 197 if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID) 198 return -(int64_t)Tzi.Bias * 60 * RT_NS_1SEC_64; 199 return 0; 200 } 201 202 203 RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec) 204 { 205 /* 206 * FileTimeToLocalFileTime does not do the right thing, so we'll have 207 * to convert to system time and SystemTimeToTzSpecificLocalTime instead. 208 */ 209 RTTIMESPEC LocalTime; 210 SYSTEMTIME SystemTimeIn; 211 FILETIME FileTime; 212 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn)) 213 { 214 SYSTEMTIME SystemTimeOut; 215 if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */, 216 &SystemTimeIn, 217 &SystemTimeOut)) 67 } 68 69 70 static uint64_t rtTimeGetSystemNanoTS(void) 71 { 72 if (RT_UNLIKELY(!g_fInitialized)) 73 rtTimeNtInitialize(); 74 75 KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA; 76 77 #if 1 78 /* 79 * If there is precise time, get the precise system time and calculate the 80 * interrupt time from it. (Microsoft doesn't expose interrupt time to user 81 * application, which is very unfortunate as there are a lot place where 82 * monotonic time is applicable but developer is "forced" to use wall clock.) 83 */ 84 if (g_pfnRtlGetSystemTimePrecise) 85 { 86 for (;;) 218 87 { 219 if (SystemTimeToFileTime(&SystemTimeOut, &FileTime)) 88 uint64_t uUpdateLockBefore; 89 while ((uUpdateLockBefore = pUserSharedData->TimeUpdateLock) & 1) 90 ASMNopPause(); 91 92 uint64_t uInterruptTime = *(uint64_t volatile *)&pUserSharedData->InterruptTime; 93 uint64_t uBaselineInterruptTimeQpc = pUserSharedData->BaselineInterruptTimeQpc; 94 uint64_t uQpcInterruptTimeIncrement = pUserSharedData->QpcInterruptTimeIncrement; 95 uint8_t uQpcInterruptTimeIncrementShift = pUserSharedData->QpcInterruptTimeIncrementShift; 96 LARGE_INTEGER QpcValue; 97 RtlQueryPerformanceCounter(&QpcValue); 98 99 if (pUserSharedData->TimeUpdateLock == uUpdateLockBefore) 220 100 { 221 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime); 222 pTime = RTTimeExplode(pTime, &LocalTime); 223 if (pTime) 224 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL; 225 return pTime; 101 uint64_t uQpcValue = QpcValue.QuadPart; 102 if (uQpcValue <= uBaselineInterruptTimeQpc) 103 return uInterruptTime * 100; 104 105 /* Calc QPC delta since base line. */ 106 uQpcValue -= uBaselineInterruptTimeQpc; 107 uQpcValue--; 108 109 /* Multiply by 10 million. */ 110 uQpcValue *= UINT32_C(10000000); 111 112 /* Multiply by QPC interrupt time increment value. */ 113 RTUINT128U Tmp128; 114 RTUInt128MulU64ByU64(&Tmp128, uQpcValue, uQpcInterruptTimeIncrement); 115 116 /* Shift the upper 64 bits by the increment shift factor. */ 117 uint64_t uResult = Tmp128.s.Hi >> uQpcInterruptTimeIncrementShift; 118 119 /* Add to base interrupt time value. */ 120 uResult += uInterruptTime; 121 122 /* Convert from NT unit to nano seconds. */ 123 return uResult * 100; 226 124 } 125 126 ASMNopPause(); 227 127 } 228 128 } 229 230 /* 231 * The fallback is to use the current offset. 232 * (A better fallback would be to use the offset of the same time of the year.) 233 */ 234 LocalTime = *pTimeSpec; 235 RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano()); 236 pTime = RTTimeExplode(pTime, &LocalTime); 237 if (pTime) 238 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL; 239 return pTime; 240 } 241 129 #endif 130 131 /* 132 * Just read interrupt time. 133 */ 134 #if ARCH_BITS >= 64 135 uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->InterruptTime; /* This is what KeQueryInterruptTime does. */ 136 uRet *= 100; 137 return uRet; 138 #else 139 140 LARGE_INTEGER NtTime; 141 do 142 { 143 NtTime.HighPart = pUserSharedData->InterruptTime.High1Time; 144 NtTime.LowPart = pUserSharedData->InterruptTime.LowPart; 145 } while (pUserSharedData->InterruptTime.High2Time != NtTime.HighPart); 146 147 return (uint64_t)NtTime.QuadPart * 100; 148 #endif 149 } 150 151 152 RTDECL(uint64_t) RTTimeSystemNanoTS(void) 153 { 154 return rtTimeGetSystemNanoTS(); 155 } 156 157 158 RTDECL(uint64_t) RTTimeSystemMilliTS(void) 159 { 160 return rtTimeGetSystemNanoTS() / RT_NS_1MS; 161 } 162 163 164 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime) 165 { 166 /* 167 * Get the precise time if possible. 168 */ 169 if (RT_UNLIKELY(!g_fInitialized)) 170 rtTimeNtInitialize(); 171 if (g_pfnRtlGetSystemTimePrecise != NULL) 172 return RTTimeSpecSetNtTime(pTime, g_pfnRtlGetSystemTimePrecise()); 173 174 /* 175 * Just read system time. 176 */ 177 KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA; 178 #ifdef RT_ARCH_AMD64 179 uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->SystemTime; /* This is what KeQuerySystemTime does. */ 180 return RTTimeSpecSetNtTime(pTime, uRet); 181 #else 182 183 LARGE_INTEGER NtTime; 184 do 185 { 186 NtTime.HighPart = pUserSharedData->SystemTime.High1Time; 187 NtTime.LowPart = pUserSharedData->SystemTime.LowPart; 188 } while (pUserSharedData->SystemTime.High2Time != NtTime.HighPart); 189 return RTTimeSpecSetNtTime(pTime, NtTime.QuadPart); 190 #endif 191 } 192 193 194 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime) 195 { 196 return RTTimeSpecAddNano(RTTimeNow(pTime), RTTimeLocalDeltaNano()); 197 } 198 199 200 RTDECL(int64_t) RTTimeLocalDeltaNano(void) 201 { 202 /* 203 * UTC = local + TimeZoneBias; The bias is given in NT units. 204 */ 205 KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA; 206 LARGE_INTEGER Delta; 207 #if ARCH_BITS == 64 208 Delta.QuadPart = *(int64_t volatile *)&pUserSharedData->TimeZoneBias; 209 #else 210 do 211 { 212 Delta.HighPart = pUserSharedData->TimeZoneBias.High1Time; 213 Delta.LowPart = pUserSharedData->TimeZoneBias.LowPart; 214 } while (pUserSharedData->TimeZoneBias.High2Time != Delta.HighPart); 215 #endif 216 return Delta.QuadPart * -100; 217 } 218 -
trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
r52953 r53471 126 126 RtlSizeHeap ;;= _RtlSizeHeap@12 127 127 RtlSubAuthoritySid ;;= _RtlSubAuthoritySid@8 128 RtlQueryPerformanceCounter ;;= _RtlQueryPerformanceCounter@4 129 RtlGetSystemTimePrecise ;;= _RtlGetSystemTimePrecise@0 128 130 -
trunk/src/VBox/Runtime/r3/win/time-win.cpp
r52823 r53471 162 162 163 163 164 RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime)165 {166 FILETIME FileTime;167 SYSTEMTIME SysTime;168 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime))169 {170 if (SetSystemTime(&SysTime))171 return VINF_SUCCESS;172 }173 return RTErrConvertFromWin32(GetLastError());174 }175 176 177 164 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime) 178 165 { … … 200 187 } 201 188 202 203 RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)204 {205 /*206 * FileTimeToLocalFileTime does not do the right thing, so we'll have207 * to convert to system time and SystemTimeToTzSpecificLocalTime instead.208 */209 RTTIMESPEC LocalTime;210 SYSTEMTIME SystemTimeIn;211 FILETIME FileTime;212 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))213 {214 SYSTEMTIME SystemTimeOut;215 if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,216 &SystemTimeIn,217 &SystemTimeOut))218 {219 if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))220 {221 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);222 pTime = RTTimeExplode(pTime, &LocalTime);223 if (pTime)224 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;225 return pTime;226 }227 }228 }229 230 /*231 * The fallback is to use the current offset.232 * (A better fallback would be to use the offset of the same time of the year.)233 */234 LocalTime = *pTimeSpec;235 RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());236 pTime = RTTimeExplode(pTime, &LocalTime);237 if (pTime)238 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;239 return pTime;240 }241 -
trunk/src/VBox/Runtime/r3/win/time2-win.cpp
r53467 r53471 35 35 #include "internal/iprt.h" 36 36 37 #include <iprt/asm.h>38 37 #include <iprt/assert.h> 39 38 #include <iprt/err.h> 40 39 #include "internal/time.h" 41 40 42 /*43 * Note! The selected time source be the exact same one as we use in kernel land!44 */45 //#define USE_TICK_COUNT46 //#define USE_PERFORMANCE_COUNTER47 //# define USE_FILE_TIME48 //#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)49 # define USE_INTERRUPT_TIME50 //#else51 //# define USE_TICK_COUNT52 //#endif53 54 55 #ifdef USE_INTERRUPT_TIME56 57 typedef struct _MY_KSYSTEM_TIME58 {59 ULONG LowPart;60 LONG High1Time;61 LONG High2Time;62 } MY_KSYSTEM_TIME;63 64 typedef struct _MY_KUSER_SHARED_DATA65 {66 ULONG TickCountLowDeprecated;67 ULONG TickCountMultiplier;68 volatile MY_KSYSTEM_TIME InterruptTime;69 /* The rest is not relevant. */70 } MY_KUSER_SHARED_DATA, *PMY_KUSER_SHARED_DATA;71 72 #endif /* USE_INTERRUPT_TIME */73 74 75 DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)76 {77 #if defined USE_TICK_COUNT78 /*79 * This would work if it didn't flip over every 49 (or so) days.80 */81 return (uint64_t)GetTickCount() * RT_NS_1MS_64;82 83 #elif defined USE_PERFORMANCE_COUNTER84 /*85 * Slow and not derived from InterruptTime.86 */87 static LARGE_INTEGER llFreq;88 static unsigned uMult;89 if (!llFreq.QuadPart)90 {91 if (!QueryPerformanceFrequency(&llFreq))92 return (uint64_t)GetTickCount() * RT_NS_1MS_64;93 llFreq.QuadPart /= 1000;94 uMult = 1000000; /* no math genius, but this seemed to help avoiding floating point. */95 }96 97 LARGE_INTEGER ll;98 if (QueryPerformanceCounter(&ll))99 return (ll.QuadPart * uMult) / llFreq.QuadPart;100 return (uint64_t)GetTickCount() * RT_NS_1MS_64;101 102 #elif defined USE_FILE_TIME103 /*104 * This is SystemTime not InterruptTime.105 */106 uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */107 GetSystemTimeAsFileTime((LPFILETIME)&u64);108 return u64 * 100;109 110 #elif defined USE_INTERRUPT_TIME111 # if 0 /* ASSUME 0x7ffe0000 is set in stone */112 /*113 * This is exactly what we want, but we have to obtain it by non-official114 * means.115 */116 static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL;117 if (!s_pUserSharedData)118 {119 /** @todo find official way of getting this or some more clever120 * detection algorithm if necessary. The com debugger class121 * exports this too, windbg knows it too... */122 s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;123 }124 # endif125 PMY_KUSER_SHARED_DATA pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;126 127 /* use interrupt time */128 LARGE_INTEGER Time;129 do130 {131 Time.HighPart = pUserSharedData->InterruptTime.High1Time;132 Time.LowPart = pUserSharedData->InterruptTime.LowPart;133 } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);134 135 return (uint64_t)Time.QuadPart * 100;136 137 #else138 # error "Must select a method bright guy!"139 #endif140 }141 142 143 RTDECL(uint64_t) RTTimeSystemNanoTS(void)144 {145 return rtTimeGetSystemNanoTS();146 }147 148 149 RTDECL(uint64_t) RTTimeSystemMilliTS(void)150 {151 return rtTimeGetSystemNanoTS() / RT_NS_1MS;152 }153 154 155 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)156 {157 uint64_t u64;158 AssertCompile(sizeof(u64) == sizeof(FILETIME));159 GetSystemTimeAsFileTime((LPFILETIME)&u64);160 return RTTimeSpecSetNtTime(pTime, u64);161 }162 41 163 42 … … 172 51 } 173 52 return RTErrConvertFromWin32(GetLastError()); 174 }175 176 177 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)178 {179 uint64_t u64;180 AssertCompile(sizeof(u64) == sizeof(FILETIME));181 GetSystemTimeAsFileTime((LPFILETIME)&u64);182 uint64_t u64Local;183 if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))184 u64Local = u64;185 return RTTimeSpecSetNtTime(pTime, u64Local);186 }187 188 189 RTDECL(int64_t) RTTimeLocalDeltaNano(void)190 {191 /*192 * UTC = local + Tzi.Bias;193 * The bias is given in minutes.194 */195 TIME_ZONE_INFORMATION Tzi;196 Tzi.Bias = 0;197 if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)198 return -(int64_t)Tzi.Bias * 60 * RT_NS_1SEC_64;199 return 0;200 53 } 201 54
Note:
See TracChangeset
for help on using the changeset viewer.