mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-19 07:38:28 +00:00
Adapt low-level components to new parent interface
This patch adjusts the components of the os repository as well as device drivers to the new parent interface. Issue #2120
This commit is contained in:
committed by
Christian Helmuth
parent
cfdbccc5c2
commit
8bafb9d41b
@ -3,3 +3,10 @@ subsystems via a session interface. The resources for the new subsystem are
|
||||
provided by the client when opening the session. The client has no control over
|
||||
the functioning of the subsystem except for the controlling the lifetime of the
|
||||
subsystem.
|
||||
|
||||
By default, the loaded subsystem can access only those ROM modules that were
|
||||
loaded into the loader session by the loader client. However, it is possible
|
||||
to define a whitelist of ROM modules to be obtained from the loader's parent.
|
||||
For an example, refer to the example 'run/loader.run' script.
|
||||
|
||||
|
||||
|
@ -29,150 +29,100 @@ namespace Loader {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
typedef Registered<Parent_service> Parent_service;
|
||||
typedef Registry<Parent_service> Parent_services;
|
||||
|
||||
class Child : public Child_policy
|
||||
{
|
||||
private:
|
||||
|
||||
typedef String<Session::Name::MAX_SIZE> Label;
|
||||
Env &_env;
|
||||
|
||||
Label _label;
|
||||
Session_label const _label;
|
||||
Name const _binary_name;
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
size_t const _ram_quota;
|
||||
|
||||
struct Resources
|
||||
{
|
||||
Pd_connection pd;
|
||||
Ram_connection ram;
|
||||
Cpu_connection cpu;
|
||||
Parent_services &_parent_services;
|
||||
|
||||
Resources(char const *label,
|
||||
Ram_session_client &ram_session_client,
|
||||
size_t ram_quota,
|
||||
Signal_context_capability fault_sigh)
|
||||
: pd(label), ram(label), cpu(label)
|
||||
{
|
||||
/* deduce session costs from usable ram quota */
|
||||
size_t session_donations = Cpu_connection::RAM_QUOTA +
|
||||
Ram_connection::RAM_QUOTA;
|
||||
|
||||
if (ram_quota > session_donations)
|
||||
ram_quota -= session_donations;
|
||||
else ram_quota = 0;
|
||||
|
||||
ram.ref_account(ram_session_client);
|
||||
ram_session_client.transfer_quota(ram.cap(), ram_quota);
|
||||
|
||||
/*
|
||||
* Install CPU exception and RM fault handler assigned by
|
||||
* the loader client via 'Loader_session::fault_handler'.
|
||||
*/
|
||||
cpu.exception_sigh(fault_sigh);
|
||||
Region_map_client address_space(pd.address_space());
|
||||
address_space.fault_handler(fault_sigh);
|
||||
}
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread { _resources.cpu,
|
||||
_resources.pd,
|
||||
_label.string() };
|
||||
|
||||
Region_map_client _address_space { _resources.pd.address_space() };
|
||||
|
||||
Service_registry &_parent_services;
|
||||
Service &_local_nitpicker_service;
|
||||
Service &_local_rom_service;
|
||||
Service &_local_cpu_service;
|
||||
Service &_local_pd_service;
|
||||
|
||||
Rom_session_client _binary_rom_session;
|
||||
|
||||
Init::Child_policy_provide_rom_file _binary_policy;
|
||||
Init::Child_policy_enforce_labeling _labeling_policy;
|
||||
|
||||
Genode::Child _child;
|
||||
|
||||
Rom_session_capability _rom_session(char const *name)
|
||||
{
|
||||
try {
|
||||
char args[Session::Name::MAX_SIZE];
|
||||
snprintf(args, sizeof(args), "ram_quota=4K, label=\"%s\"", name);
|
||||
return static_cap_cast<Rom_session>(_local_rom_service.session(args, Affinity()));
|
||||
} catch (Genode::Parent::Service_denied) {
|
||||
Genode::error("Lookup for ROM module \"", name, "\" failed");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Child(char const *binary_name,
|
||||
char const *label,
|
||||
Dataspace_capability ldso_ds,
|
||||
Rpc_entrypoint &ep,
|
||||
Ram_session_client &ram_session_client,
|
||||
Child(Env &env,
|
||||
Name const &binary_name,
|
||||
Session_label const &label,
|
||||
size_t ram_quota,
|
||||
Service_registry &parent_services,
|
||||
Parent_services &parent_services,
|
||||
Service &local_rom_service,
|
||||
Service &local_cpu_service,
|
||||
Service &local_pd_service,
|
||||
Service &local_nitpicker_service,
|
||||
Signal_context_capability fault_sigh)
|
||||
:
|
||||
_env(env),
|
||||
_label(label),
|
||||
_ep(ep),
|
||||
_resources(_label.string(), ram_session_client, ram_quota, fault_sigh),
|
||||
_binary_name(binary_name),
|
||||
_ram_quota(Genode::Child::effective_ram_quota(ram_quota)),
|
||||
_parent_services(parent_services),
|
||||
_local_nitpicker_service(local_nitpicker_service),
|
||||
_local_rom_service(local_rom_service),
|
||||
_local_cpu_service(local_cpu_service),
|
||||
_local_pd_service(local_pd_service),
|
||||
_binary_rom_session(_rom_session(binary_name)),
|
||||
_binary_policy("binary", _binary_rom_session.dataspace(), &_ep),
|
||||
_labeling_policy(_label.string()),
|
||||
_child(_binary_rom_session.dataspace(), ldso_ds,
|
||||
_resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram,
|
||||
_resources.cpu, _initial_thread,
|
||||
*env()->rm_session(), _address_space, _ep, *this)
|
||||
_child(_env.rm(), _env.ep().rpc_ep(), *this)
|
||||
{ }
|
||||
|
||||
~Child()
|
||||
{
|
||||
_local_rom_service.close(_binary_rom_session);
|
||||
}
|
||||
~Child() { }
|
||||
|
||||
|
||||
/****************************
|
||||
** Child-policy interface **
|
||||
****************************/
|
||||
|
||||
char const *name() const override { return _label.string(); }
|
||||
Name name() const override { return _label; }
|
||||
|
||||
void filter_session_args(char const *service, char *args, size_t args_len) override
|
||||
Binary_name binary_name() const override { return _binary_name; }
|
||||
|
||||
Ram_session &ref_ram() override { return _env.ram(); }
|
||||
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
|
||||
|
||||
void init(Ram_session &ram, Ram_session_capability ram_cap) override
|
||||
{
|
||||
_labeling_policy.filter_session_args(service, args, args_len);
|
||||
ram.ref_account(ref_ram_cap());
|
||||
ref_ram().transfer_quota(ram_cap, _ram_quota);
|
||||
}
|
||||
|
||||
Service *resolve_session_request(const char *name,
|
||||
const char *args) override
|
||||
void filter_session_args(Service::Name const &service, char *args, size_t args_len) override
|
||||
{
|
||||
Service *service = 0;
|
||||
_labeling_policy.filter_session_args(service.string(), args, args_len);
|
||||
}
|
||||
|
||||
if ((service = _binary_policy.resolve_session_request(name, args)))
|
||||
return service;
|
||||
|
||||
if (!strcmp(name, "Nitpicker")) return &_local_nitpicker_service;
|
||||
if (!strcmp(name, "ROM")) return &_local_rom_service;
|
||||
if (!strcmp(name, "CPU")) return &_local_cpu_service;
|
||||
if (!strcmp(name, "PD")) return &_local_pd_service;
|
||||
Service &resolve_session_request(Service::Name const &name,
|
||||
Session_state::Args const &args) override
|
||||
{
|
||||
if (name == "Nitpicker") return _local_nitpicker_service;
|
||||
if (name == "ROM") return _local_rom_service;
|
||||
if (name == "CPU") return _local_cpu_service;
|
||||
if (name == "PD") return _local_pd_service;
|
||||
|
||||
/* populate session-local parent service registry on demand */
|
||||
service = _parent_services.find(name);
|
||||
if (!service) {
|
||||
service = new (env()->heap()) Parent_service(name);
|
||||
_parent_services.insert(service);
|
||||
}
|
||||
return service;
|
||||
Service *service = nullptr;
|
||||
_parent_services.for_each([&] (Parent_service &s) {
|
||||
if (s.name() == name)
|
||||
service = &s; });
|
||||
|
||||
if (service)
|
||||
return *service;
|
||||
|
||||
return *new (env()->heap()) Parent_service(_parent_services, name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -12,14 +12,13 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/signal.h>
|
||||
#include <base/sleep.h>
|
||||
#include <loader_session/loader_session.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <root/component.h>
|
||||
#include <os/session_policy.h>
|
||||
|
||||
/* local includes */
|
||||
#include <child.h>
|
||||
@ -41,104 +40,79 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Local_rom_service : Service
|
||||
struct Local_rom_factory : Local_service<Rom_session_component>::Factory
|
||||
{
|
||||
Rpc_entrypoint &_ep;
|
||||
Entrypoint &_ep;
|
||||
Allocator &_md_alloc;
|
||||
Parent_service _parent_rom_service;
|
||||
Rom_module_registry &_rom_modules;
|
||||
Lock _lock;
|
||||
List<Rom_session_component> _rom_sessions;
|
||||
|
||||
void _close(Rom_session_component *rom)
|
||||
void _close(Rom_session_component &rom)
|
||||
{
|
||||
_rom_sessions.remove(rom);
|
||||
destroy(&_md_alloc, rom);
|
||||
_rom_sessions.remove(&rom);
|
||||
Genode::destroy(_md_alloc, &rom);
|
||||
}
|
||||
|
||||
Local_rom_service(Rpc_entrypoint &ep,
|
||||
Local_rom_factory(Entrypoint &ep,
|
||||
Allocator &md_alloc,
|
||||
Rom_module_registry &rom_modules)
|
||||
:
|
||||
Service("virtual_rom"),
|
||||
_ep(ep),
|
||||
_md_alloc(md_alloc),
|
||||
_parent_rom_service(Rom_session::service_name()),
|
||||
_rom_modules(rom_modules)
|
||||
_ep(ep), _md_alloc(md_alloc), _rom_modules(rom_modules)
|
||||
{ }
|
||||
|
||||
~Local_rom_service()
|
||||
~Local_rom_factory()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
while (_rom_sessions.first()) {
|
||||
_ep.remove(_rom_sessions.first());
|
||||
_close(_rom_sessions.first());
|
||||
}
|
||||
while (_rom_sessions.first())
|
||||
_close(*_rom_sessions.first());
|
||||
}
|
||||
|
||||
Genode::Session_capability session(char const *args,
|
||||
Affinity const &affinity)
|
||||
Rom_session_component &create(Args const &args, Affinity affinity) override
|
||||
{
|
||||
/* try to find ROM module at local ROM service */
|
||||
try {
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Session_label const label = label_from_args(args);
|
||||
Session_label name = label.last_element();
|
||||
Session_label const label = label_from_args(args.string());
|
||||
Session_label const name = label.last_element();
|
||||
|
||||
Rom_module &module = _rom_modules.lookup_and_lock(name.string());
|
||||
|
||||
Rom_session_component *rom = new (&_md_alloc)
|
||||
Rom_session_component(module);
|
||||
Rom_session_component *rom = new (_md_alloc)
|
||||
Rom_session_component(_ep, module);
|
||||
|
||||
_rom_sessions.insert(rom);
|
||||
|
||||
return _ep.manage(rom);
|
||||
return *rom;
|
||||
|
||||
} catch (...) { }
|
||||
|
||||
/* fall back to parent_rom_service */
|
||||
return _parent_rom_service.session(args, affinity);
|
||||
throw Denied();
|
||||
}
|
||||
|
||||
void close(Session_capability session)
|
||||
void upgrade(Rom_session_component &, Args const &) override { }
|
||||
|
||||
void destroy(Rom_session_component &session) override
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Rom_session_component *component;
|
||||
|
||||
_ep.apply(session, [&] (Rom_session_component *rsc) {
|
||||
component = rsc;
|
||||
if (component) _ep.remove(component);
|
||||
});
|
||||
|
||||
if (component) {
|
||||
_close(component);
|
||||
return;
|
||||
}
|
||||
|
||||
_parent_rom_service.close(session);
|
||||
_close(session);
|
||||
}
|
||||
|
||||
void upgrade(Session_capability session, const char *) { }
|
||||
};
|
||||
|
||||
typedef Local_service<Rom_session_component> Local_rom_service;
|
||||
|
||||
/**
|
||||
* Common base class of 'Local_cpu_service' and 'Local_pd_service'
|
||||
*/
|
||||
struct Intercepted_parent_service : Service
|
||||
struct Intercepted_parent_service : Genode::Parent_service
|
||||
{
|
||||
Signal_context_capability fault_sigh;
|
||||
|
||||
Intercepted_parent_service(char const *name) : Service(name) { }
|
||||
|
||||
void close(Session_capability session)
|
||||
{
|
||||
env()->parent()->close(session);
|
||||
}
|
||||
|
||||
void upgrade(Session_capability session, const char *) { }
|
||||
Intercepted_parent_service(Env &env, Service::Name const &name)
|
||||
: Parent_service(env, name) { }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -147,20 +121,17 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
*/
|
||||
struct Local_cpu_service : Intercepted_parent_service
|
||||
{
|
||||
Local_cpu_service() : Intercepted_parent_service("CPU") { }
|
||||
Local_cpu_service(Env &env) : Intercepted_parent_service(env, "CPU") { }
|
||||
|
||||
Genode::Session_capability session(char const *args,
|
||||
Affinity const &affinity)
|
||||
void initiate_request(Session_state &session) override
|
||||
{
|
||||
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args, affinity);
|
||||
Cpu_session_client(cap).exception_sigh(fault_sigh);
|
||||
return cap;
|
||||
}
|
||||
Intercepted_parent_service::initiate_request(session);
|
||||
|
||||
void upgrade(Session_capability session, const char *args)
|
||||
{
|
||||
try { env()->parent()->upgrade(session, args); }
|
||||
catch (Genode::Ipc_error) { throw Unavailable(); }
|
||||
if (session.phase != Session_state::AVAILABLE)
|
||||
return;
|
||||
|
||||
Cpu_session_client cpu(reinterpret_cap_cast<Cpu_session>(session.cap));
|
||||
cpu.exception_sigh(fault_sigh);
|
||||
}
|
||||
};
|
||||
|
||||
@ -169,109 +140,100 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
*/
|
||||
struct Local_pd_service : Intercepted_parent_service
|
||||
{
|
||||
Local_pd_service() : Intercepted_parent_service("PD") { }
|
||||
Local_pd_service(Env &env) : Intercepted_parent_service(env, "PD") { }
|
||||
|
||||
Genode::Session_capability session(char const *args,
|
||||
Affinity const &affinity)
|
||||
void initiate_request(Session_state &session) override
|
||||
{
|
||||
Pd_session_client pd(env()->parent()->session<Pd_session>(args, affinity));
|
||||
Intercepted_parent_service::initiate_request(session);
|
||||
|
||||
if (session.phase != Session_state::AVAILABLE)
|
||||
return;
|
||||
|
||||
Pd_session_client pd(reinterpret_cap_cast<Pd_session>(session.cap));
|
||||
|
||||
Region_map_client(pd.address_space()).fault_handler(fault_sigh);
|
||||
Region_map_client(pd.stack_area()) .fault_handler(fault_sigh);
|
||||
Region_map_client(pd.linker_area()) .fault_handler(fault_sigh);
|
||||
|
||||
return pd;
|
||||
}
|
||||
};
|
||||
|
||||
struct Local_nitpicker_service : Service
|
||||
struct Local_nitpicker_factory : Local_service<Nitpicker::Session_component>::Factory
|
||||
{
|
||||
Rpc_entrypoint &_ep;
|
||||
Ram_session &_ram;
|
||||
Allocator &_md_alloc;
|
||||
Entrypoint &_ep;
|
||||
Ram_session &_ram;
|
||||
|
||||
Area _max_size;
|
||||
Nitpicker::View_capability _parent_view;
|
||||
|
||||
Signal_context_capability view_ready_sigh;
|
||||
|
||||
Nitpicker::Session_component *open_session;
|
||||
Lazy_volatile_object<Nitpicker::Session_component> session;
|
||||
|
||||
Local_nitpicker_service(Rpc_entrypoint &ep, Ram_session &ram,
|
||||
Allocator &md_alloc)
|
||||
:
|
||||
Service("virtual_nitpicker"),
|
||||
_ep(ep),
|
||||
_ram(ram),
|
||||
_md_alloc(md_alloc),
|
||||
open_session(0)
|
||||
{ }
|
||||
Local_nitpicker_factory(Entrypoint &ep, Ram_session &ram)
|
||||
: _ep(ep), _ram(ram) { }
|
||||
|
||||
~Local_nitpicker_service()
|
||||
{
|
||||
if (!open_session)
|
||||
return;
|
||||
|
||||
_ep.dissolve(open_session);
|
||||
destroy(&_md_alloc, open_session);
|
||||
}
|
||||
|
||||
void constrain_geometry(Area size)
|
||||
{
|
||||
_max_size = size;
|
||||
}
|
||||
void constrain_geometry(Area size) { _max_size = size; }
|
||||
|
||||
void parent_view(Nitpicker::View_capability view)
|
||||
{
|
||||
_parent_view = view;
|
||||
}
|
||||
|
||||
Genode::Session_capability session(char const *args,
|
||||
Affinity const &)
|
||||
Nitpicker::Session_component &create(Args const &args, Affinity) override
|
||||
{
|
||||
if (open_session)
|
||||
throw Unavailable();
|
||||
if (session.constructed()) {
|
||||
warning("attempt to open more than one nitpicker session");
|
||||
throw Parent::Service_denied();
|
||||
}
|
||||
|
||||
open_session = new (&_md_alloc)
|
||||
Nitpicker::Session_component(_ep,
|
||||
_ram,
|
||||
_max_size,
|
||||
_parent_view,
|
||||
view_ready_sigh,
|
||||
args);
|
||||
|
||||
return _ep.manage(open_session);
|
||||
session.construct(_ep, _ram, _max_size,
|
||||
_parent_view, view_ready_sigh, args.string());
|
||||
return *session;
|
||||
}
|
||||
|
||||
void upgrade(Genode::Session_capability session, const char *) { }
|
||||
void upgrade(Nitpicker::Session_component &, Args const &) override { }
|
||||
void destroy(Nitpicker::Session_component &) override { }
|
||||
};
|
||||
|
||||
typedef Local_service<Nitpicker::Session_component> Local_nitpicker_service;
|
||||
|
||||
enum { STACK_SIZE = 2*4096 };
|
||||
|
||||
size_t _ram_quota;
|
||||
Ram_session_client_guard _ram_session_client;
|
||||
Heap _md_alloc;
|
||||
size_t _subsystem_ram_quota_limit;
|
||||
Rpc_entrypoint _ep;
|
||||
Dataspace_capability _ldso_ds;
|
||||
Service_registry _parent_services;
|
||||
Rom_module_registry _rom_modules;
|
||||
Local_rom_service _rom_service;
|
||||
Local_cpu_service _cpu_service;
|
||||
Local_pd_service _pd_service;
|
||||
Local_nitpicker_service _nitpicker_service;
|
||||
Signal_context_capability _fault_sigh;
|
||||
Child *_child;
|
||||
Env &_env;
|
||||
Session_label const _label;
|
||||
Xml_node const _config;
|
||||
size_t const _ram_quota;
|
||||
Ram_session_client_guard _local_ram { _env.ram_session_cap(), _ram_quota };
|
||||
Heap _md_alloc { _local_ram, _env.rm() };
|
||||
size_t _subsystem_ram_quota_limit = 0;
|
||||
Parent_services _parent_services;
|
||||
Rom_module_registry _rom_modules { _env, _config, _local_ram, _md_alloc };
|
||||
Local_rom_factory _rom_factory { _env.ep(), _md_alloc, _rom_modules };
|
||||
Local_rom_service _rom_service { _rom_factory };
|
||||
Local_cpu_service _cpu_service { _env };
|
||||
Local_pd_service _pd_service { _env };
|
||||
Local_nitpicker_factory _nitpicker_factory { _env.ep(), _local_ram };
|
||||
Local_nitpicker_service _nitpicker_service { _nitpicker_factory };
|
||||
Signal_context_capability _fault_sigh;
|
||||
Lazy_volatile_object<Child> _child;
|
||||
|
||||
/**
|
||||
* Return virtual nitpicker session component
|
||||
*/
|
||||
Nitpicker::Session_component &_virtual_nitpicker_session() const
|
||||
Nitpicker::Session_component &_virtual_nitpicker_session()
|
||||
{
|
||||
if (!_nitpicker_service.open_session)
|
||||
if (!_nitpicker_factory.session.constructed())
|
||||
throw View_does_not_exist();
|
||||
|
||||
return *_nitpicker_service.open_session;
|
||||
return *_nitpicker_factory.session;
|
||||
}
|
||||
|
||||
Nitpicker::Session_component const &_virtual_nitpicker_session() const
|
||||
{
|
||||
if (!_nitpicker_factory.session.constructed())
|
||||
throw View_does_not_exist();
|
||||
|
||||
return *_nitpicker_factory.session;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -279,34 +241,30 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(size_t quota, Ram_session &ram, Cap_session &cap,
|
||||
Dataspace_capability ldso_ds)
|
||||
Session_component(Env &env, Session_label const &label,
|
||||
Xml_node config, size_t quota)
|
||||
:
|
||||
_ram_quota(quota),
|
||||
_ram_session_client(env()->ram_session_cap(), _ram_quota),
|
||||
_md_alloc(&_ram_session_client, env()->rm_session()),
|
||||
_subsystem_ram_quota_limit(0),
|
||||
_ep(&cap, STACK_SIZE, "session_ep"),
|
||||
_ldso_ds(ldso_ds),
|
||||
_rom_modules(_ram_session_client, _md_alloc),
|
||||
_rom_service(_ep, _md_alloc, _rom_modules),
|
||||
_nitpicker_service(_ep, _ram_session_client, _md_alloc),
|
||||
_child(0)
|
||||
{ }
|
||||
_env(env), _label(label), _config(config), _ram_quota(quota)
|
||||
{
|
||||
/* fetch all parent-provided ROMs according to the config */
|
||||
config.for_each_sub_node("parent-rom", [&] (Xml_node rom)
|
||||
{
|
||||
typedef Rom_module::Name Name;
|
||||
Name name = rom.attribute_value("name", Name());
|
||||
_rom_modules.fetch_parent_rom_module(name);
|
||||
});
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
if (_child)
|
||||
destroy(&_md_alloc, _child);
|
||||
_child.destruct();
|
||||
|
||||
/*
|
||||
* The parent-service registry is populated by the 'Child'
|
||||
* on demand. Revert those allocations.
|
||||
*/
|
||||
while (Service *service = _parent_services.find_by_server(0)) {
|
||||
_parent_services.remove(service);
|
||||
destroy(env()->heap(), service);
|
||||
}
|
||||
_parent_services.for_each([&] (Parent_service &service) {
|
||||
destroy(env()->heap(), &service); });
|
||||
}
|
||||
|
||||
|
||||
@ -334,17 +292,17 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
|
||||
void constrain_geometry(Area size) override
|
||||
{
|
||||
_nitpicker_service.constrain_geometry(size);
|
||||
_nitpicker_factory.constrain_geometry(size);
|
||||
}
|
||||
|
||||
void parent_view(Nitpicker::View_capability view) override
|
||||
{
|
||||
_nitpicker_service.parent_view(view);
|
||||
_nitpicker_factory.parent_view(view);
|
||||
}
|
||||
|
||||
void view_ready_sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
_nitpicker_service.view_ready_sigh = sigh;
|
||||
_nitpicker_factory.view_ready_sigh = sigh;
|
||||
}
|
||||
|
||||
void fault_sigh(Signal_context_capability sigh) override
|
||||
@ -369,22 +327,21 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
|
||||
void start(Name const &binary_name, Name const &label) override
|
||||
{
|
||||
if (_child) {
|
||||
PWRN("cannot start subsystem twice");
|
||||
if (_child.constructed()) {
|
||||
warning("cannot start subsystem twice");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t const ram_quota = (_subsystem_ram_quota_limit > 0) ?
|
||||
min(_subsystem_ram_quota_limit, _ram_session_client.avail()) :
|
||||
_ram_session_client.avail();
|
||||
size_t const ram_quota = (_subsystem_ram_quota_limit > 0)
|
||||
? min(_subsystem_ram_quota_limit, _ram_quota)
|
||||
: _ram_quota;
|
||||
|
||||
try {
|
||||
_child = new (&_md_alloc)
|
||||
Child(binary_name.string(), label.string(), _ldso_ds,
|
||||
_ep, _ram_session_client,
|
||||
ram_quota, _parent_services, _rom_service,
|
||||
_cpu_service, _pd_service, _nitpicker_service,
|
||||
_fault_sigh);
|
||||
_child.construct(_env, binary_name.string(),
|
||||
prefixed_label(_label, Session_label(label.string())),
|
||||
ram_quota, _parent_services, _rom_service,
|
||||
_cpu_service, _pd_service, _nitpicker_service,
|
||||
_fault_sigh);
|
||||
}
|
||||
catch (Genode::Parent::Service_denied) {
|
||||
throw Rom_module_does_not_exist(); }
|
||||
@ -406,61 +363,53 @@ class Loader::Root : public Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Ram_session &_ram;
|
||||
Cap_session &_cap;
|
||||
Dataspace_capability _ldso_ds;
|
||||
Env &_env;
|
||||
Xml_node const _config;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
size_t quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
size_t quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
|
||||
return new (md_alloc()) Session_component(quota, _ram, _cap, _ldso_ds);
|
||||
Xml_node session_config("<policy/>");
|
||||
|
||||
Session_label const label = label_from_args(args);
|
||||
|
||||
try { session_config = Session_policy(label, _config); }
|
||||
catch (...) { }
|
||||
|
||||
return new (md_alloc()) Session_component(_env, label, session_config, quota);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session_ep entry point for managing ram session objects
|
||||
* \param md_alloc meta-data allocator to be used by root
|
||||
* component
|
||||
*/
|
||||
Root(Rpc_entrypoint &session_ep, Allocator &md_alloc,
|
||||
Ram_session &ram, Cap_session &cap, Dataspace_capability ldso_ds)
|
||||
Root(Env &env, Xml_node config, Allocator &md_alloc)
|
||||
:
|
||||
Root_component<Session_component>(&session_ep, &md_alloc),
|
||||
_ram(ram), _cap(cap), _ldso_ds(ldso_ds)
|
||||
Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
||||
_env(env), _config(config)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
Genode::Dataspace_capability request_ldso_ds()
|
||||
namespace Loader { struct Main; }
|
||||
|
||||
|
||||
struct Loader::Main
|
||||
{
|
||||
try {
|
||||
static Genode::Rom_connection rom("ld.lib.so");
|
||||
return rom.dataspace();
|
||||
} catch (...) { }
|
||||
return Genode::Dataspace_capability();
|
||||
}
|
||||
Env &env;
|
||||
|
||||
Heap heap { env.ram(), env.rm() };
|
||||
|
||||
Attached_rom_dataspace config { env, "config" };
|
||||
|
||||
Root root { env, config.xml(), heap };
|
||||
|
||||
Main(Env &env) : env(env)
|
||||
{
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = 8*1024 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "loader_ep");
|
||||
|
||||
static Loader::Root root(ep, *env()->heap(), *env()->ram_session(), cap,
|
||||
request_ldso_ds());
|
||||
|
||||
env()->parent()->announce(ep.manage(&root));
|
||||
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
||||
void Component::construct(Genode::Env &env) { static Loader::Main main(env); }
|
||||
|
@ -39,7 +39,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>
|
||||
*/
|
||||
Genode::Signal_context_capability _view_ready_sigh;
|
||||
|
||||
Genode::Rpc_entrypoint &_ep;
|
||||
Genode::Entrypoint &_ep;
|
||||
|
||||
Area _max_size;
|
||||
|
||||
@ -148,7 +148,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Genode::Rpc_entrypoint &ep,
|
||||
Session_component(Genode::Entrypoint &ep,
|
||||
Genode::Ram_session &ram,
|
||||
Area max_size,
|
||||
Nitpicker::View_capability parent_view,
|
||||
@ -166,10 +166,18 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>
|
||||
_view_handle(_nitpicker.create_view(_parent_view_handle)),
|
||||
|
||||
_proxy_input(_nitpicker.input_session(), _motion_delta),
|
||||
_proxy_input_cap(_ep.manage(&_proxy_input)),
|
||||
_proxy_input_cap(_ep.manage(_proxy_input)),
|
||||
|
||||
_command_ds(&ram, sizeof(Command_buffer))
|
||||
{ }
|
||||
{
|
||||
_ep.manage(*this);
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
_ep.dissolve(_proxy_input);
|
||||
_ep.dissolve(*this);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
|
@ -11,20 +11,26 @@
|
||||
#include <rom_session/rom_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <os/attached_ram_dataspace.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Rom_module : public List<Rom_module>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef String<128> Name;
|
||||
|
||||
private:
|
||||
|
||||
enum { MAX_NAME_LEN = 64 };
|
||||
char _name[MAX_NAME_LEN];
|
||||
Name const _name;
|
||||
|
||||
Ram_session &_ram;
|
||||
Attached_ram_dataspace _fg;
|
||||
Attached_ram_dataspace _bg;
|
||||
|
||||
Lazy_volatile_object<Attached_rom_dataspace> _parent_rom;
|
||||
|
||||
bool _bg_has_pending_data;
|
||||
|
||||
Signal_context_capability _sigh;
|
||||
@ -33,20 +39,28 @@ namespace Genode {
|
||||
|
||||
public:
|
||||
|
||||
Rom_module(char const *name, Ram_session &ram_session)
|
||||
enum Origin { PARENT_PROVIDED, SESSION_LOCAL };
|
||||
|
||||
Rom_module(Env &env, Xml_node config, Name const &name,
|
||||
Ram_session &ram_session, Origin origin)
|
||||
:
|
||||
_ram(ram_session),
|
||||
_name(name), _ram(ram_session),
|
||||
_fg(&_ram, 0), _bg(&_ram, 0),
|
||||
_bg_has_pending_data(false),
|
||||
_lock(Lock::LOCKED)
|
||||
{
|
||||
strncpy(_name, name, sizeof(_name));
|
||||
if (origin == SESSION_LOCAL)
|
||||
return;
|
||||
|
||||
try {
|
||||
_parent_rom.construct(env, name.string()); }
|
||||
catch (...) {
|
||||
warning("ROM ", name, " unavailable from parent, "
|
||||
"try to use session-local ROM");
|
||||
}
|
||||
}
|
||||
|
||||
bool has_name(char const *name) const
|
||||
{
|
||||
return strcmp(_name, name) == 0;
|
||||
}
|
||||
bool has_name(Name const &name) const { return _name == name; }
|
||||
|
||||
void lock() { _lock.lock(); }
|
||||
void unlock() { _lock.unlock(); }
|
||||
@ -72,6 +86,9 @@ namespace Genode {
|
||||
*/
|
||||
Rom_dataspace_capability fg_dataspace()
|
||||
{
|
||||
if (_parent_rom.constructed())
|
||||
return static_cap_cast<Rom_dataspace>(_parent_rom->cap());
|
||||
|
||||
if (!_fg.size() && !_bg_has_pending_data) {
|
||||
Genode::error("no data loaded");
|
||||
return Rom_dataspace_capability();
|
||||
@ -95,7 +112,13 @@ namespace Genode {
|
||||
*
|
||||
* This function is indirectly called by the ROM session client.
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh) { _sigh = sigh; }
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
if (_parent_rom.constructed())
|
||||
_parent_rom->sigh(sigh);
|
||||
|
||||
_sigh = sigh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit data contained in background dataspace
|
||||
@ -126,6 +149,8 @@ namespace Genode {
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Xml_node const _config;
|
||||
Lock _lock;
|
||||
Ram_session &_ram_session;
|
||||
Allocator &_md_alloc;
|
||||
@ -145,9 +170,11 @@ namespace Genode {
|
||||
* module data
|
||||
* \param md_alloc backing store for ROM module meta data
|
||||
*/
|
||||
Rom_module_registry(Ram_session &ram_session, Allocator &md_alloc)
|
||||
Rom_module_registry(Env &env, Xml_node config, Ram_session &ram_session,
|
||||
Allocator &md_alloc)
|
||||
:
|
||||
_ram_session(ram_session), _md_alloc(md_alloc)
|
||||
_env(env), _config(config), _ram_session(ram_session),
|
||||
_md_alloc(md_alloc)
|
||||
{ }
|
||||
|
||||
~Rom_module_registry()
|
||||
@ -167,7 +194,7 @@ namespace Genode {
|
||||
*
|
||||
* \throw Lookup_failed
|
||||
*/
|
||||
Rom_module &lookup_and_lock(char const *name)
|
||||
Rom_module &lookup_and_lock(Rom_module::Name const &name)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
@ -181,7 +208,7 @@ namespace Genode {
|
||||
throw Lookup_failed();
|
||||
}
|
||||
|
||||
Dataspace_capability alloc_rom_module(char const *name, size_t size)
|
||||
Dataspace_capability alloc_rom_module(Rom_module::Name const &name, size_t size)
|
||||
{
|
||||
try {
|
||||
Rom_module &module = lookup_and_lock(name);
|
||||
@ -193,7 +220,8 @@ namespace Genode {
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Rom_module *module = new (&_md_alloc)
|
||||
Rom_module(name, _ram_session);
|
||||
Rom_module(_env, _config, name, _ram_session,
|
||||
Rom_module::SESSION_LOCAL);
|
||||
|
||||
Rom_module_lock_guard module_guard(*module);
|
||||
|
||||
@ -203,6 +231,25 @@ namespace Genode {
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_parent_rom_module(Rom_module::Name const &name)
|
||||
{
|
||||
try {
|
||||
lookup_and_lock(name);
|
||||
}
|
||||
catch (Lookup_failed) {
|
||||
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Rom_module *module = new (&_md_alloc)
|
||||
Rom_module(_env, _config, name, _ram_session,
|
||||
Rom_module::PARENT_PROVIDED);
|
||||
|
||||
Rom_module_lock_guard module_guard(*module);
|
||||
|
||||
_list.insert(module);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \throw Lookup_failed
|
||||
*/
|
||||
@ -220,12 +267,15 @@ namespace Genode {
|
||||
{
|
||||
private:
|
||||
|
||||
Entrypoint &_ep;
|
||||
Rom_module &_rom_module;
|
||||
|
||||
public:
|
||||
|
||||
Rom_session_component(Rom_module &rom_module)
|
||||
: _rom_module(rom_module) { }
|
||||
Rom_session_component(Entrypoint &ep, Rom_module &rom_module)
|
||||
: _ep(ep), _rom_module(rom_module) { _ep.manage(*this); }
|
||||
|
||||
~Rom_session_component() { _ep.dissolve(*this); }
|
||||
|
||||
Rom_dataspace_capability dataspace()
|
||||
{
|
||||
|
@ -691,7 +691,7 @@ class Audio_out::Root : public Audio_out::Root_component
|
||||
void _destroy_session(Session_component *session)
|
||||
{
|
||||
if (--_sessions == 0) _mixer.stop();
|
||||
destroy(md_alloc(), session);
|
||||
Genode::destroy(md_alloc(), session);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1072,7 +1072,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
|
||||
session->destroy_all_views();
|
||||
_mode.forget(*session);
|
||||
|
||||
destroy(md_alloc(), session);
|
||||
Genode::destroy(md_alloc(), session);
|
||||
}
|
||||
|
||||
public:
|
||||
|
Reference in New Issue
Block a user