diff --git a/core/libs/prx/libkernel/System/src/Process.cpp b/core/libs/prx/libkernel/System/src/Process.cpp index 32019c4bd..c3f016425 100644 --- a/core/libs/prx/libkernel/System/src/Process.cpp +++ b/core/libs/prx/libkernel/System/src/Process.cpp @@ -107,9 +107,8 @@ ProcessArguments& getProcessArguments() { return arguments; } -void validateSchedulingPolicy(int policy) { - if (policy < 1 || policy > 3) - throw std::invalid_argument("Unsupported guest scheduling policy"); +bool hasPriorityRange(int policy) { + return policy == 1 || policy == 3; } constexpr int guestFault = 14; @@ -363,13 +362,19 @@ void APS5_VABI sync_nid_postfix(void) { } int APS5_VABI sched_get_priority_max_nid_postfix(int policy) { - validateSchedulingPolicy(policy); - return 256; + if (!hasPriorityRange(policy)) { + *__error_nid_postfix() = guestInvalid; + return -1; + } + return 767; } int APS5_VABI sched_get_priority_min_nid_postfix(int policy) { - validateSchedulingPolicy(policy); - return 767; + if (!hasPriorityRange(policy)) { + *__error_nid_postfix() = guestInvalid; + return -1; + } + return 256; } int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) { diff --git a/core/libs/tests/GuestSchedPriority.cpp b/core/libs/tests/GuestSchedPriority.cpp index 7f135f5ef..0e9d418d1 100644 --- a/core/libs/tests/GuestSchedPriority.cpp +++ b/core/libs/tests/GuestSchedPriority.cpp @@ -1,19 +1,23 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include #include +extern "C" int* APS5_VABI __error_nid_postfix(); extern "C" { int APS5_VABI sched_get_priority_max_nid_postfix(int policy); int APS5_VABI sched_get_priority_min_nid_postfix(int policy); } static void Require(bool value) { if (!value) std::abort(); } static bool Rejects(int policy) { - try { sched_get_priority_max_nid_postfix(policy); } catch (const std::invalid_argument&) { return true; } - return false; + *__error_nid_postfix() = 0; + const bool max = sched_get_priority_max_nid_postfix(policy) == -1 && *__error_nid_postfix() == 22; + *__error_nid_postfix() = 0; + return max && sched_get_priority_min_nid_postfix(policy) == -1 && *__error_nid_postfix() == 22; } int main() { - for (int policy : {1, 2, 3}) { - Require(sched_get_priority_max_nid_postfix(policy) == 256); - Require(sched_get_priority_min_nid_postfix(policy) == 767); + Require(Rejects(-1) && Rejects(2) && Rejects(5)); + for (int policy : {1, 3}) { + Require(sched_get_priority_max_nid_postfix(policy) == 767); + Require(sched_get_priority_min_nid_postfix(policy) == 256); } Require(Rejects(0) && Rejects(4)); } diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 20ddec679..f2974bd4f 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -372,7 +372,7 @@ Throughout the project, every function at every stage either **does exactly what - [scePlayerReviewDialogOpen, scePlayerReviewDialogGetResult](../../core/libs/prx/libSceCdlgPlayerReview/Export.cpp) (libSceCdlgPlayerReview) - the PS5-only dialog has no public reference: the parameter is not read and the result is assumed to start with the 32-bit common dialog result, as `sceWebBrowserDialogGetResult` assumes - [sceHttpWaitRequest](../../core/libs/prx/libSceHttp/Export.cpp) (libSceHttp) - the timeout is assumed to be in microseconds and a negative timeout to wait without limit; the invalid-value error for a null handle or event array or a non-positive event count is assumed, not measured. No request is ever pending, so a wait returns 0 events when its timeout passes - [sceVideoOutAddPreVblankStartEvent](../../core/libs/prx/libSceVideoOut/src/Event.cpp) (libSceVideoOut) - how long before the vblank the console signals pre-vblank start is unknown. The event is triggered on each emulated vblank tick immediately before the vblank event, with its own count as the event data -- [sched_get_priority_max, sched_get_priority_min](../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - `SCHED_OTHER` (2) reports the same 256 to 767 range as `SCHED_FIFO` and `SCHED_RR`; the console's answer is unverified. FreeBSD accepts `SCHED_OTHER` with its own range, and shadPS4 rejects it with `EINVAL`. `pthread_setschedparam` ignores the policy, so a priority taken from this range applies +- [sched_get_priority_max, sched_get_priority_min](../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - measured on a PS5 (firmware 13.60): `SCHED_FIFO` (1) and `SCHED_RR` (3) report a maximum of 767 and a minimum of 256, and every other policy, `SCHED_OTHER` (2) included, returns -1 with `EINVAL`. `pthread_setschedparam` ignores the policy and does not check the priority, where the console rejects `SCHED_OTHER` and priorities below 256 with `EINVAL` - [inet_pton, inet_ntop](../../core/libs/prx/libkernel/Socket/src/AddressConversion.cpp) (libkernel) - the text forms are assumed to be those of FreeBSD 11.4 and are unverified on a console: `inet_pton` accepts only four decimal parts without leading zeros for `AF_INET` and the RFC 4291 forms for `AF_INET6` (one `::` standing for at least one group, a dotted-quad tail only as the last 32 bits, no zone id), and `inet_ntop` prints lowercase hex with the first longest run of two or more zero groups compressed, and a dotted tail only for `::a.b.c.d` and `::ffff:a.b.c.d`. They no longer depend on the host resolver library - [gethostbyname](../../core/libs/prx/libScePosixForWebKit/Resolver.cpp) (libScePosixForWebKit) - numeric IPv4 forms, trailing whitespace and 64-bit accumulation follow FreeBSD 11.4 [inet_aton](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/inet/inet_addr.c); clearing the resolver error on numeric success follows [fakeaddr](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/net/gethostnamadr.c). Exact PS5 behavior is unverified; hostname lookup still uses the host resolver