mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 07:08:18 +00:00
@ -46,6 +46,19 @@ namespace Genode {
|
||||
static char const *initial_ep_name() { return "ep"; }
|
||||
|
||||
|
||||
void Entrypoint::Signal_proxy_component::signal()
|
||||
{
|
||||
/* XXX introduce while-pending loop */
|
||||
try {
|
||||
Signal sig = ep._sig_rec->pending_signal();
|
||||
ep._dispatch_signal(sig);
|
||||
} catch (Signal_receiver::Signal_not_pending) { }
|
||||
|
||||
ep._execute_post_signal_hook();
|
||||
ep._process_deferred_signals();
|
||||
}
|
||||
|
||||
|
||||
void Entrypoint::_dispatch_signal(Signal &sig)
|
||||
{
|
||||
Signal_dispatcher_base *dispatcher = 0;
|
||||
@ -58,6 +71,35 @@ void Entrypoint::_dispatch_signal(Signal &sig)
|
||||
}
|
||||
|
||||
|
||||
void Entrypoint::_defer_signal(Signal &sig)
|
||||
{
|
||||
Signal_context *context = sig.context();
|
||||
|
||||
Lock::Guard guard(_deferred_signals_mutex);
|
||||
_deferred_signals.remove(context->deferred_le());
|
||||
_deferred_signals.insert(context->deferred_le());
|
||||
}
|
||||
|
||||
|
||||
void Entrypoint::_process_deferred_signals()
|
||||
{
|
||||
for (;;) {
|
||||
Signal_context *context = nullptr;
|
||||
{
|
||||
Lock::Guard guard(_deferred_signals_mutex);
|
||||
if (!_deferred_signals.first()) return;
|
||||
|
||||
context = _deferred_signals.first()->object();
|
||||
_deferred_signals.remove(_deferred_signals.first());
|
||||
}
|
||||
|
||||
Signal_dispatcher_base *dispatcher =
|
||||
dynamic_cast<Signal_dispatcher_base *>(context);
|
||||
if (dispatcher) dispatcher->dispatch(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Entrypoint::_process_incoming_signals()
|
||||
{
|
||||
for (;;) {
|
||||
@ -71,7 +113,7 @@ void Entrypoint::_process_incoming_signals()
|
||||
success = cmpxchg(&_signal_recipient, NONE, SIGNAL_PROXY);
|
||||
}
|
||||
|
||||
/* common case, entrypoint is not in 'wait_and_dispatch_one_signal' */
|
||||
/* common case, entrypoint is not in 'wait_and_dispatch_one_io_signal' */
|
||||
if (success) {
|
||||
/*
|
||||
* It might happen that we try to forward a signal to the
|
||||
@ -86,7 +128,7 @@ void Entrypoint::_process_incoming_signals()
|
||||
cmpxchg(&_signal_recipient, SIGNAL_PROXY, NONE);
|
||||
} else {
|
||||
/*
|
||||
* Entrypoint is in 'wait_and_dispatch_one_signal', wakup it up and
|
||||
* Entrypoint is in 'wait_and_dispatch_one_io_signal', wakup it up and
|
||||
* block for next signal
|
||||
*/
|
||||
_sig_rec->unblock_signal_waiter(*_rpc_ep);
|
||||
@ -98,6 +140,7 @@ void Entrypoint::_process_incoming_signals()
|
||||
}
|
||||
} while (!_suspended);
|
||||
|
||||
_deferred_signal_handler.destruct();
|
||||
_suspend_dispatcher.destruct();
|
||||
_sig_rec.destruct();
|
||||
dissolve(_signal_proxy);
|
||||
@ -129,7 +172,7 @@ void Entrypoint::_process_incoming_signals()
|
||||
}
|
||||
|
||||
|
||||
void Entrypoint::wait_and_dispatch_one_signal()
|
||||
void Entrypoint::wait_and_dispatch_one_io_signal()
|
||||
{
|
||||
for (;;) {
|
||||
|
||||
@ -144,6 +187,12 @@ void Entrypoint::wait_and_dispatch_one_signal()
|
||||
|
||||
_signal_pending_ack_lock.unlock();
|
||||
|
||||
/* defer application-level signals */
|
||||
if (sig.context()->level() == Signal_context::Level::App) {
|
||||
_defer_signal(sig);
|
||||
continue;
|
||||
}
|
||||
|
||||
_dispatch_signal(sig);
|
||||
break;
|
||||
|
||||
@ -154,6 +203,15 @@ void Entrypoint::wait_and_dispatch_one_signal()
|
||||
}
|
||||
|
||||
_execute_post_signal_hook();
|
||||
|
||||
/* initiate potential deferred-signal handling in entrypoint */
|
||||
if (_deferred_signals.first()) {
|
||||
/* construct the handler on demand (otherwise we break core) */
|
||||
if (!_deferred_signal_handler.constructed())
|
||||
_deferred_signal_handler.construct(*this, *this,
|
||||
&Entrypoint::_handle_deferred_signals);
|
||||
Signal_transmitter(*_deferred_signal_handler).submit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -186,6 +244,12 @@ void Genode::Entrypoint::dissolve(Signal_dispatcher_base &dispatcher)
|
||||
/* _sig_rec is invalid for a small window in _process_incoming_signals */
|
||||
if (_sig_rec.constructed())
|
||||
_sig_rec->dissolve(&dispatcher);
|
||||
|
||||
/* also remove context from deferred signal list */
|
||||
{
|
||||
Lock::Guard guard(_deferred_signals_mutex);
|
||||
_deferred_signals.remove(dispatcher.deferred_le());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +86,7 @@ Signal::Signal(Signal::Data data) : _data(data)
|
||||
* Normally, the context can only have one 'Signal' in flight, which is
|
||||
* destroyed before 'pending_signal' is called the next time. However,
|
||||
* one exception is a signal handler that unexpectedly calls
|
||||
* 'pending_signal' itself (i.e., via 'wait_and_dispatch_one_signal').
|
||||
* 'pending_signal' itself (i.e., via 'wait_and_dispatch_one_io_signal').
|
||||
* As this is dangerous programming pattern (that should be fixed), we
|
||||
* print a warning.
|
||||
*
|
||||
@ -221,7 +221,7 @@ void Signal_receiver::_unsynchronized_dissolve(Signal_context * const context)
|
||||
env_deprecated()->pd_session()->free_context(context->_cap);
|
||||
|
||||
/* restore default initialization of signal context */
|
||||
context->_receiver = 0;
|
||||
context->_receiver = nullptr;
|
||||
context->_cap = Signal_context_capability();
|
||||
|
||||
/* remove context from context list */
|
||||
|
Reference in New Issue
Block a user