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     void signalForTest(nsecs_t signalTime);
116 
117 private:
118     // For tests only. If forceValidForTest is true, then getSignalTime will
119     // never return SIGNAL_TIME_INVALID and isValid will always return true.
120     FenceTime(const sp<Fence>& fence, bool forceValidForTest);
121 
122     enum class State {
123         VALID,
124         INVALID,
125         FORCED_VALID_FOR_TEST,
126     };
127 
128     const State mState{State::INVALID};
129 
130     // mMutex guards mFence and mSignalTime.
131     // mSignalTime is also atomic since it is sometimes read outside the lock
132     // for quick checks.
133     mutable std::mutex mMutex;
134     sp<Fence> mFence{Fence::NO_FENCE};
135     std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID};
136 };
137 
138 // A queue of FenceTimes that are expected to signal in FIFO order.
139 // Only maintains a queue of weak pointers so it doesn't keep references
140 // to Fences on its own.
141 //
142 // Can be used to get the signal time of a fence and close its file descriptor
143 // without making a syscall for every fence later in the timeline.
144 // Additionally, since the FenceTime caches the timestamp internally,
145 // other timelines that reference the same FenceTime can avoid the syscall.
146 //
147 // FenceTimeline only keeps track of a limited number of entries to avoid
148 // growing unbounded. Users of FenceTime must make sure they can work even
149 // if FenceTimeline did nothing. i.e. they should eventually call
150 // Fence::getSignalTime(), not only Fence::getCachedSignalTime().
151 //
152 // push() and updateSignalTimes() are safe to call simultaneously from
153 // different threads.
154 class FenceTimeline {
155 public:
156     static constexpr size_t MAX_ENTRIES = 64;
157 
158     void push(const std::shared_ptr<FenceTime>& fence);
159     void updateSignalTimes();
160 
161 private:
162     mutable std::mutex mMutex;
163     std::queue<std::weak_ptr<FenceTime>> mQueue GUARDED_BY(mMutex);
164 };
165 
166 // Used by test code to create or get FenceTimes for a given Fence.
167 //
168 // By design, Fences cannot be signaled from user space. However, this class
169 // allows test code to set the apparent signalTime of a Fence and
170 // have it be visible to all FenceTimes. Release code should not use
171 // FenceToFenceTimeMap.
172 //
173 // FenceToFenceTimeMap keeps a weak reference to the FenceTime and automatically
174 // garbage collects entries every time a new FenceTime is created to avoid
175 // leaks. This prevents us from having to make the Fence destructor
176 // automatically notify that the underlying fence has been destroyed, which
177 // would affect release code paths. Garbage collecting so often is inefficient,
178 // but acceptable for testing.
179 //
180 // Since FenceTimes maintain a strong reference to underlying Fences, there
181 // should not be any aliasing issues where a new Fence happens to have the same
182 // address as a previous Fence; the previous entry will be garbage collected
183 // before the new one is added.
184 class FenceToFenceTimeMap {
185 public:
186     // Create a new FenceTime with that wraps the provided Fence.
187     std::shared_ptr<FenceTime> createFenceTimeForTest(const sp<Fence>& fence);
188 
189     // Signals all FenceTimes created through this class that are wrappers
190     // around |fence|.
191     void signalAllForTest(const sp<Fence>& fence, nsecs_t signalTime);
192 
193 private:
194     // Cleans up the entries that no longer have a strong reference.
195     void garbageCollectLocked();
196 
197     mutable std::mutex mMutex;
198     std::unordered_map<Fence*, std::vector<std::weak_ptr<FenceTime>>> mMap;
199 };
200 
201 
202 }; // namespace android
203 
204 #endif // ANDROID_FENCE_TIME_H
205