VirtualBox

source: vbox/trunk/src/VBox/VMM/include/TMInline.h@ 96253

Last change on this file since 96253 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: TMInline.h 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * TM - Common Inlined functions.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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
18#ifndef VMM_INCLUDED_SRC_include_TMInline_h
19#define VMM_INCLUDED_SRC_include_TMInline_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24
25DECLINLINE(PTMTIMER) tmTimerQueueGetHead(PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueueShared)
26{
27#ifdef IN_RING3
28 RT_NOREF(pQueueShared);
29 uint32_t const idx = pQueueCC->idxActive;
30#else
31 uint32_t const idx = pQueueShared->idxActive;
32#endif
33 if (idx < pQueueCC->cTimersAlloc)
34 return &pQueueCC->paTimers[idx];
35 return NULL;
36}
37
38
39DECLINLINE(void) tmTimerQueueSetHead(PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueueShared, PTMTIMER pHead)
40{
41 uint32_t idx;
42 if (pHead)
43 {
44 idx = (uint32_t)(pHead - &pQueueCC->paTimers[0]);
45 AssertMsgStmt(idx < pQueueCC->cTimersAlloc,
46 ("idx=%u (%s) cTimersAlloc=%u\n", idx, pHead->szName, pQueueCC->cTimersAlloc),
47 idx = UINT32_MAX);
48 }
49 else
50 idx = UINT32_MAX;
51#ifndef IN_RING3
52 pQueueShared->idxActive = idx;
53#else
54 pQueueCC->idxActive = idx;
55 RT_NOREF(pQueueShared);
56#endif
57}
58
59
60/**
61 * Get the previous timer - translates TMTIMER::idxPrev.
62 */
63DECLINLINE(PTMTIMER) tmTimerGetPrev(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer)
64{
65 uint32_t const idxPrev = pTimer->idxPrev;
66 Assert(idxPrev);
67 if (idxPrev < pQueueCC->cTimersAlloc)
68 return &pQueueCC->paTimers[idxPrev];
69 Assert(idxPrev == UINT32_MAX);
70 return NULL;
71}
72
73
74/**
75 * Get the next timer - translates TMTIMER::idxNext.
76 */
77DECLINLINE(PTMTIMER) tmTimerGetNext(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer)
78{
79 uint32_t const idxNext = pTimer->idxNext;
80 Assert(idxNext);
81 if (idxNext < pQueueCC->cTimersAlloc)
82 return &pQueueCC->paTimers[idxNext];
83 Assert(idxNext == UINT32_MAX);
84 return NULL;
85}
86
87
88/**
89 * Set the previous timer link (TMTIMER::idxPrev).
90 */
91DECLINLINE(void) tmTimerSetPrev(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer, PTMTIMER pPrev)
92{
93 uint32_t idxPrev;
94 if (pPrev)
95 {
96 idxPrev = (uint32_t)(pPrev - &pQueueCC->paTimers[0]);
97 Assert(idxPrev);
98 AssertMsgStmt(idxPrev < pQueueCC->cTimersAlloc,
99 ("idxPrev=%u (%s) cTimersAlloc=%u\n", idxPrev, pPrev->szName, pQueueCC->cTimersAlloc),
100 idxPrev = UINT32_MAX);
101 }
102 else
103 idxPrev = UINT32_MAX;
104 pTimer->idxPrev = idxPrev;
105}
106
107
108/**
109 * Set the next timer link (TMTIMER::idxNext).
110 */
111DECLINLINE(void) tmTimerSetNext(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer, PTMTIMER pNext)
112{
113 uint32_t idxNext;
114 if (pNext)
115 {
116 idxNext = (uint32_t)(pNext - &pQueueCC->paTimers[0]);
117 Assert(idxNext);
118 AssertMsgStmt(idxNext < pQueueCC->cTimersAlloc,
119 ("idxNext=%u (%s) cTimersAlloc=%u\n", idxNext, pNext->szName, pQueueCC->cTimersAlloc),
120 idxNext = UINT32_MAX);
121 }
122 else
123 idxNext = UINT32_MAX;
124 pTimer->idxNext = idxNext;
125}
126
127
128/**
129 * Used to unlink a timer from the active list.
130 *
131 * @param pVM The cross context VM structure.
132 * @param pQueueCC The context specific queue data (same as @a pQueue for
133 * ring-3).
134 * @param pQueue The shared timer queue data.
135 * @param pTimer The timer that needs linking.
136 *
137 * @remarks Called while owning the relevant queue lock.
138 */
139DECL_FORCE_INLINE(void) tmTimerQueueUnlinkActive(PVMCC pVM, PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueue, PTMTIMER pTimer)
140{
141#ifdef VBOX_STRICT
142 TMTIMERSTATE const enmState = pTimer->enmState;
143 Assert( pQueue->enmClock == TMCLOCK_VIRTUAL_SYNC
144 ? enmState == TMTIMERSTATE_ACTIVE
145 : enmState == TMTIMERSTATE_PENDING_SCHEDULE || enmState == TMTIMERSTATE_PENDING_STOP_SCHEDULE);
146#endif
147 RT_NOREF(pVM);
148
149 const PTMTIMER pPrev = tmTimerGetPrev(pQueueCC, pTimer);
150 const PTMTIMER pNext = tmTimerGetNext(pQueueCC, pTimer);
151 if (pPrev)
152 tmTimerSetNext(pQueueCC, pPrev, pNext);
153 else
154 {
155 tmTimerQueueSetHead(pQueueCC, pQueue, pNext);
156 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX;
157 DBGFTRACE_U64_TAG(pVM, pQueue->u64Expire, "tmTimerQueueUnlinkActive");
158 }
159 if (pNext)
160 tmTimerSetPrev(pQueueCC, pNext, pPrev);
161 pTimer->idxNext = UINT32_MAX;
162 pTimer->idxPrev = UINT32_MAX;
163}
164
165/** @def TMTIMER_HANDLE_TO_VARS_RETURN_EX
166 * Converts a timer handle to a timer pointer, returning @a a_rcRet if the
167 * handle is invalid.
168 *
169 * This defines the following variables:
170 * - idxQueue: The queue index.
171 * - pQueueCC: Pointer to the context specific queue data.
172 * - pTimer: The timer pointer.
173 * - idxTimer: The timer index.
174 *
175 * @param a_pVM The cross context VM structure.
176 * @param a_hTimer The timer handle to translate.
177 * @param a_rcRet What to return on failure.
178 *
179 * @note This macro has no scoping, so careful when using it around
180 * conditional statements!
181 */
182#ifdef IN_RING3
183# define TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, a_rcRet) \
184 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
185 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
186 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \
187 PTMTIMERQUEUE const pQueue = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; \
188 PTMTIMERQUEUE const pQueueCC = pQueue; RT_NOREF(pQueueCC); \
189 \
190 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
191 AssertReturn(idxQueue < pQueue->cTimersAlloc, a_rcRet); \
192 \
193 PTMTIMER const pTimer = &pQueue->paTimers[idxTimer]; \
194 AssertReturn(pTimer->hSelf == a_hTimer, a_rcRet)
195#else
196# define TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, a_rcRet) \
197 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
198 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
199 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \
200 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \
201 PTMTIMERQUEUE const pQueue = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; RT_NOREF(pQueue); \
202 PTMTIMERQUEUER0 const pQueueCC = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue]; \
203 \
204 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
205 AssertReturn(idxQueue < pQueueCC->cTimersAlloc, a_rcRet); \
206 \
207 PTMTIMER const pTimer = &pQueueCC->paTimers[idxTimer]; \
208 AssertReturn(pTimer->hSelf == a_hTimer, a_rcRet); \
209 Assert(pTimer->fFlags & TMTIMER_FLAGS_RING0); \
210 Assert(VM_IS_EMT(pVM))
211#endif
212
213/** @def TMTIMER_HANDLE_TO_VARS_RETURN
214 * Converts a timer handle to a timer pointer, returning VERR_INVALID_HANDLE if
215 * the handle is invalid.
216 *
217 * This defines the following variables:
218 * - idxQueue: The queue index.
219 * - pQueueCC: Pointer to the context specific queue data.
220 * - pTimer: The timer pointer.
221 * - idxTimer: The timer index.
222 *
223 * @param a_pVM The cross context VM structure.
224 * @param a_hTimer The timer handle to translate.
225 *
226 * @note This macro has no scoping, so careful when using it around
227 * conditional statements!
228 */
229#define TMTIMER_HANDLE_TO_VARS_RETURN(a_pVM, a_hTimer) TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, VERR_INVALID_HANDLE)
230
231/** @def TMTIMER_HANDLE_TO_VARS_RETURN_VOID
232 * Converts a timer handle to a timer pointer, returning void if the
233 * handle is invalid.
234 *
235 * This defines the following variables:
236 * - idxQueue: The queue index.
237 * - pQueueCC: Pointer to the context specific queue data.
238 * - pTimer: The timer pointer.
239 * - idxTimer: The timer index.
240 *
241 * @param a_pVM The cross context VM structure.
242 * @param a_hTimer The timer handle to translate.
243 *
244 * @note This macro has no scoping, so careful when using it around
245 * conditional statements!
246 */
247#ifdef IN_RING3
248# define TMTIMER_HANDLE_TO_VARS_RETURN_VOID(a_pVM, a_hTimer) \
249 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
250 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
251 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \
252 PTMTIMERQUEUE const pQueue = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; \
253 PTMTIMERQUEUE const pQueueCC = pQueue; RT_NOREF(pQueueCC); \
254 \
255 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
256 AssertReturnVoid(idxQueue < pQueue->cTimersAlloc); \
257 \
258 PTMTIMER const pTimer = &pQueue->paTimers[idxTimer]; \
259 AssertReturnVoid(pTimer->hSelf == a_hTimer)
260#else
261# define TMTIMER_HANDLE_TO_VARS_RETURN_VOID(a_pVM, a_hTimer) \
262 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
263 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
264 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \
265 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \
266 PTMTIMERQUEUE const pQueue = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; RT_NOREF(pQueue); \
267 PTMTIMERQUEUER0 const pQueueCC = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue]; \
268 \
269 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
270 AssertReturnVoid(idxQueue < pQueueCC->cTimersAlloc); \
271 \
272 PTMTIMER const pTimer = &pQueueCC->paTimers[idxTimer]; \
273 AssertReturnVoid(pTimer->hSelf == a_hTimer); \
274 Assert(pTimer->fFlags & TMTIMER_FLAGS_RING0); \
275 Assert(VM_IS_EMT(pVM))
276#endif
277
278#endif /* !VMM_INCLUDED_SRC_include_TMInline_h */
279
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