2012-02-25 20:41:59 +01:00
|
|
|
/*
|
|
|
|
* \brief Noux child policy
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2012-02-25
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
2012-02-25 20:41:59 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2012-02-25 20:41:59 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _NOUX__CHILD_POLICY_H_
|
|
|
|
#define _NOUX__CHILD_POLICY_H_
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <init/child_policy.h>
|
|
|
|
|
|
|
|
/* Noux includes */
|
|
|
|
#include <family_member.h>
|
2014-01-23 17:21:35 +01:00
|
|
|
#include <parent_exit.h>
|
2012-09-14 16:46:51 +02:00
|
|
|
#include <file_descriptor_registry.h>
|
2017-01-31 18:03:11 +01:00
|
|
|
#include <empty_rom_service.h>
|
2013-07-18 16:27:42 +02:00
|
|
|
#include <local_rom_service.h>
|
2012-02-25 20:41:59 +01:00
|
|
|
|
|
|
|
namespace Noux {
|
|
|
|
|
2016-11-23 17:07:49 +01:00
|
|
|
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;
|
|
|
|
|
2017-01-06 12:12:39 +01:00
|
|
|
class Child_policy;
|
|
|
|
}
|
2016-11-23 17:07:49 +01:00
|
|
|
|
2012-02-25 20:41:59 +01:00
|
|
|
|
2017-01-06 12:12:39 +01:00
|
|
|
class Noux::Child_policy : public Genode::Child_policy
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Name const _name;
|
2017-01-31 18:03:11 +01:00
|
|
|
bool _forked;
|
2017-01-06 12:12:39 +01:00
|
|
|
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;
|
2017-01-31 18:03:11 +01:00
|
|
|
Empty_rom_service &_empty_rom_service;
|
2017-01-06 12:12:39 +01:00
|
|
|
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;
|
2017-01-06 12:12:39 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Child_policy(Name const &name,
|
2017-01-31 18:03:11 +01:00
|
|
|
bool forked,
|
2017-01-06 12:12:39 +01:00
|
|
|
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,
|
2017-01-31 18:03:11 +01:00
|
|
|
Empty_rom_service &empty_rom_service,
|
2017-01-06 12:12:39 +01:00
|
|
|
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,
|
2017-01-06 12:12:39 +01:00
|
|
|
bool verbose)
|
|
|
|
:
|
2017-01-31 18:03:11 +01:00
|
|
|
_name(name), _forked(forked),
|
2017-01-06 12:12:39 +01:00
|
|
|
_args_policy( "args", args_ds, &entrypoint),
|
|
|
|
_env_policy( "env", env_ds, &entrypoint),
|
|
|
|
_config_policy("config", config_ds, &entrypoint),
|
2017-05-11 20:03:28 +02:00
|
|
|
_pd_service(pd_service),
|
|
|
|
_cpu_service(cpu_service),
|
|
|
|
_noux_service(noux_service),
|
2017-01-31 18:03:11 +01:00
|
|
|
_empty_rom_service(empty_rom_service),
|
2017-05-11 20:03:28 +02:00
|
|
|
_rom_service(rom_service),
|
|
|
|
_parent_services(parent_services),
|
2017-01-06 12:12:39 +01:00
|
|
|
_family_member(family_member),
|
|
|
|
_parent_exit(parent_exit),
|
|
|
|
_file_descriptor_registry(file_descriptor_registry),
|
|
|
|
_destruct_context_cap(destruct_context_cap),
|
2017-05-11 20:03:28 +02:00
|
|
|
_ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap),
|
2017-01-06 12:12:39 +01:00
|
|
|
_exit_value(~0),
|
|
|
|
_verbose(verbose)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
int exit_value() const { return _exit_value; }
|
|
|
|
|
|
|
|
/****************************
|
|
|
|
** Child policy interface **
|
|
|
|
****************************/
|
|
|
|
|
2017-01-31 18:03:11 +01:00
|
|
|
Name name() const override { return _name; }
|
2017-01-06 12:12:39 +01:00
|
|
|
|
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; }
|
2017-01-06 12:12:39 +01:00
|
|
|
|
2017-05-11 20:03:28 +02:00
|
|
|
void init(Pd_session &session, Pd_session_capability cap) override
|
2017-01-06 12:12:39 +01:00
|
|
|
{
|
2017-05-11 20:03:28 +02:00
|
|
|
session.ref_account(_ref_pd_cap);
|
2017-01-06 12:12:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Service &resolve_session_request(Service::Name const &service_name,
|
|
|
|
Session_state::Args const &args) override
|
|
|
|
{
|
|
|
|
Session_label const label(Genode::label_from_args(args.string()));
|
|
|
|
|
2017-01-31 18:03:11 +01:00
|
|
|
/*
|
|
|
|
* 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;
|
2012-02-25 20:41:59 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 12:12:39 +01:00
|
|
|
Genode::Service *service = nullptr;
|
|
|
|
|
|
|
|
/* check for local ROM requests */
|
|
|
|
if ((service = _args_policy .resolve_session_request(service_name.string(), args.string()))
|
|
|
|
|| (service = _env_policy .resolve_session_request(service_name.string(), args.string()))
|
|
|
|
|| (service = _config_policy.resolve_session_request(service_name.string(), args.string())))
|
|
|
|
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;
|
|
|
|
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Service_denied();
|
2017-01-06 12:12:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2012-02-25 20:41:59 +01:00
|
|
|
}
|
2017-01-06 12:12:39 +01:00
|
|
|
}
|
2012-02-25 20:41:59 +01:00
|
|
|
|
2017-01-06 12:12:39 +01:00
|
|
|
Region_map *address_space(Pd_session &pd) override
|
|
|
|
{
|
|
|
|
return &static_cast<Pd_session_component &>(pd).address_space_region_map();
|
|
|
|
}
|
|
|
|
};
|
2012-02-25 20:41:59 +01:00
|
|
|
|
|
|
|
#endif /* _NOUX__CHILD_POLICY_H_ */
|