• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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