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

Commit d4a22754 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Extract utils::OnceFuture

Make `mRenderEnginePrimeCacheFuture` thread-safe and release its shared
state after the wait.

Bug: 328459745
Test: presubmit
Change-Id: I2bf3029823109a8c97e599d20c15e46ac1e4aeb9
parent 9cc667b4
Loading
Loading
Loading
Loading
+13 −20
Original line number Diff line number Diff line
@@ -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() {
@@ -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;
@@ -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");
@@ -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");
+3 −3
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@
#include "Tracing/TransactionTracing.h"
#include "TransactionCallbackInvoker.h"
#include "TransactionState.h"
#include "Utils/OnceFuture.h"

#include <atomic>
#include <cstdint>
@@ -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.
+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