VirtualBox

Changeset 81061 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Sep 27, 2019 4:38:54 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133665
Message:

IPRT/timer-r0drv-linux.c: Rewriting the drop-behind handling in the low-res timer code. Untested. bugref:7636

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c

    r80290 r81061  
    117117             * This is used to calculate when the timer ought to fire the next time. */
    118118            uint64_t                u64NextTS;
     119            /** When the timer was started. */
     120            uint64_t                nsStartTS;
    119121            /** The u64NextTS in jiffies. */
    120122            unsigned long           ulNextJiffies;
     
    345347    uint64_t u64NextTS = u64Now + u64First;
    346348    if (!fHighRes)
     349    {
    347350        pSubTimer->u.Std.u64NextTS = u64NextTS;
     351        pSubTimer->u.Std.nsStartTS = u64NextTS;
     352    }
    348353    RTTIMERLNX_LOG(("startsubtimer %p\n", pSubTimer->pParent));
    349354
     
    766771         * try prevent some jittering if we were started at a bad time.
    767772         */
    768         const uint64_t  iTick = ++pSubTimer->iTick;
     773        const uint64_t  iTick       = ++pSubTimer->iTick;
     774        unsigned long   uCurJiffies = jiffies;
     775        unsigned long   ulNextJiffies;
    769776        uint64_t        u64NanoInterval;
    770777        unsigned long   cJiffies;
     
    778785            pSubTimer->u.Std.fFirstAfterChg = false;
    779786            pSubTimer->u.Std.u64NextTS      = RTTimeSystemNanoTS();
    780             pSubTimer->u.Std.ulNextJiffies  = jiffies;
     787            pSubTimer->u.Std.nsStartTS      = pSubTimer->u.Std.u64NextTS - u64NanoInterval * (iTick - 1);
     788            pSubTimer->u.Std.ulNextJiffies  = uCurJiffies = jiffies;
    781789        }
    782790        spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags);
     
    785793        if (cJiffies)
    786794        {
    787             pSubTimer->u.Std.ulNextJiffies += cJiffies;
    788             /* Prevent overflows when the jiffies counter wraps around.
    789              * Special thanks to Ken Preslan for helping debugging! */
    790             while (time_before(pSubTimer->u.Std.ulNextJiffies, jiffies))
     795            ulNextJiffies = pSubTimer->u.Std.ulNextJiffies + cJiffies;
     796            pSubTimer->u.Std.ulNextJiffies = ulNextJiffies;
     797            if (time_after(ulNextJiffies, uCurJiffies))
     798            { /* likely */ }
     799            else
    791800            {
    792                 pSubTimer->u.Std.ulNextJiffies += cJiffies;
    793                 pSubTimer->u.Std.u64NextTS     += u64NanoInterval;
     801                unsigned long  cJiffiesBehind = uCurJiffies - ulNextJiffies;
     802                if (cJiffies >= 2)
     803                    ulNextJiffies = uCurJiffies + cJiffies / 2;
     804                else
     805                    ulNextJiffies = uCurJiffies + 1;
     806                if (cJiffiesBehind >= HZ / 4) /* Conside if we're lagging too far behind.  Screw the u64NextTS member. */
     807                    pSubTimer->u.Std.ulNextJiffies = ulNextJiffies;
     808                /*else: Don't update u.Std.ulNextJiffies so we can continue catching up in the next tick. */
    794809            }
    795810        }
     
    797812        {
    798813            const uint64_t u64NanoTS = RTTimeSystemNanoTS();
    799             while (pSubTimer->u.Std.u64NextTS < u64NanoTS)
    800                 pSubTimer->u.Std.u64NextTS += u64NanoInterval;
    801             pSubTimer->u.Std.ulNextJiffies = jiffies + rtTimerLnxNanoToJiffies(pSubTimer->u.Std.u64NextTS - u64NanoTS);
     814            const int64_t  cNsBehind = u64NanoTS - pSubTimer->u.Std.u64NextTS;
     815            if (cNsBehind < 0)
     816                ulNextJiffies = uCurJiffies + rtTimerLnxNanoToJiffies(pSubTimer->u.Std.u64NextTS - u64NanoTS);
     817            else if (u64NanoInterval >= RT_NS_1SEC_64 * 2 / HZ)
     818            {
     819                ulNextJiffies = uCurJiffies + rtTimerLnxNanoToJiffies(u64NanoInterval / 2);
     820                if (cNsBehind >= RT_NS_1SEC_64 / HZ / 4) /* Conside if we're lagging too far behind. */
     821                    pSubTimer->u.Std.u64NextTS = u64NanoTS + u64NanoInterval / 2;
     822            }
     823            else
     824            {
     825                ulNextJiffies = uCurJiffies + 1;
     826                if (cNsBehind >= RT_NS_1SEC_64 / HZ / 4) /* Conside if we're lagging too far behind. */
     827                    pSubTimer->u.Std.u64NextTS = u64NanoTS + RT_NS_1SEC_64 / HZ;
     828            }
     829            pSubTimer->u.Std.ulNextJiffies = ulNextJiffies;
    802830        }
    803831
     
    816844            {
    817845# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
    818                 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
     846                mod_timer(&pSubTimer->u.Std.LnxTimer, ulNextJiffies);
    819847# else
    820                 mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
     848                mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, ulNextJiffies);
    821849# endif
    822850            }
    823851            else
    824852#endif
    825                 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);
     853                mod_timer(&pSubTimer->u.Std.LnxTimer, ulNextJiffies);
    826854            return;
    827855        }
     
    14191447        return VERR_NOT_SUPPORTED;
    14201448
    1421     cJiffies = u64NanoInterval / RTTimerGetSystemGranularity();
    1422     if (cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval)
     1449    cJiffies = u64NanoInterval / (RT_NS_1SEC / HZ);
     1450    if (cJiffies * (RT_NS_1SEC / HZ) != u64NanoInterval)
    14231451        cJiffies = 0;
    14241452
     
    15801608    pTimer->pvUser          = pvUser;
    15811609    pTimer->u64NanoInterval = u64NanoInterval;
    1582     pTimer->cJiffies        = u64NanoInterval / RTTimerGetSystemGranularity();
    1583     if (pTimer->cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval)
     1610    pTimer->cJiffies        = u64NanoInterval / (RT_NS_1SEC / HZ);
     1611    if (pTimer->cJiffies * (RT_NS_1SEC / HZ) != u64NanoInterval)
    15841612        pTimer->cJiffies    = 0;
    15851613    spin_lock_init(&pTimer->ChgIntLock);
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