From 725d16e18e0e2d5b5c534dd5cead81836d30c7e9 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 5 Feb 2020 16:42:39 +0100 Subject: [PATCH] hw: optimize ipc capability allocation In preparation of ipc receive, by now a bunch of capabilities got allocated to be ready iin case of capability receiption. After that unuse slots were freed again. This overhead of senseless (de-)allocations is replaced in this commit by just restock capability slots that got used by the last receive. Fix #3640 --- repos/base-hw/src/core/kernel/thread.cc | 60 +++++++++++++------------ repos/base-hw/src/core/kernel/thread.h | 8 +++- repos/base-hw/src/core/platform_pd.cc | 4 -- repos/base-hw/src/core/platform_pd.h | 5 --- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index fc656e5da..c3466504c 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -35,19 +35,34 @@ extern "C" void _core_start(void); using namespace Kernel; -static inline void free_obj_id_ref(Pd &pd, void *ptr) + +void Thread::_ipc_alloc_recv_caps(unsigned cap_count) { - pd.platform_pd().capability_slab().free(ptr, sizeof(Object_identity_reference)); + Genode::Allocator &slab = pd().platform_pd().capability_slab(); + for (unsigned i = 0; i < cap_count; i++) { + if (_obj_id_ref_ptr[i] == nullptr) + _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference)); + } + _ipc_rcv_caps = cap_count; +} + + +void Thread::_ipc_free_recv_caps() +{ + for (unsigned i = 0; i < _ipc_rcv_caps; i++) { + if (_obj_id_ref_ptr[i]) { + Genode::Allocator &slab = pd().platform_pd().capability_slab(); + slab.free(_obj_id_ref_ptr[i], sizeof(Object_identity_reference)); + } + } + _ipc_rcv_caps = 0; } 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_alloc_recv_caps(starter._utcb->cap_cnt()); ipc_copy_msg(starter); } @@ -66,20 +81,16 @@ void Thread::ipc_copy_msg(Thread &sender) 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; - } + /* if there is no capability to send, nothing to do */ + if (i >= sender._utcb->cap_cnt()) { 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 the caller's capability is invalid, continue */ if (!oir) { _utcb->cap_add(cap_id_invalid()); - free_obj_id_ref(pd(), _obj_id_ref_ptr[i]); continue; } @@ -89,10 +100,8 @@ void Thread::ipc_copy_msg(Thread &sender) /* 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) _obj_id_ref_ptr[i] = nullptr; + } if (dst_oir) dst_oir->add_to_utcb(); @@ -405,12 +414,7 @@ void Thread::_call_delete_thread() void Thread::_call_await_request_msg() { if (_ipc_node.can_await_request()) { - 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; + _ipc_alloc_recv_caps(user_arg_1()); _ipc_node.await_request(); if (_ipc_node.awaits_request()) { _become_inactive(AWAITS_IPC); @@ -473,13 +477,8 @@ void Thread::_call_send_request_msg() 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_alloc_recv_caps(user_arg_2()); _ipc_capid = oir ? oir->capid() : cap_id_invalid(); - _ipc_rcv_caps = rcv_caps; _ipc_node.send_request(dst->_ipc_node, help); } @@ -832,6 +831,9 @@ Thread::Thread(unsigned const priority, unsigned const quota, _label(label), _core(core), regs(core) { } +Thread::~Thread() { _ipc_free_recv_caps(); } + + void Thread::print(Genode::Output &out) const { Genode::print(out, _pd ? _pd->platform_pd().label() : "?"); diff --git a/repos/base-hw/src/core/kernel/thread.h b/repos/base-hw/src/core/kernel/thread.h index fb436066b..ae088d66e 100644 --- a/repos/base-hw/src/core/kernel/thread.h +++ b/repos/base-hw/src/core/kernel/thread.h @@ -125,7 +125,9 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout DEAD = 7, }; - void *_obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAPS_PER_MSG]; + enum { MAX_RCV_CAPS = Genode::Msgbuf_base::MAX_CAPS_PER_MSG }; + + void *_obj_id_ref_ptr[MAX_RCV_CAPS] { nullptr }; Ipc_node _ipc_node; capid_t _ipc_capid { cap_id_invalid() }; size_t _ipc_rcv_caps { 0 }; @@ -269,6 +271,8 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout kobj.destruct(); } + void _ipc_alloc_recv_caps(unsigned rcv_cap_count); + void _ipc_free_recv_caps(); void _ipc_init(Genode::Native_utcb &utcb, Thread &callee); public: @@ -294,6 +298,8 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout Thread(char const * const label) : Thread(Cpu_priority::MIN, 0, label, true) { } + ~Thread(); + /************************** ** Support for syscalls ** diff --git a/repos/base-hw/src/core/platform_pd.cc b/repos/base-hw/src/core/platform_pd.cc index 3ae9ab583..ed025d0b3 100644 --- a/repos/base-hw/src/core/platform_pd.cc +++ b/repos/base-hw/src/core/platform_pd.cc @@ -132,10 +132,6 @@ bool Platform_pd::bind_thread(Platform_thread &t) } -void Platform_pd::unbind_thread(Platform_thread &t) { - t.join_pd(nullptr, false, Address_space::weak_ptr()); } - - void Platform_pd::assign_parent(Native_capability parent) { if (!_parent.valid() && parent.valid()) diff --git a/repos/base-hw/src/core/platform_pd.h b/repos/base-hw/src/core/platform_pd.h index 5ea477773..fb0c67909 100644 --- a/repos/base-hw/src/core/platform_pd.h +++ b/repos/base-hw/src/core/platform_pd.h @@ -209,11 +209,6 @@ class Genode::Platform_pd : public Hw::Address_space, */ bool bind_thread(Platform_thread &); - /** - * Unbind thread from protection domain - */ - void unbind_thread(Platform_thread &); - /** * Assign parent interface to protection domain */