mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-01 03:26:45 +00:00
9cf677cb0a
In order to be able to dynamically balance resources of slaves, we need to provide an accessor to the slave's RAM session and a way to issue yield requests.
205 lines
5.4 KiB
C++
205 lines
5.4 KiB
C++
/*
|
|
* \brief Convenience helper for running a service as child process
|
|
* \author Norman Feske
|
|
* \author Christian Helmuth
|
|
* \date 2012-01-25
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__OS__SLAVE_H_
|
|
#define _INCLUDE__OS__SLAVE_H_
|
|
|
|
/* Genode includes */
|
|
#include <base/rpc_server.h>
|
|
#include <base/child.h>
|
|
#include <init/child_policy.h>
|
|
#include <ram_session/connection.h>
|
|
#include <cpu_session/connection.h>
|
|
#include <rm_session/connection.h>
|
|
#include <os/child_policy_dynamic_rom.h>
|
|
|
|
namespace Genode {
|
|
|
|
/**
|
|
* Slave-policy class
|
|
*
|
|
* This class provides a convenience policy for single-service slaves using a
|
|
* white list of parent services.
|
|
*/
|
|
class Slave_policy : public Genode::Child_policy
|
|
{
|
|
protected:
|
|
|
|
/**
|
|
* Return white list of services the slave is permitted to use
|
|
*
|
|
* The list is terminated via a NULL pointer.
|
|
*/
|
|
virtual char const **_permitted_services() const = 0;
|
|
|
|
private:
|
|
|
|
char const *_label;
|
|
Genode::Service_registry _parent_services;
|
|
Genode::Rpc_entrypoint &_entrypoint;
|
|
Genode::Rom_connection _binary_rom;
|
|
Init::Child_policy_enforce_labeling _labeling_policy;
|
|
Init::Child_policy_provide_rom_file _binary_policy;
|
|
Genode::Child_policy_dynamic_rom_file _config_policy;
|
|
|
|
bool _service_permitted(const char *service_name)
|
|
{
|
|
for (const char **s = _permitted_services(); *s; ++s)
|
|
if (!Genode::strcmp(service_name, *s))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public:
|
|
|
|
/**
|
|
* Slave-policy constructor
|
|
*
|
|
* \param label name of the program to start
|
|
* \param entrypoint entrypoint used to provide local services
|
|
* such as the config ROM service
|
|
* \param ram RAM session used for buffering config data
|
|
*
|
|
* If 'ram' is set to 0, no configuration can be supplied to the
|
|
* slave.
|
|
*/
|
|
Slave_policy(const char *label,
|
|
Genode::Rpc_entrypoint &entrypoint,
|
|
Genode::Ram_session *ram = 0)
|
|
:
|
|
_label(label),
|
|
_entrypoint(entrypoint),
|
|
_binary_rom(_label, _label),
|
|
_labeling_policy(_label),
|
|
_binary_policy("binary", _binary_rom.dataspace(), &_entrypoint),
|
|
_config_policy("config", _entrypoint, ram)
|
|
{ }
|
|
|
|
Genode::Dataspace_capability binary() { return _binary_rom.dataspace(); }
|
|
|
|
/**
|
|
* Assign new configuration to slave
|
|
*/
|
|
void configure(char const *config)
|
|
{
|
|
_config_policy.load(config, Genode::strlen(config) + 1);
|
|
}
|
|
|
|
|
|
/****************************
|
|
** Child_policy interface **
|
|
****************************/
|
|
|
|
const char *name() const { return _label; }
|
|
|
|
Genode::Service *resolve_session_request(const char *service_name,
|
|
const char *args)
|
|
{
|
|
Genode::Service *service = 0;
|
|
|
|
/* check for binary file request */
|
|
if ((service = _binary_policy.resolve_session_request(service_name, args)))
|
|
return service;
|
|
|
|
/* check for config file request */
|
|
if ((service = _config_policy.resolve_session_request(service_name, args)))
|
|
return service;
|
|
|
|
if (!_service_permitted(service_name)) {
|
|
PERR("%s: illegal session request of service \"%s\"",
|
|
name(), service_name);
|
|
return 0;
|
|
}
|
|
|
|
/* fill parent service registry on demand */
|
|
if (!(service = _parent_services.find(service_name))) {
|
|
service = new (Genode::env()->heap())
|
|
Genode::Parent_service(service_name);
|
|
_parent_services.insert(service);
|
|
}
|
|
|
|
/* return parent service */
|
|
return service;
|
|
}
|
|
|
|
void filter_session_args(const char *service,
|
|
char *args, Genode::size_t args_len)
|
|
{
|
|
_labeling_policy.filter_session_args(service, args, args_len);
|
|
}
|
|
};
|
|
|
|
|
|
class Slave
|
|
{
|
|
private:
|
|
|
|
struct Resources
|
|
{
|
|
Genode::Ram_connection ram;
|
|
Genode::Cpu_connection cpu;
|
|
Genode::Rm_connection rm;
|
|
|
|
class Quota_exceeded : public Genode::Exception { };
|
|
|
|
Resources(const char *label, Genode::size_t ram_quota)
|
|
: ram(label), cpu(label)
|
|
{
|
|
/*
|
|
* XXX derive donated quota from information to be provided by
|
|
* the used 'Connection' interfaces
|
|
*/
|
|
enum { DONATED_RAM_QUOTA = 128*1024 };
|
|
if (ram_quota > DONATED_RAM_QUOTA)
|
|
ram_quota -= DONATED_RAM_QUOTA;
|
|
else
|
|
throw Quota_exceeded();
|
|
ram.ref_account(Genode::env()->ram_session_cap());
|
|
Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota);
|
|
}
|
|
};
|
|
|
|
Resources _resources;
|
|
Genode::Child _child;
|
|
|
|
public:
|
|
|
|
Slave(Genode::Rpc_entrypoint &entrypoint,
|
|
Slave_policy &slave_policy,
|
|
Genode::size_t ram_quota)
|
|
:
|
|
_resources(slave_policy.name(), ram_quota),
|
|
_child(slave_policy.binary(),
|
|
_resources.ram.cap(), _resources.cpu.cap(),
|
|
_resources.rm.cap(), &entrypoint, &slave_policy)
|
|
{ }
|
|
|
|
Genode::Ram_connection &ram() { return _resources.ram; }
|
|
|
|
|
|
/***************************************
|
|
** Wrappers of the 'Child' interface **
|
|
***************************************/
|
|
|
|
void yield(Genode::Parent::Resource_args const &args) {
|
|
_child.yield(args); }
|
|
|
|
void notify_resource_avail() const {
|
|
_child.notify_resource_avail(); }
|
|
};
|
|
}
|
|
|
|
#endif /* _INCLUDE__OS__SLAVE_H_ */
|