1 /* 2 * Copyright (C) 2016 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 #ifndef ANDROID_FENCE_TIME_H 18 #define ANDROID_FENCE_TIME_H 19 20 #include <ui/Fence.h> 21 #include <utils/Flattenable.h> 22 #include <utils/Mutex.h> 23 #include <utils/Timers.h> 24 25 #include <atomic> 26 #include <mutex> 27 #include <queue> 28 #include <unordered_map> 29 30 namespace android { 31 32 class FenceToFenceTimeMap; 33 34 // A wrapper around fence that only implements isValid and getSignalTime. 35 // It automatically closes the fence in a thread-safe manner once the signal 36 // time is known. 37 class FenceTime { 38 friend class FenceToFenceTimeMap; 39 public: 40 // An atomic snapshot of the FenceTime that is flattenable. 41 // 42 // This class is needed because the FenceTime class may not stay 43 // consistent for all steps of the flattening process. 44 // 45 // Not thread safe. 46 struct Snapshot : public Flattenable<Snapshot> { 47 enum class State { 48 EMPTY, 49 FENCE, 50 SIGNAL_TIME, 51 }; 52 53 Snapshot() = default; // Creates an empty snapshot. 54 explicit Snapshot(const sp<Fence>& fence); 55 explicit Snapshot(nsecs_t signalTime); 56 57 // Movable. 58 Snapshot(Snapshot&& src) = default; 59 Snapshot& operator=(Snapshot&& src) = default; 60 // Not copyable. 61 Snapshot(const Snapshot& src) = delete; 62 Snapshot& operator=(const Snapshot&& src) = delete; 63 64 // Flattenable implementation. 65 size_t getFlattenedSize() const; 66 size_t getFdCount() const; 67 status_t flatten(void*& buffer, size_t& size, int*& fds, 68 size_t& count) const; 69 status_t unflatten(void const*& buffer, size_t& size, int const*& fds, 70 size_t& count); 71 72 State state{State::EMPTY}; 73 sp<Fence> fence{Fence::NO_FENCE}; 74 nsecs_t signalTime{Fence::SIGNAL_TIME_INVALID}; 75 }; 76 77 static const std::shared_ptr<FenceTime> NO_FENCE; 78 79 explicit FenceTime(const sp<Fence>& fence); 80 explicit FenceTime(sp<Fence>&& fence); 81 82 // Passing in Fence::SIGNAL_TIME_PENDING is not allowed. 83 // Doing so will convert the signalTime to Fence::SIGNAL_TIME_INVALID. 84 explicit FenceTime(nsecs_t signalTime); 85 86 // Do not allow default construction. Share NO_FENCE or explicitly construct 87 // with Fence::SIGNAL_TIME_INVALID instead. 88 FenceTime() = delete; 89 90 // Do not allow copy, assign, or move. Use a shared_ptr to share the 91 // signalTime result. Or use getSnapshot() if a thread-safe copy is really 92 // needed. 93 FenceTime(const FenceTime&) = delete; 94 FenceTime(FenceTime&&) = delete; 95 FenceTime& operator=(const FenceTime&) = delete; 96 FenceTime& operator=(FenceTime&&) = delete; 97 98 // This method should only be called when replacing the fence with 99 // a signalTime. Since this is an indirect way of setting the signal time 100 // of a fence, the snapshot should come from a trusted source. 101 void applyTrustedSnapshot(const Snapshot& src); 102 103 bool isValid() const; 104 105 // Attempts to get the timestamp from the Fence if the timestamp isn't 106 // already cached. Otherwise, it returns the cached value. 107 nsecs_t getSignalTime(); 108 109 // Gets the cached timestamp without attempting to query the Fence. 110 nsecs_t getCachedSignalTime() const; 111 112 // Returns a snapshot of the FenceTime in its current state. 113 Snapshot getSnapshot() const; 114 115 // wait waits for up to timeout milliseconds for the fence to signal. If 116 // the fence signals then NO_ERROR is returned. If the timeout expires 117 // before the fence signals then -ETIME is returned. A timeout of 118 // TIMEOUT_NEVER may be used to indicate that the call should wait 119 // indefinitely for the fence to signal. 120 status_t wait(int timeout); 121 122 void signalForTest(nsecs_t signalTime); 123 124 private: 125 // For tests only. If forceValidForTest is true, then getSignalTime will 126 // never return SIGNAL_TIME_INVALID and isValid will always return true. 127 FenceTime(const sp<Fence>& fence, bool forceValidForTest); 128 129 enum class State { 130 VALID, 131 INVALID, 132 FORCED_VALID_FOR_TEST, 133 }; 134 135 const State mState{State::INVALID}; 136 137 // mMutex guards mFence and mSignalTime. 138 // mSignalTime is also atomic since it is sometimes read outside the lock 139 // for quick checks. 140 mutable std::mutex mMutex; 141 sp<Fence> mFence{Fence::NO_FENCE}; 142 std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID}; 143 }; 144 145 // A queue of FenceTimes that are expected to signal in FIFO order. 146 // Only maintains a queue of weak pointers so it doesn't keep references 147 // to Fences on its own. 148 // 149 // Can be used to get the signal time of a fence and close its file descriptor 150 // without making a syscall for every fence later in the timeline. 151 // Additionally, since the FenceTime caches the timestamp internally, 152 // other timelines that reference the same FenceTime can avoid the syscall. 153 // 154 // FenceTimeline only keeps track of a limited number of entries to avoid 155 // growing unbounded. Users of FenceTime must make sure they can work even 156 // if FenceTimeline did nothing. i.e. they should eventually call 157 // Fence::getSignalTime(), not only Fence::getCachedSignalTime(). 158 // 159 // push() and updateSignalTimes() are safe to call simultaneously from 160 // different threads. 161 class FenceTimeline { 162 public: 163 static constexpr size_t MAX_ENTRIES = 64; 164 165 void push(const std::shared_ptr<FenceTime>& fence); 166 void updateSignalTimes(); 167 168 private: 169 mutable std::mutex mMutex; 170 std::queue<std::weak_ptr<FenceTime>> mQueue GUARDED_BY(mMutex); 171 }; 172 173 // Used by test code to create or get FenceTimes for a given Fence. 174 // 175 // By design, Fences cannot be signaled from user space. However, this class 176 // allows test code to set the apparent signalTime of a Fence and 177 // have it be visible to all FenceTimes. Release code should not use 178 // FenceToFenceTimeMap. 179 // 180 // FenceToFenceTimeMap keeps a weak reference to the FenceTime and automatically 181 // garbage collects entries every time a new FenceTime is created to avoid 182 // leaks. This prevents us from having to make the Fence destructor 183 // automatically notify that the underlying fence has been destroyed, which 184 // would affect release code paths. Garbage collecting so often is inefficient, 185 // but acceptable for testing. 186 // 187 // Since FenceTimes maintain a strong reference to underlying Fences, there 188 // should not be any aliasing issues where a new Fence happens to have the same 189 // address as a previous Fence; the previous entry will be garbage collected 190 // before the new one is added. 191 class FenceToFenceTimeMap { 192 public: 193 // Create a new FenceTime with that wraps the provided Fence. 194 std::shared_ptr<FenceTime> createFenceTimeForTest(const sp<Fence>& fence); 195 196 // Signals all FenceTimes created through this class that are wrappers 197 // around |fence|. 198 void signalAllForTest(const sp<Fence>& fence, nsecs_t signalTime); 199 200 private: 201 // Cleans up the entries that no longer have a strong reference. 202 void garbageCollectLocked(); 203 204 mutable std::mutex mMutex; 205 std::unordered_map<Fence*, std::vector<std::weak_ptr<FenceTime>>> mMap; 206 }; 207 208 209 }; // namespace android 210 211 #endif // ANDROID_FENCE_TIME_H 212