diff --git a/base-hw/src/base/signal/signal.cc b/base-hw/src/base/signal/signal.cc index a10629602e..dac2563009 100644 --- a/base-hw/src/base/signal/signal.cc +++ b/base-hw/src/base/signal/signal.cc @@ -21,7 +21,7 @@ using namespace Genode; /** - * Provide a static signal connection + * Provide one signal connection per program */ static Signal_connection * signal_connection() { @@ -40,12 +40,10 @@ void Signal::_dec_ref_and_unlock() Lock::Guard lock_guard(_data.context->_lock); _data.context->_ref_cnt--; - /* - * We must ack a signal context to receive the next one, - * so new signals are received only when ref_cnt = 0. - */ - if (_data.context->_ref_cnt == 0) + /* acknowledge as soon as receipt is fully processed */ + if (_data.context->_ref_cnt == 0) { Kernel::ack_signal(_data.context->_cap.dst()); + } } } @@ -61,11 +59,7 @@ void Signal::_inc_ref() Signal::Signal(Signal::Data data) : _data(data) { - /* - * We assume that a kernel signal-context doesn't deliver - * multiple signals simultaneously. - */ - if (_data.context) _data.context->_ref_cnt = 1; + if (_data.context) { _data.context->_ref_cnt = 1; } } @@ -73,9 +67,8 @@ Signal::Signal(Signal::Data data) : _data(data) ** Signal transmitter ** ************************/ -void Signal_transmitter::submit(unsigned cnt) +void Signal_transmitter::submit(unsigned const cnt) { - /* submits to invalid signal contexts get ignored */ Kernel::submit_signal(_context.dst(), cnt); } @@ -116,7 +109,7 @@ void Signal_receiver::_platform_destructor() } -void Signal_receiver::_unsynchronized_dissolve(Signal_context * c) +void Signal_receiver::_unsynchronized_dissolve(Signal_context * const c) { /* release server resources of context */ signal_connection()->free_context(c->_cap); @@ -196,5 +189,6 @@ Signal Signal_receiver::wait_for_signal() void Signal_receiver::local_submit(Signal::Data signal) { - PDBG("Not implemented"); + PDBG("not implemented"); + throw Exception(); } diff --git a/base-hw/src/core/include/signal_session_component.h b/base-hw/src/core/include/signal_session_component.h index 9634b3882b..dc3b0582e3 100644 --- a/base-hw/src/core/include/signal_session_component.h +++ b/base-hw/src/core/include/signal_session_component.h @@ -58,6 +58,16 @@ namespace Genode char _initial_receivers_sb [RECEIVERS_SB_SIZE]; char _initial_contexts_sb [CONTEXTS_SB_SIZE]; + /** + * Destruct receiver 'r' + */ + void _destruct_receiver(Receiver * const r); + + /** + * Destruct context 'c' + */ + void _destruct_context(Context * const c); + public: /** diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index e8579848fe..9b4b607b8a 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -596,7 +596,7 @@ namespace Kernel { /* check permissions */ if (user->pd_id() != core_id()) { - PERR("permission to create signal receiver denied"); + PERR("not entitled to create signal receiver"); user->user_arg_0(0); return; } @@ -622,7 +622,7 @@ namespace Kernel unsigned id = user->user_arg_2(); Signal_receiver * const r = Signal_receiver::pool()->object(id); if (!r) { - PERR("invalid signal receiver"); + PERR("unknown signal receiver"); user->user_arg_0(0); return; } @@ -649,12 +649,11 @@ namespace Kernel unsigned id = user->user_arg_1(); Signal_receiver * const r = Signal_receiver::pool()->object(id); if (!r) { - PERR("invalid signal receiver"); + PERR("unknown signal receiver"); user->user_arg_0(-1); return; } /* register handler at the receiver */ - user->await_signal(r); if (r->add_handler(user)) { PERR("failed to register handler at signal receiver"); user->user_arg_0(-1); @@ -673,7 +672,7 @@ namespace Kernel unsigned id = user->user_arg_1(); Signal_receiver * const r = Signal_receiver::pool()->object(id); if (!r) { - PERR("invalid signal receiver"); + PERR("unknown signal receiver"); user->user_arg_0(0); return; } @@ -691,12 +690,13 @@ namespace Kernel unsigned const id = user->user_arg_1(); Signal_context * const c = Signal_context::pool()->object(id); if(!c) { - PERR("invalid signal context"); + PERR("unknown signal context"); user->user_arg_0(-1); return; } /* trigger signal context */ if (c->submit(user->user_arg_2())) { + PERR("failed to submit signal context"); user->user_arg_0(-1); return; } @@ -713,7 +713,7 @@ namespace Kernel unsigned id = user->user_arg_1(); Signal_context * const c = Signal_context::pool()->object(id); if (!c) { - PWRN("invalid signal context"); + PERR("unknown signal context"); return; } /* acknowledge */ @@ -736,11 +736,13 @@ namespace Kernel unsigned id = user->user_arg_1(); Signal_context * const c = Signal_context::pool()->object(id); if (!c) { + PERR("unknown signal context"); user->user_arg_0(0); return; } /* kill signal context */ if (c->kill(user)) { + PERR("failed to kill signal context"); user->user_arg_0(-1); return; } @@ -760,15 +762,16 @@ namespace Kernel return; } /* lookup signal receiver */ - user->user_arg_0(1); unsigned id = user->user_arg_1(); Signal_receiver * const r = Signal_receiver::pool()->object(id); if (!r) { + PERR("unknown signal receiver"); user->user_arg_0(0); return; } /* kill signal receiver */ if (r->kill(user)) { + PERR("unknown signal receiver"); user->user_arg_0(-1); return; } diff --git a/base-hw/src/core/kernel/signal_receiver.h b/base-hw/src/core/kernel/signal_receiver.h index a3fadc981b..a01cb5722a 100644 --- a/base-hw/src/core/kernel/signal_receiver.h +++ b/base-hw/src/core/kernel/signal_receiver.h @@ -58,7 +58,14 @@ class Kernel::Signal_handler typedef Genode::Fifo_element Fifo_element; - Fifo_element _handlers_fe; + Fifo_element _handlers_fe; + + /** + * Let the handler block for signal receipt + * + * \param receiver the signal pool that the thread blocks for + */ + virtual void _await_signal(Signal_receiver * const receiver) = 0; /** * Signal delivery backend @@ -66,7 +73,7 @@ class Kernel::Signal_handler * \param base signal-data base * \param size signal-data size */ - virtual void _signal_handler(void * const base, size_t const size) = 0; + virtual void _receive_signal(void * const base, size_t const size) = 0; public: @@ -267,7 +274,7 @@ class Kernel::Signal_receiver Signal_handler * const h = _handlers.dequeue()->object(); Signal::Data data((Genode::Signal_context *)c->_imprint, c->_submits); - h->_signal_handler(&data, sizeof(data)); + h->_receive_signal(&data, sizeof(data)); c->_delivered(); } } @@ -317,6 +324,7 @@ class Kernel::Signal_receiver { if (_killer) { return -1; } _handlers.enqueue(&h->_handlers_fe); + h->_await_signal(this); _listen(); return 0; } diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index f4c7fcbc5a..d58926005e 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -143,7 +143,14 @@ class Kernel::Thread ** Signal_handler ** ********************/ - void _signal_handler(void * const base, size_t const size) + void _await_signal(Signal_receiver * const receiver) + { + cpu_scheduler()->remove(this); + _state = AWAIT_SIGNAL; + _signal_receiver = receiver; + } + + void _receive_signal(void * const base, size_t const size) { assert(_state == AWAIT_SIGNAL && size <= phys_utcb()->size()); Genode::memcpy(phys_utcb()->base(), base, size); @@ -392,18 +399,6 @@ class Kernel::Thread */ unsigned id() const { return Object::id(); } - /** - * Let the thread block for signal receipt - * - * \param receiver the signal pool that the thread blocks for - */ - void await_signal(Signal_receiver * receiver) - { - cpu_scheduler()->remove(this); - _state = AWAIT_SIGNAL; - _signal_receiver = receiver; - } - /*********************** ** Execution_context ** diff --git a/base-hw/src/core/signal_session_component.cc b/base-hw/src/core/signal_session_component.cc index 93169d9cb2..e267b59ac7 100644 --- a/base-hw/src/core/signal_session_component.cc +++ b/base-hw/src/core/signal_session_component.cc @@ -39,8 +39,16 @@ Signal_session_component::Signal_session_component(Allocator * const md, Signal_session_component::~Signal_session_component() { - PERR("%s: Not implemented", __PRETTY_FUNCTION__); - while (1) ; + while (1) { + Context * const c = _contexts.first_locked(); + if (!c) { break; } + _destruct_context(c); + } + while (1) { + Receiver * const r = _receivers.first_locked(); + if (!r) { break; } + _destruct_receiver(r); + } } @@ -80,17 +88,8 @@ void Signal_session_component::free_receiver(Signal_receiver_capability cap) PERR("unknown signal receiver"); throw Exception(); } - /* release kernel resources */ - if (Kernel::kill_signal_receiver(r->id())) - { - /* clean-up */ - r->release(); - PERR("failed to kill signal receiver"); - throw Exception(); - } - /* release core resources */ - _receivers.remove_locked(r); - r->~Receiver(); + /* release resources */ + _destruct_receiver(r); _receivers_slab.free(r, Receiver::slab_size()); } @@ -132,6 +131,14 @@ void Signal_session_component::free_context(Signal_context_capability cap) PERR("unknown signal context"); throw Exception(); } + /* release resources */ + _destruct_context(c); + _contexts_slab.free(c, Context::slab_size()); +} + + +void Signal_session_component::_destruct_context(Context * const c) +{ /* release kernel resources */ if (Kernel::kill_signal_context(c->id())) { @@ -143,5 +150,20 @@ void Signal_session_component::free_context(Signal_context_capability cap) /* release core resources */ _contexts.remove_locked(c); c->~Context(); - _contexts_slab.free(c, Context::slab_size()); +} + + +void Signal_session_component::_destruct_receiver(Receiver * const r) +{ + /* release kernel resources */ + if (Kernel::kill_signal_receiver(r->id())) + { + /* clean-up */ + r->release(); + PERR("failed to kill signal receiver"); + throw Exception(); + } + /* release core resources */ + _receivers.remove_locked(r); + r->~Receiver(); }