Kernel/LibC: Implement sigsuspend

This commit is contained in:
Bananymous 2025-08-20 20:14:54 +03:00
parent 49122cf729
commit 247743ef9c
6 changed files with 38 additions and 0 deletions

View File

@ -193,6 +193,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact); BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
BAN::ErrorOr<long> sys_sigpending(sigset_t* set); BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset); BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
BAN::ErrorOr<long> sys_sigsuspend(const sigset_t* set);
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime); BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
BAN::ErrorOr<long> sys_yield(); BAN::ErrorOr<long> sys_yield();

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <BAN/NoCopyMove.h> #include <BAN/NoCopyMove.h>
#include <BAN/Optional.h>
#include <BAN/RefPtr.h> #include <BAN/RefPtr.h>
#include <BAN/UniqPtr.h> #include <BAN/UniqPtr.h>
#include <kernel/InterruptStack.h> #include <kernel/InterruptStack.h>
@ -60,6 +61,7 @@ namespace Kernel
// Returns true if handled signal had SA_RESTART // Returns true if handled signal had SA_RESTART
bool handle_signal(int signal = 0); bool handle_signal(int signal = 0);
void add_signal(int signal); void add_signal(int signal);
void set_suspend_signal_mask(uint64_t sigmask);
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout // blocks current thread and returns either on unblock, eintr, spuriously or after timeout
// if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake // if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
@ -160,6 +162,7 @@ namespace Kernel
uint64_t m_signal_pending_mask { 0 }; uint64_t m_signal_pending_mask { 0 };
uint64_t m_signal_block_mask { 0 }; uint64_t m_signal_block_mask { 0 };
BAN::Optional<uint64_t> m_signal_suspend_mask;
SpinLock m_signal_lock; SpinLock m_signal_lock;
static_assert(_SIGMAX < 64); static_assert(_SIGMAX < 64);

View File

@ -2651,6 +2651,20 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_sigsuspend(const sigset_t* set)
{
LockGuard _(m_process_lock);
TRY(validate_pointer_access(set, sizeof(sigset_t), false));
auto& thread = Thread::current();
thread.set_suspend_signal_mask(*set & ~(SIGKILL | SIGSTOP));
while (!thread.is_interrupted_by_signal())
Processor::scheduler().block_current_thread(nullptr, -1, &m_process_lock);
return BAN::Error::from_errno(EINTR);
}
BAN::ErrorOr<long> Process::sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime) BAN::ErrorOr<long> Process::sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime)
{ {
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr); const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);

View File

@ -547,6 +547,12 @@ namespace Kernel
m_signal_pending_mask &= ~(1ull << signal); m_signal_pending_mask &= ~(1ull << signal);
process().remove_pending_signal(signal); process().remove_pending_signal(signal);
if (m_signal_suspend_mask.has_value())
{
m_signal_block_mask = m_signal_suspend_mask.value();
m_signal_suspend_mask.clear();
}
if (signal_handler == (vaddr_t)SIG_IGN) if (signal_handler == (vaddr_t)SIG_IGN)
; ;
else if (signal_handler != (vaddr_t)SIG_DFL) else if (signal_handler != (vaddr_t)SIG_DFL)
@ -643,6 +649,14 @@ namespace Kernel
Processor::scheduler().unblock_thread(this); Processor::scheduler().unblock_thread(this);
} }
void Thread::set_suspend_signal_mask(uint64_t sigmask)
{
SpinLockGuard _(m_signal_lock);
ASSERT(!m_signal_suspend_mask.has_value());
m_signal_suspend_mask = m_signal_block_mask;
m_signal_block_mask = sigmask;
}
BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns) BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns)
{ {
if (is_interrupted_by_signal()) if (is_interrupted_by_signal())

View File

@ -90,6 +90,7 @@ __BEGIN_DECLS
O(SYS_SIGACTION, sigaction) \ O(SYS_SIGACTION, sigaction) \
O(SYS_SIGPENDING, sigpending) \ O(SYS_SIGPENDING, sigpending) \
O(SYS_SIGPROCMASK, sigprocmask) \ O(SYS_SIGPROCMASK, sigprocmask) \
O(SYS_SIGSUSPEND, sigsuspend) \
O(SYS_SETITIMER, setitimer) \ O(SYS_SETITIMER, setitimer) \
O(SYS_POSIX_OPENPT, posix_openpt) \ O(SYS_POSIX_OPENPT, posix_openpt) \
O(SYS_PTSNAME, ptsname) \ O(SYS_PTSNAME, ptsname) \

View File

@ -164,3 +164,8 @@ int sigrelse(int sig)
(void)sigaddset(&set, sig); (void)sigaddset(&set, sig);
return sigprocmask(SIG_UNBLOCK, &set, nullptr); return sigprocmask(SIG_UNBLOCK, &set, nullptr);
} }
int sigsuspend(const sigset_t* sigmask)
{
return syscall(SYS_SIGSUSPEND, sigmask);
}