Changeset 87813 in vbox
- Timestamp:
- Feb 19, 2021 9:40:11 PM (4 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
-
VMMAll/TMAll.cpp (modified) (45 diffs)
-
VMMR3/TM.cpp (modified) (10 diffs)
-
include/TMInline.h (modified) (2 diffs)
-
include/TMInternal.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r87812 r87813 1147 1147 VMMDECL(int) TMTimerLock(PVMCC pVM, TMTIMERHANDLE hTimer, int rcBusy) 1148 1148 { 1149 PTMTIMER pTimer; 1150 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 1151 AssertPtr(pTimer); 1152 AssertReturn(pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC, VERR_NOT_SUPPORTED); 1149 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 1150 AssertReturn(idxQueue == TMCLOCK_VIRTUAL_SYNC, VERR_NOT_SUPPORTED); 1153 1151 return PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, rcBusy); 1154 1152 } … … 1163 1161 VMMDECL(void) TMTimerUnlock(PVMCC pVM, TMTIMERHANDLE hTimer) 1164 1162 { 1165 PTMTIMER pTimer; 1166 TMTIMER_HANDLE_TO_PTR_RETURN_VOID(pVM, hTimer, pTimer); 1167 AssertReturnVoid(pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC); 1163 TMTIMER_HANDLE_TO_VARS_RETURN_VOID(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 1164 AssertReturnVoid(idxQueue == TMCLOCK_VIRTUAL_SYNC); 1168 1165 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 1169 1166 } … … 1179 1176 VMMDECL(bool) TMTimerIsLockOwner(PVMCC pVM, TMTIMERHANDLE hTimer) 1180 1177 { 1181 PTMTIMER pTimer; 1182 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, false, pTimer); 1183 AssertPtr(pTimer); 1184 AssertReturn(pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC, false); 1178 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, false); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 1179 AssertReturn(idxQueue == TMCLOCK_VIRTUAL_SYNC, false); 1185 1180 return PDMCritSectIsOwner(&pVM->tm.s.VirtualSyncLock); 1186 1181 } … … 1196 1191 * @param u64Expire The new expire time. 1197 1192 * @param pQueue Pointer to the shared timer queue data. 1198 * @param enmClock The sanitized clock.1199 */ 1200 static int tmTimerSetOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t u64Expire, PTMTIMERQUEUE pQueue, TMCLOCK enmClock)1193 * @param idxQueue The queue index. 1194 */ 1195 static int tmTimerSetOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t u64Expire, PTMTIMERQUEUE pQueue, uint32_t idxQueue) 1201 1196 { 1202 1197 Assert(pTimer->idxPrev == UINT32_MAX); … … 1207 1202 * Calculate and set the expiration time. 1208 1203 */ 1209 if ( enmClock== TMCLOCK_VIRTUAL_SYNC)1204 if (idxQueue == TMCLOCK_VIRTUAL_SYNC) 1210 1205 { 1211 1206 uint64_t u64Last = ASMAtomicReadU64(&pVM->tm.s.u64VirtualSync); … … 1220 1215 * Link the timer into the active list. 1221 1216 */ 1222 tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, enmClock, pQueue), pQueue, pTimer, u64Expire);1217 tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, idxQueue, pQueue), pQueue, pTimer, u64Expire); 1223 1218 1224 1219 STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetOpt); … … 1309 1304 VMMDECL(int) TMTimerSet(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t u64Expire) 1310 1305 { 1311 PTMTIMER pTimer; 1312 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 1306 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 1313 1307 STAM_COUNTER_INC(&pTimer->StatSetAbsolute); 1314 1308 1315 1309 /* Treat virtual sync timers specially. */ 1316 if ( pTimer->enmClock== TMCLOCK_VIRTUAL_SYNC)1310 if (idxQueue == TMCLOCK_VIRTUAL_SYNC) 1317 1311 return tmTimerVirtualSyncSet(pVM, pTimer, u64Expire); 1318 1312 … … 1341 1335 #endif 1342 1336 1337 #if 1 1343 1338 /* 1344 1339 * The most common case is setting the timer again during the callback. 1345 1340 * The second most common case is starting a timer at some other time. 1346 1341 */ 1347 #if 11348 1342 TMTIMERSTATE enmState1 = pTimer->enmState; 1349 1343 if ( enmState1 == TMTIMERSTATE_EXPIRED_DELIVER … … 1352 1346 { 1353 1347 /* Try take the TM lock and check the state again. */ 1354 TMCLOCK const enmClock = pTimer->enmClock;1355 AssertReturn((unsigned)enmClock < TMCLOCK_MAX, VERR_TM_IPE_2);1356 PTMTIMERQUEUE const pQueue = &pVM->tm.s.aTimerQueues[enmClock];1357 1358 1348 int rc = PDMCritSectTryEnter(&pQueue->TimerLock); 1359 1349 if (RT_SUCCESS_NP(rc)) … … 1361 1351 if (RT_LIKELY(tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState1))) 1362 1352 { 1363 tmTimerSetOptimizedStart(pVM, pTimer, u64Expire, pQueue, enmClock);1353 tmTimerSetOptimizedStart(pVM, pTimer, u64Expire, pQueue, idxQueue); 1364 1354 STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatTimerSet), a); 1365 1355 PDMCritSectLeave(&pQueue->TimerLock); … … 1509 1499 * Optional. 1510 1500 * @param pQueue Pointer to the shared timer queue data. 1511 * @param enmClock The sanitized clock.1501 * @param idxQueue The queue index. 1512 1502 */ 1513 1503 static int tmTimerSetRelativeOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now, 1514 PTMTIMERQUEUE pQueue, TMCLOCK enmClock)1504 PTMTIMERQUEUE pQueue, uint32_t idxQueue) 1515 1505 { 1516 1506 Assert(pTimer->idxPrev == UINT32_MAX); … … 1521 1511 * Calculate and set the expiration time. 1522 1512 */ 1523 uint64_t const u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1513 uint64_t const u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1524 1514 pTimer->u64Expire = u64Expire; 1525 1515 Log2(("tmTimerSetRelativeOptimizedStart: %p:{.pszDesc='%s', .u64Expire=%'RU64} cTicksToNext=%'RU64\n", pTimer, pTimer->szName, u64Expire, cTicksToNext)); … … 1529 1519 */ 1530 1520 DBGFTRACE_U64_TAG2(pVM, u64Expire, "tmTimerSetRelativeOptimizedStart", pTimer->szName); 1531 tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, enmClock, pQueue), pQueue, pTimer, u64Expire);1521 tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, idxQueue, pQueue), pQueue, pTimer, u64Expire); 1532 1522 1533 1523 STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeOpt); 1524 RT_NOREF(idxQueue); 1534 1525 return VINF_SUCCESS; 1535 1526 } … … 1624 1615 * Optional. 1625 1616 */ 1626 static int tmTimerSetRelative(PVMCC pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now) 1617 static int tmTimerSetRelative(PVMCC pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now, 1618 PTMTIMERQUEUE pQueue, uint32_t idxQueue) 1627 1619 { 1628 1620 STAM_COUNTER_INC(&pTimer->StatSetRelative); 1629 1621 1630 1622 /* Treat virtual sync timers specially. */ 1631 TMCLOCK enmClock = pTimer->enmClock; 1632 if (enmClock == TMCLOCK_VIRTUAL_SYNC) 1623 if (idxQueue == TMCLOCK_VIRTUAL_SYNC) 1633 1624 return tmTimerVirtualSyncSetRelative(pVM, pTimer, cTicksToNext, pu64Now); 1634 AssertReturn((unsigned)enmClock < (unsigned)TMCLOCK_MAX, VERR_TM_IPE_2);1635 1625 1636 1626 STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a); … … 1668 1658 * longer as this isn't supported for any timers, critsect or not.) 1669 1659 * 1670 * Note! Lock ordering doesn't apply when we only triesto1660 * Note! Lock ordering doesn't apply when we only _try_ to 1671 1661 * get the innermost locks. 1672 1662 */ 1673 PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[enmClock];1674 1663 bool fOwnTMLock = RT_SUCCESS_NP(PDMCritSectTryEnter(&pQueue->TimerLock)); 1675 1664 #if 1 … … 1682 1671 && tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState))) 1683 1672 { 1684 tmTimerSetRelativeOptimizedStart(pVM, pTimer, cTicksToNext, pu64Now, pQueue, enmClock);1673 tmTimerSetRelativeOptimizedStart(pVM, pTimer, cTicksToNext, pu64Now, pQueue, idxQueue); 1685 1674 STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a); 1686 1675 PDMCritSectLeave(&pQueue->TimerLock); … … 1705 1694 { 1706 1695 case TMTIMERSTATE_STOPPED: 1707 if ( enmClock == TMCLOCK_VIRTUAL_SYNC)1696 if (pQueue->enmClock == TMCLOCK_VIRTUAL_SYNC) 1708 1697 { 1709 1698 /** @todo To fix assertion in tmR3TimerQueueRunVirtualSync: … … 1719 1708 Assert(pTimer->idxPrev == UINT32_MAX); 1720 1709 Assert(pTimer->idxNext == UINT32_MAX); 1721 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1710 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1722 1711 Log2(("TMTimerSetRelative: %p:{.enmState=%s, .pszDesc='%s', .u64Expire=%'RU64} cRetries=%d [EXP/STOP]\n", 1723 1712 pTimer, tmTimerState(enmState), pTimer->szName, pTimer->u64Expire, cRetries)); … … 1734 1723 if (tmTimerTry(pTimer, TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE, enmState)) 1735 1724 { 1736 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1725 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1737 1726 Log2(("TMTimerSetRelative: %p:{.enmState=%s, .pszDesc='%s', .u64Expire=%'RU64} cRetries=%d [PEND_SCHED]\n", 1738 1727 pTimer, tmTimerState(enmState), pTimer->szName, pTimer->u64Expire, cRetries)); … … 1749 1738 if (tmTimerTryWithLink(pVM, pTimer, TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE, enmState)) 1750 1739 { 1751 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1740 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1752 1741 Log2(("TMTimerSetRelative: %p:{.enmState=%s, .pszDesc='%s', .u64Expire=%'RU64} cRetries=%d [ACTIVE]\n", 1753 1742 pTimer, tmTimerState(enmState), pTimer->szName, pTimer->u64Expire, cRetries)); … … 1764 1753 if (tmTimerTry(pTimer, TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE, enmState)) 1765 1754 { 1766 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1755 pTimer->u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1767 1756 Log2(("TMTimerSetRelative: %p:{.enmState=%s, .pszDesc='%s', .u64Expire=%'RU64} cRetries=%d [PEND_RESCH/STOP]\n", 1768 1757 pTimer, tmTimerState(enmState), pTimer->szName, pTimer->u64Expire, cRetries)); … … 1809 1798 if (rc != VERR_TRY_AGAIN) 1810 1799 { 1811 tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1800 tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1812 1801 break; 1813 1802 } … … 1816 1805 AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->szName)); 1817 1806 rc = VERR_TM_TIMER_UNSTABLE_STATE; 1818 tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);1807 tmTimerSetRelativeNowWorker(pVM, pQueue->enmClock, pu64Now); 1819 1808 break; 1820 1809 } … … 1851 1840 VMMDECL(int) TMTimerSetRelative(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now) 1852 1841 { 1853 PTMTIMER pTimer; 1854 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 1855 return tmTimerSetRelative(pVM, pTimer, cTicksToNext, pu64Now); 1842 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 1843 return tmTimerSetRelative(pVM, pTimer, cTicksToNext, pu64Now, pQueue, idxQueue); 1856 1844 } 1857 1845 … … 2083 2071 VMMDECL(uint64_t) TMTimerGet(PVMCC pVM, TMTIMERHANDLE hTimer) 2084 2072 { 2085 PTMTIMER pTimer; 2086 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, UINT64_MAX, pTimer); 2073 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2087 2074 STAM_COUNTER_INC(&pTimer->StatGet); 2088 2075 2089 2076 uint64_t u64; 2090 switch (p Timer->enmClock)2077 switch (pQueue->enmClock) 2091 2078 { 2092 2079 case TMCLOCK_VIRTUAL: … … 2100 2087 break; 2101 2088 default: 2102 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2089 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2103 2090 return UINT64_MAX; 2104 2091 } … … 2118 2105 VMMDECL(uint64_t) TMTimerGetFreq(PVMCC pVM, TMTIMERHANDLE hTimer) 2119 2106 { 2120 PTMTIMER pTimer; 2121 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2122 switch (pTimer->enmClock) 2107 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2108 switch (pQueue->enmClock) 2123 2109 { 2124 2110 case TMCLOCK_VIRTUAL: … … 2130 2116 2131 2117 default: 2132 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2118 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2133 2119 return 0; 2134 2120 } … … 2146 2132 VMMDECL(uint64_t) TMTimerGetExpire(PVMCC pVM, TMTIMERHANDLE hTimer) 2147 2133 { 2148 PTMTIMER pTimer; 2149 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, UINT64_MAX, pTimer); 2134 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, UINT64_MAX); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2150 2135 TMTIMER_ASSERT_CRITSECT(pVM, pTimer); 2151 2136 int cRetries = 1000; 2152 2137 do 2153 2138 { 2154 TMTIMERSTATE enmState = pTimer->enmState;2139 TMTIMERSTATE enmState = pTimer->enmState; 2155 2140 switch (enmState) 2156 2141 { … … 2211 2196 VMMDECL(bool) TMTimerIsActive(PVMCC pVM, TMTIMERHANDLE hTimer) 2212 2197 { 2213 PTMTIMER pTimer; 2214 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, false, pTimer); 2198 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, false); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2215 2199 TMTIMERSTATE enmState = pTimer->enmState; 2216 2200 switch (enmState) … … 2263 2247 VMMDECL(int) TMTimerSetMillies(PVMCC pVM, TMTIMERHANDLE hTimer, uint32_t cMilliesToNext) 2264 2248 { 2265 PTMTIMER pTimer; 2266 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2267 switch (pTimer->enmClock) 2249 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2250 switch (pQueue->enmClock) 2268 2251 { 2269 2252 case TMCLOCK_VIRTUAL: 2270 2253 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2271 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext * UINT64_C(1000000), NULL );2254 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext * UINT64_C(1000000), NULL, pQueue, idxQueue); 2272 2255 2273 2256 case TMCLOCK_VIRTUAL_SYNC: 2274 2257 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2275 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext * UINT64_C(1000000), NULL );2258 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext * UINT64_C(1000000), NULL, pQueue, idxQueue); 2276 2259 2277 2260 case TMCLOCK_REAL: 2278 2261 AssertCompile(TMCLOCK_FREQ_REAL == 1000); 2279 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext, NULL );2262 return tmTimerSetRelative(pVM, pTimer, cMilliesToNext, NULL, pQueue, idxQueue); 2280 2263 2281 2264 default: 2282 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2265 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2283 2266 return VERR_TM_TIMER_BAD_CLOCK; 2284 2267 } … … 2296 2279 VMMDECL(int) TMTimerSetMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext) 2297 2280 { 2298 PTMTIMER pTimer; 2299 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2300 switch (pTimer->enmClock) 2281 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2282 switch (pQueue->enmClock) 2301 2283 { 2302 2284 case TMCLOCK_VIRTUAL: 2303 2285 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2304 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext * 1000, NULL );2286 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext * 1000, NULL, pQueue, idxQueue); 2305 2287 2306 2288 case TMCLOCK_VIRTUAL_SYNC: 2307 2289 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2308 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext * 1000, NULL );2290 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext * 1000, NULL, pQueue, idxQueue); 2309 2291 2310 2292 case TMCLOCK_REAL: 2311 2293 AssertCompile(TMCLOCK_FREQ_REAL == 1000); 2312 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext / 1000, NULL );2294 return tmTimerSetRelative(pVM, pTimer, cMicrosToNext / 1000, NULL, pQueue, idxQueue); 2313 2295 2314 2296 default: 2315 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2297 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2316 2298 return VERR_TM_TIMER_BAD_CLOCK; 2317 2299 } … … 2329 2311 VMMDECL(int) TMTimerSetNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cNanosToNext) 2330 2312 { 2331 PTMTIMER pTimer; 2332 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2313 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2333 2314 switch (pTimer->enmClock) 2334 2315 { 2335 2316 case TMCLOCK_VIRTUAL: 2336 2317 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2337 return tmTimerSetRelative(pVM, pTimer, cNanosToNext, NULL );2318 return tmTimerSetRelative(pVM, pTimer, cNanosToNext, NULL, pQueue, idxQueue); 2338 2319 2339 2320 case TMCLOCK_VIRTUAL_SYNC: 2340 2321 AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000); 2341 return tmTimerSetRelative(pVM, pTimer, cNanosToNext, NULL );2322 return tmTimerSetRelative(pVM, pTimer, cNanosToNext, NULL, pQueue, idxQueue); 2342 2323 2343 2324 case TMCLOCK_REAL: 2344 2325 AssertCompile(TMCLOCK_FREQ_REAL == 1000); 2345 return tmTimerSetRelative(pVM, pTimer, cNanosToNext / 1000000, NULL );2326 return tmTimerSetRelative(pVM, pTimer, cNanosToNext / 1000000, NULL, pQueue, idxQueue); 2346 2327 2347 2328 default: … … 2403 2384 VMMDECL(uint64_t) TMTimerToNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks) 2404 2385 { 2405 PTMTIMER pTimer; 2406 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2407 switch (pTimer->enmClock) 2386 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2387 switch (pQueue->enmClock) 2408 2388 { 2409 2389 case TMCLOCK_VIRTUAL: … … 2417 2397 2418 2398 default: 2419 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2399 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2420 2400 return 0; 2421 2401 } … … 2435 2415 VMMDECL(uint64_t) TMTimerToMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks) 2436 2416 { 2437 PTMTIMER pTimer; 2438 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2439 switch (pTimer->enmClock) 2417 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2418 switch (pQueue->enmClock) 2440 2419 { 2441 2420 case TMCLOCK_VIRTUAL: … … 2449 2428 2450 2429 default: 2451 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2430 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2452 2431 return 0; 2453 2432 } … … 2467 2446 VMMDECL(uint64_t) TMTimerToMilli(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks) 2468 2447 { 2469 PTMTIMER pTimer; 2470 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2471 switch (pTimer->enmClock) 2448 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2449 switch (pQueue->enmClock) 2472 2450 { 2473 2451 case TMCLOCK_VIRTUAL: … … 2481 2459 2482 2460 default: 2483 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2461 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2484 2462 return 0; 2485 2463 } … … 2498 2476 VMMDECL(uint64_t) TMTimerFromNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cNanoSecs) 2499 2477 { 2500 PTMTIMER pTimer; 2501 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2502 switch (pTimer->enmClock) 2478 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2479 switch (pQueue->enmClock) 2503 2480 { 2504 2481 case TMCLOCK_VIRTUAL: … … 2512 2489 2513 2490 default: 2514 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2491 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2515 2492 return 0; 2516 2493 } … … 2529 2506 VMMDECL(uint64_t) TMTimerFromMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMicroSecs) 2530 2507 { 2531 PTMTIMER pTimer; 2532 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2533 switch (pTimer->enmClock) 2508 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2509 switch (pQueue->enmClock) 2534 2510 { 2535 2511 case TMCLOCK_VIRTUAL: … … 2543 2519 2544 2520 default: 2545 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2521 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2546 2522 return 0; 2547 2523 } … … 2560 2536 VMMDECL(uint64_t) TMTimerFromMilli(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMilliSecs) 2561 2537 { 2562 PTMTIMER pTimer; 2563 TMTIMER_HANDLE_TO_PTR_RETURN_EX(pVM, hTimer, 0, pTimer); 2564 switch (pTimer->enmClock) 2538 TMTIMER_HANDLE_TO_VARS_RETURN_EX(pVM, hTimer, 0); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2539 switch (pQueue->enmClock) 2565 2540 { 2566 2541 case TMCLOCK_VIRTUAL: … … 2574 2549 2575 2550 default: 2576 AssertMsgFailed(("Invalid enmClock=%d\n", p Timer->enmClock));2551 AssertMsgFailed(("Invalid enmClock=%d\n", pQueue->enmClock)); 2577 2552 return 0; 2578 2553 } -
trunk/src/VBox/VMM/VMMR3/TM.cpp
r87812 r87813 1883 1883 * @returns VBox status code. 1884 1884 * @param pVM The cross context VM structure. 1885 * @param pQueue The queue the timer is on. 1885 1886 * @param pTimer Timer handle as returned by one of the create functions. 1886 1887 */ 1887 static int tmR3TimerDestroy(PVMCC pVM, PTMTIMER pTimer) 1888 { 1889 AssertReturn((unsigned)pTimer->enmClock < (unsigned)TMCLOCK_MAX, VERR_INTERNAL_ERROR_3); 1890 1891 PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[pTimer->enmClock]; 1892 bool fActive = false; 1893 bool fPending = false; 1888 static int tmR3TimerDestroy(PVMCC pVM, PTMTIMERQUEUE pQueue, PTMTIMER pTimer) 1889 { 1890 bool fActive = false; 1891 bool fPending = false; 1894 1892 1895 1893 AssertMsg( !pTimer->pCritSect … … 2059 2057 if (hTimer == NIL_TMTIMERHANDLE) 2060 2058 return VINF_SUCCESS; 2061 PTMTIMER pTimer; 2062 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2063 return tmR3TimerDestroy(pVM, pTimer); 2059 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2060 return tmR3TimerDestroy(pVM, pQueue, pTimer); 2064 2061 } 2065 2062 … … 2092 2089 PDMCritSectRwLeaveShared(&pQueue->AllocLock); 2093 2090 2094 int rc = tmR3TimerDestroy(pVM, p Timer);2091 int rc = tmR3TimerDestroy(pVM, pQueue, pTimer); 2095 2092 AssertRC(rc); 2096 2093 … … 2133 2130 PDMCritSectRwLeaveShared(&pQueue->AllocLock); 2134 2131 2135 int rc = tmR3TimerDestroy(pVM, p Timer);2132 int rc = tmR3TimerDestroy(pVM, pQueue, pTimer); 2136 2133 AssertRC(rc); 2137 2134 … … 2174 2171 PDMCritSectRwLeaveShared(&pQueue->AllocLock); 2175 2172 2176 int rc = tmR3TimerDestroy(pVM, p Timer);2173 int rc = tmR3TimerDestroy(pVM, pQueue, pTimer); 2177 2174 AssertRC(rc); 2178 2175 … … 2883 2880 { 2884 2881 VM_ASSERT_EMT(pVM); 2885 PTMTIMER pTimer; 2886 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2882 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2887 2883 LogFlow(("TMR3TimerSave: %p:{enmState=%s, .szName='%s'} pSSM=%p\n", pTimer, tmTimerState(pTimer->enmState), pTimer->szName, pSSM)); 2888 2884 … … 2931 2927 { 2932 2928 VM_ASSERT_EMT(pVM); 2933 PTMTIMER pTimer; 2934 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 2929 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 2935 2930 Assert(pSSM); 2936 2931 LogFlow(("TMR3TimerLoad: %p:{enmState=%s, .szName='%s'} pSSM=%p\n", pTimer, tmTimerState(pTimer->enmState), pTimer->szName, pSSM)); … … 2957 2952 2958 2953 /* Enter the critical sections to make TMTimerSet/Stop happy. */ 2959 if (p Timer->enmClock == TMCLOCK_VIRTUAL_SYNC)2954 if (pQueue->enmClock == TMCLOCK_VIRTUAL_SYNC) 2960 2955 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); 2961 2956 PPDMCRITSECT pCritSect = pTimer->pCritSect; … … 2990 2985 if (pCritSect) 2991 2986 PDMCritSectLeave(pCritSect); 2992 if (p Timer->enmClock == TMCLOCK_VIRTUAL_SYNC)2987 if (pQueue->enmClock == TMCLOCK_VIRTUAL_SYNC) 2993 2988 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 2994 2989 … … 3080 3075 VMMR3DECL(int) TMR3TimerSetCritSect(PVM pVM, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect) 3081 3076 { 3082 PTMTIMER pTimer; 3083 TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer); 3077 TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */ 3084 3078 AssertPtrReturn(pCritSect, VERR_INVALID_PARAMETER); 3085 3079 const char *pszName = PDMR3CritSectName(pCritSect); /* exploited for validation */ -
trunk/src/VBox/VMM/include/TMInline.h
r87812 r87813 211 211 #endif 212 212 213 214 213 /** @def TMTIMER_HANDLE_TO_VARS_RETURN_EX 215 214 * Converts a timer handle to a timer pointer, returning VERR_INVALID_HANDLE if … … 230 229 #define TMTIMER_HANDLE_TO_VARS_RETURN(a_pVM, a_hTimer) TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, VERR_INVALID_HANDLE) 231 230 232 233 /** @def TMTIMER_HANDLE_TO_PTR_RETURN_EX 234 * Converts a timer handle to a timer pointer, returning @a a_rcRet if the 231 /** @def TMTIMER_HANDLE_TO_VARS_RETURN_VOID 232 * Converts a timer handle to a timer pointer, returning void if the 235 233 * handle is invalid. 236 234 * 237 * @param a_pVM The cross context VM structure. 238 * @param a_hTimer The timer handle to translate. 239 * @param a_rcRet What to return on failure. 240 * @param a_pTimerVar The timer variable to assign the resulting pointer to. 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! 241 246 */ 242 247 #ifdef IN_RING3 243 # define TMTIMER_HANDLE_TO_PTR_RETURN_EX(a_pVM, a_hTimer, a_rcRet, a_pTimerVar) do { \ 244 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 245 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 246 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \ 247 \ 248 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 249 AssertReturn(idxQueue < (a_pVM)->tm.s.aTimerQueues[idxQueue].cTimersAlloc, a_rcRet); \ 250 \ 251 (a_pTimerVar) = &(a_pVM)->tm.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 252 AssertReturn((a_pTimerVar)->hSelf == a_hTimer, a_rcRet); \ 253 } while (0) 254 #else 255 # define TMTIMER_HANDLE_TO_PTR_RETURN_EX(a_pVM, a_hTimer, a_rcRet, a_pTimerVar) do { \ 256 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 257 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 258 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \ 259 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \ 260 \ 261 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 262 AssertReturn(idxQueue < (a_pVM)->tmr0.s.aTimerQueues[idxQueue].cTimersAlloc, a_rcRet); \ 263 \ 264 (a_pTimerVar) = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 265 AssertReturn((a_pTimerVar)->hSelf == a_hTimer, a_rcRet); \ 266 Assert((a_pTimerVar)->fFlags & TMTIMER_FLAGS_RING0); \ 267 Assert(VM_IS_EMT(pVM)); \ 268 } while (0) 269 #endif 270 271 /** @def TMTIMER_HANDLE_TO_PTR_RETURN 272 * Converts a timer handle to a timer pointer, returning VERR_INVALID_HANDLE if 273 * invalid. 274 * 275 * @param a_pVM The cross context VM structure. 276 * @param a_hTimer The timer handle to translate. 277 * @param a_pTimerVar The timer variable to assign the resulting pointer to. 278 */ 279 #define TMTIMER_HANDLE_TO_PTR_RETURN(a_pVM, a_hTimer, a_pTimerVar) \ 280 TMTIMER_HANDLE_TO_PTR_RETURN_EX(a_pVM, a_hTimer, VERR_INVALID_HANDLE, a_pTimerVar) 281 282 /** @def TMTIMER_HANDLE_TO_PTR_RETURN_VOID 283 * Converts a timer handle to a timer pointer, returning VERR_INVALID_HANDLE if 284 * invalid. 285 * 286 * @param a_pVM The cross context VM structure. 287 * @param a_hTimer The timer handle to translate. 288 * @param a_pTimerVar The timer variable to assign the resulting pointer to. 289 */ 290 #ifdef IN_RING3 291 # define TMTIMER_HANDLE_TO_PTR_RETURN_VOID(a_pVM, a_hTimer, a_pTimerVar) do { \ 248 # define TMTIMER_HANDLE_TO_VARS_RETURN_VOID(a_pVM, a_hTimer) \ 292 249 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 293 250 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 294 251 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \ 295 \ 296 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 297 AssertReturnVoid(idxQueue < (a_pVM)->tm.s.aTimerQueues[idxQueue].cTimersAlloc); \ 298 \ 299 (a_pTimerVar) = &(a_pVM)->tm.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 300 AssertReturnVoid((a_pTimerVar)->hSelf == a_hTimer); \ 301 } while (0) 302 #else 303 # define TMTIMER_HANDLE_TO_PTR_RETURN_VOID(a_pVM, a_hTimer, a_pTimerVar) do { \ 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) \ 304 262 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 305 263 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 306 264 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \ 307 265 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \ 308 \309 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \310 AssertReturnVoid(idxQueue < (a_pVM)->tmr0.s.aTimerQueues[idxQueue].cTimersAlloc);\311 \312 (a_pTimerVar) = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \313 AssertReturnVoid((a_pTimerVar)->hSelf == a_hTimer);\314 Assert((a_pTimerVar)->fFlags & TMTIMER_FLAGS_RING0); \315 Assert (VM_IS_EMT(pVM)); \316 } while (0)317 #endif 318 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 319 277 320 278 #endif /* !VMM_INCLUDED_SRC_include_TMInline_h */ -
trunk/src/VBox/VMM/include/TMInternal.h
r87812 r87813 285 285 /** Align on 64-byte boundrary. */ 286 286 bool afAlignment1[7]; 287 287 288 /** Time spent doing scheduling and timer callbacks. */ 288 289 STAMPROFILE StatDo; … … 290 291 uint32_t volatile uMaxHzHint; 291 292 uint32_t u64Alignment2[7]; 293 292 294 /** Lock serializing the active timer list and associated work. */ 293 295 PDMCRITSECT TimerLock;
Note:
See TracChangeset
for help on using the changeset viewer.

