VirtualBox

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

最後變更 在這個檔案從28459是 28459,由 vboxsync 提交於 15 年 前

time-win.cpp: Fixed 1000000 scale down bug in RTTimeSystemMilliTS (always) and RTTimeMilliTS when not in a VM process. Been causing trouble since r14735.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 6.9 KB
 
1/* $Id: time-win.cpp 28459 2010-04-19 12:49:13Z vboxsync $ */
2/** @file
3 * IPRT - Time, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#define LOG_GROUP RTLOGGROUP_TIME
36#include <Windows.h>
37
38#include <iprt/time.h>
39#include "internal/iprt.h"
40
41#include <iprt/asm.h>
42#include <iprt/assert.h>
43#include <iprt/err.h>
44#include "internal/time.h"
45
46#define USE_TICK_COUNT
47//#define USE_PERFORMANCE_COUNTER
48#if 0//defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
49# define USE_INTERRUPT_TIME
50#else
51//# define USE_FILE_TIME
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 = (MY_ 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
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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