VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/time-win.cpp@ 93115

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.2 KB
Line 
1/* $Id: time-win.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT - Time, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_TIME
32#include <iprt/nt/nt-and-windows.h>
33
34#include <iprt/time.h>
35#include "internal/iprt.h"
36
37#include <iprt/asm.h>
38#include <iprt/assert.h>
39#include <iprt/errcore.h>
40#include "internal/time.h"
41#include "internal-r3-win.h"
42
43/*
44 * Note! The selected time source be the exact same one as we use in kernel land!
45 */
46//#define USE_TICK_COUNT
47//#define USE_PERFORMANCE_COUNTER
48//# define USE_FILE_TIME
49//#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
50# define USE_INTERRUPT_TIME
51//#else
52//# define USE_TICK_COUNT
53//#endif
54
55
56
57DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
58{
59#if defined USE_TICK_COUNT
60 /*
61 * This would work if it didn't flip over every 49 (or so) days.
62 */
63 return (uint64_t)GetTickCount() * RT_NS_1MS_64;
64
65#elif defined USE_PERFORMANCE_COUNTER
66 /*
67 * Slow and not derived from InterruptTime.
68 */
69 static LARGE_INTEGER llFreq;
70 static unsigned uMult;
71 if (!llFreq.QuadPart)
72 {
73 if (!QueryPerformanceFrequency(&llFreq))
74 return (uint64_t)GetTickCount() * RT_NS_1MS_64;
75 llFreq.QuadPart /= 1000;
76 uMult = 1000000; /* no math genius, but this seemed to help avoiding floating point. */
77 }
78
79 LARGE_INTEGER ll;
80 if (QueryPerformanceCounter(&ll))
81 return (ll.QuadPart * uMult) / llFreq.QuadPart;
82 return (uint64_t)GetTickCount() * RT_NS_1MS_64;
83
84#elif defined USE_FILE_TIME
85 /*
86 * This is SystemTime not InterruptTime.
87 */
88 uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */
89 GetSystemTimeAsFileTime((LPFILETIME)&u64);
90 return u64 * 100;
91
92#elif defined USE_INTERRUPT_TIME
93 /*
94 * Use interrupt time if we can (not possible on NT 3.1).
95 * Note! We cannot entirely depend on g_enmWinVer here as we're likely to
96 * get called before IPRT is initialized. Ditto g_hModNtDll.
97 */
98 static PFNRTLGETINTERRUPTTIMEPRECISE s_pfnRtlGetInterruptTimePrecise = NULL;
99 static int volatile s_iCanUseUserSharedData = -1;
100 int iCanUseUserSharedData = s_iCanUseUserSharedData;
101 if (iCanUseUserSharedData != -1)
102 { /* likely */ }
103 else
104 {
105 /* We may be called before g_enmWinVer has been initialized. */
106 if (g_enmWinVer != kRTWinOSType_UNKNOWN)
107 iCanUseUserSharedData = g_enmWinVer > kRTWinOSType_NT310;
108 else
109 {
110 DWORD dwVer = GetVersion();
111 iCanUseUserSharedData = (dwVer & 0xff) != 3 || ((dwVer >> 8) & 0xff) >= 50;
112 }
113 if (iCanUseUserSharedData != 0)
114 {
115 FARPROC pfn = GetProcAddress(g_hModNtDll ? g_hModNtDll : GetModuleHandleW(L"ntdll"), "RtlGetInterruptTimePrecise");
116 if (pfn != NULL)
117 {
118 ASMAtomicWritePtr(&s_pfnRtlGetInterruptTimePrecise, pfn);
119 iCanUseUserSharedData = 42;
120 }
121 }
122 s_iCanUseUserSharedData = iCanUseUserSharedData;
123 }
124
125 if (iCanUseUserSharedData != 0)
126 {
127 LARGE_INTEGER Time;
128 if (iCanUseUserSharedData == 42)
129 {
130 uint64_t iIgnored;
131 Time.QuadPart = s_pfnRtlGetInterruptTimePrecise(&iIgnored);
132 }
133 else
134 {
135 PKUSER_SHARED_DATA pUserSharedData = (PKUSER_SHARED_DATA)MM_SHARED_USER_DATA_VA;
136 do
137 {
138 Time.HighPart = pUserSharedData->InterruptTime.High1Time;
139 Time.LowPart = pUserSharedData->InterruptTime.LowPart;
140 } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
141 }
142
143 return (uint64_t)Time.QuadPart * 100;
144 }
145
146 return (uint64_t)GetTickCount() * RT_NS_1MS_64;
147
148#else
149# error "Must select a method bright guy!"
150#endif
151}
152
153
154RTDECL(uint64_t) RTTimeSystemNanoTS(void)
155{
156 return rtTimeGetSystemNanoTS();
157}
158
159
160RTDECL(uint64_t) RTTimeSystemMilliTS(void)
161{
162 return rtTimeGetSystemNanoTS() / RT_NS_1MS;
163}
164
165
166RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
167{
168 uint64_t u64;
169 AssertCompile(sizeof(u64) == sizeof(FILETIME));
170 GetSystemTimeAsFileTime((LPFILETIME)&u64);
171 return RTTimeSpecSetNtTime(pTime, u64);
172}
173
174
175RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
176{
177 uint64_t u64;
178 AssertCompile(sizeof(u64) == sizeof(FILETIME));
179 GetSystemTimeAsFileTime((LPFILETIME)&u64);
180 uint64_t u64Local;
181 if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
182 u64Local = u64;
183 return RTTimeSpecSetNtTime(pTime, u64Local);
184}
185
186
187RTDECL(int64_t) RTTimeLocalDeltaNano(void)
188{
189 /*
190 * UTC = local + Tzi.Bias;
191 * The bias is given in minutes.
192 */
193 TIME_ZONE_INFORMATION Tzi;
194 Tzi.Bias = 0;
195 if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
196 return -(int64_t)Tzi.Bias * 60 * RT_NS_1SEC_64;
197 return 0;
198}
199
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette