hw: do not block on destruction of signal receiver

As synchronization of signal contexts is now the users business instead of
cores and the signal framework ensures that every context of a receiver gets
synchronously destructed before the destruction of the receiver itself
synchronization and thus blocking at the destruction of a kernel
receiver-object isn't necessary anymore.

ref #989
This commit is contained in:
Martin Stein 2013-12-06 11:53:08 +01:00 committed by Norman Feske
parent 1c8c30e1f4
commit 8eef91f2ac
4 changed files with 17 additions and 196 deletions

View File

@ -47,16 +47,6 @@ void Signal_context_killer::_cancel_waiting()
}
/****************************
** Signal_receiver_killer **
****************************/
void Signal_receiver_killer::_cancel_waiting()
{
if (_receiver) { _receiver->_killer_cancelled(); }
}
/********************
** Signal_context **
********************/
@ -86,5 +76,5 @@ Signal_context::Signal_context(Signal_receiver * const r, unsigned const imprint
_killer(0),
_ack_handler(&_default_ack_handler)
{
if (r->_add_context(this)) { throw Assign_to_receiver_failed(); }
r->_add_context(this);
}

View File

@ -39,11 +39,6 @@ namespace Kernel
*/
class Signal_context_killer;
/**
* Ability to destruct signal receivers
*/
class Signal_receiver_killer;
/**
* Signal types that are assigned to a signal receiver each
*/
@ -206,55 +201,6 @@ class Kernel::Signal_context_killer
void cancel_waiting() { _cancel_waiting(); }
};
class Kernel::Signal_receiver_killer
{
friend class Signal_receiver;
private:
Signal_receiver * _receiver;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/**
* Notice that the destruction is pending
*/
virtual void _signal_receiver_kill_pending() = 0;
/**
* Notice that pending destruction is done
*/
virtual void _signal_receiver_kill_done() = 0;
protected:
/***************
** Accessors **
***************/
Signal_receiver * receiver() const { return _receiver; }
public:
/**
* Constructor
*/
Signal_receiver_killer() : _receiver(0) { }
/**
* Destructor
*/
virtual ~Signal_receiver_killer() { _cancel_waiting(); }
/**
* Stop waiting for a signal receiver
*/
void cancel_waiting() { _cancel_waiting(); }
};
class Kernel::Signal_context
:
public Object<Signal_context, MAX_SIGNAL_CONTEXTS,
@ -318,11 +264,6 @@ class Kernel::Signal_context
*/
~Signal_context();
/**
* Exception types
*/
struct Assign_to_receiver_failed { };
/**
* Constructor
*
@ -412,12 +353,10 @@ class Kernel::Signal_receiver
:
public Object<Signal_receiver, MAX_SIGNAL_RECEIVERS,
Signal_receiver_ids, signal_receiver_ids,
signal_receiver_pool>,
public Signal_context_killer
signal_receiver_pool>
{
friend class Signal_context;
friend class Signal_handler;
friend class Signal_receiver_killer;
private:
@ -428,9 +367,6 @@ class Kernel::Signal_receiver
Fifo<Signal_handler::Fifo_element> _handlers;
Fifo<Signal_context::Fifo_element> _deliver;
Fifo<Signal_context::Fifo_element> _contexts;
bool _kill;
Signal_receiver_killer * _killer;
unsigned _context_kills;
/**
* Recognize that context 'c' has submits to deliver
@ -472,7 +408,7 @@ class Kernel::Signal_receiver
/**
* Notice that a context of the receiver has been destructed
*
* \param c killed context
* \param c destructed context
*/
void _context_destructed(Signal_context * const c)
{
@ -481,11 +417,6 @@ class Kernel::Signal_receiver
_deliver.remove(&c->_deliver_fe);
}
/**
* Notice that the killer of the receiver has cancelled waiting
*/
void _killer_cancelled() { _killer = 0; }
/**
* Notice that handler 'h' has cancelled waiting
*/
@ -496,49 +427,24 @@ class Kernel::Signal_receiver
/**
* Assign context 'c' to the receiver
*
* \retval 0 succeeded
* \retval -1 failed
*/
int _add_context(Signal_context * const c)
void _add_context(Signal_context * const c)
{
if (_kill) { return -1; }
_contexts.enqueue(&c->_contexts_fe);
return 0;
}
/***************************
** Signal_context_killer **
***************************/
void _signal_context_kill_pending() { _context_kills++; }
void _signal_context_kill_done()
{
_context_kills--;
if (!_context_kills && _kill) {
this->~Signal_receiver();
if (_killer) {
_killer->_receiver = 0;
_killer->_signal_receiver_kill_done();
}
}
}
void _signal_context_kill_failed() { PERR("unexpected call"); }
public:
/**
* Constructor
* Destructor
*/
Signal_receiver()
:
_kill(0),
_killer(0),
_context_kills(0)
{ }
~Signal_receiver()
{
/* destruct all attached contexts */
while (Signal_context * c = _contexts.dequeue()->object()) {
c->~Signal_context();
}
}
/**
* Let a handler 'h' wait for signals of the receiver
@ -548,7 +454,7 @@ class Kernel::Signal_receiver
*/
int add_handler(Signal_handler * const h)
{
if (_kill || h->_receiver) { return -1; }
if (h->_receiver) { return -1; }
_handlers.enqueue(&h->_handlers_fe);
h->_receiver = this;
h->_await_signal(this);
@ -560,38 +466,6 @@ class Kernel::Signal_receiver
* Return wether any of the contexts of this receiver is deliverable
*/
bool deliverable() { return !_deliver.empty(); }
/**
* Destruct receiver or prepare to do it as soon as delivery is done
*
* \param killer object that shall receive progress reports
*
* \retval 0 succeeded
* \retval -1 failed
*/
int kill(Signal_receiver_killer * const k)
{
if (_kill) { return -1; }
/* start killing at all contexts of the receiver */
Signal_context * c = _contexts.dequeue()->object();
while (c) {
c->kill(this);
c->~Signal_context();
c = _contexts.dequeue()->object();
}
/* destruct directly if no context kill is pending */
if (!_context_kills) {
this->~Signal_receiver();
return 0;
}
/* wait for pending context kills */
_kill = 1;
_killer = k;
_killer->_receiver = this;
_killer->_signal_receiver_kill_pending();
return 0;
}
};
#endif /* _KERNEL__SIGNAL_RECEIVER_ */

View File

@ -56,22 +56,6 @@ void Thread::_signal_context_kill_failed()
}
void Thread::_signal_receiver_kill_pending()
{
assert(_state == SCHEDULED);
_state = AWAITS_SIGNAL_RECEIVER_KILL;
cpu_scheduler()->remove(this);
}
void Thread::_signal_receiver_kill_done()
{
assert(_state == AWAITS_SIGNAL_RECEIVER_KILL);
user_arg_0(0);
_schedule();
}
void Thread::_await_signal(Signal_receiver * const receiver)
{
cpu_scheduler()->remove(this);
@ -164,9 +148,6 @@ int Thread::_resume()
case AWAITS_SIGNAL_CONTEXT_KILL:
Signal_context_killer::cancel_waiting();
return 0;
case AWAITS_SIGNAL_RECEIVER_KILL:
Signal_receiver_killer::cancel_waiting();
return 0;
case AWAITS_START:
case STOPPED:;
}
@ -658,10 +639,6 @@ void Thread::_print_activity()
unsigned const context_id = Signal_context_killer::context()->id();
Genode::printf("\033[32m await SCK %u\033[0m", context_id);
break; }
case AWAITS_SIGNAL_RECEIVER_KILL: {
unsigned const receiver_id = Signal_receiver_killer::receiver()->id();
Genode::printf("\033[32m await SRK %u\033[0m", receiver_id);
break; }
case STOPPED: {
Genode::printf("\033[32m stop\033[0m");
break; }
@ -737,13 +714,8 @@ void Thread::_call_new_signal_context()
/* create and assign context*/
void * const p = (void *)user_arg_1();
unsigned const imprint = user_arg_3();
try {
Signal_context * const c = new (p) Signal_context(r, imprint);
user_arg_0(c->id());
} catch (Signal_context::Assign_to_receiver_failed) {
PERR("failed to assign context to receiver");
user_arg_0(0);
}
Signal_context * const c = new (p) Signal_context(r, imprint);
user_arg_0(c->id());
}
@ -880,12 +852,7 @@ void Thread::_call_bin_signal_receiver()
user_arg_0(0);
return;
}
/* kill signal receiver */
if (r->kill(this)) {
PERR("unknown signal receiver");
user_arg_0(-1);
return;
}
r->~Signal_receiver();
user_arg_0(0);
}

View File

@ -51,7 +51,6 @@ class Kernel::Thread
public Execution_context,
public Ipc_node,
public Signal_context_killer,
public Signal_receiver_killer,
public Signal_handler,
public Thread_cpu_support
{
@ -69,8 +68,7 @@ class Kernel::Thread
AWAITS_RESUME = 4,
AWAITS_SIGNAL = 5,
AWAITS_SIGNAL_CONTEXT_KILL = 6,
AWAITS_SIGNAL_RECEIVER_KILL = 7,
STOPPED = 8,
STOPPED = 7,
};
State _state;
@ -241,14 +239,6 @@ class Kernel::Thread
void _signal_context_kill_done();
/****************************
** Signal_receiver_killer **
****************************/
void _signal_receiver_kill_pending();
void _signal_receiver_kill_done();
/********************
** Signal_handler **
********************/