mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 22:28:18 +00:00
base: use 'Quota_transfer::Account' for 'Service'
This patch makes use of the new 'Quota_transfer::Account' by the service types in base/service.h and uses 'Quota_transfer' objects in base/child.cc and init/server.cc. Furthermore, it decouples the notion of an 'Async_service' from 'Child_service'. Init's 'Routed_service' is no longer a 'Child_service' but is based on the new 'Async_service' instead. With this patch in place, quota transfers do no longer implicitly use 'Ram_session_client' objects. So transfers can in principle originate from component-local 'Ram_session_component' objects, e.g., as used by noux. Therefore, this patch removes a strumbling block for turning noux into a single threaded component in the future. Issue #2398
This commit is contained in:
committed by
Christian Helmuth
parent
5c43074bc6
commit
3670f7735d
@ -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)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -317,12 +317,13 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
*/
|
||||
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())
|
||||
{ }
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) "
|
||||
|
@ -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<Routed_service> &services,
|
||||
Child_name const &child_name,
|
||||
Ram_accessor &ram_accessor,
|
||||
Id_space<Parent::Server> &server_id_space,
|
||||
Session_state::Factory &factory,
|
||||
Service::Name const &name,
|
||||
Child_service::Wakeup &wakeup)
|
||||
Routed_service(Registry<Routed_service> &services,
|
||||
Child_name const &child_name,
|
||||
Ram_accessor &ram_accessor,
|
||||
Id_space<Parent::Server> &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_ */
|
||||
|
@ -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})
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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("<config child=\"yes\" />");
|
||||
|
Reference in New Issue
Block a user