Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3118f969 authored by Alec Mouri's avatar Alec Mouri
Browse files

Add some tracing for release fences

* Fix FenceMonitor to cleanly teardown
* App-side tracing for BBQ release callbacks
* Trace future compleition in TxnCallbackInvoker

Bug: 360932099
Bug: 357762453
Flag: EXEMPT debugging
Test: builds
Test: perfetto
Change-Id: I188c04da1e249b672b428837c328568d9e7a1e66
parent ec115475
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>

#include <gui/FenceMonitor.h>
#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
#include <gui/IProducerListener.h>
@@ -475,6 +476,16 @@ void BLASTBufferQueue::releaseBufferCallbackLocked(
    ATRACE_CALL();
    BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());

    if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
        if (!mFenceMonitor) {
            std::string monitorName = "release :";
            monitorName.append(mName.c_str());
            mFenceMonitor.emplace(monitorName.c_str());
        }

        mFenceMonitor->queueFence(releaseFence);
    }

    // Calculate how many buffers we need to hold before we release them back
    // to the buffer queue. This will prevent higher latency when we are running
    // on a lower refresh rate than the max supported. We only do that for EGL
+25 −11
Original line number Diff line number Diff line
@@ -25,9 +25,18 @@
namespace android::gui {

FenceMonitor::FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
    std::thread thread(&FenceMonitor::loop, this);
    pthread_setname_np(thread.native_handle(), mName);
    thread.detach();
    mThread = std::thread(&FenceMonitor::loop, this);
}

FenceMonitor::~FenceMonitor() {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mStopped = true;
        mCondition.notify_one();
    }
    if (mThread.joinable()) {
        mThread.join();
    }
}

void FenceMonitor::queueFence(const sp<Fence>& fence) {
@@ -35,24 +44,26 @@ void FenceMonitor::queueFence(const sp<Fence>& fence) {

    std::lock_guard<std::mutex> lock(mMutex);
    if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
        snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued);
        snprintf(message, sizeof(message), "%s fence %u has signaled", mName.c_str(),
                 mFencesQueued);
        ATRACE_NAME(message);
        // Need an increment on both to make the trace number correct.
        mFencesQueued++;
        mFencesSignaled++;
        return;
    }
    snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued);
    snprintf(message, sizeof(message), "Trace %s fence %u", mName.c_str(), mFencesQueued);
    ATRACE_NAME(message);

    mQueue.push_back(fence);
    mCondition.notify_one();
    mFencesQueued++;
    ATRACE_INT(mName, int32_t(mQueue.size()));
    ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
}

void FenceMonitor::loop() {
    while (true) {
    pthread_setname_np(pthread_self(), mName.c_str());
    while (!mStopped) {
        threadLoop();
    }
}
@@ -62,15 +73,18 @@ void FenceMonitor::threadLoop() {
    uint32_t fenceNum;
    {
        std::unique_lock<std::mutex> lock(mMutex);
        while (mQueue.empty()) {
        while (mQueue.empty() && !mStopped) {
            mCondition.wait(lock);
        }
        if (mStopped) {
            return;
        }
        fence = mQueue[0];
        fenceNum = mFencesSignaled;
    }
    {
        char message[64];
        snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
        snprintf(message, sizeof(message), "waiting for %s %u", mName.c_str(), fenceNum);
        ATRACE_NAME(message);

        status_t result = fence->waitForever(message);
@@ -82,7 +96,7 @@ void FenceMonitor::threadLoop() {
        std::lock_guard<std::mutex> lock(mMutex);
        mQueue.pop_front();
        mFencesSignaled++;
        ATRACE_INT(mName, int32_t(mQueue.size()));
        ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
    }
}

+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
#include <gui/FenceMonitor.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/SurfaceComposerClient.h>
@@ -316,6 +317,8 @@ private:

    std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);

    std::optional<gui::FenceMonitor> mFenceMonitor GUARDED_BY(mMutex);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    class BufferReleaseReader {
    public:
+6 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <cstdint>
#include <deque>
#include <mutex>
#include <thread>

#include <ui/Fence.h>

@@ -28,17 +29,20 @@ class FenceMonitor {
public:
    explicit FenceMonitor(const char* name);
    void queueFence(const sp<Fence>& fence);
    ~FenceMonitor();

private:
    void loop();
    void threadLoop();

    const char* mName;
    std::string mName;
    uint32_t mFencesQueued;
    uint32_t mFencesSignaled;
    std::deque<sp<Fence>> mQueue;
    std::condition_variable mCondition;
    std::mutex mMutex;
    std::thread mThread;
    std::atomic_bool mStopped = false;
};

} // namespace android::gui
+4 −0
Original line number Diff line number Diff line
@@ -769,6 +769,10 @@ void Layer::prepareReleaseCallbacks(ftl::Future<FenceResult> futureFenceResult,
        // Older fences for the same layer stack can be dropped when a new fence arrives.
        // An assumption here is that RenderEngine performs work sequentially, so an
        // incoming fence will not fire before an existing fence.
        SFTRACE_NAME(
                ftl::Concat("Adding additional fence for: ", ftl::truncated<20>(mName.c_str()),
                            ", Replacing?: ", mAdditionalPreviousReleaseFences.contains(layerStack))
                        .c_str());
        mAdditionalPreviousReleaseFences.emplace_or_replace(layerStack,
                                                            std::move(futureFenceResult));
    }
Loading