mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-14 21:28:16 +00:00
hw: introduce non-blocking signal checking
* Introduces pending_signal syscall to check for new signals for the calling thread without blocking * Implements pending_signal in the base-library specific for hw to use the new syscall Fix #3217
This commit is contained in:
committed by
Christian Helmuth
parent
3e70b53165
commit
330692350e
@ -49,4 +49,7 @@ void Signal_receiver::block_for_signal()
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
Signal Signal_receiver::pending_signal() {
|
||||
throw Signal_not_pending(); }
|
||||
|
||||
void Signal_receiver::local_submit(Signal::Data) { ASSERT_NEVER_CALLED; }
|
||||
|
@ -235,6 +235,42 @@ void Signal_receiver::block_for_signal()
|
||||
_signal_available.down();
|
||||
}
|
||||
|
||||
Signal Signal_receiver::pending_signal()
|
||||
{
|
||||
Lock::Guard contexts_lock_guard(_contexts_lock);
|
||||
Signal::Data result;
|
||||
_contexts.for_each_locked([&] (Signal_context &context) {
|
||||
|
||||
if (!context._pending) return;
|
||||
|
||||
_contexts.head(context._next);
|
||||
context._pending = false;
|
||||
result = context._curr_signal;
|
||||
context._curr_signal = Signal::Data(0, 0);
|
||||
|
||||
Trace::Signal_received trace_event(context, result.num);
|
||||
throw Context_ring::Break_for_each();
|
||||
});
|
||||
if (result.context) {
|
||||
Lock::Guard lock_guard(result.context->_lock);
|
||||
if (result.num == 0)
|
||||
warning("returning signal with num == 0");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally, we should never arrive at this point because that would
|
||||
* mean, the '_signal_available' semaphore was increased without
|
||||
* registering the signal in any context associated to the receiver.
|
||||
*
|
||||
* However, if a context gets dissolved right after submitting a
|
||||
* signal, we may have increased the semaphore already. In this case
|
||||
* the signal-causing context is absent from the list.
|
||||
*/
|
||||
throw Signal_not_pending();
|
||||
}
|
||||
|
||||
|
||||
void Signal_receiver::unblock_signal_waiter(Rpc_entrypoint &)
|
||||
{
|
||||
|
@ -159,43 +159,6 @@ Signal Signal_receiver::wait_for_signal()
|
||||
}
|
||||
|
||||
|
||||
Signal Signal_receiver::pending_signal()
|
||||
{
|
||||
Lock::Guard contexts_lock_guard(_contexts_lock);
|
||||
Signal::Data result;
|
||||
_contexts.for_each_locked([&] (Signal_context &context) {
|
||||
|
||||
if (!context._pending) return;
|
||||
|
||||
_contexts.head(context._next);
|
||||
context._pending = false;
|
||||
result = context._curr_signal;
|
||||
context._curr_signal = Signal::Data(0, 0);
|
||||
|
||||
Trace::Signal_received trace_event(context, result.num);
|
||||
throw Context_ring::Break_for_each();
|
||||
});
|
||||
if (result.context) {
|
||||
Lock::Guard lock_guard(result.context->_lock);
|
||||
if (result.num == 0)
|
||||
warning("returning signal with num == 0");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally, we should never arrive at this point because that would
|
||||
* mean, the '_signal_available' semaphore was increased without
|
||||
* registering the signal in any context associated to the receiver.
|
||||
*
|
||||
* However, if a context gets dissolved right after submitting a
|
||||
* signal, we may have increased the semaphore already. In this case
|
||||
* the signal-causing context is absent from the list.
|
||||
*/
|
||||
throw Signal_not_pending();
|
||||
}
|
||||
|
||||
|
||||
Signal_receiver::~Signal_receiver()
|
||||
{
|
||||
Lock::Guard contexts_lock_guard(_contexts_lock);
|
||||
|
Reference in New Issue
Block a user