hw: use kernel signal API for page-fault signals

Instead of using the Genode user-level signal API to signal page-faults to
a page-fault handler, use the kernel API directly. Thereby the accounting
of signal contexts needed for each paging subject can be done easily.

Fix #956
This commit is contained in:
Stefan Kalkowski 2015-06-22 14:44:28 +02:00 committed by Christian Helmuth
parent 57e2f3affc
commit f5d5ed9637
5 changed files with 43 additions and 122 deletions

View File

@ -270,7 +270,7 @@ class Kernel::Signal_context : public Kernel::Object
*/ */
static capid_t syscall_create(void * p, static capid_t syscall_create(void * p,
Signal_receiver * const receiver, Signal_receiver * const receiver,
unsigned const imprint) addr_t const imprint)
{ {
return call(call_id_new_signal_context(), (Call_arg)p, return call(call_id_new_signal_context(), (Call_arg)p,
(Call_arg)receiver, (Call_arg)imprint); (Call_arg)receiver, (Call_arg)imprint);

View File

@ -20,6 +20,8 @@
#include <base/signal.h> #include <base/signal.h>
#include <pager/capability.h> #include <pager/capability.h>
#include <unmanaged_singleton.h> #include <unmanaged_singleton.h>
#include <kernel/signal_receiver.h>
#include <object.h>
namespace Genode namespace Genode
{ {
@ -124,54 +126,17 @@ class Genode::Ipc_pager
void set_reply_mapping(Mapping m); void set_reply_mapping(Mapping m);
}; };
class Genode::Pager_object : public Object_pool<Pager_object>::Entry, class Genode::Pager_object
public Signal_context : public Object_pool<Pager_object>::Entry,
public Genode::Kernel_object<Kernel::Signal_context>
{ {
friend class Pager_entrypoint; friend class Pager_entrypoint;
private: private:
Signal_context_capability _signal_context_cap;
Thread_capability _thread_cap; Thread_capability _thread_cap;
bool _signal_valid;
char _signal_buf[sizeof(Signal)];
unsigned long const _badge; unsigned long 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 **
***************/
Signal * _signal() const;
public: public:
/** /**
@ -181,18 +146,6 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
*/ */
Pager_object(unsigned const badge, Affinity::Location); Pager_object(unsigned const badge, Affinity::Location);
/**
* The faulter has caused a fault and awaits paging
*
* \param s signal that communicated the fault
*/
void fault_occured(Signal const & s) { _take_fault(s); }
/**
* Current fault has been resolved so resume faulter
*/
void fault_resolved() { _end_fault(); }
/** /**
* User identification of pager object * User identification of pager object
*/ */
@ -211,25 +164,9 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
/** /**
* Install information that is necessary to handle page faults * Install information that is necessary to handle page faults
* *
* \param c linkage between signal context and a signal receiver * \param receiver signal receiver that receives the page faults
* \param p linkage between pager object and a pager entry-point
*/ */
void start_paging(Signal_context_capability const & c, void start_paging(Kernel::Signal_receiver * receiver);
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();
}
/** /**
* Called when a page-fault finally could not be resolved * Called when a page-fault finally could not be resolved
@ -259,18 +196,16 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
Thread_capability thread_cap() const; Thread_capability thread_cap() const;
void thread_cap(Thread_capability const & c); void thread_cap(Thread_capability const & c);
unsigned signal_context_id() const;
}; };
class Genode::Pager_activation_base : public Thread_base, class Genode::Pager_activation_base
public Signal_receiver, : public Thread_base,
public Kernel_object<Kernel::Signal_receiver>,
public Ipc_pager public Ipc_pager
{ {
private: private:
Native_capability _cap; Lock _startup_lock;
Lock _cap_valid;
Pager_entrypoint * _ep; Pager_entrypoint * _ep;
public: public:
@ -304,8 +239,6 @@ class Genode::Pager_activation_base : public Thread_base,
** Accessors ** ** Accessors **
***************/ ***************/
Native_capability cap();
void ep(Pager_entrypoint * const ep); void ep(Pager_entrypoint * const ep);
}; };

View File

@ -66,9 +66,20 @@ Thread_capability Pager_object::thread_cap() const { return _thread_cap; }
void Pager_object::thread_cap(Thread_capability const & c) { _thread_cap = c; } void Pager_object::thread_cap(Thread_capability const & c) { _thread_cap = c; }
Signal * Pager_object::_signal() const { return (Signal *)_signal_buf; } void Pager_object::wake_up()
{
using Object = Kernel_object<Kernel::Signal_context>;
Kernel::ack_signal(Object::_cap.dst());
}
void Pager_object::wake_up() { fault_resolved(); } void Pager_object::start_paging(Kernel::Signal_receiver * receiver)
{
using Object = Kernel_object<Kernel::Signal_context>;
using Entry = Object_pool<Pager_object>::Entry;
create(receiver, (unsigned long)this);
Entry::cap(Object::_cap);
}
void Pager_object::exception_handler(Signal_context_capability) { } void Pager_object::exception_handler(Signal_context_capability) { }
@ -81,18 +92,11 @@ void Pager_object::unresolved_page_fault_occurred()
} }
Pager_object::Pager_object(unsigned const badge, Affinity::Location) Pager_object::Pager_object(unsigned const badge, Affinity::Location)
: : Object_pool<Pager_object>::Entry(Kernel_object<Kernel::Signal_context>::_cap),
_signal_valid(0),
_badge(badge) _badge(badge)
{ } { }
unsigned Pager_object::signal_context_id() const
{
return _signal_context_cap.dst();
}
/*************************** /***************************
** Pager_activation_base ** ** Pager_activation_base **
***************************/ ***************************/
@ -102,18 +106,12 @@ void Pager_activation_base::ep(Pager_entrypoint * const ep) { _ep = ep; }
Pager_activation_base::Pager_activation_base(char const * const name, Pager_activation_base::Pager_activation_base(char const * const name,
size_t const stack_size) size_t const stack_size)
: : Thread_base(0, name, stack_size),
Thread_base(0, name, stack_size), _cap_valid(Lock::LOCKED), _ep(0) Kernel_object<Kernel::Signal_receiver>(true),
_startup_lock(Lock::LOCKED), _ep(0)
{ } { }
Native_capability Pager_activation_base::cap()
{
if (!_cap.valid()) { _cap_valid.lock(); }
return _cap;
}
/********************** /**********************
** Pager_entrypoint ** ** Pager_entrypoint **
**********************/ **********************/
@ -121,25 +119,18 @@ Native_capability Pager_activation_base::cap()
void Pager_entrypoint::dissolve(Pager_object * const o) void Pager_entrypoint::dissolve(Pager_object * const o)
{ {
remove_locked(o); remove_locked(o);
o->stop_paging();
_activation->Signal_receiver::dissolve(o);
} }
Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_entrypoint::Pager_entrypoint(Cap_session *,
Pager_activation_base * const activation) Pager_activation_base * const activation)
: : _activation(activation) {
_activation(activation) _activation->ep(this); }
{
_activation->ep(this);
}
Pager_capability Pager_entrypoint::manage(Pager_object * const o) Pager_capability Pager_entrypoint::manage(Pager_object * const o)
{ {
Signal_context_capability scc = _activation->Signal_receiver::manage(o); o->start_paging(_activation->kernel_object());
Pager_capability p = reinterpret_cap_cast<Pager_object>(scc);
o->start_paging(scc, p);
insert(o); insert(o);
return p; return reinterpret_cap_cast<Pager_object>(o->cap());
} }

View File

@ -214,7 +214,7 @@ void Platform_thread::pager(Pager_object * const pager)
{ {
typedef Kernel::Thread_event_id Event_id; typedef Kernel::Thread_event_id Event_id;
if (pager) { if (pager) {
unsigned const sc_id = pager->signal_context_id(); unsigned const sc_id = pager->cap().dst();
if (sc_id) { if (sc_id) {
if (!Kernel::route_thread_event(kernel_object(), Event_id::FAULT, if (!Kernel::route_thread_event(kernel_object(), Event_id::FAULT,
sc_id)) { sc_id)) {

View File

@ -57,13 +57,13 @@ int Pager_activation_base::apply_mapping()
void Pager_activation_base::entry() void Pager_activation_base::entry()
{ {
/* get ready to receive faults */ /* get ready to receive faults */
_cap = Thread_base::myself()->tid().cap; _startup_lock.unlock();
_cap_valid.unlock();
while (1) while (1)
{ {
/* receive fault */ /* receive fault */
Signal s = Signal_receiver::wait_for_signal(); if (Kernel::await_signal(_cap.dst())) continue;
Pager_object * po = static_cast<Pager_object *>(s.context()); Pager_object * po =
*(Pager_object**)Thread_base::myself()->utcb()->base();
/* /*
* Synchronize access and ensure that the object is still managed * Synchronize access and ensure that the object is still managed
@ -74,9 +74,6 @@ void Pager_activation_base::entry()
Object_pool<Pager_object>::Guard pog(_ep->lookup_and_lock(pon)); Object_pool<Pager_object>::Guard pog(_ep->lookup_and_lock(pon));
if (!pog) continue; if (!pog) continue;
/* let pager object go to fault state */
pog->fault_occured(s);
/* fetch fault data */ /* fetch fault data */
Platform_thread * const pt = (Platform_thread *)pog->badge(); Platform_thread * const pt = (Platform_thread *)pog->badge();
if (!pt) { if (!pt) {
@ -104,6 +101,6 @@ void Pager_activation_base::entry()
continue; continue;
} }
/* let pager object go back to no-fault state */ /* let pager object go back to no-fault state */
pog->fault_resolved(); pog->wake_up();
} }
} }