Merge pull request #4383 from pushkarreddyy/feat/libkernel-sigpending-sigsuspend
feat(libkernel): implement sigpending
This commit is contained in:
commit
7d757bbf0a
|
|
@ -583,6 +583,17 @@ int APS5_VABI pause_nid_postfix(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int APS5_VABI sigpending_nid_postfix(GuestSignalSet* set) {
|
||||
if (set == nullptr) { *__error_nid_postfix() = 14; return -1; }
|
||||
auto& pending = Pending();
|
||||
std::lock_guard lock(pending.lock);
|
||||
set->bits[0] = pending.words[0].load(std::memory_order_relaxed) & blockedMask.load();
|
||||
set->bits[1] = 0;
|
||||
set->bits[2] = 0;
|
||||
set->bits[3] = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
#include <chrono>
|
||||
#include <thread>
|
||||
using Handler = void (APS5_VABI *)(int);
|
||||
struct GuestSignalSet {
|
||||
std::uint32_t bits[4];
|
||||
};
|
||||
extern "C" {
|
||||
Handler APS5_VABI signal_nid_postfix(int, Handler);
|
||||
int APS5_VABI raise_nid_postfix(int);
|
||||
|
|
@ -18,10 +21,8 @@ int APS5_VABI pthread_sigmask_nid_postfix(int, const void*, void*);
|
|||
int* APS5_VABI __error_nid_postfix();
|
||||
int APS5_VABI _is_signal_return_nid_postfix(std::uint64_t);
|
||||
unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int);
|
||||
int APS5_VABI sigpending_nid_postfix(GuestSignalSet*);
|
||||
}
|
||||
struct GuestSignalSet {
|
||||
std::uint32_t bits[4];
|
||||
};
|
||||
struct GuestSigaction {
|
||||
std::uintptr_t handler;
|
||||
int flags;
|
||||
|
|
@ -200,4 +201,24 @@ int main() {
|
|||
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0 && current.handler == static_cast<std::uintptr_t>(-1) && current.flags == 0x2);
|
||||
Require(signal_nid_postfix(13, nullptr) == invalid);
|
||||
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0 && current.handler == 0);
|
||||
*__error_nid_postfix() = 0;
|
||||
Require(sigpending_nid_postfix(nullptr) == -1);
|
||||
Require(*__error_nid_postfix() == 14);
|
||||
*__error_nid_postfix() = 42;
|
||||
GuestSignalSet pendingSignals{{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}};
|
||||
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
||||
Require(pendingSignals.bits[0] == 0 && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
||||
Require(*__error_nid_postfix() == 42);
|
||||
Require(signal_nid_postfix(15, nullptr) == Callback);
|
||||
Require(signal_nid_postfix(15, Callback) == nullptr);
|
||||
received = 0;
|
||||
Require(sigprocmask_nid_postfix(1, &termMask, nullptr) == 0);
|
||||
Require(raise_nid_postfix(15) == 0 && received == 0);
|
||||
pendingSignals = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}};
|
||||
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
||||
Require(pendingSignals.bits[0] == (1u << 14) && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
||||
Require(sigprocmask_nid_postfix(2, &termMask, nullptr) == 0 && received == 15);
|
||||
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
||||
Require(pendingSignals.bits[0] == 0 && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
||||
Require(signal_nid_postfix(15, nullptr) == Callback);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@
|
|||
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) reaches a thread that waits in an alertable `TimedWait` wait through an APC. A thread blocked anywhere else, including all waits under `APS5_COARSE_TIMED_WAITS` and host waits inside the emulator, is redirected and runs the handler only when that wait returns
|
||||
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows runs the handler wherever the target thread was interrupted. It waits only while the thread is inside winpthreads or restoring a context through `NtContinue`, and throws if that lasts 1 s, so a handler that calls into other host code the thread was interrupted in, such as the C runtime's heap or a lock of the emulator, can deadlock on it or reenter it
|
||||
- [sigaltstack](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) records each thread's alternate signal stack and reports it back, following FreeBSD's `kern_sigaltstack` (`EINVAL` for flags other than `SS_DISABLE`, `ENOMEM` below `MINSIGSTKSZ` 2048), but handlers never run on it, so `SS_ONSTACK` and `EPERM` are never reported
|
||||
- [sigpending](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) reports the intersection of the process-wide pending set of `sigtimedwait` and the blocked mask of `_sigprocmask`, as FreeBSD's `sys_sigpending` intersects the pending list with `td_sigmask`, and returns -1 with `EFAULT` for a null set. Because `_sigprocmask` keeps only the first 32 signals, signals 33 to 128 are never blocked and never appear in the set, and setting `SIG_IGN` (or `SIG_DFL` on a signal whose default action is to ignore) does not clear a signal that was already marked pending. PPSA99420 imports it
|
||||
- [scePthreadJoin, scePthreadCreate](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) - on a PS5 (firmware 13.60) joining a thread a second time returns `ESRCH` (`0x80020003`); here a joined thread is released, so a second join reads freed memory. A null entry crashed the payload and still throws. Joining the calling thread returns `EDEADLK` and a zeroed attribute creates a default thread, as on the console
|
||||
- [Thread cancellation](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) follows FreeBSD libthr (states and types 0/1 and 0/2, `PTHREAD_CANCELED` 1, the `_pthread_cleanup_info` node layout), not measured on the console. A request is acted on only in `scePthreadTestcancel`, the condition variable, `sem` and `scePthreadSem` waits, `scePthreadJoin` and the sleeps, and their POSIX names; file and socket calls are not cancellation points. A sleep is not interrupted: the thread exits when it ends. The asynchronous type acts like the deferred one, except at the two set calls.
|
||||
- [cpuset_setaffinity](../../../core/libs/prx/libkernel/Pthread/Posix/Thread.cpp) (libkernel) - only the calling thread or the calling process is handled; other levels (ROOT/CPUSET), other scopes (CPUSET/JAIL) and other threads throw as unmodelled, invalid levels or scopes return `EINVAL` and unknown thread or process IDs return `ESRCH`, following FreeBSD's `cpuset_setaffinity`. Bits outside `sceKernelGetAvailableCpumask` are dropped, and a mask with none of those bits fails with `EDEADLK`, as FreeBSD does when the new set has no CPU in common with the parent set
|
||||
|
|
|
|||
Loading…
Reference in New Issue