2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Child creation framework
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2006-07-22
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2006-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _INCLUDE__BASE__CHILD_H_
|
|
|
|
#define _INCLUDE__BASE__CHILD_H_
|
|
|
|
|
|
|
|
#include <base/rpc_server.h>
|
|
|
|
#include <base/heap.h>
|
|
|
|
#include <base/service.h>
|
|
|
|
#include <base/lock.h>
|
2016-11-06 14:26:34 +01:00
|
|
|
#include <base/local_connection.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <util/arg_string.h>
|
2016-11-06 14:26:34 +01:00
|
|
|
#include <ram_session/connection.h>
|
2016-04-27 16:04:58 +02:00
|
|
|
#include <region_map/client.h>
|
2016-11-06 14:26:34 +01:00
|
|
|
#include <pd_session/connection.h>
|
|
|
|
#include <cpu_session/connection.h>
|
|
|
|
#include <log_session/connection.h>
|
|
|
|
#include <rom_session/connection.h>
|
2016-04-27 16:04:58 +02:00
|
|
|
#include <parent/capability.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
namespace Genode {
|
2015-03-04 21:12:14 +01:00
|
|
|
struct Child_policy;
|
|
|
|
struct Child;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Child policy interface
|
|
|
|
*
|
|
|
|
* A child-policy object is an argument to a 'Child'. It is responsible for
|
|
|
|
* taking policy decisions regarding the parent interface. Most importantly,
|
|
|
|
* it defines how session requests are resolved and how session arguments
|
|
|
|
* are passed to servers when creating sessions.
|
|
|
|
*/
|
|
|
|
struct Genode::Child_policy
|
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
typedef String<64> Name;
|
|
|
|
typedef String<64> Binary_name;
|
|
|
|
typedef String<64> Linker_name;
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
virtual ~Child_policy() { }
|
|
|
|
|
|
|
|
/**
|
2016-11-06 14:26:34 +01:00
|
|
|
* Name of the child used as the child's label prefix
|
|
|
|
*/
|
|
|
|
virtual Name name() const = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ROM module name of the binary to start
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
virtual Binary_name binary_name() const { return name(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ROM module name of the dynamic linker
|
|
|
|
*/
|
|
|
|
virtual Linker_name linker_name() const { return "ld.lib.so"; }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine service to provide a session request
|
|
|
|
*
|
2016-11-06 14:26:34 +01:00
|
|
|
* \return service to be contacted for the new session
|
|
|
|
*
|
|
|
|
* \throw Parent::Service_denied
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
virtual Service &resolve_session_request(Service::Name const &,
|
|
|
|
Session_state::Args const &) = 0;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Apply transformations to session arguments
|
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
virtual void filter_session_args(Service::Name const &,
|
2015-03-04 21:12:14 +01:00
|
|
|
char * /*args*/, size_t /*args_len*/) { }
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
2015-03-04 21:12:14 +01:00
|
|
|
* Register a service provided by the child
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
virtual void announce_service(Service::Name const &) { }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Apply session affinity policy
|
|
|
|
*
|
|
|
|
* \param affinity affinity passed along with a session request
|
|
|
|
* \return affinity subordinated to the child policy
|
|
|
|
*/
|
|
|
|
virtual Affinity filter_session_affinity(Affinity const &affinity)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2015-03-04 21:12:14 +01:00
|
|
|
return affinity;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
/**
|
|
|
|
* Exit child
|
|
|
|
*/
|
|
|
|
virtual void exit(int exit_value)
|
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
log("child \"", name(), "\" exited with exit value ", exit_value);
|
2015-03-04 21:12:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reference RAM session
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* The RAM session returned by this method is used for session-quota
|
2015-03-04 21:12:14 +01:00
|
|
|
* transfers.
|
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
virtual Ram_session &ref_ram() = 0;
|
|
|
|
virtual Ram_session_capability ref_ram_cap() const = 0;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to the release of resources by the child
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* This method is called when the child confirms the release of
|
2015-03-04 21:12:14 +01:00
|
|
|
* resources in response to a yield request.
|
|
|
|
*/
|
|
|
|
virtual void yield_response() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Take action on additional resource needs by the child
|
|
|
|
*/
|
|
|
|
virtual void resource_request(Parent::Resource_args const &) { }
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the child's RAM session
|
|
|
|
*
|
|
|
|
* The function must define the child's reference account and transfer
|
|
|
|
* the child's initial RAM quota.
|
|
|
|
*/
|
|
|
|
virtual void init(Ram_session &, Capability<Ram_session>) = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the child's CPU session
|
|
|
|
*
|
|
|
|
* The function may install an exception signal handler or assign CPU quota
|
|
|
|
* to the child.
|
|
|
|
*/
|
|
|
|
virtual void init(Cpu_session &, Capability<Cpu_session>) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the child's PD session
|
|
|
|
*
|
|
|
|
* The function may install a region-map fault handler for the child's
|
|
|
|
* address space ('Pd_session::address_space');.
|
|
|
|
*/
|
|
|
|
virtual void init(Pd_session &, Capability<Pd_session>) { }
|
|
|
|
|
|
|
|
class Nonexistent_id_space : Exception { };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ID space for sessions provided by the child
|
|
|
|
*
|
|
|
|
* \throw Nonexistent_id_space
|
|
|
|
*/
|
|
|
|
virtual Id_space<Parent::Server> &server_id_space() { throw Nonexistent_id_space(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return region map for the child's address space
|
|
|
|
*
|
|
|
|
* \param pd the child's PD session capability
|
|
|
|
*
|
|
|
|
* By default, the function returns a 'nullptr'. In this case, the 'Child'
|
|
|
|
* interacts with the address space of the child's PD session via RPC calls
|
|
|
|
* to the 'Pd_session::address_space'.
|
|
|
|
*
|
|
|
|
* By overriding the default, those RPC calls can be omitted, which is
|
|
|
|
* useful if the child's PD session (including the PD's address space) is
|
|
|
|
* virtualized by the parent. If the virtual PD session is served by the
|
|
|
|
* same entrypoint as the child's parent interface, an RPC call to 'pd'
|
|
|
|
* would otherwise produce a deadlock.
|
|
|
|
*/
|
|
|
|
virtual Region_map *address_space(Pd_session &) { return nullptr; }
|
2015-03-04 21:12:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementation of the parent interface that supports resource trading
|
|
|
|
*
|
|
|
|
* There are three possible cases of how a session can be provided to
|
2015-03-20 17:50:41 +01:00
|
|
|
* a child: The service is implemented locally, the session was obtained by
|
|
|
|
* asking our parent, or the session is provided by one of our children.
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
|
|
|
* These types must be differentiated for the quota management when a child
|
2015-03-20 17:50:41 +01:00
|
|
|
* issues the closing of a session or transfers quota via our parent
|
2015-03-04 21:12:14 +01:00
|
|
|
* interface.
|
|
|
|
*
|
|
|
|
* If we close a session to a local service, we transfer the session quota
|
|
|
|
* from our own account to the client.
|
|
|
|
*
|
|
|
|
* If we close a parent session, we receive the session quota on our own
|
|
|
|
* account and must transfer this amount to the session-closing child.
|
|
|
|
*
|
|
|
|
* If we close a session provided by a server child, we close the session
|
2015-03-20 17:50:41 +01:00
|
|
|
* at the server, transfer the session quota from the server's RAM session
|
2015-03-04 21:12:14 +01:00
|
|
|
* to our account, and subsequently transfer the same amount from our
|
|
|
|
* account to the client.
|
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
class Genode::Child : protected Rpc_object<Parent>,
|
|
|
|
Session_state::Ready_callback,
|
|
|
|
Session_state::Closed_callback
|
2015-03-04 21:12:14 +01:00
|
|
|
{
|
2016-11-06 14:26:34 +01:00
|
|
|
private:
|
2016-05-10 18:05:38 +02:00
|
|
|
|
|
|
|
struct Initial_thread_base
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Start execution at specified instruction pointer
|
|
|
|
*/
|
|
|
|
virtual void start(addr_t ip) = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return capability of the initial thread
|
|
|
|
*/
|
|
|
|
virtual Capability<Cpu_thread> cap() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Initial_thread : Initial_thread_base
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Cpu_session &_cpu;
|
|
|
|
Thread_capability _cap;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
typedef Cpu_session::Name Name;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \throw Cpu_session::Thread_creation_failed
|
|
|
|
* \throw Cpu_session::Out_of_metadata
|
|
|
|
*/
|
|
|
|
Initial_thread(Cpu_session &, Pd_session_capability, Name const &);
|
|
|
|
~Initial_thread();
|
|
|
|
|
|
|
|
void start(addr_t) override;
|
|
|
|
|
|
|
|
Capability<Cpu_thread> cap() { return _cap; }
|
|
|
|
};
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* child policy */
|
|
|
|
Child_policy &_policy;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* sessions opened by the child */
|
|
|
|
Id_space<Client> _id_space;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
typedef Session_state::Args Args;
|
2016-04-20 21:12:57 +02:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
template <typename CONNECTION>
|
|
|
|
struct Env_connection
|
|
|
|
{
|
|
|
|
typedef String<64> Label;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Args const _args;
|
|
|
|
Service &_service;
|
|
|
|
Local_connection<CONNECTION> _connection;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/**
|
|
|
|
* Construct session arguments with the child policy applied
|
|
|
|
*/
|
|
|
|
Args _construct_args(Child_policy &policy, Label const &label)
|
|
|
|
{
|
|
|
|
/* copy original arguments into modifiable buffer */
|
|
|
|
char buf[Session_state::Args::capacity()];
|
|
|
|
buf[0] = 0;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* supply label as session argument */
|
|
|
|
if (label.valid())
|
|
|
|
Arg_string::set_arg_string(buf, sizeof(buf), "label", label.string());
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
/* apply policy to argument buffer */
|
|
|
|
policy.filter_session_args(CONNECTION::service_name(), buf, sizeof(buf));
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
return Session_state::Args(Cstring(buf));
|
|
|
|
}
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Env_connection(Child_policy &policy, Id_space<Parent::Client> &id_space,
|
|
|
|
Id_space<Parent::Client>::Id id, Label const &label = Label())
|
|
|
|
:
|
|
|
|
_args(_construct_args(policy, label)),
|
|
|
|
_service(policy.resolve_session_request(CONNECTION::service_name(), _args)),
|
|
|
|
_connection(_service, id_space, id, _args,
|
|
|
|
policy.filter_session_affinity(Affinity()))
|
|
|
|
{ }
|
|
|
|
|
|
|
|
typedef typename CONNECTION::Session_type SESSION;
|
|
|
|
|
|
|
|
SESSION &session() { return _connection.session(); }
|
|
|
|
Capability<SESSION> cap() const { return _connection.cap(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
Env_connection<Ram_connection> _ram { _policy,
|
2016-11-24 15:28:32 +01:00
|
|
|
_id_space, Parent::Env::ram(), _policy.name() };
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
Env_connection<Pd_connection> _pd { _policy,
|
2016-11-24 15:28:32 +01:00
|
|
|
_id_space, Parent::Env::pd(), _policy.name() };
|
2016-11-06 14:26:34 +01:00
|
|
|
|
|
|
|
Env_connection<Cpu_connection> _cpu { _policy,
|
2016-11-24 15:28:32 +01:00
|
|
|
_id_space, Parent::Env::cpu(), _policy.name() };
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Env_connection<Log_connection> _log { _policy,
|
2016-11-24 15:28:32 +01:00
|
|
|
_id_space, Parent::Env::log(), _policy.name() };
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Env_connection<Rom_connection> _binary { _policy,
|
|
|
|
_id_space, Parent::Env::binary(), _policy.binary_name() };
|
|
|
|
|
2016-12-01 17:37:08 +01:00
|
|
|
Constructible<Env_connection<Rom_connection> > _linker { _policy,
|
2016-11-06 14:26:34 +01:00
|
|
|
_id_space, Parent::Env::linker(), _policy.linker_name() };
|
|
|
|
|
|
|
|
/* call 'Child_policy::init' methods for the environment sessions */
|
|
|
|
void _init_env_sessions()
|
|
|
|
{
|
|
|
|
_policy.init(_ram.session(), _ram.cap());
|
|
|
|
_policy.init(_cpu.session(), _cpu.cap());
|
|
|
|
_policy.init(_pd.session(), _pd.cap());
|
|
|
|
}
|
|
|
|
bool const _env_sessions_initialized = ( _init_env_sessions(), true );
|
|
|
|
|
|
|
|
Dataspace_capability _linker_dataspace()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
_linker.construct(_policy, _id_space,
|
|
|
|
Parent::Env::linker(), _policy.linker_name());
|
|
|
|
return _linker->session().dataspace();
|
|
|
|
}
|
|
|
|
catch (Parent::Service_denied) { return Rom_dataspace_capability(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
/* heap for child-specific allocations using the child's quota */
|
|
|
|
Heap _heap;
|
|
|
|
|
|
|
|
/* factory for dynamically created session-state objects */
|
|
|
|
Session_state::Factory _session_factory { _heap };
|
|
|
|
|
|
|
|
Rpc_entrypoint &_entrypoint;
|
|
|
|
Parent_capability _parent_cap;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/* signal handlers registered by the child */
|
|
|
|
Signal_context_capability _resource_avail_sigh;
|
|
|
|
Signal_context_capability _yield_sigh;
|
2016-11-06 14:26:34 +01:00
|
|
|
Signal_context_capability _session_sigh;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/* arguments fetched by the child in response to a yield signal */
|
|
|
|
Lock _yield_request_lock;
|
|
|
|
Resource_args _yield_request_args;
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
Initial_thread _initial_thread { _cpu.session(), _pd.cap(), "initial" };
|
|
|
|
|
2016-04-27 16:04:58 +02:00
|
|
|
struct Process
|
|
|
|
{
|
|
|
|
class Missing_dynamic_linker : Exception { };
|
|
|
|
class Invalid_executable : Exception { };
|
|
|
|
|
2016-05-10 18:05:38 +02:00
|
|
|
Initial_thread_base &initial_thread;
|
|
|
|
|
2016-04-27 16:04:58 +02:00
|
|
|
struct Loaded_executable
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Initial instruction pointer of the new process, as defined
|
|
|
|
* in the header of the executable.
|
|
|
|
*/
|
|
|
|
addr_t entry;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor parses the executable and sets up segment
|
|
|
|
* dataspaces
|
|
|
|
*
|
|
|
|
* \param local_rm local address space, needed to make the
|
|
|
|
* segment dataspaces temporarily visible in
|
|
|
|
* the local address space to initialize their
|
|
|
|
* content with the data from the 'elf_ds'
|
|
|
|
*
|
|
|
|
* \throw Region_map::Attach_failed
|
|
|
|
* \throw Invalid_executable
|
|
|
|
* \throw Missing_dynamic_linker
|
|
|
|
* \throw Ram_session::Alloc_failed
|
|
|
|
*/
|
|
|
|
Loaded_executable(Dataspace_capability elf_ds,
|
|
|
|
Dataspace_capability ldso_ds,
|
|
|
|
Ram_session &ram,
|
|
|
|
Region_map &local_rm,
|
|
|
|
Region_map &remote_rm,
|
|
|
|
Parent_capability parent_cap);
|
|
|
|
} loaded_executable;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \param ram RAM session used to allocate the BSS and
|
|
|
|
* DATA segments for the new process
|
|
|
|
* \param parent parent of the new protection domain
|
|
|
|
* \param name name of protection domain
|
|
|
|
*
|
|
|
|
* \throw Missing_dynamic_linker
|
|
|
|
* \throw Invalid_executable
|
|
|
|
* \throw Region_map::Attach_failed
|
|
|
|
* \throw Ram_session::Alloc_failed
|
|
|
|
*
|
|
|
|
* The other arguments correspond to those of 'Child::Child'.
|
|
|
|
*
|
|
|
|
* On construction of a protection domain, the initial thread is
|
|
|
|
* started immediately.
|
|
|
|
*
|
|
|
|
* The argument 'elf_ds' may be invalid to create an empty process.
|
|
|
|
* In this case, all process initialization steps except for the
|
|
|
|
* creation of the initial thread must be done manually, i.e., as
|
|
|
|
* done for implementing fork.
|
|
|
|
*/
|
|
|
|
Process(Dataspace_capability elf_ds,
|
|
|
|
Dataspace_capability ldso_ds,
|
|
|
|
Pd_session_capability pd_cap,
|
|
|
|
Pd_session &pd,
|
|
|
|
Ram_session &ram,
|
2016-05-10 18:05:38 +02:00
|
|
|
Initial_thread_base &initial_thread,
|
2016-04-27 16:04:58 +02:00
|
|
|
Region_map &local_rm,
|
|
|
|
Region_map &remote_rm,
|
2016-05-10 18:05:38 +02:00
|
|
|
Parent_capability parent);
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
~Process();
|
|
|
|
};
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
Process _process;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void _revert_quota_and_destroy(Session_state &);
|
|
|
|
|
|
|
|
Close_result _close(Session_state &);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/**
|
2016-11-06 14:26:34 +01:00
|
|
|
* Session_state::Ready_callback
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
void session_ready(Session_state &session) override;
|
2015-08-10 13:34:16 +02:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
2016-11-06 14:26:34 +01:00
|
|
|
* Session_state::Closed_callback
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
void session_closed(Session_state &) override;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
public:
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-04-27 16:04:58 +02:00
|
|
|
/**
|
|
|
|
* Exception type
|
|
|
|
*
|
|
|
|
* The startup of the physical process of the child may fail if the
|
|
|
|
* ELF binary is invalid, if the ELF binary is dynamically linked
|
|
|
|
* but no dynamic linker is provided, if the creation of the initial
|
|
|
|
* thread failed, or if the RAM session of the child is exhausted.
|
|
|
|
* Each of those conditions will result in a diagnostic log message.
|
|
|
|
* But for the error handling, we only distinguish the RAM exhaustion
|
|
|
|
* from the other conditions and subsume the latter as
|
|
|
|
* 'Process_startup_failed'.
|
|
|
|
*/
|
|
|
|
class Process_startup_failed : public Exception { };
|
|
|
|
|
2013-08-14 21:19:11 +02:00
|
|
|
/**
|
2015-03-04 21:12:14 +01:00
|
|
|
* Constructor
|
2013-08-14 21:19:11 +02:00
|
|
|
*
|
2016-11-06 14:26:34 +01:00
|
|
|
* \param rm local address space, usually 'env.rm()'
|
|
|
|
* \param entrypoint entrypoint used to serve the parent interface of
|
|
|
|
* the child
|
|
|
|
* \param policy policy for the child
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
2016-11-06 14:26:34 +01:00
|
|
|
* \throw Parent::Service_denied if the initial sessions for the
|
|
|
|
* child's environment could not be
|
|
|
|
* opened
|
2016-04-27 16:04:58 +02:00
|
|
|
* \throw Ram_session::Alloc_failed
|
|
|
|
* \throw Process_startup_failed
|
2013-08-14 21:19:11 +02:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
Child(Region_map &rm, Rpc_entrypoint &entrypoint, Child_policy &policy);
|
2013-08-14 21:19:11 +02:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
2015-03-04 21:12:14 +01:00
|
|
|
* Destructor
|
|
|
|
*
|
|
|
|
* On destruction of a child, we close all sessions of the child to
|
|
|
|
* other services.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2015-03-04 21:12:14 +01:00
|
|
|
virtual ~Child();
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/**
|
2016-11-06 14:26:34 +01:00
|
|
|
* RAM quota unconditionally consumed by the child's environment
|
|
|
|
*/
|
|
|
|
static size_t env_ram_quota()
|
|
|
|
{
|
|
|
|
return Cpu_connection::RAM_QUOTA + Ram_connection::RAM_QUOTA +
|
|
|
|
Pd_connection::RAM_QUOTA + Log_connection::RAM_QUOTA +
|
|
|
|
2*Rom_connection::RAM_QUOTA;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deduce session costs from usable ram quota
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
static size_t effective_ram_quota(size_t const ram_quota)
|
|
|
|
{
|
|
|
|
if (ram_quota < env_ram_quota())
|
|
|
|
return 0;
|
2012-02-15 22:36:54 +01:00
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
return ram_quota - env_ram_quota();
|
|
|
|
}
|
2012-10-24 16:27:26 +02:00
|
|
|
|
|
|
|
/**
|
2016-11-06 14:26:34 +01:00
|
|
|
* Return heap that uses the child's quota
|
2012-10-24 16:27:26 +02:00
|
|
|
*/
|
2016-11-06 14:26:34 +01:00
|
|
|
Allocator &heap() { return _heap; }
|
|
|
|
|
|
|
|
Ram_session_capability ram_session_cap() const { return _ram.cap(); }
|
|
|
|
|
|
|
|
Parent_capability parent_cap() const { return cap(); }
|
|
|
|
|
|
|
|
Ram_session &ram() { return _ram.session(); }
|
|
|
|
Cpu_session &cpu() { return _cpu.session(); }
|
|
|
|
Pd_session &pd() { return _pd .session(); }
|
|
|
|
|
|
|
|
Session_state::Factory &session_factory() { return _session_factory; }
|
2013-09-25 10:51:57 +02:00
|
|
|
|
|
|
|
/**
|
2015-03-04 21:12:14 +01:00
|
|
|
* Instruct the child to yield resources
|
2013-09-25 10:51:57 +02:00
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* By calling this method, the child will be notified about the
|
2015-03-04 21:12:14 +01:00
|
|
|
* need to release the specified amount of resources. For more
|
|
|
|
* details about the protocol between a child and its parent,
|
|
|
|
* refer to the description given in 'parent/parent.h'.
|
2013-09-25 10:51:57 +02:00
|
|
|
*/
|
2015-03-04 21:12:14 +01:00
|
|
|
void yield(Resource_args const &args);
|
2013-09-25 10:51:57 +02:00
|
|
|
|
|
|
|
/**
|
2015-03-04 21:12:14 +01:00
|
|
|
* Notify the child about newly available resources
|
2013-09-25 10:51:57 +02:00
|
|
|
*/
|
2015-03-04 21:12:14 +01:00
|
|
|
void notify_resource_avail() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
** Parent interface **
|
|
|
|
**********************/
|
|
|
|
|
2016-11-06 14:26:34 +01:00
|
|
|
void announce(Service_name const &) override;
|
|
|
|
void session_sigh(Signal_context_capability) override;
|
|
|
|
Session_capability session(Client::Id, Service_name const &,
|
|
|
|
Session_args const &, Affinity const &) override;
|
|
|
|
Session_capability session_cap(Client::Id) override;
|
|
|
|
Upgrade_result upgrade(Client::Id, Upgrade_args const &) override;
|
|
|
|
Close_result close(Client::Id) override;
|
2015-03-04 21:12:14 +01:00
|
|
|
void exit(int) override;
|
2016-11-06 14:26:34 +01:00
|
|
|
void session_response(Server::Id, Session_response) override;
|
|
|
|
void deliver_session_cap(Server::Id, Session_capability) override;
|
2015-03-04 21:12:14 +01:00
|
|
|
Thread_capability main_thread_cap() const override;
|
|
|
|
void resource_avail_sigh(Signal_context_capability) override;
|
|
|
|
void resource_request(Resource_args const &) override;
|
|
|
|
void yield_sigh(Signal_context_capability) override;
|
|
|
|
Resource_args yield_request() override;
|
|
|
|
void yield_response() override;
|
|
|
|
};
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
#endif /* _INCLUDE__BASE__CHILD_H_ */
|