mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
Added ability to dynamically start properly managed cells by issuing an RPC to Hoitaja.
This commit is contained in:
21
repos/ealanos/include/ealanos/laucher/client.h
Normal file
21
repos/ealanos/include/ealanos/laucher/client.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
|
||||
#define __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
|
||||
|
||||
#include <base/rpc_client.h>
|
||||
#include <ealanos/laucher/session.h>
|
||||
|
||||
namespace Ealan {
|
||||
struct Launcher_client;
|
||||
using Launcher_capability = Genode::Capability<Ealan::Launcher_session>;
|
||||
}
|
||||
|
||||
struct Ealan::Launcher_client : Genode::Rpc_client<Ealan::Launcher_session>
|
||||
{
|
||||
explicit Launcher_client(Launcher_capability session) : Rpc_client<Launcher_session>(session) {}
|
||||
|
||||
void launch(Genode::String<640> start_node) override {
|
||||
call<Rpc_launch>(start_node);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
|
||||
37
repos/ealanos/include/ealanos/laucher/component.h
Normal file
37
repos/ealanos/include/ealanos/laucher/component.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef __EALANOS__INCLUDE__LAUNCHER__COMPONENT_H_
|
||||
#define __EALANOS__INCLUDE__LAUNCHER__COMPONENT_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/env.h>
|
||||
#include <base/session_label.h>
|
||||
#include <base/log.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <util/xml_generator.h>
|
||||
#include <root/component.h>
|
||||
#include <base/session_object.h>
|
||||
#include <sandbox/sandbox.h>
|
||||
|
||||
#include <ealanos/laucher/session.h>
|
||||
|
||||
|
||||
namespace Ealan {
|
||||
class Launcher_session_component;
|
||||
class Launcher_root;
|
||||
class Hoitaja;
|
||||
}
|
||||
|
||||
class Ealan::Launcher_session_component : public Genode::Session_object<Ealan::Launcher_session>
|
||||
{
|
||||
private:
|
||||
Genode::Entrypoint &_ep;
|
||||
Ealan::Hoitaja &_hoitaja;
|
||||
|
||||
public:
|
||||
template <typename... ARGS>
|
||||
Launcher_session_component(Hoitaja &hoitaja, Genode::Entrypoint &ep, Genode::Session::Resources const &res, ARGS &&...args)
|
||||
: Session_object(ep, res, args...), _ep(ep), _hoitaja(hoitaja) { Genode::log("Creating new launcher session"); }
|
||||
|
||||
void launch(Genode::String<640> start_node) override;
|
||||
};
|
||||
|
||||
#endif // __EALANOS__INCLUDE__LAUNCHER__COMPONENT_H_
|
||||
25
repos/ealanos/include/ealanos/laucher/connection.h
Normal file
25
repos/ealanos/include/ealanos/laucher/connection.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __EALANOS__INCLUDE__LAUNCHER__CONNECTION_H_
|
||||
#define __EALANOS__INCLUDE__LAUNCHER__CONNECTION_H_
|
||||
|
||||
#include <base/rpc_args.h>
|
||||
#include <base/connection.h>
|
||||
#include <session/session.h>
|
||||
|
||||
|
||||
#include <ealanos/laucher/client.h>
|
||||
|
||||
namespace Ealan {
|
||||
struct Launcher_connection;
|
||||
}
|
||||
|
||||
struct Ealan::Launcher_connection : Genode::Connection<Ealan::Launcher_session>, Launcher_client
|
||||
{
|
||||
Launcher_connection(Genode::Env &env, Genode::Affinity &affinity, Label const &label = Label())
|
||||
: Connection<Launcher_session>(env, label, Genode::Ram_quota { RAM_QUOTA }, affinity, Args("")), Launcher_client(cap()) {}
|
||||
|
||||
void launch(Genode::String<640> start_node) override
|
||||
{
|
||||
Launcher_client::launch(start_node);
|
||||
}
|
||||
};
|
||||
#endif // __EALANOS__INCLUDE__LAUNCHER__CONNECTION_H_
|
||||
28
repos/ealanos/include/ealanos/laucher/session.h
Normal file
28
repos/ealanos/include/ealanos/laucher/session.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __EALANOS__INCLUDE__LAUNCHER__SESSION_H_
|
||||
#define __EALANOS__INCLUDE__LAUNCHER__SESSION_H_
|
||||
|
||||
#include <base/rpc_args.h>
|
||||
#include <session/session.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Ealan {
|
||||
struct Launcher_session;
|
||||
}
|
||||
|
||||
struct Ealan::Launcher_session : Genode::Session
|
||||
{
|
||||
static const char *service_name() { return "Launcher"; }
|
||||
|
||||
enum
|
||||
{
|
||||
CAP_QUOTA = 1,
|
||||
RAM_QUOTA = 1024
|
||||
};
|
||||
|
||||
virtual void launch(Genode::String<640> start_node) = 0;
|
||||
|
||||
GENODE_RPC(Rpc_launch, void, launch, Genode::String<640>);
|
||||
GENODE_RPC_INTERFACE(Rpc_launch);
|
||||
};
|
||||
|
||||
#endif // __EALANOS__INCLUDE__LAUNCHER__SESSION_H_
|
||||
@@ -26,6 +26,8 @@ namespace Sandbox {
|
||||
class Child;
|
||||
}
|
||||
|
||||
namespace Ealan { class Hoitaja; }
|
||||
|
||||
class Genode::Sandbox : Noncopyable
|
||||
{
|
||||
public:
|
||||
@@ -81,6 +83,7 @@ class Genode::Sandbox : Noncopyable
|
||||
private:
|
||||
|
||||
friend class Local_service_base;
|
||||
friend class Ealan::Hoitaja;
|
||||
|
||||
Heap _heap;
|
||||
|
||||
@@ -112,7 +115,7 @@ class Genode::Sandbox : Noncopyable
|
||||
*/
|
||||
void generate_state_report(Xml_generator &) const;
|
||||
|
||||
void update(::Sandbox::Child &child);
|
||||
Xml_node* update(::Sandbox::Child &child, Xml_node *config);
|
||||
};
|
||||
|
||||
class Genode::Sandbox::Local_service_base : public Service
|
||||
|
||||
79
repos/ealanos/run/launcher_test.run
Normal file
79
repos/ealanos/run/launcher_test.run
Normal file
@@ -0,0 +1,79 @@
|
||||
set build_components {
|
||||
core init hoitaja timer lib/ld lib/libm lib/libc lib/stdcxx lib/vfs app/launcher_test app/allocating_cell
|
||||
}
|
||||
|
||||
build $build_components
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config prio_levels="32" verbose="true">
|
||||
<parent-provides>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="CPU"/>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="RM"/>
|
||||
<service name="SIGNAL"/>
|
||||
<service name="TRACE"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</default-route>
|
||||
<default caps="2000"/>
|
||||
<affinity-space width="64" height="1"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="3M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
<route>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="cell1" priority="-1">
|
||||
<binary name="launcher"/>
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev">
|
||||
<log/>
|
||||
<inline name="rtc">2022-07-20 14:30</inline>
|
||||
</dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Launcher"><local/></service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
<!--
|
||||
<start name="cell2" priority="-2">
|
||||
<binary name="empty_cell"/>
|
||||
<resource name="RAM" quantum="3M"/>
|
||||
</start>
|
||||
-->
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image [build_artifacts]
|
||||
|
||||
append qemu_args " -nographic "
|
||||
|
||||
set succeeded 0
|
||||
set failed 0
|
||||
|
||||
for {set i 0} { $i < 3000 } { incr i } {
|
||||
if { ! [catch {run_genode_until ".*Changing cell .* affinity to .*0,0,32.*" 120} result ] } {
|
||||
incr succeeded
|
||||
puts "\n $succeeded of 3000 succeeded"
|
||||
kill_spawned $qemu_spawn_id
|
||||
} else {
|
||||
incr failed
|
||||
kill_spawned $qemu_spawn_id
|
||||
}
|
||||
}
|
||||
|
||||
puts "\n $succeeded of $i succeeded. $failed of $i failed."
|
||||
65
repos/ealanos/src/app/launcher_test/launcher.cc
Normal file
65
repos/ealanos/src/app/launcher_test/launcher.cc
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <libc/component.h>
|
||||
#include <base/log.h>
|
||||
#include <ealanos/laucher/connection.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
|
||||
#define Cell(name) static const char *name = \
|
||||
"<start name=\"" #name "\" priority=\"-1\">\n" \
|
||||
" <binary name=\"allocating_cell\"/>\n" \
|
||||
" <resource name=\"RAM\" quantum=\"128M\"/>\n" \
|
||||
" <config>\n" \
|
||||
" <vfs> <dir name=\"dev\">\n" \
|
||||
" <log/>\n" \
|
||||
" <inline name=\"rtc\">2022-07-20 14:30</inline>\n" \
|
||||
" </dir>\n" \
|
||||
" </vfs>\n" \
|
||||
" <libc stdout=\"/dev/log\" stderr=\"/dev/log\" rtc=\"/dev/rtc\"/>\n" \
|
||||
" </config>\n" \
|
||||
"</start>\n";
|
||||
|
||||
Cell(allocator1);
|
||||
Cell(allocator2);
|
||||
Cell(allocator3);
|
||||
Cell(allocator4);
|
||||
Cell(allocator5);
|
||||
Cell(allocator6);
|
||||
Cell(allocator7);
|
||||
Cell(allocator8);
|
||||
|
||||
static const char *cells[8] = {allocator1, allocator2, allocator3, allocator4, allocator5, allocator6, allocator7, allocator8};
|
||||
|
||||
void Libc::Component::construct(Libc::Env &env)
|
||||
{
|
||||
Genode::Thread *myself = Genode::Thread::myself();
|
||||
Genode::Affinity::Location loc = myself->affinity();
|
||||
Genode::Affinity affinity(env.cpu().affinity_space(), loc);
|
||||
|
||||
Timer::Connection _timer{env};
|
||||
|
||||
Libc::with_libc([&]()
|
||||
{
|
||||
Ealan::Launcher_connection _launcher{env, affinity};
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
||||
bool repeat = false;
|
||||
do
|
||||
{
|
||||
try {
|
||||
Genode::Xml_node xml(cells[i]);
|
||||
_launcher.launch(xml);
|
||||
} catch (Genode::Xml_attribute::Invalid_syntax) {
|
||||
Genode::error("Invalid XML start node");
|
||||
} catch (Genode::Ipc_error) {
|
||||
repeat = true;
|
||||
}
|
||||
} while (repeat);
|
||||
//_timer.msleep(1000);
|
||||
}
|
||||
Genode::log("Launched dummy"); });
|
||||
while(true)
|
||||
;
|
||||
}
|
||||
7
repos/ealanos/src/app/launcher_test/target.mk
Normal file
7
repos/ealanos/src/app/launcher_test/target.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
SRC_CC += launcher
|
||||
TARGET = launcher
|
||||
|
||||
INC_DIR += $(call select_from_repositories,src/lib/libc)/spec/x86_64
|
||||
INC_DIR += $(call select_from_repositories,src/lib/libc)
|
||||
|
||||
LIBS = base libc stdcxx
|
||||
@@ -19,110 +19,193 @@
|
||||
#include <base/log.h>
|
||||
#include <tukija/syscall-generic.h>
|
||||
#include <child.h>
|
||||
namespace Init {
|
||||
|
||||
#include <ealanos/laucher/component.h>
|
||||
namespace Ealan {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
struct Main;
|
||||
struct Hoitaja;
|
||||
}
|
||||
|
||||
|
||||
struct Init::Main : Genode::Sandbox::State_handler
|
||||
class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_service_base::Wakeup
|
||||
{
|
||||
Env &_env;
|
||||
private:
|
||||
Env &_env;
|
||||
|
||||
Genode::Sandbox _sandbox { _env, *this };
|
||||
Genode::Sandbox _sandbox { _env, *this };
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
void _handle_resource_avail() { }
|
||||
Genode::Xml_node *_habitat_config{nullptr};
|
||||
|
||||
Signal_handler<Main> _resource_avail_handler {
|
||||
_env.ep(), *this, &Main::_handle_resource_avail };
|
||||
char *_config_dataspace{nullptr};
|
||||
|
||||
Constructible<Reporter> _reporter { };
|
||||
void _handle_resource_avail() { }
|
||||
|
||||
size_t _report_buffer_size = 0;
|
||||
Signal_handler<Hoitaja> _resource_avail_handler {
|
||||
_env.ep(), *this, &Hoitaja::_handle_resource_avail };
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
Constructible<Reporter> _reporter { };
|
||||
|
||||
Xml_node const config = _config.xml();
|
||||
Genode::Rpc_entrypoint _ep{&_env.pd(), 4096, "launcher_ep", Genode::Affinity::Location(0, 0, 1, 1)};
|
||||
|
||||
bool reporter_enabled = false;
|
||||
config.with_optional_sub_node("report", [&] (Xml_node report) {
|
||||
Genode::Entrypoint _launcher_ep{_env, 4*4096, "launcher", Genode::Affinity::Location()};
|
||||
|
||||
reporter_enabled = true;
|
||||
Genode::Sliced_heap _md_alloc{_env.ram(), _env.rm()};
|
||||
|
||||
/* (re-)construct reporter whenever the buffer size is changed */
|
||||
Number_of_bytes const buffer_size =
|
||||
report.attribute_value("buffer", Number_of_bytes(4096));
|
||||
Genode::Heap _heap{_env.ram(), _env.rm()};
|
||||
|
||||
if (buffer_size != _report_buffer_size || !_reporter.constructed()) {
|
||||
_report_buffer_size = buffer_size;
|
||||
_reporter.construct(_env, "state", "state", _report_buffer_size);
|
||||
using Launcher_service = Genode::Sandbox::Local_service<Ealan::Launcher_session_component>;
|
||||
Launcher_service _launcher_service{_sandbox, *this};
|
||||
|
||||
size_t _report_buffer_size = 0;
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
|
||||
if (_habitat_config) {
|
||||
delete _habitat_config;
|
||||
delete _config_dataspace;
|
||||
}
|
||||
});
|
||||
|
||||
if (_reporter.constructed())
|
||||
_reporter->enabled(reporter_enabled);
|
||||
_config_dataspace = static_cast<char*>(_heap.alloc(_config.size()*32));
|
||||
Genode::memcpy(_config_dataspace, _config.local_addr<char*>(), _config.size());
|
||||
_habitat_config = new (_sandbox._heap) Genode::Xml_node(_config_dataspace);
|
||||
|
||||
_sandbox.apply_config(config);
|
||||
}
|
||||
Xml_node const config = *_habitat_config;
|
||||
|
||||
Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
bool reporter_enabled = false;
|
||||
config.with_optional_sub_node("report", [&] (Xml_node report) {
|
||||
|
||||
/**
|
||||
* Sandbox::State_handler interface
|
||||
*/
|
||||
void handle_sandbox_state() override
|
||||
{
|
||||
try {
|
||||
Reporter::Xml_generator xml(*_reporter, [&] () {
|
||||
_sandbox.generate_state_report(xml); });
|
||||
reporter_enabled = true;
|
||||
|
||||
/* (re-)construct reporter whenever the buffer size is changed */
|
||||
Number_of_bytes const buffer_size =
|
||||
report.attribute_value("buffer", Number_of_bytes(4096));
|
||||
|
||||
if (buffer_size != _report_buffer_size || !_reporter.constructed()) {
|
||||
_report_buffer_size = buffer_size;
|
||||
_reporter.construct(_env, "state", "state", _report_buffer_size);
|
||||
}
|
||||
});
|
||||
|
||||
if (_reporter.constructed())
|
||||
_reporter->enabled(reporter_enabled);
|
||||
|
||||
_sandbox.apply_config(config);
|
||||
}
|
||||
catch (Xml_generator::Buffer_exceeded) {
|
||||
|
||||
error("state report exceeds maximum size");
|
||||
Signal_handler<Hoitaja> _config_handler {
|
||||
_env.ep(), *this, &Hoitaja::_handle_config };
|
||||
|
||||
/* try to reflect the error condition as state report */
|
||||
try {
|
||||
Hoitaja(const Hoitaja &);
|
||||
|
||||
Hoitaja &operator=(const Hoitaja &);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Sandbox::State_handler interface
|
||||
*/
|
||||
void handle_sandbox_state() override
|
||||
{
|
||||
Genode::log("Sandbox state changed");
|
||||
try
|
||||
{
|
||||
Reporter::Xml_generator xml(*_reporter, [&] () {
|
||||
xml.attribute("error", "report buffer exceeded"); });
|
||||
_sandbox.generate_state_report(xml); });
|
||||
}
|
||||
catch (Xml_generator::Buffer_exceeded) {
|
||||
|
||||
error("state report exceeds maximum size");
|
||||
|
||||
/* try to reflect the error condition as state report */
|
||||
try {
|
||||
Reporter::Xml_generator xml(*_reporter, [&] () {
|
||||
xml.attribute("error", "report buffer exceeded"); });
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
}
|
||||
|
||||
void handle_child_state(::Sandbox::Child &child) override {
|
||||
try {
|
||||
Genode::log("Updating sandbox state");
|
||||
_sandbox.update(child);
|
||||
} catch (Genode::Quota_guard<Genode::Cap_quota>::Limit_exceeded) {
|
||||
Genode::log("Caps exceeded while handling child state");
|
||||
_env.parent().exit(1);
|
||||
void handle_child_state(::Sandbox::Child &child) override {
|
||||
bool repeat = false;
|
||||
do
|
||||
{
|
||||
try {
|
||||
Genode::log("Updating state of child ", child.name());
|
||||
_habitat_config = _sandbox.update(child, _habitat_config);
|
||||
Genode::log("Updated config length:", _habitat_config->content_size());
|
||||
}
|
||||
catch (Genode::Quota_guard<Genode::Cap_quota>::Limit_exceeded)
|
||||
{
|
||||
Genode::log("Caps exceeded while handling child state");
|
||||
_env.parent().exit(1);
|
||||
}
|
||||
catch (Genode::Ipc_error)
|
||||
{
|
||||
Genode::error("Failed to update child state for <", child.name(), ">");
|
||||
repeat = true;
|
||||
}
|
||||
} while (repeat);
|
||||
}
|
||||
}
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_config.sigh(_config_handler);
|
||||
void wakeup_local_service() override {
|
||||
_launcher_service.for_each_requested_session([&](Launcher_service::Request &req)
|
||||
{ req.deliver_session(*new (_md_alloc) Ealan::Launcher_session_component(*this, _env.ep() , req.resources, "", req.diag)); });
|
||||
}
|
||||
|
||||
Genode::log("Hoitaja starting ...");
|
||||
void add_cell_from_xml(const char *start_node){
|
||||
char *dest = nullptr;
|
||||
|
||||
/* prevent init to block for resource upgrades (never satisfied by core) */
|
||||
_env.parent().resource_avail_sigh(_resource_avail_handler);
|
||||
_habitat_config->with_raw_content([&](char const *content, Genode::size_t)
|
||||
{ dest = const_cast<char*>(content); });
|
||||
dest += _habitat_config->content_size();
|
||||
|
||||
Tukija::Tip const *tip = Tukija::Tip::tip();
|
||||
|
||||
Genode::log("Found topology model of size ", tip->length, " at ", static_cast<const void *>(tip));
|
||||
Genode::memcpy(dest, start_node, Genode::strlen(start_node));
|
||||
dest += Genode::strlen(start_node);
|
||||
Genode::memcpy(dest, "</config>", sizeof("</config>"));
|
||||
|
||||
_handle_config();
|
||||
}
|
||||
_sandbox._heap.free(_habitat_config, sizeof(Xml_node));
|
||||
|
||||
_habitat_config = new (_sandbox._heap) Xml_node(_config_dataspace);
|
||||
|
||||
bool repeat = false;
|
||||
do {
|
||||
try {
|
||||
_sandbox.apply_config(*_habitat_config);
|
||||
} catch (Genode::Ipc_error) {
|
||||
Genode::error("IPC error while creating cell. Retrying.");
|
||||
repeat = true;
|
||||
}
|
||||
} while (repeat);
|
||||
}
|
||||
|
||||
Hoitaja(Env &env) : _env(env)
|
||||
{
|
||||
_config.sigh(_config_handler);
|
||||
|
||||
Genode::log("Hoitaja starting ...");
|
||||
|
||||
/* prevent init to block for resource upgrades (never satisfied by core) */
|
||||
_env.parent().resource_avail_sigh(_resource_avail_handler);
|
||||
|
||||
Tukija::Tip const *tip = Tukija::Tip::tip();
|
||||
|
||||
Genode::log("Found topology model of size ", tip->length, " at ", static_cast<const void *>(tip));
|
||||
|
||||
_handle_config();
|
||||
}
|
||||
};
|
||||
|
||||
void Ealan::Launcher_session_component::launch(Genode::String<640> start_node)
|
||||
{
|
||||
_hoitaja.add_cell_from_xml(start_node.string());
|
||||
}
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Init::Main main(env); }
|
||||
void Component::construct(Genode::Env &env) { static Ealan::Hoitaja main(env); }
|
||||
|
||||
|
||||
@@ -779,7 +779,7 @@ Sandbox::Child::Child(Env &env,
|
||||
_local_services(local_services),
|
||||
_session_requester(_env.ep().rpc_ep(), _env.ram(), _env.rm()),
|
||||
_habitat(habitat){
|
||||
log("Creating new cell <", _unique_name, ">");
|
||||
//log("Creating new cell <", _unique_name, ">");
|
||||
if (_verbose.enabled()) {
|
||||
log("child \"", _unique_name, "\"");
|
||||
log(" RAM quota: ", _resources.effective_ram_quota());
|
||||
|
||||
@@ -739,12 +739,12 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup
|
||||
struct Resources &resources() { return _resources; }
|
||||
|
||||
void update(Genode::Affinity affinity) {
|
||||
Genode::log("Updating affinity to ", affinity.location(), " in space ", affinity.space());
|
||||
//Genode::log("Updating affinity to ", affinity.location(), " in space ", affinity.space());
|
||||
_resources.affinity = affinity;
|
||||
//Genode::log("Moving CPU session ", _env.cpu_session_cap());
|
||||
if (_child.active()) {
|
||||
Ealan::Cell_client cell(_cell_cap);
|
||||
Genode::log("Updating cell ", _cell_cap);
|
||||
//Genode::log("Updating cell ", _cell_cap);
|
||||
cell.update(affinity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +257,7 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer,
|
||||
*/
|
||||
Parent_service &create_parent_service(Service::Name const &name) override
|
||||
{
|
||||
Genode::log("Creating parent service ", name);
|
||||
return *new (_heap) Parent_service(_parent_services, _env, name);
|
||||
}
|
||||
|
||||
@@ -309,13 +310,56 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer,
|
||||
|
||||
void maintain_cells();
|
||||
|
||||
void update(Child &child) {
|
||||
Genode::Xml_node* update(Child &child, Genode::Xml_node *config) {
|
||||
if (child.exited()) {
|
||||
_children.remove(&child);
|
||||
_core_allocator->free_cores_from_cell(child);
|
||||
Genode::log("Starting new maintenance cycle");
|
||||
/* Remove child from config */
|
||||
try {
|
||||
/* Find XML node for the child */
|
||||
Xml_node node = config->sub_node("start");
|
||||
while (node.attribute_value<Genode::Child_policy::Name>("name", Genode::Child_policy::Name()) != child.name())
|
||||
{
|
||||
node = node.next("start");
|
||||
}
|
||||
|
||||
/* Get pointer to start of node in its parent's buffer and its length */
|
||||
char *node_ptr = nullptr;
|
||||
Genode::size_t len = 0;
|
||||
node.with_raw_node([&](char const *ptr, Genode::size_t size)
|
||||
{ node_ptr = const_cast<char*>(ptr); len = size; });
|
||||
char *node_end = node_ptr + len;
|
||||
|
||||
/* Determine start and end address of config's buffer */
|
||||
Genode::size_t config_len = config->size();
|
||||
char *config_ptr = nullptr;
|
||||
config->with_raw_node([&](char const *ptr, Genode::size_t)
|
||||
{ config_ptr = const_cast<char*>(ptr); });
|
||||
char *config_end = config_ptr + config_len;
|
||||
|
||||
/* Determine length of the tail after the child's start node */
|
||||
Genode::size_t tail_len = static_cast<Genode::size_t>(config_end - node_end);
|
||||
|
||||
/* Remove child's start node with memmove */
|
||||
Genode::memmove(node_ptr-1, node_end, tail_len);
|
||||
*(node_ptr + tail_len) = '\0';
|
||||
|
||||
/* Reparse changed buffer */
|
||||
Xml_node *new_config = new (_heap) Xml_node(config_ptr, config_len - len);
|
||||
_heap.free(config, sizeof(Xml_node));
|
||||
config = new_config;
|
||||
}
|
||||
catch (Genode::Xml_node::Nonexistent_sub_node)
|
||||
{
|
||||
Genode::error("Could not find child's start node");
|
||||
return config;
|
||||
};
|
||||
|
||||
Genode::log("Removed child ", child.name());
|
||||
apply_config(*config);
|
||||
maintain_cells();
|
||||
}
|
||||
return config;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -504,7 +548,7 @@ void Genode::Sandbox::Library::apply_config(Xml_node const &config)
|
||||
|
||||
_children.for_each_child([&] (Child &child) {
|
||||
|
||||
if (child.abandoned())
|
||||
if (child.abandoned())
|
||||
return;
|
||||
|
||||
if (child.restart_scheduled()) {
|
||||
@@ -557,7 +601,6 @@ void Genode::Sandbox::Library::maintain_cells()
|
||||
int lower_limit = _affinity_space->total() - _core_allocator->cores_available();
|
||||
_children.for_each_child([&](Child &child)
|
||||
{
|
||||
log(child.name(), " ram: ", child.ram_quota());
|
||||
if (!(child.is_brick()))
|
||||
_core_allocator->update(child, &xpos, &lower_limit); });
|
||||
}
|
||||
@@ -688,8 +731,9 @@ Genode::Sandbox::Local_service_base::Local_service_base(Sandbox &sandbox,
|
||||
_session_factory(sandbox._heap, Session_state::Factory::Batch_size{16}),
|
||||
_async_wakeup(wakeup),
|
||||
_async_service(name, _server_id_space, _session_factory, _async_wakeup)
|
||||
{ }
|
||||
|
||||
{
|
||||
Genode::log("Adding local service ", name);
|
||||
}
|
||||
|
||||
/*************
|
||||
** Sandbox **
|
||||
@@ -706,9 +750,9 @@ void Genode::Sandbox::generate_state_report(Xml_generator &xml) const
|
||||
_library.generate_state_report(xml);
|
||||
}
|
||||
|
||||
void Genode::Sandbox::update(::Sandbox::Child &child)
|
||||
Genode::Xml_node* Genode::Sandbox::update(::Sandbox::Child &child, Genode::Xml_node *config)
|
||||
{
|
||||
_library.update(child);
|
||||
return _library.update(child, config);
|
||||
}
|
||||
|
||||
Genode::Sandbox::Sandbox(Env &env, State_handler &state_handler, Pd_intrinsics &pd_intrinsics)
|
||||
|
||||
@@ -145,19 +145,23 @@ namespace Sandbox {
|
||||
FILTER_FN const &filter_fn)
|
||||
{
|
||||
T *service = nullptr;
|
||||
services.for_each([&] (T &s) {
|
||||
|
||||
services.for_each([&](T &s)
|
||||
{
|
||||
if (service || s.name() != name || filter_fn(s))
|
||||
return;
|
||||
|
||||
service = &s;
|
||||
});
|
||||
service = &s; });
|
||||
|
||||
if (!service)
|
||||
if (!service) {
|
||||
Genode::log("Service ", name, " not found");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
if (service->abandoned())
|
||||
{
|
||||
Genode::log("Service ", name, " abandoned.");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
return *service;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<xs:choice minOccurs="1" maxOccurs="3">
|
||||
<xs:element name="parent"/>
|
||||
<xs:element name="any-child"/>
|
||||
<xs:element name="local"/>
|
||||
<xs:element name="child">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string" />
|
||||
|
||||
Reference in New Issue
Block a user