blob: 900bce0aa981bf43e761ac2c15a91fed0ee466c2 [file] [log] [blame]
Kevin DuBois305bef12019-10-09 13:23:27 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Dominik Laskowski62eff352021-12-06 09:59:41 -080018
Kevin DuBois305bef12019-10-09 13:23:27 -070019#include <vector>
20
Dominik Laskowski62eff352021-12-06 09:59:41 -080021#include <android-base/stringprintf.h>
Vishnu Nairbe0ad902024-06-27 23:38:43 +000022#include <common/trace.h>
Dominik Laskowski62eff352021-12-06 09:59:41 -080023#include <ftl/concat.h>
Leon Scroggins III07738132023-04-24 11:43:53 -040024#include <log/log_main.h>
Dominik Laskowski62eff352021-12-06 09:59:41 -080025
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080026#include <scheduler/TimeKeeper.h>
27
Alec Mouri9b133ca2023-11-14 19:00:01 +000028#include <common/FlagManager.h>
Kevin DuBoise4f27a82019-11-12 11:41:41 -080029#include "VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070030#include "VSyncTracker.h"
31
Leon Scroggins III07738132023-04-24 11:43:53 -040032#undef LOG_TAG
33#define LOG_TAG "VSyncDispatch"
34
Kevin DuBois305bef12019-10-09 13:23:27 -070035namespace android::scheduler {
Dominik Laskowski62eff352021-12-06 09:59:41 -080036
Ady Abraham5e7371c2020-03-24 14:47:24 -070037using base::StringAppendF;
Kevin DuBois305bef12019-10-09 13:23:27 -070038
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070039namespace {
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080040
ramindani32a88b12024-01-31 18:45:30 -080041ScheduleResult getExpectedCallbackTime(nsecs_t nextVsyncTime,
42 const VSyncDispatch::ScheduleTiming& timing) {
43 return {TimePoint::fromNs(nextVsyncTime - timing.readyDuration - timing.workDuration),
44 TimePoint::fromNs(nextVsyncTime)};
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070045}
46
Ady Abraham20024aa2024-03-05 01:32:49 +000047void traceEntry(const VSyncDispatchTimerQueueEntry& entry, nsecs_t now) {
Vishnu Nair2665ca92024-07-09 22:08:15 +000048 if (!SFTRACE_ENABLED() || !entry.wakeupTime().has_value() || !entry.targetVsync().has_value()) {
Ady Abraham20024aa2024-03-05 01:32:49 +000049 return;
50 }
51
52 ftl::Concat trace(ftl::truncated<5>(entry.name()), " alarm in ",
53 ns2us(*entry.wakeupTime() - now), "us; VSYNC in ",
54 ns2us(*entry.targetVsync() - now), "us");
Vishnu Nairbe0ad902024-06-27 23:38:43 +000055 SFTRACE_FORMAT_INSTANT(trace.c_str());
Ady Abraham20024aa2024-03-05 01:32:49 +000056}
57
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070058} // namespace
59
Kevin DuBoise4f27a82019-11-12 11:41:41 -080060VSyncDispatch::~VSyncDispatch() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070061VSyncTracker::~VSyncTracker() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070062
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080063VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string name,
64 VSyncDispatch::Callback callback,
Kevin DuBoisc94ca832019-11-26 12:56:24 -080065 nsecs_t minVsyncDistance)
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080066 : mName(std::move(name)),
67 mCallback(std::move(callback)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -080068 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -070069
Kevin DuBoise4f27a82019-11-12 11:41:41 -080070std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::lastExecutedVsyncTarget() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070071 return mLastDispatchTime;
72}
73
Kevin DuBoise4f27a82019-11-12 11:41:41 -080074std::string_view VSyncDispatchTimerQueueEntry::name() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070075 return mName;
76}
77
Kevin DuBoise4f27a82019-11-12 11:41:41 -080078std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::wakeupTime() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070079 if (!mArmedInfo) {
80 return {};
81 }
82 return {mArmedInfo->mActualWakeupTime};
83}
84
Ady Abraham9c53ee72020-07-22 21:16:18 -070085std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::readyTime() const {
86 if (!mArmedInfo) {
87 return {};
88 }
89 return {mArmedInfo->mActualReadyTime};
90}
91
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -080092std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::targetVsync() const {
93 if (!mArmedInfo) {
94 return {};
95 }
96 return {mArmedInfo->mActualVsyncTime};
97}
98
ramindani558f4a92024-02-16 15:49:23 -080099ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
100 VSyncTracker& tracker, nsecs_t now) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000101 SFTRACE_NAME("VSyncDispatchTimerQueueEntry::schedule");
Ady Abraham4335afd2023-12-18 19:10:47 -0800102 auto nextVsyncTime =
103 tracker.nextAnticipatedVSyncTimeFrom(std::max(timing.lastVsync,
104 now + timing.workDuration +
105 timing.readyDuration),
106 timing.lastVsync);
Ady Abraham69b9e622021-07-19 12:24:31 -0700107 auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800108
109 bool const wouldSkipAVsyncTarget =
110 mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
Ady Abraham69b9e622021-07-19 12:24:31 -0700111 bool const wouldSkipAWakeup =
112 mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000113 SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
114 wouldSkipAVsyncTarget, wouldSkipAWakeup);
Ady Abrahambf554892024-02-14 18:18:21 +0000115 if (FlagManager::getInstance().dont_skip_on_early_ro()) {
Ady Abraham529bd9f2023-10-05 14:55:30 -0700116 if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
Ady Abrahamb0d3d982023-10-30 11:29:51 -0700117 nextVsyncTime = mArmedInfo->mActualVsyncTime;
118 } else {
119 nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
Ady Abraham529bd9f2023-10-05 14:55:30 -0700120 }
Ady Abrahamb0d3d982023-10-30 11:29:51 -0700121 nextWakeupTime = std::max(now, nextVsyncTime - timing.workDuration - timing.readyDuration);
Ady Abraham529bd9f2023-10-05 14:55:30 -0700122 } else {
123 if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
Ady Abrahamb0d3d982023-10-30 11:29:51 -0700124 return getExpectedCallbackTime(nextVsyncTime, timing);
Ady Abraham529bd9f2023-10-05 14:55:30 -0700125 }
Ady Abrahamb0d3d982023-10-30 11:29:51 -0700126 nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
127 nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800128 }
129
Ady Abraham9c53ee72020-07-22 21:16:18 -0700130 auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
131 mScheduleTiming = timing;
132 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
ramindani32a88b12024-01-31 18:45:30 -0800133 return ScheduleResult{TimePoint::fromNs(nextWakeupTime), TimePoint::fromNs(nextVsyncTime)};
Kevin DuBois305bef12019-10-09 13:23:27 -0700134}
135
ramindani32a88b12024-01-31 18:45:30 -0800136ScheduleResult VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(
Ady Abrahamda8af4c2024-02-14 00:24:34 +0000137 VSyncTracker& tracker, nsecs_t now, VSyncDispatch::ScheduleTiming timing) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700138 mWorkloadUpdateInfo = timing;
Ady Abraham20024aa2024-03-05 01:32:49 +0000139 const auto armedInfo = getArmedInfo(tracker, now, timing, mArmedInfo);
ramindani32a88b12024-01-31 18:45:30 -0800140 return {TimePoint::fromNs(armedInfo.mActualWakeupTime),
141 TimePoint::fromNs(armedInfo.mActualVsyncTime)};
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700142}
143
144bool VSyncDispatchTimerQueueEntry::hasPendingWorkloadUpdate() const {
145 return mWorkloadUpdateInfo.has_value();
146}
147
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700148nsecs_t VSyncDispatchTimerQueueEntry::adjustVsyncIfNeeded(VSyncTracker& tracker,
149 nsecs_t nextVsyncTime) const {
150 bool const alreadyDispatchedForVsync = mLastDispatchTime &&
151 ((*mLastDispatchTime + mMinVsyncDistance) >= nextVsyncTime &&
152 (*mLastDispatchTime - mMinVsyncDistance) <= nextVsyncTime);
153 const nsecs_t currentPeriod = tracker.currentPeriod();
154 bool const nextVsyncTooClose = mLastDispatchTime &&
155 (nextVsyncTime - *mLastDispatchTime + mMinVsyncDistance) <= currentPeriod;
156 if (alreadyDispatchedForVsync) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000157 SFTRACE_FORMAT_INSTANT("alreadyDispatchedForVsync");
Ady Abraham4335afd2023-12-18 19:10:47 -0800158 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance,
159 *mLastDispatchTime);
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700160 }
161
162 if (nextVsyncTooClose) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000163 SFTRACE_FORMAT_INSTANT("nextVsyncTooClose");
Ady Abraham4335afd2023-12-18 19:10:47 -0800164 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + currentPeriod,
165 *mLastDispatchTime + currentPeriod);
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700166 }
167
168 return nextVsyncTime;
169}
170
Ady Abraham20024aa2024-03-05 01:32:49 +0000171auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t now,
172 VSyncDispatch::ScheduleTiming timing,
173 std::optional<ArmingInfo> armedInfo) const
174 -> ArmingInfo {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000175 SFTRACE_NAME("VSyncDispatchTimerQueueEntry::getArmedInfo");
Ady Abrahamda8af4c2024-02-14 00:24:34 +0000176 const auto earliestReadyBy = now + timing.workDuration + timing.readyDuration;
177 const auto earliestVsync = std::max(earliestReadyBy, timing.lastVsync);
178
179 const auto nextVsyncTime =
180 adjustVsyncIfNeeded(tracker, /*nextVsyncTime*/
181 tracker.nextAnticipatedVSyncTimeFrom(earliestVsync,
182 timing.lastVsync));
183 const auto nextReadyTime = nextVsyncTime - timing.readyDuration;
184 const auto nextWakeupTime = nextReadyTime - timing.workDuration;
185
Ady Abraham20024aa2024-03-05 01:32:49 +0000186 if (FlagManager::getInstance().dont_skip_on_early_ro()) {
187 bool const wouldSkipAVsyncTarget =
188 armedInfo && (nextVsyncTime > (armedInfo->mActualVsyncTime + mMinVsyncDistance));
189 bool const wouldSkipAWakeup =
190 armedInfo && (nextWakeupTime > (armedInfo->mActualWakeupTime + mMinVsyncDistance));
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000191 SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
192 wouldSkipAVsyncTarget, wouldSkipAWakeup);
Ady Abraham20024aa2024-03-05 01:32:49 +0000193 if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
194 return *armedInfo;
195 }
Ady Abrahamda8af4c2024-02-14 00:24:34 +0000196 }
197
198 return ArmingInfo{nextWakeupTime, nextVsyncTime, nextReadyTime};
199}
200
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800201void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000202 SFTRACE_NAME("VSyncDispatchTimerQueueEntry::update");
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700203 if (!mArmedInfo && !mWorkloadUpdateInfo) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700204 return;
205 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700206
207 if (mWorkloadUpdateInfo) {
Ady Abraham20024aa2024-03-05 01:32:49 +0000208 const auto workDelta = mWorkloadUpdateInfo->workDuration - mScheduleTiming.workDuration;
209 const auto readyDelta = mWorkloadUpdateInfo->readyDuration - mScheduleTiming.readyDuration;
210 const auto lastVsyncDelta = mWorkloadUpdateInfo->lastVsync - mScheduleTiming.lastVsync;
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000211 SFTRACE_FORMAT_INSTANT("Workload updated workDelta=%" PRId64 " readyDelta=%" PRId64
212 " lastVsyncDelta=%" PRId64,
213 workDelta, readyDelta, lastVsyncDelta);
Ady Abraham9c53ee72020-07-22 21:16:18 -0700214 mScheduleTiming = *mWorkloadUpdateInfo;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700215 mWorkloadUpdateInfo.reset();
216 }
217
Ady Abraham20024aa2024-03-05 01:32:49 +0000218 mArmedInfo = getArmedInfo(tracker, now, mScheduleTiming, mArmedInfo);
Kevin DuBois305bef12019-10-09 13:23:27 -0700219}
220
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800221void VSyncDispatchTimerQueueEntry::disarm() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700222 mArmedInfo.reset();
223}
224
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800225nsecs_t VSyncDispatchTimerQueueEntry::executing() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700226 mLastDispatchTime = mArmedInfo->mActualVsyncTime;
227 disarm();
228 return *mLastDispatchTime;
229}
230
Ady Abraham9c53ee72020-07-22 21:16:18 -0700231void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
232 nsecs_t deadlineTimestamp) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700233 {
234 std::lock_guard<std::mutex> lk(mRunningMutex);
235 mRunning = true;
236 }
237
Ady Abraham9c53ee72020-07-22 21:16:18 -0700238 mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700239
240 std::lock_guard<std::mutex> lk(mRunningMutex);
241 mRunning = false;
242 mCv.notify_all();
243}
244
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800245void VSyncDispatchTimerQueueEntry::ensureNotRunning() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700246 std::unique_lock<std::mutex> lk(mRunningMutex);
247 mCv.wait(lk, [this]() REQUIRES(mRunningMutex) { return !mRunning; });
248}
249
Ady Abraham5e7371c2020-03-24 14:47:24 -0700250void VSyncDispatchTimerQueueEntry::dump(std::string& result) const {
251 std::lock_guard<std::mutex> lk(mRunningMutex);
252 std::string armedInfo;
253 if (mArmedInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700254 StringAppendF(&armedInfo,
255 "[wake up in %.2fms deadline in %.2fms for vsync %.2fms from now]",
Ady Abraham5e7371c2020-03-24 14:47:24 -0700256 (mArmedInfo->mActualWakeupTime - systemTime()) / 1e6f,
Ady Abraham9c53ee72020-07-22 21:16:18 -0700257 (mArmedInfo->mActualReadyTime - systemTime()) / 1e6f,
Ady Abraham5e7371c2020-03-24 14:47:24 -0700258 (mArmedInfo->mActualVsyncTime - systemTime()) / 1e6f);
259 }
260
261 StringAppendF(&result, "\t\t%s: %s %s\n", mName.c_str(),
262 mRunning ? "(in callback function)" : "", armedInfo.c_str());
Ady Abraham9c53ee72020-07-22 21:16:18 -0700263 StringAppendF(&result,
Ady Abraham4335afd2023-12-18 19:10:47 -0800264 "\t\t\tworkDuration: %.2fms readyDuration: %.2fms lastVsync: %.2fms relative "
Ady Abraham9c53ee72020-07-22 21:16:18 -0700265 "to now\n",
266 mScheduleTiming.workDuration / 1e6f, mScheduleTiming.readyDuration / 1e6f,
Ady Abraham4335afd2023-12-18 19:10:47 -0800267 (mScheduleTiming.lastVsync - systemTime()) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700268
269 if (mLastDispatchTime) {
270 StringAppendF(&result, "\t\t\tmLastDispatchTime: %.2fms ago\n",
271 (systemTime() - *mLastDispatchTime) / 1e6f);
272 } else {
273 StringAppendF(&result, "\t\t\tmLastDispatchTime unknown\n");
274 }
275}
276
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800277VSyncDispatchTimerQueue::VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper> tk,
Leon Scroggins III67388622023-02-06 20:36:20 -0500278 VsyncSchedule::TrackerPtr tracker,
279 nsecs_t timerSlack, nsecs_t minVsyncDistance)
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800280 : mTimeKeeper(std::move(tk)),
Leon Scroggins III67388622023-02-06 20:36:20 -0500281 mTracker(std::move(tracker)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800282 mTimerSlack(timerSlack),
283 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700284
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800285VSyncDispatchTimerQueue::~VSyncDispatchTimerQueue() {
Ady Abraham8cb21882020-08-26 18:22:05 -0700286 std::lock_guard lock(mMutex);
en.liu07e0e292023-07-05 19:01:52 +0800287 mRunning = false;
Kevin DuBois305bef12019-10-09 13:23:27 -0700288 cancelTimer();
Leon Scroggins III07738132023-04-24 11:43:53 -0400289 for (auto& [_, entry] : mCallbacks) {
290 ALOGE("Forgot to unregister a callback on VSyncDispatch!");
291 entry->ensureNotRunning();
292 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700293}
294
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800295void VSyncDispatchTimerQueue::cancelTimer() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700296 mIntendedWakeupTime = kInvalidTime;
297 mTimeKeeper->alarmCancel();
298}
299
Ady Abrahamb491c902020-08-15 15:47:56 -0700300void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700301 mIntendedWakeupTime = targetTime;
Ady Abrahamb491c902020-08-15 15:47:56 -0700302 mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
303 mIntendedWakeupTime);
Ady Abraham75398722020-04-07 14:08:45 -0700304 mLastTimerSchedule = mTimeKeeper->now();
Kevin DuBois305bef12019-10-09 13:23:27 -0700305}
306
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800307void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) {
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500308 rearmTimerSkippingUpdateFor(now, mCallbacks.cend());
Kevin DuBois305bef12019-10-09 13:23:27 -0700309}
310
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800311void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500312 nsecs_t now, CallbackMap::const_iterator skipUpdateIt) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000313 SFTRACE_CALL();
Kevin DuBois305bef12019-10-09 13:23:27 -0700314 std::optional<nsecs_t> min;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800315 std::optional<nsecs_t> targetVsync;
316 std::optional<std::string_view> nextWakeupName;
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500317 for (auto it = mCallbacks.cbegin(); it != mCallbacks.cend(); ++it) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700318 auto& callback = it->second;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700319 if (!callback->wakeupTime() && !callback->hasPendingWorkloadUpdate()) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700320 continue;
321 }
322
323 if (it != skipUpdateIt) {
Leon Scroggins III67388622023-02-06 20:36:20 -0500324 callback->update(*mTracker, now);
Kevin DuBois305bef12019-10-09 13:23:27 -0700325 }
Ady Abraham20024aa2024-03-05 01:32:49 +0000326
327 traceEntry(*callback, now);
328
329 const auto wakeupTime = *callback->wakeupTime();
Dominik Laskowski62eff352021-12-06 09:59:41 -0800330 if (!min || *min > wakeupTime) {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800331 nextWakeupName = callback->name();
Kevin DuBois305bef12019-10-09 13:23:27 -0700332 min = wakeupTime;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800333 targetVsync = callback->targetVsync();
Kevin DuBois305bef12019-10-09 13:23:27 -0700334 }
335 }
336
Dominik Laskowski62eff352021-12-06 09:59:41 -0800337 if (min && min < mIntendedWakeupTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700338 setTimer(*min, now);
339 } else {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000340 SFTRACE_NAME("cancel timer");
Kevin DuBois305bef12019-10-09 13:23:27 -0700341 cancelTimer();
342 }
343}
344
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800345void VSyncDispatchTimerQueue::timerCallback() {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000346 SFTRACE_CALL();
Kevin DuBois305bef12019-10-09 13:23:27 -0700347 struct Invocation {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800348 std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800349 nsecs_t vsyncTimestamp;
350 nsecs_t wakeupTimestamp;
Ady Abraham9c53ee72020-07-22 21:16:18 -0700351 nsecs_t deadlineTimestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700352 };
353 std::vector<Invocation> invocations;
354 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700355 std::lock_guard lock(mMutex);
en.liu07e0e292023-07-05 19:01:52 +0800356 if (!mRunning) {
357 ALOGD("TimerQueue is not running. Skipping callback.");
358 return;
359 }
Kevin DuBoisf9477832020-07-16 10:21:36 -0700360 auto const now = mTimeKeeper->now();
361 mLastTimerCallback = now;
Kevin DuBois305bef12019-10-09 13:23:27 -0700362 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
363 auto& callback = it->second;
364 auto const wakeupTime = callback->wakeupTime();
365 if (!wakeupTime) {
366 continue;
367 }
368
Ady Abraham20024aa2024-03-05 01:32:49 +0000369 traceEntry(*callback, now);
Ady Abraham9633f8e2024-03-04 19:38:12 +0000370
Ady Abraham20024aa2024-03-05 01:32:49 +0000371 auto const readyTime = callback->readyTime();
Kevin DuBoisf9477832020-07-16 10:21:36 -0700372 auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
373 if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700374 callback->executing();
Ady Abraham9c53ee72020-07-22 21:16:18 -0700375 invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
376 *wakeupTime, *readyTime});
Kevin DuBois305bef12019-10-09 13:23:27 -0700377 }
378 }
379
380 mIntendedWakeupTime = kInvalidTime;
381 rearmTimer(mTimeKeeper->now());
382 }
383
384 for (auto const& invocation : invocations) {
Ady Abraham20024aa2024-03-05 01:32:49 +0000385 ftl::Concat trace(ftl::truncated<5>(invocation.callback->name()));
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000386 SFTRACE_FORMAT("%s: %s", __func__, trace.c_str());
Ady Abraham9c53ee72020-07-22 21:16:18 -0700387 invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
388 invocation.deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700389 }
390}
391
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800392VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800393 Callback callback, std::string callbackName) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700394 std::lock_guard lock(mMutex);
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500395 return mCallbacks
Dominik Laskowski43baf902023-11-17 18:13:11 -0500396 .try_emplace(++mCallbackToken,
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500397 std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
398 std::move(callback),
399 mMinVsyncDistance))
400 .first->first;
Kevin DuBois305bef12019-10-09 13:23:27 -0700401}
402
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800403void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) {
404 std::shared_ptr<VSyncDispatchTimerQueueEntry> entry = nullptr;
Kevin DuBois305bef12019-10-09 13:23:27 -0700405 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700406 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700407 auto it = mCallbacks.find(token);
408 if (it != mCallbacks.end()) {
409 entry = it->second;
Dominik Laskowski0f3e5b92023-11-17 18:03:41 -0500410 mCallbacks.erase(it->first);
Kevin DuBois305bef12019-10-09 13:23:27 -0700411 }
412 }
413
414 if (entry) {
415 entry->ensureNotRunning();
416 }
417}
418
ramindani32a88b12024-01-31 18:45:30 -0800419std::optional<ScheduleResult> VSyncDispatchTimerQueue::schedule(CallbackToken token,
420 ScheduleTiming scheduleTiming) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800421 std::lock_guard lock(mMutex);
422 return scheduleLocked(token, scheduleTiming);
423}
Kevin DuBois305bef12019-10-09 13:23:27 -0700424
ramindani32a88b12024-01-31 18:45:30 -0800425std::optional<ScheduleResult> VSyncDispatchTimerQueue::scheduleLocked(
426 CallbackToken token, ScheduleTiming scheduleTiming) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800427 auto it = mCallbacks.find(token);
428 if (it == mCallbacks.end()) {
429 return {};
430 }
431 auto& callback = it->second;
432 auto const now = mTimeKeeper->now();
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700433
Ady Abraham011f8ba2022-11-22 15:09:07 -0800434 /* If the timer thread will run soon, we'll apply this work update via the callback
435 * timer recalculation to avoid cancelling a callback that is about to fire. */
436 auto const rearmImminent = now > mIntendedWakeupTime;
437 if (CC_UNLIKELY(rearmImminent)) {
Ady Abrahamda8af4c2024-02-14 00:24:34 +0000438 return callback->addPendingWorkloadUpdate(*mTracker, now, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800439 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700440
ramindani558f4a92024-02-16 15:49:23 -0800441 const auto result = callback->schedule(scheduleTiming, *mTracker, now);
ramindani32a88b12024-01-31 18:45:30 -0800442
Ady Abraham011f8ba2022-11-22 15:09:07 -0800443 if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
444 rearmTimerSkippingUpdateFor(now, it);
Kevin DuBois305bef12019-10-09 13:23:27 -0700445 }
446
ramindani558f4a92024-02-16 15:49:23 -0800447 return result;
Kevin DuBois305bef12019-10-09 13:23:27 -0700448}
449
ramindani32a88b12024-01-31 18:45:30 -0800450std::optional<ScheduleResult> VSyncDispatchTimerQueue::update(CallbackToken token,
451 ScheduleTiming scheduleTiming) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800452 std::lock_guard lock(mMutex);
453 const auto it = mCallbacks.find(token);
454 if (it == mCallbacks.end()) {
455 return {};
456 }
457
458 auto& callback = it->second;
459 if (!callback->targetVsync().has_value()) {
460 return {};
461 }
462
463 return scheduleLocked(token, scheduleTiming);
464}
465
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800466CancelResult VSyncDispatchTimerQueue::cancel(CallbackToken token) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700467 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700468
469 auto it = mCallbacks.find(token);
470 if (it == mCallbacks.end()) {
471 return CancelResult::Error;
472 }
473 auto& callback = it->second;
474
Kevin DuBoisb340b732020-06-16 09:07:35 -0700475 auto const wakeupTime = callback->wakeupTime();
476 if (wakeupTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700477 callback->disarm();
Kevin DuBoisb340b732020-06-16 09:07:35 -0700478
479 if (*wakeupTime == mIntendedWakeupTime) {
480 mIntendedWakeupTime = kInvalidTime;
481 rearmTimer(mTimeKeeper->now());
482 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700483 return CancelResult::Cancelled;
484 }
485 return CancelResult::TooLate;
486}
487
Ady Abraham5e7371c2020-03-24 14:47:24 -0700488void VSyncDispatchTimerQueue::dump(std::string& result) const {
Ady Abraham8cb21882020-08-26 18:22:05 -0700489 std::lock_guard lock(mMutex);
Ady Abraham75398722020-04-07 14:08:45 -0700490 StringAppendF(&result, "\tTimer:\n");
491 mTimeKeeper->dump(result);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700492 StringAppendF(&result, "\tmTimerSlack: %.2fms mMinVsyncDistance: %.2fms\n", mTimerSlack / 1e6f,
493 mMinVsyncDistance / 1e6f);
494 StringAppendF(&result, "\tmIntendedWakeupTime: %.2fms from now\n",
Ady Abraham75398722020-04-07 14:08:45 -0700495 (mIntendedWakeupTime - mTimeKeeper->now()) / 1e6f);
496 StringAppendF(&result, "\tmLastTimerCallback: %.2fms ago mLastTimerSchedule: %.2fms ago\n",
497 (mTimeKeeper->now() - mLastTimerCallback) / 1e6f,
498 (mTimeKeeper->now() - mLastTimerSchedule) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700499 StringAppendF(&result, "\tCallbacks:\n");
500 for (const auto& [token, entry] : mCallbacks) {
501 entry->dump(result);
502 }
503}
504
Leon Scroggins III67388622023-02-06 20:36:20 -0500505VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800506 VSyncDispatch::Callback callback,
507 std::string callbackName)
Leon Scroggins III67388622023-02-06 20:36:20 -0500508 : mDispatch(std::move(dispatch)),
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400509 mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700510
511VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncCallbackRegistration&& other)
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400512 : mDispatch(std::move(other.mDispatch)), mToken(std::exchange(other.mToken, std::nullopt)) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700513
514VSyncCallbackRegistration& VSyncCallbackRegistration::operator=(VSyncCallbackRegistration&& other) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400515 if (this == &other) return *this;
516 if (mToken) {
517 mDispatch->unregisterCallback(*mToken);
518 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700519 mDispatch = std::move(other.mDispatch);
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400520 mToken = std::exchange(other.mToken, std::nullopt);
Kevin DuBois305bef12019-10-09 13:23:27 -0700521 return *this;
522}
523
524VSyncCallbackRegistration::~VSyncCallbackRegistration() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400525 if (mToken) mDispatch->unregisterCallback(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700526}
527
ramindani32a88b12024-01-31 18:45:30 -0800528std::optional<ScheduleResult> VSyncCallbackRegistration::schedule(
529 VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400530 if (!mToken) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700531 return std::nullopt;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800532 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400533 return mDispatch->schedule(*mToken, scheduleTiming);
Kevin DuBois305bef12019-10-09 13:23:27 -0700534}
535
ramindani32a88b12024-01-31 18:45:30 -0800536std::optional<ScheduleResult> VSyncCallbackRegistration::update(
537 VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400538 if (!mToken) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800539 return std::nullopt;
540 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400541 return mDispatch->update(*mToken, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800542}
543
Kevin DuBois305bef12019-10-09 13:23:27 -0700544CancelResult VSyncCallbackRegistration::cancel() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400545 if (!mToken) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800546 return CancelResult::Error;
547 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400548 return mDispatch->cancel(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700549}
550
551} // namespace android::scheduler