diff --git a/repos/base-hw/src/core/kernel/ipc_node.cc b/repos/base-hw/src/core/kernel/ipc_node.cc
index 59f59f6d44..ade00fad04 100644
--- a/repos/base-hw/src/core/kernel/ipc_node.cc
+++ b/repos/base-hw/src/core/kernel/ipc_node.cc
@@ -19,74 +19,16 @@
#include
/* core includes */
-#include
#include
-#include
#include
#include
using namespace Kernel;
-static inline void free_obj_id_ref(Pd &pd, void *ptr)
-{
- pd.platform_pd().capability_slab().free(ptr, sizeof(Object_identity_reference));
-}
-
-
-void Ipc_node::copy_msg(Ipc_node &sender)
-{
- using namespace Genode;
- using Reference = Object_identity_reference;
-
- /* copy payload and set destination capability id */
- *_utcb = *sender._utcb;
- _utcb->destination(sender._capid);
-
- /* translate capabilities */
- for (unsigned i = 0; i < _rcv_caps; i++) {
-
- capid_t id = sender._utcb->cap_get(i);
-
- /* if there is no capability to send, just free the pre-allocation */
- if (i >= sender._utcb->cap_cnt()) {
- free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
- continue;
- }
-
- /* lookup the capability id within the caller's cap space */
- Reference *oir = (id == cap_id_invalid())
- ? nullptr : sender.pd().cap_tree().find(id);
-
- /* if the caller's capability is invalid, free the pre-allocation */
- if (!oir) {
- _utcb->cap_add(cap_id_invalid());
- free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
- continue;
- }
-
- /* lookup the capability id within the callee's cap space */
- Reference *dst_oir = oir->find(pd());
-
- /* if it is not found, and the target is not core, create a reference */
- if (!dst_oir && (&pd() != &core_pd())) {
- dst_oir = oir->factory(_obj_id_ref_ptr[i], pd());
- if (!dst_oir)
- free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
- } else /* otherwise free the pre-allocation */
- free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
-
- if (dst_oir) dst_oir->add_to_utcb();
-
- /* add the translated capability id to the target buffer */
- _utcb->cap_add(dst_oir ? dst_oir->capid() : cap_id_invalid());
- }
-}
-
-
void Ipc_node::_receive_request(Ipc_node &caller)
{
- copy_msg(caller);
+ _thread.ipc_copy_msg(caller._thread);
_caller = &caller;
_state = INACTIVE;
}
@@ -94,9 +36,9 @@ void Ipc_node::_receive_request(Ipc_node &caller)
void Ipc_node::_receive_reply(Ipc_node &callee)
{
- copy_msg(callee);
+ _thread.ipc_copy_msg(callee._thread);
_state = INACTIVE;
- _send_request_succeeded();
+ _thread.ipc_send_request_succeeded();
}
@@ -105,7 +47,7 @@ void Ipc_node::_announce_request(Ipc_node &node)
/* directly receive request if we've awaited it */
if (_state == AWAIT_REQUEST) {
_receive_request(node);
- _await_request_succeeded();
+ _thread.ipc_await_request_succeeded();
return;
}
@@ -152,40 +94,24 @@ void Ipc_node::_outbuf_request_cancelled()
_callee = nullptr;
_state = INACTIVE;
- _send_request_failed();
+ _thread.ipc_send_request_failed();
}
bool Ipc_node::_helps_outbuf_dst() { return (_state == AWAIT_REPLY) && _help; }
-void Ipc_node::_init(Genode::Native_utcb &utcb, Ipc_node &starter)
+bool Ipc_node::can_send_request()
{
- _utcb = &utcb;
- _rcv_caps = starter._utcb->cap_cnt();
- Genode::Allocator &slab = pd().platform_pd().capability_slab();
- for (unsigned i = 0; i < _rcv_caps; i++)
- _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
- copy_msg(starter);
+ return _state == INACTIVE;
}
-void Ipc_node::send_request(Ipc_node &callee, capid_t capid, bool help,
- unsigned rcv_caps)
+void Ipc_node::send_request(Ipc_node &callee, bool help)
{
- if (_state != INACTIVE) {
- Genode::raw("IPC send request: bad state");
- return;
- }
- Genode::Allocator &slab = pd().platform_pd().capability_slab();
- for (unsigned i = 0; i < rcv_caps; i++)
- _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
-
_state = AWAIT_REPLY;
_callee = &callee;
- _capid = capid;
_help = false;
- _rcv_caps = rcv_caps;
/* announce request */
_callee->_announce_request(*this);
@@ -198,18 +124,14 @@ Ipc_node * Ipc_node::helping_sink() {
return _helps_outbuf_dst() ? _callee->helping_sink() : this; }
-bool Ipc_node::await_request(unsigned rcv_caps)
+bool Ipc_node::can_await_request()
{
- if (_state != INACTIVE) {
- Genode::raw("IPC await request: bad state");
- return true;
- }
- Genode::Allocator &slab = pd().platform_pd().capability_slab();
- for (unsigned i = 0; i < rcv_caps; i++)
- _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
+ return _state == INACTIVE;
+}
- _rcv_caps = rcv_caps;
+bool Ipc_node::await_request()
+{
/* if no request announced then wait */
bool announced = false;
_state = AWAIT_REQUEST;
@@ -239,11 +161,11 @@ void Ipc_node::cancel_waiting()
case AWAIT_REPLY:
_cancel_outbuf_request();
_state = INACTIVE;
- _send_request_failed();
+ _thread.ipc_send_request_failed();
break;
case AWAIT_REQUEST:
_state = INACTIVE;
- _await_request_failed();
+ _thread.ipc_await_request_failed();
break;
return;
default: return;
@@ -251,6 +173,12 @@ void Ipc_node::cancel_waiting()
}
+Ipc_node::Ipc_node(Thread &thread)
+:
+ _thread(thread)
+{ }
+
+
Ipc_node::~Ipc_node()
{
_cancel_request_queue();
diff --git a/repos/base-hw/src/core/kernel/ipc_node.h b/repos/base-hw/src/core/kernel/ipc_node.h
index 135546d208..cb31f35096 100644
--- a/repos/base-hw/src/core/kernel/ipc_node.h
+++ b/repos/base-hw/src/core/kernel/ipc_node.h
@@ -15,18 +15,14 @@
#ifndef _CORE__KERNEL__IPC_NODE_H_
#define _CORE__KERNEL__IPC_NODE_H_
-/* base-local includes */
-#include
-
-/* core includes */
-#include
-#include
+/* Genode includes */
+#include
namespace Genode { class Msgbuf_base; };
namespace Kernel
{
- class Pd;
+ class Thread;
/**
* Backend for end points of synchronous interprocess communication
@@ -47,27 +43,19 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
AWAIT_REQUEST = 3,
};
- void _init(Genode::Native_utcb &utcb, Ipc_node &callee);
private:
friend class Core_thread;
friend class Genode::Fifo;
- State _state = INACTIVE;
- capid_t _capid = cap_id_invalid();
- Ipc_node * _caller = nullptr;
- Ipc_node * _callee = nullptr;
- bool _help = false;
- size_t _rcv_caps = 0; /* max capability num to receive */
- Genode::Native_utcb * _utcb = nullptr;
+ Thread &_thread;
+ State _state { INACTIVE };
+ Ipc_node * _caller { nullptr };
+ Ipc_node * _callee { nullptr };
+ bool _help { false };
Ipc_node_queue _request_queue { };
- /* pre-allocation array for obkject identity references */
- void * _obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAPS_PER_MSG];
-
- inline void copy_msg(Ipc_node &sender);
-
/**
* Buffer next request from request queue in 'r' to handle it
*/
@@ -114,40 +102,26 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
bool _helps_outbuf_dst();
/**
- * IPC node returned from waiting due to reply receipt
+ * Make the class noncopyable because it has pointer members
*/
- virtual void _send_request_succeeded() = 0;
+ Ipc_node(const Ipc_node&) = delete;
/**
- * IPC node returned from waiting due to reply cancellation
+ * Make the class noncopyable because it has pointer members
*/
- virtual void _send_request_failed() = 0;
-
- /**
- * IPC node returned from waiting due to request receipt
- */
- virtual void _await_request_succeeded() = 0;
-
- /**
- * IPC node returned from waiting due to request cancellation
- */
- virtual void _await_request_failed() = 0;
-
- protected:
-
- Pd * _pd = nullptr; /* pointer to PD this IPC node is part of */
-
-
- /***************
- ** Accessors **
- ***************/
-
- Ipc_node * callee() { return _callee; }
- State state() { return _state; }
+ const Ipc_node& operator=(const Ipc_node&) = delete;
public:
- virtual ~Ipc_node();
+ /**
+ * Destructor
+ */
+ ~Ipc_node();
+
+ /**
+ * Constructor
+ */
+ Ipc_node(Thread &thread);
/**
* Send a request and wait for the according reply
@@ -155,8 +129,8 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
* \param callee targeted IPC node
* \param help wether the request implies a helping relationship
*/
- void send_request(Ipc_node &callee, capid_t capid, bool help,
- unsigned rcv_caps);
+ bool can_send_request();
+ void send_request(Ipc_node &callee, bool help);
/**
* Return root destination of the helping-relation tree we are in
@@ -181,7 +155,8 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
*
* \return wether a request could be received already
*/
- bool await_request(unsigned rcv_caps);
+ bool can_await_request();
+ bool await_request();
/**
* Reply to last request if there's any
@@ -198,15 +173,9 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
** Accessors **
***************/
- Pd &pd() const
- {
- if (_pd)
- return *_pd;
-
- ASSERT_NEVER_CALLED;
- }
-
- Genode::Native_utcb *utcb() { return _utcb; }
+ Ipc_node * callee() { return _callee; }
+ State state() { return _state; }
+ Thread &thread() { return _thread; }
};
#endif /* _CORE__KERNEL__IPC_NODE_H_ */
diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc
index 9f4d6db3e7..3a0b9ccf4b 100644
--- a/repos/base-hw/src/core/kernel/thread.cc
+++ b/repos/base-hw/src/core/kernel/thread.cc
@@ -35,6 +35,72 @@ extern "C" void _core_start(void);
using namespace Kernel;
+static inline void free_obj_id_ref(Pd &pd, void *ptr)
+{
+ pd.platform_pd().capability_slab().free(ptr, sizeof(Object_identity_reference));
+}
+
+
+void Thread::_ipc_init(Genode::Native_utcb &utcb, Thread &starter)
+{
+ _utcb = &utcb;
+ _ipc_rcv_caps = starter._utcb->cap_cnt();
+ Genode::Allocator &slab = pd().platform_pd().capability_slab();
+ for (unsigned i = 0; i < _ipc_rcv_caps; i++)
+ _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
+ ipc_copy_msg(starter);
+}
+
+
+void Thread::ipc_copy_msg(Thread &sender)
+{
+ using namespace Genode;
+ using Reference = Object_identity_reference;
+
+ /* copy payload and set destination capability id */
+ *_utcb = *sender._utcb;
+ _utcb->destination(sender._ipc_capid);
+
+ /* translate capabilities */
+ for (unsigned i = 0; i < _ipc_rcv_caps; i++) {
+
+ capid_t id = sender._utcb->cap_get(i);
+
+ /* if there is no capability to send, just free the pre-allocation */
+ if (i >= sender._utcb->cap_cnt()) {
+ free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
+ continue;
+ }
+
+ /* lookup the capability id within the caller's cap space */
+ Reference *oir = (id == cap_id_invalid())
+ ? nullptr : sender.pd().cap_tree().find(id);
+
+ /* if the caller's capability is invalid, free the pre-allocation */
+ if (!oir) {
+ _utcb->cap_add(cap_id_invalid());
+ free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
+ continue;
+ }
+
+ /* lookup the capability id within the callee's cap space */
+ Reference *dst_oir = oir->find(pd());
+
+ /* if it is not found, and the target is not core, create a reference */
+ if (!dst_oir && (&pd() != &core_pd())) {
+ dst_oir = oir->factory(_obj_id_ref_ptr[i], pd());
+ if (!dst_oir)
+ free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
+ } else /* otherwise free the pre-allocation */
+ free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
+
+ if (dst_oir) dst_oir->add_to_utcb();
+
+ /* add the translated capability id to the target buffer */
+ _utcb->cap_add(dst_oir ? dst_oir->capid() : cap_id_invalid());
+ }
+}
+
Thread::Tlb_invalidation::Tlb_invalidation(Thread & caller, Pd & pd,
addr_t addr, size_t size,
@@ -114,7 +180,7 @@ void Thread::_receive_signal(void * const base, size_t const size)
}
-void Thread::_send_request_succeeded()
+void Thread::ipc_send_request_succeeded()
{
assert(_state == AWAITS_IPC);
user_arg_0(0);
@@ -123,7 +189,7 @@ void Thread::_send_request_succeeded()
}
-void Thread::_send_request_failed()
+void Thread::ipc_send_request_failed()
{
assert(_state == AWAITS_IPC);
user_arg_0(-1);
@@ -132,7 +198,7 @@ void Thread::_send_request_failed()
}
-void Thread::_await_request_succeeded()
+void Thread::ipc_await_request_succeeded()
{
assert(_state == AWAITS_IPC);
user_arg_0(0);
@@ -140,7 +206,7 @@ void Thread::_await_request_succeeded()
}
-void Thread::_await_request_failed()
+void Thread::ipc_await_request_failed()
{
assert(_state == AWAITS_IPC);
user_arg_0(-1);
@@ -151,15 +217,15 @@ void Thread::_await_request_failed()
void Thread::_deactivate_used_shares()
{
Cpu_job::_deactivate_own_share();
- Ipc_node::for_each_helper([&] (Ipc_node &h) {
- static_cast(h)._deactivate_used_shares(); });
+ _ipc_node.for_each_helper([&] (Ipc_node &ipc_node) {
+ ipc_node.thread()._deactivate_used_shares(); });
}
void Thread::_activate_used_shares()
{
Cpu_job::_activate_own_share();
- Ipc_node::for_each_helper([&] (Ipc_node &h) {
- static_cast(h)._activate_used_shares(); });
+ _ipc_node.for_each_helper([&] (Ipc_node &ipc_node) {
+ ipc_node.thread()._activate_used_shares(); });
}
void Thread::_become_active()
@@ -180,7 +246,7 @@ void Thread::_die() { _become_inactive(DEAD); }
Cpu_job * Thread::helping_sink() {
- return static_cast(Ipc_node::helping_sink()); }
+ return &_ipc_node.helping_sink()->thread(); }
size_t Thread::_core_to_kernel_quota(size_t const quota) const
@@ -212,7 +278,7 @@ void Thread::_call_start_thread()
/* join protection domain */
thread._pd = (Pd *) user_arg_3();
- thread.Ipc_node::_init(*(Native_utcb *)user_arg_4(), *this);
+ thread._ipc_init(*(Native_utcb *)user_arg_4(), *this);
thread._become_active();
}
@@ -285,7 +351,7 @@ void Thread::_cancel_blocking()
_become_active();
return;
case AWAITS_IPC:
- Ipc_node::cancel_waiting();
+ _ipc_node.cancel_waiting();
return;
case AWAITS_SIGNAL:
Signal_handler::cancel_waiting();
@@ -339,7 +405,18 @@ void Thread::_call_delete_thread()
void Thread::_call_await_request_msg()
{
- if (Ipc_node::await_request(user_arg_1())) {
+ if (!_ipc_node.can_await_request()) {
+ Genode::raw("IPC await request: bad state");
+ user_arg_0(0);
+ return;
+ }
+ unsigned const rcv_caps = user_arg_1();
+ Genode::Allocator &slab = pd().platform_pd().capability_slab();
+ for (unsigned i = 0; i < rcv_caps; i++)
+ _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
+
+ _ipc_rcv_caps = rcv_caps;
+ if (_ipc_node.await_request()) {
user_arg_0(0);
return;
}
@@ -390,8 +467,19 @@ void Thread::_call_send_request_msg()
bool const help = Cpu_job::_helping_possible(*dst);
oir = oir->find(dst->pd());
- Ipc_node::send_request(*dst, oir ? oir->capid() : cap_id_invalid(),
- help, user_arg_2());
+ if (!_ipc_node.can_send_request()) {
+ Genode::raw("IPC send request: bad state");
+ } else {
+ unsigned const rcv_caps = user_arg_2();
+ Genode::Allocator &slab = pd().platform_pd().capability_slab();
+ for (unsigned i = 0; i < rcv_caps; i++)
+ _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
+
+ _ipc_capid = oir ? oir->capid() : cap_id_invalid();
+ _ipc_rcv_caps = rcv_caps;
+ _ipc_node.send_request(dst->_ipc_node, help);
+ }
+
_state = AWAITS_IPC;
if (!help || !dst->own_share_active()) { _deactivate_used_shares(); }
}
@@ -399,7 +487,7 @@ void Thread::_call_send_request_msg()
void Thread::_call_send_reply_msg()
{
- Ipc_node::send_reply();
+ _ipc_node.send_reply();
bool const await_request_msg = user_arg_2();
if (await_request_msg) { _call_await_request_msg(); }
else { user_arg_0(0); }
@@ -730,7 +818,7 @@ void Thread::_mmu_exception()
Thread::Thread(unsigned const priority, unsigned const quota,
char const * const label, bool core)
:
- Cpu_job(priority, quota), _state(AWAITS_START),
+ Cpu_job(priority, quota), _ipc_node(*this), _state(AWAITS_START),
_signal_receiver(0), _label(label), _core(core), regs(core) { }
diff --git a/repos/base-hw/src/core/kernel/thread.h b/repos/base-hw/src/core/kernel/thread.h
index c3a4584581..c632beff02 100644
--- a/repos/base-hw/src/core/kernel/thread.h
+++ b/repos/base-hw/src/core/kernel/thread.h
@@ -14,6 +14,8 @@
#ifndef _CORE__KERNEL__THREAD_H_
#define _CORE__KERNEL__THREAD_H_
+
+/* Genode includes */
#include
#include
@@ -24,6 +26,12 @@
#include
#include
#include
+#include
+#include
+
+/* base-local includes */
+#include
+
namespace Kernel
{
@@ -50,9 +58,8 @@ struct Kernel::Thread_fault
*/
class Kernel::Thread
:
- public Kernel::Object, public Cpu_job,
- public Ipc_node, public Signal_context_killer, public Signal_handler,
- private Timeout
+ public Kernel::Object, public Cpu_job, public Signal_context_killer,
+ public Signal_handler, private Timeout
{
private:
@@ -121,15 +128,21 @@ class Kernel::Thread
DEAD = 7,
};
- Signal_context * _pager = nullptr;
- Thread_fault _fault { };
- State _state;
- Signal_receiver * _signal_receiver;
- char const * const _label;
- capid_t _timeout_sigid = 0;
- bool _paused = false;
- bool _cancel_next_await_signal = false;
- bool const _core = false;
+ void *_obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAPS_PER_MSG];
+ Ipc_node _ipc_node;
+ capid_t _ipc_capid { cap_id_invalid() };
+ size_t _ipc_rcv_caps { 0 };
+ Genode::Native_utcb *_utcb { nullptr };
+ Pd *_pd { nullptr };
+ Signal_context *_pager { nullptr };
+ Thread_fault _fault { };
+ State _state;
+ Signal_receiver *_signal_receiver;
+ char const *const _label;
+ capid_t _timeout_sigid { 0 };
+ bool _paused { false };
+ bool _cancel_next_await_signal { false };
+ bool const _core { false };
Genode::Constructible _tlb_invalidation {};
Genode::Constructible _destroy {};
@@ -258,6 +271,8 @@ class Kernel::Thread
kobj.destruct();
}
+ void _ipc_init(Genode::Native_utcb &utcb, Thread &callee);
+
/***************************
** Signal_context_killer **
@@ -276,15 +291,6 @@ class Kernel::Thread
void _receive_signal(void * const base, size_t const size) override;
- /**************
- ** Ipc_node **
- **************/
-
- void _send_request_succeeded() override;
- void _send_request_failed() override;
- void _await_request_succeeded() override;
- void _await_request_failed() override;
-
public:
Genode::Align_at regs;
@@ -373,6 +379,16 @@ class Kernel::Thread
void print(Genode::Output &out) const;
+ /**************
+ ** Ipc_node **
+ **************/
+
+ void ipc_send_request_succeeded() ;
+ void ipc_send_request_failed() ;
+ void ipc_await_request_succeeded();
+ void ipc_await_request_failed() ;
+ void ipc_copy_msg(Thread &sender) ;
+
/*************
** Cpu_job **
@@ -396,6 +412,15 @@ class Kernel::Thread
char const * label() const { return _label; }
Thread_fault fault() const { return _fault; }
+ Genode::Native_utcb *utcb() { return _utcb; }
+
+ Pd &pd() const
+ {
+ if (_pd)
+ return *_pd;
+
+ ASSERT_NEVER_CALLED;
+ }
};