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

Commit 520aa4bd authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8611520 from 64921f06 to tm-qpr1-release

Change-Id: I8451362eecbfa0588b2c8b08bb214dd0256be6dc
parents ddfe5cd9 64921f06
Loading
Loading
Loading
Loading
+33 −23
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#define LOG_TAG "BackgroundExecutor"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <utils/Log.h>

#include "BackgroundExecutor.h"

namespace android {
@@ -27,41 +29,49 @@ ANDROID_SINGLETON_STATIC_INSTANCE(BackgroundExecutor);

BackgroundExecutor::BackgroundExecutor() : Singleton<BackgroundExecutor>() {
    mThread = std::thread([&]() {
        bool done = false;
        while (!done) {
            std::vector<std::function<void()>> tasks;
            {
                std::unique_lock lock(mMutex);
                android::base::ScopedLockAssertion assumeLock(mMutex);
                mWorkAvailableCv.wait(lock,
                                      [&]() REQUIRES(mMutex) { return mDone || !mTasks.empty(); });
                tasks = std::move(mTasks);
                mTasks.clear();
                done = mDone;
            } // unlock mMutex
        LOG_ALWAYS_FATAL_IF(sem_init(&mSemaphore, 0, 0), "sem_init failed");
        while (!mDone) {
            LOG_ALWAYS_FATAL_IF(sem_wait(&mSemaphore), "sem_wait failed (%d)", errno);

            ftl::SmallVector<Work*, 10> workItems;

            Work* work = mWorks.pop();
            while (work) {
                workItems.push_back(work);
                work = mWorks.pop();
            }

            for (auto& task : tasks) {
            // Sequence numbers are guaranteed to be in intended order, as we assume a single
            // producer and single consumer.
            std::stable_sort(workItems.begin(), workItems.end(), [](Work* left, Work* right) {
                return left->sequence < right->sequence;
            });
            for (Work* work : workItems) {
                for (auto& task : work->tasks) {
                    task();
                }
                delete work;
            }
        }
    });
}

BackgroundExecutor::~BackgroundExecutor() {
    {
        std::scoped_lock lock(mMutex);
    mDone = true;
        mWorkAvailableCv.notify_all();
    }
    LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed");
    if (mThread.joinable()) {
        mThread.join();
        LOG_ALWAYS_FATAL_IF(sem_destroy(&mSemaphore), "sem_destroy failed");
    }
}

void BackgroundExecutor::execute(std::function<void()> task) {
    std::scoped_lock lock(mMutex);
    mTasks.emplace_back(std::move(task));
    mWorkAvailableCv.notify_all();
void BackgroundExecutor::sendCallbacks(Callbacks&& tasks) {
    Work* work = new Work();
    work->sequence = mSequence;
    work->tasks = std::move(tasks);
    mWorks.push(work);
    mSequence++;
    LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed");
}

} // namespace android
 No newline at end of file
+21 −6
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@

#pragma once

#include <Tracing/LocklessStack.h>
#include <android-base/thread_annotations.h>
#include <ftl/small_vector.h>
#include <semaphore.h>
#include <utils/Singleton.h>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
@@ -30,13 +32,26 @@ class BackgroundExecutor : public Singleton<BackgroundExecutor> {
public:
    BackgroundExecutor();
    ~BackgroundExecutor();
    void execute(std::function<void()>);
    using Callbacks = ftl::SmallVector<std::function<void()>, 10>;
    // Queues callbacks onto a work queue to be executed by a background thread.
    // Note that this is not thread-safe - a single producer is assumed.
    void sendCallbacks(Callbacks&& tasks);

private:
    std::mutex mMutex;
    std::condition_variable mWorkAvailableCv GUARDED_BY(mMutex);
    bool mDone GUARDED_BY(mMutex) = false;
    std::vector<std::function<void()>> mTasks GUARDED_BY(mMutex);
    sem_t mSemaphore;
    std::atomic_bool mDone = false;

    // Sequence number for work items.
    // Work items are batched by sequence number. Work items for earlier sequence numbers are
    // executed first. Work items with the same sequence number are executed in the same order they
    // were added to the stack (meaning the stack must reverse the order after popping from the
    // queue)
    int32_t mSequence = 0;
    struct Work {
        int32_t sequence = 0;
        Callbacks tasks;
    };
    LocklessStack<Work> mWorks;
    std::thread mThread;
};

+2 −3
Original line number Diff line number Diff line
@@ -48,9 +48,8 @@ BufferQueueLayer::~BufferQueueLayer() {
// Interface implementation for Layer
// -----------------------------------------------------------------------

void BufferQueueLayer::onLayerDisplayed(
        std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) {
    sp<Fence> releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence));
void BufferQueueLayer::onLayerDisplayed(std::shared_future<FenceResult> futureFenceResult) {
    const sp<Fence> releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE);
    mConsumer->setReleaseFence(releaseFence);

    // Prevent tracing the same release multiple times.
+1 −2
Original line number Diff line number Diff line
@@ -42,8 +42,7 @@ public:
    // Implements Layer.
    const char* getType() const override { return "BufferQueueLayer"; }

    void onLayerDisplayed(
            std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) override;
    void onLayerDisplayed(std::shared_future<FenceResult>) override;

    // If a buffer was replaced this frame, release the former buffer
    void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
+2 −3
Original line number Diff line number Diff line
@@ -73,8 +73,7 @@ BufferStateLayer::~BufferStateLayer() {
// -----------------------------------------------------------------------
// Interface implementation for Layer
// -----------------------------------------------------------------------
void BufferStateLayer::onLayerDisplayed(
        std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) {
void BufferStateLayer::onLayerDisplayed(std::shared_future<FenceResult> futureFenceResult) {
    // If we are displayed on multiple displays in a single composition cycle then we would
    // need to do careful tracking to enable the use of the mLastClientCompositionFence.
    //  For example we can only use it if all the displays are client comp, and we need
@@ -118,7 +117,7 @@ void BufferStateLayer::onLayerDisplayed(

    if (ch != nullptr) {
        ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
        ch->previousReleaseFences.emplace_back(futureRenderEngineResult);
        ch->previousReleaseFences.emplace_back(std::move(futureFenceResult));
        ch->name = mName;
    }
}
Loading