From 30b70da6c1278e3ece8c566f352ab8c092eaedc0 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 10 May 2023 11:39:15 +0200 Subject: [PATCH] base/child.h: Child_policy::with_address_space This patch replaces the former 'address_space' accessor by a new 'with_address_space' interface that grants access to the region map of the child's address space, but limits the interface lifetime to the scope of the caller. Issue #4917 --- repos/base/include/base/child.h | 49 +++++++++++++++++++++++--------- repos/base/src/lib/base/child.cc | 31 ++------------------ 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index d38a3d75bd..d2cabfc1de 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -125,6 +125,11 @@ struct Genode::Child_policy virtual Pd_session &ref_pd() = 0; virtual Pd_session_capability ref_pd_cap() const = 0; + /** + * RAM allocator used as backing store for '_session_md_alloc' + */ + virtual Ram_allocator &session_md_ram() { return ref_pd(); } + /** * Respond to the release of resources by the child * @@ -188,22 +193,38 @@ struct Genode::Child_policy */ virtual bool initiate_env_sessions() const { return true; } + struct With_address_space_fn : Interface + { + virtual void call(Region_map &) const = 0; + }; + + virtual void _with_address_space(Pd_session &pd, With_address_space_fn const &fn) + { + Region_map_client region_map(pd.address_space()); + fn.call(region_map); + } + /** - * Return region map for the child's address space + * Call functor 'fn' with the child's address-space region map as argument * - * \param pd the child's PD session capability - * - * By default, the function returns a 'nullptr'. In this case, the 'Child' - * interacts with the address space of the child's PD session via RPC calls - * to the 'Pd_session::address_space'. - * - * By overriding the default, those RPC calls can be omitted, which is - * useful if the child's PD session (including the PD's address space) is - * virtualized by the parent. If the virtual PD session is served by the - * same entrypoint as the child's parent interface, an RPC call to 'pd' - * would otherwise produce a deadlock. + * In the common case where the child's PD is provided by core, the address + * space is accessed via the 'Region_map' RPC interface. However, in cases + * where the child's PD session interface is locally implemented - as is + * the case for a debug monitor - the address space must be accessed by + * component-local method calls instead. */ - virtual Region_map *address_space(Pd_session &) { return nullptr; } + template + void with_address_space(Pd_session &pd, FN const &fn) + { + struct Impl : With_address_space_fn + { + FN const &_fn; + Impl(FN const &fn) : _fn(fn) { }; + void call(Region_map &rm) const override { _fn(rm); } + }; + + _with_address_space(pd, Impl(fn)); + } /** * Return true if ELF loading should be inhibited @@ -307,7 +328,7 @@ class Genode::Child : protected Rpc_object, Id_space _id_space { }; /* allocator used for dynamically created session state objects */ - Sliced_heap _session_md_alloc { _policy.ref_pd(), _local_rm }; + Sliced_heap _session_md_alloc { _policy.session_md_ram(), _local_rm }; Session_state::Factory::Batch_size const _session_batch_size { _policy.session_alloc_batch_size() }; diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 42e557a09e..2f4f0f31f7 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -731,30 +731,6 @@ void Child::heartbeat_sigh(Signal_context_capability sigh) void Child::heartbeat_response() { _outstanding_heartbeats = 0; } -namespace { - - /** - * Return interface for interacting with the child's address space - * - * Depending on the return value of 'Child_policy::address_space', we - * either interact with a local object of via an RPC client stub. - */ - struct Child_address_space - { - Region_map_client _rm_client; - Region_map &_rm; - - Child_address_space(Pd_session &pd, Child_policy &policy) - : - _rm_client(pd.address_space()), - _rm(policy.address_space(pd) ? *policy.address_space(pd) : _rm_client) - { } - - Region_map ®ion_map() { return _rm; } - }; -} - - void Child::_try_construct_env_dependent_members() { /* check if the environment sessions are complete */ @@ -788,10 +764,9 @@ void Child::_try_construct_env_dependent_members() ? Process::TYPE_FORKED : Process::TYPE_LOADED; try { _initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name()); - _process.construct(type, _linker_dataspace(), _pd.session(), - *_initial_thread, _local_rm, - Child_address_space(_pd.session(), _policy).region_map(), - cap()); + _policy.with_address_space(_pd.session(), [&] (Region_map &address_space) { + _process.construct(type, _linker_dataspace(), _pd.session(), + *_initial_thread, _local_rm, address_space, cap()); }); } catch (Out_of_ram) { _error("out of RAM during ELF loading"); } catch (Out_of_caps) { _error("out of caps during ELF loading"); }