From f5d5ed96375d8a602ebf4401669fa80fa38b6331 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 22 Jun 2015 14:44:28 +0200 Subject: [PATCH] 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 --- .../src/core/include/kernel/signal_receiver.h | 2 +- repos/base-hw/src/core/include/pager.h | 95 +++---------------- repos/base-hw/src/core/pager.cc | 53 +++++------ repos/base-hw/src/core/platform_thread.cc | 2 +- repos/base-hw/src/core/rm_session_support.cc | 13 +-- 5 files changed, 43 insertions(+), 122 deletions(-) diff --git a/repos/base-hw/src/core/include/kernel/signal_receiver.h b/repos/base-hw/src/core/include/kernel/signal_receiver.h index 562c152957..57f490caff 100644 --- a/repos/base-hw/src/core/include/kernel/signal_receiver.h +++ b/repos/base-hw/src/core/include/kernel/signal_receiver.h @@ -270,7 +270,7 @@ class Kernel::Signal_context : public Kernel::Object */ static capid_t syscall_create(void * p, Signal_receiver * const receiver, - unsigned const imprint) + addr_t const imprint) { return call(call_id_new_signal_context(), (Call_arg)p, (Call_arg)receiver, (Call_arg)imprint); diff --git a/repos/base-hw/src/core/include/pager.h b/repos/base-hw/src/core/include/pager.h index fc35766354..4249d8afec 100644 --- a/repos/base-hw/src/core/include/pager.h +++ b/repos/base-hw/src/core/include/pager.h @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace Genode { @@ -124,53 +126,16 @@ class Genode::Ipc_pager void set_reply_mapping(Mapping m); }; -class Genode::Pager_object : public Object_pool::Entry, - public Signal_context +class Genode::Pager_object +: public Object_pool::Entry, + public Genode::Kernel_object { friend class Pager_entrypoint; private: - Signal_context_capability _signal_context_cap; - Thread_capability _thread_cap; - bool _signal_valid; - char _signal_buf[sizeof(Signal)]; - 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; + Thread_capability _thread_cap; + unsigned long const _badge; public: @@ -181,18 +146,6 @@ class Genode::Pager_object : public Object_pool::Entry, */ 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 */ @@ -211,25 +164,9 @@ class Genode::Pager_object : public Object_pool::Entry, /** * 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 + * \param receiver signal receiver that receives the page faults */ - void start_paging(Signal_context_capability const & c, - Pager_capability const & p) - { - _signal_context_cap = c; - Object_pool::Entry::cap(p); - } - - /** - * Uninstall paging information and cancel unresolved faults - */ - void stop_paging() - { - Object_pool::Entry::cap(Native_capability()); - _signal_context_cap = Signal_context_capability(); - _end_fault_if_pending(); - } + void start_paging(Kernel::Signal_receiver * receiver); /** * Called when a page-fault finally could not be resolved @@ -259,18 +196,16 @@ class Genode::Pager_object : public Object_pool::Entry, Thread_capability thread_cap() const; void thread_cap(Thread_capability const & c); - - unsigned signal_context_id() const; }; -class Genode::Pager_activation_base : public Thread_base, - public Signal_receiver, - public Ipc_pager +class Genode::Pager_activation_base +: public Thread_base, + public Kernel_object, + public Ipc_pager { private: - Native_capability _cap; - Lock _cap_valid; + Lock _startup_lock; Pager_entrypoint * _ep; public: @@ -304,8 +239,6 @@ class Genode::Pager_activation_base : public Thread_base, ** Accessors ** ***************/ - Native_capability cap(); - void ep(Pager_entrypoint * const ep); }; diff --git a/repos/base-hw/src/core/pager.cc b/repos/base-hw/src/core/pager.cc index 5ba6c7613d..2fd3389584 100644 --- a/repos/base-hw/src/core/pager.cc +++ b/repos/base-hw/src/core/pager.cc @@ -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; } -Signal * Pager_object::_signal() const { return (Signal *)_signal_buf; } +void Pager_object::wake_up() +{ + using Object = Kernel_object; + 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; + using Entry = Object_pool::Entry; + + create(receiver, (unsigned long)this); + Entry::cap(Object::_cap); +} 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) -: - _signal_valid(0), - _badge(badge) +: Object_pool::Entry(Kernel_object::_cap), + _badge(badge) { } -unsigned Pager_object::signal_context_id() const -{ - return _signal_context_cap.dst(); -} - - /*************************** ** 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, size_t const stack_size) -: - Thread_base(0, name, stack_size), _cap_valid(Lock::LOCKED), _ep(0) +: Thread_base(0, name, stack_size), + Kernel_object(true), + _startup_lock(Lock::LOCKED), _ep(0) { } -Native_capability Pager_activation_base::cap() -{ - if (!_cap.valid()) { _cap_valid.lock(); } - return _cap; -} - - /********************** ** Pager_entrypoint ** **********************/ @@ -121,25 +119,18 @@ Native_capability Pager_activation_base::cap() void Pager_entrypoint::dissolve(Pager_object * const o) { remove_locked(o); - o->stop_paging(); - _activation->Signal_receiver::dissolve(o); } Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base * const activation) -: - _activation(activation) -{ - _activation->ep(this); -} +: _activation(activation) { + _activation->ep(this); } Pager_capability Pager_entrypoint::manage(Pager_object * const o) { - Signal_context_capability scc = _activation->Signal_receiver::manage(o); - Pager_capability p = reinterpret_cap_cast(scc); - o->start_paging(scc, p); + o->start_paging(_activation->kernel_object()); insert(o); - return p; + return reinterpret_cap_cast(o->cap()); } diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index 34982b0949..af9bb4c8a6 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -214,7 +214,7 @@ void Platform_thread::pager(Pager_object * const pager) { typedef Kernel::Thread_event_id Event_id; if (pager) { - unsigned const sc_id = pager->signal_context_id(); + unsigned const sc_id = pager->cap().dst(); if (sc_id) { if (!Kernel::route_thread_event(kernel_object(), Event_id::FAULT, sc_id)) { diff --git a/repos/base-hw/src/core/rm_session_support.cc b/repos/base-hw/src/core/rm_session_support.cc index 8cd7857189..0400b0beca 100644 --- a/repos/base-hw/src/core/rm_session_support.cc +++ b/repos/base-hw/src/core/rm_session_support.cc @@ -57,13 +57,13 @@ int Pager_activation_base::apply_mapping() void Pager_activation_base::entry() { /* get ready to receive faults */ - _cap = Thread_base::myself()->tid().cap; - _cap_valid.unlock(); + _startup_lock.unlock(); while (1) { /* receive fault */ - Signal s = Signal_receiver::wait_for_signal(); - Pager_object * po = static_cast(s.context()); + if (Kernel::await_signal(_cap.dst())) continue; + Pager_object * po = + *(Pager_object**)Thread_base::myself()->utcb()->base(); /* * Synchronize access and ensure that the object is still managed @@ -74,9 +74,6 @@ void Pager_activation_base::entry() Object_pool::Guard pog(_ep->lookup_and_lock(pon)); if (!pog) continue; - /* let pager object go to fault state */ - pog->fault_occured(s); - /* fetch fault data */ Platform_thread * const pt = (Platform_thread *)pog->badge(); if (!pt) { @@ -104,6 +101,6 @@ void Pager_activation_base::entry() continue; } /* let pager object go back to no-fault state */ - pog->fault_resolved(); + pog->wake_up(); } }