VirtualBox

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

Last change on this file since 100594 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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