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 33namespace android { 34 35const sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence); 36 37Fence::Fence() : 38 mFenceFd(-1) { 39} 40 41Fence::Fence(int fenceFd) : 42 mFenceFd(fenceFd) { 43} 44 45Fence::~Fence() { 46 if (mFenceFd != -1) { 47 close(mFenceFd); 48 } 49} 50 51status_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 60status_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 75sp<Fence> Fence::merge(const char* 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, f1->mFenceFd, f2->mFenceFd); 84 } else if (f1->isValid()) { 85 result = sync_merge(name, f1->mFenceFd, f1->mFenceFd); 86 } else if (f2->isValid()) { 87 result = sync_merge(name, 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, f1->mFenceFd, f2->mFenceFd, 95 strerror(-err), err); 96 return NO_FENCE; 97 } 98 return sp<Fence>(new Fence(result)); 99} 100 101sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1, 102 const sp<Fence>& f2) { 103 return merge(name.string(), f1, f2); 104} 105 106int Fence::dup() const { 107 return ::dup(mFenceFd); 108} 109 110nsecs_t Fence::getSignalTime() const { 111 if (mFenceFd == -1) { 112 return -1; 113 } 114 115 struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd); 116 if (finfo == NULL) { 117 ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd); 118 return -1; 119 } 120 if (finfo->status != 1) { 121 sync_fence_info_free(finfo); 122 return INT64_MAX; 123 } 124 125 struct sync_pt_info* pinfo = NULL; 126 uint64_t timestamp = 0; 127 while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) { 128 if (pinfo->timestamp_ns > timestamp) { 129 timestamp = pinfo->timestamp_ns; 130 } 131 } 132 sync_fence_info_free(finfo); 133 134 return nsecs_t(timestamp); 135} 136 137size_t Fence::getFlattenedSize() const { 138 return 4; 139} 140 141size_t Fence::getFdCount() const { 142 return isValid() ? 1 : 0; 143} 144 145status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 146 if (size < getFlattenedSize() || count < getFdCount()) { 147 return NO_MEMORY; 148 } 149 // Cast to uint32_t since the size of a size_t can vary between 32- and 150 // 64-bit processes 151 FlattenableUtils::write(buffer, size, static_cast<uint32_t>(getFdCount())); 152 if (isValid()) { 153 *fds++ = mFenceFd; 154 count--; 155 } 156 return NO_ERROR; 157} 158 159status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) { 160 if (mFenceFd != -1) { 161 // Don't unflatten if we already have a valid fd. 162 return INVALID_OPERATION; 163 } 164 165 if (size < getFlattenedSize()) { 166 return NO_MEMORY; 167 } 168 169 uint32_t numFds; 170 FlattenableUtils::read(buffer, size, numFds); 171 172 if (numFds > 1) { 173 return BAD_VALUE; 174 } 175 176 if (count < numFds) { 177 return NO_MEMORY; 178 } 179 180 if (numFds) { 181 mFenceFd = *fds++; 182 count--; 183 } 184 185 return NO_ERROR; 186} 187 188} // namespace android 189