diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index d071cd465..223335389 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -445,7 +445,7 @@ class Genode::Child : protected Rpc_object, Env_service(Child &child, Service &service) : - Genode::Service(CONNECTION::service_name(), service.ram()), + Genode::Service(CONNECTION::service_name()), _child(child), _service(service) { } @@ -469,6 +469,23 @@ class Genode::Child : protected Rpc_object, _child._try_construct_env_dependent_members(); } + /** + * Service (Ram_transfer::Account) interface + */ + void transfer(Ram_session_capability to, Ram_quota amount) override + { + Ram_transfer::Account &from = _service; + from.transfer(to, amount); + } + + /** + * Service (Ram_transfer::Account) interface + */ + Ram_session_capability cap(Ram_quota) const override + { + Ram_transfer::Account &to = _service; + return to.cap(Ram_quota()); + } void wakeup() override { _service.wakeup(); } bool operator == (Service const &other) const override diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h index 64ae29c36..473283280 100644 --- a/repos/base/include/base/service.h +++ b/repos/base/include/base/service.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace Genode { @@ -27,11 +28,12 @@ namespace Genode { template class Session_factory; template class Local_service; class Parent_service; + class Async_service; class Child_service; } -class Genode::Service : Noncopyable +class Genode::Service : public Ram_transfer::Account { public: @@ -39,8 +41,7 @@ class Genode::Service : Noncopyable private: - Name const _name; - Ram_session_capability const _ram; + Name const _name; protected: @@ -64,10 +65,8 @@ class Genode::Service : Noncopyable * Constructor * * \param name service name - * \param ram RAM session to receive/withdraw session quota */ - Service(Name const &name, Ram_session_capability ram) - : _name(name), _ram(ram) { } + Service(Name const &name) : _name(name) { } virtual ~Service() { } @@ -104,11 +103,6 @@ class Genode::Service : Noncopyable */ virtual void wakeup() { } - /** - * Return the RAM session to be used for trading resources - */ - virtual Ram_session_capability ram() const { return _ram; } - virtual bool operator == (Service const &other) const { return this == &other; } }; @@ -181,10 +175,7 @@ class Genode::Local_service : public Service * Constructor */ Local_service(Factory &factory) - : - Service(SESSION::service_name(), Ram_session_capability()), - _factory(factory) - { } + : Service(SESSION::service_name()), _factory(factory) { } void initiate_request(Session_state &session) override { @@ -235,6 +226,7 @@ class Genode::Local_service : public Service break; } } + }; @@ -257,7 +249,7 @@ class Genode::Parent_service : public Service * Constructor */ Parent_service(Env &env, Service::Name const &name) - : Service(name, Ram_session_capability()), _env(env) { } + : Service(name), _env(env) { } /** * Constructor @@ -265,7 +257,7 @@ class Genode::Parent_service : public Service * \deprecated */ Parent_service(Service::Name const &name) - : Service(name, Ram_session_capability()), _env(_env_deprecated()) { } + : Service(name), _env(_env_deprecated()) { } void initiate_request(Session_state &session) override { @@ -284,6 +276,9 @@ class Genode::Parent_service : public Service session.phase = Session_state::AVAILABLE; } + catch (Out_of_ram) { + session.id_at_parent.destruct(); + session.phase = Session_state::INVALID_ARGS; } catch (Insufficient_ram_quota) { session.id_at_parent.destruct(); session.phase = Session_state::INSUFFICIENT_RAM_QUOTA; } @@ -304,7 +299,7 @@ class Genode::Parent_service : public Service try { _env.upgrade(session.id_at_parent->id(), args.string()); } catch (Out_of_ram) { - warning("quota exceeded while upgrading parent session"); } + warning("RAM quota exceeded while upgrading parent session"); } session.confirm_ram_upgrade(); session.phase = Session_state::CAP_HANDED_OUT; @@ -332,13 +327,13 @@ class Genode::Parent_service : public Service /** - * Representation of a service that is implemented in a child + * Representation of a service that asynchronously responds to session request */ -class Genode::Child_service : public Service +class Genode::Async_service : public Service { public: - struct Wakeup { virtual void wakeup_child_service() = 0; }; + struct Wakeup { virtual void wakeup_async_service() = 0; }; private: @@ -360,24 +355,20 @@ class Genode::Child_service : public Service public: - /** * Constructor * * \param factory server-side session-state factory * \param name name of service - * \param ram recipient of session quota * \param wakeup callback to be notified on the arrival of new * session requests - * */ - Child_service(Id_space &server_id_space, + Async_service(Service::Name const &name, + Id_space &server_id_space, Session_state::Factory &factory, - Service::Name const &name, - Ram_session_capability ram, Wakeup &wakeup) : - Service(name, ram), + Service(name), _server_id_space(server_id_space), _server_factory(factory), _wakeup(wakeup) { } @@ -395,7 +386,46 @@ class Genode::Child_service : public Service return &_server_id_space == &id_space; } - void wakeup() override { _wakeup.wakeup_child_service(); } + void wakeup() override { _wakeup.wakeup_async_service(); } +}; + + +/** + * Representation of a service that is implemented in a child + */ +class Genode::Child_service : public Async_service +{ + private: + + Ram_session_client _ram; + + public: + + /** + * Constructor + */ + Child_service(Service::Name const &name, + Id_space &server_id_space, + Session_state::Factory &factory, + Wakeup &wakeup, + Ram_session_capability ram) + : + Async_service(name, server_id_space, factory, wakeup), + _ram(ram) + { } + + /** + * Ram_transfer::Account interface + */ + void transfer(Ram_session_capability to, Ram_quota amount) override + { + if (to.valid()) _ram.transfer_quota(to, amount); + } + + /** + * Ram_transfer::Account interface + */ + Ram_session_capability cap(Ram_quota) const override { return _ram; } }; #endif /* _INCLUDE__BASE__SERVICE_H_ */ diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 94d9b2df8..12c6484b2 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -12,84 +12,11 @@ */ #include +#include using namespace Genode; -/*************** - ** Utilities ** - ***************/ - -namespace { - - /** - * Guard for transferring quota donation - * - * This class is used to provide transactional semantics of quota - * transfers. Establishing a new session involves several steps, in - * particular subsequent quota transfers. If one intermediate step - * fails, we need to revert all quota transfers that already took - * place. When instantated at a local scope, a 'Transfer' object guards - * a quota transfer. If the scope is left without prior an explicit - * acknowledgement of the transfer (for example via an exception), the - * destructor the 'Transfer' object reverts the transfer in flight. - */ - class Transfer { - - bool _ack; - Ram_quota _quantum; - Ram_session_capability _from; - Ram_session_capability _to; - - public: - - class Quota_exceeded : Exception { }; - - /** - * Constructor - * - * \param quantim number of bytes to transfer - * \param from donator RAM session - * \param to receiver RAM session - * - * \throw Quota_exceeded - */ - Transfer(Ram_quota quantum, - Ram_session_capability from, - Ram_session_capability to) - : _ack(false), _quantum(quantum), _from(from), _to(to) - { - if (!_from.valid() || !_to.valid()) - return; - - try { Ram_session_client(_from).transfer_quota(_to, quantum); } - catch (...) { - warning("not enough quota for a donation of ", quantum, " bytes"); - throw Quota_exceeded(); - } - } - - /** - * Destructor - * - * The destructor will be called when leaving the scope of the - * 'session' function. If the scope is left because of an error - * (e.g., an exception), the donation will be reverted. - */ - ~Transfer() - { - if (!_ack && _from.valid() && _to.valid()) - Ram_session_client(_to).transfer_quota(_from, _quantum); - } - - /** - * Acknowledge quota donation - */ - void acknowledge() { _ack = true; } - }; -} - - /*********** ** Child ** ***********/ @@ -270,12 +197,14 @@ Session_capability Child::session(Parent::Client::Id id, session.closed_callback = this; try { + Ram_transfer::Remote_account ref_ram_account { _policy.ref_ram(), _policy.ref_ram_cap() }; + Ram_transfer::Remote_account ram_account { ram(), ram_session_cap() }; + /* transfer the quota donation from the child's account to ourself */ - Transfer donation_from_child(ram_quota, _ram.cap(), _policy.ref_ram_cap()); + Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account); /* transfer session quota from ourself to the service provider */ - Transfer donation_to_service(forward_ram_quota, _policy.ref_ram_cap(), - service.ram()); + Ram_transfer ram_donation_to_service(forward_ram_quota, ref_ram_account, service); /* try to dispatch session request synchronously */ service.initiate_request(session); @@ -291,13 +220,13 @@ Session_capability Child::session(Parent::Client::Id id, } /* finish transaction */ - donation_from_child.acknowledge(); - donation_to_service.acknowledge(); + ram_donation_from_child.acknowledge(); + ram_donation_to_service.acknowledge(); } - catch (Transfer::Quota_exceeded) { - /* - * Release session meta data if one of the quota transfers went wrong. - */ + /* + * Release session meta data if one of the quota transfers went wrong. + */ + catch (Ram_transfer::Quota_exceeded) { session.destroy(); throw Out_of_ram(); } @@ -386,12 +315,14 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0) }; try { + Ram_transfer::Remote_account ref_ram_account { _policy.ref_ram(), _policy.ref_ram_cap() }; + Ram_transfer::Remote_account ram_account { ram(), ram_session_cap() }; + /* transfer quota from client to ourself */ - Transfer donation_from_child(ram_quota, _ram.cap(), _policy.ref_ram_cap()); + Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account); /* transfer session quota from ourself to the service provider */ - Transfer donation_to_service(ram_quota, _policy.ref_ram_cap(), - session.service().ram()); + Ram_transfer ram_donation_to_service(ram_quota, ref_ram_account, session.service()); session.increase_donated_quota(ram_quota); session.phase = Session_state::UPGRADE_REQUESTED; @@ -399,11 +330,11 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const session.service().initiate_request(session); /* finish transaction */ - donation_from_child.acknowledge(); - donation_to_service.acknowledge(); + ram_donation_from_child.acknowledge(); + ram_donation_to_service.acknowledge(); } - catch (Transfer::Quota_exceeded) { - warning(_policy.name(), ": upgrade of ", session.service().name(), " failed"); + catch (Ram_transfer::Quota_exceeded) { + warning(_policy.name(), ": RAM upgrade of ", session.service().name(), " failed"); throw Out_of_ram(); } @@ -422,10 +353,14 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const void Child::_revert_quota_and_destroy(Session_state &session) { + Ram_transfer::Remote_account ref_ram_account(_policy.ref_ram(), _policy.ref_ram_cap()); + Ram_transfer::Account &service_ram_account = session.service(); + Ram_transfer::Remote_account child_ram_account(ram(), ram_session_cap()); + try { /* transfer session quota from the service to ourself */ - Transfer donation_from_service(session.donated_ram_quota(), - session.service().ram(), _policy.ref_ram_cap()); + Ram_transfer ram_donation_from_service(session.donated_ram_quota(), + service_ram_account, ref_ram_account); /* * Transfer session quota from ourself to the client (our child). In @@ -433,15 +368,19 @@ void Child::_revert_quota_and_destroy(Session_state &session) * quota that we preserved for locally storing the session meta data * ('session_costs'). */ - Transfer donation_to_client(Ram_quota{session.donated_ram_quota().value + - _session_factory.session_costs()}, - _policy.ref_ram_cap(), ram_session_cap()); + Ram_quota const returned_ram { session.donated_ram_quota().value + + _session_factory.session_costs() }; + + Ram_transfer ram_donation_to_client(returned_ram, + ref_ram_account, child_ram_account); /* finish transaction */ - donation_from_service.acknowledge(); - donation_to_client.acknowledge(); + ram_donation_from_service.acknowledge(); + ram_donation_to_client.acknowledge(); } - catch (Transfer::Quota_exceeded) { - warning(_policy.name(), ": could not revert session quota (", session, ")"); } + catch (Ram_transfer::Quota_exceeded) { + warning(_policy.name(), ": could not revert session RAM quota (", session, ")"); } + catch (Cap_transfer::Quota_exceeded) { + warning(_policy.name(), ": could not revert session cap quota (", session, ")"); } session.destroy(); _policy.session_state_changed(); diff --git a/repos/demo/include/launchpad/launchpad.h b/repos/demo/include/launchpad/launchpad.h index 2d7c891e0..311ffbdb2 100644 --- a/repos/demo/include/launchpad/launchpad.h +++ b/repos/demo/include/launchpad/launchpad.h @@ -34,7 +34,7 @@ class Launchpad; class Launchpad_child : public Genode::Child_policy, public Genode::List::Element, - public Genode::Child_service::Wakeup + public Genode::Async_service::Wakeup { public: @@ -75,7 +75,7 @@ class Launchpad_child : public Genode::Child_policy, /** * Child_service::Wakeup callback */ - void wakeup_child_service() override + void wakeup_async_service() override { _session_requester.trigger_update(); } @@ -133,8 +133,7 @@ class Launchpad_child : public Genode::Child_policy, Binary_name binary_name() const override { return _elf_name; } - Genode::Ram_session &ref_ram() override { return _ref_ram; } - + Genode::Ram_session &ref_ram() override { return _ref_ram; } Genode::Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; } void init(Genode::Ram_session &session, @@ -198,9 +197,10 @@ class Launchpad_child : public Genode::Child_policy, } new (_alloc) - Child_service(_child_services, _session_requester.id_space(), - _child.session_factory(), service_name, - _child.ram_session_cap(), *this); + Child_service(_child_services, service_name, + _session_requester.id_space(), + _child.session_factory(), *this, + _child.ram_session_cap()); } }; diff --git a/repos/gems/include/gems/report_rom_slave.h b/repos/gems/include/gems/report_rom_slave.h index 717514da8..fb308e4b5 100644 --- a/repos/gems/include/gems/report_rom_slave.h +++ b/repos/gems/include/gems/report_rom_slave.h @@ -50,10 +50,12 @@ class Report_rom_slave : public Genode::Noncopyable Policy(Genode::Rpc_entrypoint &ep, Genode::Region_map &rm, - Genode::Ram_session_capability ram, + Genode::Ram_session &ref_ram, + Genode::Ram_session_capability ref_ram_cap, const char *config) : - Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota()) + Genode::Slave::Policy(_name(), _name(), *this, ep, rm, + ref_ram, ref_ram_cap, _quota()) { if (config) configure(config); @@ -76,11 +78,12 @@ class Report_rom_slave : public Genode::Noncopyable */ Report_rom_slave(Genode::Pd_session &pd, Genode::Region_map &rm, - Genode::Ram_session_capability ram, + Genode::Ram_session &ram, + Genode::Ram_session_capability ram_cap, char const *config) : _ep(&pd, _ep_stack_size, "report_rom"), - _policy(_ep, rm, ram, config), + _policy(_ep, rm, ram, ram_cap, config), _child(rm, _ep, _policy) { } diff --git a/repos/gems/src/app/launcher/fading_dialog.h b/repos/gems/src/app/launcher/fading_dialog.h index 0a6b37dae..da0c424c7 100644 --- a/repos/gems/src/app/launcher/fading_dialog.h +++ b/repos/gems/src/app/launcher/fading_dialog.h @@ -196,10 +196,12 @@ class Launcher::Fading_dialog : private Input_event_handler _fader_slave_ep(&env.pd(), _fader_slave_ep_stack_size, "nit_fader"), _nitpicker_connection(env, "menu"), _nitpicker_session(env, _nitpicker_connection, env.ep(), _fader_slave_ep, *this), - _nit_fader_slave(_fader_slave_ep, env.rm(), env.ram_session_cap(), + _nit_fader_slave(_fader_slave_ep, env.rm(), + env.ram(), env.ram_session_cap(), _nitpicker_service), _nit_fader_connection(env.rm(), _nit_fader_slave.policy(), Slave::Args("label=menu")), - _menu_view_slave(env.pd(), env.rm(), env.ram_session_cap(), + _menu_view_slave(env.pd(), env.rm(), + env.ram(), env.ram_session_cap(), _nit_fader_connection, _dialog_rom, _hover_report, initial_position) { diff --git a/repos/gems/src/app/launcher/main.cc b/repos/gems/src/app/launcher/main.cc index e0c0b60c5..dd69c638a 100644 --- a/repos/gems/src/app/launcher/main.cc +++ b/repos/gems/src/app/launcher/main.cc @@ -43,7 +43,8 @@ struct Launcher::Main ""; Report_rom_slave _report_rom_slave { - _env.pd(), _env.rm(), _env.ram_session_cap(), _report_rom_config }; + _env.pd(), _env.rm(), _env.ram(), _env.ram_session_cap(), + _report_rom_config }; /** * Nitpicker session used to perform session-control operations on the diff --git a/repos/gems/src/app/launcher/menu_view_slave.h b/repos/gems/src/app/launcher/menu_view_slave.h index ddb834e2f..09c249194 100644 --- a/repos/gems/src/app/launcher/menu_view_slave.h +++ b/repos/gems/src/app/launcher/menu_view_slave.h @@ -80,13 +80,15 @@ class Launcher::Menu_view_slave Policy(Genode::Rpc_entrypoint &ep, Genode::Region_map &rm, - Genode::Ram_session_capability ram, + Genode::Ram_session &ref_ram, + Genode::Ram_session_capability ref_ram_cap, Capability nitpicker_session, Capability dialog_rom_session, Capability hover_report_session, Position position) : - Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota()), + Genode::Slave::Policy(_name(), _name(), *this, ep, rm, + ref_ram, ref_ram_cap, _quota()), _nitpicker(rm, nitpicker_session), _dialog_rom(dialog_rom_session), _hover_report(hover_report_session), @@ -127,14 +129,16 @@ class Launcher::Menu_view_slave */ Menu_view_slave(Genode::Pd_session &pd, Genode::Region_map &rm, - Genode::Ram_session_capability ram, + Genode::Ram_session &ref_ram, + Genode::Ram_session_capability ref_ram_cap, Capability nitpicker_session, Capability dialog_rom_session, Capability hover_report_session, Position initial_position) : _ep(&pd, _ep_stack_size, "nit_fader"), - _policy(_ep, rm, ram, nitpicker_session, dialog_rom_session, + _policy(_ep, rm, ref_ram, ref_ram_cap, + nitpicker_session, dialog_rom_session, hover_report_session, initial_position), _child(rm, _ep, _policy) { } diff --git a/repos/gems/src/app/launcher/nit_fader_slave.h b/repos/gems/src/app/launcher/nit_fader_slave.h index 6d6115a4d..1d0b51530 100644 --- a/repos/gems/src/app/launcher/nit_fader_slave.h +++ b/repos/gems/src/app/launcher/nit_fader_slave.h @@ -52,10 +52,12 @@ class Launcher::Nit_fader_slave Policy(Rpc_entrypoint &ep, Region_map &rm, - Ram_session_capability ram, + Ram_session &ref_ram, + Ram_session_capability ref_ram_cap, Genode::Service &nitpicker_service) : - Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota()), + Genode::Slave::Policy(_name(), _name(), *this, ep, rm, + ref_ram, ref_ram_cap, _quota()), _nitpicker_service(nitpicker_service) { visible(false); @@ -87,16 +89,17 @@ class Launcher::Nit_fader_slave /** * Constructor * - * \param ep entrypoint used for nitpicker child thread - * \param ram RAM session used to allocate the configuration - * dataspace + * \param ep entrypoint used for nitpicker child thread + * \param ref_ram RAM session used to allocate the configuration + * dataspace and child memory */ Nit_fader_slave(Rpc_entrypoint &ep, Genode::Region_map &rm, - Ram_session_capability ram, + Ram_session &ref_ram, + Ram_session_capability ref_ram_cap, Genode::Service &nitpicker_service) : - _policy(ep, rm, ram, nitpicker_service), + _policy(ep, rm, ref_ram, ref_ram_cap, nitpicker_service), _child(rm, ep, _policy) { visible(false); diff --git a/repos/os/include/os/child_policy_dynamic_rom.h b/repos/os/include/os/child_policy_dynamic_rom.h index fff97bb4b..c69cc7439 100644 --- a/repos/os/include/os/child_policy_dynamic_rom.h +++ b/repos/os/include/os/child_policy_dynamic_rom.h @@ -78,7 +78,7 @@ class Genode::Child_policy_dynamic_rom_file : public Rpc_object, Rpc_entrypoint &ep, Ram_session *ram) : - Service("ROM", Ram_session_capability()), + Service("ROM"), _ram(ram), _rm(rm), _fg(*_ram, _rm, 0), _bg(*_ram, _rm, 0), _bg_has_pending_data(false), @@ -101,7 +101,7 @@ class Genode::Child_policy_dynamic_rom_file : public Rpc_object, Rpc_entrypoint &ep, Ram_session *ram) __attribute__((deprecated)) : - Service("ROM", Ram_session_capability()), + Service("ROM"), _ram(ram), _rm(*env_deprecated()->rm_session()), _fg(*_ram, _rm, 0), _bg(*_ram, _rm, 0), _bg_has_pending_data(false), diff --git a/repos/os/include/os/slave.h b/repos/os/include/os/slave.h index 5e3520fa9..afc3bd09c 100644 --- a/repos/os/include/os/slave.h +++ b/repos/os/include/os/slave.h @@ -54,7 +54,8 @@ class Genode::Slave::Policy : public Child_policy Label const _label; Binary_name const _binary_name; - Ram_session_client _ram; + Ram_session &_ref_ram; + Ram_session_capability _ref_ram_cap; Genode::Parent_service _binary_service; Ram_quota const _ram_quota; Parent_services &_parent_services; @@ -77,19 +78,22 @@ class Genode::Slave::Policy : public Child_policy * \throw Ram_session::Alloc_failed by 'Child_policy_dynamic_rom_file' * \throw Rm_session::Attach_failed by 'Child_policy_dynamic_rom_file' */ - Policy(Label const &label, - Name const &binary_name, - Parent_services &parent_services, - Rpc_entrypoint &ep, - Region_map &rm, - Ram_session_capability ram_cap, - Ram_quota ram_quota) + Policy(Label const &label, + Name const &binary_name, + Parent_services &parent_services, + Rpc_entrypoint &ep, + Region_map &rm, + Ram_session &ref_ram, + Ram_session_capability ref_ram_cap, + Ram_quota ram_quota) : - _label(label), _binary_name(binary_name), _ram(ram_cap), + _label(label), _binary_name(binary_name), + _ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap), _binary_service(Rom_session::service_name()), - _ram_quota(ram_quota), _parent_services(parent_services), _ep(ep), - _config_policy(rm, "config", _ep, &_ram), - _session_requester(ep, _ram, rm) + _ram_quota(ram_quota), + _parent_services(parent_services), _ep(ep), + _config_policy(rm, "config", _ep, &_ref_ram), + _session_requester(ep, _ref_ram, rm) { configure(""); } @@ -123,13 +127,13 @@ class Genode::Slave::Policy : public Child_policy Binary_name binary_name() const override { return _binary_name; } - Ram_session &ref_ram() override { return _ram; } - Ram_session_capability ref_ram_cap() const override { return _ram; } + Ram_session &ref_ram() override { return _ref_ram; } + Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; } void init(Ram_session &session, Ram_session_capability cap) override { - session.ref_account(_ram); - _ram.transfer_quota(cap, _ram_quota); + session.ref_account(_ref_ram_cap); + _ref_ram.transfer_quota(cap, _ram_quota); } Service &resolve_session_request(Service::Name const &service_name, @@ -178,15 +182,13 @@ class Genode::Slave::Connection_base struct Service : Genode::Service, Session_state::Ready_callback, Session_state::Closed_callback { - Id_space &_id_space; - - Lock _lock { Lock::LOCKED }; - bool _alive = false; + Policy &_policy; + Lock _lock { Lock::LOCKED }; + bool _alive = false; Service(Policy &policy) : - Genode::Service(CONNECTION::service_name(), policy.ref_ram_cap()), - _id_space(policy.server_id_space()) + Genode::Service(CONNECTION::service_name()), _policy(policy) { } void initiate_request(Session_state &session) override @@ -196,7 +198,8 @@ class Genode::Slave::Connection_base case Session_state::CREATE_REQUESTED: if (!session.id_at_server.constructed()) - session.id_at_server.construct(session, _id_space); + session.id_at_server.construct(session, + _policy.server_id_space()); session.ready_callback = this; session.async_client_notify = true; @@ -237,6 +240,22 @@ class Genode::Slave::Connection_base */ void session_closed(Session_state &s) override { _lock.unlock(); } + /** + * Service ('Ram_transfer::Account') interface + */ + void transfer(Ram_session_capability to, Ram_quota amount) override + { + if (to.valid()) _policy.ref_ram().transfer_quota(to, amount); + } + + /** + * Service ('Ram_transfer::Account') interface + */ + Ram_session_capability cap(Ram_quota) const override + { + return _policy.ref_ram_cap(); + } + } _service; Local_connection _connection; diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd.h b/repos/os/src/drivers/platform/spec/x86/device_pd.h index f00707428..406a93433 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd.h +++ b/repos/os/src/drivers/platform/spec/x86/device_pd.h @@ -33,12 +33,13 @@ class Platform::Device_pd_policy Device_pd_policy(Genode::Rpc_entrypoint &slave_ep, Genode::Region_map &local_rm, + Genode::Ram_session &ram_ref, Genode::Ram_session_capability ram_ref_cap, Genode::Ram_quota ram_quota, Genode::Session_label const &label) : Genode::Slave::Policy(label, "device_pd", *this, slave_ep, local_rm, - ram_ref_cap, ram_quota) + ram_ref, ram_ref_cap, ram_quota) { } }; diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index f802ec864..9425c0593 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -317,12 +317,13 @@ class Platform::Session_component : public Genode::Rpc_object */ Device_pd(Genode::Region_map &local_rm, Genode::Rpc_entrypoint &ep, - Genode::Ram_session_guard &guard, - Genode::Ram_session_capability ref_ram, + Genode::Ram_session_guard &ref_ram, + Genode::Ram_session_capability ref_ram_cap, Genode::Session_label const &label) try : - _reservation(guard, RAM_QUOTA), - _policy(ep, local_rm, ref_ram, Genode::Ram_quota{RAM_QUOTA}, label), + _reservation(ref_ram, RAM_QUOTA), + _policy(ep, local_rm, + ref_ram, ref_ram_cap, Genode::Ram_quota{RAM_QUOTA}, label), _child(local_rm, ep, _policy), _connection(_policy, Genode::Slave::Args()) { } diff --git a/repos/os/src/init/child.h b/repos/os/src/init/child.h index 169692cf9..8ee582c9f 100644 --- a/repos/os/src/init/child.h +++ b/repos/os/src/init/child.h @@ -31,8 +31,7 @@ namespace Init { class Child; } - -class Init::Child : Child_policy, Child_service::Wakeup +class Init::Child : Child_policy, Routed_service::Wakeup { public: @@ -170,7 +169,7 @@ class Init::Child : Child_policy, Child_service::Wakeup void _check_ram_constraints(Ram_quota ram_limit) { if (_resources.effective_ram_quota().value == 0) - warning("no valid RAM RESOURCE for child \"", _unique_name, "\""); + warning(name(), ": no valid RAM quota defined"); /* * If the configured RAM quota exceeds our own quota, we donate @@ -256,10 +255,10 @@ class Init::Child : Child_policy, Child_service::Wakeup struct Requested_resources { Ram_quota const ram; + Requested_resources(Parent::Resource_args const &args) : - ram(Ram_quota { Arg_string::find_arg(args.string(), "ram_quota") - .ulong_value(0) }) + ram (ram_quota_from_args(args.string())) { } }; @@ -270,15 +269,18 @@ class Init::Child : Child_policy, Child_service::Wakeup struct Ram_accessor : Routed_service::Ram_accessor { Genode::Child &_child; + Ram_accessor(Genode::Child &child) : _child(child) { } - Ram_session_capability ram() const override { - return _child.ram_session_cap(); } + + Ram_session &ram() override { return _child.ram(); } + Ram_session_capability ram_cap() const override { return _child.ram_session_cap(); } + } _ram_accessor { _child }; /** - * Child_service::Wakeup callback + * Async_service::Wakeup callback */ - void wakeup_child_service() override + void wakeup_async_service() override { _session_requester.trigger_update(); } @@ -340,7 +342,8 @@ class Init::Child : Child_policy, Child_service::Wakeup log(" provides service ", name); new (_alloc) - Routed_service(_child_services, this->name(), _ram_accessor, + Routed_service(_child_services, this->name(), + _ram_accessor, _session_requester.id_space(), _child.session_factory(), name, *this); diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index 7218d9477..03cdc2d44 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -276,11 +276,11 @@ void Init::Main::_handle_config() _destroy_abandoned_parent_services(); - /* initial RAM limit before starting new children */ - Ram_quota const avail_ram = _avail_ram(); + /* initial RAM and caps limit before starting new children */ + Ram_quota const avail_ram = _avail_ram(); - /* variable used to track the RAM taken by new started children */ - Ram_quota used_ram { 0 }; + /* variable used to track the RAM and caps taken by new started children */ + Ram_quota used_ram { 0 }; /* create new children */ try { @@ -324,8 +324,8 @@ void Init::Main::_handle_config() * by the Rom_connection constructor. */ } - catch (Allocator::Out_of_memory) { - warning("local memory exhausted during child creation"); } + catch (Out_of_ram) { + warning("memory exhausted during child creation"); } catch (Ram_session::Alloc_failed) { warning("failed to allocate memory during child construction"); } catch (Child::Missing_name_attribute) { diff --git a/repos/os/src/init/server.cc b/repos/os/src/init/server.cc index ef4b700df..9f5738666 100644 --- a/repos/os/src/init/server.cc +++ b/repos/os/src/init/server.cc @@ -148,13 +148,16 @@ void Init::Server::session_closed(Session_state &session) { _report_update_trigger.trigger_report_update(); - Parent::Server::Id id { session.id_at_client().value }; - _env.parent().session_response(id, Parent::SESSION_CLOSED); + Ram_transfer::Account &service_ram_account = session.service(); - Ram_session_client(session.service().ram()) - .transfer_quota(_env.ram_session_cap(), session.donated_ram_quota()); + service_ram_account.try_transfer(_env.ram_session_cap(), + session.donated_ram_quota()); + + Parent::Server::Id id { session.id_at_client().value }; session.destroy(); + + _env.parent().session_response(id, Parent::SESSION_CLOSED); } @@ -192,13 +195,18 @@ void Init::Server::_handle_create_session_request(Xml_node request, Session_state &session = route.service.create_session(route.service.factory(), - _client_id_space, id, - route.label, argbuf, Affinity()); + _client_id_space, id, route.label, + argbuf, Affinity()); /* transfer session quota */ - try { _env.ram().transfer_quota(route.service.ram(), forward_ram_quota); } - catch (...) { + try { + Ram_transfer::Remote_account env_ram_account(_env.ram(), _env.ram_session_cap()); + Ram_transfer ram_transfer(forward_ram_quota, env_ram_account, route.service); + + ram_transfer.acknowledge(); + } + catch (...) { /* * This should never happen unless our parent missed to * transfor the session quota to us prior issuing the session @@ -227,9 +235,11 @@ void Init::Server::_handle_create_session_request(Xml_node request, throw Genode::Insufficient_ram_quota(); } catch (Parent::Service_denied) { - _env.parent().session_response(Parent::Server::Id { id.value }, Parent::INVALID_ARGS); } + _env.parent().session_response(Parent::Server::Id { id.value }, + Parent::INVALID_ARGS); } catch (Genode::Insufficient_ram_quota) { - _env.parent().session_response(Parent::Server::Id { id.value }, Parent::INSUFFICIENT_RAM_QUOTA); } + _env.parent().session_response(Parent::Server::Id { id.value }, + Parent::INSUFFICIENT_RAM_QUOTA); } } @@ -243,7 +253,11 @@ void Init::Server::_handle_upgrade_session_request(Xml_node request, session.phase = Session_state::UPGRADE_REQUESTED; try { - _env.ram().transfer_quota(session.service().ram(), ram_quota); + Ram_transfer::Remote_account env_ram_account(_env.ram(), _env.ram_session_cap()); + + Ram_transfer ram_transfer(ram_quota, env_ram_account, session.service()); + + ram_transfer.acknowledge(); } catch (...) { warning("unable to upgrade session quota (", ram_quota, " bytes) " diff --git a/repos/os/src/init/service.h b/repos/os/src/init/service.h index 2172e3f02..8f4da4370 100644 --- a/repos/os/src/init/service.h +++ b/repos/os/src/init/service.h @@ -59,13 +59,17 @@ class Init::Parent_service : public Genode::Parent_service, public Abandonable /** * Init-specific representation of a child service */ -class Init::Routed_service : public Child_service, public Abandonable +class Init::Routed_service : public Async_service, public Abandonable { public: typedef Child_policy::Name Child_name; - struct Ram_accessor { virtual Ram_session_capability ram() const = 0; }; + struct Ram_accessor + { + virtual Ram_session &ram() = 0; + virtual Ram_session_capability ram_cap() const = 0; + }; private: @@ -85,34 +89,41 @@ class Init::Routed_service : public Child_service, public Abandonable * \param services registry of all services provides by children * \param child_name child name of server, used for session routing * - * The other arguments correspond to the arguments of 'Child_service'. + * The other arguments correspond to the arguments of 'Async_service'. */ - Routed_service(Registry &services, - Child_name const &child_name, - Ram_accessor &ram_accessor, - Id_space &server_id_space, - Session_state::Factory &factory, - Service::Name const &name, - Child_service::Wakeup &wakeup) + Routed_service(Registry &services, + Child_name const &child_name, + Ram_accessor &ram_accessor, + Id_space &server_id_space, + Session_state::Factory &factory, + Service::Name const &name, + Wakeup &wakeup) : - Child_service(server_id_space, factory, name, - Ram_session_capability(), wakeup), - _child_name(child_name), _ram_accessor(ram_accessor), + Async_service(name, server_id_space, factory, wakeup), + _child_name(child_name), + _ram_accessor(ram_accessor), _factory(factory), _registry_element(services, *this) { } Child_name const &child_name() const { return _child_name; } - Ram_session_capability ram() const { return _ram_accessor.ram(); } + Session_state::Factory &factory() { return _factory; } /** - * Return factory for creating/destroying session-state objects - * - * This accessor is solely meant to be used by 'Forwarded_service' to - * allocate session-state objects for sessions requested by init's - * parent. + * Ram_transfer::Account interface */ - Session_state::Factory &factory() { return _factory; } + void transfer(Ram_session_capability to, Ram_quota amount) override + { + if (to.valid()) _ram_accessor.ram().transfer_quota(to, amount); + } + + /** + * Ram_transfer::Account interface + */ + Ram_session_capability cap(Ram_quota) const override + { + return _ram_accessor.ram_cap(); + } }; #endif /* _SRC__INIT__SERVICE_H_ */ diff --git a/repos/os/src/test/dynamic_config/master/main.cc b/repos/os/src/test/dynamic_config/master/main.cc index a526c4ab4..cf351cb7d 100644 --- a/repos/os/src/test/dynamic_config/master/main.cc +++ b/repos/os/src/test/dynamic_config/master/main.cc @@ -36,7 +36,7 @@ struct Test::Policy Policy(Env &env, Name const &name) : Slave::Policy(name, name, *this, env.ep().rpc_ep(), env.rm(), - env.ram_session_cap(), Ram_quota{1024*1024}) + env.ram(), env.ram_session_cap(), Ram_quota{1024*1024}) { } }; diff --git a/repos/os/src/test/resource_yield/main.cc b/repos/os/src/test/resource_yield/main.cc index 37812a02f..9f6b6ab2f 100644 --- a/repos/os/src/test/resource_yield/main.cc +++ b/repos/os/src/test/resource_yield/main.cc @@ -296,7 +296,7 @@ class Test::Parent : Slave::Policy(Label("child"), "test-resource_yield", *this, env.ep().rpc_ep(), env.rm(), - env.ram_session_cap(), Ram_quota{SLAVE_QUOTA}), + env.ram(), env.ram_session_cap(), Ram_quota{SLAVE_QUOTA}), _parent(parent) { configure("");