VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/time/timesupref.h@ 42599

Last change on this file since 42599 was 36262, checked in by vboxsync, 14 years ago

SUPDrv,IPRT,++: Enabled the code for supporting up to 256 host CPUs/cores/threads.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.0 KB
Line 
1/* $Id: timesupref.h 36262 2011-03-11 14:50:45Z vboxsync $ */
2/** @file
3 * IPRT - Time using SUPLib, the C Code Template.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/**
29 * The C reference implementation of the assembly routines.
30 *
31 * Calculate NanoTS using the information in the global information page (GIP)
32 * which the support library (SUPLib) exports.
33 *
34 * This function guarantees that the returned timestamp is later (in time) than
35 * any previous calls in the same thread.
36 *
37 * @remark The way the ever increasing time guarantee is currently implemented means
38 * that if you call this function at a frequency higher than 1GHz you're in for
39 * trouble. We currently assume that no idiot will do that for real life purposes.
40 *
41 * @returns Nanosecond timestamp.
42 * @param pData Pointer to the data structure.
43 */
44RTDECL(uint64_t) rtTimeNanoTSInternalRef(PRTTIMENANOTSDATA pData)
45{
46 uint64_t u64Delta;
47 uint32_t u32NanoTSFactor0;
48 uint64_t u64TSC;
49 uint64_t u64NanoTS;
50 uint32_t u32UpdateIntervalTSC;
51 uint64_t u64PrevNanoTS;
52
53 /*
54 * Read the GIP data and the previous value.
55 */
56 for (;;)
57 {
58 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
59#ifdef IN_RING3
60 if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
61 return pData->pfnRediscover(pData);
62#endif
63
64#ifdef ASYNC_GIP
65 uint8_t u8ApicId = ASMGetApicId();
66 PSUPGIPCPU pGipCpu = &pGip->aCPUs[pGip->aiCpuFromApicId[u8ApicId]];
67#else
68 PSUPGIPCPU pGipCpu = &pGip->aCPUs[0];
69#endif
70
71#ifdef NEED_TRANSACTION_ID
72 uint32_t u32TransactionId = pGipCpu->u32TransactionId;
73 uint32_t volatile Tmp1;
74 ASMAtomicXchgU32(&Tmp1, u32TransactionId);
75#endif
76
77 u32UpdateIntervalTSC = pGipCpu->u32UpdateIntervalTSC;
78 u64NanoTS = pGipCpu->u64NanoTS;
79 u64TSC = pGipCpu->u64TSC;
80 u32NanoTSFactor0 = pGip->u32UpdateIntervalNS;
81 u64Delta = ASMReadTSC();
82 u64PrevNanoTS = ASMAtomicReadU64(pData->pu64Prev);
83
84#ifdef NEED_TRANSACTION_ID
85# ifdef ASYNC_GIP
86 if (RT_UNLIKELY(u8ApicId != ASMGetApicId()))
87 continue;
88# elif !defined(RT_ARCH_X86)
89 uint32_t volatile Tmp2;
90 ASMAtomicXchgU32(&Tmp2, u64Delta);
91# endif
92 if (RT_UNLIKELY( pGipCpu->u32TransactionId != u32TransactionId
93 || (u32TransactionId & 1)))
94 continue;
95#endif
96 break;
97 }
98
99 /*
100 * Calc NanoTS delta.
101 */
102 u64Delta -= u64TSC;
103 if (RT_UNLIKELY(u64Delta > u32UpdateIntervalTSC))
104 {
105 /*
106 * We've expired the interval, cap it. If we're here for the 2nd
107 * time without any GIP update in-between, the checks against
108 * *pu64Prev below will force 1ns stepping.
109 */
110 pData->cExpired++;
111 u64Delta = u32UpdateIntervalTSC;
112 }
113#if !defined(_MSC_VER) || defined(RT_ARCH_AMD64) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
114 u64Delta = ASMMult2xU32RetU64((uint32_t)u64Delta, u32NanoTSFactor0);
115 u64Delta = ASMDivU64ByU32RetU32(u64Delta, u32UpdateIntervalTSC);
116#else
117 __asm
118 {
119 mov eax, dword ptr [u64Delta]
120 mul dword ptr [u32NanoTSFactor0]
121 div dword ptr [u32UpdateIntervalTSC]
122 mov dword ptr [u64Delta], eax
123 xor edx, edx
124 mov dword ptr [u64Delta + 4], edx
125 }
126#endif
127
128 /*
129 * Calculate the time and compare it with the previously returned value.
130 */
131 u64NanoTS += u64Delta;
132 uint64_t u64DeltaPrev = u64NanoTS - u64PrevNanoTS;
133 if (RT_LIKELY( u64DeltaPrev > 0
134 && u64DeltaPrev < UINT64_C(86000000000000) /* 24h */))
135 /* Frequent - less than 24h since last call. */;
136 else if (RT_LIKELY( (int64_t)u64DeltaPrev <= 0
137 && (int64_t)u64DeltaPrev + u32NanoTSFactor0 * 2 >= 0))
138 {
139 /* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
140 ASMAtomicIncU32(&pData->c1nsSteps);
141 u64NanoTS = u64PrevNanoTS + 1;
142 }
143 else if (!u64PrevNanoTS)
144 /* We're resuming (see TMVirtualResume). */;
145 else
146 {
147 /* Something has gone bust, if negative offset it's real bad. */
148 ASMAtomicIncU32(&pData->cBadPrev);
149 pData->pfnBad(pData, u64NanoTS, u64DeltaPrev, u64PrevNanoTS);
150 }
151
152 if (RT_UNLIKELY(!ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS)))
153 {
154 /*
155 * Attempt updating the previous value, provided we're still ahead of it.
156 *
157 * There is no point in recalculating u64NanoTS because we got preempted or if
158 * we raced somebody while the GIP was updated, since these are events
159 * that might occur at any point in the return path as well.
160 */
161 pData->cUpdateRaces++;
162 for (int cTries = 25; cTries > 0; cTries--)
163 {
164 u64PrevNanoTS = ASMAtomicReadU64(pData->pu64Prev);
165 if (u64PrevNanoTS >= u64NanoTS)
166 break;
167 if (ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS))
168 break;
169 }
170 }
171 return u64NanoTS;
172}
173
Note: See TracBrowser for help on using the repository browser.

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