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 30 namespace android { 31 32 const sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence); 33 34 Fence::Fence() : 35 mFenceFd(-1) { 36 } 37 38 Fence::Fence(int fenceFd) : 39 mFenceFd(fenceFd) { 40 } 41 42 Fence::~Fence() { 43 if (mFenceFd != -1) { 44 close(mFenceFd); 45 } 46 } 47 48 status_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 57 status_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 72 sp<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 98 int Fence::dup() const { 99 return ::dup(mFenceFd); 100 } 101 102 nsecs_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 129 size_t Fence::getFlattenedSize() const { 130 return 1; 131 } 132 133 size_t Fence::getFdCount() const { 134 return isValid() ? 1 : 0; 135 } 136 137 status_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 149 status_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