diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index b6dab9deb1..c445a5ff6d 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -200,6 +200,16 @@ struct Genode::Child_policy */ virtual size_t session_alloc_batch_size() const { return 16; } + /** + * Return true to create the environment sessions at child construction + * + * By returning 'false', it is possible to create 'Child' objects without + * routing of their environment sessions at construction time. Once the + * routing information is available, the child's environment sessions + * must be manually initiated by calling 'Child::initiate_env_sessions()'. + */ + virtual bool initiate_env_sessions() const { return true; } + /** * Return region map for the child's address space * @@ -413,12 +423,14 @@ class Genode::Child : protected Rpc_object, template struct Env_connection { + Child &_child; + + Id_space::Id const _client_id; + typedef String<64> Label; Args const _args; - Child_policy::Route _route; - /* * The 'Env_service' monitors session responses in order to attempt * to 'Child::_try_construct_env_dependent_members()' on the @@ -456,10 +468,11 @@ class Genode::Child : protected Rpc_object, } void wakeup() override { _service.wakeup(); } + }; - } _env_service; + Constructible _env_service; - Local_connection _connection; + Constructible > _connection; /** * Construct session arguments with the child policy applied @@ -485,18 +498,34 @@ class Genode::Child : protected Rpc_object, Env_connection(Child &child, Id_space::Id id, Label const &label = Label()) : - _args(_construct_args(child._policy, label)), - _route(child._resolve_session_request(child._policy, _service_name(), - _args.string())), - _env_service(child, _route.service), - _connection(_env_service, child._id_space, id, _args, - child._policy.filter_session_affinity(Affinity())) + _child(child), _client_id(id), + _args(_construct_args(child._policy, label)) { } + /** + * Initiate routing and creation of the environment session + */ + void initiate() + { + /* don't attempt to initiate env session twice */ + if (_connection.constructed()) + return; + + Child_policy::Route const route = + _child._resolve_session_request(_child._policy, + _service_name(), + _args.string()); + + _env_service.construct(_child, route.service); + _connection.construct(*_env_service, _child._id_space, _client_id, + _args, _child._policy.filter_session_affinity(Affinity())); + } + typedef typename CONNECTION::Session_type SESSION; - SESSION &session() { return _connection.session(); } - Capability cap() const { return _connection.cap(); } + SESSION &session() { return _connection->session(); } + + Capability cap() const { return _connection->cap(); } }; Env_connection _ram { *this, Env::ram(), _policy.name() }; @@ -569,6 +598,18 @@ class Genode::Child : protected Rpc_object, */ bool active() const { return _process.constructed(); } + /** + * Initialize the child's RAM session + */ + void initiate_env_ram_session(); + + /** + * Trigger the routing and creation of the child's environment session + * + * See the description of 'Child_policy::initiate_env_sessions'. + */ + void initiate_env_sessions(); + /** * RAM quota unconditionally consumed by the child's environment */ diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h index 200df961ae..b9e8adfa7a 100644 --- a/repos/base/include/base/service.h +++ b/repos/base/include/base/service.h @@ -108,10 +108,7 @@ class Genode::Service : Noncopyable /** * Return the RAM session to be used for trading resources */ - Ram_session_capability ram() const - { - return _ram; - } + virtual Ram_session_capability ram() const { return _ram; } }; diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 420cd84430..29c11b2d8c 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -230,6 +230,8 @@ _ZN6Genode5Child16resource_requestERKNS_6StringILm160EEE T _ZN6Genode5Child16session_responseENS_8Id_spaceINS_6Parent6ServerEE2IdENS2_16Session_responseE T _ZN6Genode5Child19deliver_session_capENS_8Id_spaceINS_6Parent6ServerEE2IdENS_10CapabilityINS_7SessionEEE T _ZN6Genode5Child19resource_avail_sighENS_10CapabilityINS_14Signal_contextEEE T +_ZN6Genode5Child21initiate_env_sessionsEv T +_ZN6Genode5Child24initiate_env_ram_sessionEv T _ZN6Genode5Child4exitEi T _ZN6Genode5Child5closeENS_8Id_spaceINS_6Parent6ClientEE2IdE T _ZN6Genode5Child5yieldERKNS_6StringILm160EEE T diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index d9351af9c0..5fc0a83f46 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -712,6 +712,31 @@ void Child::_discard_env_session(Id_space::Id id) } +void Child::initiate_env_ram_session() { _ram.initiate(); } + + +void Child::initiate_env_sessions() +{ + _pd .initiate(); + _cpu .initiate(); + _log .initiate(); + _binary.initiate(); + + /* + * Issue environment-session request for obtaining the linker binary. We + * accept this request to fail. In this case, the child creation may still + * succeed if the binary is statically linked. + */ + try { + _linker.construct(*this, Parent::Env::linker(), _policy.linker_name()); + _linker->initiate(); + } + catch (Parent::Service_denied) { } + + _try_construct_env_dependent_members(); +} + + Child::Child(Region_map &local_rm, Rpc_entrypoint &entrypoint, Child_policy &policy) @@ -719,15 +744,10 @@ Child::Child(Region_map &local_rm, _policy(policy), _local_rm(local_rm), _entrypoint(entrypoint), _parent_cap(_entrypoint.manage(this)) { - /* - * Issue environment-session request for obtaining the linker binary. We - * accept this request to fail. In this case, the child creation may still - * succeed if the binary is statically linked. - */ - try { _linker.construct(*this, Parent::Env::linker(), _policy.linker_name()); } - catch (Parent::Service_denied) { } - - _try_construct_env_dependent_members(); + if (_policy.initiate_env_sessions()) { + initiate_env_ram_session(); + initiate_env_sessions(); + } }