VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/time-r0drv-nt.cpp

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.3 KB
Line 
1/* $Id: time-r0drv-nt.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Time, Ring-0 Driver, Nt.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_TIME
42#include "the-nt-kernel.h"
43#include "internal-r0drv-nt.h"
44#include <iprt/time.h>
45
46
47/*
48 * The KeQueryTickCount macro isn't compatible with NT 3.1, use the
49 * exported KPI instead.
50 */
51#ifdef RT_ARCH_X86
52# undef KeQueryTickCount
53extern "C" NTKERNELAPI void NTAPI KeQueryTickCount(PLARGE_INTEGER);
54#endif
55
56
57DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
58{
59 /*
60 * Note! The time source we use here must be exactly the same as in
61 * the ring-3 code!
62 *
63 * Using interrupt time is the simplest and requires the least calculation.
64 * It is also accounting for suspended time. Unfortuantely, there is no
65 * ring-3 for reading it... but that won't stop us.
66 *
67 * Using the tick count is problematic in ring-3 on older windows version
68 * as we can only get the 32-bit tick value, i.e. we'll roll over sooner or
69 * later.
70 */
71#if 1
72 /* Interrupt time. */
73 LARGE_INTEGER InterruptTime;
74 if (g_pfnrtKeQueryInterruptTimePrecise)
75 {
76 ULONG64 QpcTsIgnored;
77 InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTimePrecise(&QpcTsIgnored);
78 }
79# ifdef RT_ARCH_X86
80 else if (g_pfnrtKeQueryInterruptTime) /* W2K+ */
81 InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTime();
82 else if (g_uRtNtVersion >= RTNT_MAKE_VERSION(3, 50))
83 {
84 /* NT 3.50 and later, also pre-init: Use the user shared data. */
85 do
86 {
87 InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time;
88 InterruptTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart;
89 } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart);
90 }
91 else
92 {
93 /*
94 * There is no KUSER_SHARED_DATA structure on NT 3.1, so we have no choice
95 * but to use the tick count. We must also avoid the KeQueryTickCount macro
96 * in the WDK, since NT 3.1 doesn't have the KeTickCount data export either (see above).
97 */
98 static ULONG volatile s_uTimeIncrement = 0;
99 ULONG uTimeIncrement = s_uTimeIncrement;
100 if (!uTimeIncrement)
101 {
102 uTimeIncrement = KeQueryTimeIncrement();
103 Assert(uTimeIncrement != 0);
104 Assert(uTimeIncrement * 100 / 100 == uTimeIncrement);
105 uTimeIncrement *= 100;
106 s_uTimeIncrement = uTimeIncrement;
107 }
108
109 KeQueryTickCount(&InterruptTime);
110 return (uint64_t)InterruptTime.QuadPart * uTimeIncrement;
111 }
112# else
113 else
114 InterruptTime.QuadPart = KeQueryInterruptTime(); /* Macro on AMD64. */
115# endif
116 return (uint64_t)InterruptTime.QuadPart * 100;
117#else
118 /* Tick count. Works all the way back to NT 3.1 with #undef above. */
119 LARGE_INTEGER Tick;
120 KeQueryTickCount(&Tick);
121 return (uint64_t)Tick.QuadPart * KeQueryTimeIncrement() * 100;
122#endif
123}
124
125
126RTDECL(uint64_t) RTTimeNanoTS(void)
127{
128 return rtTimeGetSystemNanoTS();
129}
130
131
132RTDECL(uint64_t) RTTimeMilliTS(void)
133{
134 return rtTimeGetSystemNanoTS() / RT_NS_1MS;
135}
136
137
138RTDECL(uint64_t) RTTimeSystemNanoTS(void)
139{
140 return rtTimeGetSystemNanoTS();
141}
142
143
144RTDECL(uint64_t) RTTimeSystemMilliTS(void)
145{
146 return rtTimeGetSystemNanoTS() / RT_NS_1MS;
147}
148
149
150RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
151{
152 LARGE_INTEGER SystemTime;
153 if (g_pfnrtKeQuerySystemTimePrecise)
154 g_pfnrtKeQuerySystemTimePrecise(&SystemTime);
155 else
156 KeQuerySystemTime(&SystemTime); /* Macro on AMD64, export on X86. */
157 return RTTimeSpecSetNtTime(pTime, SystemTime.QuadPart);
158}
159
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use