os/slave.h: Remove use of global allocator

This patch eliminates the need for a global allocator by passing the
parent-service registry as argument to the 'Slave::Policy' constructor.

Fixes #2269
This commit is contained in:
Norman Feske 2017-02-01 14:04:53 +01:00
parent c0d61858c3
commit f8349b5bc7
9 changed files with 148 additions and 170 deletions

View File

@ -16,6 +16,7 @@
/* Genode includes */
#include <base/lock.h>
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <report_session/connection.h>
#include <rom_session/connection.h>
@ -25,7 +26,14 @@ class Report_rom_slave : public Genode::Noncopyable
{
private:
class Policy : public Genode::Slave::Policy
class Policy
:
private Genode::Static_parent_services<Genode::Rom_session,
Genode::Cpu_session,
Genode::Pd_session,
Genode::Ram_session,
Genode::Log_session>,
public Genode::Slave::Policy
{
private:
@ -35,14 +43,6 @@ class Report_rom_slave : public Genode::Noncopyable
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"ROM", "CPU", "PD", "RAM", "LOG", 0 };
return permitted_services;
};
static Name _name() { return "report_rom"; }
static Genode::size_t _quota() { return 1024*1024; }
@ -53,7 +53,7 @@ class Report_rom_slave : public Genode::Noncopyable
Genode::Ram_session_capability ram,
const char *config)
:
Genode::Slave::Policy(_name(), _name(), ep, rm, ram, _quota())
Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota())
{
if (config)
configure(config);

View File

@ -15,6 +15,7 @@
#define _MENU_VIEW_SLAVE_H_
/* Genode includes */
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <nitpicker_session/nitpicker_session.h>
@ -35,7 +36,15 @@ class Launcher::Menu_view_slave
private:
class Policy : public Genode::Slave::Policy
class Policy
:
private Genode::Static_parent_services<Genode::Cpu_session,
Genode::Pd_session,
Genode::Ram_session,
Genode::Rom_session,
Genode::Log_session,
Timer::Session>,
public Genode::Slave::Policy
{
private:
@ -45,16 +54,6 @@ class Launcher::Menu_view_slave
Position _position;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"CPU", "PD", "RAM", "ROM", "LOG", "Timer", 0 };
return permitted_services;
};
private:
void _configure(Position pos)
@ -87,7 +86,7 @@ class Launcher::Menu_view_slave
Capability<Report::Session> hover_report_session,
Position position)
:
Genode::Slave::Policy(_name(), _name(), ep, rm, ram, _quota()),
Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota()),
_nitpicker(nitpicker_session),
_dialog_rom(dialog_rom_session),
_hover_report(hover_report_session),

View File

@ -15,6 +15,7 @@
#define _NIT_FADER_SLAVE_H_
/* Genode includes */
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <nitpicker_session/nitpicker_session.h>
@ -28,7 +29,15 @@ class Launcher::Nit_fader_slave
{
private:
class Policy : public Slave::Policy
class Policy
:
private Genode::Static_parent_services<Genode::Ram_session,
Genode::Cpu_session,
Genode::Pd_session,
Genode::Rom_session,
Genode::Log_session,
Timer::Session>,
public Slave::Policy
{
private:
@ -36,14 +45,6 @@ class Launcher::Nit_fader_slave
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"RAM", "CPU", "PD", "ROM", "LOG", "Timer", 0 };
return permitted_services;
};
static Name _name() { return "nit_fader"; }
static size_t _quota() { return 2*1024*1024; }
@ -54,7 +55,7 @@ class Launcher::Nit_fader_slave
Ram_session_capability ram,
Genode::Service &nitpicker_service)
:
Genode::Slave::Policy(_name(), _name(), ep, rm, ram, _quota()),
Genode::Slave::Policy(_name(), _name(), *this, ep, rm, ram, _quota()),
_nitpicker_service(nitpicker_service)
{
visible(false);

View File

@ -23,6 +23,9 @@
/* Genode includes */
#include <input/component.h>
#include <timer_session/timer_session.h>
#include <audio_out_session/audio_out_session.h>
#include <os/static_parent_services.h>
#include <os/slave.h>
/* local includes */
@ -36,7 +39,16 @@ class Avplay_slave : public QObject
private:
class Policy : public Genode::Slave::Policy
class Policy
:
private Genode::Static_parent_services<Genode::Cpu_session,
Genode::Log_session,
Genode::Pd_session,
Genode::Ram_session,
Genode::Rom_session,
Timer::Session,
Audio_out::Session>,
public Genode::Slave::Policy
{
private:
@ -94,16 +106,6 @@ class Avplay_slave : public QObject
static Genode::size_t _quota() { return 32*1024*1024; }
static Name _name() { return "avplay"; }
protected:
const char **_permitted_services() const override
{
static const char *permitted_services[] = {
"CPU", "LOG", "PD", "RAM", "RM", "ROM", "Timer", "Audio_out", 0 };
return permitted_services;
};
public:
Policy(Genode::Rpc_entrypoint &entrypoint,
@ -112,12 +114,13 @@ class Avplay_slave : public QObject
Input_service &input_service,
Framebuffer_service_factory &framebuffer_service_factory,
char const *mediafile)
: Genode::Slave::Policy(_name(), _name(), entrypoint, rm, ram,
_quota()),
_input_service(input_service),
_framebuffer_service_factory(framebuffer_service_factory),
_mediafile(mediafile),
_sdl_audio_volume(100)
:
Genode::Slave::Policy(_name(), _name(), *this, entrypoint,
rm, ram, _quota()),
_input_service(input_service),
_framebuffer_service_factory(framebuffer_service_factory),
_mediafile(mediafile),
_sdl_audio_volume(100)
{
configure(_config());
}

View File

@ -16,7 +16,9 @@
/* Genode includes */
#include <base/service.h>
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <timer_session/timer_session.h>
/* local includes */
#include "framebuffer_service_factory.h"
@ -26,22 +28,20 @@ class Filter_framebuffer_slave
{
private:
class Policy : public Genode::Slave::Policy
class Policy
:
private Genode::Static_parent_services<Genode::Cpu_session,
Genode::Log_session,
Genode::Pd_session,
Genode::Ram_session,
Genode::Rom_session,
Timer::Session>,
public Genode::Slave::Policy
{
private:
Framebuffer_service_factory &_framebuffer_service_factory;
protected:
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CPU", "LOG", "PD", "RAM", "RM", "ROM", "Timer", 0 };
return permitted_services;
};
public:
Policy(Genode::Rpc_entrypoint &entrypoint,
@ -50,11 +50,13 @@ class Filter_framebuffer_slave
Name const &name,
size_t quota,
Framebuffer_service_factory &framebuffer_service_factory)
: Genode::Slave::Policy(name, name, entrypoint, rm, ram, quota),
_framebuffer_service_factory(framebuffer_service_factory) { }
:
Genode::Slave::Policy(name, name, *this, entrypoint, rm, ram, quota),
_framebuffer_service_factory(framebuffer_service_factory)
{ }
Genode::Service &resolve_session_request(Genode::Service::Name const &service_name,
Genode::Session_state::Args const &args) override
Genode::Session_state::Args const &args) override
{
if (service_name == "Framebuffer")
return _framebuffer_service_factory.create(args);

View File

@ -47,18 +47,9 @@ class Genode::Slave::Policy : public Child_policy
typedef Child_policy::Name Name;
typedef Session_label Label;
protected:
typedef Registered<Genode::Parent_service> Parent_service;
typedef Registry<Parent_service> Parent_services;
/**
* 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:
Label const _label;
@ -66,20 +57,10 @@ class Genode::Slave::Policy : public Child_policy
Ram_session_client _ram;
Genode::Parent_service _binary_service;
size_t _ram_quota;
Parent_services _parent_services;
Parent_services &_parent_services;
Rpc_entrypoint &_ep;
Child_policy_dynamic_rom_file _config_policy;
bool _service_permitted(Service::Name const &service_name) const
{
for (const char **s = _permitted_services(); *s; ++s)
if (service_name == *s)
return true;
return false;
}
Session_requester _session_requester;
Session_requester _session_requester;
public:
@ -98,6 +79,7 @@ class Genode::Slave::Policy : public Child_policy
*/
Policy(Label const &label,
Name const &binary_name,
Parent_services &parent_services,
Rpc_entrypoint &ep,
Region_map &rm,
Ram_session_capability ram_cap,
@ -105,7 +87,7 @@ class Genode::Slave::Policy : public Child_policy
:
_label(label), _binary_name(binary_name), _ram(ram_cap),
_binary_service(Rom_session::service_name()),
_ram_quota(ram_quota), _ep(ep),
_ram_quota(ram_quota), _parent_services(parent_services), _ep(ep),
_config_policy("config", _ep, &_ram),
_session_requester(ep, _ram, rm)
{
@ -163,21 +145,17 @@ class Genode::Slave::Policy : public Child_policy
if (rom_name == "session_requests") return _session_requester.service();
}
if (!_service_permitted(service_name)) {
error(name(), ": illegal session request of "
"service \"", service_name, "\" (", args, ")");
throw Parent::Service_denied();
}
/* fill parent service registry on demand */
Parent_service *service = nullptr;
_parent_services.for_each([&] (Parent_service &s) {
if (!service && s.name() == service_name)
service = &s; });
if (!service)
service = new (env()->heap())
Parent_service(_parent_services, service_name);
if (!service) {
error(name(), ": illegal session request of "
"service \"", service_name, "\" (", args, ")");
throw Parent::Service_denied();
}
return *service;
}

View File

@ -13,23 +13,22 @@
#pragma once
#include <os/static_parent_services.h>
#include <os/slave.h>
enum { STACK_SIZE = 4 * sizeof(void *) * 1024 };
namespace Platform { class Device_pd_policy; }
class Platform::Device_pd_policy : public Genode::Slave::Policy
class Platform::Device_pd_policy
:
private Genode::Static_parent_services<Genode::Ram_session,
Genode::Pd_session,
Genode::Cpu_session,
Genode::Log_session,
Genode::Rom_session>,
public Genode::Slave::Policy
{
protected:
char const **_permitted_services() const override
{
static char const *permitted_services[] = {
"RAM", "PD", "CPU", "LOG", "ROM", 0 };
return permitted_services;
};
public:
Device_pd_policy(Genode::Rpc_entrypoint &slave_ep,
@ -38,9 +37,8 @@ class Platform::Device_pd_policy : public Genode::Slave::Policy
Genode::size_t ram_quota,
Genode::Session_label const &label)
:
Genode::Slave::Policy(label, "device_pd", slave_ep, local_rm,
Genode::Slave::Policy(label, "device_pd", *this, slave_ep, local_rm,
ram_ref_cap, ram_quota)
{ }
};

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <base/component.h>
#include <os/static_parent_services.h>
#include <os/slave.h>
#include <timer_session/connection.h>
@ -26,20 +27,16 @@ namespace Test {
}
struct Test::Policy : Genode::Slave::Policy
struct Test::Policy
:
private Static_parent_services<Cpu_session, Ram_session, Rom_session,
Pd_session, Log_session>,
public Slave::Policy
{
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CPU", "RAM", "ROM", "PD", "LOG", 0 };
return permitted_services;
};
Policy(Genode::Env &env, Name const &name)
Policy(Env &env, Name const &name)
:
Genode::Slave::Policy(name, name, env.ep().rpc_ep(), env.rm(),
env.ram_session_cap(), 1024*1024)
Slave::Policy(name, name, *this, env.ep().rpc_ep(), env.rm(),
env.ram_session_cap(), 1024*1024)
{ }
};

View File

@ -32,8 +32,15 @@
#include <base/log.h>
#include <base/signal.h>
#include <timer_session/connection.h>
#include <os/static_parent_services.h>
#include <os/slave.h>
namespace Test {
class Child;
class Parent;
using namespace Genode;
}
/****************
** Child role **
@ -43,21 +50,19 @@
* The child eats more and more RAM. However, when receiving a yield request,
* it releases the requested amount of resources.
*/
class Child
class Test::Child
{
private:
typedef Genode::size_t size_t;
struct Ram_chunk : Genode::List<Ram_chunk>::Element
struct Ram_chunk : List<Ram_chunk>::Element
{
Genode::Env &env;
Env &env;
size_t const size;
Genode::Ram_dataspace_capability ds_cap;
Ram_dataspace_capability ds_cap;
Ram_chunk(Genode::Env &env, size_t size)
Ram_chunk(Env &env, size_t size)
:
env(env),size(size), ds_cap(env.ram().alloc(size))
{ }
@ -65,14 +70,14 @@ class Child
~Ram_chunk() { env.ram().free(ds_cap); }
};
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
bool const _expand;
Genode::List<Ram_chunk> _ram_chunks;
Timer::Connection _timer { _env };
Genode::Signal_handler<Child> _periodic_timeout_handler;
Genode::Signal_handler<Child> _yield_handler;
unsigned long const _period_ms;
Env &_env;
Heap _heap { _env.ram(), _env.rm() };
bool const _expand;
List<Ram_chunk> _ram_chunks;
Timer::Connection _timer { _env };
Signal_handler<Child> _periodic_timeout_handler;
Signal_handler<Child> _yield_handler;
unsigned long const _period_ms;
void _handle_periodic_timeout();
void _handle_yield();
@ -84,19 +89,19 @@ class Child
public:
Child(Genode::Env &, Genode::Xml_node);
Child(Env &, Xml_node);
void main();
};
void Child::_handle_periodic_timeout()
void Test::Child::_handle_periodic_timeout()
{
size_t const chunk_size = 1024*1024;
if (_env.ram().avail() < chunk_size) {
if (_expand) {
Genode::log("quota consumed, request additional resources");
log("quota consumed, request additional resources");
/*
* The attempt to allocate RAM will result in a resource request to
@ -105,7 +110,7 @@ void Child::_handle_periodic_timeout()
*/
} else {
Genode::log("consumed all of our quota, stop allocating");
log("consumed all of our quota, stop allocating");
return;
}
}
@ -113,18 +118,16 @@ void Child::_handle_periodic_timeout()
/* perform allocation and remember chunk in list */
_ram_chunks.insert(new (_heap) Ram_chunk(_env, chunk_size));
Genode::log("allocated chunk of ", chunk_size / 1024, " KiB");
log("allocated chunk of ", chunk_size / 1024, " KiB");
_schedule_next_timeout();
}
void Child::_handle_yield()
void Test::Child::_handle_yield()
{
using namespace Genode;
/* request yield request arguments */
Parent::Resource_args const args = _env.parent().yield_request();
Genode::Parent::Resource_args const args = _env.parent().yield_request();
log("yield request: ", args.string());
@ -156,7 +159,7 @@ void Child::_handle_yield()
}
Child::Child(Genode::Env &env, Genode::Xml_node config)
Test::Child::Child(Env &env, Xml_node config)
:
_env(env),
_expand(config.attribute_value("expand", false)),
@ -182,22 +185,20 @@ Child::Child(Genode::Env &env, Genode::Xml_node config)
* The parent grants resource requests as long as it has free resources.
* Once in a while, it politely requests the child to yield resources.
*/
class Parent
class Test::Parent
{
private:
Genode::Env &_env;
typedef Genode::size_t size_t;
Env &_env;
Timer::Connection _timer { _env };
Genode::Lock _yield_blockade;
Lock _yield_blockade;
void _print_status()
{
Genode::log("quota: ", _child.ram().quota() / 1024, " KiB "
"used: ", _child.ram().used() / 1024, " KiB");
log("quota: ", _child.ram().quota() / 1024, " KiB "
"used: ", _child.ram().used() / 1024, " KiB");
}
size_t _used_ram_prior_yield = 0;
@ -214,7 +215,7 @@ class Parent
void _schedule_one_second_timeout()
{
Genode::log("wait ", _wait_cnt, "/", _wait_secs);
log("wait ", _wait_cnt, "/", _wait_secs);
_timer.trigger_once(1000*1000);
}
@ -230,7 +231,7 @@ class Parent
/* remember quantum of resources used by the child */
_used_ram_prior_yield = _child.ram().used();
Genode::log("request yield (ram prior yield: ", _used_ram_prior_yield);
log("request yield (ram prior yield: ", _used_ram_prior_yield);
/* issue yield request */
Genode::Parent::Resource_args yield_args("ram_quota=5M");
@ -252,7 +253,7 @@ class Parent
void _yield_response()
{
Genode::log("got yield response");
log("got yield response");
_state = YIELD_GOT_RESPONSE;
_print_status();
@ -260,43 +261,42 @@ class Parent
/* validate that the amount of yielded resources matches the request */
size_t const used_after_yield = _child.ram().used();
if (used_after_yield + 5*1024*1024 > _used_ram_prior_yield) {
Genode::error("child has not yielded enough resources");
error("child has not yielded enough resources");
throw Insufficient_yield();
}
if (_cnt-- > 0) {
_init();
} else {
Genode::log("--- test-resource_yield finished ---");
log("--- test-resource_yield finished ---");
_env.parent().exit(0);
}
}
Genode::Signal_handler<Parent> _timeout_handler {
Signal_handler<Parent> _timeout_handler {
_env.ep(), *this, &Parent::_handle_timeout };
struct Policy : Genode::Slave::Policy
struct Policy
:
private Static_parent_services<Ram_session, Pd_session,
Cpu_session, Rom_session,
Log_session, Timer::Session>,
public Slave::Policy
{
Parent &_parent;
enum { SLAVE_QUOTA = 10*1024*1024 };
char const **_permitted_services() const override
{
static char const *services[] = { "RAM", "PD", "CPU", "ROM", "LOG", "Timer" };
return services;
}
void yield_response() override
{
_parent._yield_response();
}
Policy(Parent &parent, Genode::Env &env)
Policy(Parent &parent, Env &env)
:
Genode::Slave::Policy(Label("child"), "test-resource_yield",
env.ep().rpc_ep(), env.rm(),
env.ram_session_cap(), SLAVE_QUOTA),
Slave::Policy(Label("child"), "test-resource_yield",
*this, env.ep().rpc_ep(), env.rm(),
env.ram_session_cap(), SLAVE_QUOTA),
_parent(parent)
{
configure("<config child=\"yes\" />");
@ -314,7 +314,7 @@ class Parent
/**
* Constructor
*/
Parent(Genode::Env &env) : _env(env)
Parent(Env &env) : _env(env)
{
_timer.sigh(_timeout_handler);
_init();
@ -339,9 +339,9 @@ void Component::construct(Genode::Env &env)
if (is_child) {
log("--- test-resource_yield child role started ---");
static ::Child child(env, config.xml());
static Test::Child child(env, config.xml());
} else {
log("--- test-resource_yield parent role started ---");
static ::Parent parent(env);
static Test::Parent parent(env);
}
}