From d31492040c0abae8a61f6dcd2470292a3fe890a0 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 3 Dec 2014 14:25:12 +0100 Subject: [PATCH] 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. --- repos/base-hw/src/core/rm_session_support.cc | 38 ++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/repos/base-hw/src/core/rm_session_support.cc b/repos/base-hw/src/core/rm_session_support.cc index 78e0141d6..fa38b108b 100644 --- a/repos/base-hw/src/core/rm_session_support.cc +++ b/repos/base-hw/src/core/rm_session_support.cc @@ -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(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(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::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(); } }