blob: 1f922f11fb888cc9435f0db6afc9a1a8dc6ee6bb [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>
22#include <ftl/concat.h>
23#include <utils/Trace.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
Kevin DuBoise4f27a82019-11-12 11:41:41 -080028#include "VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070029#include "VSyncTracker.h"
30
Leon Scroggins III07738132023-04-24 11:43:53 -040031#undef LOG_TAG
32#define LOG_TAG "VSyncDispatch"
33
Kevin DuBois305bef12019-10-09 13:23:27 -070034namespace android::scheduler {
Dominik Laskowski62eff352021-12-06 09:59:41 -080035
Ady Abraham5e7371c2020-03-24 14:47:24 -070036using base::StringAppendF;
Kevin DuBois305bef12019-10-09 13:23:27 -070037
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070038namespace {
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080039
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070040nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
41 const VSyncDispatch::ScheduleTiming& timing) {
42 return nextVsyncTime - timing.readyDuration - timing.workDuration;
43}
44
45nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now,
46 const VSyncDispatch::ScheduleTiming& timing) {
47 const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
48 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
49 return getExpectedCallbackTime(nextVsyncTime, timing);
50}
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080051
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070052} // namespace
53
Kevin DuBoise4f27a82019-11-12 11:41:41 -080054VSyncDispatch::~VSyncDispatch() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070055VSyncTracker::~VSyncTracker() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070056
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080057VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string name,
58 VSyncDispatch::Callback callback,
Kevin DuBoisc94ca832019-11-26 12:56:24 -080059 nsecs_t minVsyncDistance)
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080060 : mName(std::move(name)),
61 mCallback(std::move(callback)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -080062 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -070063
Kevin DuBoise4f27a82019-11-12 11:41:41 -080064std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::lastExecutedVsyncTarget() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070065 return mLastDispatchTime;
66}
67
Kevin DuBoise4f27a82019-11-12 11:41:41 -080068std::string_view VSyncDispatchTimerQueueEntry::name() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070069 return mName;
70}
71
Kevin DuBoise4f27a82019-11-12 11:41:41 -080072std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::wakeupTime() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070073 if (!mArmedInfo) {
74 return {};
75 }
76 return {mArmedInfo->mActualWakeupTime};
77}
78
Ady Abraham9c53ee72020-07-22 21:16:18 -070079std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::readyTime() const {
80 if (!mArmedInfo) {
81 return {};
82 }
83 return {mArmedInfo->mActualReadyTime};
84}
85
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -080086std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::targetVsync() const {
87 if (!mArmedInfo) {
88 return {};
89 }
90 return {mArmedInfo->mActualVsyncTime};
91}
92
Ady Abraham9c53ee72020-07-22 21:16:18 -070093ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
Kevin DuBois2311b1a2019-11-18 16:19:08 -080094 VSyncTracker& tracker, nsecs_t now) {
Ady Abraham9c53ee72020-07-22 21:16:18 -070095 auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
96 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
Ady Abraham69b9e622021-07-19 12:24:31 -070097 auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBoisc94ca832019-11-26 12:56:24 -080098
99 bool const wouldSkipAVsyncTarget =
100 mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
Ady Abraham69b9e622021-07-19 12:24:31 -0700101 bool const wouldSkipAWakeup =
102 mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
103 if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700104 return getExpectedCallbackTime(nextVsyncTime, timing);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800105 }
106
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700107 nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
108 nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800109
Ady Abraham9c53ee72020-07-22 21:16:18 -0700110 auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
111 mScheduleTiming = timing;
112 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700113 return getExpectedCallbackTime(nextVsyncTime, timing);
Kevin DuBois305bef12019-10-09 13:23:27 -0700114}
115
Ady Abraham9c53ee72020-07-22 21:16:18 -0700116void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) {
117 mWorkloadUpdateInfo = timing;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700118}
119
120bool VSyncDispatchTimerQueueEntry::hasPendingWorkloadUpdate() const {
121 return mWorkloadUpdateInfo.has_value();
122}
123
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700124nsecs_t VSyncDispatchTimerQueueEntry::adjustVsyncIfNeeded(VSyncTracker& tracker,
125 nsecs_t nextVsyncTime) const {
126 bool const alreadyDispatchedForVsync = mLastDispatchTime &&
127 ((*mLastDispatchTime + mMinVsyncDistance) >= nextVsyncTime &&
128 (*mLastDispatchTime - mMinVsyncDistance) <= nextVsyncTime);
129 const nsecs_t currentPeriod = tracker.currentPeriod();
130 bool const nextVsyncTooClose = mLastDispatchTime &&
131 (nextVsyncTime - *mLastDispatchTime + mMinVsyncDistance) <= currentPeriod;
132 if (alreadyDispatchedForVsync) {
133 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance);
134 }
135
136 if (nextVsyncTooClose) {
137 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + currentPeriod);
138 }
139
140 return nextVsyncTime;
141}
142
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800143void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700144 if (!mArmedInfo && !mWorkloadUpdateInfo) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700145 return;
146 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700147
148 if (mWorkloadUpdateInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700149 mScheduleTiming = *mWorkloadUpdateInfo;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700150 mWorkloadUpdateInfo.reset();
151 }
152
Ady Abraham9c53ee72020-07-22 21:16:18 -0700153 const auto earliestReadyBy = now + mScheduleTiming.workDuration + mScheduleTiming.readyDuration;
154 const auto earliestVsync = std::max(earliestReadyBy, mScheduleTiming.earliestVsync);
155
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700156 const auto nextVsyncTime =
157 adjustVsyncIfNeeded(tracker, /*nextVsyncTime*/
158 tracker.nextAnticipatedVSyncTimeFrom(earliestVsync));
Ady Abraham9c53ee72020-07-22 21:16:18 -0700159 const auto nextReadyTime = nextVsyncTime - mScheduleTiming.readyDuration;
160 const auto nextWakeupTime = nextReadyTime - mScheduleTiming.workDuration;
161
162 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Kevin DuBois305bef12019-10-09 13:23:27 -0700163}
164
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800165void VSyncDispatchTimerQueueEntry::disarm() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700166 mArmedInfo.reset();
167}
168
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800169nsecs_t VSyncDispatchTimerQueueEntry::executing() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700170 mLastDispatchTime = mArmedInfo->mActualVsyncTime;
171 disarm();
172 return *mLastDispatchTime;
173}
174
Ady Abraham9c53ee72020-07-22 21:16:18 -0700175void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
176 nsecs_t deadlineTimestamp) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700177 {
178 std::lock_guard<std::mutex> lk(mRunningMutex);
179 mRunning = true;
180 }
181
Ady Abraham9c53ee72020-07-22 21:16:18 -0700182 mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700183
184 std::lock_guard<std::mutex> lk(mRunningMutex);
185 mRunning = false;
186 mCv.notify_all();
187}
188
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800189void VSyncDispatchTimerQueueEntry::ensureNotRunning() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700190 std::unique_lock<std::mutex> lk(mRunningMutex);
191 mCv.wait(lk, [this]() REQUIRES(mRunningMutex) { return !mRunning; });
192}
193
Ady Abraham5e7371c2020-03-24 14:47:24 -0700194void VSyncDispatchTimerQueueEntry::dump(std::string& result) const {
195 std::lock_guard<std::mutex> lk(mRunningMutex);
196 std::string armedInfo;
197 if (mArmedInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700198 StringAppendF(&armedInfo,
199 "[wake up in %.2fms deadline in %.2fms for vsync %.2fms from now]",
Ady Abraham5e7371c2020-03-24 14:47:24 -0700200 (mArmedInfo->mActualWakeupTime - systemTime()) / 1e6f,
Ady Abraham9c53ee72020-07-22 21:16:18 -0700201 (mArmedInfo->mActualReadyTime - systemTime()) / 1e6f,
Ady Abraham5e7371c2020-03-24 14:47:24 -0700202 (mArmedInfo->mActualVsyncTime - systemTime()) / 1e6f);
203 }
204
205 StringAppendF(&result, "\t\t%s: %s %s\n", mName.c_str(),
206 mRunning ? "(in callback function)" : "", armedInfo.c_str());
Ady Abraham9c53ee72020-07-22 21:16:18 -0700207 StringAppendF(&result,
208 "\t\t\tworkDuration: %.2fms readyDuration: %.2fms earliestVsync: %.2fms relative "
209 "to now\n",
210 mScheduleTiming.workDuration / 1e6f, mScheduleTiming.readyDuration / 1e6f,
211 (mScheduleTiming.earliestVsync - systemTime()) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700212
213 if (mLastDispatchTime) {
214 StringAppendF(&result, "\t\t\tmLastDispatchTime: %.2fms ago\n",
215 (systemTime() - *mLastDispatchTime) / 1e6f);
216 } else {
217 StringAppendF(&result, "\t\t\tmLastDispatchTime unknown\n");
218 }
219}
220
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800221VSyncDispatchTimerQueue::VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper> tk,
Leon Scroggins III67388622023-02-06 20:36:20 -0500222 VsyncSchedule::TrackerPtr tracker,
223 nsecs_t timerSlack, nsecs_t minVsyncDistance)
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800224 : mTimeKeeper(std::move(tk)),
Leon Scroggins III67388622023-02-06 20:36:20 -0500225 mTracker(std::move(tracker)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800226 mTimerSlack(timerSlack),
227 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700228
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800229VSyncDispatchTimerQueue::~VSyncDispatchTimerQueue() {
Ady Abraham8cb21882020-08-26 18:22:05 -0700230 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700231 cancelTimer();
Leon Scroggins III07738132023-04-24 11:43:53 -0400232 for (auto& [_, entry] : mCallbacks) {
233 ALOGE("Forgot to unregister a callback on VSyncDispatch!");
234 entry->ensureNotRunning();
235 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700236}
237
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800238void VSyncDispatchTimerQueue::cancelTimer() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700239 mIntendedWakeupTime = kInvalidTime;
240 mTimeKeeper->alarmCancel();
241}
242
Ady Abrahamb491c902020-08-15 15:47:56 -0700243void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700244 mIntendedWakeupTime = targetTime;
Ady Abrahamb491c902020-08-15 15:47:56 -0700245 mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
246 mIntendedWakeupTime);
Ady Abraham75398722020-04-07 14:08:45 -0700247 mLastTimerSchedule = mTimeKeeper->now();
Kevin DuBois305bef12019-10-09 13:23:27 -0700248}
249
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800250void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700251 rearmTimerSkippingUpdateFor(now, mCallbacks.end());
252}
253
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800254void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
255 nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700256 std::optional<nsecs_t> min;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800257 std::optional<nsecs_t> targetVsync;
258 std::optional<std::string_view> nextWakeupName;
Kevin DuBois305bef12019-10-09 13:23:27 -0700259 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
260 auto& callback = it->second;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700261 if (!callback->wakeupTime() && !callback->hasPendingWorkloadUpdate()) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700262 continue;
263 }
264
265 if (it != skipUpdateIt) {
Leon Scroggins III67388622023-02-06 20:36:20 -0500266 callback->update(*mTracker, now);
Kevin DuBois305bef12019-10-09 13:23:27 -0700267 }
268 auto const wakeupTime = *callback->wakeupTime();
Dominik Laskowski62eff352021-12-06 09:59:41 -0800269 if (!min || *min > wakeupTime) {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800270 nextWakeupName = callback->name();
Kevin DuBois305bef12019-10-09 13:23:27 -0700271 min = wakeupTime;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800272 targetVsync = callback->targetVsync();
Kevin DuBois305bef12019-10-09 13:23:27 -0700273 }
274 }
275
Dominik Laskowski62eff352021-12-06 09:59:41 -0800276 if (min && min < mIntendedWakeupTime) {
277 if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
278 ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
279 "us; VSYNC in ", ns2us(*targetVsync - now), "us");
280 ATRACE_NAME(trace.c_str());
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800281 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700282 setTimer(*min, now);
283 } else {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800284 ATRACE_NAME("cancel timer");
Kevin DuBois305bef12019-10-09 13:23:27 -0700285 cancelTimer();
286 }
287}
288
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800289void VSyncDispatchTimerQueue::timerCallback() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700290 struct Invocation {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800291 std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800292 nsecs_t vsyncTimestamp;
293 nsecs_t wakeupTimestamp;
Ady Abraham9c53ee72020-07-22 21:16:18 -0700294 nsecs_t deadlineTimestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700295 };
296 std::vector<Invocation> invocations;
297 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700298 std::lock_guard lock(mMutex);
Kevin DuBoisf9477832020-07-16 10:21:36 -0700299 auto const now = mTimeKeeper->now();
300 mLastTimerCallback = now;
Kevin DuBois305bef12019-10-09 13:23:27 -0700301 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
302 auto& callback = it->second;
303 auto const wakeupTime = callback->wakeupTime();
304 if (!wakeupTime) {
305 continue;
306 }
307
Ady Abraham9c53ee72020-07-22 21:16:18 -0700308 auto const readyTime = callback->readyTime();
309
Kevin DuBoisf9477832020-07-16 10:21:36 -0700310 auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
311 if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700312 callback->executing();
Ady Abraham9c53ee72020-07-22 21:16:18 -0700313 invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
314 *wakeupTime, *readyTime});
Kevin DuBois305bef12019-10-09 13:23:27 -0700315 }
316 }
317
318 mIntendedWakeupTime = kInvalidTime;
319 rearmTimer(mTimeKeeper->now());
320 }
321
322 for (auto const& invocation : invocations) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700323 invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
324 invocation.deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700325 }
326}
327
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800328VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800329 Callback callback, std::string callbackName) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700330 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700331 return CallbackToken{
332 mCallbacks
333 .emplace(++mCallbackToken,
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800334 std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
335 std::move(callback),
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800336 mMinVsyncDistance))
Kevin DuBois305bef12019-10-09 13:23:27 -0700337 .first->first};
338}
339
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800340void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) {
341 std::shared_ptr<VSyncDispatchTimerQueueEntry> entry = nullptr;
Kevin DuBois305bef12019-10-09 13:23:27 -0700342 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700343 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700344 auto it = mCallbacks.find(token);
345 if (it != mCallbacks.end()) {
346 entry = it->second;
347 mCallbacks.erase(it);
348 }
349 }
350
351 if (entry) {
352 entry->ensureNotRunning();
353 }
354}
355
Ady Abraham9c53ee72020-07-22 21:16:18 -0700356ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
357 ScheduleTiming scheduleTiming) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800358 std::lock_guard lock(mMutex);
359 return scheduleLocked(token, scheduleTiming);
360}
Kevin DuBois305bef12019-10-09 13:23:27 -0700361
Ady Abraham011f8ba2022-11-22 15:09:07 -0800362ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
363 ScheduleTiming scheduleTiming) {
364 auto it = mCallbacks.find(token);
365 if (it == mCallbacks.end()) {
366 return {};
367 }
368 auto& callback = it->second;
369 auto const now = mTimeKeeper->now();
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700370
Ady Abraham011f8ba2022-11-22 15:09:07 -0800371 /* If the timer thread will run soon, we'll apply this work update via the callback
372 * timer recalculation to avoid cancelling a callback that is about to fire. */
373 auto const rearmImminent = now > mIntendedWakeupTime;
374 if (CC_UNLIKELY(rearmImminent)) {
375 callback->addPendingWorkloadUpdate(scheduleTiming);
Leon Scroggins III67388622023-02-06 20:36:20 -0500376 return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800377 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700378
Leon Scroggins III67388622023-02-06 20:36:20 -0500379 const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800380 if (!result.has_value()) {
381 return {};
382 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700383
Ady Abraham011f8ba2022-11-22 15:09:07 -0800384 if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
385 rearmTimerSkippingUpdateFor(now, it);
Kevin DuBois305bef12019-10-09 13:23:27 -0700386 }
387
388 return result;
389}
390
Ady Abraham011f8ba2022-11-22 15:09:07 -0800391ScheduleResult VSyncDispatchTimerQueue::update(CallbackToken token, ScheduleTiming scheduleTiming) {
392 std::lock_guard lock(mMutex);
393 const auto it = mCallbacks.find(token);
394 if (it == mCallbacks.end()) {
395 return {};
396 }
397
398 auto& callback = it->second;
399 if (!callback->targetVsync().has_value()) {
400 return {};
401 }
402
403 return scheduleLocked(token, scheduleTiming);
404}
405
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800406CancelResult VSyncDispatchTimerQueue::cancel(CallbackToken token) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700407 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700408
409 auto it = mCallbacks.find(token);
410 if (it == mCallbacks.end()) {
411 return CancelResult::Error;
412 }
413 auto& callback = it->second;
414
Kevin DuBoisb340b732020-06-16 09:07:35 -0700415 auto const wakeupTime = callback->wakeupTime();
416 if (wakeupTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700417 callback->disarm();
Kevin DuBoisb340b732020-06-16 09:07:35 -0700418
419 if (*wakeupTime == mIntendedWakeupTime) {
420 mIntendedWakeupTime = kInvalidTime;
421 rearmTimer(mTimeKeeper->now());
422 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700423 return CancelResult::Cancelled;
424 }
425 return CancelResult::TooLate;
426}
427
Ady Abraham5e7371c2020-03-24 14:47:24 -0700428void VSyncDispatchTimerQueue::dump(std::string& result) const {
Ady Abraham8cb21882020-08-26 18:22:05 -0700429 std::lock_guard lock(mMutex);
Ady Abraham75398722020-04-07 14:08:45 -0700430 StringAppendF(&result, "\tTimer:\n");
431 mTimeKeeper->dump(result);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700432 StringAppendF(&result, "\tmTimerSlack: %.2fms mMinVsyncDistance: %.2fms\n", mTimerSlack / 1e6f,
433 mMinVsyncDistance / 1e6f);
434 StringAppendF(&result, "\tmIntendedWakeupTime: %.2fms from now\n",
Ady Abraham75398722020-04-07 14:08:45 -0700435 (mIntendedWakeupTime - mTimeKeeper->now()) / 1e6f);
436 StringAppendF(&result, "\tmLastTimerCallback: %.2fms ago mLastTimerSchedule: %.2fms ago\n",
437 (mTimeKeeper->now() - mLastTimerCallback) / 1e6f,
438 (mTimeKeeper->now() - mLastTimerSchedule) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700439 StringAppendF(&result, "\tCallbacks:\n");
440 for (const auto& [token, entry] : mCallbacks) {
441 entry->dump(result);
442 }
443}
444
Leon Scroggins III67388622023-02-06 20:36:20 -0500445VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800446 VSyncDispatch::Callback callback,
447 std::string callbackName)
Leon Scroggins III67388622023-02-06 20:36:20 -0500448 : mDispatch(std::move(dispatch)),
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400449 mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700450
451VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncCallbackRegistration&& other)
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400452 : mDispatch(std::move(other.mDispatch)), mToken(std::exchange(other.mToken, std::nullopt)) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700453
454VSyncCallbackRegistration& VSyncCallbackRegistration::operator=(VSyncCallbackRegistration&& other) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400455 if (this == &other) return *this;
456 if (mToken) {
457 mDispatch->unregisterCallback(*mToken);
458 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700459 mDispatch = std::move(other.mDispatch);
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400460 mToken = std::exchange(other.mToken, std::nullopt);
Kevin DuBois305bef12019-10-09 13:23:27 -0700461 return *this;
462}
463
464VSyncCallbackRegistration::~VSyncCallbackRegistration() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400465 if (mToken) mDispatch->unregisterCallback(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700466}
467
Ady Abraham9c53ee72020-07-22 21:16:18 -0700468ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400469 if (!mToken) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700470 return std::nullopt;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800471 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400472 return mDispatch->schedule(*mToken, scheduleTiming);
Kevin DuBois305bef12019-10-09 13:23:27 -0700473}
474
Ady Abraham011f8ba2022-11-22 15:09:07 -0800475ScheduleResult VSyncCallbackRegistration::update(VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400476 if (!mToken) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800477 return std::nullopt;
478 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400479 return mDispatch->update(*mToken, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800480}
481
Kevin DuBois305bef12019-10-09 13:23:27 -0700482CancelResult VSyncCallbackRegistration::cancel() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400483 if (!mToken) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800484 return CancelResult::Error;
485 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400486 return mDispatch->cancel(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700487}
488
489} // namespace android::scheduler