VirtualBox

Ignore:
Timestamp:
Oct 5, 2007 1:33:36 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
25066
Message:

New halt method.

File:
1 edited

Legend:

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

    r4977 r5167  
    139139 *
    140140 * @returns Virtual timer ticks to the next event.
     141 * @param   pVM         Pointer to the shared VM structure.
    141142 * @thread  The emulation thread.
    142143 */
     
    220221    STAM_COUNTER_INC(&pVM->tm.s.StatPollMiss);
    221222    return RT_MIN(i64Delta1, i64Delta2);
     223}
     224
     225
     226/**
     227 * Set FF if we've passed the next virtual event.
     228 *
     229 * This function is called before FFs are checked in the inner execution EM loops.
     230 *
     231 * @returns The GIP timestamp of the next event.
     232 *          0 if the next event has already expired.
     233 * @param   pVM         Pointer to the shared VM structure.
     234 * @param   pVM         Pointer to the shared VM structure.
     235 * @param   pu64Delta   Where to store the delta.
     236 * @thread  The emulation thread.
     237 */
     238TMDECL(uint64_t) TMTimerPollGIP(PVM pVM, uint64_t *pu64Delta)
     239{
     240    /*
     241     * Return straight away if the timer FF is already set.
     242     */
     243    if (VM_FF_ISSET(pVM, VM_FF_TIMER))
     244    {
     245        STAM_COUNTER_INC(&pVM->tm.s.StatPollAlreadySet);
     246        *pu64Delta = 0;
     247        return 0;
     248    }
     249
     250    /*
     251     * Get current time and check the expire times of the two relevant queues.
     252     */
     253    const uint64_t u64Now = TMVirtualGet(pVM);
     254
     255    /*
     256     * TMCLOCK_VIRTUAL
     257     */
     258    const uint64_t u64Expire1 = pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire;
     259    const int64_t i64Delta1 = u64Expire1 - u64Now;
     260    if (i64Delta1 <= 0)
     261    {
     262        LogFlow(("TMTimerPoll: expire1=%RU64 <= now=%RU64\n", u64Expire1, u64Now));
     263        STAM_COUNTER_INC(&pVM->tm.s.StatPollVirtual);
     264        VM_FF_SET(pVM, VM_FF_TIMER);
     265#ifdef IN_RING3
     266        REMR3NotifyTimerPending(pVM);
     267#endif
     268        *pu64Delta = 0;
     269        return 0;
     270    }
     271
     272    /*
     273     * TMCLOCK_VIRTUAL_SYNC
     274     * This isn't quite as stright forward if in a catch-up, not only do
     275     * we have to adjust the 'now' but when have to adjust the delta as well.
     276     */
     277    const uint64_t u64Expire2 = pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire;
     278    uint64_t u64VirtualSyncNow;
     279    if (!pVM->tm.s.fVirtualSyncTicking)
     280        u64VirtualSyncNow = pVM->tm.s.u64VirtualSync;
     281    else
     282    {
     283        if (!pVM->tm.s.fVirtualSyncCatchUp)
     284            u64VirtualSyncNow = u64Now - pVM->tm.s.offVirtualSync;
     285        else
     286        {
     287            uint64_t off = pVM->tm.s.offVirtualSync;
     288            uint64_t u64Delta = u64Now - pVM->tm.s.u64VirtualSyncCatchUpPrev;
     289            if (RT_LIKELY(!(u64Delta >> 32)))
     290            {
     291                uint64_t u64Sub = ASMMultU64ByU32DivByU32(u64Delta, pVM->tm.s.u32VirtualSyncCatchUpPercentage, 100);
     292                if (off > u64Sub + pVM->tm.s.offVirtualSyncGivenUp)
     293                    off -= u64Sub;
     294                else
     295                    off = pVM->tm.s.offVirtualSyncGivenUp;
     296            }
     297            u64VirtualSyncNow = u64Now - off;
     298        }
     299    }
     300    int64_t i64Delta2 = u64Expire2 - u64VirtualSyncNow;
     301    if (i64Delta2 <= 0)
     302    {
     303        LogFlow(("TMTimerPoll: expire2=%RU64 <= now=%RU64\n", u64Expire2, u64Now));
     304        STAM_COUNTER_INC(&pVM->tm.s.StatPollVirtualSync);
     305        VM_FF_SET(pVM, VM_FF_TIMER);
     306#ifdef IN_RING3
     307        REMR3NotifyTimerPending(pVM);
     308#endif
     309        *pu64Delta = 0;
     310        return 0;
     311    }
     312    if (pVM->tm.s.fVirtualSyncCatchUp)
     313        i64Delta2 = ASMMultU64ByU32DivByU32(i64Delta2, 100, pVM->tm.s.u32VirtualSyncCatchUpPercentage + 100);
     314
     315    /*
     316     * Return the GIP time of the next event.
     317     * This is the reverse of what tmVirtualGetRaw is doing.
     318     */
     319    STAM_COUNTER_INC(&pVM->tm.s.StatPollMiss);
     320    uint64_t u64GipTime = RT_MIN(i64Delta1, i64Delta2);
     321    *pu64Delta = u64GipTime;
     322    u64GipTime += u64Now + pVM->tm.s.u64VirtualOffset;
     323    if (RT_UNLIKELY(!pVM->tm.s.fVirtualWarpDrive))
     324    {
     325        u64GipTime -= pVM->tm.s.u64VirtualWarpDriveStart; /* the start is GIP time. */
     326        u64GipTime *= 100;
     327        u64GipTime /= pVM->tm.s.u32VirtualWarpDrivePercentage;
     328        u64GipTime += pVM->tm.s.u64VirtualWarpDriveStart;
     329    }
     330    return u64GipTime;
    222331}
    223332#endif
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