VirtualBox

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

Last change on this file since 6749 was 6267, checked in by vboxsync, 17 years ago

We have to use InterruptTime like we do for the GIP. (GetSystemTimeAsFileTime isn't monotonic either.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1/* $Id: time-win.cpp 6267 2008-01-07 22:00:46Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Time, win32.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 <Windows.h>
33
34#include <iprt/time.h>
35#include <iprt/asm.h>
36#include <iprt/assert.h>
37#include "internal/time.h"
38
39#define USE_TICK_COUNT
40//#define USE_PERFORMANCE_COUNTER
41#if 0//defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
42# define USE_INTERRUPT_TIME
43#else
44//# define USE_FILE_TIME
45#endif
46
47
48#ifdef USE_INTERRUPT_TIME
49
50typedef struct _MY_KSYSTEM_TIME
51{
52 ULONG LowPart;
53 LONG High1Time;
54 LONG High2Time;
55} MY_KSYSTEM_TIME;
56
57typedef struct _MY_KUSER_SHARED_DATA
58{
59 ULONG TickCountLowDeprecated;
60 ULONG TickCountMultiplier;
61 volatile MY_KSYSTEM_TIME InterruptTime;
62 /* The rest is not relevant. */
63} MY_KUSER_SHARED_DATA, *PMY_KUSER_SHARED_DATA;
64
65#endif /* USE_INTERRUPT_TIME */
66
67
68DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
69{
70#if defined USE_TICK_COUNT
71 /*
72 * This would work if it didn't flip over every 49 (or so) days.
73 */
74 return (uint64_t)GetTickCount() * (uint64_t)1000000;
75
76#elif defined USE_PERFORMANCE_COUNTER
77 /*
78 * Slow and no derived from InterruptTime.
79 */
80 static LARGE_INTEGER llFreq;
81 static unsigned uMult;
82 if (!llFreq.QuadPart)
83 {
84 if (!QueryPerformanceFrequency(&llFreq))
85 return (uint64_t)GetTickCount() * (uint64_t)1000000;
86 llFreq.QuadPart /= 1000;
87 uMult = 1000000; /* no math genius, but this seemed to help avoiding floating point. */
88 }
89
90 LARGE_INTEGER ll;
91 if (QueryPerformanceCounter(&ll))
92 return (ll.QuadPart * uMult) / llFreq.QuadPart;
93 else
94 return (uint64_t)GetTickCount() * (uint64_t)1000000;
95
96#elif defined USE_FILE_TIME
97 /*
98 * This is SystemTime not InterruptTime.
99 */
100 uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */
101 GetSystemTimeAsFileTime((LPFILETIME)&u64);
102 return u64 * 100;
103
104#elif defined USE_INTERRUPT_TIME
105 /*
106 * This is exactly what we want, but we have to obtain it by non-official
107 * means.
108 */
109 static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL;
110 if (!s_pUserSharedData)
111 {
112 /** @todo find official way of getting this or some more clever
113 * detection algorithm if necessary. The com debugger class
114 * exports this too, windbg knows it too... */
115 s_pUserSharedData = (MY_ KUSER_SHARED_DATA *)(uintptr_t)0x7ffe0000;
116 }
117
118 /* use interrupt time */
119 LARGE_INTEGER Time;
120 do
121 {
122 Time.HighPart = s_pUserSharedData->InterruptTime.High1Time;
123 Time.LowPart = s_pUserSharedData->InterruptTime.LowPart;
124 } while (s_pUserSharedData->InterruptTime.High2Time != Time.HighPart);
125
126 return (uint64_t)Time.QuadPart * 100;
127
128#else
129# error "Must select a method bright guy!"
130#endif
131}
132
133
134/**
135 * Gets the current nanosecond timestamp.
136 *
137 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
138 * resolution or performance optimizations.
139 *
140 * @returns nanosecond timestamp.
141 */
142RTDECL(uint64_t) RTTimeSystemNanoTS(void)
143{
144 return rtTimeGetSystemNanoTS();
145}
146
147
148/**
149 * Gets the current millisecond timestamp.
150 *
151 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
152 * resolution or performance optimizations.
153 *
154 * @returns millisecond timestamp.
155 */
156RTDECL(uint64_t) RTTimeSystemMilliTS(void)
157{
158 return rtTimeGetSystemNanoTS();
159}
160
161
162/**
163 * Gets the current system time.
164 *
165 * @returns pTime.
166 * @param pTime Where to store the time.
167 */
168RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
169{
170 uint64_t u64;
171 AssertCompile(sizeof(u64) == sizeof(FILETIME));
172 GetSystemTimeAsFileTime((LPFILETIME)&u64);
173 return RTTimeSpecSetNtTime(pTime, u64);
174}
175
176
177/**
178 * Gets the current local system time.
179 *
180 * @returns pTime.
181 * @param pTime Where to store the local time.
182 */
183RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
184{
185 uint64_t u64;
186 AssertCompile(sizeof(u64) == sizeof(FILETIME));
187 GetSystemTimeAsFileTime((LPFILETIME)&u64);
188 uint64_t u64Local;
189 if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
190 u64Local = u64;
191 return RTTimeSpecSetNtTime(pTime, u64Local);
192}
193
194
195/**
196 * Gets the delta between UTC and local time.
197 *
198 * @code
199 * RTTIMESPEC LocalTime;
200 * RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano());
201 * @endcode
202 *
203 * @returns Returns the nanosecond delta between UTC and local time.
204 */
205RTDECL(int64_t) RTTimeLocalDeltaNano(void)
206{
207 /*
208 * UTC = local + Tzi.Bias;
209 * The bias is given in minutes.
210 */
211 TIME_ZONE_INFORMATION Tzi;
212 Tzi.Bias = 0;
213 if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
214 return -(int64_t)Tzi.Bias * 60*1000*1000*1000;
215 return 0;
216}
217
218
219/**
220 * Explodes a time spec to the localized timezone.
221 *
222 * @returns pTime.
223 * @param pTime Where to store the exploded time.
224 * @param pTimeSpec The time spec to exploded. (UTC)
225 */
226RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
227{
228 /*
229 * FileTimeToLocalFileTime does not do the right thing, so we'll have
230 * to convert to system time and SystemTimeToTzSpecificLocalTime instead.
231 */
232 RTTIMESPEC LocalTime;
233 SYSTEMTIME SystemTimeIn;
234 FILETIME FileTime;
235 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))
236 {
237 SYSTEMTIME SystemTimeOut;
238 if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,
239 &SystemTimeIn,
240 &SystemTimeOut))
241 {
242 if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))
243 {
244 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);
245 pTime = RTTimeExplode(pTime, &LocalTime);
246 if (pTime)
247 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
248 return pTime;
249 }
250 }
251 }
252
253 /*
254 * The fallback is to use the current offset.
255 * (A better fallback would be to use the offset of the same time of the year.)
256 */
257 LocalTime = *pTimeSpec;
258 RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
259 pTime = RTTimeExplode(pTime, &LocalTime);
260 if (pTime)
261 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
262 return pTime;
263}
264
Note: See TracBrowser for help on using the repository browser.

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