timesupref.h revision e64031e20c39650a7bc902a3e1aba613b9415dee
/* $Id$ */
/** @file
* IPRT - Time using SUPLib, the C Code Template.
*/
/*
* Copyright (C) 2006-2007 Oracle Corporation
*
* 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 (GPL) 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.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/**
* The C reference implementation of the assembly routines.
*
* 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.
*
* @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.
*
* @returns Nanosecond timestamp.
* @param pData Pointer to the data structure.
*/
{
/*
* Read the GIP data and the previous value.
*/
for (;;)
{
#ifdef IN_RING3
#endif
#ifdef ASYNC_GIP
#else
#endif
#ifdef NEED_TRANSACTION_ID
#endif
u64Delta = ASMReadTSC();
#ifdef NEED_TRANSACTION_ID
# ifdef ASYNC_GIP
continue;
# elif !defined(RT_ARCH_X86)
# endif
|| (u32TransactionId & 1)))
continue;
#endif
break;
}
/*
* Calc NanoTS delta.
*/
{
/*
* We've expired the interval, cap it. If we're here for the 2nd
* time without any GIP update inbetween, the checks against
* *pu64Prev below will force 1ns stepping.
*/
}
#if !defined(_MSC_VER) || defined(RT_ARCH_AMD64) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
#else
{
}
#endif
/*
* Calculate the time and compare it with the previously returned value.
*/
if (RT_LIKELY( u64DeltaPrev > 0
/* Frequent - less than 24h since last call. */;
{
/* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
}
else if (!u64PrevNanoTS)
/* We're resuming (see TMVirtualResume). */;
else
{
/* Something has gone bust, if negative offset it's real bad. */
}
{
/*
* Attempt updating the previous value, provided we're still ahead of it.
*
* There is no point in recalculating u64NanoTS because we got preemted or if
* we raced somebody while the GIP was updated, since these are events
* that might occure at any point in the return path as well.
*/
pData->cUpdateRaces++;
{
if (u64PrevNanoTS >= u64NanoTS)
break;
break;
}
}
return u64NanoTS;
}