genode/repos/ports/src/noux/child_policy.h

219 lines
7.1 KiB
C
Raw Normal View History

/*
* \brief Noux child policy
* \author Norman Feske
* \date 2012-02-25
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NOUX__CHILD_POLICY_H_
#define _NOUX__CHILD_POLICY_H_
/* Genode includes */
#include <init/child_policy.h>
/* Noux includes */
#include <family_member.h>
#include <parent_exit.h>
#include <file_descriptor_registry.h>
#include <empty_rom_service.h>
#include <local_rom_service.h>
namespace Noux {
typedef Registered<Genode::Parent_service> Parent_service;
typedef Registry<Parent_service> Parent_services;
typedef Local_service<Pd_session_component> Pd_service;
typedef Local_service<Cpu_session_component> Cpu_service;
typedef Local_service<Rpc_object<Session> > Noux_service;
class Child_policy;
}
class Noux::Child_policy : public Genode::Child_policy
{
private:
2019-01-18 16:18:19 +01:00
/**
* Noncopyable
*/
Child_policy(Child_policy const &);
Child_policy &operator = (Child_policy const &);
Name const _name;
bool _forked;
Init::Child_policy_provide_rom_file _args_policy;
Init::Child_policy_provide_rom_file _env_policy;
Init::Child_policy_provide_rom_file _config_policy;
Pd_service &_pd_service;
Cpu_service &_cpu_service;
Noux_service &_noux_service;
Empty_rom_service &_empty_rom_service;
Local_rom_service &_rom_service;
Parent_services &_parent_services;
Family_member &_family_member;
Parent_exit *_parent_exit;
File_descriptor_registry &_file_descriptor_registry;
Signal_context_capability _destruct_context_cap;
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Pd_session &_ref_pd;
Pd_session_capability _ref_pd_cap;
int _exit_value;
bool _verbose;
template <typename T>
static Genode::Service *_find_service(Genode::Registry<T> &services,
Genode::Service::Name const &name)
{
Genode::Service *service = nullptr;
services.for_each([&] (T &s) {
if (!service && (s.name() == name))
service = &s; });
return service;
}
/**
* Find suitable service for a given session request
*
* \throw Service_denied
*/
Service &_matching_service(Service::Name const &service_name,
Session_label const &label)
{
/*
* Route initial ROM requests (binary and linker) of a forked child
* to the empty ROM service, since the ROMs are already attached in
* the replayed region map.
*/
if (_forked && (service_name == Genode::Rom_session::service_name())) {
if (label.last_element() == name()) return _empty_rom_service;
if (label.last_element() == linker_name()) return _empty_rom_service;
}
Genode::Service *service = nullptr;
/* check for local ROM requests */
if ((service = _args_policy .resolve_session_request_with_label(service_name, label))
|| (service = _env_policy .resolve_session_request_with_label(service_name, label))
|| (service = _config_policy.resolve_session_request_with_label(service_name, label)))
return *service;
/* check for local services */
if (service_name == Genode::Cpu_session::service_name()) return _cpu_service;
if (service_name == Genode::Rom_session::service_name()) return _rom_service;
if (service_name == Genode::Pd_session::service_name()) return _pd_service;
if (service_name == Noux::Session::service_name()) return _noux_service;
/* check for parent services */
if ((service = _find_service(_parent_services, service_name)))
return *service;
throw Service_denied();
}
public:
Child_policy(Name const &name,
bool forked,
Dataspace_capability args_ds,
Dataspace_capability env_ds,
Dataspace_capability config_ds,
Rpc_entrypoint &entrypoint,
Pd_service &pd_service,
Cpu_service &cpu_service,
Noux_service &noux_service,
Empty_rom_service &empty_rom_service,
Local_rom_service &rom_service,
Parent_services &parent_services,
Family_member &family_member,
Parent_exit *parent_exit,
File_descriptor_registry &file_descriptor_registry,
Signal_context_capability destruct_context_cap,
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Pd_session &ref_pd,
Pd_session_capability ref_pd_cap,
bool verbose)
:
_name(name), _forked(forked),
_args_policy( "args", args_ds, &entrypoint),
_env_policy( "env", env_ds, &entrypoint),
_config_policy("config", config_ds, &entrypoint),
_pd_service(pd_service),
_cpu_service(cpu_service),
_noux_service(noux_service),
_empty_rom_service(empty_rom_service),
_rom_service(rom_service),
_parent_services(parent_services),
_family_member(family_member),
_parent_exit(parent_exit),
_file_descriptor_registry(file_descriptor_registry),
_destruct_context_cap(destruct_context_cap),
_ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap),
_exit_value(~0),
_verbose(verbose)
{ }
int exit_value() const { return _exit_value; }
/****************************
** Child policy interface **
****************************/
Name name() const override { return _name; }
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Pd_session &ref_pd() override { return _ref_pd; }
Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
2019-01-18 16:18:19 +01:00
void init(Pd_session &session, Pd_session_capability) override
{
session.ref_account(_ref_pd_cap);
}
Route resolve_session_request(Service::Name const &service_name,
Session_label const &label) override
{
return Route { .service = _matching_service(service_name, label),
.label = label,
.diag = Session::Diag() };
}
void exit(int exit_value) override
{
_exit_value = exit_value;
if (_verbose || (exit_value != 0))
log("child ", _name, " exited with exit value ", exit_value);
/*
* Close all open file descriptors. This is necessary to unblock
* the parent if it is trying to read from a pipe (connected to
* the child) before calling 'wait4()'.
*/
_file_descriptor_registry.flush();
_family_member.exit(exit_value);
/* notify the parent */
if (_parent_exit)
_parent_exit->exit_child();
else {
/* handle exit of the init process */
Signal_transmitter(_destruct_context_cap).submit();
}
}
Region_map *address_space(Pd_session &pd) override
{
return &static_cast<Pd_session_component &>(pd).address_space_region_map();
}
bool forked() const override { return _forked; }
};
#endif /* _NOUX__CHILD_POLICY_H_ */