1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync/* $Id$ */
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Time, Ring-0 Driver, Nt.
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync */
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync/*
6cf438776892898b86c5c34c92e32fc446b057d2vboxsync * Copyright (C) 2007-2014 Oracle Corporation
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync *
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync * available from http://www.virtualbox.org. This file is free software;
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync */
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync/*******************************************************************************
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync* Header Files *
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync*******************************************************************************/
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#define LOG_GROUP RTLOGGROUP_TIME
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#include "the-nt-kernel.h"
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync#include "internal-r0drv-nt.h"
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#include <iprt/time.h>
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncDECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync /*
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync * Note! The time source we use here must be exactly the same as in
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync * the ring-3 code!
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync *
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * Using interrupt time is the simplest and requires the least calculation.
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * It is also accounting for suspended time. Unfortuantely, there is no
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * ring-3 for reading it... but that won't stop us.
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync *
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * Using the tick count is problematic in ring-3 on older windows version
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * as we can only get the 32-bit tick value, i.e. we'll roll over sooner or
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync * later.
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync */
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync#if 1
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync /* Interrupt time. */
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync LARGE_INTEGER InterruptTime;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync if (g_pfnrtKeQueryInterruptTimePrecise)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync {
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync ULONG64 QpcTsIgnored;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTimePrecise(&QpcTsIgnored);
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync }
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync# ifdef RT_ARCH_AMD64
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync InterruptTime.QuadPart = KeQueryInterruptTime(); /* macro */
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync# else
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else if (g_pfnrtKeQueryInterruptTime)
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync InterruptTime.QuadPart = g_pfnrtKeQueryInterruptTime();
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync {
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync /* NT4 (no API) and pre-init fallback. */
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync do
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync {
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync InterruptTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart);
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync }
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync# endif
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync return (uint64_t)InterruptTime.QuadPart * 100;
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync#else
6162a4a3d82747a7d0a3a2b2633a67a945cb5002vboxsync /* Tick Count (NT4 SP1 has these APIs, haven't got SP0 to check). */
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync LARGE_INTEGER Tick;
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync KeQueryTickCount(&Tick);
282f5fe327c5d622addc8b943407a35d8b192a19vboxsync return (uint64_t)Tick.QuadPart * KeQueryTimeIncrement() * 100;
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#endif
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncRTDECL(uint64_t) RTTimeNanoTS(void)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync return rtTimeGetSystemNanoTS();
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncRTDECL(uint64_t) RTTimeMilliTS(void)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
6cf438776892898b86c5c34c92e32fc446b057d2vboxsync return rtTimeGetSystemNanoTS() / RT_NS_1MS;
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncRTDECL(uint64_t) RTTimeSystemNanoTS(void)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync return rtTimeGetSystemNanoTS();
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncRTDECL(uint64_t) RTTimeSystemMilliTS(void)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
6cf438776892898b86c5c34c92e32fc446b057d2vboxsync return rtTimeGetSystemNanoTS() / RT_NS_1MS;
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsyncRTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync{
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync LARGE_INTEGER SystemTime;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync if (g_pfnrtKeQuerySystemTimePrecise)
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync g_pfnrtKeQuerySystemTimePrecise(&SystemTime);
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync#ifdef RT_ARCH_AMD64
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync KeQuerySystemTime(&SystemTime); /* macro */
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#else
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else if (g_pfnrtKeQuerySystemTime)
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync g_pfnrtKeQuerySystemTime(&SystemTime);
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync else
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync {
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync do
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync {
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync SystemTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High1Time;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync SystemTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.LowPart;
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->SystemTime.High2Time != SystemTime.HighPart);
5a8ae0443b7be3b1a5501bd101b1533daa844c23vboxsync }
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync#endif
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync return RTTimeSpecSetNtTime(pTime, SystemTime.QuadPart);
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync}
1319c68f8bf1c1195c93ecf9acccf19354d91ba8vboxsync