SurfaceFlinger: use TFD_TIMER_ABSTIME for VSP timer
Using the semantics of alarmIn in VSP timer may lead to lag
if the thread is getting preempted. For example:
Time 0: t1 calls to alarmIn(5)
-- t1 gets preempted for 2ms --
Time 2: t1 calls to timerfd_settime(5)
Time 7: timer wakes up t1, results in 2ms lag
Switching to alarmAt semantics and using TFD_TIMER_ABSTIME to
schedule the timer solves this problem:
Time 0: t1 calls to alarmAt(5)
-- t1 gets preempted for 2ms --
Time 2: t1 calls to timerfd_settime(5)
Time 5: timer wakes up t1
Bug: 159884130
Test: bouncy ball with simulated scheduling delays
Change-Id: I3d727530c2dd47c1a8d1d6a66114d654d7261d87
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index 373f6a5..f630e3b 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -64,19 +64,19 @@
class ControllableClock : public TimeKeeper {
public:
ControllableClock() {
- ON_CALL(*this, alarmIn(_, _))
- .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
+ ON_CALL(*this, alarmAt(_, _))
+ .WillByDefault(Invoke(this, &ControllableClock::alarmAtDefaultBehavior));
ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
}
MOCK_CONST_METHOD0(now, nsecs_t());
- MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
+ MOCK_METHOD2(alarmAt, void(std::function<void()> const&, nsecs_t time));
MOCK_METHOD0(alarmCancel, void());
MOCK_CONST_METHOD1(dump, void(std::string&));
- void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
+ void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
mCallback = callback;
- mNextCallbackTime = time + mCurrentTime;
+ mNextCallbackTime = time;
}
nsecs_t fakeTime() const { return mCurrentTime; }
@@ -192,8 +192,8 @@
class TimeKeeperWrapper : public TimeKeeper {
public:
TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
- void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
- mControllableClock.alarmIn(callback, time);
+ void alarmAt(std::function<void()> const& callback, nsecs_t time) final {
+ mControllableClock.alarmAt(callback, time);
}
void alarmCancel() final { mControllableClock.alarmCancel(); }
nsecs_t now() const final { return mControllableClock.now(); }
@@ -222,7 +222,7 @@
};
TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
EXPECT_CALL(mMockClock, alarmCancel());
{
VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
@@ -234,7 +234,7 @@
TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
auto intended = mPeriod - 230;
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
CountingCallback cb(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
@@ -246,7 +246,7 @@
TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
- EXPECT_CALL(mMockClock, alarmIn(_, 1050));
+ EXPECT_CALL(mMockClock, alarmAt(_, 1050));
CountingCallback cb(mDispatch);
mDispatch.schedule(cb, 100, mPeriod);
@@ -262,14 +262,14 @@
auto const workDuration = 10 * mPeriod;
EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
.WillOnce(Return(mPeriod * 11));
- EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
+ EXPECT_CALL(mMockClock, alarmAt(_, mPeriod));
CountingCallback cb(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
}
TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
EXPECT_CALL(mMockClock, alarmCancel());
CountingCallback cb(mDispatch);
@@ -278,7 +278,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
EXPECT_CALL(mMockClock, alarmCancel());
CountingCallback cb(mDispatch);
@@ -288,7 +288,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
EXPECT_CALL(mMockClock, alarmCancel());
PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
@@ -302,7 +302,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
+ EXPECT_CALL(mMockClock, alarmAt(_, 900));
EXPECT_CALL(mMockClock, alarmCancel());
auto resource = std::make_shared<int>(110);
@@ -332,9 +332,9 @@
.WillOnce(Return(1075));
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 955)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 813)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 975)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -360,9 +360,9 @@
.WillOnce(Return(10000));
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 750)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -374,8 +374,8 @@
TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -388,9 +388,9 @@
TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -403,10 +403,10 @@
TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1590)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
auto offset = 400;
auto closeOffset = offset + mDispatchGroupThreshold - 1;
@@ -437,9 +437,10 @@
}
TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
- EXPECT_CALL(mMockClock, alarmIn(_, 900));
- EXPECT_CALL(mMockClock, alarmIn(_, 800));
- EXPECT_CALL(mMockClock, alarmIn(_, 100));
+ Sequence seq;
+ EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 800)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
EXPECT_CALL(mMockClock, alarmCancel());
CountingCallback cb0(mDispatch);
@@ -477,8 +478,8 @@
TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
VSyncDispatch::CallbackToken tmp;
tmp = mDispatch.registerCallback([&](auto, auto) { mDispatch.schedule(tmp, 100, 2000); },
@@ -512,10 +513,10 @@
TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1000)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 950)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1950)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
CountingCallback cb(mDispatch);
mDispatch.schedule(cb, 0, 1000);
@@ -532,10 +533,10 @@
TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 850)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1800)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -553,7 +554,7 @@
TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
CountingCallback cb0(mDispatch);
CountingCallback cb1(mDispatch);
@@ -563,9 +564,9 @@
TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
CountingCallback cb0(mDispatch);
mDispatch.schedule(cb0, 500, 1000);
@@ -587,7 +588,7 @@
// b/1450138150
TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
- EXPECT_CALL(mMockClock, alarmIn(_, 500));
+ EXPECT_CALL(mMockClock, alarmAt(_, 500));
CountingCallback cb(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
mMockClock.advanceBy(400);
@@ -617,8 +618,8 @@
TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1100)).InSequence(seq);
CountingCallback cb0(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
advanceToNextCallback();
@@ -626,7 +627,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
- EXPECT_CALL(mMockClock, alarmIn(_, 600));
+ EXPECT_CALL(mMockClock, alarmAt(_, 600));
CountingCallback cb(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
@@ -637,7 +638,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
VSyncCallbackRegistration cb(
@@ -651,7 +652,7 @@
}
TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
- EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
VSyncCallbackRegistration cb(
@@ -669,8 +670,8 @@
// b/154303580
TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 1200)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
CountingCallback cb1(mDispatch);
CountingCallback cb2(mDispatch);
@@ -691,8 +692,8 @@
// update later, as opposed to blocking the calling thread.
TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminentSameCallback) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 930)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq);
CountingCallback cb(mDispatch);
EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
@@ -709,7 +710,7 @@
// b/154303580.
TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
CountingCallback cb1(mDispatch);
CountingCallback cb2(mDispatch);
@@ -730,8 +731,8 @@
TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) {
Sequence seq;
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
- EXPECT_CALL(mMockClock, alarmIn(_, 1280)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
CountingCallback cb1(mDispatch);
CountingCallback cb2(mDispatch);
@@ -760,7 +761,7 @@
EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
.InSequence(seq)
.WillOnce(Return(1000));
- EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
.InSequence(seq)
.WillOnce(Return(1000));