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.

199 lines
6.2 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2020-2020. All rights reserved.
* Description: On behalf of a display device, hwcomposer is called for composition and sent for display
* Author: Hisilicon
* Created: 2020.08.04
*/
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <utils/Trace.h>
#include <log/log.h>
#include <securec.h>
#include "FenceMonitor.h"
namespace android {
HwcLayerFence::HwcLayerFence(const sp<Fence> &fence, hwc2_layer_t layerId, uint64_t seq)
: m_fence(fence), m_layerid(layerId), m_seq(seq)
{}
HwcLayerFence::~HwcLayerFence() {}
nsecs_t HwcLayerFence::GetSignalTime() const
{
return m_fence->getSignalTime();
}
status_t HwcLayerFence::WaitForever(std::string msg)
{
return m_fence->waitForever(msg.c_str());
}
int HwcLayerFence::Get() const
{
return m_fence->get();
}
bool HwcLayerFence::HasSignaled() const
{
return (m_fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING);
}
const sp<Fence> &HwcLayerFence::GetFence()
{
return m_fence;
}
std::string HwcLayerFence::GetString() const
{
std::stringstream os;
os << " ";
os << "layer_id:" << m_layerid << " fence seq:" << m_seq << " State: " << (HasSignaled() ? "Signaled" : "Waiting");
if (!HasSignaled() && (m_timestamp != 0)) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
double dur = (now - m_timestamp) / static_cast<double>((TIME_CONVERSION_LEVEL * TIME_CONVERSION_LEVEL));
os << " for " << dur << " ms";
}
return os.str();
}
hwc2_layer_t HwcLayerFence::GetLayerId() const
{
return m_layerid;
}
uint64_t HwcLayerFence::GetSeq() const
{
return m_seq;
}
inline void HwcLayerFence::UpdateTimeStamp()
{
if (m_timestamp == 0) {
m_timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
}
}
FenceMonitor::FenceMonitor(const std::string &name) : mName(name), mFencesQueued(0), mFencesSignaled(0)
{
std::thread thread(&FenceMonitor::Loop, this);
pthread_setname_np(thread.native_handle(), mName.c_str());
thread.detach();
}
FenceMonitor::~FenceMonitor() {}
std::string FenceMonitor::Dump()
{
std::stringstream os;
std::lock_guard<std::mutex> lock(mMutex);
os << mName << ":" << std::endl;
for (auto fence = mQueue.cbegin(); fence != mQueue.cend(); ++fence) {
os << " " << (*fence)->GetString() << std::endl;
}
return os.str();
}
void FenceMonitor::QueueFence(const sp<HwcLayerFence> &fence)
{
const int maxMsgLen = 100;
char message[maxMsgLen] = {0};
std::lock_guard<std::mutex> lock(mMutex);
if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) {
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "%s fence:%llu %llu - %llu has signaled",
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued);
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
ATRACE_NAME(message);
// Need an increment on both to make the trace number correct.
mFencesQueued++;
mFencesSignaled++;
return;
}
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "Trace %s fence:%llu %llu - %llu",
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued);
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
ATRACE_NAME(message);
fence->UpdateTimeStamp();
mQueue.push_back(fence);
mCondition.notify_one();
mFencesQueued++;
ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
void FenceMonitor::Loop()
{
while (true) {
ThreadLoop();
}
}
#pragma clang diagnostic pop
void FenceMonitor::ThreadLoop()
{
sp<HwcLayerFence> fence;
const int maxMsgLen = 100;
uint64_t fenceNum;
{
std::unique_lock<std::mutex> lock(mMutex);
while (mQueue.empty()) {
mCondition.wait(lock);
}
fence = mQueue[0];
fenceNum = mFencesSignaled;
}
{
char message[maxMsgLen] = {0};
if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) {
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1,
"%s fence:%llu %llu - %llu has signaled", mName.c_str(), fence->GetSeq(),
fence->GetLayerId(), fenceNum);
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
ATRACE_NAME(message);
} else {
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "waiting for %s:%llu %llu - %llu",
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), fenceNum);
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
ATRACE_NAME(message);
std::string msg = message;
status_t result = fence->WaitForever(msg);
if (result != OK) {
ALOGE("Error waiting for fence: %d", result);
}
}
}
{
std::lock_guard<std::mutex> lock(mMutex);
mQueue.pop_front();
mFencesSignaled++;
ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
}
}
FenceMonitorMng::FenceMonitorMng() {}
FenceMonitorMng::~FenceMonitorMng() {}
void FenceMonitorMng::AddFence(int fd, FENCE_TYPE type, hwc2_layer_t layerid, uint64_t seq)
{
if (type >= FENCE_TYPE_ENUM::FENCE_TYPE_NUM) {
return;
}
if (m_fenceMonior[(int)type] == nullptr) {
m_fenceMonior[(int)type] = std::make_unique<FenceMonitor>(G_FENCE_TYPE_NMAE[(int)type]);
}
m_fenceMonior[(int)type]->QueueFence(new HwcLayerFence(new Fence(dup(fd)), layerid, seq));
}
std::string FenceMonitorMng::Dump() const
{
std::stringstream os;
os << "HWC fence monitor:" << std::endl;
for (int i = 0; i < static_cast<int>(FENCE_TYPE_ENUM::FENCE_TYPE_NUM); i++) {
if (m_fenceMonior[i] != nullptr) {
os << " " << m_fenceMonior[i]->Dump() << std::endl;
}
}
return os.str();
}
} // end namespace