Changeset 87812 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Feb 19, 2021 8:54:49 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142873
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/TM.cpp
r87796 r87812 210 210 AssertCompileMemberAlignment(VM, tm.s, 32); 211 211 AssertCompile(sizeof(pVM->tm.s) <= sizeof(pVM->tm.padding)); 212 AssertCompileMemberAlignment(TM, TimerCritSect, 8);213 212 AssertCompileMemberAlignment(TM, VirtualSyncLock, 8); 214 213 … … 217 216 */ 218 217 pVM->tm.s.idTimerCpu = pVM->cCpus - 1; /* The last CPU. */ 218 219 int rc = PDMR3CritSectInit(pVM, &pVM->tm.s.VirtualSyncLock, RT_SRC_POS, "TM VirtualSync Lock"); 220 AssertLogRelRCReturn(rc, rc); 219 221 220 222 strcpy(pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].szName, "virtual"); … … 231 233 pVM->tm.s.aTimerQueues[i].idxSchedule = UINT32_MAX; 232 234 pVM->tm.s.aTimerQueues[i].idxFreeHint = 1; 233 int rc = PDMR3CritSectRwInit(pVM, &pVM->tm.s.aTimerQueues[i].AllocLock, RT_SRC_POS, 234 "TM queue %s", pVM->tm.s.aTimerQueues[i].szName); 235 rc = PDMR3CritSectInit(pVM, &pVM->tm.s.aTimerQueues[i].TimerLock, RT_SRC_POS, 236 "TM %s queue timer lock", pVM->tm.s.aTimerQueues[i].szName); 237 AssertLogRelRCReturn(rc, rc); 238 239 rc = PDMR3CritSectRwInit(pVM, &pVM->tm.s.aTimerQueues[i].AllocLock, RT_SRC_POS, 240 "TM %s queue alloc lock", pVM->tm.s.aTimerQueues[i].szName); 235 241 AssertLogRelRCReturn(rc, rc); 236 242 } … … 249 255 250 256 RTHCPHYS HCPhysGIP; 251 intrc = SUPR3GipGetPhys(&HCPhysGIP);257 rc = SUPR3GipGetPhys(&HCPhysGIP); 252 258 AssertMsgRCReturn(rc, ("Failed to get GIP physical address!\n"), rc); 253 259 … … 305 311 AssertRelease(pVM->tm.s.VirtualGetRawDataR0.pu64Prev); 306 312 /* The rest is done in TMR3InitFinalize() since it's too early to call PDM. */ 307 308 /*309 * Init the locks.310 */311 rc = PDMR3CritSectInit(pVM, &pVM->tm.s.TimerCritSect, RT_SRC_POS, "TM Timer Lock");312 if (RT_FAILURE(rc))313 return rc;314 rc = PDMR3CritSectInit(pVM, &pVM->tm.s.VirtualSyncLock, RT_SRC_POS, "TM VirtualSync Lock");315 if (RT_FAILURE(rc))316 return rc;317 313 318 314 /* … … 699 695 STAM_REL_REG( pVM,(void*)&pVM->tm.s.offVirtualSync, STAMTYPE_U64, "/TM/VirtualSync/CurrentOffset", STAMUNIT_NS, "The current offset. (subtract GivenUp to get the lag)"); 700 696 STAM_REL_REG_USED(pVM,(void*)&pVM->tm.s.offVirtualSyncGivenUp, STAMTYPE_U64, "/TM/VirtualSync/GivenUp", STAMUNIT_NS, "Nanoseconds of the 'CurrentOffset' that's been given up and won't ever be attempted caught up with."); 701 STAM_REL_REG( pVM,(void*)&pVM->tm.s.uMaxHzHint, STAMTYPE_U32, "/TM/MaxHzHint", STAMUNIT_HZ, "Max guest timer frequency hint."); 697 STAM_REL_REG( pVM,(void*)&pVM->tm.s.HzHint.s.uMax, STAMTYPE_U32, "/TM/MaxHzHint", STAMUNIT_HZ, "Max guest timer frequency hint."); 698 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->tm.s.aTimerQueues); i++) 699 { 700 rc = STAMR3RegisterF(pVM, (void *)&pVM->tm.s.aTimerQueues[i].uMaxHzHint, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_HZ, 701 "", "/TM/MaxHzHint/%s", pVM->tm.s.aTimerQueues[i].szName); 702 AssertRC(rc); 703 } 702 704 703 705 #ifdef VBOX_WITH_STATISTICS … … 709 711 STAM_REG_USED(pVM,(void *)&pVM->tm.s.VirtualGetRawDataRC.cUpdateRaces,STAMTYPE_U32, "/TM/RC/cUpdateRaces", STAMUNIT_OCCURENCES, "Thread races when updating the previous timestamp."); 710 712 STAM_REG(pVM, &pVM->tm.s.StatDoQueues, STAMTYPE_PROFILE, "/TM/DoQueues", STAMUNIT_TICKS_PER_CALL, "Profiling timer TMR3TimerQueuesDo."); 711 STAM_REG(pVM, &pVM->tm.s.a StatDoQueues[TMCLOCK_VIRTUAL], STAMTYPE_PROFILE_ADV, "/TM/DoQueues/Virtual", STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual clock queue.");712 STAM_REG(pVM, &pVM->tm.s.a StatDoQueues[TMCLOCK_VIRTUAL_SYNC], STAMTYPE_PROFILE_ADV,"/TM/DoQueues/VirtualSync", STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual sync clock queue.");713 STAM_REG(pVM, &pVM->tm.s.a StatDoQueues[TMCLOCK_REAL], STAMTYPE_PROFILE_ADV, "/TM/DoQueues/Real", STAMUNIT_TICKS_PER_CALL, "Time spent on the real clock queue.");713 STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].StatDo, STAMTYPE_PROFILE, "/TM/DoQueues/Virtual", STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual clock queue."); 714 STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].StatDo,STAMTYPE_PROFILE,"/TM/DoQueues/VirtualSync", STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual sync clock queue."); 715 STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL].StatDo, STAMTYPE_PROFILE, "/TM/DoQueues/Real", STAMUNIT_TICKS_PER_CALL, "Time spent on the real clock queue."); 714 716 715 717 STAM_REG(pVM, &pVM->tm.s.StatPoll, STAMTYPE_COUNTER, "/TM/Poll", STAMUNIT_OCCURENCES, "TMTimerPoll calls."); … … 1212 1214 LogFlow(("TMR3Reset:\n")); 1213 1215 VM_ASSERT_EMT(pVM); 1214 TM_LOCK_TIMERS(pVM);1215 1216 1216 1217 /* … … 1239 1240 * Process the queues. 1240 1241 */ 1241 for (int i = 0; i < TMCLOCK_MAX; i++) 1242 tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[i], &pVM->tm.s.aTimerQueues[i]); 1242 for (uint32_t idxQueue = 0; idxQueue < RT_ELEMENTS(pVM->tm.s.aTimerQueues); idxQueue++) 1243 { 1244 PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue]; 1245 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 1246 tmTimerQueueSchedule(pVM, pQueue, pQueue); 1247 PDMCritSectLeave(&pQueue->TimerLock); 1248 } 1243 1249 #ifdef VBOX_STRICT 1244 1250 tmTimerQueuesSanityChecks(pVM, "TMR3Reset"); … … 1292 1298 pVCpu->tm.s.u64TSCLastSeen = 0; 1293 1299 } 1294 1295 TM_UNLOCK_TIMERS(pVM);1296 1300 } 1297 1301 … … 1693 1697 1694 1698 #ifdef VBOX_STRICT 1695 TM_LOCK_TIMERS(pVM);1696 1699 tmTimerQueuesSanityChecks(pVM, "tmR3TimerCreate"); 1697 TM_UNLOCK_TIMERS(pVM);1698 1700 #endif 1699 1701 … … 1900 1902 */ 1901 1903 PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED); 1902 TM_LOCK_TIMERS(pVM); 1904 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 1905 1903 1906 for (int cRetries = 1000;; cRetries--) 1904 1907 { … … 1937 1940 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: 1938 1941 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName)); 1939 TM_UNLOCK_TIMERS(pVM);1942 PDMCritSectLeave(&pQueue->TimerLock); 1940 1943 PDMCritSectRwLeaveExcl(&pQueue->AllocLock); 1941 1944 … … 1946 1949 1947 1950 PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED); 1948 TM_LOCK_TIMERS(pVM);1951 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 1949 1952 continue; 1950 1953 … … 1954 1957 case TMTIMERSTATE_FREE: 1955 1958 case TMTIMERSTATE_DESTROY: 1956 TM_UNLOCK_TIMERS(pVM);1959 PDMCritSectLeave(&pQueue->TimerLock); 1957 1960 PDMCritSectRwLeaveExcl(&pQueue->AllocLock); 1958 1961 AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE); … … 1960 1963 default: 1961 1964 AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, pTimer->szName)); 1962 TM_UNLOCK_TIMERS(pVM);1965 PDMCritSectLeave(&pQueue->TimerLock); 1963 1966 PDMCritSectRwLeaveExcl(&pQueue->AllocLock); 1964 1967 return VERR_TM_UNKNOWN_STATE; … … 1974 1977 break; 1975 1978 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName)); 1976 TM_UNLOCK_TIMERS(pVM);1979 PDMCritSectLeave(&pQueue->TimerLock); 1977 1980 PDMCritSectRwLeaveExcl(&pQueue->AllocLock); 1978 1981 … … 1981 1984 1982 1985 PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED); 1983 TM_LOCK_TIMERS(pVM);1986 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 1984 1987 } 1985 1988 … … 2038 2041 tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy"); 2039 2042 #endif 2040 TM_UNLOCK_TIMERS(pVM);2043 PDMCritSectLeave(&pQueue->TimerLock); 2041 2044 PDMCritSectRwLeaveExcl(&pQueue->AllocLock); 2042 2045 return VINF_SUCCESS; … … 2324 2327 Assert(!pVM->tm.s.fRunningQueues); 2325 2328 ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, true); 2326 TM_LOCK_TIMERS(pVM);2327 2329 2328 2330 /* … … 2331 2333 AssertCompile(TMCLOCK_MAX == 4); 2332 2334 2333 /* TMCLOCK_VIRTUAL_SYNC (see also TMR3VirtualSyncFF) */ 2334 STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1); 2335 /* 2336 * TMCLOCK_VIRTUAL_SYNC (see also TMR3VirtualSyncFF) 2337 */ 2338 PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC]; 2339 STAM_PROFILE_START(&pQueue->StatDo, s1); 2340 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 2335 2341 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); 2336 2342 ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, true); 2337 2343 VMCPU_FF_CLEAR(pVCpuDst, VMCPU_FF_TIMER); /* Clear the FF once we started working for real. */ 2338 2344 2339 Assert(p VM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].idxSchedule == UINT32_MAX);2345 Assert(pQueue->idxSchedule == UINT32_MAX); 2340 2346 tmR3TimerQueueRunVirtualSync(pVM); 2341 2347 if (pVM->tm.s.fVirtualSyncTicking) /** @todo move into tmR3TimerQueueRunVirtualSync - FIXME */ … … 2344 2350 ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false); 2345 2351 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 2346 STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1); 2347 2348 /* TMCLOCK_VIRTUAL */ 2349 STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL], s2); 2350 if (pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].idxSchedule != UINT32_MAX) 2351 tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL], &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL]); 2352 tmR3TimerQueueRun(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL]); 2353 STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL], s2); 2354 2355 /* TMCLOCK_TSC */ 2352 PDMCritSectLeave(&pQueue->TimerLock); 2353 STAM_PROFILE_STOP(&pQueue->StatDo, s1); 2354 2355 /* 2356 * TMCLOCK_VIRTUAL 2357 */ 2358 pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL]; 2359 STAM_PROFILE_START(&pQueue->StatDo, s2); 2360 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 2361 if (pQueue->idxSchedule != UINT32_MAX) 2362 tmTimerQueueSchedule(pVM, pQueue, pQueue); 2363 tmR3TimerQueueRun(pVM, pQueue); 2364 PDMCritSectLeave(&pQueue->TimerLock); 2365 STAM_PROFILE_STOP(&pQueue->StatDo, s2); 2366 2367 /* 2368 * TMCLOCK_TSC 2369 */ 2356 2370 Assert(pVM->tm.s.aTimerQueues[TMCLOCK_TSC].idxActive == UINT32_MAX); /* not used */ 2357 2371 2358 /* TMCLOCK_REAL */ 2359 STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_REAL], s3); 2360 if (pVM->tm.s.aTimerQueues[TMCLOCK_REAL].idxSchedule != UINT32_MAX) 2361 tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL], &pVM->tm.s.aTimerQueues[TMCLOCK_REAL]); 2362 tmR3TimerQueueRun(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL]); 2363 STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_REAL], s3); 2372 /* 2373 * TMCLOCK_REAL 2374 */ 2375 pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_REAL]; 2376 STAM_PROFILE_START(&pQueue->StatDo, s3); 2377 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 2378 if (pQueue->idxSchedule != UINT32_MAX) 2379 tmTimerQueueSchedule(pVM, pQueue, pQueue); 2380 tmR3TimerQueueRun(pVM, pQueue); 2381 PDMCritSectLeave(&pQueue->TimerLock); 2382 STAM_PROFILE_STOP(&pQueue->StatDo, s3); 2364 2383 2365 2384 #ifdef VBOX_STRICT 2366 2385 /* check that we didn't screw up. */ 2367 TM_LOCK_TIMERS(pVM);2368 2386 tmTimerQueuesSanityChecks(pVM, "TMR3TimerQueuesDo"); 2369 TM_UNLOCK_TIMERS(pVM);2370 2387 #endif 2371 2388 … … 2373 2390 Log2(("TMR3TimerQueuesDo: returns void\n")); 2374 2391 ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, false); 2375 TM_UNLOCK_TIMERS(pVM);2376 2392 STAM_PROFILE_STOP(&pVM->tm.s.StatDoQueues, a); 2377 2393 } … … 2649 2665 if (fRc && pTimer->uHzHint) 2650 2666 { 2651 if (pTimer->uHzHint >= p VM->tm.s.uMaxHzHint)2652 ASMAtomic WriteBool(&pVM->tm.s.fHzHintNeedsUpdating, true);2667 if (pTimer->uHzHint >= pQueue->uMaxHzHint) 2668 ASMAtomicOrU64(&pVM->tm.s.HzHint.u64Combined, RT_BIT_32(TMCLOCK_VIRTUAL_SYNC) | RT_BIT_32(TMCLOCK_VIRTUAL_SYNC + 16)); 2653 2669 pTimer->uHzHint = 0; 2654 2670 } … … 2825 2841 2826 2842 /* try run it. */ 2827 TM_LOCK_TIMERS(pVM);2843 PDMCritSectEnter(&pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].TimerLock, VERR_IGNORED); 2828 2844 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); 2829 2845 if (pVM->tm.s.fVirtualSyncTicking) … … 2841 2857 ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false); 2842 2858 } 2859 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 2843 2860 STAM_PROFILE_STOP(&pVM->tm.s.StatVirtualSyncFF, a); /* before the unlock! */ 2844 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 2845 TM_UNLOCK_TIMERS(pVM); 2861 PDMCritSectLeave(&pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].TimerLock); 2846 2862 } 2847 2863 } … … 3152 3168 { 3153 3169 VMCPU_ASSERT_EMT(pVCpu); 3170 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */ 3154 3171 3155 3172 /* 3156 3173 * The shared virtual clock (includes virtual sync which is tied to it). 3157 3174 */ 3158 TM_LOCK_TIMERS(pVM); /* Paranoia: Exploiting the timer lock here. */3159 3175 int rc = tmVirtualPauseLocked(pVM); 3160 TM_UNLOCK_TIMERS(pVM); 3161 if (RT_FAILURE(rc)) 3162 return rc; 3176 AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc); 3163 3177 3164 3178 /* … … 3168 3182 if (!pVM->tm.s.fTSCTiedToExecution) 3169 3183 { 3170 TM_LOCK_TIMERS(pVM); /* Exploit the timer lock for synchronization. */3171 3184 rc = tmCpuTickPauseLocked(pVM, pVCpu); 3172 TM_UNLOCK_TIMERS(pVM); 3173 if (RT_FAILURE(rc)) 3174 return rc; 3185 AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc); 3175 3186 } 3176 3187 … … 3198 3209 #endif 3199 3210 3211 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 3200 3212 return VINF_SUCCESS; 3201 3213 } … … 3213 3225 { 3214 3226 VMCPU_ASSERT_EMT(pVCpu); 3215 int rc;3227 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */ 3216 3228 3217 3229 #ifndef VBOX_WITHOUT_NS_ACCOUNTING … … 3233 3245 if (!pVM->tm.s.fTSCTiedToExecution) 3234 3246 { 3235 TM_LOCK_TIMERS(pVM); /* Exploit the timer lock for synchronization. */ 3236 rc = tmCpuTickResumeLocked(pVM, pVCpu); 3237 TM_UNLOCK_TIMERS(pVM); 3238 if (RT_FAILURE(rc)) 3239 return rc; 3247 int rc = tmCpuTickResumeLocked(pVM, pVCpu); 3248 AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc); 3240 3249 } 3241 3250 … … 3243 3252 * The shared virtual clock (includes virtual sync which is tied to it). 3244 3253 */ 3245 TM_LOCK_TIMERS(pVM); /* Paranoia: Exploiting the timer lock here. */ 3246 rc = tmVirtualResumeLocked(pVM); 3247 TM_UNLOCK_TIMERS(pVM); 3248 3254 int rc = tmVirtualResumeLocked(pVM); 3255 3256 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 3249 3257 return rc; 3250 3258 } … … 3288 3296 * TM level and make it affect TMR3UTCNow as well! */ 3289 3297 3298 PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */ 3299 3290 3300 /* 3291 3301 * If the time is running we'll have to pause it before we can change 3292 3302 * the warp drive settings. 3293 3303 */ 3294 TM_LOCK_TIMERS(pVM); /* Paranoia: Exploiting the timer lock here. */3295 3304 bool fPaused = !!pVM->tm.s.cVirtualTicking; 3296 3305 if (fPaused) /** @todo this isn't really working, but wtf. */ … … 3305 3314 if (fPaused) 3306 3315 TMR3NotifyResume(pVM, pVCpu); 3307 TM_UNLOCK_TIMERS(pVM); 3316 3317 PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock); 3308 3318 return VINF_SUCCESS; 3309 3319 } … … 3896 3906 PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue]; 3897 3907 PDMCritSectRwEnterShared(&pQueue->AllocLock, VERR_IGNORED); 3898 TM_LOCK_TIMERS(pVM); 3908 PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED); 3909 3899 3910 for (PTMTIMERR3 pTimer = tmTimerQueueGetHead(pQueue, pQueue); 3900 3911 pTimer; … … 3914 3925 pTimer->szName); 3915 3926 } 3916 TM_UNLOCK_TIMERS(pVM); 3927 3928 PDMCritSectLeave(&pQueue->TimerLock); 3917 3929 PDMCritSectRwLeaveShared(&pQueue->AllocLock); 3918 3930 }
Note:
See TracChangeset
for help on using the changeset viewer.