timesup.cpp revision a3557eb865ae03877f40c9c91c147d31ab4902bc
/* $Id$ */
/** @file
* innotek Portable Runtime - Time using SUPLib.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_TIME
/*******************************************************************************
* Global Variables *
*******************************************************************************/
#ifndef IN_GUEST
/** The previously returned nano TS.
* This handles TSC drift on SMP systems and expired interval.
* This is a valid range u64NanoTS to u64NanoTS + 1000000000 (ie. 1sec).
*/
static uint64_t volatile s_u64PrevNanoTS = 0;
/**
* Number of times we've had to resort to 1ns walking. */
static uint32_t volatile g_c1nsSteps = 0;
#endif
/**
* Calculate NanoTS using the information in the global information page (GIP)
* which the support library (SUPLib) exports.
*
* This function guarantees that the returned timestamp is later (in time) than
* any previous calls in the same thread.
*
* @returns Nanosecond timestamp.
*
* @remark The way the ever increasing time guarantee is currently implemented means
* that if you call this function at a freqency higher than 1GHz you're in for
* trouble. We currently assume that no idiot will do that for real life purposes.
*/
{
#ifndef IN_GUEST
/*
* Read the data.
*/
for (;;)
{
#ifdef IN_RING3
return RTTimeSystemNanoTS();
#endif
{
#ifdef RT_OS_L4
#endif
u64Delta = ASMReadTSC();
|| (u32TransactionId & 1)))
continue;
}
else
{
/* SUPGIPMODE_ASYNC_TSC */
else
{
}
#ifdef RT_OS_L4
#endif
u64Delta = ASMReadTSC();
continue;
|| (u32TransactionId & 1)))
continue;
}
break;
}
/*
* Calc NanoTS delta.
*/
if (u64Delta > u32UpdateIntervalTSC)
{
/*
* We've expired the interval. Do 1ns per call until we've
* got valid TSC deltas again (s_u64PrevNanoTS takes care of this).
*/
}
#if !defined(_MSC_VER) || defined(RT_ARCH_AMD64) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
#else
{
}
#endif
/*
* The most frequent case is that the delta is either too old
* or that our timestamp is higher (relative to u64NanoTS) than it.
*/
{
return u64;
}
else
{
/*
* Our timestamp is lower than the last returned timestamp;
* advance 1ns beyond that.
*/
}
/*
* Attempt updating the previous value.
* u64 == timestamp, u64Delta == delta relative to u64NanoTS.
*/
for (int cTries = 100;;)
{
if (u64DeltaPrev > u64Delta)
break;
break;
if (--cTries <= 0)
{
AssertBreakpoint(); /* (recursion) */
break;
}
}
return u64;
#else /* IN_GUEST */
return RTTimeSystemNanoTS();
#endif /* IN_GUEST */
}
/**
* Gets the current nanosecond timestamp.
*
* @returns nanosecond timestamp.
*/
{
return rtTimeNanoTSInternal();
}
/**
* Gets the current millisecond timestamp.
*
* @returns millisecond timestamp.
*/
{
return rtTimeNanoTSInternal() / 1000000;
}
#ifndef IN_GUEST
/**
* Debugging the time api.
*
* @returns the number of 1ns steps which has been applied by rtTimeNanoTSInternal().
*/
{
return g_c1nsSteps;
}
#endif