b44f0554bd
This patch adjusts the various users of the 'Child' API to the changes on the account of the new non-blocking parent interface. It also removes the use of the no-longer-available 'Connection::KEEP_OPEN' feature. With the adjustment, we took the opportunity to redesign several components to fit the non-blocking execution model much better, in particular the demo applications. Issue #2120
230 lines
5.4 KiB
C++
230 lines
5.4 KiB
C++
/*
|
|
* \brief Management of subsystems
|
|
* \author Norman Feske
|
|
* \date 2014-10-02
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2014 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _SUBSYSTEM_MANAGER_H_
|
|
#define _SUBSYSTEM_MANAGER_H_
|
|
|
|
/* Genode includes */
|
|
#include <os/server.h>
|
|
#include <decorator/xml_utils.h>
|
|
|
|
/* CLI-monitor includes */
|
|
#include <cli_monitor/child.h>
|
|
|
|
namespace Launcher {
|
|
|
|
class Subsystem_manager;
|
|
using Decorator::string_attribute;
|
|
using namespace Genode;
|
|
}
|
|
|
|
|
|
class Launcher::Subsystem_manager
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Exception types
|
|
*/
|
|
class Invalid_config { };
|
|
|
|
private:
|
|
|
|
Entrypoint &_ep;
|
|
Pd_session &_pd;
|
|
|
|
size_t const _ram_preservation;
|
|
|
|
struct Child : Child_base, List<Child>::Element
|
|
{
|
|
template <typename... ARGS>
|
|
Child(ARGS &&... args) : Child_base(args...) { }
|
|
};
|
|
|
|
List<Child> _children;
|
|
|
|
void _try_response_to_resource_request()
|
|
{
|
|
for (Child *child = _children.first(); child; child = child->next())
|
|
child->try_response_to_resource_request();
|
|
}
|
|
|
|
Signal_handler<Subsystem_manager> _yield_broadcast_handler =
|
|
{ _ep, *this, &Subsystem_manager::_handle_yield_broadcast };
|
|
|
|
void _handle_yield_broadcast()
|
|
{
|
|
_try_response_to_resource_request();
|
|
|
|
/*
|
|
* XXX copied from 'cli_monitor/main.cc'
|
|
*/
|
|
|
|
/*
|
|
* Compute argument of yield request to be broadcasted to all
|
|
* processes.
|
|
*/
|
|
size_t amount = 0;
|
|
|
|
/* amount needed to reach preservation limit */
|
|
Ram::Status ram_status = _ram.status();
|
|
if (ram_status.avail < ram_status.preserve)
|
|
amount += ram_status.preserve - ram_status.avail;
|
|
|
|
/* sum of pending resource requests */
|
|
for (Child *child = _children.first(); child; child = child->next())
|
|
amount += child->requested_ram_quota();
|
|
|
|
for (Child *child = _children.first(); child; child = child->next())
|
|
child->yield(amount, true);
|
|
}
|
|
|
|
Signal_handler<Subsystem_manager> _resource_avail_handler =
|
|
{ _ep, *this, &Subsystem_manager::_handle_resource_avail };
|
|
|
|
void _handle_resource_avail()
|
|
{
|
|
_try_response_to_resource_request();
|
|
}
|
|
|
|
Signal_handler<Subsystem_manager> _yield_response_handler =
|
|
{ _ep, *this, &Subsystem_manager::_handle_yield_response };
|
|
|
|
void _handle_yield_response()
|
|
{
|
|
_try_response_to_resource_request();
|
|
}
|
|
|
|
Genode::Signal_context_capability _exited_child_sig_cap;
|
|
|
|
Ram _ram { _ram_preservation,
|
|
_yield_broadcast_handler,
|
|
_resource_avail_handler };
|
|
|
|
static Child::Binary_name _binary_name(Xml_node subsystem)
|
|
{
|
|
try {
|
|
return string_attribute(subsystem.sub_node("binary"),
|
|
"name", Child::Binary_name(""));
|
|
} catch (Xml_node::Nonexistent_sub_node) {
|
|
Genode::error("missing <binary> definition");
|
|
throw Invalid_config();
|
|
}
|
|
}
|
|
|
|
struct Ram_config { Number_of_bytes quantum, limit; };
|
|
|
|
static Ram_config _ram_config(Xml_node subsystem)
|
|
{
|
|
Number_of_bytes quantum = 0, limit = 0;
|
|
try {
|
|
subsystem.for_each_sub_node("resource", [&] (Xml_node rsc) {
|
|
if (rsc.attribute("name").has_value("RAM")) {
|
|
|
|
rsc.attribute("quantum").value(&quantum);
|
|
|
|
if (rsc.has_attribute("limit"))
|
|
rsc.attribute("limit").value(&limit);
|
|
}
|
|
});
|
|
} catch (...) {
|
|
Genode::error("invalid RAM resource declaration");
|
|
throw Invalid_config();
|
|
}
|
|
|
|
return Ram_config { quantum, limit };
|
|
}
|
|
|
|
public:
|
|
|
|
Subsystem_manager(Genode::Entrypoint &ep, Pd_session &pd,
|
|
size_t ram_preservation,
|
|
Genode::Signal_context_capability exited_child_sig_cap)
|
|
:
|
|
_ep(ep), _pd(pd), _ram_preservation(ram_preservation),
|
|
_exited_child_sig_cap(exited_child_sig_cap)
|
|
{ }
|
|
|
|
/**
|
|
* Start subsystem
|
|
*
|
|
* \throw Invalid_config
|
|
*/
|
|
void start(Xml_node subsystem)
|
|
{
|
|
Child::Binary_name const binary_name = _binary_name(subsystem);
|
|
|
|
Label const label = string_attribute(subsystem, "name",
|
|
Label(""));
|
|
|
|
Ram_config const ram_config = _ram_config(subsystem);
|
|
|
|
Genode::log("starting child '", label.string(), "'");
|
|
|
|
try {
|
|
Child *child = new (env()->heap())
|
|
Child(_ram, label, binary_name.string(),
|
|
*Genode::env()->pd_session(),
|
|
*Genode::env()->ram_session(),
|
|
Genode::env()->ram_session_cap(),
|
|
*Genode::env()->rm_session(),
|
|
ram_config.quantum, ram_config.limit,
|
|
_yield_broadcast_handler,
|
|
_exited_child_sig_cap);
|
|
|
|
/* configure child */
|
|
try {
|
|
Xml_node config_node = subsystem.sub_node("config");
|
|
child->configure(config_node.addr(), config_node.size());
|
|
} catch (...) { }
|
|
|
|
_children.insert(child);
|
|
|
|
child->start();
|
|
|
|
} catch (Parent::Service_denied) {
|
|
Genode::error("failed to start ", binary_name);
|
|
throw Invalid_config();
|
|
}
|
|
}
|
|
|
|
void kill(char const *label)
|
|
{
|
|
for (Child *c = _children.first(); c; c = c->next()) {
|
|
if (c->label() == Label(label)) {
|
|
_children.remove(c);
|
|
destroy(env()->heap(), c);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call functor for each exited child
|
|
*
|
|
* The functor takes a 'Label' as argument.
|
|
*/
|
|
template <typename FUNC>
|
|
void for_each_exited_child(FUNC const &func)
|
|
{
|
|
Child *next = nullptr;
|
|
for (Child *child = _children.first(); child; child = next) {
|
|
next = child->next();
|
|
if (child->exited())
|
|
func(Label(child->label().string()));
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif /* _SUBSYSTEM_MANAGER_H_ */
|