1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2016 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include <ui/FenceTime.h>
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "FenceTime"
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include <cutils/compiler.h> // For CC_[UN]LIKELY
22*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker #include <memory>
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker namespace android {
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
31*38e8c45fSAndroid Build Coastguard Worker // FenceTime
32*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker const auto FenceTime::NO_FENCE = std::make_shared<FenceTime>(Fence::NO_FENCE);
35*38e8c45fSAndroid Build Coastguard Worker
FenceTime(const sp<Fence> & fence)36*38e8c45fSAndroid Build Coastguard Worker FenceTime::FenceTime(const sp<Fence>& fence)
37*38e8c45fSAndroid Build Coastguard Worker : mState(((fence.get() != nullptr) && fence->isValid()) ?
38*38e8c45fSAndroid Build Coastguard Worker State::VALID : State::INVALID),
39*38e8c45fSAndroid Build Coastguard Worker mFence(fence),
40*38e8c45fSAndroid Build Coastguard Worker mSignalTime(mState == State::INVALID ?
41*38e8c45fSAndroid Build Coastguard Worker Fence::SIGNAL_TIME_INVALID : Fence::SIGNAL_TIME_PENDING) {
42*38e8c45fSAndroid Build Coastguard Worker }
43*38e8c45fSAndroid Build Coastguard Worker
FenceTime(sp<Fence> && fence)44*38e8c45fSAndroid Build Coastguard Worker FenceTime::FenceTime(sp<Fence>&& fence)
45*38e8c45fSAndroid Build Coastguard Worker : mState(((fence.get() != nullptr) && fence->isValid()) ?
46*38e8c45fSAndroid Build Coastguard Worker State::VALID : State::INVALID),
47*38e8c45fSAndroid Build Coastguard Worker mFence(std::move(fence)),
48*38e8c45fSAndroid Build Coastguard Worker mSignalTime(mState == State::INVALID ?
49*38e8c45fSAndroid Build Coastguard Worker Fence::SIGNAL_TIME_INVALID : Fence::SIGNAL_TIME_PENDING) {
50*38e8c45fSAndroid Build Coastguard Worker }
51*38e8c45fSAndroid Build Coastguard Worker
FenceTime(nsecs_t signalTime)52*38e8c45fSAndroid Build Coastguard Worker FenceTime::FenceTime(nsecs_t signalTime)
53*38e8c45fSAndroid Build Coastguard Worker : mState(Fence::isValidTimestamp(signalTime) ? State::VALID : State::INVALID),
54*38e8c45fSAndroid Build Coastguard Worker mFence(nullptr),
55*38e8c45fSAndroid Build Coastguard Worker mSignalTime(signalTime) {
56*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(mSignalTime == Fence::SIGNAL_TIME_PENDING)) {
57*38e8c45fSAndroid Build Coastguard Worker ALOGE("Pending signal time not allowed after signal.");
58*38e8c45fSAndroid Build Coastguard Worker mSignalTime = Fence::SIGNAL_TIME_INVALID;
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker }
61*38e8c45fSAndroid Build Coastguard Worker
applyTrustedSnapshot(const Snapshot & src)62*38e8c45fSAndroid Build Coastguard Worker void FenceTime::applyTrustedSnapshot(const Snapshot& src) {
63*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(src.state != Snapshot::State::SIGNAL_TIME)) {
64*38e8c45fSAndroid Build Coastguard Worker // Applying Snapshot::State::FENCE, could change the valid state of the
65*38e8c45fSAndroid Build Coastguard Worker // FenceTime, which is not allowed. Callers should create a new
66*38e8c45fSAndroid Build Coastguard Worker // FenceTime from the snapshot instead.
67*38e8c45fSAndroid Build Coastguard Worker ALOGE("applyTrustedSnapshot: Unexpected fence.");
68*38e8c45fSAndroid Build Coastguard Worker return;
69*38e8c45fSAndroid Build Coastguard Worker }
70*38e8c45fSAndroid Build Coastguard Worker
71*38e8c45fSAndroid Build Coastguard Worker if (src.state == Snapshot::State::EMPTY) {
72*38e8c45fSAndroid Build Coastguard Worker return;
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker
75*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed);
76*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
77*38e8c45fSAndroid Build Coastguard Worker // We should always get the same signalTime here that we did in
78*38e8c45fSAndroid Build Coastguard Worker // getSignalTime(). This check races with getSignalTime(), but it is
79*38e8c45fSAndroid Build Coastguard Worker // only a sanity check so that's okay.
80*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(signalTime != src.signalTime)) {
81*38e8c45fSAndroid Build Coastguard Worker ALOGE("FenceTime::applyTrustedSnapshot: signalTime mismatch. "
82*38e8c45fSAndroid Build Coastguard Worker "(%" PRId64 " (old) != %" PRId64 " (new))",
83*38e8c45fSAndroid Build Coastguard Worker signalTime, src.signalTime);
84*38e8c45fSAndroid Build Coastguard Worker }
85*38e8c45fSAndroid Build Coastguard Worker return;
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
88*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
89*38e8c45fSAndroid Build Coastguard Worker mFence.clear();
90*38e8c45fSAndroid Build Coastguard Worker mSignalTime.store(src.signalTime, std::memory_order_relaxed);
91*38e8c45fSAndroid Build Coastguard Worker }
92*38e8c45fSAndroid Build Coastguard Worker
isValid() const93*38e8c45fSAndroid Build Coastguard Worker bool FenceTime::isValid() const {
94*38e8c45fSAndroid Build Coastguard Worker // We store the valid state in the constructors and return it here.
95*38e8c45fSAndroid Build Coastguard Worker // This lets release code remember the valid state even after the
96*38e8c45fSAndroid Build Coastguard Worker // underlying fence is destroyed.
97*38e8c45fSAndroid Build Coastguard Worker return mState != State::INVALID;
98*38e8c45fSAndroid Build Coastguard Worker }
99*38e8c45fSAndroid Build Coastguard Worker
wait(int timeout)100*38e8c45fSAndroid Build Coastguard Worker status_t FenceTime::wait(int timeout) {
101*38e8c45fSAndroid Build Coastguard Worker // See if we already have a cached value we can return.
102*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed);
103*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
104*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker
107*38e8c45fSAndroid Build Coastguard Worker // Hold a reference to the fence on the stack in case the class'
108*38e8c45fSAndroid Build Coastguard Worker // reference is removed by another thread. This prevents the
109*38e8c45fSAndroid Build Coastguard Worker // fence from being destroyed until the end of this method, where
110*38e8c45fSAndroid Build Coastguard Worker // we conveniently do not have the lock held.
111*38e8c45fSAndroid Build Coastguard Worker sp<Fence> fence;
112*38e8c45fSAndroid Build Coastguard Worker {
113*38e8c45fSAndroid Build Coastguard Worker // With the lock acquired this time, see if we have the cached
114*38e8c45fSAndroid Build Coastguard Worker // value or if we need to poll the fence.
115*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
116*38e8c45fSAndroid Build Coastguard Worker if (!mFence.get()) {
117*38e8c45fSAndroid Build Coastguard Worker // Another thread set the signal time just before we added the
118*38e8c45fSAndroid Build Coastguard Worker // reference to mFence.
119*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
120*38e8c45fSAndroid Build Coastguard Worker }
121*38e8c45fSAndroid Build Coastguard Worker fence = mFence;
122*38e8c45fSAndroid Build Coastguard Worker }
123*38e8c45fSAndroid Build Coastguard Worker
124*38e8c45fSAndroid Build Coastguard Worker // Make the system call without the lock held.
125*38e8c45fSAndroid Build Coastguard Worker return fence->wait(timeout);
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker
getSignalTime()128*38e8c45fSAndroid Build Coastguard Worker nsecs_t FenceTime::getSignalTime() {
129*38e8c45fSAndroid Build Coastguard Worker // See if we already have a cached value we can return.
130*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed);
131*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
132*38e8c45fSAndroid Build Coastguard Worker return signalTime;
133*38e8c45fSAndroid Build Coastguard Worker }
134*38e8c45fSAndroid Build Coastguard Worker
135*38e8c45fSAndroid Build Coastguard Worker // Hold a reference to the fence on the stack in case the class'
136*38e8c45fSAndroid Build Coastguard Worker // reference is removed by another thread. This prevents the
137*38e8c45fSAndroid Build Coastguard Worker // fence from being destroyed until the end of this method, where
138*38e8c45fSAndroid Build Coastguard Worker // we conveniently do not have the lock held.
139*38e8c45fSAndroid Build Coastguard Worker sp<Fence> fence;
140*38e8c45fSAndroid Build Coastguard Worker {
141*38e8c45fSAndroid Build Coastguard Worker // With the lock acquired this time, see if we have the cached
142*38e8c45fSAndroid Build Coastguard Worker // value or if we need to poll the fence.
143*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
144*38e8c45fSAndroid Build Coastguard Worker if (!mFence.get()) {
145*38e8c45fSAndroid Build Coastguard Worker // Another thread set the signal time just before we added the
146*38e8c45fSAndroid Build Coastguard Worker // reference to mFence.
147*38e8c45fSAndroid Build Coastguard Worker return mSignalTime.load(std::memory_order_relaxed);
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker fence = mFence;
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker // Make the system call without the lock held.
153*38e8c45fSAndroid Build Coastguard Worker signalTime = fence->getSignalTime();
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker // Allow tests to override SIGNAL_TIME_INVALID behavior, since tests
156*38e8c45fSAndroid Build Coastguard Worker // use invalid underlying Fences without real file descriptors.
157*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(mState == State::FORCED_VALID_FOR_TEST)) {
158*38e8c45fSAndroid Build Coastguard Worker if (signalTime == Fence::SIGNAL_TIME_INVALID) {
159*38e8c45fSAndroid Build Coastguard Worker signalTime = Fence::SIGNAL_TIME_PENDING;
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker }
162*38e8c45fSAndroid Build Coastguard Worker
163*38e8c45fSAndroid Build Coastguard Worker // Make the signal time visible to everyone if it is no longer pending
164*38e8c45fSAndroid Build Coastguard Worker // and remove the class' reference to the fence.
165*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
166*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
167*38e8c45fSAndroid Build Coastguard Worker mFence.clear();
168*38e8c45fSAndroid Build Coastguard Worker mSignalTime.store(signalTime, std::memory_order_relaxed);
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker
171*38e8c45fSAndroid Build Coastguard Worker return signalTime;
172*38e8c45fSAndroid Build Coastguard Worker }
173*38e8c45fSAndroid Build Coastguard Worker
getCachedSignalTime() const174*38e8c45fSAndroid Build Coastguard Worker nsecs_t FenceTime::getCachedSignalTime() const {
175*38e8c45fSAndroid Build Coastguard Worker // memory_order_acquire since we don't have a lock fallback path
176*38e8c45fSAndroid Build Coastguard Worker // that will do an acquire.
177*38e8c45fSAndroid Build Coastguard Worker return mSignalTime.load(std::memory_order_acquire);
178*38e8c45fSAndroid Build Coastguard Worker }
179*38e8c45fSAndroid Build Coastguard Worker
getSnapshot() const180*38e8c45fSAndroid Build Coastguard Worker FenceTime::Snapshot FenceTime::getSnapshot() const {
181*38e8c45fSAndroid Build Coastguard Worker // Quick check without the lock.
182*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed);
183*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
184*38e8c45fSAndroid Build Coastguard Worker return Snapshot(signalTime);
185*38e8c45fSAndroid Build Coastguard Worker }
186*38e8c45fSAndroid Build Coastguard Worker
187*38e8c45fSAndroid Build Coastguard Worker // Do the full check with the lock.
188*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
189*38e8c45fSAndroid Build Coastguard Worker signalTime = mSignalTime.load(std::memory_order_relaxed);
190*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
191*38e8c45fSAndroid Build Coastguard Worker return Snapshot(signalTime);
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker return Snapshot(mFence);
194*38e8c45fSAndroid Build Coastguard Worker }
195*38e8c45fSAndroid Build Coastguard Worker
196*38e8c45fSAndroid Build Coastguard Worker // For tests only. If forceValidForTest is true, then getSignalTime will
197*38e8c45fSAndroid Build Coastguard Worker // never return SIGNAL_TIME_INVALID and isValid will always return true.
FenceTime(const sp<Fence> & fence,bool forceValidForTest)198*38e8c45fSAndroid Build Coastguard Worker FenceTime::FenceTime(const sp<Fence>& fence, bool forceValidForTest)
199*38e8c45fSAndroid Build Coastguard Worker : mState(forceValidForTest ?
200*38e8c45fSAndroid Build Coastguard Worker State::FORCED_VALID_FOR_TEST : State::INVALID),
201*38e8c45fSAndroid Build Coastguard Worker mFence(fence),
202*38e8c45fSAndroid Build Coastguard Worker mSignalTime(mState == State::INVALID ?
203*38e8c45fSAndroid Build Coastguard Worker Fence::SIGNAL_TIME_INVALID : Fence::SIGNAL_TIME_PENDING) {
204*38e8c45fSAndroid Build Coastguard Worker }
205*38e8c45fSAndroid Build Coastguard Worker
signalForTest(nsecs_t signalTime)206*38e8c45fSAndroid Build Coastguard Worker void FenceTime::signalForTest(nsecs_t signalTime) {
207*38e8c45fSAndroid Build Coastguard Worker // To be realistic, this should really set a hidden value that
208*38e8c45fSAndroid Build Coastguard Worker // gets picked up in the next call to getSignalTime, but this should
209*38e8c45fSAndroid Build Coastguard Worker // be good enough.
210*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
211*38e8c45fSAndroid Build Coastguard Worker mFence.clear();
212*38e8c45fSAndroid Build Coastguard Worker mSignalTime.store(signalTime, std::memory_order_relaxed);
213*38e8c45fSAndroid Build Coastguard Worker }
214*38e8c45fSAndroid Build Coastguard Worker
215*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
216*38e8c45fSAndroid Build Coastguard Worker // FenceTime::Snapshot
217*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
Snapshot(const sp<Fence> & srcFence)218*38e8c45fSAndroid Build Coastguard Worker FenceTime::Snapshot::Snapshot(const sp<Fence>& srcFence)
219*38e8c45fSAndroid Build Coastguard Worker : state(State::FENCE), fence(srcFence) {
220*38e8c45fSAndroid Build Coastguard Worker }
221*38e8c45fSAndroid Build Coastguard Worker
Snapshot(nsecs_t srcSignalTime)222*38e8c45fSAndroid Build Coastguard Worker FenceTime::Snapshot::Snapshot(nsecs_t srcSignalTime)
223*38e8c45fSAndroid Build Coastguard Worker : state(State::SIGNAL_TIME), signalTime(srcSignalTime) {
224*38e8c45fSAndroid Build Coastguard Worker }
225*38e8c45fSAndroid Build Coastguard Worker
getFlattenedSize() const226*38e8c45fSAndroid Build Coastguard Worker size_t FenceTime::Snapshot::getFlattenedSize() const {
227*38e8c45fSAndroid Build Coastguard Worker constexpr size_t min = sizeof(state);
228*38e8c45fSAndroid Build Coastguard Worker switch (state) {
229*38e8c45fSAndroid Build Coastguard Worker case State::EMPTY:
230*38e8c45fSAndroid Build Coastguard Worker return min;
231*38e8c45fSAndroid Build Coastguard Worker case State::FENCE:
232*38e8c45fSAndroid Build Coastguard Worker return min + fence->getFlattenedSize();
233*38e8c45fSAndroid Build Coastguard Worker case State::SIGNAL_TIME:
234*38e8c45fSAndroid Build Coastguard Worker return min + sizeof(signalTime);
235*38e8c45fSAndroid Build Coastguard Worker }
236*38e8c45fSAndroid Build Coastguard Worker return 0;
237*38e8c45fSAndroid Build Coastguard Worker }
238*38e8c45fSAndroid Build Coastguard Worker
getFdCount() const239*38e8c45fSAndroid Build Coastguard Worker size_t FenceTime::Snapshot::getFdCount() const {
240*38e8c45fSAndroid Build Coastguard Worker return state == State::FENCE ? fence->getFdCount() : 0u;
241*38e8c45fSAndroid Build Coastguard Worker }
242*38e8c45fSAndroid Build Coastguard Worker
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const243*38e8c45fSAndroid Build Coastguard Worker status_t FenceTime::Snapshot::flatten(
244*38e8c45fSAndroid Build Coastguard Worker void*& buffer, size_t& size, int*& fds, size_t& count) const {
245*38e8c45fSAndroid Build Coastguard Worker if (size < getFlattenedSize()) {
246*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
247*38e8c45fSAndroid Build Coastguard Worker }
248*38e8c45fSAndroid Build Coastguard Worker
249*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::write(buffer, size, state);
250*38e8c45fSAndroid Build Coastguard Worker switch (state) {
251*38e8c45fSAndroid Build Coastguard Worker case State::EMPTY:
252*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
253*38e8c45fSAndroid Build Coastguard Worker case State::FENCE:
254*38e8c45fSAndroid Build Coastguard Worker return fence->flatten(buffer, size, fds, count);
255*38e8c45fSAndroid Build Coastguard Worker case State::SIGNAL_TIME:
256*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::write(buffer, size, signalTime);
257*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
258*38e8c45fSAndroid Build Coastguard Worker }
259*38e8c45fSAndroid Build Coastguard Worker
260*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
261*38e8c45fSAndroid Build Coastguard Worker }
262*38e8c45fSAndroid Build Coastguard Worker
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)263*38e8c45fSAndroid Build Coastguard Worker status_t FenceTime::Snapshot::unflatten(
264*38e8c45fSAndroid Build Coastguard Worker void const*& buffer, size_t& size, int const*& fds, size_t& count) {
265*38e8c45fSAndroid Build Coastguard Worker if (size < sizeof(state)) {
266*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
267*38e8c45fSAndroid Build Coastguard Worker }
268*38e8c45fSAndroid Build Coastguard Worker
269*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::read(buffer, size, state);
270*38e8c45fSAndroid Build Coastguard Worker switch (state) {
271*38e8c45fSAndroid Build Coastguard Worker case State::EMPTY:
272*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
273*38e8c45fSAndroid Build Coastguard Worker case State::FENCE:
274*38e8c45fSAndroid Build Coastguard Worker fence = new Fence;
275*38e8c45fSAndroid Build Coastguard Worker return fence->unflatten(buffer, size, fds, count);
276*38e8c45fSAndroid Build Coastguard Worker case State::SIGNAL_TIME:
277*38e8c45fSAndroid Build Coastguard Worker if (size < sizeof(signalTime)) {
278*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
279*38e8c45fSAndroid Build Coastguard Worker }
280*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::read(buffer, size, signalTime);
281*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
282*38e8c45fSAndroid Build Coastguard Worker }
283*38e8c45fSAndroid Build Coastguard Worker
284*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
285*38e8c45fSAndroid Build Coastguard Worker }
286*38e8c45fSAndroid Build Coastguard Worker
287*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
288*38e8c45fSAndroid Build Coastguard Worker // FenceTimeline
289*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
push(const std::shared_ptr<FenceTime> & fence)290*38e8c45fSAndroid Build Coastguard Worker void FenceTimeline::push(const std::shared_ptr<FenceTime>& fence) {
291*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
292*38e8c45fSAndroid Build Coastguard Worker while (mQueue.size() >= MAX_ENTRIES) {
293*38e8c45fSAndroid Build Coastguard Worker // This is a sanity check to make sure the queue doesn't grow unbounded.
294*38e8c45fSAndroid Build Coastguard Worker // MAX_ENTRIES should be big enough not to trigger this path.
295*38e8c45fSAndroid Build Coastguard Worker // In case this path is taken though, users of FenceTime must make sure
296*38e8c45fSAndroid Build Coastguard Worker // not to rely solely on FenceTimeline to get the final timestamp and
297*38e8c45fSAndroid Build Coastguard Worker // should eventually call Fence::getSignalTime on their own.
298*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> front = mQueue.front().lock();
299*38e8c45fSAndroid Build Coastguard Worker if (front) {
300*38e8c45fSAndroid Build Coastguard Worker // Make a last ditch effort to get the signalTime here since
301*38e8c45fSAndroid Build Coastguard Worker // we are removing it from the timeline.
302*38e8c45fSAndroid Build Coastguard Worker front->getSignalTime();
303*38e8c45fSAndroid Build Coastguard Worker }
304*38e8c45fSAndroid Build Coastguard Worker mQueue.pop();
305*38e8c45fSAndroid Build Coastguard Worker }
306*38e8c45fSAndroid Build Coastguard Worker mQueue.push(fence);
307*38e8c45fSAndroid Build Coastguard Worker }
308*38e8c45fSAndroid Build Coastguard Worker
updateSignalTimes()309*38e8c45fSAndroid Build Coastguard Worker void FenceTimeline::updateSignalTimes() {
310*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
311*38e8c45fSAndroid Build Coastguard Worker while (!mQueue.empty()) {
312*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> fence = mQueue.front().lock();
313*38e8c45fSAndroid Build Coastguard Worker if (!fence) {
314*38e8c45fSAndroid Build Coastguard Worker // The shared_ptr no longer exists and no one cares about the
315*38e8c45fSAndroid Build Coastguard Worker // timestamp anymore.
316*38e8c45fSAndroid Build Coastguard Worker mQueue.pop();
317*38e8c45fSAndroid Build Coastguard Worker continue;
318*38e8c45fSAndroid Build Coastguard Worker } else if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
319*38e8c45fSAndroid Build Coastguard Worker // The fence has signaled and we've removed the sp<Fence> ref.
320*38e8c45fSAndroid Build Coastguard Worker mQueue.pop();
321*38e8c45fSAndroid Build Coastguard Worker continue;
322*38e8c45fSAndroid Build Coastguard Worker } else {
323*38e8c45fSAndroid Build Coastguard Worker // The fence didn't signal yet. Break since the later ones
324*38e8c45fSAndroid Build Coastguard Worker // shouldn't have signaled either.
325*38e8c45fSAndroid Build Coastguard Worker break;
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker }
328*38e8c45fSAndroid Build Coastguard Worker }
329*38e8c45fSAndroid Build Coastguard Worker
330*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
331*38e8c45fSAndroid Build Coastguard Worker // FenceToFenceTimeMap
332*38e8c45fSAndroid Build Coastguard Worker // ============================================================================
createFenceTimeForTest(const sp<Fence> & fence)333*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> FenceToFenceTimeMap::createFenceTimeForTest(
334*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& fence) {
335*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
336*38e8c45fSAndroid Build Coastguard Worker // Always garbage collecting isn't efficient, but this is only for testing.
337*38e8c45fSAndroid Build Coastguard Worker garbageCollectLocked();
338*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> fenceTime(new FenceTime(fence, true));
339*38e8c45fSAndroid Build Coastguard Worker mMap[fence.get()].push_back(fenceTime);
340*38e8c45fSAndroid Build Coastguard Worker return fenceTime;
341*38e8c45fSAndroid Build Coastguard Worker }
342*38e8c45fSAndroid Build Coastguard Worker
signalAllForTest(const sp<Fence> & fence,nsecs_t signalTime)343*38e8c45fSAndroid Build Coastguard Worker void FenceToFenceTimeMap::signalAllForTest(
344*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& fence, nsecs_t signalTime) {
345*38e8c45fSAndroid Build Coastguard Worker bool signaled = false;
346*38e8c45fSAndroid Build Coastguard Worker
347*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
348*38e8c45fSAndroid Build Coastguard Worker auto it = mMap.find(fence.get());
349*38e8c45fSAndroid Build Coastguard Worker if (it != mMap.end()) {
350*38e8c45fSAndroid Build Coastguard Worker for (auto& weakFenceTime : it->second) {
351*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> fenceTime = weakFenceTime.lock();
352*38e8c45fSAndroid Build Coastguard Worker if (!fenceTime) {
353*38e8c45fSAndroid Build Coastguard Worker continue;
354*38e8c45fSAndroid Build Coastguard Worker }
355*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!fenceTime->isValid(),
356*38e8c45fSAndroid Build Coastguard Worker "signalAllForTest: Signaling invalid fence.");
357*38e8c45fSAndroid Build Coastguard Worker fenceTime->signalForTest(signalTime);
358*38e8c45fSAndroid Build Coastguard Worker signaled = true;
359*38e8c45fSAndroid Build Coastguard Worker }
360*38e8c45fSAndroid Build Coastguard Worker }
361*38e8c45fSAndroid Build Coastguard Worker
362*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!signaled, "signalAllForTest: Nothing to signal.");
363*38e8c45fSAndroid Build Coastguard Worker }
364*38e8c45fSAndroid Build Coastguard Worker
garbageCollectLocked()365*38e8c45fSAndroid Build Coastguard Worker void FenceToFenceTimeMap::garbageCollectLocked() {
366*38e8c45fSAndroid Build Coastguard Worker for (auto it = mMap.begin(); it != mMap.end();) {
367*38e8c45fSAndroid Build Coastguard Worker // Erase all expired weak pointers from the vector.
368*38e8c45fSAndroid Build Coastguard Worker auto& vect = it->second;
369*38e8c45fSAndroid Build Coastguard Worker vect.erase(
370*38e8c45fSAndroid Build Coastguard Worker std::remove_if(vect.begin(), vect.end(),
371*38e8c45fSAndroid Build Coastguard Worker [](const std::weak_ptr<FenceTime>& ft) {
372*38e8c45fSAndroid Build Coastguard Worker return ft.expired();
373*38e8c45fSAndroid Build Coastguard Worker }),
374*38e8c45fSAndroid Build Coastguard Worker vect.end());
375*38e8c45fSAndroid Build Coastguard Worker
376*38e8c45fSAndroid Build Coastguard Worker // Also erase the map entry if the vector is now empty.
377*38e8c45fSAndroid Build Coastguard Worker if (vect.empty()) {
378*38e8c45fSAndroid Build Coastguard Worker it = mMap.erase(it);
379*38e8c45fSAndroid Build Coastguard Worker } else {
380*38e8c45fSAndroid Build Coastguard Worker it++;
381*38e8c45fSAndroid Build Coastguard Worker }
382*38e8c45fSAndroid Build Coastguard Worker }
383*38e8c45fSAndroid Build Coastguard Worker }
384*38e8c45fSAndroid Build Coastguard Worker
385*38e8c45fSAndroid Build Coastguard Worker } // namespace android
386