VirtualBox

Changeset 53456 in vbox


Ignore:
Timestamp:
Dec 5, 2014 12:52:46 PM (10 years ago)
Author:
vboxsync
Message:

RTTime/r0drv/nt: Use higher precision APIs to get times when available.

Location:
trunk/src/VBox/Runtime/r0drv/nt
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp

    r48935 r53456  
    5050 * and update this variable as CPUs comes online. (The code is done already.)
    5151 */
    52 RTCPUSET                    g_rtMpNtCpuSet;
     52RTCPUSET                            g_rtMpNtCpuSet;
    5353
    5454/** ExSetTimerResolution, introduced in W2K. */
    55 PFNMYEXSETTIMERRESOLUTION   g_pfnrtNtExSetTimerResolution;
     55PFNMYEXSETTIMERRESOLUTION           g_pfnrtNtExSetTimerResolution;
    5656/** KeFlushQueuedDpcs, introduced in XP. */
    57 PFNMYKEFLUSHQUEUEDDPCS      g_pfnrtNtKeFlushQueuedDpcs;
     57PFNMYKEFLUSHQUEUEDDPCS              g_pfnrtNtKeFlushQueuedDpcs;
    5858/** HalRequestIpi, introduced in ??. */
    59 PFNHALREQUESTIPI            g_pfnrtNtHalRequestIpi;
     59PFNHALREQUESTIPI                    g_pfnrtNtHalRequestIpi;
    6060/** HalSendSoftwareInterrupt */
    61 PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt;
     61PFNHALSENDSOFTWAREINTERRUPT         g_pfnrtNtHalSendSoftwareInterrupt;
    6262/** SendIpi handler based on Windows version */
    63 PFNRTSENDIPI                g_pfnrtSendIpi;
     63PFNRTSENDIPI                        g_pfnrtSendIpi;
    6464/** KeIpiGenericCall - Windows Server 2003+ only */
    65 PFNRTKEIPIGENERICCALL       g_pfnrtKeIpiGenericCall;
     65PFNRTKEIPIGENERICCALL               g_pfnrtKeIpiGenericCall;
    6666/** RtlGetVersion, introduced in ??. */
    67 PFNRTRTLGETVERSION          g_pfnrtRtlGetVersion;
     67PFNRTRTLGETVERSION                  g_pfnrtRtlGetVersion;
     68#ifndef RT_ARCH_AMD64
     69/** KeQueryInterruptTime - exported/new in Windows 2000. */
     70PFNRTKEQUERYINTERRUPTTIME           g_pfnrtKeQueryInterruptTime;
     71/** KeQuerySystemTime - exported/new in Windows 2000. */
     72PFNRTKEQUERYSYSTEMTIME              g_pfnrtKeQuerySystemTime;
     73#endif
     74/** KeQueryInterruptTimePrecise - new in Windows 8. */
     75PFNRTKEQUERYINTERRUPTTIMEPRECISE    g_pfnrtKeQueryInterruptTimePrecise;
     76/** KeQuerySystemTimePrecise - new in Windows 8. */
     77PFNRTKEQUERYSYSTEMTIMEPRECISE       g_pfnrtKeQuerySystemTimePrecise;
    6878
    6979/** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */
    70 uint32_t                    g_offrtNtPbQuantumEnd;
     80uint32_t                            g_offrtNtPbQuantumEnd;
    7181/** Size of the _KPRCB::QuantumEnd field. 0 if not found. */
    72 uint32_t                    g_cbrtNtPbQuantumEnd;
     82uint32_t                            g_cbrtNtPbQuantumEnd;
    7383/** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */
    74 uint32_t                    g_offrtNtPbDpcQueueDepth;
     84uint32_t                            g_offrtNtPbDpcQueueDepth;
    7585
    7686
     
    200210/** @todo Port to W2K8 with > 64 cpus/threads. */
    201211
     212    /*
     213     * Initialize the function pointers.
     214     */
    202215#ifdef IPRT_TARGET_NT4
    203216    g_pfnrtNtExSetTimerResolution = NULL;
     
    207220    g_pfnrtKeIpiGenericCall = NULL;
    208221    g_pfnrtRtlGetVersion = NULL;
     222    g_pfnrtKeQueryInterruptTime = NULL;
     223    g_pfnrtKeQueryInterruptTimePrecise = NULL;
     224    g_pfnrtKeQuerySystemTime = NULL;
     225    g_pfnrtKeQuerySystemTimePrecise = NULL;
    209226#else
    210     /*
    211      * Initialize the function pointers.
    212      */
    213227    UNICODE_STRING RoutineName;
    214228    RtlInitUnicodeString(&RoutineName, L"ExSetTimerResolution");
     
    229243    RtlInitUnicodeString(&RoutineName, L"RtlGetVersion");
    230244    g_pfnrtRtlGetVersion = (PFNRTRTLGETVERSION)MmGetSystemRoutineAddress(&RoutineName);
     245# ifndef RT_ARCH_AMD64
     246    RtlInitUnicodeString(&RoutineName, L"KeQueryInterruptTime");
     247    g_pfnrtKeQueryInterruptTime = (PFNRTKEQUERYINTERRUPTTIME)MmGetSystemRoutineAddress(&RoutineName);
     248
     249    RtlInitUnicodeString(&RoutineName, L"KeQuerySystemTime");
     250    g_pfnrtKeQuerySystemTime = (PFNRTKEQUERYSYSTEMTIME)MmGetSystemRoutineAddress(&RoutineName);
     251# endif
     252    RtlInitUnicodeString(&RoutineName, L"KeQueryInterruptTimePrecise");
     253    g_pfnrtKeQueryInterruptTimePrecise = (PFNRTKEQUERYINTERRUPTTIMEPRECISE)MmGetSystemRoutineAddress(&RoutineName);
     254
     255    RtlInitUnicodeString(&RoutineName, L"KeQuerySystemTimePrecise");
     256    g_pfnrtKeQuerySystemTimePrecise = (PFNRTKEQUERYSYSTEMTIMEPRECISE)MmGetSystemRoutineAddress(&RoutineName);
    231257#endif
    232258
  • trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h

    r45443 r53456  
    4242typedef ULONG_PTR (__stdcall *PFNRTKEIPIGENERICCALL)(PKIPI_BROADCAST_WORKER BroadcastFunction, ULONG_PTR  Context);
    4343typedef ULONG (__stdcall *PFNRTRTLGETVERSION)(PRTL_OSVERSIONINFOEXW pVerInfo);
     44#ifndef RT_ARCH_AMD64
     45typedef ULONGLONG (__stdcall *PFNRTKEQUERYINTERRUPTTIME)(VOID);
     46typedef VOID (__stdcall *PFNRTKEQUERYSYSTEMTIME)(PLARGE_INTEGER pTime);
     47#endif
     48typedef ULONG64 (__stdcall *PFNRTKEQUERYINTERRUPTTIMEPRECISE)(PULONG64 pQpcTS);
     49typedef VOID (__stdcall *PFNRTKEQUERYSYSTEMTIMEPRECISE)(PLARGE_INTEGER pTime);
     50
    4451
    4552/*******************************************************************************
    4653*   Global Variables                                                           *
    4754*******************************************************************************/
    48 extern RTCPUSET                     g_rtMpNtCpuSet;
    49 extern PFNMYEXSETTIMERRESOLUTION    g_pfnrtNtExSetTimerResolution;
    50 extern PFNMYKEFLUSHQUEUEDDPCS       g_pfnrtNtKeFlushQueuedDpcs;
    51 extern PFNHALREQUESTIPI             g_pfnrtNtHalRequestIpi;
    52 extern PFNHALSENDSOFTWAREINTERRUPT  g_pfnrtNtHalSendSoftwareInterrupt;
    53 extern PFNRTSENDIPI                 g_pfnrtSendIpi;
    54 extern PFNRTKEIPIGENERICCALL        g_pfnrtKeIpiGenericCall;
    55 extern PFNRTRTLGETVERSION             g_pfnrtRtlGetVersion;
    56 extern uint32_t                     g_offrtNtPbQuantumEnd;
    57 extern uint32_t                     g_cbrtNtPbQuantumEnd;
    58 extern uint32_t                     g_offrtNtPbDpcQueueDepth;
     55extern RTCPUSET                         g_rtMpNtCpuSet;
     56extern PFNMYEXSETTIMERRESOLUTION        g_pfnrtNtExSetTimerResolution;
     57extern PFNMYKEFLUSHQUEUEDDPCS           g_pfnrtNtKeFlushQueuedDpcs;
     58extern PFNHALREQUESTIPI                 g_pfnrtNtHalRequestIpi;
     59extern PFNHALSENDSOFTWAREINTERRUPT      g_pfnrtNtHalSendSoftwareInterrupt;
     60extern PFNRTSENDIPI                     g_pfnrtSendIpi;
     61extern PFNRTKEIPIGENERICCALL            g_pfnrtKeIpiGenericCall;
     62extern PFNRTRTLGETVERSION               g_pfnrtRtlGetVersion;
     63#ifndef RT_ARCH_AMD64
     64extern PFNRTKEQUERYINTERRUPTTIME        g_pfnrtKeQueryInterruptTime;
     65extern PFNRTKEQUERYSYSTEMTIME           g_pfnrtKeQuerySystemTime;
     66#endif
     67extern PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise;
     68extern PFNRTKEQUERYSYSTEMTIMEPRECISE    g_pfnrtKeQuerySystemTimePrecise;
     69extern uint32_t                         g_offrtNtPbQuantumEnd;
     70extern uint32_t                         g_cbrtNtPbQuantumEnd;
     71extern uint32_t                         g_offrtNtPbDpcQueueDepth;
    5972
    6073
  • trunk/src/VBox/Runtime/r0drv/nt/time-r0drv-nt.cpp

    r52822 r53456  
    3131#define LOG_GROUP RTLOGGROUP_TIME
    3232#include "the-nt-kernel.h"
     33#include "internal-r0drv-nt.h"
    3334#include <iprt/time.h>
    3435
     
    4950     */
    5051#if 1
    51     /* Interrupt time. (NT4 doesn't have an API for it.) */
    52 # ifndef IPRT_TARGET_NT4
    53     ULONGLONG InterruptTime = KeQueryInterruptTime();
    54     return (uint64_t)InterruptTime * 100; /* The value is in 100ns, convert to ns units. */
     52    /* Interrupt time. */
     53    LARGE_INTEGER InterruptTime;
     54    if (g_pfnrtKeQueryInterruptTimePrecise)
     55    {
     56        ULONG64 QpcTsIgnored;
     57        InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTimePrecise(&QpcTsIgnored);
     58    }
     59# ifdef RT_ARCH_AMD64
     60    else
     61        InterruptTime.QuadPart = KeQueryInterruptTime(); /* macro */
    5562# else
    56     LARGE_INTEGER InterruptTime;
    57     do
     63    else if (g_pfnrtKeQueryInterruptTime)
     64        InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTime();
     65    else
    5866    {
    59         InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time;
    60         InterruptTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart;
    61     } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart);
    62 
     67        /* NT4 (no API) and pre-init fallback. */
     68        do
     69        {
     70            InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time;
     71            InterruptTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart;
     72        } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart);
     73    }
     74# endif
    6375    return (uint64_t)InterruptTime.QuadPart * 100;
    64 # endif
    6576#else
    6677    /* Tick Count (NT4 SP1 has these APIs, haven't got SP0 to check). */
     
    99110{
    100111    LARGE_INTEGER SystemTime;
    101 #ifndef IPRT_TARGET_NT4
    102     KeQuerySystemTime(&SystemTime);
     112    if (g_pfnrtKeQuerySystemTimePrecise)
     113        g_pfnrtKeQuerySystemTimePrecise(&SystemTime);
     114#ifdef RT_ARCH_AMD64
     115    else
     116        KeQuerySystemTime(&SystemTime); /* macro */
    103117#else
    104     do
     118    else if (g_pfnrtKeQuerySystemTime)
     119        g_pfnrtKeQuerySystemTime(&SystemTime);
     120    else
    105121    {
    106         SystemTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High1Time;
    107         SystemTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.LowPart;
    108     } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High2Time != SystemTime.HighPart);
     122        do
     123        {
     124            SystemTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High1Time;
     125            SystemTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.LowPart;
     126        } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High2Time != SystemTime.HighPart);
     127    }
    109128#endif
    110129    return RTTimeSpecSetNtTime(pTime, SystemTime.QuadPart);
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