1 /* 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 #pragma once 18 19 #include <functional> 20 #include <memory> 21 #include <mutex> 22 #include <string> 23 #include <string_view> 24 #include <unordered_map> 25 26 #include <android-base/thread_annotations.h> 27 28 #include "VSyncDispatch.h" 29 30 namespace android::scheduler { 31 32 class TimeKeeper; 33 class VSyncTracker; 34 35 // VSyncDispatchTimerQueueEntry is a helper class representing internal state for each entry in 36 // VSyncDispatchTimerQueue hoisted to public for unit testing. 37 class VSyncDispatchTimerQueueEntry { 38 public: 39 // This is the state of the entry. There are 3 states, armed, running, disarmed. 40 // Valid transition: disarmed -> armed ( when scheduled ) 41 // Valid transition: armed -> running -> disarmed ( when timer is called) 42 // Valid transition: armed -> disarmed ( when cancelled ) 43 VSyncDispatchTimerQueueEntry(std::string name, VSyncDispatch::Callback, 44 nsecs_t minVsyncDistance); 45 std::string_view name() const; 46 47 // Start: functions that are not threadsafe. 48 // Return the last vsync time this callback was invoked. 49 std::optional<nsecs_t> lastExecutedVsyncTarget() const; 50 51 // This moves the state from disarmed->armed and will calculate the wakeupTime. 52 ScheduleResult schedule(VSyncDispatch::ScheduleTiming, VSyncTracker&, nsecs_t now); 53 // This will update armed entries with the latest vsync information. Entry remains armed. 54 void update(VSyncTracker&, nsecs_t now); 55 56 // This will return empty if not armed, or the next calculated wakeup time if armed. 57 // It will not update the wakeupTime. 58 std::optional<nsecs_t> wakeupTime() const; 59 60 std::optional<nsecs_t> readyTime() const; 61 62 std::optional<nsecs_t> targetVsync() const; 63 64 // This moves state from armed->disarmed. 65 void disarm(); 66 67 // This moves the state from armed->running. 68 // Store the timestamp that this was intended for as the last called timestamp. 69 nsecs_t executing(); 70 71 // Adds a pending upload of the earliestVSync and workDuration that will be applied on the next 72 // call to update() 73 void addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming); 74 75 // Checks if there is a pending update to the workload, returning true if so. 76 bool hasPendingWorkloadUpdate() const; 77 // End: functions that are not threadsafe. 78 79 // Invoke the callback with the two given timestamps, moving the state from running->disarmed. 80 void callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp, nsecs_t deadlineTimestamp); 81 // Block calling thread while the callback is executing. 82 void ensureNotRunning(); 83 84 void dump(std::string& result) const; 85 86 private: 87 const std::string mName; 88 const VSyncDispatch::Callback mCallback; 89 90 VSyncDispatch::ScheduleTiming mScheduleTiming; 91 const nsecs_t mMinVsyncDistance; 92 93 struct ArmingInfo { 94 nsecs_t mActualWakeupTime; 95 nsecs_t mActualVsyncTime; 96 nsecs_t mActualReadyTime; 97 }; 98 std::optional<ArmingInfo> mArmedInfo; 99 std::optional<nsecs_t> mLastDispatchTime; 100 101 std::optional<VSyncDispatch::ScheduleTiming> mWorkloadUpdateInfo; 102 103 mutable std::mutex mRunningMutex; 104 std::condition_variable mCv; 105 bool mRunning GUARDED_BY(mRunningMutex) = false; 106 }; 107 108 /* 109 * VSyncDispatchTimerQueue is a class that will dispatch callbacks as per VSyncDispatch interface 110 * using a single timer queue. 111 */ 112 class VSyncDispatchTimerQueue : public VSyncDispatch { 113 public: 114 // Constructs a VSyncDispatchTimerQueue. 115 // \param[in] tk A timekeeper. 116 // \param[in] tracker A tracker. 117 // \param[in] timerSlack The threshold at which different similarly timed callbacks 118 // should be grouped into one wakeup. 119 // \param[in] minVsyncDistance The minimum distance between two vsync estimates before the 120 // vsyncs are considered the same vsync event. 121 VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper>, VSyncTracker&, nsecs_t timerSlack, 122 nsecs_t minVsyncDistance); 123 ~VSyncDispatchTimerQueue(); 124 125 CallbackToken registerCallback(Callback, std::string callbackName) final; 126 void unregisterCallback(CallbackToken) final; 127 ScheduleResult schedule(CallbackToken, ScheduleTiming) final; 128 CancelResult cancel(CallbackToken) final; 129 void dump(std::string&) const final; 130 131 private: 132 VSyncDispatchTimerQueue(const VSyncDispatchTimerQueue&) = delete; 133 VSyncDispatchTimerQueue& operator=(const VSyncDispatchTimerQueue&) = delete; 134 135 using CallbackMap = 136 std::unordered_map<CallbackToken, std::shared_ptr<VSyncDispatchTimerQueueEntry>>; 137 138 void timerCallback(); 139 void setTimer(nsecs_t, nsecs_t) REQUIRES(mMutex); 140 void rearmTimer(nsecs_t now) REQUIRES(mMutex); 141 void rearmTimerSkippingUpdateFor(nsecs_t now, CallbackMap::iterator const& skipUpdate) 142 REQUIRES(mMutex); 143 void cancelTimer() REQUIRES(mMutex); 144 145 static constexpr nsecs_t kInvalidTime = std::numeric_limits<int64_t>::max(); 146 std::unique_ptr<TimeKeeper> const mTimeKeeper; 147 VSyncTracker& mTracker; 148 nsecs_t const mTimerSlack; 149 nsecs_t const mMinVsyncDistance; 150 151 std::mutex mutable mMutex; 152 size_t mCallbackToken GUARDED_BY(mMutex) = 0; 153 154 CallbackMap mCallbacks GUARDED_BY(mMutex); 155 nsecs_t mIntendedWakeupTime GUARDED_BY(mMutex) = kInvalidTime; 156 157 // For debugging purposes 158 nsecs_t mLastTimerCallback GUARDED_BY(mMutex) = kInvalidTime; 159 nsecs_t mLastTimerSchedule GUARDED_BY(mMutex) = kInvalidTime; 160 }; 161 162 } // namespace android::scheduler 163