From 552404292238bd1758346cc526827580aec4f532 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 11 Jun 2023 12:06:23 +0200 Subject: [PATCH] Android: Move host thread lock to a separate file --- Source/Android/jni/CMakeLists.txt | 2 + Source/Android/jni/Host.cpp | 8 ++++ Source/Android/jni/Host.h | 24 ++++++++++++ Source/Android/jni/MainAndroid.cpp | 60 +++++++++++------------------- 4 files changed, 55 insertions(+), 39 deletions(-) create mode 100644 Source/Android/jni/Host.cpp create mode 100644 Source/Android/jni/Host.h diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index 7218c64924..bb849074e4 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -10,6 +10,8 @@ add_library(main SHARED GameList/GameFile.cpp GameList/GameFile.h GameList/GameFileCache.cpp + Host.cpp + Host.h InfinityConfig.cpp Input/Control.cpp Input/Control.h diff --git a/Source/Android/jni/Host.cpp b/Source/Android/jni/Host.cpp new file mode 100644 index 0000000000..71647afac1 --- /dev/null +++ b/Source/Android/jni/Host.cpp @@ -0,0 +1,8 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "jni/Host.h" + +#include + +std::mutex HostThreadLock::s_host_identity_mutex; diff --git a/Source/Android/jni/Host.h b/Source/Android/jni/Host.h new file mode 100644 index 0000000000..6025c62644 --- /dev/null +++ b/Source/Android/jni/Host.h @@ -0,0 +1,24 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "Core/Core.h" + +// The Core only supports using a single Host thread. +// If multiple threads want to call host functions then they need to queue +// sequentially for access. +struct HostThreadLock +{ + static std::mutex s_host_identity_mutex; + std::unique_lock m_lock; + + explicit HostThreadLock() : m_lock(s_host_identity_mutex) { Core::DeclareAsHostThread(); } + HostThreadLock(const HostThreadLock& other) = delete; + HostThreadLock(HostThreadLock&& other) = delete; + HostThreadLock& operator=(const HostThreadLock& other) = delete; + HostThreadLock& operator=(HostThreadLock&& other) = delete; + ~HostThreadLock() { Core::UndeclareAsHostThread(); } +}; diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index d73c9f3d75..d99326aaae 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -63,6 +63,7 @@ #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" +#include "jni/Host.h" namespace { @@ -70,25 +71,6 @@ constexpr char DOLPHIN_TAG[] = "DolphinEmuNative"; ANativeWindow* s_surf; -// The Core only supports using a single Host thread. -// If multiple threads want to call host functions then they need to queue -// sequentially for access. -std::mutex s_host_identity_lock; -template -struct HostThreadWrapper -{ - T lock; - - explicit HostThreadWrapper(auto&&... args) : lock(std::forward(args)...) - { - Core::DeclareAsHostThread(); - } - HostThreadWrapper(const HostThreadWrapper& other) = delete; - HostThreadWrapper(HostThreadWrapper&& other) = delete; - HostThreadWrapper& operator=(const HostThreadWrapper& other) = delete; - HostThreadWrapper& operator=(HostThreadWrapper&& other) = delete; - ~HostThreadWrapper() { Core::UndeclareAsHostThread(); } -}; Common::Event s_update_main_frame_event; // This exists to prevent surfaces from being destroyed during the boot process, @@ -263,19 +245,19 @@ extern "C" { JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_UnPauseEmulation(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; Core::SetState(Core::State::Running); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulation(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; Core::SetState(Core::State::Paused); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; Core::Stop(); // Kick the waiting event @@ -318,7 +300,7 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGitRev JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; Core::SaveScreenShot(); } @@ -332,7 +314,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JN jint slot, jboolean wait) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; State::Save(slot, wait); } @@ -340,21 +322,21 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveStateAs( jstring path, jboolean wait) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; State::SaveAs(GetJString(env, path), wait); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv*, jclass, jint slot) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; State::Load(slot); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(JNIEnv* env, jclass, jstring path) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; State::LoadAs(GetJString(env, path)); } @@ -383,7 +365,7 @@ Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_SetGpuDriverDirecto JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory( JNIEnv* env, jclass, jstring jDirectory) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; UICommon::SetUserDirectory(GetJString(env, jDirectory)); } @@ -396,7 +378,7 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserDi JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetCacheDirectory( JNIEnv* env, jclass, jstring jDirectory) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; File::SetUserPath(D_CACHE_IDX, GetJString(env, jDirectory)); } @@ -419,7 +401,7 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetMaxLogLev JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv*, jclass, jboolean enable) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; Core::SetState(Core::State::Paused); auto& jit_interface = Core::System::GetInstance().GetJitInterface(); jit_interface.ClearCache(); @@ -431,7 +413,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; std::string filename = File::GetUserPath(D_DUMP_IDX) + "Debug/profiler.txt"; File::CreateFullPath(filename); auto& jit_interface = Core::System::GetInstance().GetJitInterface(); @@ -460,14 +442,14 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr // If emulation continues running without a valid surface, we will probably crash, // so pause emulation until we get a valid surface again. EmulationFragment handles resuming. - HostThreadWrapper> host_identity_guard(s_host_identity_lock); + HostThreadLock host_identity_guard; while (s_is_booting.IsSet()) { // Need to wait for boot to finish before we can pause - host_identity_guard.lock.unlock(); + host_identity_guard.m_lock.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); - host_identity_guard.lock.lock(); + host_identity_guard.m_lock.lock(); } if (Core::GetState() == Core::State::Running) @@ -501,7 +483,7 @@ JNIEXPORT jfloat JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGameAsp JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv*, jclass) { - HostThreadWrapper> guard(s_host_identity_lock); + HostThreadLock guard; WiimoteReal::Refresh(); } @@ -559,7 +541,7 @@ static float GetRenderSurfaceScale(JNIEnv* env) static void Run(JNIEnv* env, std::unique_ptr&& boot, bool riivolution) { - HostThreadWrapper> host_identity_guard(s_host_identity_lock); + HostThreadLock host_identity_guard; if (riivolution && std::holds_alternative(boot->parameters)) { @@ -590,15 +572,15 @@ static void Run(JNIEnv* env, std::unique_ptr&& boot, bool riivol while (Core::IsRunning()) { - host_identity_guard.lock.unlock(); + host_identity_guard.m_lock.unlock(); s_update_main_frame_event.Wait(); - host_identity_guard.lock.lock(); + host_identity_guard.m_lock.lock(); Core::HostDispatchJobs(); } s_game_metadata_is_valid = false; Core::Shutdown(); - host_identity_guard.lock.unlock(); + host_identity_guard.m_lock.unlock(); env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetFinishEmulationActivity());