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
This commit is contained in:
Norman Feske 2023-05-10 11:39:15 +02:00
parent f47c64e246
commit 30b70da6c1
2 changed files with 38 additions and 42 deletions

View File

@ -125,6 +125,11 @@ struct Genode::Child_policy
virtual Pd_session &ref_pd() = 0; virtual Pd_session &ref_pd() = 0;
virtual Pd_session_capability ref_pd_cap() const = 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 * 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; } 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 * 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
* By default, the function returns a 'nullptr'. In this case, the 'Child' * where the child's PD session interface is locally implemented - as is
* interacts with the address space of the child's PD session via RPC calls * the case for a debug monitor - the address space must be accessed by
* to the 'Pd_session::address_space'. * component-local method calls instead.
*
* 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.
*/ */
virtual Region_map *address_space(Pd_session &) { return nullptr; } template <typename FN>
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 * Return true if ELF loading should be inhibited
@ -307,7 +328,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Id_space<Client> _id_space { }; Id_space<Client> _id_space { };
/* allocator used for dynamically created session state objects */ /* 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_state::Factory::Batch_size const
_session_batch_size { _policy.session_alloc_batch_size() }; _session_batch_size { _policy.session_alloc_batch_size() };

View File

@ -731,30 +731,6 @@ void Child::heartbeat_sigh(Signal_context_capability sigh)
void Child::heartbeat_response() { _outstanding_heartbeats = 0; } 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 &region_map() { return _rm; }
};
}
void Child::_try_construct_env_dependent_members() void Child::_try_construct_env_dependent_members()
{ {
/* check if the environment sessions are complete */ /* check if the environment sessions are complete */
@ -788,10 +764,9 @@ void Child::_try_construct_env_dependent_members()
? Process::TYPE_FORKED : Process::TYPE_LOADED; ? Process::TYPE_FORKED : Process::TYPE_LOADED;
try { try {
_initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name()); _initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name());
_policy.with_address_space(_pd.session(), [&] (Region_map &address_space) {
_process.construct(type, _linker_dataspace(), _pd.session(), _process.construct(type, _linker_dataspace(), _pd.session(),
*_initial_thread, _local_rm, *_initial_thread, _local_rm, address_space, cap()); });
Child_address_space(_pd.session(), _policy).region_map(),
cap());
} }
catch (Out_of_ram) { _error("out of RAM during ELF loading"); } catch (Out_of_ram) { _error("out of RAM during ELF loading"); }
catch (Out_of_caps) { _error("out of caps during ELF loading"); } catch (Out_of_caps) { _error("out of caps during ELF loading"); }