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

Commit acfe554b authored by Kevin DuBois's avatar Kevin DuBois Committed by Ady Abraham
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
Merged-In: Ia17bc5a09a085fcb334226849214e5247e010b37
parent ae8cd554
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;