Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cd2bf53 authored by Kevin DuBois's avatar Kevin DuBois
Browse files

VSR: dispatch cbs skipped due to timer lag.

If the timer has a lot of lag relative to the intended wakeup time,
there could be two callbacks that should be dispatched during this
wakeup, not just one, with the additional callback being woken up being
the one that was skipped because of the timer lag.

Fixes: 159884130
Test: 1 new unit test
Test: uibench a/b

Change-Id: Ia17bc5a09a085fcb334226849214e5247e010b37
(cherry picked from commit f947783f)
parent 56892df0
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -243,7 +243,8 @@ void VSyncDispatchTimerQueue::timerCallback() {
    std::vector<Invocation> invocations;
    {
        std::lock_guard<decltype(mMutex)> lk(mMutex);
        mLastTimerCallback = mTimeKeeper->now();
        auto const now = mTimeKeeper->now();
        mLastTimerCallback = now;
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
            auto& callback = it->second;
            auto const wakeupTime = callback->wakeupTime();
@@ -251,7 +252,8 @@ void VSyncDispatchTimerQueue::timerCallback() {
                continue;
            }

            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack) {
            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                invocations.emplace_back(
                        Invocation{callback, *callback->lastExecutedVsyncTarget(), *wakeupTime});
+30 −1
Original line number Diff line number Diff line
@@ -115,11 +115,15 @@ public:

    operator VSyncDispatch::CallbackToken() const { return mToken; }

    void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); }
    void counter(nsecs_t time, nsecs_t wakeup_time) {
        mCalls.push_back(time);
        mWakeupTime.push_back(wakeup_time);
    }

    VSyncDispatch& mDispatch;
    VSyncDispatch::CallbackToken mToken;
    std::vector<nsecs_t> mCalls;
    std::vector<nsecs_t> mWakeupTime;
};

class PausingCallback {
@@ -747,6 +751,31 @@ TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) {
    EXPECT_THAT(cb2.mCalls.size(), Eq(1));
}

TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
    CountingCallback cb1(mDispatch);
    CountingCallback cb2(mDispatch);

    Sequence seq;
    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
            .InSequence(seq)
            .WillOnce(Return(1000));
    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
            .InSequence(seq)
            .WillOnce(Return(1000));

    EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled);
    EXPECT_EQ(mDispatch.schedule(cb2, 390, 1000), ScheduleResult::Scheduled);

    mMockClock.setLag(100);
    mMockClock.advanceBy(700);

    ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
    EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
    ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
    EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
}

class VSyncDispatchTimerQueueEntryTest : public testing::Test {
protected:
    nsecs_t const mPeriod = 1000;