16d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov/* 26d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Copyright (C) 2012 The Android Open Source Project 36d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * 46d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Licensed under the Apache License, Version 2.0 (the "License"); 56d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * you may not use this file except in compliance with the License. 66d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * You may obtain a copy of the License at 76d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * 86d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * http://www.apache.org/licenses/LICENSE-2.0 96d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * 106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Unless required by applicable law or agreed to in writing, software 116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * distributed under the License is distributed on an "AS IS" BASIS, 126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * See the License for the specific language governing permissions and 146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * limitations under the License. 156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov */ 166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#define LOG_TAG "Fence" 186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#define ATRACE_TAG ATRACE_TAG_GRAPHICS 196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//#define LOG_NDEBUG 0 206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // This is needed for stdint.h to define INT64_MAX in C++ 226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov #define __STDC_LIMIT_MACROS 236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <sync/sync.h> 256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <ui/Fence.h> 266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <unistd.h> 276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <utils/Log.h> 286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <utils/Trace.h> 296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace android { 316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovconst sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence); 336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::Fence() : 356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov mFenceFd(-1) { 366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 37e374e4ece521692173aad355420d03e1b2cd819aAlexey Samsonov 386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::Fence(int fenceFd) : 396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov mFenceFd(fenceFd) { 406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::~Fence() { 436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (mFenceFd != -1) { 446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov close(mFenceFd); 456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::wait(unsigned int timeout) { 496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ATRACE_CALL(); 506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (mFenceFd == -1) { 516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return NO_ERROR; 526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov int err = sync_wait(mFenceFd, timeout); 546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return err < 0 ? -errno : status_t(NO_ERROR); 556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::waitForever(const char* logname) { 586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ATRACE_CALL(); 596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (mFenceFd == -1) { 60ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return NO_ERROR; 616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov unsigned int warningTimeout = 3000; 636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov int err = sync_wait(mFenceFd, warningTimeout); 646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (err < 0 && errno == ETIME) { 656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd, 666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov warningTimeout); 676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov err = sync_wait(mFenceFd, TIMEOUT_NEVER); 686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return err < 0 ? -errno : status_t(NO_ERROR); 70ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovsp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1, 736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov const sp<Fence>& f2) { 746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ATRACE_CALL(); 756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov int result; 766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Merge the two fences. In the case where one of the fences is not a 77827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so 78827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov // that a new fence with the given name is created. 796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (f1->isValid() && f2->isValid()) { 806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd); 816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } else if (f1->isValid()) { 826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd); 836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } else if (f2->isValid()) { 846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd); 856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } else { 866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return NO_FENCE; 876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (result == -1) { 896d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status_t err = -errno; 906d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)", 916d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name.string(), f1->mFenceFd, f2->mFenceFd, 926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov strerror(-err), err); 936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return NO_FENCE; 946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 956d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return sp<Fence>(new Fence(result)); 966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovint Fence::dup() const { 996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return ::dup(mFenceFd); 1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnsecs_t Fence::getSignalTime() const { 1036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (mFenceFd == -1) { 1046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return -1; 1056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd); 1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (finfo == NULL) { 1096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd); 1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return -1; 1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (finfo->status != 1) { 1136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov sync_fence_info_free(finfo); 1146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return INT64_MAX; 115116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov } 116116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov 117116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov struct sync_pt_info* pinfo = NULL; 118116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov uint64_t timestamp = 0; 119116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) { 120116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov if (pinfo->timestamp_ns > timestamp) { 121116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov timestamp = pinfo->timestamp_ns; 122116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov } 123116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov } 124116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov sync_fence_info_free(finfo); 125116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov 126116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov return nsecs_t(timestamp); 127116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov} 128116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov 129116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonovsize_t Fence::getFlattenedSize() const { 130116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov return 1; 131116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov} 132116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov 133ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovsize_t Fence::getFdCount() const { 134ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return isValid() ? 1 : 0; 135ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 136ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov 1376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 1386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (size < getFlattenedSize() || count < getFdCount()) { 1396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return NO_MEMORY; 1406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov FlattenableUtils::write(buffer, size, (uint32_t)getFdCount()); 1426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (isValid()) { 1436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov *fds++ = mFenceFd; 1446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 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