1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2012 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/Fence.h>
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "Fence"
20*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21*38e8c45fSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker // We would eliminate the non-conforming zero-length array, but we can't since
24*38e8c45fSAndroid Build Coastguard Worker // this is effectively included from the Linux kernel
25*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
26*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wzero-length-array"
27*38e8c45fSAndroid Build Coastguard Worker #include <sync/sync.h>
28*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
35*38e8c45fSAndroid Build Coastguard Worker
36*38e8c45fSAndroid Build Coastguard Worker namespace android {
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker const sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence);
39*38e8c45fSAndroid Build Coastguard Worker
Fence(int fenceFd)40*38e8c45fSAndroid Build Coastguard Worker Fence::Fence(int fenceFd) :
41*38e8c45fSAndroid Build Coastguard Worker mFenceFd(fenceFd) {
42*38e8c45fSAndroid Build Coastguard Worker }
43*38e8c45fSAndroid Build Coastguard Worker
Fence(base::unique_fd fenceFd)44*38e8c45fSAndroid Build Coastguard Worker Fence::Fence(base::unique_fd fenceFd) :
45*38e8c45fSAndroid Build Coastguard Worker mFenceFd(std::move(fenceFd)) {
46*38e8c45fSAndroid Build Coastguard Worker }
47*38e8c45fSAndroid Build Coastguard Worker
wait(int timeout)48*38e8c45fSAndroid Build Coastguard Worker status_t Fence::wait(int timeout) {
49*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
50*38e8c45fSAndroid Build Coastguard Worker if (mFenceFd == -1) {
51*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
52*38e8c45fSAndroid Build Coastguard Worker }
53*38e8c45fSAndroid Build Coastguard Worker int err = sync_wait(mFenceFd, timeout);
54*38e8c45fSAndroid Build Coastguard Worker return err < 0 ? -errno : status_t(NO_ERROR);
55*38e8c45fSAndroid Build Coastguard Worker }
56*38e8c45fSAndroid Build Coastguard Worker
waitForever(const char * logname)57*38e8c45fSAndroid Build Coastguard Worker status_t Fence::waitForever(const char* logname) {
58*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
59*38e8c45fSAndroid Build Coastguard Worker if (mFenceFd == -1) {
60*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
61*38e8c45fSAndroid Build Coastguard Worker }
62*38e8c45fSAndroid Build Coastguard Worker int warningTimeout = 3000;
63*38e8c45fSAndroid Build Coastguard Worker int err = sync_wait(mFenceFd, warningTimeout);
64*38e8c45fSAndroid Build Coastguard Worker if (err < 0 && errno == ETIME) {
65*38e8c45fSAndroid Build Coastguard Worker ALOGE("waitForever: %s: fence %d didn't signal in %u ms", logname, mFenceFd.get(),
66*38e8c45fSAndroid Build Coastguard Worker warningTimeout);
67*38e8c45fSAndroid Build Coastguard Worker
68*38e8c45fSAndroid Build Coastguard Worker struct sync_file_info* finfo = sync_file_info(mFenceFd);
69*38e8c45fSAndroid Build Coastguard Worker if (finfo) {
70*38e8c45fSAndroid Build Coastguard Worker // status: active(0) signaled(1) error(<0)
71*38e8c45fSAndroid Build Coastguard Worker ALOGI("waitForever: fence(%s) status(%d)", finfo->name, finfo->status);
72*38e8c45fSAndroid Build Coastguard Worker
73*38e8c45fSAndroid Build Coastguard Worker struct sync_fence_info* pinfo = sync_get_fence_info(finfo);
74*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < finfo->num_fences; i++) {
75*38e8c45fSAndroid Build Coastguard Worker uint64_t ts_sec = pinfo[i].timestamp_ns / 1000000000LL;
76*38e8c45fSAndroid Build Coastguard Worker uint64_t ts_usec = (pinfo[i].timestamp_ns % 1000000000LL) / 1000LL;
77*38e8c45fSAndroid Build Coastguard Worker
78*38e8c45fSAndroid Build Coastguard Worker ALOGI("waitForever: sync point: timeline(%s) drv(%s) status(%d) timestamp(%" PRIu64
79*38e8c45fSAndroid Build Coastguard Worker ".%06" PRIu64 ")",
80*38e8c45fSAndroid Build Coastguard Worker pinfo[i].obj_name, pinfo[i].driver_name, pinfo[i].status, ts_sec, ts_usec);
81*38e8c45fSAndroid Build Coastguard Worker }
82*38e8c45fSAndroid Build Coastguard Worker sync_file_info_free(finfo);
83*38e8c45fSAndroid Build Coastguard Worker }
84*38e8c45fSAndroid Build Coastguard Worker
85*38e8c45fSAndroid Build Coastguard Worker err = sync_wait(mFenceFd, TIMEOUT_NEVER);
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker return err < 0 ? -errno : status_t(NO_ERROR);
88*38e8c45fSAndroid Build Coastguard Worker }
89*38e8c45fSAndroid Build Coastguard Worker
merge(const char * name,const sp<Fence> & f1,const sp<Fence> & f2)90*38e8c45fSAndroid Build Coastguard Worker sp<Fence> Fence::merge(const char* name, const sp<Fence>& f1,
91*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& f2) {
92*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
93*38e8c45fSAndroid Build Coastguard Worker int result;
94*38e8c45fSAndroid Build Coastguard Worker // Merge the two fences. In the case where one of the fences is not a
95*38e8c45fSAndroid Build Coastguard Worker // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
96*38e8c45fSAndroid Build Coastguard Worker // that a new fence with the given name is created.
97*38e8c45fSAndroid Build Coastguard Worker if (f1->isValid() && f2->isValid()) {
98*38e8c45fSAndroid Build Coastguard Worker result = sync_merge(name, f1->mFenceFd, f2->mFenceFd);
99*38e8c45fSAndroid Build Coastguard Worker } else if (f1->isValid()) {
100*38e8c45fSAndroid Build Coastguard Worker result = sync_merge(name, f1->mFenceFd, f1->mFenceFd);
101*38e8c45fSAndroid Build Coastguard Worker } else if (f2->isValid()) {
102*38e8c45fSAndroid Build Coastguard Worker result = sync_merge(name, f2->mFenceFd, f2->mFenceFd);
103*38e8c45fSAndroid Build Coastguard Worker } else {
104*38e8c45fSAndroid Build Coastguard Worker return NO_FENCE;
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker if (result == -1) {
107*38e8c45fSAndroid Build Coastguard Worker status_t err = -errno;
108*38e8c45fSAndroid Build Coastguard Worker ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
109*38e8c45fSAndroid Build Coastguard Worker name, f1->mFenceFd.get(), f2->mFenceFd.get(),
110*38e8c45fSAndroid Build Coastguard Worker strerror(-err), err);
111*38e8c45fSAndroid Build Coastguard Worker return NO_FENCE;
112*38e8c45fSAndroid Build Coastguard Worker }
113*38e8c45fSAndroid Build Coastguard Worker return sp<Fence>(new Fence(result));
114*38e8c45fSAndroid Build Coastguard Worker }
115*38e8c45fSAndroid Build Coastguard Worker
merge(const String8 & name,const sp<Fence> & f1,const sp<Fence> & f2)116*38e8c45fSAndroid Build Coastguard Worker sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
117*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& f2) {
118*38e8c45fSAndroid Build Coastguard Worker return merge(name.c_str(), f1, f2);
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker
dup() const121*38e8c45fSAndroid Build Coastguard Worker int Fence::dup() const {
122*38e8c45fSAndroid Build Coastguard Worker return ::dup(mFenceFd);
123*38e8c45fSAndroid Build Coastguard Worker }
124*38e8c45fSAndroid Build Coastguard Worker
getSignalTime() const125*38e8c45fSAndroid Build Coastguard Worker nsecs_t Fence::getSignalTime() const {
126*38e8c45fSAndroid Build Coastguard Worker if (mFenceFd == -1) {
127*38e8c45fSAndroid Build Coastguard Worker return SIGNAL_TIME_INVALID;
128*38e8c45fSAndroid Build Coastguard Worker }
129*38e8c45fSAndroid Build Coastguard Worker
130*38e8c45fSAndroid Build Coastguard Worker struct sync_file_info* finfo = sync_file_info(mFenceFd);
131*38e8c45fSAndroid Build Coastguard Worker if (finfo == nullptr) {
132*38e8c45fSAndroid Build Coastguard Worker ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get());
133*38e8c45fSAndroid Build Coastguard Worker return SIGNAL_TIME_INVALID;
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker
136*38e8c45fSAndroid Build Coastguard Worker if (finfo->status != 1) {
137*38e8c45fSAndroid Build Coastguard Worker const auto status = finfo->status;
138*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(status < 0, "%s: sync_file_info contains an error: <%d> for fd: <%d>", __func__,
139*38e8c45fSAndroid Build Coastguard Worker status, mFenceFd.get());
140*38e8c45fSAndroid Build Coastguard Worker sync_file_info_free(finfo);
141*38e8c45fSAndroid Build Coastguard Worker return status < 0 ? SIGNAL_TIME_INVALID : SIGNAL_TIME_PENDING;
142*38e8c45fSAndroid Build Coastguard Worker }
143*38e8c45fSAndroid Build Coastguard Worker
144*38e8c45fSAndroid Build Coastguard Worker uint64_t timestamp = 0;
145*38e8c45fSAndroid Build Coastguard Worker struct sync_fence_info* pinfo = sync_get_fence_info(finfo);
146*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < finfo->num_fences; i++) {
147*38e8c45fSAndroid Build Coastguard Worker if (pinfo[i].timestamp_ns > timestamp) {
148*38e8c45fSAndroid Build Coastguard Worker timestamp = pinfo[i].timestamp_ns;
149*38e8c45fSAndroid Build Coastguard Worker }
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker sync_file_info_free(finfo);
153*38e8c45fSAndroid Build Coastguard Worker return nsecs_t(timestamp);
154*38e8c45fSAndroid Build Coastguard Worker }
155*38e8c45fSAndroid Build Coastguard Worker
getFlattenedSize() const156*38e8c45fSAndroid Build Coastguard Worker size_t Fence::getFlattenedSize() const {
157*38e8c45fSAndroid Build Coastguard Worker return 4;
158*38e8c45fSAndroid Build Coastguard Worker }
159*38e8c45fSAndroid Build Coastguard Worker
getFdCount() const160*38e8c45fSAndroid Build Coastguard Worker size_t Fence::getFdCount() const {
161*38e8c45fSAndroid Build Coastguard Worker return isValid() ? 1 : 0;
162*38e8c45fSAndroid Build Coastguard Worker }
163*38e8c45fSAndroid Build Coastguard Worker
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const164*38e8c45fSAndroid Build Coastguard Worker status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
165*38e8c45fSAndroid Build Coastguard Worker if (size < getFlattenedSize() || count < getFdCount()) {
166*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
167*38e8c45fSAndroid Build Coastguard Worker }
168*38e8c45fSAndroid Build Coastguard Worker // Cast to uint32_t since the size of a size_t can vary between 32- and
169*38e8c45fSAndroid Build Coastguard Worker // 64-bit processes
170*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::write(buffer, size, static_cast<uint32_t>(getFdCount()));
171*38e8c45fSAndroid Build Coastguard Worker if (isValid()) {
172*38e8c45fSAndroid Build Coastguard Worker *fds++ = mFenceFd;
173*38e8c45fSAndroid Build Coastguard Worker count--;
174*38e8c45fSAndroid Build Coastguard Worker }
175*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
176*38e8c45fSAndroid Build Coastguard Worker }
177*38e8c45fSAndroid Build Coastguard Worker
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)178*38e8c45fSAndroid Build Coastguard Worker status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) {
179*38e8c45fSAndroid Build Coastguard Worker if (mFenceFd != -1) {
180*38e8c45fSAndroid Build Coastguard Worker // Don't unflatten if we already have a valid fd.
181*38e8c45fSAndroid Build Coastguard Worker return INVALID_OPERATION;
182*38e8c45fSAndroid Build Coastguard Worker }
183*38e8c45fSAndroid Build Coastguard Worker
184*38e8c45fSAndroid Build Coastguard Worker if (size < getFlattenedSize()) {
185*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker
188*38e8c45fSAndroid Build Coastguard Worker uint32_t numFds;
189*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::read(buffer, size, numFds);
190*38e8c45fSAndroid Build Coastguard Worker
191*38e8c45fSAndroid Build Coastguard Worker if (numFds > 1) {
192*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
193*38e8c45fSAndroid Build Coastguard Worker }
194*38e8c45fSAndroid Build Coastguard Worker
195*38e8c45fSAndroid Build Coastguard Worker if (count < numFds) {
196*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker
199*38e8c45fSAndroid Build Coastguard Worker if (numFds) {
200*38e8c45fSAndroid Build Coastguard Worker mFenceFd.reset(*fds++);
201*38e8c45fSAndroid Build Coastguard Worker count--;
202*38e8c45fSAndroid Build Coastguard Worker }
203*38e8c45fSAndroid Build Coastguard Worker
204*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
205*38e8c45fSAndroid Build Coastguard Worker }
206*38e8c45fSAndroid Build Coastguard Worker
207*38e8c45fSAndroid Build Coastguard Worker } // namespace android
208