VirtualBox

Ignore:
Timestamp:
Sep 10, 2010 3:41:00 PM (14 years ago)
Author:
vboxsync
Message:

TM,HWVMXR0: Use the preemption timer to make sure we stop executing guest code in time for the next TMCLOCK_VIRTUAL_SYNC timer deadline.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r29250 r32419  
    370370VMM_INT_DECL(uint64_t) TMVirtualGet(PVM pVM)
    371371{
    372     return tmVirtualGet(pVM, true /* check timers */);
     372    return tmVirtualGet(pVM, true /*fCheckTimers*/);
    373373}
    374374
     
    388388{
    389389    return tmVirtualGet(pVM, false /*fCheckTimers*/);
     390}
     391
     392
     393/**
     394 * Converts the dead line interval from TMCLOCK_VIRTUAL to host nano seconds.
     395 *
     396 * @returns Host nano second count.
     397 * @param   pVM                     The VM handle.
     398 * @param   cVirtTicksToDeadline    The TMCLOCK_VIRTUAL interval.
     399 */
     400DECLINLINE(uint64_t) tmVirtualVirtToNsDeadline(PVM pVM, uint64_t cVirtTicksToDeadline)
     401{
     402    if (RT_UNLIKELY(pVM->tm.s.fVirtualWarpDrive))
     403        return ASMMultU64ByU32DivByU32(cVirtTicksToDeadline, 100, pVM->tm.s.u32VirtualWarpDrivePercentage);
     404    return cVirtTicksToDeadline;
    390405}
    391406
     
    398413 * @param   u64                 raw virtual time.
    399414 * @param   off                 offVirtualSync.
    400  */
    401 DECLINLINE(uint64_t) tmVirtualSyncGetHandleCatchUpLocked(PVM pVM, uint64_t u64, uint64_t off)
     415 * @param   pcNsToDeadline      Where to return the number of nano seconds to
     416 *                              the next virtual sync timer deadline. Can be
     417 *                              NULL.
     418 */
     419DECLINLINE(uint64_t) tmVirtualSyncGetHandleCatchUpLocked(PVM pVM, uint64_t u64, uint64_t off, uint64_t *pcNsToDeadline)
    402420{
    403421    STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetLocked);
     
    451469        if (fUpdatePrev)
    452470            ASMAtomicWriteU64(&pVM->tm.s.u64VirtualSyncCatchUpPrev, u64);
     471        if (pcNsToDeadline)
     472        {
     473            uint64_t cNsToDeadline = u64Expire - u64;
     474            if (pVM->tm.s.fVirtualSyncCatchUp)
     475                cNsToDeadline = ASMMultU64ByU32DivByU32(cNsToDeadline, 100,
     476                                                        pVM->tm.s.u32VirtualSyncCatchUpPercentage + 100);
     477            *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, cNsToDeadline);
     478        }
    453479        tmVirtualSyncUnlock(pVM);
    454480    }
     
    466492        tmVirtualSyncUnlock(pVM);
    467493
     494        if (pcNsToDeadline)
     495            *pcNsToDeadline = 0;
    468496#ifdef IN_RING3
    469497        REMR3NotifyTimerPending(pVM, pVCpuDst);
     
    486514 * @param   pVM                 The VM handle.
    487515 * @param   u64                 The virtual clock timestamp.
    488  */
    489 DECLINLINE(uint64_t) tmVirtualSyncGetLocked(PVM pVM, uint64_t u64)
     516 * @param   pcNsToDeadline      Where to return the number of nano seconds to
     517 *                              the next virtual sync timer deadline.  Can be
     518 *                              NULL.
     519 */
     520DECLINLINE(uint64_t) tmVirtualSyncGetLocked(PVM pVM, uint64_t u64, uint64_t *pcNsToDeadline)
    490521{
    491522    /*
     
    496527        u64 = ASMAtomicUoReadU64(&pVM->tm.s.u64VirtualSync);
    497528        tmVirtualSyncUnlock(pVM);
     529        if (pcNsToDeadline)
     530            *pcNsToDeadline = 0;
    498531        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetLocked);
    499532        Log6(("tmVirtualSyncGetLocked -> %'RU64 [stopped]\n", u64));
     
    506539    uint64_t off = ASMAtomicUoReadU64(&pVM->tm.s.offVirtualSync);
    507540    if (ASMAtomicUoReadBool(&pVM->tm.s.fVirtualSyncCatchUp))
    508         return tmVirtualSyncGetHandleCatchUpLocked(pVM, u64, off);
     541        return tmVirtualSyncGetHandleCatchUpLocked(pVM, u64, off, pcNsToDeadline);
    509542
    510543    /*
     
    516549    uint64_t u64Expire = ASMAtomicReadU64(&pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire);
    517550    if (u64 < u64Expire)
     551    {
    518552        tmVirtualSyncUnlock(pVM);
     553        if (pcNsToDeadline)
     554            *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, u64Expire - u64);
     555    }
    519556    else
    520557    {
     
    534571        VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
    535572#endif
     573        if (pcNsToDeadline)
     574            *pcNsToDeadline = 0;
    536575        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetSetFF);
    537576        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetExpired);
     
    547586 *
    548587 * @returns The timestamp.
    549  * @param   pVM     VM handle.
    550  * @param   fCheckTimers    Check timers or not
     588 * @param   pVM                 VM handle.
     589 * @param   fCheckTimers        Check timers or not
     590 * @param   pcNsToDeadline      Where to return the number of nano seconds to
     591 *                              the next virtual sync timer deadline.  Can be
     592 *                              NULL.
    551593 * @thread  EMT.
    552594 */
    553 DECLINLINE(uint64_t) tmVirtualSyncGetEx(PVM pVM, bool fCheckTimers)
     595DECLINLINE(uint64_t) tmVirtualSyncGetEx(PVM pVM, bool fCheckTimers, uint64_t *pcNsToDeadline)
    554596{
    555597    STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGet);
    556598
    557599    if (!pVM->tm.s.fVirtualSyncTicking)
     600    {
     601        if (pcNsToDeadline)
     602            *pcNsToDeadline = 0;
    558603        return pVM->tm.s.u64VirtualSync;
     604    }
    559605
    560606    /*
     
    594640            {
    595641                off = u64 - off;
    596                 if (off < ASMAtomicReadU64(&pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire))
     642                uint64_t const u64Expire = ASMAtomicReadU64(&pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire);
     643                if (off < u64Expire)
    597644                {
     645                    if (pcNsToDeadline)
     646                        *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, u64Expire - off);
    598647                    STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetLockless);
    599648                    Log6(("tmVirtualSyncGetEx -> %'RU64 [lockless]\n", off));
     
    608657        if (RT_LIKELY(!ASMAtomicReadBool(&pVM->tm.s.fVirtualSyncTicking)))
    609658        {
     659            if (pcNsToDeadline)
     660                *pcNsToDeadline = 0;
    610661            STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetLockless);
    611662            Log6(("tmVirtualSyncGetEx -> %'RU64 [lockless/stopped]\n", off));
     
    639690        int rcLock = tmVirtualSyncTryLock(pVM);
    640691        if (RT_SUCCESS_NP(rcLock))
    641             return tmVirtualSyncGetLocked(pVM, u64);
     692            return tmVirtualSyncGetLocked(pVM, u64, pcNsToDeadline);
    642693
    643694        /* Re-check the ticking flag. */
     
    648699                && cOuterTries > 0)
    649700                continue;
     701            if (pcNsToDeadline)
     702                *pcNsToDeadline = 0;
    650703            Log6(("tmVirtualSyncGetEx -> %'RU64 [stopped]\n", off));
    651704            return off;
     
    727780        else
    728781            Log4(("TM: %'RU64/-%'8RU64: exp tmr [NoLock]\n", u64, pVM->tm.s.offVirtualSync - pVM->tm.s.offVirtualSyncGivenUp));
     782        if (pcNsToDeadline)
     783            *pcNsToDeadline = 0;
    729784        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualSyncGetExpired);
     785    }
     786    else if (pcNsToDeadline)
     787    {
     788        uint64_t cNsToDeadline = u64Expire - u64;
     789        if (ASMAtomicReadBool(&pVM->tm.s.fVirtualSyncCatchUp))
     790            cNsToDeadline = ASMMultU64ByU32DivByU32(cNsToDeadline, 100,
     791                                                    ASMAtomicReadU32(&pVM->tm.s.u32VirtualSyncCatchUpPercentage) + 100);
     792        *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, cNsToDeadline);
    730793    }
    731794
     
    745808VMM_INT_DECL(uint64_t) TMVirtualSyncGet(PVM pVM)
    746809{
    747     return tmVirtualSyncGetEx(pVM, true /* check timers */);
     810    return tmVirtualSyncGetEx(pVM, true /*fCheckTimers*/, NULL /*pcNsToDeadline*/);
    748811}
    749812
     
    760823VMM_INT_DECL(uint64_t) TMVirtualSyncGetNoCheck(PVM pVM)
    761824{
    762     return tmVirtualSyncGetEx(pVM, false /* check timers */);
     825    return tmVirtualSyncGetEx(pVM, false /*fCheckTimers*/, NULL /*pcNsToDeadline*/);
    763826}
    764827
     
    775838VMM_INT_DECL(uint64_t) TMVirtualSyncGetEx(PVM pVM, bool fCheckTimers)
    776839{
    777     return tmVirtualSyncGetEx(pVM, fCheckTimers);
     840    return tmVirtualSyncGetEx(pVM, fCheckTimers, NULL /*pcNsToDeadline*/);
     841}
     842
     843
     844/**
     845 * Gets the current TMCLOCK_VIRTUAL_SYNC time and ticks to the next deadline
     846 * without checking timers running on TMCLOCK_VIRTUAL.
     847 *
     848 * @returns The timestamp.
     849 * @param   pVM                 VM handle.
     850 * @param   pcNsToDeadline      Where to return the number of nano seconds to
     851 *                              the next virtual sync timer deadline.
     852 * @thread  EMT.
     853 * @remarks May set the timer and virtual sync FFs.
     854 */
     855VMM_INT_DECL(uint64_t) TMVirtualSyncGetWithDeadlineNoCheck(PVM pVM, uint64_t *pcNsToDeadline)
     856{
     857    uint64_t cNsToDeadlineTmp;       /* try convince the compiler to skip the if tests. */
     858    uint64_t u64Now = tmVirtualSyncGetEx(pVM, false /*fCheckTimers*/, &cNsToDeadlineTmp);
     859    *pcNsToDeadline = cNsToDeadlineTmp;
     860    return u64Now;
     861}
     862
     863
     864/**
     865 * Gets the number of nano seconds to the next virtual sync deadline.
     866 *
     867 * @returns The number of TMCLOCK_VIRTUAL ticks.
     868 * @param   pVM                 VM handle.
     869 * @thread  EMT.
     870 * @remarks May set the timer and virtual sync FFs.
     871 */
     872VMM_INT_DECL(uint64_t) TMVirtualSyncGetNsToDeadline(PVM pVM)
     873{
     874    uint64_t cNsToDeadline;
     875    tmVirtualSyncGetEx(pVM, false /*fCheckTimers*/, &cNsToDeadline);
     876    return cNsToDeadline;
    778877}
    779878
Note: See TracChangeset for help on using the changeset viewer.

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