mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 11:27:29 +00:00
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:
parent
1c8c30e1f4
commit
8eef91f2ac
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 **
|
||||
********************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user