diff --git a/repos/ealanos/include/ealanos/laucher/client.h b/repos/ealanos/include/ealanos/laucher/client.h
new file mode 100644
index 0000000000..a3f3ad2819
--- /dev/null
+++ b/repos/ealanos/include/ealanos/laucher/client.h
@@ -0,0 +1,21 @@
+#ifndef __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
+#define __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
+
+#include
+#include
+
+namespace Ealan {
+ struct Launcher_client;
+ using Launcher_capability = Genode::Capability;
+}
+
+struct Ealan::Launcher_client : Genode::Rpc_client
+{
+ explicit Launcher_client(Launcher_capability session) : Rpc_client(session) {}
+
+ void launch(Genode::String<640> start_node) override {
+ call(start_node);
+ }
+};
+
+#endif // __EALANOS__INCLUDE__LAUNCHER__CLIENT_H_
\ No newline at end of file
diff --git a/repos/ealanos/include/ealanos/laucher/component.h b/repos/ealanos/include/ealanos/laucher/component.h
new file mode 100644
index 0000000000..68e9519fde
--- /dev/null
+++ b/repos/ealanos/include/ealanos/laucher/component.h
@@ -0,0 +1,37 @@
+#ifndef __EALANOS__INCLUDE__LAUNCHER__COMPONENT_H_
+#define __EALANOS__INCLUDE__LAUNCHER__COMPONENT_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+namespace Ealan {
+ class Launcher_session_component;
+ class Launcher_root;
+ class Hoitaja;
+}
+
+class Ealan::Launcher_session_component : public Genode::Session_object
+{
+ private:
+ Genode::Entrypoint &_ep;
+ Ealan::Hoitaja &_hoitaja;
+
+ public:
+ template
+ 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_
\ No newline at end of file
diff --git a/repos/ealanos/include/ealanos/laucher/connection.h b/repos/ealanos/include/ealanos/laucher/connection.h
new file mode 100644
index 0000000000..622836f577
--- /dev/null
+++ b/repos/ealanos/include/ealanos/laucher/connection.h
@@ -0,0 +1,25 @@
+#ifndef __EALANOS__INCLUDE__LAUNCHER__CONNECTION_H_
+#define __EALANOS__INCLUDE__LAUNCHER__CONNECTION_H_
+
+#include
+#include
+#include
+
+
+#include
+
+namespace Ealan {
+ struct Launcher_connection;
+}
+
+struct Ealan::Launcher_connection : Genode::Connection, Launcher_client
+{
+ Launcher_connection(Genode::Env &env, Genode::Affinity &affinity, Label const &label = Label())
+ : Connection(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_
\ No newline at end of file
diff --git a/repos/ealanos/include/ealanos/laucher/session.h b/repos/ealanos/include/ealanos/laucher/session.h
new file mode 100644
index 0000000000..830f30b8a2
--- /dev/null
+++ b/repos/ealanos/include/ealanos/laucher/session.h
@@ -0,0 +1,28 @@
+#ifndef __EALANOS__INCLUDE__LAUNCHER__SESSION_H_
+#define __EALANOS__INCLUDE__LAUNCHER__SESSION_H_
+
+#include
+#include
+#include
+
+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_
\ No newline at end of file
diff --git a/repos/ealanos/include/sandbox/sandbox.h b/repos/ealanos/include/sandbox/sandbox.h
index 1502d5b1ce..622e39f1b8 100644
--- a/repos/ealanos/include/sandbox/sandbox.h
+++ b/repos/ealanos/include/sandbox/sandbox.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
diff --git a/repos/ealanos/run/launcher_test.run b/repos/ealanos/run/launcher_test.run
new file mode 100644
index 0000000000..6d0a099d8e
--- /dev/null
+++ b/repos/ealanos/run/launcher_test.run
@@ -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 {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+}
+
+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."
\ No newline at end of file
diff --git a/repos/ealanos/src/app/launcher_test/launcher.cc b/repos/ealanos/src/app/launcher_test/launcher.cc
new file mode 100644
index 0000000000..701f345046
--- /dev/null
+++ b/repos/ealanos/src/app/launcher_test/launcher.cc
@@ -0,0 +1,65 @@
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+#define Cell(name) static const char *name = \
+ "\n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " 2022-07-20 14:30\n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ "\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)
+ ;
+}
\ No newline at end of file
diff --git a/repos/ealanos/src/app/launcher_test/target.mk b/repos/ealanos/src/app/launcher_test/target.mk
new file mode 100644
index 0000000000..2f276e6755
--- /dev/null
+++ b/repos/ealanos/src/app/launcher_test/target.mk
@@ -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
diff --git a/repos/ealanos/src/hoitaja/main.cc b/repos/ealanos/src/hoitaja/main.cc
index 03d6045a9c..231426cb1c 100644
--- a/repos/ealanos/src/hoitaja/main.cc
+++ b/repos/ealanos/src/hoitaja/main.cc
@@ -19,110 +19,193 @@
#include
#include
#include
-namespace Init {
+
+#include
+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 _resource_avail_handler {
- _env.ep(), *this, &Main::_handle_resource_avail };
+ char *_config_dataspace{nullptr};
- Constructible _reporter { };
+ void _handle_resource_avail() { }
- size_t _report_buffer_size = 0;
+ Signal_handler _resource_avail_handler {
+ _env.ep(), *this, &Hoitaja::_handle_resource_avail };
- void _handle_config()
- {
- _config.update();
+ Constructible _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;
+ 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(_heap.alloc(_config.size()*32));
+ Genode::memcpy(_config_dataspace, _config.local_addr(), _config.size());
+ _habitat_config = new (_sandbox._heap) Genode::Xml_node(_config_dataspace);
- _sandbox.apply_config(config);
- }
+ Xml_node const config = *_habitat_config;
- Signal_handler _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 _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::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::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(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(tip));
+ Genode::memcpy(dest, start_node, Genode::strlen(start_node));
+ dest += Genode::strlen(start_node);
+ Genode::memcpy(dest, "", sizeof(""));
- _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(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); }
diff --git a/repos/ealanos/src/lib/sandbox/child.cc b/repos/ealanos/src/lib/sandbox/child.cc
index 9de8c8f83f..de5dc8bf73 100644
--- a/repos/ealanos/src/lib/sandbox/child.cc
+++ b/repos/ealanos/src/lib/sandbox/child.cc
@@ -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());
diff --git a/repos/ealanos/src/lib/sandbox/child.h b/repos/ealanos/src/lib/sandbox/child.h
index 70084ed7dd..fa2ee2e6c3 100644
--- a/repos/ealanos/src/lib/sandbox/child.h
+++ b/repos/ealanos/src/lib/sandbox/child.h
@@ -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);
}
}
diff --git a/repos/ealanos/src/lib/sandbox/library.cc b/repos/ealanos/src/lib/sandbox/library.cc
index f71a641de9..e84b75a735 100644
--- a/repos/ealanos/src/lib/sandbox/library.cc
+++ b/repos/ealanos/src/lib/sandbox/library.cc
@@ -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("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(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(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(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)
diff --git a/repos/ealanos/src/lib/sandbox/utils.h b/repos/ealanos/src/lib/sandbox/utils.h
index 9962f7e1a1..cc71780bfc 100644
--- a/repos/ealanos/src/lib/sandbox/utils.h
+++ b/repos/ealanos/src/lib/sandbox/utils.h
@@ -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;
}
diff --git a/repos/os/src/init/config.xsd b/repos/os/src/init/config.xsd
index 015e2d6f8f..58e8d66e2c 100644
--- a/repos/os/src/init/config.xsd
+++ b/repos/os/src/init/config.xsd
@@ -7,6 +7,7 @@
+