hw: destruct signal sessions

ref 
This commit is contained in:
Martin Stein 2013-09-12 21:13:22 +02:00 committed by Norman Feske
parent 1571e09823
commit 6d03292a1e
6 changed files with 85 additions and 53 deletions

@ -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();
}

@ -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:
/**

@ -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;
}

@ -58,7 +58,14 @@ class Kernel::Signal_handler
typedef Genode::Fifo_element<Signal_handler> 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;
}

@ -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 **

@ -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();
}