Android: Move host thread lock to a separate file

This commit is contained in:
JosJuice 2023-06-11 12:06:23 +02:00
parent c8559a7933
commit 5524042922
4 changed files with 55 additions and 39 deletions

View file

@ -10,6 +10,8 @@ add_library(main SHARED
GameList/GameFile.cpp GameList/GameFile.cpp
GameList/GameFile.h GameList/GameFile.h
GameList/GameFileCache.cpp GameList/GameFileCache.cpp
Host.cpp
Host.h
InfinityConfig.cpp InfinityConfig.cpp
Input/Control.cpp Input/Control.cpp
Input/Control.h Input/Control.h

View file

@ -0,0 +1,8 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "jni/Host.h"
#include <mutex>
std::mutex HostThreadLock::s_host_identity_mutex;

24
Source/Android/jni/Host.h Normal file
View file

@ -0,0 +1,24 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <mutex>
#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<std::mutex> 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(); }
};

View file

@ -63,6 +63,7 @@
#include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h" #include "jni/AndroidCommon/IDCache.h"
#include "jni/Host.h"
namespace namespace
{ {
@ -70,25 +71,6 @@ constexpr char DOLPHIN_TAG[] = "DolphinEmuNative";
ANativeWindow* s_surf; 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 <typename T>
struct HostThreadWrapper
{
T lock;
explicit HostThreadWrapper(auto&&... args) : lock(std::forward<decltype(args)>(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; Common::Event s_update_main_frame_event;
// This exists to prevent surfaces from being destroyed during the boot process, // 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*, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_UnPauseEmulation(JNIEnv*,
jclass) jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
Core::SetState(Core::State::Running); Core::SetState(Core::State::Running);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulation(JNIEnv*, jclass) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulation(JNIEnv*, jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
Core::SetState(Core::State::Paused); Core::SetState(Core::State::Paused);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv*, jclass) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv*, jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
Core::Stop(); Core::Stop();
// Kick the waiting event // 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) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv*, jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
Core::SaveScreenShot(); Core::SaveScreenShot();
} }
@ -332,7 +314,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JN
jint slot, jint slot,
jboolean wait) jboolean wait)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
State::Save(slot, wait); State::Save(slot, wait);
} }
@ -340,21 +322,21 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveStateAs(
jstring path, jstring path,
jboolean wait) jboolean wait)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
State::SaveAs(GetJString(env, path), wait); State::SaveAs(GetJString(env, path), wait);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv*, jclass, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv*, jclass,
jint slot) jint slot)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
State::Load(slot); State::Load(slot);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(JNIEnv* env, jclass, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(JNIEnv* env, jclass,
jstring path) jstring path)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
State::LoadAs(GetJString(env, path)); 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( JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(
JNIEnv* env, jclass, jstring jDirectory) JNIEnv* env, jclass, jstring jDirectory)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
UICommon::SetUserDirectory(GetJString(env, jDirectory)); 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( JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetCacheDirectory(
JNIEnv* env, jclass, jstring jDirectory) JNIEnv* env, jclass, jstring jDirectory)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
File::SetUserPath(D_CACHE_IDX, GetJString(env, jDirectory)); 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, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv*, jclass,
jboolean enable) jboolean enable)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
Core::SetState(Core::State::Paused); Core::SetState(Core::State::Paused);
auto& jit_interface = Core::System::GetInstance().GetJitInterface(); auto& jit_interface = Core::System::GetInstance().GetJitInterface();
jit_interface.ClearCache(); 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*, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv*,
jclass) jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
std::string filename = File::GetUserPath(D_DUMP_IDX) + "Debug/profiler.txt"; std::string filename = File::GetUserPath(D_DUMP_IDX) + "Debug/profiler.txt";
File::CreateFullPath(filename); File::CreateFullPath(filename);
auto& jit_interface = Core::System::GetInstance().GetJitInterface(); 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, // 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. // so pause emulation until we get a valid surface again. EmulationFragment handles resuming.
HostThreadWrapper<std::unique_lock<std::mutex>> host_identity_guard(s_host_identity_lock); HostThreadLock host_identity_guard;
while (s_is_booting.IsSet()) while (s_is_booting.IsSet())
{ {
// Need to wait for boot to finish before we can pause // 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)); 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) 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) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv*, jclass)
{ {
HostThreadWrapper<std::lock_guard<std::mutex>> guard(s_host_identity_lock); HostThreadLock guard;
WiimoteReal::Refresh(); WiimoteReal::Refresh();
} }
@ -559,7 +541,7 @@ static float GetRenderSurfaceScale(JNIEnv* env)
static void Run(JNIEnv* env, std::unique_ptr<BootParameters>&& boot, bool riivolution) static void Run(JNIEnv* env, std::unique_ptr<BootParameters>&& boot, bool riivolution)
{ {
HostThreadWrapper<std::unique_lock<std::mutex>> host_identity_guard(s_host_identity_lock); HostThreadLock host_identity_guard;
if (riivolution && std::holds_alternative<BootParameters::Disc>(boot->parameters)) if (riivolution && std::holds_alternative<BootParameters::Disc>(boot->parameters))
{ {
@ -590,15 +572,15 @@ static void Run(JNIEnv* env, std::unique_ptr<BootParameters>&& boot, bool riivol
while (Core::IsRunning()) while (Core::IsRunning())
{ {
host_identity_guard.lock.unlock(); host_identity_guard.m_lock.unlock();
s_update_main_frame_event.Wait(); s_update_main_frame_event.Wait();
host_identity_guard.lock.lock(); host_identity_guard.m_lock.lock();
Core::HostDispatchJobs(); Core::HostDispatchJobs();
} }
s_game_metadata_is_valid = false; s_game_metadata_is_valid = false;
Core::Shutdown(); Core::Shutdown();
host_identity_guard.lock.unlock(); host_identity_guard.m_lock.unlock();
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
IDCache::GetFinishEmulationActivity()); IDCache::GetFinishEmulationActivity());