~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/r3/win32/time-win32.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: time-win32.cpp 4071 2007-08-07 17:07:59Z 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 as published by the Free Software Foundation,
 
13
 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
 
14
 * distribution. VirtualBox OSE is distributed in the hope that it will
 
15
 * be useful, but WITHOUT ANY WARRANTY of any kind.
 
16
 */
 
17
 
 
18
 
 
19
/*******************************************************************************
 
20
*   Header Files                                                               *
 
21
*******************************************************************************/
 
22
#define LOG_GROUP RTLOGGROUP_TIME
 
23
//#define USE_TICK_COUNT
 
24
//#define USE_PERFORMANCE_COUNTER
 
25
#define USE_FILE_TIME
 
26
//#define USE_INTERRUPT_TIME
 
27
#ifndef USE_INTERRUPT_TIME
 
28
# include <Windows.h>
 
29
#else
 
30
# define _X86_
 
31
  extern "C" {
 
32
# include <ntddk.h>
 
33
  }
 
34
# undef PAGE_SIZE
 
35
# undef PAGE_SHIFT
 
36
#endif
 
37
 
 
38
#include <iprt/time.h>
 
39
#include <iprt/asm.h>
 
40
#include <iprt/assert.h>
 
41
#include "internal/time.h"
 
42
 
 
43
 
 
44
DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
 
45
{
 
46
#if defined USE_TICK_COUNT
 
47
    return (uint64_t)GetTickCount() * (uint64_t)1000000;
 
48
 
 
49
#elif defined USE_PERFORMANCE_COUNTER
 
50
    static LARGE_INTEGER    llFreq;
 
51
    static unsigned         uMult;
 
52
    if (!llFreq.QuadPart)
 
53
    {
 
54
        if (!QueryPerformanceFrequency(&llFreq))
 
55
            return (uint64_t)GetTickCount() * (uint64_t)1000000;
 
56
        llFreq.QuadPart /=    1000;
 
57
        uMult            = 1000000;     /* no math genious, but this seemed to help avoiding floating point. */
 
58
    }
 
59
 
 
60
    LARGE_INTEGER   ll;
 
61
    if (QueryPerformanceCounter(&ll))
 
62
        return (ll.QuadPart * uMult) / llFreq.QuadPart;
 
63
    else
 
64
        return (uint64_t)GetTickCount() * (uint64_t)1000000;
 
65
 
 
66
#elif defined USE_FILE_TIME
 
67
    uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */
 
68
    GetSystemTimeAsFileTime((LPFILETIME)&u64);
 
69
    return u64 * 100;
 
70
 
 
71
#elif defined USE_INTERRUPT_TIME
 
72
 
 
73
    /* HACK! HACK! HACK! HACK! HACK! HACK! */
 
74
    /* HACK! HACK! HACK! HACK! HACK! HACK! */
 
75
    /* HACK! HACK! HACK! HACK! HACK! HACK! */
 
76
# error "don't use this in production"
 
77
 
 
78
    static const KUSER_SHARED_DATA *s_pUserSharedData = NULL;
 
79
    if (!s_pUserSharedData)
 
80
    {
 
81
        /** @todo clever detection algorithm.
 
82
         * The com debugger class exports this too, windbg knows it too... */
 
83
        s_pUserSharedData = (const KUSER_SHARED_DATA *)0x7ffe0000;
 
84
    }
 
85
 
 
86
    /* use interrupt time */
 
87
    LARGE_INTEGER Time;
 
88
    do
 
89
    {
 
90
        Time.HighPart = s_pUserSharedData->InterruptTime.High1Time;
 
91
        Time.LowPart = s_pUserSharedData->InterruptTime.LowPart;
 
92
    } while (s_pUserSharedData->InterruptTime.High2Time != Time.HighPart);
 
93
 
 
94
    return (uint64_t)Time.QuadPart * 100;
 
95
 
 
96
#else
 
97
# error "Must select a method bright guy!"
 
98
#endif
 
99
}
 
100
 
 
101
 
 
102
/**
 
103
 * Gets the current nanosecond timestamp.
 
104
 *
 
105
 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
 
106
 * resolution or performance optimizations.
 
107
 *
 
108
 * @returns nanosecond timestamp.
 
109
 */
 
110
RTDECL(uint64_t) RTTimeSystemNanoTS(void)
 
111
{
 
112
    return rtTimeGetSystemNanoTS();
 
113
}
 
114
 
 
115
 
 
116
/**
 
117
 * Gets the current millisecond timestamp.
 
118
 *
 
119
 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
 
120
 * resolution or performance optimizations.
 
121
 *
 
122
 * @returns millisecond timestamp.
 
123
 */
 
124
RTDECL(uint64_t) RTTimeSystemMilliTS(void)
 
125
{
 
126
    return rtTimeGetSystemNanoTS();
 
127
}
 
128
 
 
129
 
 
130
/**
 
131
 * Gets the current system time.
 
132
 *
 
133
 * @returns pTime.
 
134
 * @param   pTime   Where to store the time.
 
135
 */
 
136
RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
 
137
{
 
138
    uint64_t u64;
 
139
    AssertCompile(sizeof(u64) == sizeof(FILETIME));
 
140
    GetSystemTimeAsFileTime((LPFILETIME)&u64);
 
141
    return RTTimeSpecSetNtTime(pTime, u64);
 
142
}
 
143
 
 
144
 
 
145
/**
 
146
 * Gets the current local system time.
 
147
 *
 
148
 * @returns pTime.
 
149
 * @param   pTime   Where to store the local time.
 
150
 */
 
151
RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
 
152
{
 
153
    uint64_t u64;
 
154
    AssertCompile(sizeof(u64) == sizeof(FILETIME));
 
155
    GetSystemTimeAsFileTime((LPFILETIME)&u64);
 
156
    uint64_t u64Local;
 
157
    if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
 
158
        u64Local = u64;
 
159
    return RTTimeSpecSetNtTime(pTime, u64Local);
 
160
}
 
161
 
 
162
 
 
163
/**
 
164
 * Gets the delta between UTC and local time.
 
165
 *
 
166
 * @code
 
167
 *      RTTIMESPEC LocalTime;
 
168
 *      RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano());
 
169
 * @endcode
 
170
 *
 
171
 * @returns Returns the nanosecond delta between UTC and local time.
 
172
 */
 
173
RTDECL(int64_t) RTTimeLocalDeltaNano(void)
 
174
{
 
175
    /*
 
176
     * UTC = local + Tzi.Bias;
 
177
     * The bias is given in minutes.
 
178
     */
 
179
    TIME_ZONE_INFORMATION Tzi;
 
180
    Tzi.Bias = 0;
 
181
    if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
 
182
        return -(int64_t)Tzi.Bias * 60*1000*1000*1000;
 
183
    return 0;
 
184
}
 
185
 
 
186
 
 
187
/**
 
188
 * Explodes a time spec to the localized timezone.
 
189
 *
 
190
 * @returns pTime.
 
191
 * @param   pTime       Where to store the exploded time.
 
192
 * @param   pTimeSpec   The time spec to exploded. (UTC)
 
193
 */
 
194
RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
 
195
{
 
196
    /*
 
197
     * FileTimeToLocalFileTime does not do the right thing, so we'll have
 
198
     * to convert to system time and SystemTimeToTzSpecificLocalTime instead.
 
199
     */
 
200
    RTTIMESPEC LocalTime;
 
201
    SYSTEMTIME SystemTimeIn;
 
202
    FILETIME FileTime;
 
203
    if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))
 
204
    {
 
205
        SYSTEMTIME SystemTimeOut;
 
206
        if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,
 
207
                                            &SystemTimeIn,
 
208
                                            &SystemTimeOut))
 
209
        {
 
210
            if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))
 
211
            {
 
212
                RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);
 
213
                pTime = RTTimeExplode(pTime, &LocalTime);
 
214
                if (pTime)
 
215
                    pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
 
216
                return pTime;
 
217
            }
 
218
        }
 
219
    }
 
220
 
 
221
    /*
 
222
     * The fallback is to use the current offset.
 
223
     * (A better fallback would be to use the offset of the same time of the year.)
 
224
     */
 
225
    LocalTime = *pTimeSpec;
 
226
    RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
 
227
    pTime = RTTimeExplode(pTime, &LocalTime);
 
228
    if (pTime)
 
229
        pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
 
230
    return pTime;
 
231
}
 
232