diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp index 60d68c4f..3f4b2d0d 100644 --- a/src/core/libraries/avplayer/avplayer.cpp +++ b/src/core/libraries/avplayer/avplayer.cpp @@ -1,18 +1,14 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer.h" - -#include "avplayer_impl.h" #include "common/logging/log.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_impl.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/thread_management.h" #include "core/libraries/libs.h" namespace Libraries::AvPlayer { -using namespace Kernel; - s32 PS4_SYSV_ABI sceAvPlayerAddSource(SceAvPlayerHandle handle, const char* filename) { LOG_TRACE(Lib_AvPlayer, "filename = {}", filename); if (handle == nullptr) { diff --git a/src/core/libraries/avplayer/avplayer.h b/src/core/libraries/avplayer/avplayer.h index 98e93207..9f100bef 100644 --- a/src/core/libraries/avplayer/avplayer.h +++ b/src/core/libraries/avplayer/avplayer.h @@ -5,8 +5,8 @@ #include "common/types.h" -#include // va_list -#include // size_t +#include // va_list +#include // size_t namespace Core::Loader { class SymbolsResolver; diff --git a/src/core/libraries/avplayer/avplayer_common.cpp b/src/core/libraries/avplayer/avplayer_common.cpp index 306603e2..805920a3 100644 --- a/src/core/libraries/avplayer/avplayer_common.cpp +++ b/src/core/libraries/avplayer/avplayer_common.cpp @@ -1,24 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer.h" -#include "avplayer_common.h" +#include // std::equal +#include // std::tolower -#include // std::equal -#include // std::tolower -#include // std::string_view +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_common.h" namespace Libraries::AvPlayer { -using namespace Kernel; - -static bool ichar_equals(char a, char b) { - return std::tolower(static_cast(a)) == - std::tolower(static_cast(b)); -} - static bool iequals(std::string_view l, std::string_view r) { - return std::ranges::equal(l, r, ichar_equals); + return std::ranges::equal(l, r, [](u8 a, u8 b) { return std::tolower(a) == std::tolower(b); }); } SceAvPlayerSourceType GetSourceType(std::string_view path) { diff --git a/src/core/libraries/avplayer/avplayer_common.h b/src/core/libraries/avplayer/avplayer_common.h index a53696ec..dc3cd787 100644 --- a/src/core/libraries/avplayer/avplayer_common.h +++ b/src/core/libraries/avplayer/avplayer_common.h @@ -3,16 +3,14 @@ #pragma once -#include "avplayer.h" - -#include "common/assert.h" -#include "common/logging/log.h" -#include "core/libraries/kernel/thread_management.h" - +#include #include +#include #include #include +#include "core/libraries/avplayer/avplayer.h" + #define AVPLAYER_IS_ERROR(x) ((x) < 0) namespace Libraries::AvPlayer { diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.cpp b/src/core/libraries/avplayer/avplayer_file_streamer.cpp index c7bd5b5d..3323ee9b 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.cpp +++ b/src/core/libraries/avplayer/avplayer_file_streamer.cpp @@ -1,20 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer_file_streamer.h" - -#include "avplayer_common.h" - +#include // std::max, std::min #include +#include "core/libraries/avplayer/avplayer_file_streamer.h" extern "C" { #include #include } -#include // std::max, std::min - -#define AVPLAYER_AVIO_BUFFER_SIZE 4096 +constexpr u32 AVPLAYER_AVIO_BUFFER_SIZE = 4096; namespace Libraries::AvPlayer { diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.h b/src/core/libraries/avplayer/avplayer_file_streamer.h index 034e40dd..bc096bcc 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.h +++ b/src/core/libraries/avplayer/avplayer_file_streamer.h @@ -3,11 +3,9 @@ #pragma once -#include "avplayer.h" -#include "avplayer_data_streamer.h" - #include -#include +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_data_streamer.h" struct AVIOContext; diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp index 1c414c96..0f39acfd 100644 --- a/src/core/libraries/avplayer/avplayer_impl.cpp +++ b/src/core/libraries/avplayer/avplayer_impl.cpp @@ -1,17 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer_common.h" -#include "avplayer_file_streamer.h" -#include "avplayer_impl.h" - -#include "common/logging/log.h" -#include "common/singleton.h" +#include "core/libraries/avplayer/avplayer_common.h" +#include "core/libraries/avplayer/avplayer_impl.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" -#include "core/linker.h" - -using namespace Libraries::Kernel; +#include "core/tls.h" namespace Libraries::AvPlayer { @@ -19,32 +12,28 @@ void* PS4_SYSV_ABI AvPlayer::Allocate(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(allocate, ptr, alignment, size); + return Core::ExecuteGuest(allocate, ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::Deallocate(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(deallocate, ptr, memory); + return Core::ExecuteGuest(deallocate, ptr, memory); } void* PS4_SYSV_ABI AvPlayer::AllocateTexture(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(allocate, ptr, alignment, size); + return Core::ExecuteGuest(allocate, ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::DeallocateTexture(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(deallocate, ptr, memory); + return Core::ExecuteGuest(deallocate, ptr, memory); } int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { @@ -53,8 +42,7 @@ int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { const auto open = self->m_init_data_original.file_replacement.open; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(open, ptr, filename); + return Core::ExecuteGuest(open, ptr, filename); } int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { @@ -63,8 +51,7 @@ int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { const auto close = self->m_init_data_original.file_replacement.close; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(close, ptr); + return Core::ExecuteGuest(close, ptr); } int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position, u32 length) { @@ -73,8 +60,7 @@ int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position const auto read_offset = self->m_init_data_original.file_replacement.readOffset; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(read_offset, ptr, buffer, position, length); + return Core::ExecuteGuest(read_offset, ptr, buffer, position, length); } u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { @@ -83,8 +69,7 @@ u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { const auto size = self->m_init_data_original.file_replacement.size; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - const auto* linker = Common::Singleton::Instance(); - return linker->ExecuteGuest(size, ptr); + return Core::ExecuteGuest(size, ptr); } SceAvPlayerInitData AvPlayer::StubInitData(const SceAvPlayerInitData& data) { diff --git a/src/core/libraries/avplayer/avplayer_impl.h b/src/core/libraries/avplayer/avplayer_impl.h index d7f28094..984d8149 100644 --- a/src/core/libraries/avplayer/avplayer_impl.h +++ b/src/core/libraries/avplayer/avplayer_impl.h @@ -3,11 +3,8 @@ #pragma once -#include "avplayer.h" -#include "avplayer_data_streamer.h" -#include "avplayer_state.h" - -#include "core/libraries/kernel/thread_management.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_state.h" #include @@ -17,7 +14,6 @@ extern "C" { } #include -#include namespace Libraries::AvPlayer { diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 19925ba0..76edc1dd 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -1,16 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer_source.h" - -#include "avplayer_file_streamer.h" - #include "common/alignment.h" #include "common/singleton.h" #include "common/thread.h" - #include "core/file_sys/fs.h" -#include "core/libraries/kernel/time_management.h" +#include "core/libraries/avplayer/avplayer_file_streamer.h" +#include "core/libraries/avplayer/avplayer_source.h" #include @@ -35,8 +31,6 @@ av_always_inline std::string av_err2string(int errnum) { namespace Libraries::AvPlayer { -using namespace Kernel; - AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, bool use_vdec2) : m_state(state), m_use_vdec2(use_vdec2) {} diff --git a/src/core/libraries/avplayer/avplayer_source.h b/src/core/libraries/avplayer/avplayer_source.h index 505d7446..b647600c 100644 --- a/src/core/libraries/avplayer/avplayer_source.h +++ b/src/core/libraries/avplayer/avplayer_source.h @@ -3,20 +3,18 @@ #pragma once -#include "avplayer.h" -#include "avplayer_common.h" -#include "avplayer_data_streamer.h" - -#include "common/polyfill_thread.h" -#include "common/types.h" -#include "core/libraries/kernel/thread_management.h" - #include #include #include #include #include -#include +#include + +#include "common/assert.h" +#include "common/polyfill_thread.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_common.h" +#include "core/libraries/avplayer/avplayer_data_streamer.h" struct AVCodecContext; struct AVFormatContext; @@ -139,8 +137,6 @@ public: bool IsActive(); private: - using ScePthread = Kernel::ScePthread; - static void ReleaseAVPacket(AVPacket* packet); static void ReleaseAVFrame(AVFrame* frame); static void ReleaseAVCodecContext(AVCodecContext* context); diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index e6610067..ce9629c1 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -1,22 +1,17 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "avplayer_file_streamer.h" -#include "avplayer_source.h" -#include "avplayer_state.h" - -#include "common/singleton.h" +#include "common/logging/log.h" #include "common/thread.h" +#include "core/libraries/avplayer/avplayer_source.h" +#include "core/libraries/avplayer/avplayer_state.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/time_management.h" -#include "core/linker.h" +#include "core/tls.h" #include namespace Libraries::AvPlayer { -using namespace Kernel; - void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, SceAvPlayerEvents event_id, s32 source_id, void* event_data) { auto const self = reinterpret_cast(opaque); @@ -96,8 +91,7 @@ void AvPlayerState::DefaultEventCallback(void* opaque, SceAvPlayerEvents event_i const auto callback = self->m_event_replacement.event_callback; const auto ptr = self->m_event_replacement.object_ptr; if (callback != nullptr) { - const auto* linker = Common::Singleton::Instance(); - linker->ExecuteGuest(callback, ptr, event_id, 0, event_data); + Core::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 d106127e..8f8480ef 100644 --- a/src/core/libraries/avplayer/avplayer_state.h +++ b/src/core/libraries/avplayer/avplayer_state.h @@ -3,17 +3,14 @@ #pragma once -#include "avplayer.h" -#include "avplayer_data_streamer.h" -#include "avplayer_source.h" - -#include "common/polyfill_thread.h" -#include "core/libraries/kernel/thread_management.h" - #include #include #include +#include "common/polyfill_thread.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/avplayer/avplayer_source.h" + namespace Libraries::AvPlayer { class Stream; diff --git a/src/core/libraries/fiber/fiber.cpp b/src/core/libraries/fiber/fiber.cpp index a0bfd685..92bf894b 100644 --- a/src/core/libraries/fiber/fiber.cpp +++ b/src/core/libraries/fiber/fiber.cpp @@ -4,10 +4,9 @@ #include "fiber.h" #include "common/logging/log.h" -#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "core/linker.h" +#include "core/tls.h" #ifdef _WIN64 #include @@ -31,9 +30,7 @@ void FiberEntry(void* param) { argRun = *fiber->pArgRun; } - const auto* linker = Common::Singleton::Instance(); - linker->ExecuteGuest(fiber->entry, fiber->argOnInitialize, argRun); - + Core::ExecuteGuest(fiber->entry, fiber->argOnInitialize, argRun); UNREACHABLE(); } @@ -281,4 +278,4 @@ void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("JzyT91ucGDc", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberRename); } -} // namespace Libraries::Fiber \ No newline at end of file +} // namespace Libraries::Fiber diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index bba45d0f..de64de5f 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -11,7 +11,7 @@ #include "common/singleton.h" #include "core/libraries/ime/ime_dialog.h" #include "core/libraries/ime/ime_dialog_ui.h" -#include "core/linker.h" +#include "core/tls.h" #include "imgui/imgui_std.h" using namespace ImGui; @@ -124,9 +124,8 @@ bool ImeDialogState::CallTextFilter() { return false; } - auto* linker = Common::Singleton::Instance(); int ret = - linker->ExecuteGuest(text_filter, out_text, &out_text_length, src_text, src_text_length); + Core::ExecuteGuest(text_filter, out_text, &out_text_length, src_text, src_text_length); if (ret != 0) { return false; @@ -147,15 +146,12 @@ bool ImeDialogState::CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* return true; } - auto* linker = Common::Singleton::Instance(); - int ret = linker->ExecuteGuest(keyboard_filter, src_keycode, out_keycode, out_status, nullptr); - + int ret = Core::ExecuteGuest(keyboard_filter, src_keycode, out_keycode, out_status, nullptr); return ret == 0; } bool ImeDialogState::ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, std::size_t utf8_text_len) { - std::fill(utf8_text, utf8_text + utf8_text_len, '\0'); const ImWchar* orbis_text_ptr = reinterpret_cast(orbis_text); ImTextStrToUtf8(utf8_text, utf8_text_len, orbis_text_ptr, orbis_text_ptr + orbis_text_len); @@ -165,7 +161,6 @@ bool ImeDialogState::ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t bool ImeDialogState::ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_text_len, char16_t* orbis_text, std::size_t orbis_text_len) { - std::fill(orbis_text, orbis_text + orbis_text_len, u'\0'); ImTextStrFromUtf8(reinterpret_cast(orbis_text), orbis_text_len, utf8_text, nullptr); @@ -387,4 +382,4 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { return 0; } -} // namespace Libraries::ImeDialog \ No newline at end of file +} // namespace Libraries::ImeDialog diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 695ad038..3dd850ad 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -13,7 +13,7 @@ namespace Libraries::Kernel { -std::vector GetDirectoryEntries(const std::filesystem::path& path) { +auto GetDirectoryEntries(const std::filesystem::path& path) { std::vector files; for (const auto& entry : std::filesystem::directory_iterator(path)) { auto& dir_entry = files.emplace_back(); diff --git a/src/core/libraries/kernel/file_system.h b/src/core/libraries/kernel/file_system.h index 1286783f..67bf579d 100644 --- a/src/core/libraries/kernel/file_system.h +++ b/src/core/libraries/kernel/file_system.h @@ -65,11 +65,6 @@ constexpr int ORBIS_KERNEL_O_DSYNC = 0x1000; constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000; constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000; -int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, /* SceKernelMode*/ u16 mode); - -int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode); -s64 PS4_SYSV_ABI lseek(int d, s64 offset, int whence); - void RegisterFileSystem(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 223034e9..09bb16c1 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -29,7 +29,6 @@ #include #include #else -#include #ifdef __APPLE__ #include #endif diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 7a81ac79..3ca10cf0 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -7,6 +7,20 @@ namespace Libraries::Kernel { +int PS4_SYSV_ABI posix_pthread_attr_init(PthreadAttrT* attr); + +int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAttrT* attr, + PthreadEntryFunc start_routine, void* arg, + const char* name); + +PthreadT LaunchThread(PthreadEntryFunc start_routine, void* arg, const char* name) { + PthreadT thread{}; + PthreadAttrT attr{}; + posix_pthread_attr_init(&attr); + posix_pthread_create_name_np(&thread, &attr, start_routine, arg, name); + return thread; +} + void RegisterThreads(Core::Loader::SymbolsResolver* sym) { RegisterMutex(sym); RegisterCond(sym); @@ -14,6 +28,8 @@ void RegisterThreads(Core::Loader::SymbolsResolver* sym) { RegisterSemaphore(sym); RegisterSpec(sym); RegisterThreadAttr(sym); + RegisterThread(sym); + RegisterRtld(sym); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index 125de720..feb60fc2 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -3,223 +3,15 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include - -#include "common/types.h" - -#define ORBIS_PTHREAD_MUTEX_ADAPTIVE_INITIALIZER (reinterpret_cast(1)) +#include "core/libraries/kernel/threads/threads.h" namespace Core::Loader { class SymbolsResolver; } namespace Libraries::Kernel { -constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700; -constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256; -constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767; -constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF; -constexpr int ORBIS_PTHREAD_MUTEX_ERRORCHECK = 1; -constexpr int ORBIS_PTHREAD_MUTEX_RECURSIVE = 2; -constexpr int ORBIS_PTHREAD_MUTEX_NORMAL = 3; -constexpr int ORBIS_PTHREAD_MUTEX_ADAPTIVE = 4; - -struct PthreadInternal; -struct PthreadAttrInternal; -struct PthreadMutexInternal; -struct PthreadMutexattrInternal; -struct PthreadCondInternal; -struct PthreadCondAttrInternal; -struct PthreadRwInternal; -struct PthreadRwLockAttrInternal; -class PthreadKeys; - -using SceKernelSchedParam = ::sched_param; -using ScePthread = PthreadInternal*; -using ScePthreadAttr = PthreadAttrInternal*; -using ScePthreadMutex = PthreadMutexInternal*; -using ScePthreadMutexattr = PthreadMutexattrInternal*; -using ScePthreadCond = PthreadCondInternal*; -using ScePthreadCondattr = PthreadCondAttrInternal*; -using OrbisPthreadRwlock = PthreadRwInternal*; -using OrbisPthreadRwlockattr = PthreadRwLockAttrInternal*; -using OrbisPthreadKey = u32; - -using PthreadKeyDestructor = PS4_SYSV_ABI void (*)(void*); -using PthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*); - -struct PthreadInternal { - u8 reserved[4096]; - std::string name; - pthread_t pth; - ScePthreadAttr attr; - PthreadEntryFunc entry; - void* arg; - std::atomic_bool is_started; - std::atomic_bool is_detached; - std::atomic_bool is_almost_done; - std::atomic_bool is_free; - using Destructor = std::pair; - std::vector key_destructors; - int prio; -}; - -struct PthreadAttrInternal { - u8 reserved[64]; - u64 affinity; - size_t guard_size; - int policy; - bool detached; - pthread_attr_t pth_attr; -}; - -struct PthreadMutexInternal { - u8 reserved[256]; - std::string name; - pthread_mutex_t pth_mutex; -}; - -struct PthreadMutexattrInternal { - u8 reserved[64]; - pthread_mutexattr_t pth_mutex_attr; - int pprotocol; -}; - -struct PthreadCondInternal { - u8 reserved[256]; - std::string name; - pthread_cond_t cond; -}; - -struct PthreadCondAttrInternal { - u8 reserved[64]; - pthread_condattr_t cond_attr; - clockid_t clock; -}; - -struct PthreadRwLockAttrInternal { - u8 reserved[64]; - pthread_rwlockattr_t attr_rwlock; - int type; -}; - -struct PthreadRwInternal { - pthread_rwlock_t pth_rwlock; - std::string name; -}; - -struct PthreadSemInternal { - std::counting_semaphore semaphore; - std::atomic value; -}; - -class PThreadPool { -public: - ScePthread Create(const char* name); - -private: - std::vector m_threads; - std::mutex m_mutex; -}; - -class PThreadCxt { -public: - ScePthreadMutexattr* getDefaultMutexattr() { - return &m_default_mutexattr; - } - void setDefaultMutexattr(ScePthreadMutexattr attr) { - m_default_mutexattr = attr; - } - ScePthreadMutexattr* getAdaptiveMutexattr() { - return &m_adaptive_mutexattr; - } - void setAdaptiveMutexattr(ScePthreadMutexattr attr) { - m_adaptive_mutexattr = attr; - } - ScePthreadCondattr* getDefaultCondattr() { - return &m_default_condattr; - } - void setDefaultCondattr(ScePthreadCondattr attr) { - m_default_condattr = attr; - } - ScePthreadAttr* GetDefaultAttr() { - return &m_default_attr; - } - void SetDefaultAttr(ScePthreadAttr attr) { - m_default_attr = attr; - } - PThreadPool* GetPthreadPool() { - return m_pthread_pool; - } - void SetPthreadPool(PThreadPool* pool) { - m_pthread_pool = pool; - } - OrbisPthreadRwlockattr* getDefaultRwattr() { - return &m_default_Rwattr; - } - void setDefaultRwattr(OrbisPthreadRwlockattr attr) { - m_default_Rwattr = attr; - } - -private: - ScePthreadMutexattr m_default_mutexattr = nullptr; - ScePthreadMutexattr m_adaptive_mutexattr = nullptr; - ScePthreadCondattr m_default_condattr = nullptr; - ScePthreadAttr m_default_attr = nullptr; - PThreadPool* m_pthread_pool = nullptr; - OrbisPthreadRwlockattr m_default_Rwattr = nullptr; -}; - -void init_pthreads(); -void pthreadInitSelfMainThread(); - -int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr); -int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate); -int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched); -int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr, - const SceKernelSchedParam* param); -int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy); -ScePthread PS4_SYSV_ABI scePthreadSelf(); -int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, - const /*SceKernelCpumask*/ u64 mask); -int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask); -int PS4_SYSV_ABI scePthreadGetaffinity(ScePthread thread, /*SceKernelCpumask*/ u64* mask); -int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, - PthreadEntryFunc start_routine, void* arg, const char* name); - -int PS4_SYSV_ABI scePthreadSetprio(ScePthread thread, int prio); - -/*** - * Mutex calls - */ -int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, - const char* name); -int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr); -int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type); -int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol); -int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex); -int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex); -/**** - * Cond calls - */ -int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr, - const char* name); -int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr); -int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond); -int PS4_SYSV_ABI scePthreadCondWait(ScePthreadCond* cond, ScePthreadMutex* mutex); -/**** - * Posix calls - */ -int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr); -int PS4_SYSV_ABI posix_pthread_mutex_lock(ScePthreadMutex* mutex); -int PS4_SYSV_ABI posix_pthread_mutex_unlock(ScePthreadMutex* mutex); -int PS4_SYSV_ABI posix_pthread_cond_broadcast(ScePthreadCond* cond); +PthreadT LaunchThread(PthreadEntryFunc start_routine, void* arg, const char* name); void RegisterThreads(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/libraries/kernel/threads/thr_attr.cpp b/src/core/libraries/kernel/threads/thr_attr.cpp index ec6941e7..b06e8491 100644 --- a/src/core/libraries/kernel/threads/thr_attr.cpp +++ b/src/core/libraries/kernel/threads/thr_attr.cpp @@ -224,6 +224,7 @@ int PS4_SYSV_ABI posix_pthread_attr_get_np(PthreadT pthread, PthreadAttrT* dstat if (True(pthread->flags & ThreadFlags::Detached)) { attr.flags |= PthreadAttrFlags::Detached; } + pthread->lock->unlock(); if (ret == 0) { memcpy(dst, &attr, sizeof(PthreadAttr)); } diff --git a/src/core/libraries/kernel/threads/thr_cond.cpp b/src/core/libraries/kernel/threads/thr_cond.cpp index d41081b9..5eae613f 100644 --- a/src/core/libraries/kernel/threads/thr_cond.cpp +++ b/src/core/libraries/kernel/threads/thr_cond.cpp @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later - +#pragma clang optimize off #include #include "core/libraries/error_codes.h" #include "core/libraries/kernel/libkernel.h" @@ -68,6 +68,7 @@ static int InitStatic(Pthread* thread, PthreadCondT* cond) { } else if (cvp == THR_COND_DESTROYED) { \ return POSIX_EINVAL; \ } \ + cvp = *cond; \ } int PS4_SYSV_ABI posix_pthread_cond_init(PthreadCondT* cond, const PthreadCondAttrT* cond_attr) { diff --git a/src/core/libraries/kernel/threads/thr_create.cpp b/src/core/libraries/kernel/threads/thr_create.cpp index 3dfcaff8..ef4a679c 100644 --- a/src/core/libraries/kernel/threads/thr_create.cpp +++ b/src/core/libraries/kernel/threads/thr_create.cpp @@ -9,22 +9,188 @@ #include "core/libraries/kernel/threads/thread_state.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" -#include "core/linker.h" #include "core/memory.h" #include namespace Libraries::Kernel { +constexpr int PthreadInheritSched = 4; + constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700; constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256; constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767; extern PthreadAttr PthreadAttrDefault; -using PthreadEntryFunc = void* (*)(void*); +void _thread_cleanupspecific(); -void PS4_SYSV_ABI posix_pthread_exit(void* status); +static void ExitThread() { + Pthread* curthread = g_curthread; + + /* Check if there is thread specific data: */ + if (curthread->specific != nullptr) { + /* Run the thread-specific data destructors: */ + _thread_cleanupspecific(); + } + + auto* thread_state = ThrState::Instance(); + ASSERT(thread_state->active_threads.fetch_sub(1) != 1); + + curthread->lock->lock(); + curthread->state = PthreadState::Dead; + ASSERT(False(curthread->flags & ThreadFlags::NeedSuspend)); + + /* + * Thread was created with initial refcount 1, we drop the + * reference count to allow it to be garbage collected. + */ + curthread->refcount--; + thread_state->TryCollect(curthread, curthread); /* thread lock released */ + + /* + * Kernel will do wakeup at the address, so joiner thread + * will be resumed if it is sleeping at the address. + */ + curthread->tid.store(TidTerminated); + curthread->tid.notify_all(); + + pthread_exit(nullptr); + UNREACHABLE(); + /* Never reach! */ +} + +void PS4_SYSV_ABI posix_pthread_exit(void* status) { + Pthread* curthread = g_curthread; + + /* Check if this thread is already in the process of exiting: */ + ASSERT_MSG(!curthread->cancelling, "Thread {} has called pthread_exit from a destructor", + fmt::ptr(curthread)); + + /* Flag this thread as exiting. */ + curthread->cancelling = 1; + curthread->no_cancel = 1; + curthread->cancel_async = 0; + curthread->cancel_point = 0; + + /* Save the return value: */ + curthread->ret = status; + while (!curthread->cleanup.empty()) { + PthreadCleanup* old = curthread->cleanup.front(); + curthread->cleanup.pop_front(); + old->routine(old->routine_arg); + if (old->onheap) { + free(old); + } + } + + ExitThread(); +} + +static int JoinThread(PthreadT pthread, void** thread_return, const OrbisKernelTimespec* abstime) { + Pthread* curthread = g_curthread; + + if (pthread == nullptr) { + return POSIX_EINVAL; + } + + if (pthread == curthread) { + return POSIX_EDEADLK; + } + + auto* thread_state = ThrState::Instance(); + if (int ret = thread_state->FindThread(pthread, 1); ret != 0) { + return POSIX_ESRCH; + } + + int ret = 0; + if (True(pthread->flags & ThreadFlags::Detached)) { + ret = POSIX_EINVAL; + } else if (pthread->joiner != nullptr) { + /* Multiple joiners are not supported. */ + ret = POSIX_ENOTSUP; + } + if (ret) { + pthread->lock->unlock(); + return ret; + } + /* Set the running thread to be the joiner: */ + pthread->joiner = curthread; + pthread->lock->unlock(); + + const auto backout_join = [](void* arg) { + Pthread* pthread = (Pthread*)arg; + std::scoped_lock lk{*pthread->lock}; + pthread->joiner = nullptr; + }; + + PthreadCleanup cup{backout_join, pthread, 0}; + curthread->cleanup.push_front(&cup); + + //_thr_cancel_enter(curthread); + + const int tid = pthread->tid; + while (pthread->tid.load() != TidTerminated) { + //_thr_testcancel(curthread); + ASSERT(abstime == nullptr); + pthread->tid.wait(tid); + } + + //_thr_cancel_leave(curthread, 0); + curthread->cleanup.pop_front(); + + if (ret == POSIX_ETIMEDOUT) { + backout_join(pthread); + return ret; + } + + void* tmp = pthread->ret; + pthread->lock->lock(); + pthread->flags |= ThreadFlags::Detached; + pthread->joiner = nullptr; + thread_state->TryCollect(curthread, pthread); /* thread lock released */ + if (thread_return != nullptr) { + *thread_return = tmp; + } + + return 0; +} + +int PS4_SYSV_ABI posix_pthread_join(PthreadT pthread, void** thread_return) { + return JoinThread(pthread, thread_return, NULL); +} + +int PS4_SYSV_ABI posix_pthread_timedjoin_np(PthreadT pthread, void** thread_return, + const OrbisKernelTimespec* abstime) { + if (abstime == nullptr || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || + abstime->tv_nsec >= 1000000000) { + return POSIX_EINVAL; + } + + return JoinThread(pthread, thread_return, abstime); +} + +int PS4_SYSV_ABI posix_pthread_detach(PthreadT pthread) { + if (pthread == nullptr) { + return POSIX_EINVAL; + } + + auto* thread_state = ThrState::Instance(); + if (int ret = thread_state->FindThread(pthread, 1); ret != 0) { + return ret; + } + + /* Check if the thread is already detached or has a joiner. */ + if (True(pthread->flags & ThreadFlags::Detached) || (pthread->joiner != NULL)) { + pthread->lock->unlock(); + return POSIX_EINVAL; + } + + /* Flag the thread as detached. */ + pthread->flags |= ThreadFlags::Detached; + thread_state->TryCollect(g_curthread, pthread); /* thread lock released */ + return 0; +} static void RunThread(Pthread* curthread) { g_curthread = curthread; @@ -32,8 +198,7 @@ static void RunThread(Pthread* curthread) { DebugState.AddCurrentThreadToGuestList(); /* Run the current thread's start routine with argument: */ - const auto* linker = Common::Singleton::Instance(); - void* ret = linker->ExecuteGuest(curthread->start_routine, curthread->arg); + void* ret = Core::ExecuteGuest(curthread->start_routine, curthread->arg); /* Remove thread from tracking */ DebugState.RemoveCurrentThreadFromGuestList(); @@ -56,7 +221,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt new_thread->attr = *(*attr); new_thread->attr.cpusetsize = 0; } - if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) { + if (new_thread->attr.sched_inherit == PthreadInheritSched) { if (True(curthread->attr.flags & PthreadAttrFlags::ScopeSystem)) { new_thread->attr.flags |= PthreadAttrFlags::ScopeSystem; } else { @@ -85,7 +250,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt new_thread->cancel_async = 0; auto* memory = Core::Memory::Instance(); - if (memory->IsValidAddress(name)) { + if (name && (std::string_view{name} == "GAME_MainThread" || memory->IsValidAddress(name))) { new_thread->name = name; } @@ -109,6 +274,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt pthread_attr_setstack(&pattr, new_thread->attr.stackaddr_attr, new_thread->attr.stacksize_attr); pthread_t pthr; int ret = pthread_create(&pthr, &pattr, (PthreadEntryFunc)RunThread, new_thread); + ASSERT_MSG(ret == 0, "Failed to create thread with error {}", ret); if (ret) { *thread = nullptr; } @@ -203,6 +369,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("m0iS6jNsXds", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_min); LIB_FUNCTION("EotR8a3ASf4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_self); LIB_FUNCTION("B5GmVDKwpn0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_yield); + LIB_FUNCTION("+U1R4WtXvoc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_detach); // Posix-Kernel LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self); @@ -212,6 +379,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("GBUY7ywdULE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_rename_np)); LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_create_name_np)); + LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_detach)); LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self); LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_equal); LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, posix_pthread_yield); diff --git a/src/core/libraries/kernel/threads/thr_ctrdtr.cpp b/src/core/libraries/kernel/threads/thr_ctrdtr.cpp index 98cb9482..34e0e0f5 100644 --- a/src/core/libraries/kernel/threads/thr_ctrdtr.cpp +++ b/src/core/libraries/kernel/threads/thr_ctrdtr.cpp @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/alignment.h" #include "common/assert.h" #include "common/singleton.h" #include "core/libraries/kernel/threads/threads.h" +#include "core/libraries/libs.h" #include "core/linker.h" #include "core/tls.h" @@ -16,11 +16,10 @@ static constexpr size_t TlsTcbAlign = 0x20; static std::shared_mutex RtldLock; Core::Tcb* TcbCtor(Pthread* thread, int initial) { - ASSERT(initial == 0); std::scoped_lock lk{RtldLock}; auto* linker = Common::Singleton::Instance(); - auto* addr_out = linker->AllocateTlsForThread(false); + auto* addr_out = linker->AllocateTlsForThread(initial); ASSERT_MSG(addr_out, "Unable to allocate guest TCB"); // Initialize allocated memory and allocate DTV table. @@ -43,15 +42,15 @@ Core::Tcb* TcbCtor(Pthread* thread, int initial) { auto* module = linker->GetModule(0); u8* dest = reinterpret_cast(addr + static_tls_size - module->tls.offset); - if (module->tls.image_virtual_addr != 0) { - const u8* src = reinterpret_cast(module->tls.image_virtual_addr); - memcpy(dest, src, module->tls.init_image_size); + if (module->tls.image_size != 0) { + if (module->tls.image_virtual_addr != 0) { + const u8* src = reinterpret_cast(module->tls.image_virtual_addr); + memcpy(dest, src, module->tls.init_image_size); + } + ASSERT_MSG(module->tls.modid > 0 && module->tls.modid <= num_dtvs); + tcb->tcb_dtv[module->tls.modid + 1].pointer = dest; } - // Initialize DTV entry of main module - ASSERT_MSG(module->tls.modid > 0 && module->tls.modid <= num_dtvs); - tcb->tcb_dtv[module->tls.modid + 1].pointer = dest; - if (tcb) { tcb->tcb_thread = thread; } @@ -68,21 +67,12 @@ void TcbDtor(Core::Tcb* oldtls) { ASSERT_MSG(num_dtvs <= max_tls_index, "Out of bounds DTV access"); const u32 static_tls_size = linker->StaticTlsSize(); - const u8* tls_base = (const u8*)oldtls - Common::AlignUp(static_tls_size, tcbalign); + const u8* tls_base = (const u8*)oldtls - static_tls_size; for (int i = 1; i < num_dtvs; i++) { u8* dtv_ptr = dtv_table[i + 1].pointer; if (dtv_ptr && (dtv_ptr < tls_base || (const u8*)oldtls < dtv_ptr)) { - bool is_occupied; - - _is_occupied = IsDtvIndexOccupied ? ((ulong)tcb, next); - if (_is_occupied != 0) { - FreeMem(dtv_ptr); - return; - } - (**(code**)(LibcHeapApiPtr + 8))(dtv_ptr); - FreeIfOccupied(tcb, dtv_addr & 0xffffffffffff, mod_index); - dtv[modid + 1] = (ulong) * (ushort*)((long)dtv + modid * 8 + 0xe) << 0x30; + linker->FreeTlsForNonPrimaryThread(dtv_ptr); } } @@ -99,4 +89,8 @@ void* PS4_SYSV_ABI __tls_get_addr(TlsIndex* index) { return linker->TlsGetAddr(index->ti_module, index->ti_offset); } +void RegisterRtld(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("vNe1w4diLCs", "libkernel", 1, "libkernel", 1, 1, __tls_get_addr); +} + } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/thr_exit.cpp b/src/core/libraries/kernel/threads/thr_exit.cpp index 4e1ae80d..3816a1de 100644 --- a/src/core/libraries/kernel/threads/thr_exit.cpp +++ b/src/core/libraries/kernel/threads/thr_exit.cpp @@ -7,175 +7,4 @@ #include "core/libraries/kernel/threads/thread_state.h" #include "core/libraries/kernel/threads/threads.h" -namespace Libraries::Kernel { - -void _thread_cleanupspecific(); - -static void ExitThread() { - Pthread* curthread = g_curthread; - - /* Check if there is thread specific data: */ - if (curthread->specific != nullptr) { - /* Run the thread-specific data destructors: */ - _thread_cleanupspecific(); - } - - auto* thread_state = ThrState::Instance(); - ASSERT(thread_state->active_threads.fetch_sub(1) != 1); - - curthread->lock->lock(); - curthread->state = PthreadState::Dead; - ASSERT(False(curthread->flags & ThreadFlags::NeedSuspend)); - - /* - * Thread was created with initial refcount 1, we drop the - * reference count to allow it to be garbage collected. - */ - curthread->refcount--; - thread_state->TryCollect(curthread, curthread); /* thread lock released */ - - /* - * Kernel will do wakeup at the address, so joiner thread - * will be resumed if it is sleeping at the address. - */ - curthread->tid.store(TidTerminated); - curthread->tid.notify_all(); - - pthread_exit(nullptr); - UNREACHABLE(); - /* Never reach! */ -} - -void PS4_SYSV_ABI posix_pthread_exit(void* status) { - Pthread* curthread = g_curthread; - - /* Check if this thread is already in the process of exiting: */ - ASSERT_MSG(!curthread->cancelling, "Thread {} has called pthread_exit from a destructor", - fmt::ptr(curthread)); - - /* Flag this thread as exiting. */ - curthread->cancelling = 1; - curthread->no_cancel = 1; - curthread->cancel_async = 0; - curthread->cancel_point = 0; - - /* Save the return value: */ - curthread->ret = status; - while (!curthread->cleanup.empty()) { - PthreadCleanup* old = curthread->cleanup.front(); - curthread->cleanup.pop_front(); - old->routine(old->routine_arg); - if (old->onheap) { - free(old); - } - } - - ExitThread(); -} - -static int JoinThread(PthreadT pthread, void** thread_return, const OrbisKernelTimespec* abstime) { - Pthread* curthread = g_curthread; - - if (pthread == nullptr) { - return POSIX_EINVAL; - } - - if (pthread == curthread) { - return POSIX_EDEADLK; - } - - auto* thread_state = ThrState::Instance(); - if (int ret = thread_state->FindThread(pthread, 1); ret != 0) { - return POSIX_ESRCH; - } - - int ret = 0; - if (True(pthread->flags & ThreadFlags::Detached)) { - ret = POSIX_EINVAL; - } else if (pthread->joiner != nullptr) { - /* Multiple joiners are not supported. */ - ret = POSIX_ENOTSUP; - } - if (ret) { - pthread->lock->unlock(); - return ret; - } - /* Set the running thread to be the joiner: */ - pthread->joiner = curthread; - pthread->lock->unlock(); - - const auto backout_join = [](void* arg) { - Pthread* pthread = (Pthread*)arg; - std::scoped_lock lk{*pthread->lock}; - pthread->joiner = nullptr; - }; - - PthreadCleanup cup{backout_join, pthread, 0}; - curthread->cleanup.push_front(&cup); - - //_thr_cancel_enter(curthread); - - const int tid = pthread->tid; - while (pthread->tid.load() != TidTerminated) { - //_thr_testcancel(curthread); - ASSERT(abstime == nullptr); - pthread->tid.wait(tid); - } - - //_thr_cancel_leave(curthread, 0); - curthread->cleanup.pop_front(); - - if (ret == POSIX_ETIMEDOUT) { - backout_join(pthread); - return ret; - } - - void* tmp = pthread->ret; - pthread->lock->lock(); - pthread->flags |= ThreadFlags::Detached; - pthread->joiner = nullptr; - thread_state->TryCollect(curthread, pthread); /* thread lock released */ - if (thread_return != nullptr) { - *thread_return = tmp; - } - - return 0; -} - -int PS4_SYSV_ABI posix_pthread_join(PthreadT pthread, void** thread_return) { - return JoinThread(pthread, thread_return, NULL); -} - -int PS4_SYSV_ABI posix_pthread_timedjoin_np(PthreadT pthread, void** thread_return, - const OrbisKernelTimespec* abstime) { - if (abstime == nullptr || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || - abstime->tv_nsec >= 1000000000) { - return POSIX_EINVAL; - } - - return JoinThread(pthread, thread_return, abstime); -} - -int PS4_SYSV_ABI posix_pthread_detach(PthreadT pthread) { - if (pthread == nullptr) { - return POSIX_EINVAL; - } - - auto* thread_state = ThrState::Instance(); - if (int ret = thread_state->FindThread(pthread, 1); ret != 0) { - return ret; - } - - /* Check if the thread is already detached or has a joiner. */ - if (True(pthread->flags & ThreadFlags::Detached) || (pthread->joiner != NULL)) { - pthread->lock->unlock(); - return POSIX_EINVAL; - } - - /* Flag the thread as detached. */ - pthread->flags |= ThreadFlags::Detached; - thread_state->TryCollect(g_curthread, pthread); /* thread lock released */ - return 0; -} - -} // namespace Libraries::Kernel +namespace Libraries::Kernel {} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/thr_mutex.cpp b/src/core/libraries/kernel/threads/thr_mutex.cpp index 908feb8f..66b38bd0 100644 --- a/src/core/libraries/kernel/threads/thr_mutex.cpp +++ b/src/core/libraries/kernel/threads/thr_mutex.cpp @@ -99,7 +99,7 @@ int PS4_SYSV_ABI posix_pthread_mutex_destroy(PthreadMutexT* mutex) { return POSIX_EINVAL; } if (m->m_owner != nullptr) { - return EBUSY; + return POSIX_EBUSY; } *mutex = THR_MUTEX_DESTROYED; std::destroy_at(m); diff --git a/src/core/libraries/kernel/threads/thr_rwlock.cpp b/src/core/libraries/kernel/threads/thr_rwlock.cpp index 95f68590..b06db6b3 100644 --- a/src/core/libraries/kernel/threads/thr_rwlock.cpp +++ b/src/core/libraries/kernel/threads/thr_rwlock.cpp @@ -178,7 +178,17 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(PthreadRwlockT* rwlock) { return POSIX_EINVAL; } - s32 state = prwlock->lock.rw_state; + if (prwlock->owner == curthread) { + prwlock->lock.unlock(); + prwlock->owner = nullptr; + } else { + prwlock->lock.unlock_shared(); + if (prwlock->owner == nullptr) { + curthread->rdlock_count--; + } + } + + /*s32 state = prwlock->lock.rw_state; if (state & URWLOCK_WRITE_OWNER) { if (prwlock->owner != curthread) [[unlikely]] { return POSIX_EPERM; @@ -189,7 +199,7 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(PthreadRwlockT* rwlock) { prwlock->lock.unlock(); if ((state & URWLOCK_WRITE_OWNER) == 0) { curthread->rdlock_count--; - } + }*/ return 0; } diff --git a/src/core/libraries/kernel/threads/thr_spec.cpp b/src/core/libraries/kernel/threads/thr_spec.cpp index c5b26ad4..ccedf5b8 100644 --- a/src/core/libraries/kernel/threads/thr_spec.cpp +++ b/src/core/libraries/kernel/threads/thr_spec.cpp @@ -140,20 +140,6 @@ const void* PS4_SYSV_ABI posix_pthread_getspecific(PthreadKeyT key) { return nullptr; } -void _thr_tsd_unload(struct dl_phdr_info* phdr_info) { - std::scoped_lock lk{KeytableLock}; - for (int key = 0; key < PTHREAD_KEYS_MAX; key++) { - if (!ThreadKeytable[key].allocated) { - continue; - } - const auto destructor = ThreadKeytable[key].destructor; - if (destructor != nullptr) { - if (__elf_phdr_match_addr(phdr_info, destructor)) - ThreadKeytable[key].destructor = nullptr; - } - } -} - void RegisterSpec(Core::Loader::SymbolsResolver* sym) { // Posix LIB_FUNCTION("mqULNdimTn0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_key_create); @@ -162,8 +148,7 @@ void RegisterSpec(Core::Loader::SymbolsResolver* sym) { // Orbis LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_create)); - LIB_FUNCTION("eoht7mQOCmo", "libkernel", 1, "libkernel", 1, 1, - ORBIS(posix_pthread_getspecific)); + LIB_FUNCTION("eoht7mQOCmo", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getspecific); LIB_FUNCTION("+BzXYkqYeLE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setspecific)); } diff --git a/src/core/libraries/kernel/threads/thr_stack.cpp b/src/core/libraries/kernel/threads/thr_stack.cpp index ec4a956a..396b24e4 100644 --- a/src/core/libraries/kernel/threads/thr_stack.cpp +++ b/src/core/libraries/kernel/threads/thr_stack.cpp @@ -78,7 +78,8 @@ int ThreadState::CreateStack(PthreadAttr* attr) { /* Allocate a stack from usrstack. */ if (last_stack == 0) { - last_stack = _usrstack - ThrStackInitial - ThrGuardDefault; + static constexpr VAddr UsrStack = 0x7EFFF8000ULL; + last_stack = UsrStack - ThrStackInitial - ThrGuardDefault; } /* Allocate a new stack. */ diff --git a/src/core/libraries/kernel/threads/thread_state.cpp b/src/core/libraries/kernel/threads/thread_state.cpp index f340952a..671c8381 100644 --- a/src/core/libraries/kernel/threads/thread_state.cpp +++ b/src/core/libraries/kernel/threads/thread_state.cpp @@ -10,6 +10,8 @@ namespace Libraries::Kernel { +Pthread* g_curthread{}; + Core::Tcb* TcbCtor(Pthread* thread, int initial); void TcbDtor(Core::Tcb* oldtls); @@ -85,11 +87,11 @@ Pthread* ThreadState::Alloc(Pthread* curthread) { tcb = TcbCtor(thread, 1 /* initial tls */); } if (tcb != nullptr) { - memset(thread, 0, sizeof(*thread)); thread->tcb = tcb; // thread->sleepqueue = _sleepq_alloc(); // thread->wake_addr = _thr_alloc_wake_addr(); } else { + std::destroy_at(thread); free(thread); total_threads.fetch_sub(1); thread = nullptr; @@ -108,6 +110,7 @@ void ThreadState::Free(Pthread* curthread, Pthread* thread) { if (free_threads.size() >= MaxCachedThreads) { //_sleepq_free(thread->sleepqueue); //_thr_release_wake_addr(thread->wake_addr); + std::destroy_at(thread); free(thread); total_threads.fetch_sub(1); } else { diff --git a/src/core/libraries/kernel/threads/threads.h b/src/core/libraries/kernel/threads/threads.h index bc3fffce..4a997ef4 100644 --- a/src/core/libraries/kernel/threads/threads.h +++ b/src/core/libraries/kernel/threads/threads.h @@ -194,6 +194,8 @@ enum class ThreadListFlags : u32 { InGcList = 4, }; +using PthreadEntryFunc = void* (*)(void*); + constexpr u32 TidTerminated = 1; struct Pthread { @@ -272,15 +274,6 @@ void RegisterSemaphore(Core::Loader::SymbolsResolver* sym); void RegisterSpec(Core::Loader::SymbolsResolver* sym); void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym); void RegisterThread(Core::Loader::SymbolsResolver* sym); - -inline void RegisterThreads(Core::Loader::SymbolsResolver* sym) { - RegisterMutex(sym); - RegisterCond(sym); - RegisterRwlock(sym); - RegisterSemaphore(sym); - RegisterSpec(sym); - RegisterThreadAttr(sym); - RegisterThread(sym); -} +void RegisterRtld(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 23d75162..5816b787 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -49,11 +49,9 @@ namespace Libraries { void InitHLELibs(Core::Loader::SymbolsResolver* sym) { LOG_INFO(Lib_Kernel, "Initializing HLE libraries"); - Libraries::Kernel::LibKernel_Register(sym); + Libraries::Kernel::RegisterKernel(sym); Libraries::GnmDriver::RegisterlibSceGnmDriver(sym); Libraries::VideoOut::RegisterLib(sym); - - // New libraries folder from autogen Libraries::UserService::RegisterlibSceUserService(sym); Libraries::SystemService::RegisterlibSceSystemService(sym); Libraries::CommonDialog::RegisterlibSceCommonDialog(sym); diff --git a/src/core/libraries/network/net_ctl_obj.cpp b/src/core/libraries/network/net_ctl_obj.cpp index 07381d67..8d1c7ad9 100644 --- a/src/core/libraries/network/net_ctl_obj.cpp +++ b/src/core/libraries/network/net_ctl_obj.cpp @@ -1,80 +1,62 @@ // 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" +#include "core/libraries/network/net_ctl_codes.h" +#include "core/libraries/network/net_ctl_obj.h" +#include "core/tls.h" -Libraries::NetCtl::NetCtlInternal::NetCtlInternal() { - callbacks.fill({nullptr, nullptr}); - nptoolCallbacks.fill({nullptr, nullptr}); -} +namespace Libraries::NetCtl { -Libraries::NetCtl::NetCtlInternal::~NetCtlInternal() {} +NetCtlInternal::NetCtlInternal() = default; -s32 Libraries::NetCtl::NetCtlInternal::registerCallback(OrbisNetCtlCallback func, void* arg) { - std::unique_lock lock{m_mutex}; +NetCtlInternal::~NetCtlInternal() = default; + +s32 NetCtlInternal::RegisterCallback(OrbisNetCtlCallback func, void* arg) { + std::scoped_lock lock{m_mutex}; // Find the next available slot - int next_id = 0; - for (const auto& callback : callbacks) { - if (callback.func == nullptr) { - break; - } - next_id++; - } - - if (next_id == 8) { + const auto it = std::ranges::find(callbacks, nullptr, &NetCtlCallback::func); + if (it == callbacks.end()) { return ORBIS_NET_CTL_ERROR_CALLBACK_MAX; } + const int next_id = std::distance(callbacks.begin(), it); callbacks[next_id].func = func; callbacks[next_id].arg = arg; return next_id; } -s32 Libraries::NetCtl::NetCtlInternal::registerNpToolkitCallback( - OrbisNetCtlCallbackForNpToolkit func, void* arg) { - - std::unique_lock lock{m_mutex}; +s32 NetCtlInternal::RegisterNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit func, void* arg) { + std::scoped_lock lock{m_mutex}; // Find the next available slot - int next_id = 0; - for (const auto& callback : nptoolCallbacks) { - if (callback.func == nullptr) { - break; - } - next_id++; - } - - if (next_id == 8) { + const auto it = std::ranges::find(nptool_callbacks, nullptr, &NetCtlCallbackForNpToolkit::func); + if (it == nptool_callbacks.end()) { return ORBIS_NET_CTL_ERROR_CALLBACK_MAX; } - nptoolCallbacks[next_id].func = func; - nptoolCallbacks[next_id].arg = arg; + const int next_id = std::distance(nptool_callbacks.begin(), it); + nptool_callbacks[next_id].func = func; + nptool_callbacks[next_id].arg = arg; return next_id; } -void Libraries::NetCtl::NetCtlInternal::checkCallback() { - std::unique_lock lock{m_mutex}; - const auto* linker = Common::Singleton::Instance(); - for (auto& callback : callbacks) { - if (callback.func != nullptr) { - linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, - callback.arg); +void NetCtlInternal::CheckCallback() { + std::scoped_lock lock{m_mutex}; + for (const auto [func, arg] : callbacks) { + if (func != nullptr) { + Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg); } } } -void Libraries::NetCtl::NetCtlInternal::checkNpToolkitCallback() { - std::unique_lock lock{m_mutex}; - const auto* linker = Common::Singleton::Instance(); - for (auto& callback : nptoolCallbacks) { - if (callback.func != nullptr) { - linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, - callback.arg); +void NetCtlInternal::CheckNpToolkitCallback() { + std::scoped_lock lock{m_mutex}; + for (const auto [func, arg] : nptool_callbacks) { + if (func != nullptr) { + Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg); } } } + +} // namespace Libraries::NetCtl diff --git a/src/core/libraries/network/net_ctl_obj.h b/src/core/libraries/network/net_ctl_obj.h index 3178677f..cbbb33a4 100644 --- a/src/core/libraries/network/net_ctl_obj.h +++ b/src/core/libraries/network/net_ctl_obj.h @@ -3,9 +3,7 @@ #pragma once -#include #include - #include "common/types.h" namespace Libraries::NetCtl { @@ -25,16 +23,17 @@ struct NetCtlCallbackForNpToolkit { class NetCtlInternal { public: - NetCtlInternal(); + explicit NetCtlInternal(); ~NetCtlInternal(); - s32 registerCallback(OrbisNetCtlCallback func, void* arg); - s32 registerNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit func, void* arg); - void checkCallback(); - void checkNpToolkitCallback(); + + s32 RegisterCallback(OrbisNetCtlCallback func, void* arg); + s32 RegisterNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit func, void* arg); + void CheckCallback(); + void CheckNpToolkitCallback(); public: - std::array nptoolCallbacks; - std::array callbacks; + std::array nptool_callbacks{}; + std::array callbacks{}; std::mutex m_mutex; }; } // namespace Libraries::NetCtl diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index d3f83c29..b167d278 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -13,7 +13,6 @@ #endif #include "common/logging/log.h" -#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/network/net_ctl_codes.h" @@ -21,6 +20,8 @@ namespace Libraries::NetCtl { +static NetCtlInternal netctl; + int PS4_SYSV_ABI sceNetBweCheckCallbackIpcInt() { LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); return ORBIS_OK; @@ -92,8 +93,7 @@ int PS4_SYSV_ABI sceNetCtlUnregisterCallbackV6() { } int PS4_SYSV_ABI sceNetCtlCheckCallback() { - auto* netctl = Common::Singleton::Instance(); - netctl->checkCallback(); + netctl.CheckCallback(); return ORBIS_OK; } @@ -298,8 +298,7 @@ int PS4_SYSV_ABI sceNetCtlRegisterCallback(OrbisNetCtlCallback func, void* arg, if (!func || !cid) { return ORBIS_NET_CTL_ERROR_INVALID_ADDR; } - auto* netctl = Common::Singleton::Instance(); - s32 result = netctl->registerCallback(func, arg); + s32 result = netctl.RegisterCallback(func, arg); if (result < 0) { return result; } else { @@ -374,8 +373,7 @@ int PS4_SYSV_ABI Func_D8DCB6973537A3DC() { } int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit() { - auto* netctl = Common::Singleton::Instance(); - netctl->checkNpToolkitCallback(); + netctl.CheckNpToolkitCallback(); return ORBIS_OK; } @@ -389,8 +387,7 @@ int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit(OrbisNetCtlCallbackForNpT if (!func || !cid) { return ORBIS_NET_CTL_ERROR_INVALID_ADDR; } - auto* netctl = Common::Singleton::Instance(); - s32 result = netctl->registerNpToolkitCallback(func, arg); + s32 result = netctl.RegisterNpToolkitCallback(func, arg); if (result < 0) { return result; } else { diff --git a/src/core/libraries/network/netctl.h b/src/core/libraries/network/netctl.h index 89ba34c3..4482729a 100644 --- a/src/core/libraries/network/netctl.h +++ b/src/core/libraries/network/netctl.h @@ -4,7 +4,7 @@ #pragma once #include "common/types.h" -#include "net_ctl_obj.h" +#include "core/libraries/network/net_ctl_obj.h" namespace Core::Loader { class SymbolsResolver; diff --git a/src/core/libraries/np_manager/np_manager.cpp b/src/core/libraries/np_manager/np_manager.cpp index 4fff5900..00070ef8 100644 --- a/src/core/libraries/np_manager/np_manager.cpp +++ b/src/core/libraries/np_manager/np_manager.cpp @@ -1,13 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "np_manager.h" +#include "core/libraries/np_manager/np_manager.h" +#include "core/tls.h" namespace Libraries::NpManager { @@ -2519,10 +2518,7 @@ struct NpStateCallbackForNpToolkit { NpStateCallbackForNpToolkit NpStateCbForNp; int PS4_SYSV_ABI sceNpCheckCallbackForLib() { - // LOG_ERROR(Lib_NpManager, "(STUBBED) called"); - const auto* linker = Common::Singleton::Instance(); - linker->ExecuteGuest(NpStateCbForNp.func, 1, ORBIS_NP_STATE_SIGNED_OUT, - NpStateCbForNp.userdata); + Core::ExecuteGuest(NpStateCbForNp.func, 1, ORBIS_NP_STATE_SIGNED_OUT, NpStateCbForNp.userdata); return ORBIS_OK; } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index a0886b51..56b35b43 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -8,30 +8,26 @@ #include "common/logging/log.h" #include "common/path_util.h" #include "common/string_util.h" -#include "common/thread.h" #include "core/aerolib/aerolib.h" #include "core/aerolib/stubs.h" -#include "core/cpu_patches.h" #include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/thread_management.h" #include "core/linker.h" #include "core/memory.h" #include "core/tls.h" #include "core/virtual_memory.h" -#include "debug_state.h" namespace Core { -using ExitFunc = PS4_SYSV_ABI void (*)(); - static PS4_SYSV_ABI void ProgramExitFunc() { - fmt::print("exit function called\n"); + LOG_ERROR(Core_Linker, "Exit function called"); } #ifdef ARCH_X86_64 -static PS4_SYSV_ABI void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) { - // reinterpret_cast(addr)(params, exit_func); // can't be used, stack has to have - // a specific layout +static PS4_SYSV_ABI void* RunMainEntry [[noreturn]] (void* arg) { + EntryParams* params = (EntryParams*)arg; + // Start shared library modules + params->linker->LoadSharedLibraries(); asm volatile("andq $-16, %%rsp\n" // Align to 16 bytes "subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned @@ -47,8 +43,9 @@ static PS4_SYSV_ABI void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc "jmp *%0\n" // can't use call here, as that would mangle the prepared stack. // there's no coming back : - : "r"(addr), "r"(params), "r"(exit_func) + : "r"(params->entry_addr), "r"(params), "r"(params->exit_func) : "rax", "rsi", "rdi"); + UNREACHABLE(); } #endif @@ -62,10 +59,8 @@ void Linker::Execute() { } // Calculate static TLS size. - for (const auto& module : m_modules) { - static_tls_size += module->tls.image_size; - module->tls.offset = static_tls_size; - } + Module* module = m_modules[0].get(); + static_tls_size = module->tls.offset = module->tls.image_size; // Relocate all modules for (const auto& m : m_modules) { @@ -87,36 +82,14 @@ void Linker::Execute() { } } - // Init primary thread. - Common::SetCurrentThreadName("GAME_MainThread"); - DebugState.AddCurrentThreadToGuestList(); - Libraries::Kernel::pthreadInitSelfMainThread(); - EnsureThreadInitialized(true); - - // Start shared library modules - for (auto& m : m_modules) { - if (m->IsSharedLib()) { - m->Start(0, nullptr, nullptr); - } - } - // Start main module. - EntryParams p{}; - p.argc = 1; - p.argv[0] = "eboot.bin"; - - for (auto& m : m_modules) { - if (!m->IsSharedLib()) { -#ifdef ARCH_X86_64 - ExecuteGuest(RunMainEntry, m->GetEntryAddress(), &p, ProgramExitFunc); -#else - UNIMPLEMENTED_MSG( - "Missing guest entrypoint implementation for target CPU architecture."); -#endif - } - } - - SetTcbBase(nullptr); + EntryParams* params = new EntryParams; + params->argc = 1; + params->argv[0] = "eboot.bin"; + params->entry_addr = module->GetEntryAddress(); + params->exit_func = ProgramExitFunc; + params->linker = this; + Libraries::Kernel::LaunchThread(RunMainEntry, params, "GAME_MainThread"); } s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { @@ -337,17 +310,6 @@ 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) const { - std::call_once(init_tls_flag, [this, is_primary] { -#ifdef ARCH_X86_64 - InitializeThreadPatchStack(); -#endif - InitTlsForThread(is_primary); - }); -} - void* Linker::AllocateTlsForThread(bool is_primary) { static constexpr size_t TcbSize = 0x40; static constexpr size_t TlsAllocAlign = 0x20; @@ -369,7 +331,7 @@ void* Linker::AllocateTlsForThread(bool is_primary) { ASSERT_MSG(ret == 0, "Unable to allocate TLS+TCB for the primary thread"); } else { if (heap_api) { - addr_out = heap_api->heap_malloc(total_tls_size); + addr_out = Core::ExecuteGuest(heap_api->heap_malloc, total_tls_size); } else { addr_out = std::malloc(total_tls_size); } @@ -377,22 +339,31 @@ void* Linker::AllocateTlsForThread(bool is_primary) { return addr_out; } +void Linker::FreeTlsForNonPrimaryThread(void* pointer) { + if (heap_api) { + Core::ExecuteGuest(heap_api->heap_free, pointer); + } else { + std::free(pointer); + } +} + void Linker::DebugDump() { const auto& log_dir = Common::FS::GetUserPath(Common::FS::PathType::LogDir); const std::filesystem::path debug(log_dir / "debugdump"); std::filesystem::create_directory(debug); for (const auto& m : m_modules) { - // TODO make a folder with game id for being more unique? - const std::filesystem::path filepath(debug / m.get()->file.stem()); + Module* module = m.get(); + auto& elf = module->elf; + const std::filesystem::path filepath(debug / module->file.stem()); std::filesystem::create_directory(filepath); - m.get()->import_sym.DebugDump(filepath / "imports.txt"); - m.get()->export_sym.DebugDump(filepath / "exports.txt"); - if (m.get()->elf.IsSelfFile()) { - m.get()->elf.SelfHeaderDebugDump(filepath / "selfHeader.txt"); - m.get()->elf.SelfSegHeaderDebugDump(filepath / "selfSegHeaders.txt"); + module->import_sym.DebugDump(filepath / "imports.txt"); + module->export_sym.DebugDump(filepath / "exports.txt"); + if (elf.IsSelfFile()) { + elf.SelfHeaderDebugDump(filepath / "selfHeader.txt"); + elf.SelfSegHeaderDebugDump(filepath / "selfSegHeaders.txt"); } - m.get()->elf.ElfHeaderDebugDump(filepath / "elfHeader.txt"); - m.get()->elf.PHeaderDebugDump(filepath / "elfPHeaders.txt"); + elf.ElfHeaderDebugDump(filepath / "elfHeader.txt"); + elf.PHeaderDebugDump(filepath / "elfPHeaders.txt"); } } diff --git a/src/core/linker.h b/src/core/linker.h index 216ca33e..6709793a 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -40,10 +40,17 @@ struct OrbisProcParam { u64 unknown1; }; +using ExitFunc = PS4_SYSV_ABI void (*)(); + +class Linker; + struct EntryParams { int argc; u32 padding; const char* argv[3]; + VAddr entry_addr; + ExitFunc exit_func; + Linker* linker; }; struct HeapAPI { @@ -101,6 +108,14 @@ public: } } + void LoadSharedLibraries() { + for (auto& module : m_modules) { + if (module->IsSharedLib()) { + module->Start(0, nullptr, nullptr); + } + } + } + void SetHeapAPI(void* func[]) { heap_api = reinterpret_cast(func); } @@ -111,6 +126,7 @@ public: void* TlsGetAddr(u64 module_index, u64 offset); void* AllocateTlsForThread(bool is_primary); + void FreeTlsForNonPrimaryThread(void* pointer); s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false); Module* FindByAddress(VAddr address); @@ -121,24 +137,8 @@ public: void Execute(); void DebugDump(); - template - ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), - CallArgs&&... args) const { - // Make sure TLS is initialized for the thread before entering guest. - EnsureThreadInitialized(); - return ExecuteGuestWithoutTls(func, args...); - } - private: const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); - void EnsureThreadInitialized(bool is_primary = false) const; - void InitTlsForThread(bool is_primary) const; - - template - ReturnType ExecuteGuestWithoutTls(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), - CallArgs&&... args) const { - return func(std::forward(args)...); - } MemoryManager* memory; std::mutex mutex; diff --git a/src/core/memory.h b/src/core/memory.h index be2bcb87..ce4b87d1 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -148,7 +148,7 @@ public: VAddr SystemReservedVirtualBase() noexcept { return impl.SystemReservedVirtualBase(); } - + bool IsValidAddress(const void* addr) const noexcept { const VAddr virtual_addr = reinterpret_cast(addr); const auto end_it = std::prev(vma_map.end()); diff --git a/src/core/module.cpp b/src/core/module.cpp index 5d3b4057..cdd032e1 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -9,10 +9,10 @@ #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" +#include "core/tls.h" namespace Core { @@ -70,9 +70,8 @@ Module::~Module() = default; s32 Module::Start(size_t args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", name); - const auto* linker = Common::Singleton::Instance(); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); - return linker->ExecuteGuest(reinterpret_cast(addr), args, argp, param); + return ExecuteGuest(reinterpret_cast(addr), args, argp, param); } void Module::LoadModuleToMemory(u32& max_tls_index) { diff --git a/src/core/tls.cpp b/src/core/tls.cpp index eb07e7a7..679208de 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -5,6 +5,8 @@ #include "common/arch.h" #include "common/assert.h" #include "common/types.h" +#include "core/cpu_patches.h" +#include "core/libraries/kernel/threads/threads.h" #include "core/tls.h" #ifdef _WIN32 @@ -181,4 +183,15 @@ Tcb* GetTcbBase() { #endif +thread_local std::once_flag init_tls_flag; + +void EnsureThreadInitialized() { + std::call_once(init_tls_flag, [] { +#ifdef ARCH_X86_64 + InitializeThreadPatchStack(); +#endif + SetTcbBase(Libraries::Kernel::g_curthread->tcb); + }); +} + } // namespace Core diff --git a/src/core/tls.h b/src/core/tls.h index f5bf3318..4df9e4ac 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -12,7 +12,7 @@ class CodeGenerator; namespace Core { union DtvEntry { - size_t counter; + std::size_t counter; u8* pointer; }; @@ -33,4 +33,13 @@ void SetTcbBase(void* image_address); /// Retrieves Tcb structure for the calling thread. Tcb* GetTcbBase(); +/// Makes sure TLS is initialized for the thread before entering guest. +void EnsureThreadInitialized(); + +template +ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) { + EnsureThreadInitialized(); + return func(std::forward(args)...); +} + } // namespace Core diff --git a/src/emulator.cpp b/src/emulator.cpp index d9d32ec1..24f5907a 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -29,7 +29,6 @@ #include "core/file_sys/fs.h" #include "core/libraries/disc_map/disc_map.h" #include "core/libraries/fiber/fiber.h" -#include "core/libraries/kernel/thread_management.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" @@ -222,7 +221,6 @@ void Emulator::Run(const std::filesystem::path& file) { VideoCore::SetOutputDir(mount_captures_dir, id); // Initialize kernel and library facilities. - Libraries::Kernel::init_pthreads(); Libraries::InitHLELibs(&linker->GetHLESymbols()); // Load the module with the linker @@ -257,9 +255,7 @@ void Emulator::Run(const std::filesystem::path& file) { } #endif - // start execution - std::jthread mainthread = - std::jthread([this](std::stop_token stop_token) { linker->Execute(); }); + linker->Execute(); window->initTimers(); while (window->isOpen()) {