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