VirtualBox

Changeset 87812 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Feb 19, 2021 8:54:49 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142873
Message:

VMM/TM: Replaced the global timer active list lock with per queue locks. bugref:9943

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r87796 r87812  
    210210    AssertCompileMemberAlignment(VM, tm.s, 32);
    211211    AssertCompile(sizeof(pVM->tm.s) <= sizeof(pVM->tm.padding));
    212     AssertCompileMemberAlignment(TM, TimerCritSect, 8);
    213212    AssertCompileMemberAlignment(TM, VirtualSyncLock, 8);
    214213
     
    217216     */
    218217    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);
    219221
    220222    strcpy(pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].szName,      "virtual");
     
    231233        pVM->tm.s.aTimerQueues[i].idxSchedule = UINT32_MAX;
    232234        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);
    235241        AssertLogRelRCReturn(rc, rc);
    236242    }
     
    249255
    250256    RTHCPHYS HCPhysGIP;
    251     int rc = SUPR3GipGetPhys(&HCPhysGIP);
     257    rc = SUPR3GipGetPhys(&HCPhysGIP);
    252258    AssertMsgRCReturn(rc, ("Failed to get GIP physical address!\n"), rc);
    253259
     
    305311    AssertRelease(pVM->tm.s.VirtualGetRawDataR0.pu64Prev);
    306312    /* 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;
    317313
    318314    /*
     
    699695    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)");
    700696    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    }
    702704
    703705#ifdef VBOX_WITH_STATISTICS
     
    709711    STAM_REG_USED(pVM,(void *)&pVM->tm.s.VirtualGetRawDataRC.cUpdateRaces,STAMTYPE_U32, "/TM/RC/cUpdateRaces",                 STAMUNIT_OCCURENCES, "Thread races when updating the previous timestamp.");
    710712    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.aStatDoQueues[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.aStatDoQueues[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.aStatDoQueues[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.");
    714716
    715717    STAM_REG(pVM, &pVM->tm.s.StatPoll,                                STAMTYPE_COUNTER, "/TM/Poll",                            STAMUNIT_OCCURENCES, "TMTimerPoll calls.");
     
    12121214    LogFlow(("TMR3Reset:\n"));
    12131215    VM_ASSERT_EMT(pVM);
    1214     TM_LOCK_TIMERS(pVM);
    12151216
    12161217    /*
     
    12391240     * Process the queues.
    12401241     */
    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    }
    12431249#ifdef VBOX_STRICT
    12441250    tmTimerQueuesSanityChecks(pVM, "TMR3Reset");
     
    12921298        pVCpu->tm.s.u64TSCLastSeen = 0;
    12931299    }
    1294 
    1295     TM_UNLOCK_TIMERS(pVM);
    12961300}
    12971301
     
    16931697
    16941698#ifdef VBOX_STRICT
    1695     TM_LOCK_TIMERS(pVM);
    16961699    tmTimerQueuesSanityChecks(pVM, "tmR3TimerCreate");
    1697     TM_UNLOCK_TIMERS(pVM);
    16981700#endif
    16991701
     
    19001902     */
    19011903    PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
    1902     TM_LOCK_TIMERS(pVM);
     1904    PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
     1905
    19031906    for (int cRetries = 1000;; cRetries--)
    19041907    {
     
    19371940            case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
    19381941                AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName));
    1939                 TM_UNLOCK_TIMERS(pVM);
     1942                PDMCritSectLeave(&pQueue->TimerLock);
    19401943                PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
    19411944
     
    19461949
    19471950                PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
    1948                 TM_LOCK_TIMERS(pVM);
     1951                PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
    19491952                continue;
    19501953
     
    19541957            case TMTIMERSTATE_FREE:
    19551958            case TMTIMERSTATE_DESTROY:
    1956                 TM_UNLOCK_TIMERS(pVM);
     1959                PDMCritSectLeave(&pQueue->TimerLock);
    19571960                PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
    19581961                AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE);
     
    19601963            default:
    19611964                AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, pTimer->szName));
    1962                 TM_UNLOCK_TIMERS(pVM);
     1965                PDMCritSectLeave(&pQueue->TimerLock);
    19631966                PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
    19641967                return VERR_TM_UNKNOWN_STATE;
     
    19741977            break;
    19751978        AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName));
    1976         TM_UNLOCK_TIMERS(pVM);
     1979        PDMCritSectLeave(&pQueue->TimerLock);
    19771980        PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
    19781981
     
    19811984
    19821985        PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
    1983         TM_LOCK_TIMERS(pVM);
     1986        PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
    19841987    }
    19851988
     
    20382041    tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy");
    20392042#endif
    2040     TM_UNLOCK_TIMERS(pVM);
     2043    PDMCritSectLeave(&pQueue->TimerLock);
    20412044    PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
    20422045    return VINF_SUCCESS;
     
    23242327    Assert(!pVM->tm.s.fRunningQueues);
    23252328    ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, true);
    2326     TM_LOCK_TIMERS(pVM);
    23272329
    23282330    /*
     
    23312333    AssertCompile(TMCLOCK_MAX == 4);
    23322334
    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);
    23352341    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
    23362342    ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, true);
    23372343    VMCPU_FF_CLEAR(pVCpuDst, VMCPU_FF_TIMER);   /* Clear the FF once we started working for real. */
    23382344
    2339     Assert(pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].idxSchedule == UINT32_MAX);
     2345    Assert(pQueue->idxSchedule == UINT32_MAX);
    23402346    tmR3TimerQueueRunVirtualSync(pVM);
    23412347    if (pVM->tm.s.fVirtualSyncTicking) /** @todo move into tmR3TimerQueueRunVirtualSync - FIXME */
     
    23442350    ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false);
    23452351    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     */
    23562370    Assert(pVM->tm.s.aTimerQueues[TMCLOCK_TSC].idxActive == UINT32_MAX); /* not used */
    23572371
    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);
    23642383
    23652384#ifdef VBOX_STRICT
    23662385    /* check that we didn't screw up. */
    2367     TM_LOCK_TIMERS(pVM);
    23682386    tmTimerQueuesSanityChecks(pVM, "TMR3TimerQueuesDo");
    2369     TM_UNLOCK_TIMERS(pVM);
    23702387#endif
    23712388
     
    23732390    Log2(("TMR3TimerQueuesDo: returns void\n"));
    23742391    ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, false);
    2375     TM_UNLOCK_TIMERS(pVM);
    23762392    STAM_PROFILE_STOP(&pVM->tm.s.StatDoQueues, a);
    23772393}
     
    26492665        if (fRc && pTimer->uHzHint)
    26502666        {
    2651             if (pTimer->uHzHint >= pVM->tm.s.uMaxHzHint)
    2652                 ASMAtomicWriteBool(&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));
    26532669            pTimer->uHzHint = 0;
    26542670        }
     
    28252841
    28262842            /* try run it. */
    2827             TM_LOCK_TIMERS(pVM);
     2843            PDMCritSectEnter(&pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].TimerLock, VERR_IGNORED);
    28282844            PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
    28292845            if (pVM->tm.s.fVirtualSyncTicking)
     
    28412857                ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false);
    28422858            }
     2859            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    28432860            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);
    28462862        }
    28472863    }
     
    31523168{
    31533169    VMCPU_ASSERT_EMT(pVCpu);
     3170    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
    31543171
    31553172    /*
    31563173     * The shared virtual clock (includes virtual sync which is tied to it).
    31573174     */
    3158     TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
    31593175    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);
    31633177
    31643178    /*
     
    31683182    if (!pVM->tm.s.fTSCTiedToExecution)
    31693183    {
    3170         TM_LOCK_TIMERS(pVM);    /* Exploit the timer lock for synchronization. */
    31713184        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);
    31753186    }
    31763187
     
    31983209#endif
    31993210
     3211    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    32003212    return VINF_SUCCESS;
    32013213}
     
    32133225{
    32143226    VMCPU_ASSERT_EMT(pVCpu);
    3215     int rc;
     3227    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
    32163228
    32173229#ifndef VBOX_WITHOUT_NS_ACCOUNTING
     
    32333245    if (!pVM->tm.s.fTSCTiedToExecution)
    32343246    {
    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);
    32403249    }
    32413250
     
    32433252     * The shared virtual clock (includes virtual sync which is tied to it).
    32443253     */
    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);
    32493257    return rc;
    32503258}
     
    32883296 * TM level and make it affect TMR3UTCNow as well! */
    32893297
     3298    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
     3299
    32903300    /*
    32913301     * If the time is running we'll have to pause it before we can change
    32923302     * the warp drive settings.
    32933303     */
    3294     TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
    32953304    bool fPaused = !!pVM->tm.s.cVirtualTicking;
    32963305    if (fPaused) /** @todo this isn't really working, but wtf. */
     
    33053314    if (fPaused)
    33063315        TMR3NotifyResume(pVM, pVCpu);
    3307     TM_UNLOCK_TIMERS(pVM);
     3316
     3317    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    33083318    return VINF_SUCCESS;
    33093319}
     
    38963906        PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue];
    38973907        PDMCritSectRwEnterShared(&pQueue->AllocLock, VERR_IGNORED);
    3898         TM_LOCK_TIMERS(pVM);
     3908        PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
     3909
    38993910        for (PTMTIMERR3 pTimer = tmTimerQueueGetHead(pQueue, pQueue);
    39003911             pTimer;
     
    39143925                            pTimer->szName);
    39153926        }
    3916         TM_UNLOCK_TIMERS(pVM);
     3927
     3928        PDMCritSectLeave(&pQueue->TimerLock);
    39173929        PDMCritSectRwLeaveShared(&pQueue->AllocLock);
    39183930    }
Note: See TracChangeset for help on using the changeset viewer.

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