From 786db8074233f9fb18377912f5bd6ed80e67ef08 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 14:33:48 -0500 Subject: [PATCH 1/6] Improve posix_sem functions Use ErrSceToPosix to update g_posix_errno appropriately after sem function calls. --- .../libraries/kernel/thread_management.cpp | 147 +++++++++++++++++- 1 file changed, 140 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 6319b7c2..a38ea626 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -11,6 +11,7 @@ #include "common/singleton.h" #include "common/thread.h" #include "core/libraries/error_codes.h" +#include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" @@ -1374,15 +1375,69 @@ int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) { } int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { - return sem_init(sem, pshared, value); + int result = sem_init(sem, pshared, value); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ENOSPC: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOSPC); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { - return sem_wait(sem); + int result = sem_wait(sem); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ETIMEDOUT: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { - return sem_trywait(sem); + int result = sem_trywait(sem); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case EAGAIN : + ErrSceToPosix(ORBIS_KERNEL_ERROR_EAGAIN); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } #ifndef HAVE_SEM_TIMEDWAIT @@ -1416,19 +1471,97 @@ int sem_timedwait(sem_t* sem, const struct timespec* abstime) { #endif int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { - return sem_timedwait(sem, t); + int result = sem_timedwait(sem, t); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ETIMEDOUT: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { - return sem_post(sem); + int result = sem_post(sem); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ERANGE: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ERANGE); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { - return sem_destroy(sem); + int result = sem_destroy(sem); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ETIMEDOUT: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); + break; + case EDEADLK: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { - return sem_getvalue(sem, sval); + int result = sem_getvalue(sem, sval); + if (result == -1) { + switch (errno) { + case ENOMEM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); + break; + case EPERM: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); + break; + case ETIMEDOUT: + ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); + break; + case EDEADLK: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); + break; + case EINVAL: + default: + ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); + break; + } + } + return result; } int PS4_SYSV_ABI posix_pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* size) { From f36440dc0994b55780a5ce3cf9ef1a5e40adbdc7 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 14:55:55 -0500 Subject: [PATCH 2/6] clang-format fix --- src/core/libraries/kernel/thread_management.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index a38ea626..c904fc91 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1428,7 +1428,7 @@ int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { case EPERM: ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); break; - case EAGAIN : + case EAGAIN: ErrSceToPosix(ORBIS_KERNEL_ERROR_EAGAIN); break; case EINVAL: From 6510af90beedeba69f3c216ac7fdd75b9ac83f0c Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 15:07:19 -0500 Subject: [PATCH 3/6] another clang-format fix --- src/core/libraries/kernel/thread_management.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index c904fc91..8eb7d79b 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1388,6 +1388,7 @@ int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOSPC); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1410,6 +1411,7 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1432,6 +1434,7 @@ int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EAGAIN); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1484,6 +1487,7 @@ int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1506,6 +1510,7 @@ int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ERANGE); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1531,6 +1536,7 @@ int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; @@ -1556,6 +1562,7 @@ int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); break; case EINVAL: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; From 93f14e8ae95e753953c75a8c6d62763ce3b75b35 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 15:10:20 -0500 Subject: [PATCH 4/6] Might fix clang-format? --- .../libraries/kernel/thread_management.cpp | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 8eb7d79b..19621424 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1388,8 +1388,7 @@ int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOSPC); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1411,8 +1410,7 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1434,8 +1432,7 @@ int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EAGAIN); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1487,8 +1484,7 @@ int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1510,8 +1506,7 @@ int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_ERANGE); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1536,8 +1531,7 @@ int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } @@ -1562,8 +1556,7 @@ int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); break; case EINVAL: - - default: + default: ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); break; } From 9fce6f7c01f1328994e2ea91433cbe65f5444d84 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 17:20:21 -0500 Subject: [PATCH 5/6] Add SetPosixErrno function I used a switch statement for future proofing, as some codes differ between Windows, Mac, Linux, or Orbis. Right now I've only added the codes that should be possible to encounter. --- src/core/libraries/kernel/libkernel.cpp | 31 +++++ src/core/libraries/kernel/libkernel.h | 1 + .../libraries/kernel/thread_management.cpp | 118 ++---------------- 3 files changed, 39 insertions(+), 111 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 9657ba04..93afbc4f 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -125,6 +125,37 @@ int ErrnoToSceKernelError(int e) { return res > SCE_KERNEL_ERROR_ESTOP ? SCE_KERNEL_ERROR_UNKNOWN : res; } +void SetPosixErrno(int e) { + //Some error numbers are different between supported OSes or the PS4 + switch (e) { + case EPERM: + g_posix_errno = POSIX_EPERM; + break; + case EAGAIN: + g_posix_errno = POSIX_EAGAIN; + break; + case ENOMEM: + g_posix_errno = POSIX_ENOMEM; + break; + case EINVAL: + g_posix_errno = POSIX_EINVAL; + break; + case ENOSPC: + g_posix_errno = POSIX_ENOSPC; + break; + case ERANGE: + g_posix_errno = POSIX_ERANGE; + break; + case EDEADLK: + g_posix_errno = POSIX_EDEADLK; + break; + case ETIMEDOUT: + g_posix_errno = POSIX_ETIMEDOUT; + break; + default: + g_posix_errno = e; + } +} int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res) { LOG_INFO(Kernel_Vmm, "called addr = {}, len = {}, prot = {}, flags = {}, fd = {}, offset = {}", diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h index 5b22dea4..5b7f1e72 100644 --- a/src/core/libraries/kernel/libkernel.h +++ b/src/core/libraries/kernel/libkernel.h @@ -14,6 +14,7 @@ namespace Libraries::Kernel { void ErrSceToPosix(int result); int ErrnoToSceKernelError(int e); +void SetPosixErrno(int e); struct OrbisTimesec { time_t t; diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 19621424..68953269 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1377,21 +1377,7 @@ int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) { int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { int result = sem_init(sem, pshared, value); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ENOSPC: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOSPC); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1399,21 +1385,7 @@ int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { int result = sem_wait(sem); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ETIMEDOUT: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1421,21 +1393,7 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { int result = sem_trywait(sem); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case EAGAIN: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EAGAIN); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1473,21 +1431,7 @@ int sem_timedwait(sem_t* sem, const struct timespec* abstime) { int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { int result = sem_timedwait(sem, t); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ETIMEDOUT: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1495,21 +1439,7 @@ int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { int result = sem_post(sem); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ERANGE: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ERANGE); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1517,24 +1447,7 @@ int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { int result = sem_destroy(sem); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ETIMEDOUT: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); - break; - case EDEADLK: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } @@ -1542,24 +1455,7 @@ int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { int result = sem_getvalue(sem, sval); if (result == -1) { - switch (errno) { - case ENOMEM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ENOMEM); - break; - case EPERM: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EPERM); - break; - case ETIMEDOUT: - ErrSceToPosix(ORBIS_KERNEL_ERROR_ETIMEDOUT); - break; - case EDEADLK: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EDEADLK); - break; - case EINVAL: - default: - ErrSceToPosix(ORBIS_KERNEL_ERROR_EINVAL); - break; - } + SetPosixErrno(errno); } return result; } From 2935ca0fef9df989ab210475e61a25964401cc12 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Fri, 16 Aug 2024 17:22:06 -0500 Subject: [PATCH 6/6] clang-format fix --- src/core/libraries/kernel/libkernel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 93afbc4f..781feef8 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -126,7 +126,7 @@ int ErrnoToSceKernelError(int e) { } void SetPosixErrno(int e) { - //Some error numbers are different between supported OSes or the PS4 + // Some error numbers are different between supported OSes or the PS4 switch (e) { case EPERM: g_posix_errno = POSIX_EPERM; @@ -146,7 +146,7 @@ void SetPosixErrno(int e) { case ERANGE: g_posix_errno = POSIX_ERANGE; break; - case EDEADLK: + case EDEADLK: g_posix_errno = POSIX_EDEADLK; break; case ETIMEDOUT: