hw: cancel unresolved faults before pager dissolve

If an RM client gets dissolved the RM server tries to first
dissolve and then destruct the according pager object. As pager objects
previously cancelled unresolved faults only in destructor the dissolve
operation blocked forever when an unresolved fault existed.
As every pager object should get dissolved before it gets destructed
(signal-context complains otherwise) no more unresolved-fault cancelling
is needed in the destructor.

ref #989
This commit is contained in:
Martin Stein 2013-12-06 19:06:32 +01:00 committed by Norman Feske
parent 8eef91f2ac
commit f4bd2368f6
2 changed files with 65 additions and 42 deletions

View File

@ -20,6 +20,9 @@
#include <base/signal.h>
#include <pager/capability.h>
/* base-hw includes */
#include <placement_new.h>
namespace Genode
{
class Cap_session;
@ -132,9 +135,38 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
Signal_context_capability _signal_context_cap;
Thread_capability _thread_cap;
bool _signal_valid;
char _signal_buf[sizeof(Signal)];
unsigned const _badge;
/**
* Remember an incoming fault for handling
*
* \param s fault signal
*/
void _take_fault(Signal const & s)
{
new (_signal_buf) Signal(s);
_signal_valid = 1;
}
/**
* End handling of current fault
*/
void _end_fault()
{
_signal()->~Signal();
_signal_valid = 0;
}
/**
* End handling of current fault if there is one
*/
void _end_fault_if_pending()
{
if (_signal_valid) { _end_fault(); }
}
/***************
** Accessors **
@ -151,27 +183,22 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
*/
Pager_object(unsigned const badge, Affinity::Location);
/**
* Destructor
*/
virtual ~Pager_object() { }
/**
* The faulter has caused a fault and awaits paging
*
* \param s signal that communicated the fault
*/
void fault_occured(Signal const & s);
void fault_occured(Signal const & s) { _take_fault(s); }
/**
* Current fault has been resolved so resume faulter
*/
void fault_resolved();
void fault_resolved() { _end_fault(); }
/**
* User identification of pager object
*/
unsigned badge() const;
unsigned badge() const { return _badge; }
/**
* Resume faulter
@ -183,6 +210,29 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
*/
void exception_handler(Signal_context_capability);
/**
* Install information that is necessary to handle page faults
*
* \param c linkage between signal context and a signal receiver
* \param p linkage between pager object and a pager entry-point
*/
void start_paging(Signal_context_capability const & c,
Pager_capability const & p)
{
_signal_context_cap = c;
Object_pool<Pager_object>::Entry::cap(p);
}
/**
* Uninstall paging information and cancel unresolved faults
*/
void stop_paging()
{
Object_pool<Pager_object>::Entry::cap(Native_capability());
_signal_context_cap = Signal_context_capability();
_end_fault_if_pending();
}
/******************
** Pure virtual **
@ -207,8 +257,6 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
void thread_cap(Thread_capability const & c);
void cap(Native_capability const & c);
unsigned signal_context_id() const;
};

View File

@ -15,9 +15,6 @@
#include <base/pager.h>
#include <base/printf.h>
/* base-hw includes */
#include <placement_new.h>
using namespace Genode;
@ -70,25 +67,10 @@ void Pager_object::wake_up() { fault_resolved(); }
void Pager_object::exception_handler(Signal_context_capability) { }
void Pager_object::fault_resolved() { _signal()->~Signal(); }
unsigned Pager_object::badge() const { return _badge; }
void Pager_object::fault_occured(Signal const & s)
{
new (_signal()) Signal(s);
}
void Pager_object::cap(Native_capability const & c)
{
Object_pool<Pager_object>::Entry::cap(c);
}
Pager_object::Pager_object(unsigned const badge, Affinity::Location)
:
_signal_valid(0),
_badge(badge)
{ }
@ -126,12 +108,8 @@ Native_capability Pager_activation_base::cap()
void Pager_entrypoint::dissolve(Pager_object * const o)
{
/* let entrypoint dissolve the pager object */
remove_locked(o);
o->cap(Native_capability());
/* let activation signal-receiver dissolve the pager signal-context */
o->_signal_context_cap = Signal_context_capability();
o->stop_paging();
_activation->Signal_receiver::dissolve(o);
}
@ -147,13 +125,10 @@ Pager_entrypoint::Pager_entrypoint(Cap_session *,
Pager_capability Pager_entrypoint::manage(Pager_object * const o)
{
/* let activation signal-receiver manage the pager signal-context */
o->_signal_context_cap = _activation->Signal_receiver::manage(o);
/* let entrypoint manage the pager object */
unsigned const dst = _activation->cap().dst();
Native_capability c = Native_capability(dst, o->badge());
o->cap(c);
unsigned const d = _activation->cap().dst();
unsigned const b = o->badge();
auto const p = reinterpret_cap_cast<Pager_object>(Native_capability(d, b));
o->start_paging(_activation->Signal_receiver::manage(o), p);
insert(o);
return reinterpret_cap_cast<Pager_object>(c);
return p;
}