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