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