From b7b1487d99a6d1f88d493214705ccc2dcc2beaa7 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:40:40 +0300 Subject: [PATCH] kernel: Rework keys --- src/core/address_space.cpp | 4 +- .../libraries/kernel/thread_management.cpp | 24 ++--- src/core/libraries/kernel/thread_management.h | 12 ++- src/core/libraries/kernel/threads/keys.cpp | 98 ++++--------------- src/core/libraries/kernel/threads/threads.h | 1 + src/video_core/amdgpu/liverpool.cpp | 1 - 6 files changed, 40 insertions(+), 100 deletions(-) diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index df31de8ec..f83026417 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -85,7 +85,7 @@ struct AddressSpace::Impl { } } - void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, HANDLE fd = nullptr) { + void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) { const auto it = placeholders.find(virtual_addr); ASSERT_MSG(it != placeholders.end(), "Cannot map already mapped region"); ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + size <= it->upper(), @@ -117,7 +117,7 @@ struct AddressSpace::Impl { // Perform the map. void* ptr = nullptr; if (phys_addr != -1) { - HANDLE backing = fd ? fd : backing_handle; + HANDLE backing = fd ? reinterpret_cast(fd) : backing_handle; ptr = MapViewOfFile3(backing, process, reinterpret_cast(virtual_addr), phys_addr, size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0); } else { diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index c1fd28df9..946c248c2 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -881,6 +881,11 @@ int PS4_SYSV_ABI scePthreadAttrGet(ScePthread thread, ScePthreadAttr* attr) { static void cleanup_thread(void* arg) { auto* thread = static_cast(arg); + for (const auto& [key, destructor] : thread->key_destructors) { + if (void* value = pthread_getspecific(key); value != nullptr) { + destructor(value); + } + } thread->is_almost_done = true; } @@ -899,7 +904,7 @@ static void* run_thread(void* arg) { } int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, - pthreadEntryFunc start_routine, void* arg, const char* name) { + PthreadEntryFunc start_routine, void* arg, const char* name) { if (thread == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -1161,7 +1166,7 @@ int PS4_SYSV_ABI posix_pthread_attr_setdetachstate(ScePthreadAttr* attr, int det } int PS4_SYSV_ABI posix_pthread_create_name_np(ScePthread* thread, const ScePthreadAttr* attr, - pthreadEntryFunc start_routine, void* arg, + PthreadEntryFunc start_routine, void* arg, const char* name) { LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate: name = {}", name); @@ -1176,7 +1181,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(ScePthread* thread, const ScePthre } int PS4_SYSV_ABI posix_pthread_create(ScePthread* thread, const ScePthreadAttr* attr, - pthreadEntryFunc start_routine, void* arg) { + PthreadEntryFunc start_routine, void* arg) { return posix_pthread_create_name_np(thread, attr, start_routine, arg, "NoName"); } @@ -1240,19 +1245,7 @@ int PS4_SYSV_ABI scePthreadSetschedparam(ScePthread thread, int policy, int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { return pthread_once(reinterpret_cast(once_control), init_routine); } -int PS4_SYSV_ABI posix_pthread_create(ScePthread* thread, const ScePthreadAttr* attr, - pthreadEntryFunc start_routine, void* arg) { - LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate"); - int result = scePthreadCreate(thread, attr, start_routine, arg, ""); - if (result != 0) { - int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP - ? result + -SCE_KERNEL_ERROR_UNKNOWN - : POSIX_EOTHER; - return rt; - } - return result; -} void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate); LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init); @@ -1349,6 +1342,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { // libs RwlockSymbolsRegister(sym); SemaphoreSymbolsRegister(sym); + KeySymbolsRegister(sym); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index 6452bad08..1909ffd3a 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -39,22 +39,24 @@ using ScePthreadCond = PthreadCondInternal*; using ScePthreadCondattr = PthreadCondAttrInternal*; using OrbisPthreadRwlock = PthreadRwInternal*; using OrbisPthreadRwlockattr = PthreadRwLockAttrInternal*; -using OrbisPthreadKey = int; -using PthreadKeyDestructor = PS4_SYSV_ABI void (*)(void*); +using OrbisPthreadKey = u32; -using pthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*); +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; + 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; }; struct PthreadAttrInternal { @@ -195,7 +197,7 @@ 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 scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, - pthreadEntryFunc start_routine, void* arg, const char* name); + PthreadEntryFunc start_routine, void* arg, const char* name); /*** * Mutex calls diff --git a/src/core/libraries/kernel/threads/keys.cpp b/src/core/libraries/kernel/threads/keys.cpp index 10a81855b..786468339 100644 --- a/src/core/libraries/kernel/threads/keys.cpp +++ b/src/core/libraries/kernel/threads/keys.cpp @@ -1,103 +1,47 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include "common/logging/log.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/threads/threads.h" +#include "core/libraries/kernel/thread_management.h" #include "core/libraries/libs.h" namespace Libraries::Kernel { -extern PThreadCxt* g_pthread_cxt; - -bool PthreadKeys::CreateKey(int* key, PthreadKeyDestructor destructor) { - std::scoped_lock lk{m_mutex}; - - for (int index = 0; index < 256; index++) { - if (!m_keys[index].used) { - *key = index; - m_keys[index].used = true; - m_keys[index].destructor = destructor; - m_keys[index].specific_values.clear(); - return true; - } - } - - return false; -} - -bool PthreadKeys::GetKey(int key, int thread_id, void** data) { - std::scoped_lock lk{m_mutex}; - - if (key < 0 || key >= 256 || !m_keys[key].used) { - return false; - } - - for (auto& v : m_keys[key].specific_values) { - if (v.thread_id == thread_id) { - *data = v.data; - return true; - } - } - - *data = nullptr; - - return true; -} -bool PthreadKeys::SetKey(int key, int thread_id, void* data) { - std::scoped_lock lk{m_mutex}; - - if (key < 0 || key >= 256 || !m_keys[key].used) { - return false; - } - - for (auto& v : m_keys[key].specific_values) { - if (v.thread_id == thread_id) { - v.data = data; - return true; - } - } - - Map keymap = {thread_id, data}; - m_keys[key].specific_values.push_back(keymap); - - return true; -} - int PS4_SYSV_ABI scePthreadKeyCreate(OrbisPthreadKey* key, PthreadKeyDestructor destructor) { if (key == nullptr) { return ORBIS_KERNEL_ERROR_EINVAL; } - if (!g_pthread_cxt->getPthreadKeys()->CreateKey(key, destructor)) { - return ORBIS_KERNEL_ERROR_EAGAIN; + int result = pthread_key_create(key, nullptr); + if (destructor) { + auto thread = scePthreadSelf(); + thread->key_destructors.emplace_back(*key, destructor); } - return ORBIS_OK; + if (result != 0) { + LOG_ERROR(Kernel_Pthread, "scePthreadKeyCreate: error = {}", result); + result += ORBIS_KERNEL_ERROR_UNKNOWN; + } + return result; } void* PS4_SYSV_ABI scePthreadGetspecific(OrbisPthreadKey key) { - auto id = std::this_thread::get_id(); - int thread_id = *(unsigned*)&id; - - void* value = nullptr; - if (!g_pthread_cxt->getPthreadKeys()->GetKey(key, thread_id, &value)) { - return nullptr; - } - - return value; + return pthread_getspecific(key); } int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* value) { - auto id = std::this_thread::get_id(); - int thread_id = *(unsigned*)&id; - - if (!g_pthread_cxt->getPthreadKeys()->SetKey(key, thread_id, value)) { - return ORBIS_KERNEL_ERROR_EINVAL; + int result = pthread_setspecific(key, value); + if (result != 0) { + LOG_ERROR(Kernel_Pthread, "scePthreadSetspecific: error = {}", result); + result += ORBIS_KERNEL_ERROR_UNKNOWN; } + return result; +} - return ORBIS_OK; +void KeySymbolsRegister(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, scePthreadKeyCreate); + LIB_FUNCTION("eoht7mQOCmo", "libkernel", 1, "libkernel", 1, 1, scePthreadGetspecific); + LIB_FUNCTION("+BzXYkqYeLE", "libkernel", 1, "libkernel", 1, 1, scePthreadSetspecific); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/threads.h b/src/core/libraries/kernel/threads/threads.h index 135bccec5..a3fd354b0 100644 --- a/src/core/libraries/kernel/threads/threads.h +++ b/src/core/libraries/kernel/threads/threads.h @@ -15,5 +15,6 @@ int PS4_SYSV_ABI scePthreadRwlockattrInit(OrbisPthreadRwlockattr* attr); void SemaphoreSymbolsRegister(Core::Loader::SymbolsResolver* sym); void RwlockSymbolsRegister(Core::Loader::SymbolsResolver* sym); +void KeySymbolsRegister(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 833794588..956e65a18 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "common/assert.h" #include "common/debug.h" #include "common/thread.h"