signal: organize signal contexts as ring list

Ref #2532
This commit is contained in:
Martin Stein
2017-11-07 14:04:46 +01:00
committed by Christian Helmuth
parent 07b36573ea
commit 8e80c05be7
4 changed files with 206 additions and 216 deletions

View File

@ -221,10 +221,10 @@ Signal_context_capability Signal_receiver::manage(Signal_context *context)
context->_receiver = this;
Lock::Guard list_lock_guard(_contexts_lock);
Lock::Guard contexts_lock_guard(_contexts_lock);
/* insert context into context list */
_contexts.insert(context);
_contexts.insert_as_tail(context);
/* register context at process-wide registry */
signal_context_registry()->insert(&context->_registry_le);

View File

@ -160,30 +160,24 @@ Signal Signal_receiver::wait_for_signal()
Signal Signal_receiver::pending_signal()
{
Lock::Guard list_lock_guard(_contexts_lock);
Lock::Guard contexts_lock_guard(_contexts_lock);
Signal::Data result;
_contexts.for_each_locked([&] (Signal_context &context) {
/* look up the contexts for the pending signal */
for (Signal_context *context = _contexts.head(); context; context = context->_next) {
if (!context._pending) return;
Lock::Guard lock_guard(context->_lock);
/* check if context has a pending signal */
if (!context->_pending)
continue;
_contexts.head(context);
context->_pending = false;
Signal::Data result = context->_curr_signal;
/* invalidate current signal in context */
context->_curr_signal = Signal::Data(0, 0);
_contexts.head(context._next);
context._pending = false;
result = context._curr_signal;
context._curr_signal = Signal::Data(0, 0);
Trace::Signal_received trace_event(context, result.num);
throw Context_ring::Break_for_each();
});
if (result.context) {
if (result.num == 0)
warning("returning signal with num == 0");
Trace::Signal_received trace_event(*context, result.num);
/* return last received signal */
return result;
}
@ -202,7 +196,7 @@ Signal Signal_receiver::pending_signal()
Signal_receiver::~Signal_receiver()
{
Lock::Guard list_lock_guard(_contexts_lock);
Lock::Guard contexts_lock_guard(_contexts_lock);
/* disassociate contexts from the receiver */
while (_contexts.head())
@ -235,7 +229,7 @@ void Signal_receiver::dissolve(Signal_context *context)
if (context->_receiver != this)
throw Context_not_associated();
Lock::Guard list_lock_guard(_contexts_lock);
Lock::Guard contexts_lock_guard(_contexts_lock);
_unsynchronized_dissolve(context);
@ -243,59 +237,38 @@ void Signal_receiver::dissolve(Signal_context *context)
}
bool Signal_receiver::pending()
{
Lock::Guard list_lock_guard(_contexts_lock);
/* look up the contexts for the pending signal */
for (Signal_context *context = _contexts.head(); context; context = context->_next) {
Lock::Guard lock_guard(context->_lock);
if (context->_pending)
return true;
}
return false;
Lock::Guard contexts_lock_guard(_contexts_lock);
bool result = false;
_contexts.for_each_locked([&] (Signal_context &context) {
if (context._pending) {
result = true;
throw Context_ring::Break_for_each();
}
});
return result;
}
void Signal_receiver::Context_list::insert(Signal_context *re)
void Signal_receiver::Context_ring::insert_as_tail(Signal_context *re)
{
if (_head) {
re->_prev = _head->_prev;
re->_next = nullptr;
_head->_prev->_next = re;
_head->_prev = re;
re->_prev = _head->_prev;
re->_next = _head;
_head->_prev = _head->_prev->_next = re;
} else {
re->_prev = re;
re->_next = nullptr;
_head = re;
_head = re->_prev = re->_next = re;
}
}
void Signal_receiver::Context_list::remove(Signal_context const *re)
void Signal_receiver::Context_ring::remove(Signal_context const *re)
{
if (re->_prev == re) {
_head = nullptr;
} else {
if (_head == re) {
_head = re->_next;
}
if (re->_next != re) {
if (re == _head) { _head = re->_next; }
re->_prev->_next = re->_next;
if (re->_next) {
re->_next->_prev = re->_prev;
} else {
_head->_prev = re->_prev;
}
re->_next->_prev = re->_prev;
}
}
void Signal_receiver::Context_list::head(Signal_context *re)
{
_head->_prev->_next = _head;
_head = re;
_head->_prev->_next = nullptr;
else { _head = nullptr; }
}