blob: 27cc7200289421c068c9f91c51c733d57bde4597 [file] [log] [blame]
Brian Anderson221de2a2016-09-21 16:53:28 -07001/*
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
28namespace android {
29
30// A wrapper around fence that only implements isValid and getSignalTime.
31// It automatically closes the fence in a thread-safe manner once the signal
32// time is known.
33class FenceTime {
34public:
35 // An atomic snapshot of the FenceTime that is flattenable.
36 //
37 // This class is needed because the FenceTime class may not stay
38 // consistent for all steps of the flattening process.
39 //
40 // Not thread safe.
41 struct Snapshot : public Flattenable<Snapshot> {
42 enum class State {
43 EMPTY,
44 FENCE,
45 SIGNAL_TIME,
46 };
47
48 Snapshot() = default; // Creates an empty snapshot.
49 explicit Snapshot(const sp<Fence>& fence);
50 explicit Snapshot(nsecs_t signalTime);
51
52 // Movable.
53 Snapshot(Snapshot&& src) = default;
54 Snapshot& operator=(Snapshot&& src) = default;
55 // Not copyable.
56 Snapshot(const Snapshot& src) = delete;
57 Snapshot& operator=(const Snapshot&& src) = delete;
58
59 // Flattenable implementation.
60 size_t getFlattenedSize() const;
61 size_t getFdCount() const;
62 status_t flatten(void*& buffer, size_t& size, int*& fds,
63 size_t& count) const;
64 status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
65 size_t& count);
66
67 State state{State::EMPTY};
68 sp<Fence> fence{Fence::NO_FENCE};
69 nsecs_t signalTime{Fence::SIGNAL_TIME_INVALID};
70 };
71
72 static const std::shared_ptr<FenceTime> NO_FENCE;
73
74 explicit FenceTime(const sp<Fence>& fence);
75 explicit FenceTime(sp<Fence>&& fence);
76
77 // Passing in Fence::SIGNAL_TIME_PENDING is not allowed.
78 // Doing so will convert the signalTime to Fence::SIGNAL_TIME_INVALID.
79 explicit FenceTime(nsecs_t signalTime);
80
81 // Do not allow default construction. Share NO_FENCE or explicitly construct
82 // with Fence::SIGNAL_TIME_INVALID instead.
83 FenceTime() = delete;
84
85 // Do not allow copy, assign, or move. Use a shared_ptr to share the
86 // signalTime result. Or use getSnapshot() if a thread-safe copy is really
87 // needed.
88 FenceTime(const FenceTime&) = delete;
89 FenceTime(FenceTime&&) = delete;
90 FenceTime& operator=(const FenceTime&) = delete;
91 FenceTime& operator=(FenceTime&&) = delete;
92
93 // This method should only be called when replacing the fence with
94 // a signalTime. Since this is an indirect way of setting the signal time
95 // of a fence, the snapshot should come from a trusted source.
96 void applyTrustedSnapshot(const Snapshot& src);
97
98 bool isValid() const;
99
100 // Attempts to get the timestamp from the Fence if the timestamp isn't
101 // already cached. Otherwise, it returns the cached value.
102 nsecs_t getSignalTime();
103
104 // Gets the cached timestamp without attempting to query the Fence.
105 nsecs_t getCachedSignalTime() const;
106
107 // Returns a snapshot of the FenceTime in its current state.
108 Snapshot getSnapshot() const;
109
110 // Override new and delete since this needs 8-byte alignment, which
111 // is not guaranteed on x86.
112 static void* operator new(size_t nbytes) noexcept;
113 static void operator delete(void *p);
114
115private:
116 enum class State {
117 VALID,
118 INVALID,
119 };
120
121 const State mState{State::INVALID};
122
123 // mMutex guards mFence and mSignalTime.
124 // mSignalTime is also atomic since it is sometimes read outside the lock
125 // for quick checks.
126 mutable std::mutex mMutex;
127 sp<Fence> mFence{Fence::NO_FENCE};
128 std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID};
129};
130
131// A queue of FenceTimes that are expected to signal in FIFO order.
132// Only maintains a queue of weak pointers so it doesn't keep references
133// to Fences on its own.
134//
135// Can be used to get the signal time of a fence and close its file descriptor
136// without making a syscall for every fence later in the timeline.
137// Additionally, since the FenceTime caches the timestamp internally,
138// other timelines that reference the same FenceTime can avoid the syscall.
139//
140// FenceTimeline only keeps track of a limited number of entries to avoid
141// growing unbounded. Users of FenceTime must make sure they can work even
142// if FenceTimeline did nothing. i.e. they should eventually call
143// Fence::getSignalTime(), not only Fence::getCachedSignalTime().
144//
145// push() and updateSignalTimes() are safe to call simultaneously from
146// different threads.
147class FenceTimeline {
148public:
149 static constexpr size_t MAX_ENTRIES = 64;
150
151 void push(const std::shared_ptr<FenceTime>& fence);
152 void updateSignalTimes();
153
154private:
155 mutable std::mutex mMutex;
156 std::queue<std::weak_ptr<FenceTime>> mQueue;
157};
158
159}; // namespace android
160
161#endif // ANDROID_FENCE_TIME_H