Loading services/surfaceflinger/SurfaceFlinger.cpp +13 −20 Original line number Diff line number Diff line Loading @@ -565,14 +565,11 @@ void SurfaceFlinger::binderDied(const wp<IBinder>&) { initializeDisplays(); })); std::lock_guard lock(mInitBootPropsFutureMutex); if (!mInitBootPropsFuture.valid()) { mInitBootPropsFuture = std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); } mInitBootPropsFuture.callOnce([this] { return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); }); mInitBootPropsFuture.wait(); mInitBootPropsFuture = {}; } void SurfaceFlinger::run() { Loading Loading @@ -729,13 +726,8 @@ void SurfaceFlinger::bootFinished() { mBootFinished = true; FlagManager::getMutableInstance().markBootCompleted(); if (std::lock_guard lock(mInitBootPropsFutureMutex); mInitBootPropsFuture.valid()) { mInitBootPropsFuture.wait(); mInitBootPropsFuture = {}; } if (mRenderEnginePrimeCacheFuture.valid()) { mRenderEnginePrimeCacheFuture.wait(); } const nsecs_t now = systemTime(); const nsecs_t duration = now - mBootTime; Loading Loading @@ -925,9 +917,11 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { ALOGW("Can't set SCHED_OTHER for primeCache"); } bool shouldPrimeUltraHDR = mRenderEnginePrimeCacheFuture.callOnce([this] { const bool shouldPrimeUltraHDR = base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false); mRenderEnginePrimeCacheFuture = getRenderEngine().primeCache(shouldPrimeUltraHDR); return getRenderEngine().primeCache(shouldPrimeUltraHDR); }); if (setSchedFifo(true) != NO_ERROR) { ALOGW("Can't set SCHED_FIFO after primeCache"); Loading @@ -935,10 +929,9 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { } // Avoid blocking the main thread on `init` to set properties. if (std::lock_guard lock(mInitBootPropsFutureMutex); !mInitBootPropsFuture.valid()) { mInitBootPropsFuture = std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); } mInitBootPropsFuture.callOnce([this] { return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); }); initTransactionTraceWriter(); ALOGV("Done initializing"); Loading services/surfaceflinger/SurfaceFlinger.h +3 −3 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ #include "Tracing/TransactionTracing.h" #include "TransactionCallbackInvoker.h" #include "TransactionState.h" #include "Utils/OnceFuture.h" #include <atomic> #include <cstdint> Loading Loading @@ -1189,10 +1190,9 @@ private: pid_t mPid; // TODO: b/328459745 - Encapsulate in a SystemProperties object. std::mutex mInitBootPropsFutureMutex; std::future<void> mInitBootPropsFuture GUARDED_BY(mInitBootPropsFutureMutex); utils::OnceFuture mInitBootPropsFuture; std::future<void> mRenderEnginePrimeCacheFuture; utils::OnceFuture mRenderEnginePrimeCacheFuture; // mStateLock has conventions related to the current thread, because only // the main thread should modify variables protected by mStateLock. Loading services/surfaceflinger/Utils/OnceFuture.h 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright 2024 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 <future> #include <mutex> #include <android-base/thread_annotations.h> namespace android::utils { // Allows a thread to `wait` for a future produced by a different thread. The future is returned by // the first call to a function `F` that multiple threads may `callOnce`. If no `callOnce` happens, // then `wait` does nothing. Otherwise, it blocks on the future, then destroys it, which resets the // `OnceFuture`. class OnceFuture { public: template <typename F> void callOnce(F f) { std::lock_guard lock(mMutex); if (!mFuture.valid()) { mFuture = f(); } } void wait() { std::lock_guard lock(mMutex); if (mFuture.valid()) { mFuture.wait(); mFuture = {}; } } private: std::mutex mMutex; std::future<void> mFuture GUARDED_BY(mMutex); }; } // namespace android::utils Loading
services/surfaceflinger/SurfaceFlinger.cpp +13 −20 Original line number Diff line number Diff line Loading @@ -565,14 +565,11 @@ void SurfaceFlinger::binderDied(const wp<IBinder>&) { initializeDisplays(); })); std::lock_guard lock(mInitBootPropsFutureMutex); if (!mInitBootPropsFuture.valid()) { mInitBootPropsFuture = std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); } mInitBootPropsFuture.callOnce([this] { return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); }); mInitBootPropsFuture.wait(); mInitBootPropsFuture = {}; } void SurfaceFlinger::run() { Loading Loading @@ -729,13 +726,8 @@ void SurfaceFlinger::bootFinished() { mBootFinished = true; FlagManager::getMutableInstance().markBootCompleted(); if (std::lock_guard lock(mInitBootPropsFutureMutex); mInitBootPropsFuture.valid()) { mInitBootPropsFuture.wait(); mInitBootPropsFuture = {}; } if (mRenderEnginePrimeCacheFuture.valid()) { mRenderEnginePrimeCacheFuture.wait(); } const nsecs_t now = systemTime(); const nsecs_t duration = now - mBootTime; Loading Loading @@ -925,9 +917,11 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { ALOGW("Can't set SCHED_OTHER for primeCache"); } bool shouldPrimeUltraHDR = mRenderEnginePrimeCacheFuture.callOnce([this] { const bool shouldPrimeUltraHDR = base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false); mRenderEnginePrimeCacheFuture = getRenderEngine().primeCache(shouldPrimeUltraHDR); return getRenderEngine().primeCache(shouldPrimeUltraHDR); }); if (setSchedFifo(true) != NO_ERROR) { ALOGW("Can't set SCHED_FIFO after primeCache"); Loading @@ -935,10 +929,9 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { } // Avoid blocking the main thread on `init` to set properties. if (std::lock_guard lock(mInitBootPropsFutureMutex); !mInitBootPropsFuture.valid()) { mInitBootPropsFuture = std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); } mInitBootPropsFuture.callOnce([this] { return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); }); initTransactionTraceWriter(); ALOGV("Done initializing"); Loading
services/surfaceflinger/SurfaceFlinger.h +3 −3 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ #include "Tracing/TransactionTracing.h" #include "TransactionCallbackInvoker.h" #include "TransactionState.h" #include "Utils/OnceFuture.h" #include <atomic> #include <cstdint> Loading Loading @@ -1189,10 +1190,9 @@ private: pid_t mPid; // TODO: b/328459745 - Encapsulate in a SystemProperties object. std::mutex mInitBootPropsFutureMutex; std::future<void> mInitBootPropsFuture GUARDED_BY(mInitBootPropsFutureMutex); utils::OnceFuture mInitBootPropsFuture; std::future<void> mRenderEnginePrimeCacheFuture; utils::OnceFuture mRenderEnginePrimeCacheFuture; // mStateLock has conventions related to the current thread, because only // the main thread should modify variables protected by mStateLock. Loading
services/surfaceflinger/Utils/OnceFuture.h 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright 2024 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 <future> #include <mutex> #include <android-base/thread_annotations.h> namespace android::utils { // Allows a thread to `wait` for a future produced by a different thread. The future is returned by // the first call to a function `F` that multiple threads may `callOnce`. If no `callOnce` happens, // then `wait` does nothing. Otherwise, it blocks on the future, then destroys it, which resets the // `OnceFuture`. class OnceFuture { public: template <typename F> void callOnce(F f) { std::lock_guard lock(mMutex); if (!mFuture.valid()) { mFuture = f(); } } void wait() { std::lock_guard lock(mMutex); if (mFuture.valid()) { mFuture.wait(); mFuture = {}; } } private: std::mutex mMutex; std::future<void> mFuture GUARDED_BY(mMutex); }; } // namespace android::utils