diff options
-rw-r--r-- | services/surfaceflinger/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/BackgroundExecutor.cpp | 65 | ||||
-rw-r--r-- | services/surfaceflinger/BackgroundExecutor.h | 42 | ||||
-rw-r--r-- | services/surfaceflinger/TransactionCallbackInvoker.cpp | 39 | ||||
-rw-r--r-- | services/surfaceflinger/TransactionCallbackInvoker.h | 9 |
5 files changed, 113 insertions, 43 deletions
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index fb42cc02eb..2a9e2e7f0d 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -144,6 +144,7 @@ cc_library_headers { filegroup { name: "libsurfaceflinger_sources", srcs: [ + "BackgroundExecutor.cpp", "BufferLayer.cpp", "BufferLayerConsumer.cpp", "BufferQueueLayer.cpp", diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp new file mode 100644 index 0000000000..3663cdb0ec --- /dev/null +++ b/services/surfaceflinger/BackgroundExecutor.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "BackgroundExecutor" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BackgroundExecutor.h" + +namespace android { + +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); + mWorkAvailableCv.wait(lock, [&]() { return mDone || !mTasks.empty(); }); + tasks = std::move(mTasks); + mTasks.clear(); + done = mDone; + } // unlock mMutex + + for (auto& task : tasks) { + task(); + } + } + }); +} + +BackgroundExecutor::~BackgroundExecutor() { + { + std::unique_lock lock(mMutex); + mDone = true; + mWorkAvailableCv.notify_all(); + } + if (mThread.joinable()) { + mThread.join(); + } +} + +void BackgroundExecutor::execute(std::function<void()> task) { + std::unique_lock lock(mMutex); + mTasks.emplace_back(std::move(task)); + mWorkAvailableCv.notify_all(); +} + +} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h new file mode 100644 index 0000000000..6f6d305280 --- /dev/null +++ b/services/surfaceflinger/BackgroundExecutor.h @@ -0,0 +1,42 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <utils/Singleton.h> +#include <condition_variable> +#include <mutex> +#include <queue> +#include <thread> + +namespace android { + +// Executes tasks off the main thread. +class BackgroundExecutor : public Singleton<BackgroundExecutor> { +public: + BackgroundExecutor(); + ~BackgroundExecutor(); + void execute(std::function<void()>); + +private: + std::mutex mMutex; + std::condition_variable mWorkAvailableCv; + std::thread mThread; + bool mDone = false; + std::vector<std::function<void()>> mTasks; +}; + +} // namespace android diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index f3d46ea061..b705d9cf7b 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -24,6 +24,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "TransactionCallbackInvoker.h" +#include "BackgroundExecutor.h" #include <cinttypes> @@ -49,31 +50,6 @@ static bool containsOnCommitCallbacks(const std::vector<CallbackId>& callbacks) return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT; } -TransactionCallbackInvoker::TransactionCallbackInvoker() { - mThread = std::thread([&]() { - std::unique_lock lock(mCallbackThreadMutex); - - while (mKeepRunning) { - while (mCallbackThreadWork.size() > 0) { - mCallbackThreadWork.front()(); - mCallbackThreadWork.pop(); - } - mCallbackConditionVariable.wait(lock); - } - }); -} - -TransactionCallbackInvoker::~TransactionCallbackInvoker() { - { - std::unique_lock lock(mCallbackThreadMutex); - mKeepRunning = false; - mCallbackConditionVariable.notify_all(); - } - if (mThread.joinable()) { - mThread.join(); - } -} - void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; auto& transactionStatsDeque = mCompletedTransactions[listener]; @@ -242,15 +218,10 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // keep it as an IBinder due to consistency reasons: if we // interface_cast at the IPC boundary when reading a Parcel, // we get pointers that compare unequal in the SF process. - { - std::unique_lock lock(mCallbackThreadMutex); - mCallbackThreadWork.push( - [stats = std::move(listenerStats)]() { - interface_cast<ITransactionCompletedListener>(stats.listener) - ->onTransactionCompleted(stats); - }); - mCallbackConditionVariable.notify_all(); - } + BackgroundExecutor::getInstance().execute([stats = std::move(listenerStats)]() { + interface_cast<ITransactionCompletedListener>(stats.listener) + ->onTransactionCompleted(stats); + }); } } completedTransactionsItr++; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index e203d41bd9..5ef54757d7 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -61,9 +61,6 @@ public: class TransactionCallbackInvoker { public: - TransactionCallbackInvoker(); - ~TransactionCallbackInvoker(); - status_t addCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData); status_t addOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, @@ -94,12 +91,6 @@ private: mCompletedTransactions; sp<Fence> mPresentFence; - - std::mutex mCallbackThreadMutex; - std::condition_variable mCallbackConditionVariable; - std::thread mThread; - bool mKeepRunning = true; - std::queue<std::function<void()>> mCallbackThreadWork; }; } // namespace android |