diff --git a/repos/ealanos/include/ealanos/shell/client.h b/repos/ealanos/include/ealanos/shell/client.h
new file mode 100644
index 0000000000..e045cc93b4
--- /dev/null
+++ b/repos/ealanos/include/ealanos/shell/client.h
@@ -0,0 +1,27 @@
+#ifndef __EALANOS__INCLUDE__SHELL__CLIENT_H_
+#define __EALANOS__INCLUDE__SHELL__CLIENT_H_
+
+#include "base/capability.h"
+#include "base/ram_allocator.h"
+#include "region_map/region_map.h"
+#include
+#include
+
+namespace Ealan
+{
+ namespace Shell
+ {
+ using Capability = Genode::Capability;
+
+ struct Client : Genode::Rpc_client {
+ explicit Client(Capability cap) : Genode::Rpc_client(cap) { }
+
+ Genode::Ram_dataspace_capability connect() override { return call(); }
+
+ void disconnect() override { call(); }
+ void commit() override { call(); }
+ };
+ } // namespace Shell
+}
+
+#endif
\ No newline at end of file
diff --git a/repos/ealanos/include/ealanos/shell/component.h b/repos/ealanos/include/ealanos/shell/component.h
new file mode 100644
index 0000000000..2ec94ec542
--- /dev/null
+++ b/repos/ealanos/include/ealanos/shell/component.h
@@ -0,0 +1,43 @@
+#ifndef __EALANOS__INCLUDE__SHELL__COMPONENT_H_
+#define __EALANOS__INCLUDE__SHELL__COMPONENT_H_
+
+#include "base/capability.h"
+#include "base/entrypoint.h"
+#include "base/ram_allocator.h"
+#include "region_map/region_map.h"
+#include
+#include
+#include
+#include
+
+#include
+
+namespace Ealan {
+ class Hoitaja;
+
+ namespace Shell {
+ class Session_component : public Genode::Session_object
+ {
+ private:
+
+ Genode::Entrypoint &_ep;
+ Ealan::Hoitaja &_hoitaja;
+
+ public:
+
+ template
+ Session_component(Hoitaja &hoitaja, Genode::Entrypoint &ep,
+ Genode::Session::Resources const &res, ARGS &&...args)
+ : Genode::Session_object(ep, res, args...), _ep(ep), _hoitaja(hoitaja)
+ {
+ }
+
+ Genode::Ram_dataspace_capability connect() override;
+ void disconnect() override;
+
+ void commit() override;
+ };
+ }
+} // namespace Ealan
+
+#endif
\ No newline at end of file
diff --git a/repos/ealanos/include/ealanos/shell/connection.h b/repos/ealanos/include/ealanos/shell/connection.h
new file mode 100644
index 0000000000..aadbdd19f7
--- /dev/null
+++ b/repos/ealanos/include/ealanos/shell/connection.h
@@ -0,0 +1,33 @@
+#ifndef __EALANOS__INCLUDE__SHELL__CONNECTION_H_
+#define __EALANOS__INCLUDE__SHELL__CONNECTION_H_
+
+#include "base/affinity.h"
+#include "base/capability.h"
+#include "base/ram_allocator.h"
+#include "region_map/region_map.h"
+#include
+#include
+
+#include
+
+namespace Ealan
+{
+ namespace Shell
+ {
+ struct Connection : Genode::Connection, Client {
+ Connection(Genode::Env &env, Genode::Affinity affinity = Genode::Affinity(Genode::Affinity::Space(1,1), Genode::Affinity::Location(0,0)),
+ Label const &label = Label())
+ : Genode::Connection(env, label, Genode::Ram_quota{RAM_QUOTA},
+ affinity, Args("")), Client(cap())
+ {
+ }
+
+ Genode::Ram_dataspace_capability connect() override { return Client::connect(); }
+
+ void disconnect() override { Client::disconnect(); }
+ void commit() override { Client::commit(); }
+
+ };
+ } // namespace Shell
+} // namespace Ealan
+#endif
diff --git a/repos/ealanos/include/ealanos/shell/session.h b/repos/ealanos/include/ealanos/shell/session.h
new file mode 100644
index 0000000000..81bb952060
--- /dev/null
+++ b/repos/ealanos/include/ealanos/shell/session.h
@@ -0,0 +1,59 @@
+#ifndef __EALANOS__INCLUDE__SHELL__SESSION_H_
+#define __EALANOS__INCLUDE__SHELL__SESSION_H_
+
+#include "base/capability.h"
+#include "base/ram_allocator.h"
+#include "base/rpc.h"
+#include "dataspace/capability.h"
+#include "region_map/region_map.h"
+#include
+#include
+#include
+
+namespace Ealan
+{
+ namespace Shell
+ {
+ struct Session : Genode::Session
+ {
+ static const char *service_name() { return "Shell"; }
+
+ enum { CAP_QUOTA = 2, RAM_QUOTA = 1024 };
+
+ /**
+ * @brief Connect to a shell session by supplying a region map
+ *
+ * @param rm - region map used for mapping the habitat's config to the client's virtual address space
+ * @return true - Mapping was successful
+ * @return false - An invalid region map was supplied or the mapping failed (e.g. lack of quota or caps)
+ */
+ virtual Genode::Ram_dataspace_capability connect() = 0;
+
+ /**
+ * @brief Disconnects a client's shell session
+ *
+ */
+ virtual void disconnect() = 0;
+
+ /**
+ * @brief Commit a change to the habitat's configuration made by the client.
+ * @details In order to let changes made in the habitat's configuration take effect, the
+ * changes must be reported by using this method. This will cause Hoitaja to
+ * re-read its configuration and applying any changes, such as creating new cells, destroying cells etc.
+ */
+ virtual void commit() = 0;
+
+ /*****************
+ * RPC interface *
+ *****************/
+
+ GENODE_RPC(Rpc_connect, Genode::Ram_dataspace_capability, connect);
+ GENODE_RPC(Rpc_disconnect, void, disconnect);
+ GENODE_RPC(Rpc_commit, void, commit);
+
+ GENODE_RPC_INTERFACE(Rpc_connect, Rpc_disconnect, Rpc_commit);
+ };
+ } // namespace Shell
+} // namespace Ealan
+
+#endif
diff --git a/repos/ealanos/src/hoitaja/main.cc b/repos/ealanos/src/hoitaja/main.cc
index 231426cb1c..306b930319 100644
--- a/repos/ealanos/src/hoitaja/main.cc
+++ b/repos/ealanos/src/hoitaja/main.cc
@@ -12,8 +12,14 @@
*/
/* Genode includes */
+#include "base/capability.h"
+#include "base/ipc.h"
+#include "base/ram_allocator.h"
+#include "region_map/client.h"
+#include "region_map/region_map.h"
#include
#include
+#include
#include
#include
#include
@@ -21,6 +27,10 @@
#include
#include
+
+#include
+
+#include
namespace Ealan {
using namespace Genode;
@@ -31,7 +41,10 @@ namespace Ealan {
class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_service_base::Wakeup
{
- private:
+ private:
+
+ friend class Ealan::Shell::Session_component;
+
Env &_env;
Genode::Sandbox _sandbox { _env, *this };
@@ -40,6 +53,7 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
Genode::Xml_node *_habitat_config{nullptr};
+ Genode::Ram_dataspace_capability _config_ds{};
char *_config_dataspace{nullptr};
void _handle_resource_avail() { }
@@ -49,21 +63,23 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
Constructible _reporter { };
- Genode::Rpc_entrypoint _ep{&_env.pd(), 4096, "launcher_ep", Genode::Affinity::Location(0, 0, 1, 1)};
-
- Genode::Entrypoint _launcher_ep{_env, 4*4096, "launcher", Genode::Affinity::Location()};
-
Genode::Sliced_heap _md_alloc{_env.ram(), _env.rm()};
Genode::Heap _heap{_env.ram(), _env.rm()};
+ Genode::Mutex _config_lock{};
+
using Launcher_service = Genode::Sandbox::Local_service;
Launcher_service _launcher_service{_sandbox, *this};
+ using Shell_service = Genode::Sandbox::Local_service;
+ Shell_service _shell_service{_sandbox, *this};
+
size_t _report_buffer_size = 0;
void _handle_config()
{
+ _config_lock.acquire();
_config.update();
if (_habitat_config) {
@@ -71,7 +87,19 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
delete _config_dataspace;
}
- _config_dataspace = static_cast(_heap.alloc(_config.size()*32));
+ _config_ds = _env.ram().alloc(32 * _config.size());
+
+ Genode::Region_map::Attr attr{};
+ attr.writeable = true;
+
+ _config_dataspace = _env.rm()
+ .attach(_config_ds, attr)
+ .convert(
+ [&](Genode::Region_map::Range r) {
+ return reinterpret_cast(r.start);
+ },
+ [&](Genode::Region_map::Attach_error) { return nullptr; });
+ //_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);
@@ -96,6 +124,7 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
_reporter->enabled(reporter_enabled);
_sandbox.apply_config(config);
+ _config_lock.release();
}
Signal_handler _config_handler {
@@ -136,31 +165,41 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
do
{
try {
+ _config_lock.acquire();
Genode::log("Updating state of child ", child.name());
_habitat_config = _sandbox.update(child, _habitat_config);
Genode::log("Updated config length:", _habitat_config->content_size());
+ _config_lock.release();
}
catch (Genode::Quota_guard::Limit_exceeded)
{
Genode::log("Caps exceeded while handling child state");
+ _config_lock.release();
_env.parent().exit(1);
}
catch (Genode::Ipc_error)
{
Genode::error("Failed to update child state for <", child.name(), ">");
+ _config_lock.release();
repeat = true;
}
} while (repeat);
}
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)); });
+ _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));
+ });
+ _shell_service.for_each_requested_session([&](Shell_service::Request &req) {
+ req.deliver_session(*new (_md_alloc) Ealan::Shell::Session_component(*this, _env.ep(), req.resources, "", req.diag));
+ });
}
void add_cell_from_xml(const char *start_node){
char *dest = nullptr;
+ _config_lock.acquire();
_habitat_config->with_raw_content([&](char const *content, Genode::size_t)
{ dest = const_cast(content); });
dest += _habitat_config->content_size();
@@ -183,8 +222,27 @@ class Ealan::Hoitaja : Genode::Sandbox::State_handler, Genode::Sandbox::Local_se
repeat = true;
}
} while (repeat);
+ _config_lock.release();
}
+ void update_config()
+ {
+ _config_lock.acquire();
+ _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::warning("IPC error while applying new configuration.");
+ repeat = true;
+ }
+ } while (repeat);
+ _config_lock.release();
+ }
+
Hoitaja(Env &env) : _env(env)
{
_config.sigh(_config_handler);
@@ -207,5 +265,26 @@ void Ealan::Launcher_session_component::launch(Genode::String<640> start_node)
_hoitaja.add_cell_from_xml(start_node.string());
}
+/*******************************
+ * Shell server implementation *
+ *******************************/
+
+Genode::Ram_dataspace_capability
+ Ealan::Shell::Session_component::connect()
+{
+ return _hoitaja._config_ds;
+}
+
+void Ealan::Shell::Session_component::disconnect()
+{
+}
+
+void Ealan::Shell::Session_component::commit()
+{
+ _hoitaja.update_config();
+}
+
+
+
void Component::construct(Genode::Env &env) { static Ealan::Hoitaja main(env); }