Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/libs/prx/libkernel/Pthread/Posix/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ int APS5_VABI pthread_attr_get_np_nid_postfix(Pthread thread, PthreadAttr* attr)
p->stackAddress = thread->stackAddress;
p->_detachstate = thread->_detached ? 1 : 0;
p->_schedpriority = thread->priority.load(std::memory_order_relaxed);
p->_schedpolicy = thread->schedPolicy.load(std::memory_order_relaxed);
p->_affinity = thread->affinity.load(std::memory_order_relaxed);
p->_affinityExplicit = true;
p->_scope = thread->scope;
Expand Down
2 changes: 1 addition & 1 deletion core/libs/prx/libkernel/Pthread/src/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr) {
(*attr)->stackAddress = thread->stackAddress;
(*attr)->_detachstate = thread->_detached ? DETACH_DETACHED : DETACH_JOINABLE;
(*attr)->_schedpriority = thread->priority.load(std::memory_order_relaxed);
(*attr)->_schedpolicy = SCHED_FIFO_PS5;
(*attr)->_schedpolicy = thread->schedPolicy.load(std::memory_order_relaxed);
(*attr)->_inheritsched = 4;
(*attr)->_affinity = thread->affinity.load(std::memory_order_relaxed);
(*attr)->_affinityExplicit = true;
Expand Down
56 changes: 56 additions & 0 deletions core/libs/tests/GuestPthreadAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ int APS5_VABI pthread_attr_setinheritsched_nid_postfix(PthreadAttr* attr, int in
int APS5_VABI pthread_attr_getscope_nid_postfix(const PthreadAttr* attr, int* scope);
int APS5_VABI pthread_attr_setscope_nid_postfix(PthreadAttr* attr, int scope);
int APS5_VABI pthread_attr_get_np_nid_postfix(Pthread thread, PthreadAttr* attr);
int APS5_VABI pthread_attr_getschedpolicy_nid_postfix(const PthreadAttr* attr, int* policy);
int APS5_VABI pthread_attr_setschedpolicy_nid_postfix(PthreadAttr* attr, int policy);
Pthread APS5_VABI scePthreadSelf();
int APS5_VABI scePthreadGetschedparam(Pthread thread, int* policy, KernelSchedParam* param);
int APS5_VABI scePthreadSetschedparam(Pthread thread, int policy, const KernelSchedParam* param);
int APS5_VABI pthread_setschedparam_nid_postfix(Pthread thread, int policy, const KernelSchedParam* param);
}

static constexpr int SCE_OK = 0;
static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast<int>(0x80020016);
static constexpr int EXPLICIT_SCHED = 0;
static constexpr int INHERIT_SCHED = 4;
static constexpr int GUEST_SCHED_FIFO = 1;
static constexpr int GUEST_SCHED_RR = 3;
static constexpr int SCOPE_PROCESS = 0;
static constexpr int SCOPE_SYSTEM = 2;
static constexpr int DETACH_JOINABLE = 0;
Expand Down Expand Up @@ -217,11 +225,59 @@ static void CheckThreadScope() {
Require(scePthreadJoin(inheritedThread, nullptr) == SCE_OK);
}

static void CheckThreadSchedulingPolicy(int inheritSched) {
Pthread self = scePthreadSelf();
int originalPolicy = -1;
KernelSchedParam originalParam{};
Require(scePthreadGetschedparam(self, &originalPolicy, &originalParam) == SCE_OK);
Require(scePthreadSetschedparam(self, inheritSched == EXPLICIT_SCHED ? GUEST_SCHED_FIFO : GUEST_SCHED_RR, &originalParam) == SCE_OK);

PthreadAttr attr = nullptr;
Require(scePthreadAttrInit(&attr) == SCE_OK);
Require(pthread_attr_setinheritsched_nid_postfix(&attr, inheritSched) == 0);
Require(pthread_attr_setschedpolicy_nid_postfix(&attr,
inheritSched == EXPLICIT_SCHED ? GUEST_SCHED_RR : GUEST_SCHED_FIFO) == 0);

std::promise<void> release;
auto released = release.get_future();
Pthread thread = nullptr;
Require(scePthreadCreate(&thread, &attr, Worker, &released, nullptr) == SCE_OK);
Require(scePthreadAttrDestroy(&attr) == SCE_OK);
Require(scePthreadSetschedparam(self, originalPolicy, &originalParam) == SCE_OK);

PthreadAttr queryAttr = nullptr;
Require(scePthreadAttrInit(&queryAttr) == SCE_OK);
const auto requirePolicy = [&](int expectedPolicy) {
using QueryAttributes = int (APS5_VABI *)(Pthread, PthreadAttr*);
const QueryAttributes queries[] = {scePthreadAttrGet, pthread_attr_get_np_nid_postfix};
for (const auto query : queries) {
Require(pthread_attr_setschedpolicy_nid_postfix(&queryAttr,
expectedPolicy == GUEST_SCHED_RR ? GUEST_SCHED_FIFO : GUEST_SCHED_RR) == 0);
Require(query(thread, &queryAttr) == 0);
int policy = -1;
Require(pthread_attr_getschedpolicy_nid_postfix(&queryAttr, &policy) == 0);
Require(policy == expectedPolicy);
}
};
requirePolicy(GUEST_SCHED_RR);
const KernelSchedParam updatedParam{UPDATED_PRIORITY};
Require(scePthreadSetschedparam(thread, GUEST_SCHED_FIFO, &updatedParam) == SCE_OK);
requirePolicy(GUEST_SCHED_FIFO);
Require(pthread_setschedparam_nid_postfix(thread, GUEST_SCHED_RR, &updatedParam) == 0);
requirePolicy(GUEST_SCHED_RR);
Require(scePthreadAttrDestroy(&queryAttr) == SCE_OK);

release.set_value();
Require(scePthreadJoin(thread, nullptr) == SCE_OK);
}

int main() {
CheckStackSizeLimit();
CheckSoloSched();
CheckSchedulingAttributes();
CheckThreadScope();
CheckThreadSchedulingPolicy(EXPLICIT_SCHED);
CheckThreadSchedulingPolicy(INHERIT_SCHED);
PthreadAttr attr = nullptr;
Require(scePthreadAttrInit(&attr) == SCE_OK);
Require(scePthreadAttrSetinheritsched(&attr, EXPLICIT_SCHED) == SCE_OK);
Expand Down
2 changes: 2 additions & 0 deletions docs/dev/debt/libkernel.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

### Unknown function info

- [pthread_attr_get_np](../../../core/libs/prx/libkernel/Pthread/Posix/Attr.cpp) and [scePthreadAttrGet](../../../core/libs/prx/libkernel/Pthread/src/Attr.cpp) (libkernel) report the stored current scheduling policy, including inherited or explicit creation and successful scheduling changes, following FreeBSD 11.4's [thr_attr.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_attr.c) and [thr_setschedparam.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_setschedparam.c). Applying the same rule to the SCE query is inferred from the shared thread attributes; its policy result has not been measured on PS5 hardware.

- [getlogin_r](../../../core/libs/prx/libkernel/System/src/Login.cpp) (libkernel) returns the host effective account name: `GetUserNameW` as UTF-8 on Windows and `getpwuid_r(geteuid())` on POSIX. A valid account returns a name even without a login session; host `getlogin_r`, `USER` and `LOGNAME` are not consulted. The console's login name and behaviour without a session are unknown. Account lookup or encoding failures, a missing or empty account name, and POSIX account records exceeding the 16 KiB lookup buffer throw; there is no replacement name or retry. A short guest buffer returns `ERANGE` without modifying it, and a null output returns `EFAULT`.
- [sceCoredumpGetThreadContextInfo](../../../core/libs/prx/libkernel/System/src/Coredump.cpp) (libkernel, NID `ShChva57wIM`) - declared as a throwing stub. The pointer and size arguments and integer return type follow [SharpProspero's PS5 bindings](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Kernel/KernelSystem.cs). The context structure and console behavior are unverified; the stub does not read or write caller memory. PPSA01736 imports it
- [sceKernelGetSystemSwVersion](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports baseline system software version `0x01000000` ("01.000.000") for ProsperoStore (PPSA99000). The 0x28-byte layout (`uint64_t size` at 0, `versionString` at 8 and `version` at 0x24) matches [ProsperoStore's caller](https://github.com/blackbearreloaded/ProsperoStore/blob/20584011/src/diag/trace.cpp#L20-L26), [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/811bfcd7d1/src/core/libraries/kernel/kernel.h#L45-L49), [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6/kernel/ps4_libkernel.pas#L502-L506) and [OpenOrbis](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/blob/0a1aaf9dd4/include/orbis/_types/kernel.h#L256-L260). These sources support the structure layout, but not the reported version value: the console firmware version remains unverified. The checks are unverified too: a null pointer returns `SCE_KERNEL_ERROR_EFAULT` and a `size` other than 0x28 returns `SCE_KERNEL_ERROR_EINVAL`, while shadPS4 returns success for null and never reads `size`.
Expand Down
Loading