/* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #define __CLASS__ "Fence" namespace sdm { #define ASSERT_IF_NO_BUFFER_SYNC(x) if (!x) { assert(false); } BufferSyncHandler* Fence::g_buffer_sync_handler_ = nullptr; std::vector> Fence::wps_; Fence::Fence(int fd, const string &name) : fd_(fd), name_(name) { } Fence::~Fence() { close(fd_); // erase all expired weak references. /* wps_.erase(std::remove_if(wps_.begin(), wps_.end(), [](const std::weak_ptr &wp) { return wp.expired(); }), wps_.end()); */ } void Fence::Set(BufferSyncHandler *buffer_sync_handler) { g_buffer_sync_handler_ = buffer_sync_handler; } shared_ptr Fence::Create(int fd, const string &name) { // Do not create Fence object for invalid fd, so that nullptr can be used for invalid fences. if (fd < 0) { return nullptr; } shared_ptr fence(new Fence(fd, name)); if (!fence) { close(fd); } // wps_.push_back(fence); return fence; } int Fence::Dup(const shared_ptr &fence) { return (fence ? dup(fence->fd_) : -1); } int Fence::Get(const shared_ptr &fence) { return (fence ? fence->fd_ : -1); } shared_ptr Fence::Merge(const shared_ptr &fence1, const shared_ptr &fence2) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); // Sync merge will return a new unique fd if source fds are same. int fd1 = fence1 ? fence1->fd_ : -1; int fd2 = fence2 ? fence2->fd_ : -1; int merged = -1; std::string name = "merged[" + to_string(fd1) + ", " + to_string(fd2) + "]"; g_buffer_sync_handler_->SyncMerge(fd1, fd2, &merged); return Create(merged, name); } shared_ptr Fence::Merge(const std::vector> &fences, bool ignore_signaled) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); shared_ptr merged_fence = nullptr; for (auto &fence : fences) { if (ignore_signaled && (Fence::Wait(fence, 0) == kErrorNone)) { continue; } merged_fence = Fence::Merge(fence, merged_fence); } return merged_fence; } DisplayError Fence::Wait(const shared_ptr &fence) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 1000); } DisplayError Fence::Wait(const shared_ptr &fence, int timeout) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), timeout); } Fence::Status Fence::GetStatus(const shared_ptr &fence) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); if (!fence) { return Fence::Status::kSignaled; } // Treat only timeout error as pending, assume other errors as signaled. return (g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 0) == kErrorTimeOut ? Fence::Status::kPending : Fence::Status::kSignaled); } string Fence::GetStr(const shared_ptr &fence) { return std::to_string(Fence::Get(fence)); } void Fence::Dump(std::ostringstream *os) { ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_); *os << "\n------------Active Fences Info---------"; /* for (auto &wp : wps_) { *os << "\n"; shared_ptr fence = wp.lock(); if (!fence) { continue; } *os << "FD: " << fence->fd_; *os << ", name: " << fence->name_; *os << ", use_count: " << fence.use_count() - 1; // Do not count wp lock reference *os << ", "; g_buffer_sync_handler_->GetSyncInfo(fence->fd_, os); } */ *os << "\n---------------------------------------\n"; } Fence::ScopedRef::~ScopedRef() { for (int dup_fd : dup_fds_) { close(dup_fd); } } int Fence::ScopedRef::Get(const shared_ptr &fence) { int dup_fd = Fence::Dup(fence); if (dup_fd >= 0) { dup_fds_.push_back(dup_fd); } return dup_fd; } } // namespace sdm