diff --git a/src/core/libraries/avplayer/avplayer.h b/src/core/libraries/avplayer/avplayer.h index 360f06b6..98e93207 100644 --- a/src/core/libraries/avplayer/avplayer.h +++ b/src/core/libraries/avplayer/avplayer.h @@ -161,7 +161,20 @@ struct SceAvPlayerFileReplacement { SceAvPlayerSizeFile size; }; -typedef void PS4_SYSV_ABI (*SceAvPlayerEventCallback)(void* p, s32 event, s32 src_id, void* data); +enum SceAvPlayerEvents { + SCE_AVPLAYER_STATE_STOP = 0x01, + SCE_AVPLAYER_STATE_READY = 0x02, + SCE_AVPLAYER_STATE_PLAY = 0x03, + SCE_AVPLAYER_STATE_PAUSE = 0x04, + SCE_AVPLAYER_STATE_BUFFERING = 0x05, + SCE_AVPLAYER_TIMED_TEXT_DELIVERY = 0x10, + SCE_AVPLAYER_WARNING_ID = 0x20, + SCE_AVPLAYER_ENCRYPTION = 0x30, + SCE_AVPLAYER_DRM_ERROR = 0x40 +}; + +typedef void PS4_SYSV_ABI (*SceAvPlayerEventCallback)(void* p, SceAvPlayerEvents event, s32 src_id, + void* data); struct SceAvPlayerEventReplacement { void* object_ptr; @@ -275,18 +288,6 @@ enum SceAvPlayerAvSyncMode { typedef int PS4_SYSV_ABI (*SceAvPlayerLogCallback)(void* p, const char* format, va_list args); -enum SceAvPlayerEvents { - SCE_AVPLAYER_STATE_STOP = 0x01, - SCE_AVPLAYER_STATE_READY = 0x02, - SCE_AVPLAYER_STATE_PLAY = 0x03, - SCE_AVPLAYER_STATE_PAUSE = 0x04, - SCE_AVPLAYER_STATE_BUFFERING = 0x05, - SCE_AVPLAYER_TIMED_TEXT_DELIVERY = 0x10, - SCE_AVPLAYER_WARNING_ID = 0x20, - SCE_AVPLAYER_ENCRYPTION = 0x30, - SCE_AVPLAYER_DRM_ERROR = 0x40 -}; - void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::AvPlayer diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index 654e0483..c4d666fc 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -5,10 +5,11 @@ #include "avplayer_source.h" #include "avplayer_state.h" +#include "common/singleton.h" #include "common/thread.h" - #include "core/libraries/error_codes.h" #include "core/libraries/kernel/time_management.h" +#include "core/linker.h" #include @@ -16,8 +17,8 @@ namespace Libraries::AvPlayer { using namespace Kernel; -void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_id, s32 source_id, - void* event_data) { +void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, SceAvPlayerEvents event_id, + s32 source_id, void* event_data) { auto const self = reinterpret_cast(opaque); if (event_id == SCE_AVPLAYER_STATE_READY) { @@ -90,7 +91,8 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i const auto callback = self->m_event_replacement.event_callback; const auto ptr = self->m_event_replacement.object_ptr; if (callback != nullptr) { - callback(ptr, event_id, 0, event_data); + auto* linker = Common::Singleton::Instance(); + linker->ExecuteGuest(callback, ptr, event_id, 0, event_data); } } @@ -365,7 +367,8 @@ void AvPlayerState::EmitEvent(SceAvPlayerEvents event_id, void* event_data) { const auto callback = m_init_data.event_replacement.event_callback; if (callback) { const auto ptr = m_init_data.event_replacement.object_ptr; - callback(ptr, event_id, 0, event_data); + auto* linker = Common::Singleton::Instance(); + linker->ExecuteGuest(callback, ptr, event_id, 0, event_data); } } diff --git a/src/core/libraries/avplayer/avplayer_state.h b/src/core/libraries/avplayer/avplayer_state.h index 7a15eaf8..f50d1bc1 100644 --- a/src/core/libraries/avplayer/avplayer_state.h +++ b/src/core/libraries/avplayer/avplayer_state.h @@ -39,8 +39,8 @@ public: private: // Event Replacement - static void PS4_SYSV_ABI AutoPlayEventCallback(void* handle, s32 event_id, s32 source_id, - void* event_data); + static void PS4_SYSV_ABI AutoPlayEventCallback(void* handle, SceAvPlayerEvents event_id, + s32 source_id, void* event_data); void OnWarning(u32 id) override; void OnError() override; diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 2a44f853..b7a8f153 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -6,13 +6,11 @@ #include #include "common/alignment.h" -#include "common/arch.h" #include "common/assert.h" #include "common/error.h" #include "common/logging/log.h" #include "common/singleton.h" #include "common/thread.h" -#include "core/cpu_patches.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/thread_management.h" @@ -991,16 +989,12 @@ static void cleanup_thread(void* arg) { static void* run_thread(void* arg) { auto* thread = static_cast(arg); Common::SetCurrentThreadName(thread->name.c_str()); -#ifdef ARCH_X86_64 - Core::InitializeThreadPatchStack(); -#endif auto* linker = Common::Singleton::Instance(); - linker->InitTlsForThread(false); void* ret = nullptr; g_pthread_self = thread; pthread_cleanup_push(cleanup_thread, thread); thread->is_started = true; - ret = thread->entry(thread->arg); + ret = linker->ExecuteGuest(thread->entry, thread->arg); pthread_cleanup_pop(1); return ret; } diff --git a/src/core/libraries/network/net_ctl_obj.cpp b/src/core/libraries/network/net_ctl_obj.cpp index 935a700c..8193c684 100644 --- a/src/core/libraries/network/net_ctl_obj.cpp +++ b/src/core/libraries/network/net_ctl_obj.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/singleton.h" +#include "core/linker.h" #include "net_ctl_codes.h" #include "net_ctl_obj.h" @@ -57,18 +59,22 @@ s32 Libraries::NetCtl::NetCtlInternal::registerNpToolkitCallback( void Libraries::NetCtl::NetCtlInternal::checkCallback() { std::unique_lock lock{m_mutex}; + auto* linker = Common::Singleton::Instance(); for (auto& callback : callbacks) { if (callback.func != nullptr) { - callback.func(ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, callback.arg); + linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, + callback.arg); } } } void Libraries::NetCtl::NetCtlInternal::checkNpToolkitCallback() { std::unique_lock lock{m_mutex}; + auto* linker = Common::Singleton::Instance(); for (auto& callback : nptoolCallbacks) { if (callback.func != nullptr) { - callback.func(ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, callback.arg); + linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, + callback.arg); } } } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index e8aab673..4e4fa28d 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -90,11 +90,8 @@ void Linker::Execute() { // Init primary thread. Common::SetCurrentThreadName("GAME_MainThread"); -#ifdef ARCH_X86_64 - InitializeThreadPatchStack(); -#endif Libraries::Kernel::pthreadInitSelfMainThread(); - InitTlsForThread(true); + EnsureThreadInitialized(true); // Start shared library modules for (auto& m : m_modules) { @@ -335,6 +332,17 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { return addr + offset; } +thread_local std::once_flag init_tls_flag; + +void Linker::EnsureThreadInitialized(bool is_primary) { + std::call_once(init_tls_flag, [this, is_primary] { +#ifdef ARCH_X86_64 + InitializeThreadPatchStack(); +#endif + InitTlsForThread(is_primary); + }); +} + void Linker::InitTlsForThread(bool is_primary) { static constexpr size_t TcbSize = 0x40; static constexpr size_t TlsAllocAlign = 0x20; diff --git a/src/core/linker.h b/src/core/linker.h index ed1fe400..18454f60 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -98,7 +98,6 @@ public: } void* TlsGetAddr(u64 module_index, u64 offset); - void InitTlsForThread(bool is_primary = false); s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false); Module* FindByAddress(VAddr address); @@ -109,8 +108,17 @@ public: void Execute(); void DebugDump(); + template + ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) { + // Make sure TLS is initialized for the thread before entering guest. + EnsureThreadInitialized(); + return func(std::forward(args)...); + } + private: const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); + void EnsureThreadInitialized(bool is_primary = false); + void InitTlsForThread(bool is_primary); MemoryManager* memory; std::mutex mutex; diff --git a/src/core/module.cpp b/src/core/module.cpp index ce2f9d3a..e62c5778 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -9,6 +9,7 @@ #include "common/string_util.h" #include "core/aerolib/aerolib.h" #include "core/cpu_patches.h" +#include "core/linker.h" #include "core/loader/dwarf.h" #include "core/memory.h" #include "core/module.h" @@ -69,8 +70,9 @@ Module::~Module() = default; s32 Module::Start(size_t args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", name); + auto* linker = Common::Singleton::Instance(); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); - return reinterpret_cast(addr)(args, argp, param); + return linker->ExecuteGuest(reinterpret_cast(addr), args, argp, param); } void Module::LoadModuleToMemory(u32& max_tls_index) {