diff --git a/src/core/hle/libraries/libkernel/thread_management.cpp b/src/core/hle/libraries/libkernel/thread_management.cpp index 0e982e0b..6d82be94 100644 --- a/src/core/hle/libraries/libkernel/thread_management.cpp +++ b/src/core/hle/libraries/libkernel/thread_management.cpp @@ -15,9 +15,14 @@ constexpr bool log_pthread_file = true; // disable it to disable logging void init_pthreads() { g_pthread_cxt = new PThreadCxt{}; + // default mutex init ScePthreadMutexattr default_mutexattr = nullptr; scePthreadMutexattrInit(&default_mutexattr); g_pthread_cxt->setDefaultMutexattr(default_mutexattr); + // default cond init + ScePthreadCondattr default_condattr = nullptr; + scePthreadCondattrInit(&default_condattr); + g_pthread_cxt->setDefaultCondattr(default_condattr); } void pthreadInitSelfMainThread() { @@ -62,7 +67,7 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst default: LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetdetachstate invalid detachstate: {}\n", detachstate); std::exit(0); } - //int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work correctly + // int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work correctly int result = 0; (*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED); @@ -177,7 +182,7 @@ int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMut if (name != nullptr) { (*mutex)->name = name; } else { - (*mutex)->name = "noname"; + (*mutex)->name = "nonameMutex"; } int result = pthread_mutex_init(&(*mutex)->pth_mutex, &(*attr)->pth_mutex_attr); @@ -275,6 +280,81 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { } } +/**** + * Cond calls + */ +void* createCond(void* addr) { + if (addr == nullptr || *static_cast(addr) != nullptr) { + return addr; + } + auto vaddr = reinterpret_cast(addr); + + std::string name = fmt::format("cond{:#x}", vaddr); + scePthreadCondInit(static_cast(addr), nullptr, name.c_str()); + return addr; +} + +int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr, const char* name) { + if (cond == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + if (attr == nullptr) { + attr = g_pthread_cxt->getDefaultCondattr(); + } + + *cond = new PthreadCondInternal{}; + + if (name != nullptr) { + (*cond)->name = name; + } else { + (*cond)->name = "nonameCond"; + } + + int result = pthread_cond_init(&(*cond)->cond, &(*attr)->cond_attr); + + if (name != nullptr) { + LOG_INFO_IF(log_pthread_file, "cond init name={},result={}\n", (*cond)->name, result); + } + + 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 scePthreadCondattrInit(ScePthreadCondattr* attr) { + *attr = new PthreadCondAttrInternal{}; + + int result = pthread_condattr_init(&(*attr)->cond_attr); + + switch (result) { + case 0: return SCE_OK; + case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; + default: return SCE_KERNEL_ERROR_EINVAL; + } +} + +int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) { + PRINT_FUNCTION_NAME(); + cond = static_cast(createCond(cond)); + + if (cond == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + int result = pthread_cond_broadcast(&(*cond)->cond); + + LOG_INFO_IF(log_pthread_file, "cond broadcast name={},result={}\n", (*cond)->name, result); + + return (result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL); +} +/**** + * Posix calls + */ 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); @@ -305,6 +385,16 @@ int PS4_SYSV_ABI posix_pthread_mutex_unlock(ScePthreadMutex* mutex) { return result; } +int PS4_SYSV_ABI posix_pthread_cond_broadcast(ScePthreadCond* cond) { + LOG_INFO_IF(log_pthread_file, "posix posix_pthread_cond_broadcast redirect to scePthreadCondBroadcast\n"); + int result = scePthreadCondBroadcast(cond); + 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(Loader::SymbolsResolver* sym) { LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy); LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate); @@ -315,22 +405,27 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) { LIB_FUNCTION("3qxgM4ezETA", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetaffinity); LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, scePthreadSetaffinity); LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, scePthreadCreate); - //mutex calls + // mutex calls 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); LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock); LIB_FUNCTION("tn3VlD0hG60", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexUnlock); - + //cond calls + LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit); + LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit); + LIB_FUNCTION("JGgj7Uvrl+A", "libkernel", 1, "libkernel", 1, 1, scePthreadCondBroadcast); // posix calls LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init); LIB_FUNCTION("7H0iTOciTLo", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_lock); LIB_FUNCTION("2Z+PpY6CaJg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_unlock); + LIB_FUNCTION("mkx2fVhNMsg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_broadcast); // openorbis weird functions LIB_FUNCTION("7H0iTOciTLo", "libkernel", 1, "libkernel", 1, 1, posix_pthread_mutex_lock); LIB_FUNCTION("2Z+PpY6CaJg", "libkernel", 1, "libkernel", 1, 1, posix_pthread_mutex_unlock); + LIB_FUNCTION("mkx2fVhNMsg", "libkernel", 1, "libkernel", 1, 1, posix_pthread_cond_broadcast); } } // namespace Core::Libraries::LibKernel \ No newline at end of file diff --git a/src/core/hle/libraries/libkernel/thread_management.h b/src/core/hle/libraries/libkernel/thread_management.h index 74f8d7b9..dc8e9d79 100644 --- a/src/core/hle/libraries/libkernel/thread_management.h +++ b/src/core/hle/libraries/libkernel/thread_management.h @@ -105,11 +105,18 @@ int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int p 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); + /**** * 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); void pthreadSymbolsRegister(Loader::SymbolsResolver* sym); } // namespace Core::Libraries::LibKernel \ No newline at end of file