You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.4 KiB
182 lines
5.4 KiB
4 months ago
|
/*
|
||
|
* 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 <utils/fence.h>
|
||
|
#include <debug_handler.h>
|
||
|
#include <assert.h>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
#include <algorithm>
|
||
|
|
||
|
#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<std::weak_ptr<Fence>> 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<Fence> &wp) {
|
||
|
return wp.expired();
|
||
|
}), wps_.end());
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
void Fence::Set(BufferSyncHandler *buffer_sync_handler) {
|
||
|
g_buffer_sync_handler_ = buffer_sync_handler;
|
||
|
}
|
||
|
|
||
|
shared_ptr<Fence> 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> fence(new Fence(fd, name));
|
||
|
if (!fence) {
|
||
|
close(fd);
|
||
|
}
|
||
|
|
||
|
// wps_.push_back(fence);
|
||
|
|
||
|
return fence;
|
||
|
}
|
||
|
|
||
|
int Fence::Dup(const shared_ptr<Fence> &fence) {
|
||
|
return (fence ? dup(fence->fd_) : -1);
|
||
|
}
|
||
|
|
||
|
int Fence::Get(const shared_ptr<Fence> &fence) {
|
||
|
return (fence ? fence->fd_ : -1);
|
||
|
}
|
||
|
|
||
|
shared_ptr<Fence> Fence::Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &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> Fence::Merge(const std::vector<shared_ptr<Fence>> &fences, bool ignore_signaled) {
|
||
|
ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
|
||
|
|
||
|
shared_ptr<Fence> 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> &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> &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> &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> &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> 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> &fence) {
|
||
|
int dup_fd = Fence::Dup(fence);
|
||
|
if (dup_fd >= 0) {
|
||
|
dup_fds_.push_back(dup_fd);
|
||
|
}
|
||
|
|
||
|
return dup_fd;
|
||
|
}
|
||
|
|
||
|
} // namespace sdm
|