From 91885e8a413a6ce2689add5cc48c6e1862b7c9b3 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 10 Nov 2023 19:52:41 +0200 Subject: [PATCH] added sceMutexInit functions --- .../hle/libraries/libkernel/libkernel.cpp | 2 + .../libraries/libkernel/thread_management.cpp | 123 ++++++++++++++++-- .../libraries/libkernel/thread_management.h | 62 +++++++-- src/main.cpp | 24 ++-- 4 files changed, 181 insertions(+), 30 deletions(-) diff --git a/src/core/hle/libraries/libkernel/libkernel.cpp b/src/core/hle/libraries/libkernel/libkernel.cpp index 65b96dcd..7ab71291 100644 --- a/src/core/hle/libraries/libkernel/libkernel.cpp +++ b/src/core/hle/libraries/libkernel/libkernel.cpp @@ -14,6 +14,7 @@ #ifdef _WIN64 #include #endif +#include "thread_management.h" namespace Core::Libraries::LibKernel { @@ -50,6 +51,7 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) { Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym); Core::Libraries::LibKernel::timeSymbolsRegister(sym); + Core::Libraries::LibKernel::pthreadSymbolsRegister(sym); } } // namespace Core::Libraries::LibKernel diff --git a/src/core/hle/libraries/libkernel/thread_management.cpp b/src/core/hle/libraries/libkernel/thread_management.cpp index 32afa443..5a6297f2 100644 --- a/src/core/hle/libraries/libkernel/thread_management.cpp +++ b/src/core/hle/libraries/libkernel/thread_management.cpp @@ -1,19 +1,32 @@ -#include "common/debug.h" #include "core/hle/libraries/libkernel/thread_management.h" + +#include + +#include "common/debug.h" +#include "common/log.h" #include "core/hle/error_codes.h" -namespace Core::Kernel { +namespace Core::Libraries::LibKernel { thread_local PthreadInternal g_pthread_self{}; PThreadCxt* g_pthread_cxt = nullptr; +constexpr bool log_pthread_file = true; // disable it to disable logging + +void init_pthreads() { + g_pthread_cxt = new PThreadCxt{}; + ScePthreadMutexattr default_mutexattr = nullptr; + scePthreadMutexattrInit(&default_mutexattr); + g_pthread_cxt->setDefaultMutexattr(default_mutexattr); +} + void Pthread_Init_Self_MainThread() { scePthreadAttrInit(&g_pthread_self.attr); g_pthread_self.pth = pthread_self(); g_pthread_self.name = "Main_Thread"; } -int scePthreadAttrInit(ScePthreadAttr* attr) { +int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr) { *attr = new PthreadAttrInternal{}; int result = pthread_attr_init(&(*attr)->pth_attr); @@ -36,7 +49,7 @@ int scePthreadAttrInit(ScePthreadAttr* attr) { } } -int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate) { +int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate) { if (attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -58,7 +71,7 @@ int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate) { return SCE_KERNEL_ERROR_EINVAL; } -int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) { +int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) { if (attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -78,7 +91,7 @@ int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) { return SCE_KERNEL_ERROR_EINVAL; } -int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param) { +int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param) { if (param == nullptr || attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -100,7 +113,7 @@ int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* return SCE_KERNEL_ERROR_EINVAL; } -int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) { +int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) { if (attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -119,4 +132,98 @@ int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) { return SCE_KERNEL_ERROR_EINVAL; } -} // namespace Core::Kernel +/**** + * Mutex calls + */ +int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, const char* name) { + PRINT_FUNCTION_NAME(); + if (mutex == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + if (attr == nullptr) { + attr = g_pthread_cxt->getDefaultMutexattr(); + } + + *mutex = new PthreadMutexInternal{}; + if (name != nullptr) { + (*mutex)->name = name; + } + + int result = pthread_mutex_init(&(*mutex)->pth_mutex, &(*attr)->pth_mutex_attr); + + if (name != nullptr) { + LOG_INFO_IF(log_pthread_file, "mutex_init name={},result={}\n"); + } + + switch (result) { + case 0: return SCE_OK; + case EAGAIN: return SCE_KERNEL_ERROR_EAGAIN; + case EINVAL: return SCE_KERNEL_ERROR_EINVAL; + case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; + default: return SCE_KERNEL_ERROR_EINVAL; + } +} +int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) { + *attr = new PthreadMutexattrInternal{}; + + int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr); + + result = (result == 0 ? scePthreadMutexattrSettype(attr, 1) : result); + result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result); + + switch (result) { + case 0: return SCE_OK; + case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; + default: return SCE_KERNEL_ERROR_EINVAL; + } +} + +int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) { + int ptype = PTHREAD_MUTEX_DEFAULT; + switch (type) { + case 1: ptype = PTHREAD_MUTEX_ERRORCHECK; break; + case 2: ptype = PTHREAD_MUTEX_RECURSIVE; break; + case 3: + case 4: ptype = PTHREAD_MUTEX_NORMAL; break; + default: LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSettype invalid type: {}\n", type); std::exit(0); + } + + int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype); + + return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; +} + +int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) { + int pprotocol = PTHREAD_PRIO_NONE; + switch (protocol) { + case 0: pprotocol = PTHREAD_PRIO_NONE; break; + case 1: pprotocol = PTHREAD_PRIO_INHERIT; break; + case 2: pprotocol = PTHREAD_PRIO_PROTECT; break; + default: LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSetprotocol invalid protocol: {}\n", protocol); std::exit(0); + } + + int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that pprotocol has issues in winpthreads + (*attr)->pprotocol = pprotocol; + + return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; +} + +int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr) { + LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_init redirect to scePthreadMutexInit\n"); + int result = scePthreadMutexInit(mutex, attr, nullptr); + if (result < 0) { + BREAKPOINT(); // posix calls different only for their return values + } + return result; +} + +void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) { + LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit); + LIB_FUNCTION("F8bUHwAG284", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrInit); + LIB_FUNCTION("iMp8QpE+XO4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSettype); + LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol); + // posix calls + LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init); +} + +} // namespace Core::Libraries::LibKernel diff --git a/src/core/hle/libraries/libkernel/thread_management.h b/src/core/hle/libraries/libkernel/thread_management.h index 4dd50eb9..68d4fe5b 100644 --- a/src/core/hle/libraries/libkernel/thread_management.h +++ b/src/core/hle/libraries/libkernel/thread_management.h @@ -3,15 +3,25 @@ #include #include -#include "common/types.h" + #include -namespace Core::Kernel { +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Core::Libraries::LibKernel { struct PthreadAttrInternal; +struct PthreadMutexInternal; +struct PthreadMutexattrInternal; -using SceKernelSchedParam = ::sched_param; +using SceKernelSchedParam = ::sched_param; using ScePthreadAttr = PthreadAttrInternal*; +using ScePthreadMutex = PthreadMutexInternal*; +using ScePthreadMutexattr = PthreadMutexattrInternal*; struct PthreadInternal { u08 reserved[4096]; @@ -29,14 +39,46 @@ struct PthreadAttrInternal { pthread_attr_t pth_attr; }; -class PThreadCxt {}; +struct PthreadMutexInternal { + u08 reserved[256]; + std::string name; + pthread_mutex_t pth_mutex; +}; +struct PthreadMutexattrInternal { + u08 reserved[64]; + pthread_mutexattr_t pth_mutex_attr; + int pprotocol; +}; + +class PThreadCxt { + public: + ScePthreadMutexattr* getDefaultMutexattr() { return &m_default_mutexattr; } + void setDefaultMutexattr(ScePthreadMutexattr attr) { m_default_mutexattr = attr; } + + private: + ScePthreadMutexattr m_default_mutexattr = nullptr; +}; +void init_pthreads(); void Pthread_Init_Self_MainThread(); -int scePthreadAttrInit(ScePthreadAttr* attr); -int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate); -int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched); -int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param); -int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy); +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); -} // namespace Core::Kernel +/*** + * 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); +/**** + * Posix calls + */ +int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr); + +void pthreadSymbolsRegister(Loader::SymbolsResolver* sym); +} // namespace Core::Libraries::LibKernel diff --git a/src/main.cpp b/src/main.cpp index 4c727527..d9d56865 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,22 @@ -#include -#include -#include -#include #include #include +#include + +#include +#include +#include + +#include "Util/config.h" #include "common/discord.h" -#include "common/types.h" #include "common/log.h" #include "common/singleton.h" +#include "common/types.h" #include "core/PS4/HLE/Graphics/video_out.h" -#include "Util/config.h" -#include "emulator.h" #include "core/hle/libraries/libs.h" #include "core/linker.h" #include "emuTimer.h" +#include "emulator.h" +#include int main(int argc, char* argv[]) { if (argc == 1) { @@ -22,6 +25,7 @@ int main(int argc, char* argv[]) { } Config::load("config.toml"); Common::Log::Init(true); + Core::Libraries::LibKernel::init_pthreads(); auto width = Config::getScreenWidth(); auto height = Config::getScreenHeight(); Emu::emuInit(width, height); @@ -34,11 +38,7 @@ int main(int argc, char* argv[]) { auto linker = Common::Singleton::Instance(); Core::Libraries::InitHLELibs(&linker->getHLESymbols()); linker->LoadModule(path); - std::jthread mainthread( - [linker](std::stop_token stop_token, void*) { - linker->Execute(); - }, - nullptr); + std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); }, nullptr); Discord::RPC discordRPC; discordRPC.init(); discordRPC.update(Discord::RPCStatus::Idling, "");