Support upgrading of child-environment resources

Fixes #5
This commit is contained in:
Norman Feske 2012-08-15 15:21:00 +02:00
parent 27a5edaf78
commit 47e95d4e18

View File

@ -281,6 +281,11 @@ namespace Genode {
/* RM session representing the address space of the child */ /* RM session representing the address space of the child */
Rm_session_capability _rm; Rm_session_capability _rm;
/* Services where the RAM, CPU, and RM resources come from */
Service &_ram_service;
Service &_cpu_service;
Service &_rm_service;
/* heap for child-specific allocations using the child's quota */ /* heap for child-specific allocations using the child's quota */
Heap _heap; Heap _heap;
@ -349,6 +354,20 @@ namespace Genode {
destroy(heap(), s); destroy(heap(), s);
} }
/**
* Return service interface targetting the parent
*
* The service returned by this function is used as default
* provider for the RAM, CPU, and RM resources of the child. It is
* solely used for targeting resource donations during
* 'Parent::upgrade_quota()' calls.
*/
static Service *_parent_service()
{
static Parent_service parent_service("");
return &parent_service;
}
public: public:
/** /**
@ -357,23 +376,38 @@ namespace Genode {
* \param elf_ds dataspace containing the binary * \param elf_ds dataspace containing the binary
* \param ram RAM session with the child's quota * \param ram RAM session with the child's quota
* \param cpu CPU session with the child's quota * \param cpu CPU session with the child's quota
* \param rm RM session representing the address space
* of the child
* \param entrypoint server entrypoint to serve the parent interface * \param entrypoint server entrypoint to serve the parent interface
* \param policy child policy * \param policy child policy
* \param ram_service provider of the 'ram' session
* \param cpu_service provider of the 'cpu' session
* \param rm_service provider of the 'rm' session
* *
* If assigning a separate entry point to each child, the host of * If assigning a separate entry point to each child, the host of
* multiple children is able to handle a blocking invocation of * multiple children is able to handle a blocking invocation of
* the parent interface of one child while still maintaining the * the parent interface of one child while still maintaining the
* service to other children, each having an independent entry * service to other children, each having an independent entry
* point. * point.
*
* The 'ram_service', 'cpu_service', and 'rm_service' arguments are
* needed to direct quota upgrades referring to the resources of
* the child environment. By default, we expect that these
* resources are provided by the parent.
*/ */
Child(Dataspace_capability elf_ds, Child(Dataspace_capability elf_ds,
Ram_session_capability ram, Ram_session_capability ram,
Cpu_session_capability cpu, Cpu_session_capability cpu,
Rm_session_capability rm, Rm_session_capability rm,
Rpc_entrypoint *entrypoint, Rpc_entrypoint *entrypoint,
Child_policy *policy) Child_policy *policy,
Service &ram_service = *_parent_service(),
Service &cpu_service = *_parent_service(),
Service &rm_service = *_parent_service())
: :
_ram(ram), _ram_session_client(ram), _cpu(cpu), _rm(rm), _ram(ram), _ram_session_client(ram), _cpu(cpu), _rm(rm),
_ram_service(ram_service), _cpu_service(cpu_service),
_rm_service(rm_service),
_heap(&_ram_session_client, env()->rm_session()), _heap(&_ram_session_client, env()->rm_session()),
_entrypoint(entrypoint), _entrypoint(entrypoint),
_parent_cap(_entrypoint->manage(this)), _parent_cap(_entrypoint->manage(this)),
@ -493,10 +527,23 @@ namespace Genode {
void upgrade(Session_capability to_session, Upgrade_args const &args) void upgrade(Session_capability to_session, Upgrade_args const &args)
{ {
Session *s = _session_pool.obj_by_cap(to_session); Service *targeted_service = 0;
if (!s) { /* check of upgrade refers to an Env:: resource */
PWRN("no session structure found - nothing to be done\n"); if (to_session.local_name() == _ram.local_name())
targeted_service = &_ram_service;
if (to_session.local_name() == _cpu.local_name())
targeted_service = &_cpu_service;
if (to_session.local_name() == _rm.local_name())
targeted_service = &_rm_service;
/* check if upgrade refers to server */
Session * const session = _session_pool.obj_by_cap(to_session);
if (session)
targeted_service = session->service();
if (!targeted_service) {
PWRN("could not lookup service for session upgrade");
return; return;
} }
@ -505,7 +552,8 @@ namespace Genode {
return; return;
} }
size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0); size_t const ram_quota =
Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0);
/* transfer quota from client to ourself */ /* transfer quota from client to ourself */
Transfer donation_from_child(ram_quota, _ram, Transfer donation_from_child(ram_quota, _ram,
@ -513,13 +561,14 @@ namespace Genode {
/* transfer session quota from ourself to the service provider */ /* transfer session quota from ourself to the service provider */
Transfer donation_to_service(ram_quota, env()->ram_session_cap(), Transfer donation_to_service(ram_quota, env()->ram_session_cap(),
s->service()->ram_session_cap()); targeted_service->ram_session_cap());
try { s->service()->upgrade(to_session, args.string()); } try { targeted_service->upgrade(to_session, args.string()); }
catch (Service::Quota_exceeded) { throw Quota_exceeded(); } catch (Service::Quota_exceeded) { throw Quota_exceeded(); }
/* remember new amount attached to the session */ /* remember new amount attached to the session */
s->upgrade_ram_quota(ram_quota); if (session)
session->upgrade_ram_quota(ram_quota);
/* finish transaction */ /* finish transaction */
donation_from_child.acknowledge(); donation_from_child.acknowledge();