From 552404292238bd1758346cc526827580aec4f532 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 11 Jun 2023 12:06:23 +0200 Subject: Android: Move host thread lock to a separate file --- Source/Android/jni/MainAndroid.cpp | 60 +++++++++++++------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) (limited to 'Source/Android/jni/MainAndroid.cpp') 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()); -- cgit v1.2.3 From 3519a7070d5dc476cb1911bb1d2b05befbe0804b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 11 Jun 2023 12:18:16 +0200 Subject: Android: And Lock and Unlock wrappers to HostThreadLock This way we can ensure DeclareAsHostThread and UndeclareAsHostThread are called when locking and unlocking. --- Source/Android/jni/MainAndroid.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Source/Android/jni/MainAndroid.cpp') diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index d99326aaae..0b8a0760ab 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -447,9 +447,9 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr while (s_is_booting.IsSet()) { // Need to wait for boot to finish before we can pause - host_identity_guard.m_lock.unlock(); + host_identity_guard.Unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); - host_identity_guard.m_lock.lock(); + host_identity_guard.Lock(); } if (Core::GetState() == Core::State::Running) @@ -572,15 +572,15 @@ static void Run(JNIEnv* env, std::unique_ptr&& boot, bool riivol while (Core::IsRunning()) { - host_identity_guard.m_lock.unlock(); + host_identity_guard.Unlock(); s_update_main_frame_event.Wait(); - host_identity_guard.m_lock.lock(); + host_identity_guard.Lock(); Core::HostDispatchJobs(); } s_game_metadata_is_valid = false; Core::Shutdown(); - host_identity_guard.m_lock.unlock(); + host_identity_guard.Unlock(); env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetFinishEmulationActivity()); -- cgit v1.2.3 From 03f2f57edf7ac7340b25c4d603b721ab6910359c Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 11 Jun 2023 13:00:52 +0200 Subject: Android: Add HostThreadLock where necessary --- Source/Android/jni/MainAndroid.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Source/Android/jni/MainAndroid.cpp') diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 0b8a0760ab..90e56822f4 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -489,12 +489,14 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimo JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReloadConfig(JNIEnv*, jclass) { + HostThreadLock guard; SConfig::GetInstance().LoadSettings(); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_UpdateGCAdapterScanThread(JNIEnv*, jclass) { + HostThreadLock guard; if (GCAdapter::UseAdapter()) { GCAdapter::StartScanThread(); @@ -507,6 +509,9 @@ Java_org_dolphinemu_dolphinemu_NativeLibrary_UpdateGCAdapterScanThread(JNIEnv*, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Initialize(JNIEnv*, jclass) { + // InitControllers ends up calling config code, and some config callbacks use RunAsCPUThread + HostThreadLock guard; + UICommon::CreateDirectories(); Common::RegisterMsgAlertHandler(&MsgAlert); Common::AndroidSetReportHandler(&ReportSend); @@ -621,6 +626,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RunSystemMen JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ChangeDisc(JNIEnv* env, jclass, jstring jFile) { + HostThreadLock guard; const std::string path = GetJString(env, jFile); __android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Change Disc: %s", path.c_str()); Core::RunAsCPUThread([&path] { Core::System::GetInstance().GetDVDInterface().ChangeDisc(path); }); -- cgit v1.2.3