VirtualBox

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

Last change on this file since 46223 was 46223, checked in by vboxsync, 12 years ago

Must use same time source in user and kernel land otherwise we might get huge deltas between GIP time and system time.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.9 KB
Line 
1/* $Id: time-win.cpp 46223 2013-05-22 17:18:47Z vboxsync $ */
2/** @file
3 * IPRT - Time, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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 <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/err.h>
40#include "internal/time.h"
41
42/*
43 * Note! The selected time source be the exact same one as we use in kernel land!
44 */
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
57typedef struct _MY_KSYSTEM_TIME
58{
59 ULONG LowPart;
60 LONG High1Time;
61 LONG High2Time;
62} MY_KSYSTEM_TIME;
63
64typedef 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
75DECLINLINE(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() * (uint64_t)1000000;
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() * (uint64_t)1000000;
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() * (uint64_t)1000000;
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 /*
112 * This is exactly what we want, but we have to obtain it by non-official
113 * means.
114 */
115 static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL;
116 if (!s_pUserSharedData)
117 {
118 /** @todo find official way of getting this or some more clever
119 * detection algorithm if necessary. The com debugger class
120 * exports this too, windbg knows it too... */
121 s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
122 }
123
124 /* use interrupt time */
125 LARGE_INTEGER Time;
126 do
127 {
128 Time.HighPart = s_pUserSharedData->InterruptTime.High1Time;
129 Time.LowPart = s_pUserSharedData->InterruptTime.LowPart;
130 } while (s_pUserSharedData->InterruptTime.High2Time != Time.HighPart);
131
132 return (uint64_t)Time.QuadPart * 100;
133
134#else
135# error "Must select a method bright guy!"
136#endif
137}
138
139
140RTDECL(uint64_t) RTTimeSystemNanoTS(void)
141{
142 return rtTimeGetSystemNanoTS();
143}
144
145
146RTDECL(uint64_t) RTTimeSystemMilliTS(void)
147{
148 return rtTimeGetSystemNanoTS() / 1000000;
149}
150
151
152RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
153{
154 uint64_t u64;
155 AssertCompile(sizeof(u64) == sizeof(FILETIME));
156 GetSystemTimeAsFileTime((LPFILETIME)&u64);
157 return RTTimeSpecSetNtTime(pTime, u64);
158}
159
160
161RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime)
162{
163 FILETIME FileTime;
164 SYSTEMTIME SysTime;
165 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime))
166 {
167 if (SetSystemTime(&SysTime))
168 return VINF_SUCCESS;
169 }
170 return RTErrConvertFromWin32(GetLastError());
171}
172
173
174RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
175{
176 uint64_t u64;
177 AssertCompile(sizeof(u64) == sizeof(FILETIME));
178 GetSystemTimeAsFileTime((LPFILETIME)&u64);
179 uint64_t u64Local;
180 if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
181 u64Local = u64;
182 return RTTimeSpecSetNtTime(pTime, u64Local);
183}
184
185
186RTDECL(int64_t) RTTimeLocalDeltaNano(void)
187{
188 /*
189 * UTC = local + Tzi.Bias;
190 * The bias is given in minutes.
191 */
192 TIME_ZONE_INFORMATION Tzi;
193 Tzi.Bias = 0;
194 if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
195 return -(int64_t)Tzi.Bias * 60*1000*1000*1000;
196 return 0;
197}
198
199
200RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
201{
202 /*
203 * FileTimeToLocalFileTime does not do the right thing, so we'll have
204 * to convert to system time and SystemTimeToTzSpecificLocalTime instead.
205 */
206 RTTIMESPEC LocalTime;
207 SYSTEMTIME SystemTimeIn;
208 FILETIME FileTime;
209 if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))
210 {
211 SYSTEMTIME SystemTimeOut;
212 if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,
213 &SystemTimeIn,
214 &SystemTimeOut))
215 {
216 if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))
217 {
218 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);
219 pTime = RTTimeExplode(pTime, &LocalTime);
220 if (pTime)
221 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
222 return pTime;
223 }
224 }
225 }
226
227 /*
228 * The fallback is to use the current offset.
229 * (A better fallback would be to use the offset of the same time of the year.)
230 */
231 LocalTime = *pTimeSpec;
232 RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
233 pTime = RTTimeExplode(pTime, &LocalTime);
234 if (pTime)
235 pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
236 return pTime;
237}
238
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