2012-10-09 13:45:33 +02:00
|
|
|
/*
|
|
|
|
* \brief Child creation framework
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2006-07-22
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2006-2017 Genode Labs GmbH
|
2012-10-09 13:45:33 +02: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-10-09 13:45:33 +02:00
|
|
|
*/
|
|
|
|
|
2018-01-12 14:10:47 +01:00
|
|
|
/* Genode includes */
|
2012-10-09 13:45:33 +02:00
|
|
|
#include <base/child.h>
|
2017-05-08 16:49:00 +02:00
|
|
|
#include <base/quota_transfer.h>
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2018-01-12 14:10:47 +01:00
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/child_policy.h>
|
|
|
|
|
2012-10-09 13:45:33 +02:00
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/***********
|
|
|
|
** Child **
|
|
|
|
***********/
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
template <typename SESSION>
|
|
|
|
static Service &parent_service()
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
static Parent_service service(SESSION::service_name());
|
|
|
|
return service;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::yield(Resource_args const &args)
|
|
|
|
{
|
|
|
|
Lock::Guard guard(_yield_request_lock);
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* buffer yield request arguments to be picked up by the child */
|
|
|
|
_yield_request_args = args;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* notify the child about the yield request */
|
|
|
|
if (_yield_sigh.valid())
|
|
|
|
Signal_transmitter(_yield_sigh).submit();
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::notify_resource_avail() const
|
|
|
|
{
|
|
|
|
if (_resource_avail_sigh.valid())
|
|
|
|
Signal_transmitter(_resource_avail_sigh).submit();
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::announce(Parent::Service_name const &name)
|
|
|
|
{
|
|
|
|
if (!name.valid_string()) return;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
_policy.announce_service(name.string());
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::session_sigh(Signal_context_capability sigh)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
_session_sigh = sigh;
|
|
|
|
|
|
|
|
if (!_session_sigh.valid())
|
|
|
|
return;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
/*
|
2016-11-06 14:26:34 +01:00
|
|
|
* Deliver pending session response if a session became available before
|
|
|
|
* the signal handler got installed. This can happen for the very first
|
|
|
|
* asynchronously created session of a component. In 'component.cc', the
|
|
|
|
* signal handler is registered as response of the session request that
|
|
|
|
* needs asynchronous handling.
|
2012-10-09 13:45:33 +02:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
_id_space.for_each<Session_state const>([&] (Session_state const &session) {
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
if (session.phase == Session_state::AVAILABLE ||
|
2017-05-08 14:32:03 +02:00
|
|
|
session.phase == Session_state::INSUFFICIENT_RAM_QUOTA ||
|
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
|
|
|
session.phase == Session_state::INSUFFICIENT_CAP_QUOTA ||
|
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
|
|
|
session.phase == Session_state::SERVICE_DENIED) {
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
if (sigh.valid() && session.async_client_notify)
|
|
|
|
Signal_transmitter(sigh).submit();
|
|
|
|
}
|
|
|
|
});
|
2016-11-06 14:26:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create session-state object for a dynamically created session
|
|
|
|
*
|
2017-05-08 19:55:54 +02:00
|
|
|
* \throw Out_of_ram
|
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 Out_of_caps
|
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
|
|
|
* \throw Insufficient_cap_quota
|
2017-05-08 14:32:03 +02:00
|
|
|
* \throw Insufficient_ram_quota
|
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
|
2016-11-06 14:26:34 +01:00
|
|
|
*/
|
|
|
|
Session_state &
|
|
|
|
create_session(Child_policy::Name const &child_name, Service &service,
|
2017-02-14 17:38:09 +01:00
|
|
|
Session_label const &label,
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_state::Factory &factory, Id_space<Parent::Client> &id_space,
|
|
|
|
Parent::Client::Id id, Session_state::Args const &args,
|
|
|
|
Affinity const &affinity)
|
|
|
|
{
|
2012-10-09 13:45:33 +02:00
|
|
|
try {
|
2017-05-08 14:32:03 +02:00
|
|
|
return service.create_session(factory, id_space, id, label, args, affinity); }
|
|
|
|
|
|
|
|
catch (Insufficient_ram_quota) {
|
|
|
|
error(child_name, " requested session with insufficient RAM quota");
|
|
|
|
throw; }
|
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
|
|
|
|
|
|
|
catch (Insufficient_cap_quota) {
|
|
|
|
error(child_name, " requested session with insufficient cap quota");
|
|
|
|
throw; }
|
|
|
|
|
2012-10-09 13:45:33 +02:00
|
|
|
catch (Allocator::Out_of_memory) {
|
2017-05-08 14:32:03 +02:00
|
|
|
error(child_name, " session meta data could not be allocated");
|
|
|
|
throw Out_of_ram(); }
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
catch (Id_space<Parent::Client>::Conflicting_id) {
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
error(child_name, " requested conflicting session ID ", id, " "
|
|
|
|
"(service=", service.name(), " args=", args, ")");
|
|
|
|
|
|
|
|
id_space.apply<Session_state>(id, [&] (Session_state &session) {
|
|
|
|
error("existing session: ", session); });
|
|
|
|
}
|
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();
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-14 17:38:09 +01:00
|
|
|
/*
|
|
|
|
* \deprecated Temporary wrapper around 'Child_policy::resolve_session_request'
|
|
|
|
* that tries both overloads.
|
|
|
|
*
|
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-02-14 17:38:09 +01:00
|
|
|
*/
|
|
|
|
Child_policy::Route Child::_resolve_session_request(Child_policy &policy,
|
|
|
|
Service::Name const &name,
|
|
|
|
char const *argbuf)
|
|
|
|
{
|
|
|
|
Session_label const label = label_from_args(argbuf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \deprecated Try old interface, remove once all 'Child_policy'
|
|
|
|
* implementations are updated.
|
|
|
|
*/
|
|
|
|
try {
|
|
|
|
|
|
|
|
Session_state::Args args(argbuf);
|
2017-05-08 19:45:47 +02:00
|
|
|
return { policy.resolve_session_request(name, args), label,
|
|
|
|
session_diag_from_args(argbuf) };
|
2017-02-14 17:38:09 +01:00
|
|
|
}
|
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
|
|
|
catch (Service_denied) { }
|
2017-02-14 17:38:09 +01:00
|
|
|
|
|
|
|
return policy.resolve_session_request(name, label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_capability Child::session(Parent::Client::Id id,
|
|
|
|
Parent::Service_name const &name,
|
|
|
|
Parent::Session_args const &args,
|
|
|
|
Affinity const &affinity)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
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
|
|
|
if (!name.valid_string() || !args.valid_string())
|
|
|
|
throw Service_denied();
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
char argbuf[Parent::Session_args::MAX_SIZE];
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
strncpy(argbuf, args.string(), sizeof(argbuf));
|
2016-11-24 15:28:32 +01:00
|
|
|
|
|
|
|
/* prefix session label */
|
|
|
|
Session_label const orig_label(label_from_args(argbuf));
|
|
|
|
Arg_string::set_arg_string(argbuf, sizeof(argbuf), "label",
|
|
|
|
prefixed_label(_policy.name(), orig_label).string());
|
|
|
|
|
|
|
|
/* filter session arguments according to the child policy */
|
2016-11-06 14:26:34 +01:00
|
|
|
_policy.filter_session_args(name.string(), argbuf, sizeof(argbuf));
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* filter session affinity */
|
|
|
|
Affinity const filtered_affinity = _policy.filter_session_affinity(affinity);
|
2012-10-09 13:45:33 +02: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
|
|
|
Cap_quota const cap_quota = cap_quota_from_args(argbuf);
|
2017-05-08 01:33:40 +02:00
|
|
|
Ram_quota const ram_quota = ram_quota_from_args(argbuf);
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
/* portion of quota to keep for ourself to maintain the session meta data */
|
|
|
|
size_t const keep_ram_quota = _session_factory.session_costs();
|
|
|
|
|
2017-05-08 01:33:40 +02:00
|
|
|
if (ram_quota.value < keep_ram_quota)
|
2017-05-08 14:32:03 +02:00
|
|
|
throw Insufficient_ram_quota();
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
/* ram quota to be forwarded to the server */
|
2017-05-08 01:33:40 +02:00
|
|
|
Ram_quota const forward_ram_quota { ram_quota.value - keep_ram_quota };
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
/* adjust the session information as presented to the server */
|
2017-05-08 01:33:40 +02:00
|
|
|
Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", forward_ram_quota.value);
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
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
|
|
|
/* may throw a 'Service_denied' exception */
|
2017-02-14 17:38:09 +01:00
|
|
|
Child_policy::Route route = _resolve_session_request(_policy, name.string(), argbuf);
|
|
|
|
Service &service = route.service;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2017-05-08 19:45:47 +02:00
|
|
|
/* propagate diag flag */
|
|
|
|
Arg_string::set_arg(argbuf, sizeof(argbuf), "diag", route.diag.enabled);
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_state &session =
|
2017-05-08 01:33:40 +02:00
|
|
|
create_session(_policy.name(), service, route.label,
|
|
|
|
_session_factory, _id_space, id, argbuf, filtered_affinity);
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
session.ready_callback = this;
|
|
|
|
session.closed_callback = this;
|
|
|
|
|
|
|
|
try {
|
2017-05-11 20:03:28 +02:00
|
|
|
Ram_transfer::Remote_account ref_ram_account { _policy.ref_pd(), _policy.ref_pd_cap() };
|
|
|
|
Cap_transfer::Remote_account ref_cap_account { _policy.ref_pd(), _policy.ref_pd_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
|
|
|
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer::Remote_account ram_account { ram(), ram_session_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
|
|
|
Cap_transfer::Remote_account cap_account { pd(), pd_session_cap() };
|
2017-05-08 16:49:00 +02:00
|
|
|
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
/* transfer the quota donation from the child's account to ourself */
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account);
|
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
|
|
|
Cap_transfer cap_donation_from_child(cap_quota, cap_account, ref_cap_account);
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
/* transfer session quota from ourself to the service provider */
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer ram_donation_to_service(forward_ram_quota, ref_ram_account, service);
|
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
|
|
|
Cap_transfer cap_donation_to_service(cap_quota, ref_cap_account, service);
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
/* finish transaction */
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_from_child.acknowledge();
|
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
|
|
|
cap_donation_from_child.acknowledge();
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_to_service.acknowledge();
|
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
|
|
|
cap_donation_to_service.acknowledge();
|
2016-11-06 14:26:34 +01:00
|
|
|
}
|
2017-05-08 16:49:00 +02:00
|
|
|
/*
|
|
|
|
* Release session meta data if one of the quota transfers went wrong.
|
|
|
|
*/
|
|
|
|
catch (Ram_transfer::Quota_exceeded) {
|
2016-11-06 14:26:34 +01:00
|
|
|
session.destroy();
|
2017-05-08 14:32:03 +02:00
|
|
|
throw Out_of_ram();
|
2015-08-10 13:34:16 +02: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
|
|
|
catch (Cap_transfer::Quota_exceeded) {
|
|
|
|
session.destroy();
|
|
|
|
throw Out_of_caps();
|
|
|
|
}
|
2015-08-10 13:34:16 +02:00
|
|
|
|
2017-06-20 11:12:31 +02:00
|
|
|
/* try to dispatch session request synchronously */
|
|
|
|
service.initiate_request(session);
|
|
|
|
|
|
|
|
if (session.phase == Session_state::SERVICE_DENIED) {
|
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
throw Service_denied();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session.phase == Session_state::INSUFFICIENT_RAM_QUOTA) {
|
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
throw Insufficient_ram_quota();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
|
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
throw Insufficient_cap_quota();
|
|
|
|
}
|
|
|
|
|
2015-08-10 13:34:16 +02:00
|
|
|
/*
|
2016-11-06 14:26:34 +01:00
|
|
|
* Copy out the session cap before we are potentially kicking off the
|
|
|
|
* asynchonous request handling at the server to avoid doule-read
|
|
|
|
* issues with the session.cap, which will be asynchronously assigned
|
|
|
|
* by the server side.
|
2015-08-10 13:34:16 +02:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_capability cap = session.cap;
|
2015-08-10 13:34:16 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* if request was not handled synchronously, kick off async operation */
|
|
|
|
if (session.phase == Session_state::CREATE_REQUESTED)
|
|
|
|
service.wakeup();
|
2015-08-10 13:34:16 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (cap.valid())
|
|
|
|
session.phase = Session_state::CAP_HANDED_OUT;
|
|
|
|
|
|
|
|
return cap;
|
2015-08-10 13:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_capability Child::session_cap(Client::Id id)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
Session_capability cap;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
auto lamda = [&] (Session_state &session) {
|
2012-10-09 13:45:33 +02:00
|
|
|
|
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
|
|
|
if (session.phase == Session_state::SERVICE_DENIED
|
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
|
|
|
|| session.phase == Session_state::INSUFFICIENT_RAM_QUOTA
|
|
|
|
|| session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
|
|
|
Session_state::Phase const phase = session.phase;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/*
|
|
|
|
* Implicity discard the session request when delivering an
|
|
|
|
* exception because the exception will trigger the deallocation
|
|
|
|
* of the session ID at the child anyway.
|
|
|
|
*/
|
|
|
|
_revert_quota_and_destroy(session);
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
|
2017-05-08 14:32:03 +02:00
|
|
|
switch (phase) {
|
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
|
|
|
case Session_state::SERVICE_DENIED: throw Service_denied();
|
2017-05-08 14:32:03 +02:00
|
|
|
case Session_state::INSUFFICIENT_RAM_QUOTA: throw Insufficient_ram_quota();
|
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
|
|
|
case Session_state::INSUFFICIENT_CAP_QUOTA: throw Insufficient_cap_quota();
|
2017-05-08 14:32:03 +02:00
|
|
|
default: break;
|
|
|
|
}
|
2016-11-06 14:26:34 +01:00
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (!session.alive())
|
|
|
|
warning(_policy.name(), ": attempt to request cap for unavailable session: ", session);
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (session.cap.valid())
|
|
|
|
session.phase = Session_state::CAP_HANDED_OUT;
|
2013-09-25 10:51:57 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
cap = session.cap;
|
|
|
|
};
|
2013-09-25 10:51:57 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
try {
|
|
|
|
_id_space.apply<Session_state>(id, lamda); }
|
2013-09-25 10:51:57 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
catch (Id_space<Parent::Client>::Unknown_id) {
|
|
|
|
warning(_policy.name(), " requested session cap for unknown ID"); }
|
2013-09-25 10:51:57 +02:00
|
|
|
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
2016-11-06 14:26:34 +01:00
|
|
|
return cap;
|
2013-09-25 10:51:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const &args)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
if (!args.valid_string()) {
|
|
|
|
warning("no valid session-upgrade arguments");
|
|
|
|
return UPGRADE_DONE;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Upgrade_result result = UPGRADE_PENDING;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
_id_space.apply<Session_state>(id, [&] (Session_state &session) {
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (session.phase != Session_state::CAP_HANDED_OUT) {
|
|
|
|
warning("attempt to upgrade session in invalid state");
|
|
|
|
return;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2017-05-08 01:33:40 +02:00
|
|
|
Ram_quota const ram_quota {
|
|
|
|
Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0) };
|
2012-10-09 13:45:33 +02: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
|
|
|
Cap_quota const cap_quota {
|
|
|
|
Arg_string::find_arg(args.string(), "cap_quota").ulong_value(0) };
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
try {
|
2017-05-11 20:03:28 +02:00
|
|
|
Ram_transfer::Remote_account ref_ram_account { _policy.ref_pd(), _policy.ref_pd_cap() };
|
|
|
|
Cap_transfer::Remote_account ref_cap_account { _policy.ref_pd(), _policy.ref_pd_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
|
|
|
|
2017-05-11 20:03:28 +02:00
|
|
|
Ram_transfer::Remote_account ram_account { ram(), pd_session_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
|
|
|
Cap_transfer::Remote_account cap_account { pd(), pd_session_cap() };
|
2017-05-08 16:49:00 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* transfer quota from client to ourself */
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account);
|
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
|
|
|
Cap_transfer cap_donation_from_child(cap_quota, cap_account, ref_cap_account);
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* transfer session quota from ourself to the service provider */
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer ram_donation_to_service(ram_quota, ref_ram_account, session.service());
|
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
|
|
|
Cap_transfer cap_donation_to_service(cap_quota, ref_cap_account, session.service());
|
2013-08-14 21:19:11 +02: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
|
|
|
session.increase_donated_quota(ram_quota, cap_quota);
|
2016-11-06 14:26:34 +01:00
|
|
|
session.phase = Session_state::UPGRADE_REQUESTED;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
session.service().initiate_request(session);
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* finish transaction */
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_from_child.acknowledge();
|
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
|
|
|
cap_donation_from_child.acknowledge();
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_to_service.acknowledge();
|
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
|
|
|
cap_donation_to_service.acknowledge();
|
2016-11-06 14:26:34 +01:00
|
|
|
}
|
2017-05-08 16:49:00 +02:00
|
|
|
catch (Ram_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), ": RAM upgrade of ", session.service().name(), " failed");
|
2017-05-08 14:32:03 +02:00
|
|
|
throw Out_of_ram();
|
2016-11-06 14:26:34 +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
|
|
|
catch (Cap_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), ": cap upgrade of ", session.service().name(), " failed");
|
|
|
|
throw Out_of_caps();
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (session.phase == Session_state::CAP_HANDED_OUT) {
|
|
|
|
result = UPGRADE_DONE;
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
2016-11-06 14:26:34 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
session.service().wakeup();
|
|
|
|
});
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
2016-11-06 14:26:34 +01:00
|
|
|
return result;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::_revert_quota_and_destroy(Session_state &session)
|
|
|
|
{
|
2017-05-11 20:03:28 +02:00
|
|
|
Ram_transfer::Remote_account ref_ram_account(_policy.ref_pd(), _policy.ref_pd_cap());
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer::Account &service_ram_account = session.service();
|
2017-05-11 20:03:28 +02:00
|
|
|
Ram_transfer::Remote_account child_ram_account(ram(), pd_session_cap());
|
2017-05-08 16:49:00 +02: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
|
|
|
Cap_transfer::Remote_account ref_cap_account(_policy.ref_pd(), _policy.ref_pd_cap());
|
|
|
|
Cap_transfer::Account &service_cap_account = session.service();
|
|
|
|
Cap_transfer::Remote_account child_cap_account(pd(), pd_session_cap());
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
try {
|
|
|
|
/* transfer session quota from the service to ourself */
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_transfer ram_donation_from_service(session.donated_ram_quota(),
|
|
|
|
service_ram_account, ref_ram_account);
|
2012-10-09 13:45:33 +02: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
|
|
|
Cap_transfer cap_donation_from_service(session.donated_cap_quota(),
|
|
|
|
service_cap_account, ref_cap_account);
|
|
|
|
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
/*
|
|
|
|
* Transfer session quota from ourself to the client (our child). In
|
|
|
|
* addition to the quota returned from the server, we also return the
|
|
|
|
* quota that we preserved for locally storing the session meta data
|
|
|
|
* ('session_costs').
|
|
|
|
*/
|
2017-05-08 16:49:00 +02:00
|
|
|
Ram_quota const returned_ram { session.donated_ram_quota().value +
|
|
|
|
_session_factory.session_costs() };
|
|
|
|
|
|
|
|
Ram_transfer ram_donation_to_client(returned_ram,
|
|
|
|
ref_ram_account, child_ram_account);
|
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
|
|
|
Cap_transfer cap_donation_to_client(session.donated_cap_quota(),
|
|
|
|
ref_cap_account, child_cap_account);
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* finish transaction */
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_from_service.acknowledge();
|
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
|
|
|
cap_donation_from_service.acknowledge();
|
2017-05-08 16:49:00 +02:00
|
|
|
ram_donation_to_client.acknowledge();
|
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
|
|
|
cap_donation_to_client.acknowledge();
|
2016-11-06 14:26:34 +01:00
|
|
|
}
|
2017-05-08 16:49:00 +02:00
|
|
|
catch (Ram_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), ": could not revert session RAM quota (", session, ")"); }
|
|
|
|
catch (Cap_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), ": could not revert session cap quota (", session, ")"); }
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
session.destroy();
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Child::Close_result Child::_close(Session_state &session)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
/*
|
|
|
|
* If session could not be established, destruct session immediately
|
|
|
|
* without involving the server
|
|
|
|
*/
|
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
|
|
|
if (session.phase == Session_state::SERVICE_DENIED
|
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
|
|
|
|| session.phase == Session_state::INSUFFICIENT_RAM_QUOTA
|
|
|
|
|| session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
|
2016-11-06 14:26:34 +01:00
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
return CLOSE_DONE;
|
|
|
|
}
|
2015-08-10 13:34:16 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* close session if alive */
|
|
|
|
if (session.alive()) {
|
|
|
|
session.phase = Session_state::CLOSE_REQUESTED;
|
|
|
|
session.service().initiate_request(session);
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/*
|
|
|
|
* The service may have completed the close request immediately (e.g.,
|
|
|
|
* a locally implemented service). In this case, we can skip the
|
|
|
|
* asynchonous handling.
|
|
|
|
*/
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
if (session.phase == Session_state::CLOSED) {
|
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
return CLOSE_DONE;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2017-02-17 15:25:52 +01:00
|
|
|
_policy.session_state_changed();
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
session.discard_id_at_client();
|
|
|
|
session.service().wakeup();
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
return CLOSE_PENDING;
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Child::Close_result Child::close(Client::Id id)
|
|
|
|
{
|
|
|
|
/* refuse to close the child's initial sessions */
|
|
|
|
if (Parent::Env::session_id(id))
|
|
|
|
return CLOSE_DONE;
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
try {
|
|
|
|
Close_result result = CLOSE_PENDING;
|
|
|
|
auto lamda = [&] (Session_state &session) { result = _close(session); };
|
|
|
|
_id_space.apply<Session_state>(id, lamda);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
catch (Id_space<Parent::Client>::Unknown_id) { return CLOSE_DONE; }
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void Child::session_ready(Session_state &session)
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
if (_session_sigh.valid() && session.async_client_notify)
|
|
|
|
Signal_transmitter(_session_sigh).submit();
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
void Child::session_closed(Session_state &session)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the session was provided by a child of us, 'service.ram()' returns
|
|
|
|
* the RAM session of the corresponding child. Since the session to the
|
|
|
|
* server is closed now, we expect the server to have released all donated
|
|
|
|
* resources so that we can decrease the servers' quota.
|
|
|
|
*
|
|
|
|
* If this goes wrong, the server is misbehaving.
|
|
|
|
*/
|
|
|
|
_revert_quota_and_destroy(session);
|
|
|
|
|
|
|
|
if (_session_sigh.valid())
|
|
|
|
Signal_transmitter(_session_sigh).submit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Child::session_response(Server::Id id, Session_response response)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
_policy.server_id_space().apply<Session_state>(id, [&] (Session_state &session) {
|
|
|
|
|
|
|
|
switch (response) {
|
|
|
|
|
|
|
|
case Parent::SESSION_CLOSED:
|
|
|
|
session.phase = Session_state::CLOSED;
|
2017-04-12 11:26:31 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the client exists, reflect the response to the client
|
|
|
|
* via the 'closed_callback'. If the client has vanished,
|
|
|
|
* i.e., if the close request was issued by ourself while
|
|
|
|
* killing a child, we drop the session state immediately.
|
|
|
|
*/
|
2018-06-07 12:02:38 +02:00
|
|
|
if (session.closed_callback) {
|
2016-11-06 14:26:34 +01:00
|
|
|
session.closed_callback->session_closed(session);
|
2018-06-07 12:02:38 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The client no longer exists. So we cannot take the
|
|
|
|
* regular path of executing '_revert_quota_and_destroy' in
|
|
|
|
* the context of the client. Instead, we immediately
|
|
|
|
* withdraw the session quota from the server ('this') to
|
|
|
|
* the reference account, and destroy the session object.
|
|
|
|
*/
|
|
|
|
Ram_transfer::Remote_account ref_ram_account(_policy.ref_pd(), _policy.ref_pd_cap());
|
|
|
|
Ram_transfer::Account &service_ram_account = session.service();
|
|
|
|
|
|
|
|
Cap_transfer::Remote_account ref_cap_account(_policy.ref_pd(), _policy.ref_pd_cap());
|
|
|
|
Cap_transfer::Account &service_cap_account = session.service();
|
|
|
|
|
|
|
|
try {
|
|
|
|
/* transfer session quota from the service to ourself */
|
|
|
|
Ram_transfer ram_donation_from_service(session.donated_ram_quota(),
|
|
|
|
service_ram_account, ref_ram_account);
|
|
|
|
|
|
|
|
Cap_transfer cap_donation_from_service(session.donated_cap_quota(),
|
|
|
|
service_cap_account, ref_cap_account);
|
|
|
|
|
|
|
|
ram_donation_from_service.acknowledge();
|
|
|
|
cap_donation_from_service.acknowledge();
|
|
|
|
}
|
|
|
|
catch (Ram_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), " failed to return session RAM quota "
|
|
|
|
"(", session.donated_ram_quota(), ")"); }
|
|
|
|
catch (Cap_transfer::Quota_exceeded) {
|
|
|
|
warning(_policy.name(), " failed to return session cap quota "
|
|
|
|
"(", session.donated_cap_quota(), ")"); }
|
|
|
|
|
|
|
|
session.destroy();
|
|
|
|
_policy.session_state_changed();
|
|
|
|
}
|
2016-11-06 14:26:34 +01:00
|
|
|
break;
|
|
|
|
|
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
|
|
|
case Parent::SERVICE_DENIED:
|
|
|
|
session.phase = Session_state::SERVICE_DENIED;
|
2016-11-06 14:26:34 +01:00
|
|
|
if (session.ready_callback)
|
|
|
|
session.ready_callback->session_ready(session);
|
|
|
|
break;
|
|
|
|
|
2017-05-08 14:32:03 +02:00
|
|
|
case Parent::INSUFFICIENT_RAM_QUOTA:
|
|
|
|
session.phase = Session_state::INSUFFICIENT_RAM_QUOTA;
|
base: remove Child::heap
This patch improves the accounting for the backing store of
session-state meta data. Originally, the session state used to be
allocated by a child-local heap partition fed from the child's RAM
session. However, whereas this approach was somehow practical from a
runtime's (parent's) point of view, the child component could not count
on the quota in its own RAM session. I.e., if the Child::heap grew at
the parent side, the child's RAM session would magically diminish. This
caused two problems. First, it violates assumptions of components like
init that carefully manage their RAM resources (and giving most of them
away their children). Second, if a child transfers most of its RAM
session quota to another RAM session (like init does), the child's RAM
session may actually not allow the parent's heap to grow, which is a
very difficult error condition to deal with.
In the new version, there is no Child::heap anymore. Instead, session
states are allocated from the runtime's RAM session. In order to let
children pay for these costs, the parent withdraws the local session
costs from the session quota donated from the child when the child
initiates a new session. Hence, in principle, all components on the
route of the session request take a small bite from the session quota to
pay for their local book keeping
Consequently, the session quota that ends up at the server may become
depleted more or less, depending on the route. In the case where the
remaining quota is insufficient for the server, the server responds with
'QUOTA_EXCEEDED'. Since this behavior must generally be expected, this
patch equips the client-side 'Env::session' implementation with the
ability to re-issue session requests with successively growing quota
donations.
For several of core's services (ROM, IO_MEM, IRQ), the default session
quota has now increased by 2 KiB, which should suffice for session
requests to up to 3 hops as is the common case for most run scripts. For
longer routes, the retry mechanism as described above comes into effect.
For the time being, we give a warning whenever the server-side quota
check triggers the retry mechanism. The warning may eventually be
removed at a later stage.
2017-02-19 10:31:50 +01:00
|
|
|
if (session.ready_callback)
|
|
|
|
session.ready_callback->session_ready(session);
|
|
|
|
break;
|
|
|
|
|
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
|
|
|
case Parent::INSUFFICIENT_CAP_QUOTA:
|
|
|
|
session.phase = Session_state::INSUFFICIENT_CAP_QUOTA;
|
|
|
|
if (session.ready_callback)
|
|
|
|
session.ready_callback->session_ready(session);
|
|
|
|
break;
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
case Parent::SESSION_OK:
|
|
|
|
if (session.phase == Session_state::UPGRADE_REQUESTED) {
|
|
|
|
session.phase = Session_state::CAP_HANDED_OUT;
|
|
|
|
if (session.ready_callback)
|
|
|
|
session.ready_callback->session_ready(session);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (Child_policy::Nonexistent_id_space) { }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Child::deliver_session_cap(Server::Id id, Session_capability cap)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
_policy.server_id_space().apply<Session_state>(id, [&] (Session_state &session) {
|
|
|
|
|
|
|
|
if (session.cap.valid()) {
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
_error("attempt to assign session cap twice");
|
2016-11-06 14:26:34 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
session.cap = cap;
|
|
|
|
session.phase = Session_state::AVAILABLE;
|
|
|
|
|
|
|
|
if (session.ready_callback)
|
|
|
|
session.ready_callback->session_ready(session);
|
|
|
|
});
|
|
|
|
} catch (Child_policy::Nonexistent_id_space) { }
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Child::exit(int exit_value)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This function receives the hint from the child that now, its a good time
|
|
|
|
* to kill it. An inherited child class could use this hint to schedule the
|
|
|
|
* destruction of the child object.
|
|
|
|
*
|
|
|
|
* Note that the child object must not be destructed from by this function
|
|
|
|
* because it is executed by the thread contained in the child object.
|
|
|
|
*/
|
2016-04-27 16:04:58 +02:00
|
|
|
return _policy.exit(exit_value);
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-10 13:05:54 +02:00
|
|
|
Thread_capability Child::main_thread_cap() const
|
|
|
|
{
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
/*
|
|
|
|
* The '_initial_thread' is always constructed when this function is
|
|
|
|
* called because the RPC call originates from the active child.
|
|
|
|
*/
|
|
|
|
return _initial_thread.constructed() ? _initial_thread->cap()
|
|
|
|
: Thread_capability();
|
2012-10-10 13:05:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-25 10:51:57 +02:00
|
|
|
void Child::resource_avail_sigh(Signal_context_capability sigh)
|
|
|
|
{
|
|
|
|
_resource_avail_sigh = sigh;
|
|
|
|
}
|
|
|
|
|
2013-09-19 20:39:35 +02:00
|
|
|
|
2013-09-25 10:51:57 +02:00
|
|
|
void Child::resource_request(Resource_args const &args)
|
|
|
|
{
|
2016-04-27 16:04:58 +02:00
|
|
|
_policy.resource_request(args);
|
2013-09-25 10:51:57 +02:00
|
|
|
}
|
2013-09-19 20:39:35 +02:00
|
|
|
|
|
|
|
|
2013-09-25 10:51:57 +02:00
|
|
|
void Child::yield_sigh(Signal_context_capability sigh) { _yield_sigh = sigh; }
|
2013-09-19 20:39:35 +02:00
|
|
|
|
|
|
|
|
2013-09-25 10:51:57 +02:00
|
|
|
Parent::Resource_args Child::yield_request()
|
|
|
|
{
|
|
|
|
Lock::Guard guard(_yield_request_lock);
|
2013-09-19 20:39:35 +02:00
|
|
|
|
2013-09-25 10:51:57 +02:00
|
|
|
return _yield_request_args;
|
|
|
|
}
|
2013-09-19 20:39:35 +02:00
|
|
|
|
|
|
|
|
2016-04-27 16:04:58 +02:00
|
|
|
void Child::yield_response() { _policy.yield_response(); }
|
2013-09-19 20:39:35 +02:00
|
|
|
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return interface for interacting with the child's address space
|
|
|
|
*
|
|
|
|
* Depending on the return value of 'Child_policy::address_space', we
|
|
|
|
* either interact with a local object of via an RPC client stub.
|
|
|
|
*/
|
|
|
|
struct Child_address_space
|
|
|
|
{
|
|
|
|
Region_map_client _rm_client;
|
|
|
|
Region_map &_rm;
|
|
|
|
|
|
|
|
Child_address_space(Pd_session &pd, Child_policy &policy)
|
|
|
|
:
|
|
|
|
_rm_client(pd.address_space()),
|
|
|
|
_rm(policy.address_space(pd) ? *policy.address_space(pd) : _rm_client)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Region_map ®ion_map() { return _rm; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
void Child::_try_construct_env_dependent_members()
|
|
|
|
{
|
|
|
|
/* check if the environment sessions are complete */
|
2017-05-11 20:03:28 +02:00
|
|
|
if (!_pd.cap().valid() || !_cpu.cap().valid() || !_log.cap().valid()
|
|
|
|
|| !_binary.cap().valid())
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the ROM-session request for the dynamic linker was granted but the
|
|
|
|
* response to the session request is still outstanding, we have to wait.
|
|
|
|
* Note that we proceed if the session request was denied by the policy,
|
|
|
|
* which may be the case when using a statically linked executable.
|
|
|
|
*/
|
|
|
|
if (_linker.constructed() && !_linker->cap().valid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark all environment sessions as handed out to prevent the triggering
|
|
|
|
* of signals by 'Child::session_sigh' for these sessions.
|
|
|
|
*/
|
|
|
|
_id_space.for_each<Session_state>([&] (Session_state &session) {
|
|
|
|
if (session.phase == Session_state::AVAILABLE)
|
|
|
|
session.phase = Session_state::CAP_HANDED_OUT; });
|
|
|
|
|
|
|
|
_policy.init(_cpu.session(), _cpu.cap());
|
|
|
|
|
|
|
|
try {
|
2017-08-17 19:19:38 +02:00
|
|
|
_initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name());
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
_process.construct(_binary.session().dataspace(), _linker_dataspace(),
|
2017-05-11 20:03:28 +02:00
|
|
|
_pd.cap(), _pd.session(), _pd.session(),
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
*_initial_thread, _local_rm,
|
|
|
|
Child_address_space(_pd.session(), _policy).region_map(),
|
2017-05-13 01:03:59 +02:00
|
|
|
cap());
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
}
|
2017-05-08 14:32:03 +02:00
|
|
|
catch (Out_of_ram) { _error("out of RAM during ELF loading"); }
|
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
|
|
|
catch (Out_of_caps) { _error("out of caps during ELF loading"); }
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
catch (Cpu_session::Thread_creation_failed) { _error("unable to create initial thread"); }
|
|
|
|
catch (Process::Missing_dynamic_linker) { _error("dynamic linker unavailable"); }
|
|
|
|
catch (Process::Invalid_executable) { _error("invalid ELF executable"); }
|
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
|
|
|
catch (Region_map::Invalid_dataspace) { _error("ELF loading failed (Invalid_dataspace)"); }
|
|
|
|
catch (Region_map::Region_conflict) { _error("ELF loading failed (Region_conflict)"); }
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-18 13:47:17 +01:00
|
|
|
void Child::_discard_env_session(Id_space<Parent::Client>::Id id)
|
|
|
|
{
|
|
|
|
auto discard_id_fn = [&] (Session_state &s) { s.discard_id_at_client(); };
|
|
|
|
|
|
|
|
try { _id_space.apply<Session_state>(id, discard_id_fn); }
|
|
|
|
catch (Id_space<Parent::Client>::Unknown_id) { }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-11 20:03:28 +02:00
|
|
|
void Child::initiate_env_ram_session()
|
|
|
|
{
|
|
|
|
_pd.initiate();
|
|
|
|
_policy.init(_pd.session(), _pd.cap());
|
|
|
|
}
|
2017-02-19 21:40:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
void Child::initiate_env_sessions()
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
{
|
2017-02-19 21:40:52 +01:00
|
|
|
_cpu .initiate();
|
|
|
|
_log .initiate();
|
|
|
|
_binary.initiate();
|
|
|
|
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
/*
|
|
|
|
* Issue environment-session request for obtaining the linker binary. We
|
|
|
|
* accept this request to fail. In this case, the child creation may still
|
|
|
|
* succeed if the binary is statically linked.
|
|
|
|
*/
|
2017-02-19 21:40:52 +01:00
|
|
|
try {
|
|
|
|
_linker.construct(*this, Parent::Env::linker(), _policy.linker_name());
|
|
|
|
_linker->initiate();
|
|
|
|
}
|
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
|
|
|
catch (Service_denied) { }
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
|
|
|
|
_try_construct_env_dependent_members();
|
|
|
|
}
|
2012-10-09 13:45:33 +02:00
|
|
|
|
|
|
|
|
2018-01-12 14:10:47 +01:00
|
|
|
/**
|
|
|
|
* Return any CPU session that is initiated by the child
|
|
|
|
*
|
|
|
|
* \return client ID of a CPU session, or
|
|
|
|
* client ID 0 if no session exists
|
|
|
|
*/
|
|
|
|
static Parent::Client::Id any_cpu_session_id(Id_space<Parent::Client> const &id_space)
|
2017-02-19 21:40:52 +01:00
|
|
|
{
|
2018-01-12 14:10:47 +01:00
|
|
|
Parent::Client::Id result { 0 };
|
|
|
|
id_space.for_each<Session_state const>([&] (Session_state const &session) {
|
|
|
|
if (result.value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool cpu = (session.service().name() == Cpu_session::service_name());
|
|
|
|
bool env = Parent::Env::session_id(session.id_at_client());
|
|
|
|
|
|
|
|
if (!env && cpu)
|
|
|
|
result = session.id_at_client();
|
|
|
|
});
|
|
|
|
return result;
|
2017-02-19 21:40:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-12 14:10:47 +01:00
|
|
|
void Child::close_all_sessions()
|
2012-10-09 13:45:33 +02:00
|
|
|
{
|
2018-01-12 14:10:47 +01:00
|
|
|
/*
|
|
|
|
* Destroy CPU sessions prior to other session types to avoid page-fault
|
|
|
|
* warnings generated by threads that are losing their PD while still
|
|
|
|
* running.
|
|
|
|
*/
|
|
|
|
while (unsigned long id_value = any_cpu_session_id(_id_space).value)
|
|
|
|
close(Parent::Client::Id{id_value});
|
|
|
|
|
|
|
|
_initial_thread.destruct();
|
|
|
|
|
|
|
|
if (KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION)
|
|
|
|
_cpu._connection.destruct();
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/*
|
|
|
|
* Purge the meta data about any dangling sessions provided by the child to
|
|
|
|
* other children.
|
|
|
|
*
|
|
|
|
* Note that the session quota is not transferred back to the respective
|
|
|
|
* clients.
|
|
|
|
*
|
|
|
|
* All the session meta data is lost after this point. In principle, we
|
|
|
|
* could accumulate the to-be-replenished quota at each client. Once the
|
|
|
|
* server is completely destroyed (and we thereby regained all of the
|
|
|
|
* server's resources, the RAM sessions of the clients could be updated.
|
|
|
|
* However, a client of a suddenly disappearing server is expected to be in
|
|
|
|
* trouble anyway and likely to get stuck on the next attempt to interact
|
|
|
|
* with the server. So the added complexity of reverting the session quotas
|
|
|
|
* would be to no benefit.
|
|
|
|
*/
|
|
|
|
try {
|
|
|
|
auto lambda = [&] (Session_state &s) { _revert_quota_and_destroy(s); };
|
|
|
|
while (_policy.server_id_space().apply_any<Session_state>(lambda));
|
|
|
|
}
|
|
|
|
catch (Child_policy::Nonexistent_id_space) { }
|
|
|
|
|
2018-05-22 11:32:36 +02:00
|
|
|
/*
|
|
|
|
* Issue close requests to the providers of the environment sessions,
|
|
|
|
* which may be async services. Don't close the PD session since it
|
|
|
|
* is still needed for reverting session quotas.
|
|
|
|
*/
|
|
|
|
_log.close();
|
|
|
|
_binary.close();
|
|
|
|
if (_linker.constructed())
|
|
|
|
_linker->close();
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/*
|
|
|
|
* Remove statically created env sessions from the child's ID space.
|
|
|
|
*/
|
2017-01-18 13:47:17 +01:00
|
|
|
_discard_env_session(Env::cpu());
|
|
|
|
_discard_env_session(Env::pd());
|
|
|
|
_discard_env_session(Env::log());
|
2017-03-06 17:02:44 +01:00
|
|
|
_discard_env_session(Env::binary());
|
|
|
|
_discard_env_session(Env::linker());
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove dynamically created sessions from the child's ID space.
|
|
|
|
*/
|
|
|
|
auto close_fn = [&] (Session_state &session) {
|
|
|
|
session.closed_callback = nullptr;
|
|
|
|
session.ready_callback = nullptr;
|
|
|
|
_close(session);
|
|
|
|
};
|
|
|
|
|
|
|
|
while (_id_space.apply_any<Session_state>(close_fn));
|
2018-05-22 11:32:36 +02:00
|
|
|
|
|
|
|
if (!KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION)
|
|
|
|
_cpu._connection.destruct();
|
2018-01-12 14:10:47 +01:00
|
|
|
}
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
|
2018-01-12 14:10:47 +01:00
|
|
|
|
|
|
|
Child::Child(Region_map &local_rm,
|
|
|
|
Rpc_entrypoint &entrypoint,
|
|
|
|
Child_policy &policy)
|
|
|
|
:
|
|
|
|
_policy(policy), _local_rm(local_rm), _parent_cap_guard(entrypoint, *this)
|
|
|
|
{
|
|
|
|
if (_policy.initiate_env_sessions()) {
|
|
|
|
initiate_env_ram_session();
|
|
|
|
initiate_env_sessions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Child::~Child()
|
|
|
|
{
|
|
|
|
close_all_sessions();
|
base: apply routing policy to environment sessions
This patch changes the child-construction procedure to allow the routing
of environment sessions to arbitrary servers, not only to the parent.
In particular, it restores the ability to route the LOG session of the
child to a LOG service provided by a child of init. In principle, it
becomes possible to also route the immediate child's PD, CPU, and RAM
environment sessions in arbitrary ways, which simplifies scenarios that
intercept those sessions, e.g., the CPU sampler.
Note that the latter ability should be used with great caution because
init needs to interact with these sessions to create/destruct the child.
Normally, the sessions are provided by the parent. So init is safe at
all times. If they are routed to a child however, init will naturally
become dependent on this particular child. For the LOG session, this is
actually not a problem because even though the parent creates the LOG
session as part of the child's environment, it never interacts with the
session directly.
Fixes #2197
2016-12-12 17:40:55 +01:00
|
|
|
_process.destruct();
|
2012-10-09 13:45:33 +02:00
|
|
|
}
|
|
|
|
|