1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:38:11 +00:00

Kernel+LibC: Implement sigtimedwait()

This includes a new Thread::Blocker called SignalBlocker which blocks
until a signal of a matching type is pending. The current Blocker
implementation in the Kernel is very complicated, but cleaning it up is
a different yak for a different day.
This commit is contained in:
Idan Horowitz 2021-12-12 01:01:42 +02:00
parent 13d98999b7
commit 762e047ec9
8 changed files with 120 additions and 0 deletions

View file

@ -446,6 +446,48 @@ void Thread::SelectBlocker::was_unblocked(bool did_timeout)
}
}
Thread::SignalBlocker::SignalBlocker(sigset_t pending_set, siginfo_t& result)
: m_pending_set(pending_set)
, m_result(result)
{
}
void Thread::SignalBlocker::will_unblock_immediately_without_blocking(UnblockImmediatelyReason unblock_immediately_reason)
{
if (unblock_immediately_reason != UnblockImmediatelyReason::TimeoutInThePast)
return;
// If the specified timeout is 0 the caller is simply trying to poll once for pending signals,
// so simply calling check_pending_signals should populate the requested information.
check_pending_signals(false);
}
bool Thread::SignalBlocker::setup_blocker()
{
return add_to_blocker_set(thread().m_signal_blocker_set);
}
bool Thread::SignalBlocker::check_pending_signals(bool from_add_blocker)
{
{
SpinlockLocker lock(m_lock);
if (m_did_unblock)
return false;
auto matching_pending_signal = __builtin_ffsl(thread().pending_signals() & m_pending_set);
if (matching_pending_signal == 0)
return false;
m_did_unblock = true;
m_result = {};
m_result.si_signo = matching_pending_signal;
m_result.si_code = 0; // FIXME: How can we determine this?
}
if (!from_add_blocker)
unblock_from_blocker();
return true;
}
Thread::WaitBlockerSet::ProcessBlockInfo::ProcessBlockInfo(NonnullRefPtr<Process>&& process, WaitBlocker::UnblockFlags flags, u8 signal)
: process(move(process))
, flags(flags)