hw: fix race on pager-object dissolve

The HW-kernel, in contrast to other kernels, provides a direct reference
to the pager object with the fault signal that is send to the pager
activation. When accessing this reference directly we may fall into the
time span where the root parent-entrypoint of the faulter has alredy
dissolved the pager object from the pager entrypoint, but not yet
silenced the according signal context.  To avoid this we issue an
additional 'lookup_and_lock' with the received pager object. This isn't
optimal as we don't need the potentially cost-intensive lookup but only the
synchronization.

Fixes #1311.
Fixes #1332.
This commit is contained in:
Martin Stein 2014-12-03 14:25:12 +01:00 committed by Christian Helmuth
parent a59cf9f557
commit d31492040c
1 changed files with 24 additions and 14 deletions

View File

@ -96,19 +96,26 @@ void Pager_activation_base::entry()
_cap_valid.unlock();
while (1)
{
/* await fault */
Pager_object * o;
while (1) {
Signal s = Signal_receiver::wait_for_signal();
o = dynamic_cast<Pager_object *>(s.context());
if (o) {
o->fault_occured(s);
break;
}
PWRN("unknown pager object");
/* receive fault */
Signal s = Signal_receiver::wait_for_signal();
Pager_object * po = static_cast<Pager_object *>(s.context());
/*
* Synchronize access and ensure that the object is still managed
*
* FIXME: The implicit lookup of the oject isn't needed.
*/
unsigned const pon = po->cap().local_name();
Object_pool<Pager_object>::Guard pog(_ep->lookup_and_lock(pon));
if (!pog) {
PWRN("failed to lookup pager object");
continue;
}
/* let pager object go to fault state */
pog->fault_occured(s);
/* fetch fault data */
Platform_thread * const pt = (Platform_thread *)o->badge();
Platform_thread * const pt = (Platform_thread *)pog->badge();
if (!pt) {
PWRN("failed to get platform thread of faulter");
continue;
@ -126,12 +133,15 @@ void Pager_activation_base::entry()
PWRN("failed to read fault data");
continue;
}
/* handle fault */
if (o->pager(*this)) { continue; }
/* try to resolve fault directly via local region managers */
if (pog->pager(*this)) { continue; }
/* apply mapping that was determined by the local region managers */
if (apply_mapping()) {
PWRN("failed to apply mapping");
continue;
}
o->fault_resolved();
/* let pager object go back to no-fault state */
pog->fault_resolved();
}
}