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