diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index 0cec2f0986..f1d216b211 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -162,14 +162,10 @@ struct Genode::Child_policy */ virtual void init(Pd_session &, Capability) { } - class Nonexistent_id_space : Exception { }; - /** * ID space for sessions provided by the child - * - * \throw Nonexistent_id_space */ - virtual Id_space &server_id_space() { throw Nonexistent_id_space(); } + virtual Id_space &server_id_space() = 0; /** * Notification hook invoked each time a session state is modified diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 9da4ed6fd5..861a424847 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -121,6 +121,8 @@ class Core_child : public Child_policy Cap_quota const _cap_quota; Ram_quota const _ram_quota; + Id_space _server_ids { }; + Child _child; public: @@ -183,6 +185,8 @@ class Core_child : public Child_policy Pd_session_capability ref_pd_cap() const override { return _core_pd_cap; } size_t session_alloc_batch_size() const override { return 128; } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index ec476d5726..93140d6f0e 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -506,133 +506,127 @@ void Child::session_closed(Session_state &session) void Child::session_response(Server::Id id, Session_response response) { - try { - _policy.server_id_space().apply(id, [&] (Session_state &session) { + _policy.server_id_space().apply(id, [&] (Session_state &session) { - switch (response) { + switch (response) { - case Parent::SESSION_CLOSED: - session.phase = Session_state::CLOSED; + case Parent::SESSION_CLOSED: + session.phase = Session_state::CLOSED; + + /* + * If the client exists, reflect the response to the client + * via the 'closed_callback'. If the client has vanished, + * i.e., if the close request was issued by ourself while + * killing a child, we drop the session state immediately. + */ + if (session.closed_callback) { + session.closed_callback->session_closed(session); + + } else { /* - * If the client exists, reflect the response to the client - * via the 'closed_callback'. If the client has vanished, - * i.e., if the close request was issued by ourself while - * killing a child, we drop the session state immediately. + * The client no longer exists. So we cannot take the + * regular path of executing '_revert_quota_and_destroy' in + * the context of the client. Instead, we immediately + * withdraw the session quota from the server ('this') to + * the reference account, and destroy the session object. */ - if (session.closed_callback) { - session.closed_callback->session_closed(session); + Ram_transfer::Remote_account ref_ram_account(_policy.ref_pd(), _policy.ref_pd_cap()); + Ram_transfer::Account &service_ram_account = session.service(); - } else { + Cap_transfer::Remote_account ref_cap_account(_policy.ref_pd(), _policy.ref_pd_cap()); + Cap_transfer::Account &service_cap_account = session.service(); - /* - * The client no longer exists. So we cannot take the - * regular path of executing '_revert_quota_and_destroy' in - * the context of the client. Instead, we immediately - * withdraw the session quota from the server ('this') to - * the reference account, and destroy the session object. - */ - Ram_transfer::Remote_account ref_ram_account(_policy.ref_pd(), _policy.ref_pd_cap()); - Ram_transfer::Account &service_ram_account = session.service(); + try { + /* transfer session quota from the service to ourself */ + Ram_transfer ram_donation_from_service(session.donated_ram_quota(), + service_ram_account, ref_ram_account); - Cap_transfer::Remote_account ref_cap_account(_policy.ref_pd(), _policy.ref_pd_cap()); - Cap_transfer::Account &service_cap_account = session.service(); + Cap_transfer cap_donation_from_service(session.donated_cap_quota(), + service_cap_account, ref_cap_account); - try { - /* transfer session quota from the service to ourself */ - Ram_transfer ram_donation_from_service(session.donated_ram_quota(), - service_ram_account, ref_ram_account); - - Cap_transfer cap_donation_from_service(session.donated_cap_quota(), - service_cap_account, ref_cap_account); - - ram_donation_from_service.acknowledge(); - cap_donation_from_service.acknowledge(); - } - catch (Ram_transfer::Quota_exceeded) { - warning(_policy.name(), " failed to return session RAM quota " - "(", session.donated_ram_quota(), ")"); } - catch (Cap_transfer::Quota_exceeded) { - warning(_policy.name(), " failed to return session cap quota " - "(", session.donated_cap_quota(), ")"); } - - session.destroy(); - _policy.session_state_changed(); + ram_donation_from_service.acknowledge(); + cap_donation_from_service.acknowledge(); } - break; + catch (Ram_transfer::Quota_exceeded) { + warning(_policy.name(), " failed to return session RAM quota " + "(", session.donated_ram_quota(), ")"); } + catch (Cap_transfer::Quota_exceeded) { + warning(_policy.name(), " failed to return session cap quota " + "(", session.donated_cap_quota(), ")"); } - case Parent::SERVICE_DENIED: - session.phase = Session_state::SERVICE_DENIED; - if (session.ready_callback) - session.ready_callback->session_ready(session); - break; - - case Parent::INSUFFICIENT_RAM_QUOTA: - session.phase = Session_state::INSUFFICIENT_RAM_QUOTA; - if (session.ready_callback) - session.ready_callback->session_ready(session); - break; - - case Parent::INSUFFICIENT_CAP_QUOTA: - session.phase = Session_state::INSUFFICIENT_CAP_QUOTA; - if (session.ready_callback) - session.ready_callback->session_ready(session); - break; - - case Parent::SESSION_OK: - if (session.phase == Session_state::UPGRADE_REQUESTED) { - session.phase = Session_state::CAP_HANDED_OUT; - if (session.ready_callback) - session.ready_callback->session_ready(session); - } - break; + session.destroy(); + _policy.session_state_changed(); } - }, - [&] /* missing ID */ { - warning("unexpected session response for unknown session"); - }); - } - catch (Child_policy::Nonexistent_id_space) { } + break; + + case Parent::SERVICE_DENIED: + session.phase = Session_state::SERVICE_DENIED; + if (session.ready_callback) + session.ready_callback->session_ready(session); + break; + + case Parent::INSUFFICIENT_RAM_QUOTA: + session.phase = Session_state::INSUFFICIENT_RAM_QUOTA; + if (session.ready_callback) + session.ready_callback->session_ready(session); + break; + + case Parent::INSUFFICIENT_CAP_QUOTA: + session.phase = Session_state::INSUFFICIENT_CAP_QUOTA; + if (session.ready_callback) + session.ready_callback->session_ready(session); + break; + + case Parent::SESSION_OK: + if (session.phase == Session_state::UPGRADE_REQUESTED) { + session.phase = Session_state::CAP_HANDED_OUT; + if (session.ready_callback) + session.ready_callback->session_ready(session); + } + break; + } + }, + [&] /* missing ID */ { + warning("unexpected session response for unknown session"); + }); } void Child::deliver_session_cap(Server::Id id, Session_capability cap) { - try { - _policy.server_id_space().apply(id, [&] (Session_state &session) { + _policy.server_id_space().apply(id, [&] (Session_state &session) { - /* ignore responses after 'close_all_sessions' of the client */ - if (session.phase != Session_state::CREATE_REQUESTED) - return; + /* ignore responses after 'close_all_sessions' of the client */ + if (session.phase != Session_state::CREATE_REQUESTED) + return; - if (session.cap.valid()) { - _error("attempt to assign session cap twice"); - return; - } + if (session.cap.valid()) { + _error("attempt to assign session cap twice"); + return; + } - /* - * If the client vanished during the session creation, the - * session-close state change must be reflected to the server - * as soon as the session becomes available. This enables the - * server to wind down the session. If we just discarded the - * session, the server's ID space would become inconsistent - * with ours. - */ - if (!session.client_exists()) { - session.phase = Session_state::CLOSE_REQUESTED; - session.service().initiate_request(session); - return; - } + /* + * If the client vanished during the session creation, the + * session-close state change must be reflected to the server + * as soon as the session becomes available. This enables the + * server to wind down the session. If we just discarded the + * session, the server's ID space would become inconsistent + * with ours. + */ + if (!session.client_exists()) { + session.phase = Session_state::CLOSE_REQUESTED; + session.service().initiate_request(session); + return; + } - session.cap = cap; - session.phase = Session_state::AVAILABLE; + session.cap = cap; + session.phase = Session_state::AVAILABLE; - if (session.ready_callback) - session.ready_callback->session_ready(session); - }, - [&] /* missing ID */ { }); - } - catch (Child_policy::Nonexistent_id_space) { } + if (session.ready_callback) + session.ready_callback->session_ready(session); + }, + [&] /* missing ID */ { }); } @@ -866,11 +860,8 @@ void Child::close_all_sessions() * with the server. So the added complexity of reverting the session quotas * would be to no benefit. */ - try { - auto lambda = [&] (Session_state &s) { _revert_quota_and_destroy(s); }; - while (_policy.server_id_space().apply_any(lambda)); - } - catch (Child_policy::Nonexistent_id_space) { } + auto lambda = [&] (Session_state &s) { _revert_quota_and_destroy(s); }; + while (_policy.server_id_space().apply_any(lambda)); /* * Issue close requests to the providers of the environment sessions, diff --git a/repos/base/src/test/rm_fault/main.cc b/repos/base/src/test/rm_fault/main.cc index 16b81e813e..1a86ab7f94 100644 --- a/repos/base/src/test/rm_fault/main.cc +++ b/repos/base/src/test/rm_fault/main.cc @@ -174,6 +174,7 @@ class Test_child_policy : public Child_policy Env &_env; Parent_services &_parent_services; + Id_space _server_ids { }; Signal_context_capability const _fault_handler_sigh; Signal_context_capability const _fault_handler_stack_sigh; @@ -239,6 +240,8 @@ class Test_child_policy : public Child_policy .label = label, .diag = diag }; } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/libports/src/lib/libc/fork.cc b/repos/libports/src/lib/libc/fork.cc index 0344c57c94..acd7d3d4b4 100644 --- a/repos/libports/src/lib/libc/fork.cc +++ b/repos/libports/src/lib/libc/fork.cc @@ -428,6 +428,8 @@ struct Libc::Forked_child : Child_policy, Child_ready Local_clone_service _local_clone_service; Local_rom_service _config_rom_service; + Id_space _server_ids { }; + pid_t pid() const { return _pid; } bool running() const { return _state == State::RUNNING; } @@ -539,6 +541,8 @@ struct Libc::Forked_child : Child_policy, Child_ready Signal_transmitter(_exit_handler).submit(); } + Id_space &server_id_space() override { return _server_ids; } + Child _child; Forked_child(Env &env, diff --git a/repos/os/src/app/sequence/main.cc b/repos/os/src/app/sequence/main.cc index ead37ab9a4..148ec96ba6 100644 --- a/repos/os/src/app/sequence/main.cc +++ b/repos/os/src/app/sequence/main.cc @@ -70,6 +70,8 @@ struct Sequence::Child : Genode::Child_policy Registry _parent_services { }; + Id_space _server_ids { }; + /* queue a child reload from the async Parent interface */ Signal_transmitter _exit_transmitter; @@ -205,6 +207,8 @@ struct Sequence::Child : Genode::Child_policy ref_pd().transfer_quota(pd_cap, Cap_quota{_env.pd().avail_caps().value >> 1}); ref_pd().transfer_quota(pd_cap, Ram_quota{_env.pd().avail_ram().value >> 1}); } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/os/src/app/shim/main.cc b/repos/os/src/app/shim/main.cc index b2cb421b6d..bf01a07bb1 100644 --- a/repos/os/src/app/shim/main.cc +++ b/repos/os/src/app/shim/main.cc @@ -57,6 +57,8 @@ class Shim::Main : public Child_policy Parent_services _parent_services { }; + Id_space _server_ids { }; + Child _child { _env.rm(), _env.ep().rpc_ep(), *this }; Service &_matching_service(Service::Name const &name) @@ -125,6 +127,8 @@ class Shim::Main : public Child_policy label.length()), .diag = diag }; } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/os/src/test/bomb/main.cc b/repos/os/src/test/bomb/main.cc index 1ddf16267d..f0e01e01d3 100644 --- a/repos/os/src/test/bomb/main.cc +++ b/repos/os/src/test/bomb/main.cc @@ -37,6 +37,8 @@ class Bomb_child : public Child_policy Registry > &_parent_services; + Id_space _server_ids { }; + Child_policy_dynamic_rom_file _config_policy { _env.rm(), "config", _env.ep().rpc_ep(), &_env.ram() }; Child _child { _env.rm(), _env.ep().rpc_ep(), *this }; @@ -108,6 +110,8 @@ class Bomb_child : public Child_policy .label = label, .diag = diag }; } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/os/src/test/fault_detection/main.cc b/repos/os/src/test/fault_detection/main.cc index 505f28b9b6..4bc527ac76 100644 --- a/repos/os/src/test/fault_detection/main.cc +++ b/repos/os/src/test/fault_detection/main.cc @@ -75,6 +75,7 @@ class Test_child : public Genode::Child_policy Parent_service _pd_service { _env, Pd_session::service_name() }; Parent_service _log_service { _env, Log_session::service_name() }; Parent_service _rom_service { _env, Rom_session::service_name() }; + Id_space _server_ids { }; Child _child; public: @@ -134,6 +135,8 @@ class Test_child : public Genode::Child_policy throw Service_denied(); } + + Id_space &server_id_space() override { return _server_ids; } }; diff --git a/repos/os/src/test/resource_yield/main.cc b/repos/os/src/test/resource_yield/main.cc index ff36796ed9..dd2aa1df05 100644 --- a/repos/os/src/test/resource_yield/main.cc +++ b/repos/os/src/test/resource_yield/main.cc @@ -288,6 +288,8 @@ class Test::Parent Ram_quota const _ram_quota { 10*1024*1024 }; Binary_name const _binary_name { "test-resource_yield" }; + Id_space _server_ids { }; + /* * Config ROM service */ @@ -353,6 +355,8 @@ class Test::Parent return route(*service_ptr); } + + Id_space &server_id_space() override { return _server_ids; } }; Policy _policy { *this, _env };