VirtualBox

Changeset 53471 in vbox for trunk


Ignore:
Timestamp:
Dec 6, 2014 3:57:52 AM (10 years ago)
Author:
vboxsync
Message:

IPRT/r3/nt&win: Precision time APIs for NT (not enabled).

Location:
trunk
Files:
4 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/nt/nt.h

    r53445 r53471  
    7171#define PEB_LDR_DATA               Incomplete_PEB_LDR_DATA
    7272#define PPEB_LDR_DATA              Incomplete_PPEB_LDR_DATA
     73#define _KUSER_SHARED_DATA         Incomplete__KUSER_SHARED_DATA
     74#define KUSER_SHARED_DATA          Incomplete_KUSER_SHARED_DATA
     75#define PKUSER_SHARED_DATA         Incomplete_PKUSER_SHARED_DATA
    7376
    7477
     
    208211#undef PEB_LDR_DATA
    209212#undef PPEB_LDR_DATA
     213#undef _KUSER_SHARED_DATA
     214#undef KUSER_SHARED_DATA
     215#undef PKUSER_SHARED_DATA
    210216
    211217
     
    438444typedef XSTATE_CONFIGURATION *PXSTATE_CONFIGURATION;
    439445# endif
     446#endif /* IPRT_NT_USE_WINTERNL */
    440447
    441448typedef struct _KUSER_SHARED_DATA
     
    559566} KUSER_SHARED_DATA;
    560567typedef KUSER_SHARED_DATA *PKUSER_SHARED_DATA;
    561 #endif /* IPRT_NT_USE_WINTERNL */
    562568AssertCompileMemberOffset(KUSER_SHARED_DATA, InterruptTime,             0x008);
    563569AssertCompileMemberOffset(KUSER_SHARED_DATA, SystemTime,                0x014);
     
    568574AssertCompileMemberOffset(KUSER_SHARED_DATA, Cookie,                    0x330);
    569575AssertCompileMemberOffset(KUSER_SHARED_DATA, ImageFileExecutionOptions, 0x3a0);
    570 #ifdef IPRT_NT_USE_WINTERNL
    571576AssertCompileMemberOffset(KUSER_SHARED_DATA, XState,                    0x3d8);
    572 #endif /* IPRT_NT_USE_WINTERNL */
     577/** @def MM_SHARED_USER_DATA_VA
     578 * Read only userland mapping of KUSER_SHARED_DATA. */
     579#ifndef MM_SHARED_USER_DATA_VA
     580# if ARCH_BITS == 32
     581#  define MM_SHARED_USER_DATA_VA        UINT32_C(0x7ffe0000)
     582# elif ARCH_BITS == 64
     583#  define MM_SHARED_USER_DATA_VA        UINT64_C(0x7ffe0000)
     584# else
     585#  error "Unsupported/undefined ARCH_BITS value."
     586# endif
     587#endif
     588/** @def KI_USER_SHARED_DATA
     589 * Read write kernel mapping of KUSER_SHARED_DATA. */
     590#ifndef KI_USER_SHARED_DATA
     591# ifdef RT_ARCH_X86
     592#  define KI_USER_SHARED_DATA           UINT32_C(0xffdf0000)
     593# elif defined(RT_ARCH_AMD64)
     594#  define KI_USER_SHARED_DATA           UINT64_C(0xfffff78000000000)
     595# else
     596#  error "PORT ME - KI_USER_SHARED_DATA"
     597# endif
     598#endif
    573599/** @} */
    574600
     
    22992325NTSYSAPI VOID NTAPI     RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS rcNt);
    23002326NTSYSAPI VOID NTAPI     RtlRestoreLastWin32Error(ULONG uError);
     2327NTSYSAPI BOOLEAN NTAPI  RtlQueryPerformanceCounter(PLARGE_INTEGER);
     2328NTSYSAPI uint64_t NTAPI RtlGetSystemTimePrecise(VOID);
     2329typedef uint64_t (NTAPI * PFNRTLGETSYSTEMTIMEPRECISE)(VOID);
    23012330
    23022331RT_C_DECLS_END
  • trunk/src/VBox/Runtime/Makefile.kmk

    r53278 r53471  
    752752        r3/win/thread-win.cpp \
    753753        r3/win/thread2-win.cpp \
    754         r3/win/time-win.cpp \
     754        $(if-expr 1,r3/win/time-win.cpp,r3/nt/time-nt.cpp) \
     755        r3/win/time2-win.cpp \
    755756        r3/win/timer-win.cpp \
    756757        r3/win/tls-win.cpp \
  • trunk/src/VBox/Runtime/r3/nt/time-nt.cpp

    r53467 r53471  
    3030*******************************************************************************/
    3131#define LOG_GROUP RTLOGGROUP_TIME
    32 #include <Windows.h>
     32#include "internal-r3-nt.h"
    3333
    3434#include <iprt/time.h>
    35 #include "internal/iprt.h"
    36 
    3735#include <iprt/asm.h>
    3836#include <iprt/assert.h>
    3937#include <iprt/err.h>
     38#include <iprt/ldr.h>
     39#include <iprt/uint128.h>
    4040#include "internal/time.h"
    4141
    42 /*
    43  * Note! The selected time source be the exact same one as we use in kernel land!
     42
     43/*******************************************************************************
     44*   Global Variables                                                           *
     45*******************************************************************************/
     46/** Whether we've tried to resolve g_pfnRtlGetSystemTimePrecise or not. */
     47static bool                         g_fInitialized = false;
     48/** Pointer to RtlGetSystemTimePrecise, added in 6.2 (windows 8).   */
     49static PFNRTLGETSYSTEMTIMEPRECISE   g_pfnRtlGetSystemTimePrecise = NULL;
     50
     51
     52/**
     53 * Initializes globals.
    4454 */
    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 
    57 typedef struct _MY_KSYSTEM_TIME
    58 {
    59     ULONG LowPart;
    60     LONG High1Time;
    61     LONG High2Time;
    62 } MY_KSYSTEM_TIME;
    63 
    64 typedef 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 
    75 DECLINLINE(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() * RT_NS_1MS_64;
    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() * RT_NS_1MS_64;
    93         llFreq.QuadPart /=    1000;
    94         uMult            = 1000000;     /* no math genius, but this seemed to help avoiding floating point. */
     55static void rtTimeNtInitialize(void)
     56{
     57    /*
     58     * Make sure we don't recurse here when calling into RTLdr.
     59     */
     60    if (ASMAtomicCmpXchgBool(&g_fInitialized, true, false))
     61    {
     62        void *pvFunc = RTLdrGetSystemSymbol("ntdll.dll", "RtlGetSystemTimePrecise");
     63        if (pvFunc)
     64            ASMAtomicWritePtr((void * volatile *)&g_pfnRtlGetSystemTimePrecise, pvFunc);
     65        ASMCompilerBarrier();
    9566    }
    96 
    97     LARGE_INTEGER   ll;
    98     if (QueryPerformanceCounter(&ll))
    99         return (ll.QuadPart * uMult) / llFreq.QuadPart;
    100     return (uint64_t)GetTickCount() * RT_NS_1MS_64;
    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 # if 0 /* ASSUME 0x7ffe0000 is set in stone */
    112     /*
    113      * This is exactly what we want, but we have to obtain it by non-official
    114      * means.
    115      */
    116     static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL;
    117     if (!s_pUserSharedData)
    118     {
    119         /** @todo find official way of getting this or some more clever
    120          * detection algorithm if necessary. The com debugger class
    121          * exports this too, windbg knows it too... */
    122         s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
    123     }
    124 # endif
    125     PMY_KUSER_SHARED_DATA pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
    126 
    127     /* use interrupt time */
    128     LARGE_INTEGER Time;
    129     do
    130     {
    131         Time.HighPart = pUserSharedData->InterruptTime.High1Time;
    132         Time.LowPart  = pUserSharedData->InterruptTime.LowPart;
    133     } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
    134 
    135     return (uint64_t)Time.QuadPart * 100;
    136 
    137 #else
    138 # error "Must select a method bright guy!"
    139 #endif
    140 }
    141 
    142 
    143 RTDECL(uint64_t) RTTimeSystemNanoTS(void)
    144 {
    145     return rtTimeGetSystemNanoTS();
    146 }
    147 
    148 
    149 RTDECL(uint64_t) RTTimeSystemMilliTS(void)
    150 {
    151     return rtTimeGetSystemNanoTS() / RT_NS_1MS;
    152 }
    153 
    154 
    155 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
    156 {
    157     uint64_t u64;
    158     AssertCompile(sizeof(u64) == sizeof(FILETIME));
    159     GetSystemTimeAsFileTime((LPFILETIME)&u64);
    160     return RTTimeSpecSetNtTime(pTime, u64);
    161 }
    162 
    163 
    164 RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime)
    165 {
    166     FILETIME    FileTime;
    167     SYSTEMTIME  SysTime;
    168     if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime))
    169     {
    170         if (SetSystemTime(&SysTime))
    171             return VINF_SUCCESS;
    172     }
    173     return RTErrConvertFromWin32(GetLastError());
    174 }
    175 
    176 
    177 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
    178 {
    179     uint64_t u64;
    180     AssertCompile(sizeof(u64) == sizeof(FILETIME));
    181     GetSystemTimeAsFileTime((LPFILETIME)&u64);
    182     uint64_t u64Local;
    183     if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
    184         u64Local = u64;
    185     return RTTimeSpecSetNtTime(pTime, u64Local);
    186 }
    187 
    188 
    189 RTDECL(int64_t) RTTimeLocalDeltaNano(void)
    190 {
    191     /*
    192      * UTC = local + Tzi.Bias;
    193      * The bias is given in minutes.
    194      */
    195     TIME_ZONE_INFORMATION Tzi;
    196     Tzi.Bias = 0;
    197     if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
    198         return -(int64_t)Tzi.Bias * 60 * RT_NS_1SEC_64;
    199     return 0;
    200 }
    201 
    202 
    203 RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
    204 {
    205     /*
    206      * FileTimeToLocalFileTime does not do the right thing, so we'll have
    207      * to convert to system time and SystemTimeToTzSpecificLocalTime instead.
    208      */
    209     RTTIMESPEC LocalTime;
    210     SYSTEMTIME SystemTimeIn;
    211     FILETIME FileTime;
    212     if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))
    213     {
    214         SYSTEMTIME SystemTimeOut;
    215         if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,
    216                                             &SystemTimeIn,
    217                                             &SystemTimeOut))
     67}
     68
     69
     70static uint64_t rtTimeGetSystemNanoTS(void)
     71{
     72    if (RT_UNLIKELY(!g_fInitialized))
     73        rtTimeNtInitialize();
     74
     75    KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
     76
     77#if 1
     78    /*
     79     * If there is precise time, get the precise system time and calculate the
     80     * interrupt time from it.  (Microsoft doesn't expose interrupt time to user
     81     * application, which is very unfortunate as there are a lot place where
     82     * monotonic time is applicable but developer is "forced" to use wall clock.)
     83     */
     84    if (g_pfnRtlGetSystemTimePrecise)
     85    {
     86        for (;;)
    21887        {
    219             if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))
     88            uint64_t uUpdateLockBefore;
     89            while ((uUpdateLockBefore = pUserSharedData->TimeUpdateLock) & 1)
     90                ASMNopPause();
     91
     92            uint64_t        uInterruptTime                  = *(uint64_t volatile *)&pUserSharedData->InterruptTime;
     93            uint64_t        uBaselineInterruptTimeQpc       = pUserSharedData->BaselineInterruptTimeQpc;
     94            uint64_t        uQpcInterruptTimeIncrement      = pUserSharedData->QpcInterruptTimeIncrement;
     95            uint8_t         uQpcInterruptTimeIncrementShift = pUserSharedData->QpcInterruptTimeIncrementShift;
     96            LARGE_INTEGER   QpcValue;
     97            RtlQueryPerformanceCounter(&QpcValue);
     98
     99            if (pUserSharedData->TimeUpdateLock == uUpdateLockBefore)
    220100            {
    221                 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);
    222                 pTime = RTTimeExplode(pTime, &LocalTime);
    223                 if (pTime)
    224                     pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
    225                 return pTime;
     101                uint64_t uQpcValue = QpcValue.QuadPart;
     102                if (uQpcValue <= uBaselineInterruptTimeQpc)
     103                    return uInterruptTime * 100;
     104
     105                /* Calc QPC delta since base line. */
     106                uQpcValue -= uBaselineInterruptTimeQpc;
     107                uQpcValue--;
     108
     109                /* Multiply by 10 million. */
     110                uQpcValue *= UINT32_C(10000000);
     111
     112                /* Multiply by QPC interrupt time increment value. */
     113                RTUINT128U Tmp128;
     114                RTUInt128MulU64ByU64(&Tmp128, uQpcValue, uQpcInterruptTimeIncrement);
     115
     116                /* Shift the upper 64 bits by the increment shift factor. */
     117                uint64_t uResult = Tmp128.s.Hi >> uQpcInterruptTimeIncrementShift;
     118
     119                /* Add to base interrupt time value. */
     120                uResult += uInterruptTime;
     121
     122                /* Convert from NT unit to nano seconds. */
     123                return uResult * 100;
    226124            }
     125
     126            ASMNopPause();
    227127        }
    228128    }
    229 
    230     /*
    231      * The fallback is to use the current offset.
    232      * (A better fallback would be to use the offset of the same time of the year.)
    233      */
    234     LocalTime = *pTimeSpec;
    235     RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
    236     pTime = RTTimeExplode(pTime, &LocalTime);
    237     if (pTime)
    238         pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
    239     return pTime;
    240 }
    241 
     129#endif
     130
     131    /*
     132     * Just read interrupt time.
     133     */
     134#if ARCH_BITS >= 64
     135    uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->InterruptTime; /* This is what KeQueryInterruptTime does. */
     136    uRet *= 100;
     137    return uRet;
     138#else
     139
     140    LARGE_INTEGER NtTime;
     141    do
     142    {
     143        NtTime.HighPart = pUserSharedData->InterruptTime.High1Time;
     144        NtTime.LowPart  = pUserSharedData->InterruptTime.LowPart;
     145    } while (pUserSharedData->InterruptTime.High2Time != NtTime.HighPart);
     146
     147    return (uint64_t)NtTime.QuadPart * 100;
     148#endif
     149}
     150
     151
     152RTDECL(uint64_t) RTTimeSystemNanoTS(void)
     153{
     154    return rtTimeGetSystemNanoTS();
     155}
     156
     157
     158RTDECL(uint64_t) RTTimeSystemMilliTS(void)
     159{
     160    return rtTimeGetSystemNanoTS() / RT_NS_1MS;
     161}
     162
     163
     164RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
     165{
     166    /*
     167     * Get the precise time if possible.
     168     */
     169    if (RT_UNLIKELY(!g_fInitialized))
     170        rtTimeNtInitialize();
     171    if (g_pfnRtlGetSystemTimePrecise != NULL)
     172        return RTTimeSpecSetNtTime(pTime, g_pfnRtlGetSystemTimePrecise());
     173
     174    /*
     175     * Just read system time.
     176     */
     177    KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
     178#ifdef RT_ARCH_AMD64
     179    uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->SystemTime; /* This is what KeQuerySystemTime does. */
     180    return RTTimeSpecSetNtTime(pTime, uRet);
     181#else
     182
     183    LARGE_INTEGER NtTime;
     184    do
     185    {
     186        NtTime.HighPart = pUserSharedData->SystemTime.High1Time;
     187        NtTime.LowPart  = pUserSharedData->SystemTime.LowPart;
     188    } while (pUserSharedData->SystemTime.High2Time != NtTime.HighPart);
     189    return RTTimeSpecSetNtTime(pTime, NtTime.QuadPart);
     190#endif
     191}
     192
     193
     194RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
     195{
     196    return RTTimeSpecAddNano(RTTimeNow(pTime), RTTimeLocalDeltaNano());
     197}
     198
     199
     200RTDECL(int64_t) RTTimeLocalDeltaNano(void)
     201{
     202    /*
     203     * UTC = local + TimeZoneBias; The bias is given in NT units.
     204     */
     205    KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
     206    LARGE_INTEGER               Delta;
     207#if ARCH_BITS == 64
     208    Delta.QuadPart = *(int64_t volatile *)&pUserSharedData->TimeZoneBias;
     209#else
     210    do
     211    {
     212        Delta.HighPart = pUserSharedData->TimeZoneBias.High1Time;
     213        Delta.LowPart  = pUserSharedData->TimeZoneBias.LowPart;
     214    } while (pUserSharedData->TimeZoneBias.High2Time != Delta.HighPart);
     215#endif
     216    return Delta.QuadPart * -100;
     217}
     218
  • trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def

    r52953 r53471  
    126126    RtlSizeHeap                           ;;= _RtlSizeHeap@12
    127127    RtlSubAuthoritySid                    ;;= _RtlSubAuthoritySid@8
     128    RtlQueryPerformanceCounter            ;;= _RtlQueryPerformanceCounter@4
     129    RtlGetSystemTimePrecise               ;;= _RtlGetSystemTimePrecise@0
    128130
  • trunk/src/VBox/Runtime/r3/win/time-win.cpp

    r52823 r53471  
    162162
    163163
    164 RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime)
    165 {
    166     FILETIME    FileTime;
    167     SYSTEMTIME  SysTime;
    168     if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime))
    169     {
    170         if (SetSystemTime(&SysTime))
    171             return VINF_SUCCESS;
    172     }
    173     return RTErrConvertFromWin32(GetLastError());
    174 }
    175 
    176 
    177164RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
    178165{
     
    200187}
    201188
    202 
    203 RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
    204 {
    205     /*
    206      * FileTimeToLocalFileTime does not do the right thing, so we'll have
    207      * to convert to system time and SystemTimeToTzSpecificLocalTime instead.
    208      */
    209     RTTIMESPEC LocalTime;
    210     SYSTEMTIME SystemTimeIn;
    211     FILETIME FileTime;
    212     if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn))
    213     {
    214         SYSTEMTIME SystemTimeOut;
    215         if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */,
    216                                             &SystemTimeIn,
    217                                             &SystemTimeOut))
    218         {
    219             if (SystemTimeToFileTime(&SystemTimeOut, &FileTime))
    220             {
    221                 RTTimeSpecSetNtFileTime(&LocalTime, &FileTime);
    222                 pTime = RTTimeExplode(pTime, &LocalTime);
    223                 if (pTime)
    224                     pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
    225                 return pTime;
    226             }
    227         }
    228     }
    229 
    230     /*
    231      * The fallback is to use the current offset.
    232      * (A better fallback would be to use the offset of the same time of the year.)
    233      */
    234     LocalTime = *pTimeSpec;
    235     RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
    236     pTime = RTTimeExplode(pTime, &LocalTime);
    237     if (pTime)
    238         pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
    239     return pTime;
    240 }
    241 
  • trunk/src/VBox/Runtime/r3/win/time2-win.cpp

    r53467 r53471  
    3535#include "internal/iprt.h"
    3636
    37 #include <iprt/asm.h>
    3837#include <iprt/assert.h>
    3938#include <iprt/err.h>
    4039#include "internal/time.h"
    4140
    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 
    57 typedef struct _MY_KSYSTEM_TIME
    58 {
    59     ULONG LowPart;
    60     LONG High1Time;
    61     LONG High2Time;
    62 } MY_KSYSTEM_TIME;
    63 
    64 typedef 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 
    75 DECLINLINE(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() * RT_NS_1MS_64;
    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() * RT_NS_1MS_64;
    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() * RT_NS_1MS_64;
    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 # if 0 /* ASSUME 0x7ffe0000 is set in stone */
    112     /*
    113      * This is exactly what we want, but we have to obtain it by non-official
    114      * means.
    115      */
    116     static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL;
    117     if (!s_pUserSharedData)
    118     {
    119         /** @todo find official way of getting this or some more clever
    120          * detection algorithm if necessary. The com debugger class
    121          * exports this too, windbg knows it too... */
    122         s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
    123     }
    124 # endif
    125     PMY_KUSER_SHARED_DATA pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
    126 
    127     /* use interrupt time */
    128     LARGE_INTEGER Time;
    129     do
    130     {
    131         Time.HighPart = pUserSharedData->InterruptTime.High1Time;
    132         Time.LowPart  = pUserSharedData->InterruptTime.LowPart;
    133     } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
    134 
    135     return (uint64_t)Time.QuadPart * 100;
    136 
    137 #else
    138 # error "Must select a method bright guy!"
    139 #endif
    140 }
    141 
    142 
    143 RTDECL(uint64_t) RTTimeSystemNanoTS(void)
    144 {
    145     return rtTimeGetSystemNanoTS();
    146 }
    147 
    148 
    149 RTDECL(uint64_t) RTTimeSystemMilliTS(void)
    150 {
    151     return rtTimeGetSystemNanoTS() / RT_NS_1MS;
    152 }
    153 
    154 
    155 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
    156 {
    157     uint64_t u64;
    158     AssertCompile(sizeof(u64) == sizeof(FILETIME));
    159     GetSystemTimeAsFileTime((LPFILETIME)&u64);
    160     return RTTimeSpecSetNtTime(pTime, u64);
    161 }
    16241
    16342
     
    17251    }
    17352    return RTErrConvertFromWin32(GetLastError());
    174 }
    175 
    176 
    177 RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
    178 {
    179     uint64_t u64;
    180     AssertCompile(sizeof(u64) == sizeof(FILETIME));
    181     GetSystemTimeAsFileTime((LPFILETIME)&u64);
    182     uint64_t u64Local;
    183     if (!FileTimeToLocalFileTime((FILETIME const *)&u64, (LPFILETIME)&u64Local))
    184         u64Local = u64;
    185     return RTTimeSpecSetNtTime(pTime, u64Local);
    186 }
    187 
    188 
    189 RTDECL(int64_t) RTTimeLocalDeltaNano(void)
    190 {
    191     /*
    192      * UTC = local + Tzi.Bias;
    193      * The bias is given in minutes.
    194      */
    195     TIME_ZONE_INFORMATION Tzi;
    196     Tzi.Bias = 0;
    197     if (GetTimeZoneInformation(&Tzi) != TIME_ZONE_ID_INVALID)
    198         return -(int64_t)Tzi.Bias * 60 * RT_NS_1SEC_64;
    199     return 0;
    20053}
    20154
Note: See TracChangeset for help on using the changeset viewer.

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