diff --git a/repos/os/include/os/sandbox.h b/repos/os/include/os/sandbox.h new file mode 100644 index 000000000..6e533ffae --- /dev/null +++ b/repos/os/include/os/sandbox.h @@ -0,0 +1,260 @@ +/* + * \brief Sandbox library interface + * \author Norman Feske + * \date 2020-01-09 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__OS__SANDBOX_H_ +#define _INCLUDE__OS__SANDBOX_H_ + +#include +#include +#include +#include +#include + +namespace Genode { class Sandbox; } + + +class Genode::Sandbox : Noncopyable +{ + public: + + class Local_service_base; + + template + class Local_service; + + private: + + friend class Local_service_base; + + Heap _heap; + + class Library; + + Library &_library; + + Registry _local_services { }; + + public: + + Sandbox(Env &env); + + void apply_config(Xml_node const &); +}; + + +class Genode::Sandbox::Local_service_base : public Service +{ + public: + + struct Wakeup : Interface, Noncopyable + { + virtual void wakeup_local_service() = 0; + }; + + bool abandoned() const { return false; } + + enum class Upgrade_response { CONFIRMED, DEFERRED }; + + enum class Close_response { CLOSED, DEFERRED }; + + class Request : Interface, Noncopyable + { + private: + + Session *_session_ptr = nullptr; + Capability _session_cap { }; + + bool _denied = false; + + friend class Local_service_base; + + Request(Session_state const &session) + : + resources(session_resources_from_args(session.args().string())), + label(session.label()), + diag(session_diag_from_args(session.args().string())) + { } + + /* + * Noncopyable + */ + Request(Request const &); + void operator = (Request const &); + + public: + + Session::Resources const resources; + Session::Label const label; + Session::Diag const diag; + + template + void deliver_session(ST &session) + { + _session_ptr = &session; + _session_cap = session.cap(); + } + + void deny() { _denied = false; } + }; + + private: + + Registry::Element _element; + + Session_state::Factory _session_factory; + + /** + * Async_service::Wakeup interface + */ + struct Async_wakeup : Async_service::Wakeup + { + Local_service_base::Wakeup &_wakeup; + + Async_wakeup(Local_service_base::Wakeup &wakeup) : _wakeup(wakeup) { } + + void wakeup_async_service() override + { + _wakeup.wakeup_local_service(); + } + } _async_wakeup; + + Async_service _async_service; + + /** + * Service interface + */ + void initiate_request(Session_state &session) override + { + _async_service.initiate_request(session); + } + + void wakeup() override { _async_service.wakeup(); } + + protected: + + using Resources = Session::Resources; + + struct Request_fn : Interface + { + virtual void with_requested_session(Request &) = 0; + }; + + void _for_each_requested_session(Request_fn &); + + struct Upgrade_fn : Interface + { + virtual Upgrade_response with_upgraded_session(Session &, Resources) = 0; + }; + + void _for_each_upgraded_session(Upgrade_fn &); + + struct Close_fn : Interface + { + virtual Close_response close_session(Session &) = 0; + }; + + void _for_each_session_to_close(Close_fn &); + + Id_space _server_id_space { }; + + Local_service_base(Sandbox &, Service::Name const &, Wakeup &); +}; + + +template +struct Genode::Sandbox::Local_service : private Local_service_base +{ + Local_service(Sandbox &sandbox, Wakeup &wakeup) + : Local_service_base(sandbox, ST::service_name(), wakeup) { } + + using Upgrade_response = Local_service_base::Upgrade_response; + using Close_response = Local_service_base::Close_response; + using Request = Local_service_base::Request; + + /** + * Call functor 'fn' for each session requested by the sandbox + * + * The functor is called with a 'Request &' as argument. The 'Request' + * provides the caller with information about the requested session + * ('resources', 'label', 'diag') and allows the caller to respond + * to the session request ('deliver_session', 'deny'). + */ + template + void for_each_requested_session(FN const &fn) + { + struct Untyped_fn : Local_service_base::Request_fn + { + FN const &_fn; + Untyped_fn(FN const &fn) : _fn(fn) { } + + void with_requested_session(Request &request) override + { + _fn(request); + } + } untyped_fn(fn); + + _for_each_requested_session(untyped_fn); + } + + /** + * Call functor 'fn' for each session that received a quota upgrade + * + * The functor is called with a reference to the session object (type + * 'ST') and a 'Session::Resources' object as arguments. The latter + * contains the amount of additional resources provided by the client. + * + * The functor must return an 'Upgrade_response'. + */ + template + void for_each_upgraded_session(FN const &fn) + { + struct Untyped_fn : Local_service_base::Upgrade_fn + { + FN const &_fn; + Untyped_fn(FN const &fn) : _fn(fn) { } + + Upgrade_response with_upgraded_session(Session &session, + Resources resources) override + { + return _fn(static_cast(session), resources); + } + } untyped_fn(fn); + + _for_each_upgraded_session(untyped_fn); + } + + /** + * Call functor 'fn' for each session to close + * + * The functor is called with a reference to the session object (type + * 'ST') as argument and must return a 'Close_response'. + */ + template + void for_each_session_to_close(FN const &fn) + { + struct Untyped_fn : Local_service_base::Close_fn + { + FN const &_fn; + Untyped_fn(FN const &fn) : _fn(fn) { } + + Close_response close_session(Session &session) override + { + return _fn(static_cast(session)); + } + } untyped_fn(fn); + + _for_each_session_to_close(untyped_fn); + } +}; + +#endif /* _INCLUDE__OS__SANDBOX_H_ */ diff --git a/repos/os/lib/mk/sandbox.mk b/repos/os/lib/mk/sandbox.mk new file mode 100644 index 000000000..9fe8dfab3 --- /dev/null +++ b/repos/os/lib/mk/sandbox.mk @@ -0,0 +1,7 @@ +SRC_CC = library.cc child.cc server.cc +INC_DIR += $(REP_DIR)/src/lib/sandbox +LIBS += base + +SHARED_LIB = yes + +vpath %.cc $(REP_DIR)/src/lib/sandbox diff --git a/repos/os/recipes/src/init/content.mk b/repos/os/recipes/src/init/content.mk index 81ea00679..a799bd461 100644 --- a/repos/os/recipes/src/init/content.mk +++ b/repos/os/recipes/src/init/content.mk @@ -1,2 +1,8 @@ SRC_DIR = src/init include $(GENODE_DIR)/repos/base/recipes/src/content.inc + +MIRROR_FROM_REP_DIR += src/lib/sandbox +content: $(MIRROR_FROM_REP_DIR) + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) diff --git a/repos/os/recipes/src/sandbox/content.mk b/repos/os/recipes/src/sandbox/content.mk new file mode 100644 index 000000000..0bfc4af80 --- /dev/null +++ b/repos/os/recipes/src/sandbox/content.mk @@ -0,0 +1,13 @@ +SRC_DIR = src/lib/sandbox +include $(GENODE_DIR)/repos/base/recipes/src/content.inc + +MIRROR_FROM_REP_DIR += lib/mk/sandbox.mk +content: $(MIRROR_FROM_REP_DIR) + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +content: src/lib/sandbox/target.mk + +src/lib/sandbox/target.mk: + echo "LIBS += sandbox" > $@ diff --git a/repos/os/recipes/src/sandbox/hash b/repos/os/recipes/src/sandbox/hash new file mode 100644 index 000000000..b5ba1e489 --- /dev/null +++ b/repos/os/recipes/src/sandbox/hash @@ -0,0 +1 @@ +2020-01-12 0ad1e14e664613b8ef9057c1fc91fed5f17d8a74 diff --git a/repos/os/recipes/src/sandbox/used_apis b/repos/os/recipes/src/sandbox/used_apis new file mode 100644 index 000000000..69a94c6d2 --- /dev/null +++ b/repos/os/recipes/src/sandbox/used_apis @@ -0,0 +1,3 @@ +base +os +report_session diff --git a/repos/os/run/sandbox.run b/repos/os/run/sandbox.run new file mode 100644 index 000000000..e802d4c3d --- /dev/null +++ b/repos/os/run/sandbox.run @@ -0,0 +1,27 @@ +build "core init test/sandbox app/dummy" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + +} + +build_boot_image { core ld.lib.so init test-sandbox sandbox.lib.so dummy } + +append qemu_args " -nographic " + +run_genode_until "child \"dummy\" exited with exit value 0.*\n" 20 diff --git a/repos/os/src/init/config.explicit_routing b/repos/os/src/init/config.explicit_routing deleted file mode 100644 index 9eb65154f..000000000 --- a/repos/os/src/init/config.explicit_routing +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/os/src/init/config.wildcard b/repos/os/src/init/config.wildcard deleted file mode 100644 index a25eb11af..000000000 --- a/repos/os/src/init/config.wildcard +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index f369c1b9b..47f4217b3 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -14,149 +14,38 @@ /* Genode includes */ #include #include +#include -/* local includes */ -#include -#include -#include -#include +namespace Init { -namespace Init { struct Main; } + using namespace Genode; + + struct Main; +} -struct Init::Main : State_reporter::Producer, - Child::Default_route_accessor, Child::Default_caps_accessor, - Child::Ram_limit_accessor, Child::Cap_limit_accessor +struct Init::Main { Env &_env; - Registry _parent_services { }; - Registry _child_services { }; - Child_registry _children { }; - - Heap _heap { _env.ram(), _env.rm() }; + Sandbox _sandbox { _env }; Attached_rom_dataspace _config { _env, "config" }; - Xml_node _config_xml = _config.xml(); - - Reconstructible _verbose { _config_xml }; - - Constructible _default_route { }; - - Cap_quota _default_caps { 0 }; - - unsigned _child_cnt = 0; - - static Ram_quota _preserved_ram_from_config(Xml_node config) - { - Number_of_bytes preserve { 40*sizeof(long)*1024 }; - - config.for_each_sub_node("resource", [&] (Xml_node node) { - if (node.attribute_value("name", String<16>()) == "RAM") - preserve = node.attribute_value("preserve", preserve); }); - - return Ram_quota { preserve }; - } - - Ram_quota _avail_ram() const - { - Ram_quota const preserved_ram = _preserved_ram_from_config(_config_xml); - - Ram_quota avail_ram = _env.pd().avail_ram(); - - if (preserved_ram.value > avail_ram.value) { - error("RAM preservation exceeds available memory"); - return Ram_quota { 0 }; - } - - /* deduce preserved quota from available quota */ - return Ram_quota { avail_ram.value - preserved_ram.value }; - } - - static Cap_quota _preserved_caps_from_config(Xml_node config) - { - size_t preserve = 20; - - config.for_each_sub_node("resource", [&] (Xml_node node) { - if (node.attribute_value("name", String<16>()) == "CAP") - preserve = node.attribute_value("preserve", preserve); }); - - return Cap_quota { preserve }; - } - - Cap_quota _avail_caps() const - { - Cap_quota const preserved_caps = _preserved_caps_from_config(_config_xml); - - Cap_quota avail_caps { _env.pd().avail_caps().value }; - - if (preserved_caps.value > avail_caps.value) { - error("Capability preservation exceeds available capabilities"); - return Cap_quota { 0 }; - } - - /* deduce preserved quota from available quota */ - return Cap_quota { avail_caps.value - preserved_caps.value }; - } - - /** - * Child::Ram_limit_accessor interface - */ - Ram_quota resource_limit(Ram_quota const &) const override { return _avail_ram(); } - - /** - * Child::Cap_limit_accessor interface - */ - Cap_quota resource_limit(Cap_quota const &) const override { return _avail_caps(); } - void _handle_resource_avail() { } - void produce_state_report(Xml_generator &xml, Report_detail const &detail) const override - { - if (detail.init_ram()) - xml.node("ram", [&] () { generate_ram_info (xml, _env.pd()); }); - - if (detail.init_caps()) - xml.node("caps", [&] () { generate_caps_info(xml, _env.pd()); }); - - if (detail.children()) - _children.report_state(xml, detail); - } - - /** - * Default_route_accessor interface - */ - Xml_node default_route() override - { - return _default_route.constructed() ? _default_route->xml() - : Xml_node(""); - } - - /** - * Default_caps_accessor interface - */ - Cap_quota default_caps() override { return _default_caps; } - - State_reporter _state_reporter { _env, *this }; - - Heartbeat _heartbeat { _env, _children, _state_reporter }; - Signal_handler
_resource_avail_handler { _env.ep(), *this, &Main::_handle_resource_avail }; - void _update_aliases_from_config(); - void _update_parent_services_from_config(); - void _abandon_obsolete_children(); - void _update_children_config(); - void _destroy_abandoned_parent_services(); - void _handle_config(); + void _handle_config() + { + _config.update(); + _sandbox.apply_config(_config.xml()); + } Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; - Server _server { _env, _heap, _child_services, _state_reporter }; - Main(Env &env) : _env(env) { _config.sigh(_config_handler); @@ -169,312 +58,5 @@ struct Init::Main : State_reporter::Producer, }; -void Init::Main::_update_parent_services_from_config() -{ - Xml_node const node = _config_xml.has_sub_node("parent-provides") - ? _config_xml.sub_node("parent-provides") - : Xml_node(""); - - /* remove services that are no longer present in config */ - _parent_services.for_each([&] (Parent_service &service) { - - Service::Name const name = service.name(); - - bool obsolete = true; - node.for_each_sub_node("service", [&] (Xml_node service) { - if (name == service.attribute_value("name", Service::Name())) { - obsolete = false; }}); - - if (obsolete) - service.abandon(); - }); - - /* used to prepend the list of new parent services with title */ - bool first_log = true; - - /* register new services */ - node.for_each_sub_node("service", [&] (Xml_node service) { - - Service::Name const name = service.attribute_value("name", Service::Name()); - - bool registered = false; - _parent_services.for_each([&] (Parent_service const &service) { - if (service.name() == name) - registered = true; }); - - if (!registered) { - new (_heap) Init::Parent_service(_parent_services, _env, name); - if (_verbose->enabled()) { - if (first_log) - log("parent provides"); - log(" service \"", name, "\""); - first_log = false; - } - } - }); -} - - -void Init::Main::_destroy_abandoned_parent_services() -{ - _parent_services.for_each([&] (Parent_service &service) { - if (service.abandoned()) - destroy(_heap, &service); }); -} - - -void Init::Main::_update_aliases_from_config() -{ - /* remove all known aliases */ - while (_children.any_alias()) { - Init::Alias *alias = _children.any_alias(); - _children.remove_alias(alias); - destroy(_heap, alias); - } - - /* create aliases */ - _config_xml.for_each_sub_node("alias", [&] (Xml_node alias_node) { - - try { - _children.insert_alias(new (_heap) Alias(alias_node)); } - catch (Alias::Name_is_missing) { - warning("missing 'name' attribute in '' entry"); } - catch (Alias::Child_is_missing) { - warning("missing 'child' attribute in '' entry"); } - }); -} - - -void Init::Main::_abandon_obsolete_children() -{ - _children.for_each_child([&] (Child &child) { - - bool obsolete = true; - _config_xml.for_each_sub_node("start", [&] (Xml_node node) { - if (child.has_name (node.attribute_value("name", Child_policy::Name())) - && child.has_version(node.attribute_value("version", Child::Version()))) - obsolete = false; }); - - if (obsolete) - child.abandon(); - }); -} - - -void Init::Main::_update_children_config() -{ - for (;;) { - - /* - * Children are abandoned if any of their client sessions can no longer - * be routed or result in a different route. As each child may be a - * service, an avalanche effect may occur. It stops if no update causes - * a potential side effect in one iteration over all chilren. - */ - bool side_effects = false; - - _config_xml.for_each_sub_node("start", [&] (Xml_node node) { - - Child_policy::Name const start_node_name = - node.attribute_value("name", Child_policy::Name()); - - _children.for_each_child([&] (Child &child) { - if (!child.abandoned() && child.name() == start_node_name) { - switch (child.apply_config(node)) { - case Child::NO_SIDE_EFFECTS: break; - case Child::MAY_HAVE_SIDE_EFFECTS: side_effects = true; break; - }; - } - }); - }); - - if (!side_effects) - break; - } -} - - -void Init::Main::_handle_config() -{ - bool update_state_report = false; - - _config.update(); - - _config_xml = _config.xml(); - - _verbose.construct(_config_xml); - _state_reporter.apply_config(_config_xml); - _heartbeat.apply_config(_config_xml); - - /* determine default route for resolving service requests */ - try { - _default_route.construct(_heap, _config_xml.sub_node("default-route")); } - catch (...) { } - - _default_caps = Cap_quota { 0 }; - try { - _default_caps = Cap_quota { _config_xml.sub_node("default") - .attribute_value("caps", 0UL) }; } - catch (...) { } - - Prio_levels const prio_levels = prio_levels_from_xml(_config_xml); - Affinity::Space const affinity_space = affinity_space_from_xml(_config_xml); - bool const space_defined = _config_xml.has_sub_node("affinity-space"); - - _update_aliases_from_config(); - _update_parent_services_from_config(); - _abandon_obsolete_children(); - _update_children_config(); - - /* kill abandoned children */ - _children.for_each_child([&] (Child &child) { - - if (!child.abandoned()) - return; - - /* make the child's services unavailable */ - child.destroy_services(); - child.close_all_sessions(); - update_state_report = true; - - /* destroy child once all environment sessions are gone */ - if (child.env_sessions_closed()) { - _children.remove(&child); - destroy(_heap, &child); - } - }); - - _destroy_abandoned_parent_services(); - - /* initial RAM and caps limit before starting new children */ - Ram_quota const avail_ram = _avail_ram(); - Cap_quota const avail_caps = _avail_caps(); - - /* variable used to track the RAM and caps taken by new started children */ - Ram_quota used_ram { 0 }; - Cap_quota used_caps { 0 }; - - /* create new children */ - try { - _config_xml.for_each_sub_node("start", [&] (Xml_node start_node) { - - bool exists = false; - - unsigned num_abandoned = 0; - - Child_policy::Name const child_name(start_node.attribute_value("name", Child_policy::Name())); - - _children.for_each_child([&] (Child const &child) { - if (child.name() == child_name) { - if (child.abandoned()) - num_abandoned++; - else - exists = true; - } - }); - - /* skip start node if corresponding child already exists */ - if (exists) - return; - - /* prevent queuing up abandoned children with the same name */ - if (num_abandoned > 1) - return; - - if (used_ram.value > avail_ram.value) { - error("RAM exhausted while starting child: ", child_name); - return; - } - - if (used_caps.value > avail_caps.value) { - error("capabilities exhausted while starting child: ", child_name); - return; - } - - if (!space_defined && start_node.has_sub_node("affinity")) { - warning("affinity-space configuration missing, " - "but affinity defined for child: ", child_name); - } - - try { - Init::Child &child = *new (_heap) - Init::Child(_env, _heap, *_verbose, - Init::Child::Id { ++_child_cnt }, _state_reporter, - start_node, *this, *this, _children, - Ram_quota { avail_ram.value - used_ram.value }, - Cap_quota { avail_caps.value - used_caps.value }, - *this, *this, prio_levels, affinity_space, - _parent_services, _child_services); - _children.insert(&child); - - update_state_report = true; - - /* account for the start XML node buffered in the child */ - size_t const metadata_overhead = start_node.size() - + sizeof(Init::Child); - /* track used memory and RAM limit */ - used_ram = Ram_quota { used_ram.value - + child.ram_quota().value - + metadata_overhead }; - - used_caps = Cap_quota { used_caps.value - + child.cap_quota().value }; - } - catch (Rom_connection::Rom_connection_failed) { - /* - * The binary does not exist. An error message is printed - * by the Rom_connection constructor. - */ - } - catch (Out_of_ram) { - warning("memory exhausted during child creation"); } - catch (Out_of_caps) { - warning("local capabilities exhausted during child creation"); } - catch (Child::Missing_name_attribute) { - warning("skipped startup of nameless child"); } - catch (Region_map::Region_conflict) { - warning("failed to attach dataspace to local address space " - "during child construction"); } - catch (Region_map::Invalid_dataspace) { - warning("attempt to attach invalid dataspace to local address space " - "during child construction"); } - catch (Service_denied) { - warning("failed to create session during child construction"); } - }); - } - catch (Xml_node::Nonexistent_sub_node) { error("no children to start"); } - catch (Xml_node::Invalid_syntax) { error("config has invalid syntax"); } - catch (Init::Child_registry::Alias_name_is_not_unique) { } - - /* - * Initiate RAM sessions of all new children - */ - _children.for_each_child([&] (Child &child) { - if (!child.abandoned()) - child.initiate_env_pd_session(); }); - - /* - * Initiate remaining environment sessions of all new children - */ - _children.for_each_child([&] (Child &child) { - if (!child.abandoned()) - child.initiate_env_sessions(); }); - - /* - * (Re-)distribute RAM and capability quota among the children, given their - * resource assignments and the available slack memory. We first apply - * possible downgrades to free as much resources as we can. These resources - * are then incorporated in the subsequent upgrade step. - */ - _children.for_each_child([&] (Child &child) { child.apply_downgrade(); }); - _children.for_each_child([&] (Child &child) { child.apply_upgrade(); }); - - _server.apply_config(_config_xml); - - if (update_state_report) - _state_reporter.trigger_immediate_report_update(); -} - - void Component::construct(Genode::Env &env) { static Init::Main main(env); } diff --git a/repos/os/src/init/target.mk b/repos/os/src/init/target.mk index 794f739e0..279736b2d 100644 --- a/repos/os/src/init/target.mk +++ b/repos/os/src/init/target.mk @@ -1,6 +1,11 @@ TARGET = init -SRC_CC = main.cc child.cc server.cc +SRC_CC = main.cc LIBS = base INC_DIR += $(PRG_DIR) CONFIG_XSD = config.xsd + +# statically link sandbox library to avoid dependency from sandbox.lib.so +SRC_CC += library.cc child.cc server.cc +INC_DIR += $(REP_DIR)/src/lib/sandbox +vpath %.cc $(REP_DIR)/src/lib/sandbox diff --git a/repos/os/src/init/alias.h b/repos/os/src/lib/sandbox/alias.h similarity index 82% rename from repos/os/src/init/alias.h rename to repos/os/src/lib/sandbox/alias.h index 89f07df22..d723365c6 100644 --- a/repos/os/src/init/alias.h +++ b/repos/os/src/lib/sandbox/alias.h @@ -11,15 +11,15 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__ALIAS_H_ -#define _SRC__INIT__ALIAS_H_ +#ifndef _LIB__SANDBOX__ALIAS_H_ +#define _LIB__SANDBOX__ALIAS_H_ /* local includes */ #include -namespace Init { struct Alias; } +namespace Sandbox { struct Alias; } -struct Init::Alias : List::Element +struct Sandbox::Alias : List::Element { typedef String<128> Name; typedef String<128> Child; @@ -50,4 +50,4 @@ struct Init::Alias : List::Element } }; -#endif /* _SRC__INIT__ALIAS_H_ */ +#endif /* _LIB__SANDBOX__ALIAS_H_ */ diff --git a/repos/os/src/init/child.cc b/repos/os/src/lib/sandbox/child.cc similarity index 88% rename from repos/os/src/init/child.cc rename to repos/os/src/lib/sandbox/child.cc index d21d9aef6..6f640f3be 100644 --- a/repos/os/src/init/child.cc +++ b/repos/os/src/lib/sandbox/child.cc @@ -17,7 +17,7 @@ #include -void Init::Child::destroy_services() +void Sandbox::Child::destroy_services() { _child_services.for_each([&] (Routed_service &service) { if (service.has_id_space(_session_requester.id_space())) @@ -25,8 +25,8 @@ void Init::Child::destroy_services() } -Init::Child::Apply_config_result -Init::Child::apply_config(Xml_node start_node) +Sandbox::Child::Apply_config_result +Sandbox::Child::apply_config(Xml_node start_node) { if (_state == STATE_ABANDONED || _exited) return NO_SIDE_EFFECTS; @@ -166,7 +166,7 @@ Init::Child::apply_config(Xml_node start_node) } -Init::Ram_quota Init::Child::_configured_ram_quota() const +Sandbox::Ram_quota Sandbox::Child::_configured_ram_quota() const { size_t assigned = 0; @@ -178,7 +178,7 @@ Init::Ram_quota Init::Child::_configured_ram_quota() const } -Init::Cap_quota Init::Child::_configured_cap_quota() const +Sandbox::Cap_quota Sandbox::Child::_configured_cap_quota() const { size_t const default_caps = _default_caps_accessor.default_caps().value; @@ -187,8 +187,8 @@ Init::Cap_quota Init::Child::_configured_cap_quota() const template -void Init::Child::_apply_resource_upgrade(QUOTA &assigned, QUOTA const configured, - LIMIT_ACCESSOR const &limit_accessor) +void Sandbox::Child::_apply_resource_upgrade(QUOTA &assigned, QUOTA const configured, + LIMIT_ACCESSOR const &limit_accessor) { if (configured.value <= assigned.value) return; @@ -230,7 +230,7 @@ void Init::Child::_apply_resource_upgrade(QUOTA &assigned, QUOTA const configure } -void Init::Child::apply_upgrade() +void Sandbox::Child::apply_upgrade() { /* pd_session_cap of exited child is invalid and unusable for transfers */ if (_exited) @@ -251,9 +251,9 @@ void Init::Child::apply_upgrade() template -void Init::Child::_apply_resource_downgrade(QUOTA &assigned, QUOTA const configured, - QUOTA const preserved, - CHILD_AVAIL_QUOTA_FN const &child_avail_quota_fn) +void Sandbox::Child::_apply_resource_downgrade(QUOTA &assigned, QUOTA const configured, + QUOTA const preserved, + CHILD_AVAIL_QUOTA_FN const &child_avail_quota_fn) { if (configured.value >= assigned.value) return; @@ -287,7 +287,7 @@ void Init::Child::_apply_resource_downgrade(QUOTA &assigned, QUOTA const configu } -void Init::Child::apply_downgrade() +void Sandbox::Child::apply_downgrade() { Ram_quota const configured_ram_quota = _configured_ram_quota(); Cap_quota const configured_cap_quota = _configured_cap_quota(); @@ -322,7 +322,7 @@ void Init::Child::apply_downgrade() } -void Init::Child::report_state(Xml_generator &xml, Report_detail const &detail) const +void Sandbox::Child::report_state(Xml_generator &xml, Report_detail const &detail) const { if (abandoned()) return; @@ -402,7 +402,7 @@ void Init::Child::report_state(Xml_generator &xml, Report_detail const &detail) } -void Init::Child::init(Pd_session &session, Pd_session_capability cap) +void Sandbox::Child::init(Pd_session &session, Pd_session_capability cap) { session.ref_account(_env.pd_session_cap()); @@ -425,7 +425,7 @@ void Init::Child::init(Pd_session &session, Pd_session_capability cap) } -void Init::Child::init(Cpu_session &session, Cpu_session_capability cap) +void Sandbox::Child::init(Cpu_session &session, Cpu_session_capability cap) { static size_t avail = Cpu_session::quota_lim_upscale( 100, 100); size_t const need = Cpu_session::quota_lim_upscale(_resources.cpu_quota_pc, 100); @@ -444,8 +444,9 @@ void Init::Child::init(Cpu_session &session, Cpu_session_capability cap) } -Init::Child::Route Init::Child::resolve_session_request(Service::Name const &service_name, - Session_label const &label) +Sandbox::Child::Route +Sandbox::Child::resolve_session_request(Service::Name const &service_name, + Session_label const &label) { /* check for "config" ROM request */ if (service_name == Rom_session::service_name() && @@ -550,6 +551,14 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser } catch (Service_denied) { } } + if (target.has_type("local")) { + + try { + return Route { find_service(_local_services, service_name, no_filter), + target_label, target_diag }; + } catch (Service_denied) { } + } + if (target.has_type("child")) { typedef Name_registry::Name Name; @@ -596,8 +605,8 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser } -void Init::Child::filter_session_args(Service::Name const &service, - char *args, size_t args_len) +void Sandbox::Child::filter_session_args(Service::Name const &service, + char *args, size_t args_len) { /* * Intercept CPU session requests to scale priorities @@ -655,7 +664,7 @@ void Init::Child::filter_session_args(Service::Name const &service, } -Genode::Affinity Init::Child::filter_session_affinity(Affinity const &session_affinity) +Genode::Affinity Sandbox::Child::filter_session_affinity(Affinity const &session_affinity) { Affinity::Space const &child_space = _resources.affinity.space(); Affinity::Location const &child_location = _resources.affinity.location(); @@ -680,7 +689,7 @@ Genode::Affinity Init::Child::filter_session_affinity(Affinity const &session_af } -void Init::Child::announce_service(Service::Name const &service_name) +void Sandbox::Child::announce_service(Service::Name const &service_name) { if (_verbose.enabled()) log("child \"", name(), "\" announces service \"", service_name, "\""); @@ -697,7 +706,7 @@ void Init::Child::announce_service(Service::Name const &service_name) } -void Init::Child::resource_request(Parent::Resource_args const &args) +void Sandbox::Child::resource_request(Parent::Resource_args const &args) { log("child \"", name(), "\" requests resources: ", args); @@ -706,23 +715,24 @@ void Init::Child::resource_request(Parent::Resource_args const &args) } -Init::Child::Child(Env &env, - Allocator &alloc, - Verbose const &verbose, - Id id, - Report_update_trigger &report_update_trigger, - Xml_node start_node, - Default_route_accessor &default_route_accessor, - Default_caps_accessor &default_caps_accessor, - Name_registry &name_registry, - Ram_quota ram_limit, - Cap_quota cap_limit, - Ram_limit_accessor &ram_limit_accessor, - Cap_limit_accessor &cap_limit_accessor, - Prio_levels prio_levels, - Affinity::Space const &affinity_space, - Registry &parent_services, - Registry &child_services) +Sandbox::Child::Child(Env &env, + Allocator &alloc, + Verbose const &verbose, + Id id, + Report_update_trigger &report_update_trigger, + Xml_node start_node, + Default_route_accessor &default_route_accessor, + Default_caps_accessor &default_caps_accessor, + Name_registry &name_registry, + Ram_quota ram_limit, + Cap_quota cap_limit, + Ram_limit_accessor &ram_limit_accessor, + Cap_limit_accessor &cap_limit_accessor, + Prio_levels prio_levels, + Affinity::Space const &affinity_space, + Registry &parent_services, + Registry &child_services, + Registry &local_services) : _env(env), _alloc(alloc), _verbose(verbose), _id(id), _report_update_trigger(report_update_trigger), @@ -739,6 +749,7 @@ Init::Child::Child(Env &env, _resources_clamped_to_limit((_clamp_resources(ram_limit, cap_limit), true)), _parent_services(parent_services), _child_services(child_services), + _local_services(local_services), _session_requester(_env.ep().rpc_ep(), _env.ram(), _env.rm()) { if (_verbose.enabled()) { @@ -764,4 +775,4 @@ Init::Child::Child(Env &env, } -Init::Child::~Child() { } +Sandbox::Child::~Child() { } diff --git a/repos/os/src/init/child.h b/repos/os/src/lib/sandbox/child.h similarity index 97% rename from repos/os/src/init/child.h rename to repos/os/src/lib/sandbox/child.h index 0adc97b63..4dd280341 100644 --- a/repos/os/src/init/child.h +++ b/repos/os/src/lib/sandbox/child.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__CHILD_H_ -#define _SRC__INIT__CHILD_H_ +#ifndef _LIB__SANDBOX__CHILD_H_ +#define _LIB__SANDBOX__CHILD_H_ /* Genode includes */ #include @@ -20,6 +20,7 @@ #include #include #include +#include /* local includes */ #include @@ -29,9 +30,9 @@ #include #include -namespace Init { class Child; } +namespace Sandbox { class Child; } -class Init::Child : Child_policy, Routed_service::Wakeup +class Sandbox::Child : Child_policy, Routed_service::Wakeup { public: @@ -255,12 +256,15 @@ class Init::Child : Child_policy, Routed_service::Wakeup bool const _resources_clamped_to_limit; + using Local_service = Genode::Sandbox::Local_service_base; + Registry &_parent_services; Registry &_child_services; + Registry &_local_services; struct Inline_config_rom_service : Abandonable, Dynamic_rom_session::Content_producer { - typedef Local_service Service; + typedef Genode::Local_service Service; Child &_child; @@ -480,7 +484,8 @@ class Init::Child : Child_policy, Routed_service::Wakeup Prio_levels prio_levels, Affinity::Space const &affinity_space, Registry &parent_services, - Registry &child_services); + Registry &child_services, + Registry &local_services); virtual ~Child(); @@ -645,4 +650,4 @@ class Init::Child : Child_policy, Routed_service::Wakeup } }; -#endif /* _SRC__INIT__CHILD_H_ */ +#endif /* _LIB__SANDBOX__CHILD_H_ */ diff --git a/repos/os/src/init/child_registry.h b/repos/os/src/lib/sandbox/child_registry.h similarity index 90% rename from repos/os/src/init/child_registry.h rename to repos/os/src/lib/sandbox/child_registry.h index 61ed13beb..259eb2b35 100644 --- a/repos/os/src/init/child_registry.h +++ b/repos/os/src/lib/sandbox/child_registry.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__CHILD_REGISTRY_H_ -#define _SRC__INIT__CHILD_REGISTRY_H_ +#ifndef _LIB__SANDBOX__CHILD_REGISTRY_H_ +#define _LIB__SANDBOX__CHILD_REGISTRY_H_ /* local includes */ #include @@ -20,10 +20,10 @@ #include #include -namespace Init { struct Child_registry; } +namespace Sandbox { struct Child_registry; } -class Init::Child_registry : public Name_registry, Child_list +class Sandbox::Child_registry : public Name_registry, Child_list { private: @@ -32,7 +32,7 @@ class Init::Child_registry : public Name_registry, Child_list bool _unique(const char *name) const { /* check for name clash with an existing child */ - Genode::List_element const *curr = first(); + List_element const *curr = first(); for (; curr; curr = curr->next()) if (curr->object()->has_name(name)) return false; @@ -146,4 +146,4 @@ class Init::Child_registry : public Name_registry, Child_list } }; -#endif /* _SRC__INIT__CHILD_REGISTRY_H_ */ +#endif /* _LIB__SANDBOX__CHILD_REGISTRY_H_ */ diff --git a/repos/os/src/init/heartbeat.h b/repos/os/src/lib/sandbox/heartbeat.h similarity index 89% rename from repos/os/src/init/heartbeat.h rename to repos/os/src/lib/sandbox/heartbeat.h index da9a6e1c0..64ab915ca 100644 --- a/repos/os/src/init/heartbeat.h +++ b/repos/os/src/lib/sandbox/heartbeat.h @@ -11,18 +11,18 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__HEARTBEAT_H_ -#define _SRC__INIT__HEARTBEAT_H_ +#ifndef _LIB__SANDBOX__HEARTBEAT_H_ +#define _LIB__SANDBOX__HEARTBEAT_H_ /* local includes */ #include #include #include -namespace Init { class Heartbeat; } +namespace Sandbox { class Heartbeat; } -class Init::Heartbeat : Genode::Noncopyable +class Sandbox::Heartbeat : Noncopyable { private: @@ -86,4 +86,4 @@ class Init::Heartbeat : Genode::Noncopyable } }; -#endif /* _SRC__INIT__HEARTBEAT_H_ */ +#endif /* _LIB__SANDBOX__HEARTBEAT_H_ */ diff --git a/repos/os/src/lib/sandbox/library.cc b/repos/os/src/lib/sandbox/library.cc new file mode 100644 index 000000000..39b9867b9 --- /dev/null +++ b/repos/os/src/lib/sandbox/library.cc @@ -0,0 +1,620 @@ +/* + * \brief Sandbox library + * \author Norman Feske + * \date 2020-01-10 + */ + +/* + * Copyright (C) 2010-2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include +#include +#include +#include + +struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, + ::Sandbox::Child::Default_route_accessor, + ::Sandbox::Child::Default_caps_accessor, + ::Sandbox::Child::Ram_limit_accessor, + ::Sandbox::Child::Cap_limit_accessor +{ + using Routed_service = ::Sandbox::Routed_service; + using Parent_service = ::Sandbox::Parent_service; + using Local_service = ::Genode::Sandbox::Local_service_base; + using Report_detail = ::Sandbox::Report_detail; + using Child_registry = ::Sandbox::Child_registry; + using Verbose = ::Sandbox::Verbose; + using State_reporter = ::Sandbox::State_reporter; + using Heartbeat = ::Sandbox::Heartbeat; + using Server = ::Sandbox::Server; + using Alias = ::Sandbox::Alias; + using Child = ::Sandbox::Child; + using Prio_levels = ::Sandbox::Prio_levels; + + Env &_env; + Heap &_heap; + + Registry _parent_services { }; + Registry _child_services { }; + Registry &_local_services; + Child_registry _children { }; + + Reconstructible _verbose { }; + + Constructible _default_route { }; + + Cap_quota _default_caps { 0 }; + + unsigned _child_cnt = 0; + + static Ram_quota _preserved_ram_from_config(Xml_node config) + { + Number_of_bytes preserve { 40*sizeof(long)*1024 }; + + config.for_each_sub_node("resource", [&] (Xml_node node) { + if (node.attribute_value("name", String<16>()) == "RAM") + preserve = node.attribute_value("preserve", preserve); }); + + return Ram_quota { preserve }; + } + + Ram_quota _preserved_ram { 0 }; + Cap_quota _preserved_caps { 0 }; + + Ram_quota _avail_ram() const + { + Ram_quota avail_ram = _env.pd().avail_ram(); + + if (_preserved_ram.value > avail_ram.value) { + error("RAM preservation exceeds available memory"); + return Ram_quota { 0 }; + } + + /* deduce preserved quota from available quota */ + return Ram_quota { avail_ram.value - _preserved_ram.value }; + } + + static Cap_quota _preserved_caps_from_config(Xml_node config) + { + size_t preserve = 20; + + config.for_each_sub_node("resource", [&] (Xml_node node) { + if (node.attribute_value("name", String<16>()) == "CAP") + preserve = node.attribute_value("preserve", preserve); }); + + return Cap_quota { preserve }; + } + + Cap_quota _avail_caps() const + { + Cap_quota avail_caps { _env.pd().avail_caps().value }; + + if (_preserved_caps.value > avail_caps.value) { + error("Capability preservation exceeds available capabilities"); + return Cap_quota { 0 }; + } + + /* deduce preserved quota from available quota */ + return Cap_quota { avail_caps.value - _preserved_caps.value }; + } + + /** + * Child::Ram_limit_accessor interface + */ + Ram_quota resource_limit(Ram_quota const &) const override { return _avail_ram(); } + + /** + * Child::Cap_limit_accessor interface + */ + Cap_quota resource_limit(Cap_quota const &) const override { return _avail_caps(); } + + void _handle_resource_avail() { } + + void produce_state_report(Xml_generator &xml, Report_detail const &detail) const override + { + if (detail.init_ram()) + xml.node("ram", [&] () { ::Sandbox::generate_ram_info (xml, _env.pd()); }); + + if (detail.init_caps()) + xml.node("caps", [&] () { ::Sandbox::generate_caps_info(xml, _env.pd()); }); + + if (detail.children()) + _children.report_state(xml, detail); + } + + /** + * Default_route_accessor interface + */ + Xml_node default_route() override + { + return _default_route.constructed() ? _default_route->xml() + : Xml_node(""); + } + + /** + * Default_caps_accessor interface + */ + Cap_quota default_caps() override { return _default_caps; } + + State_reporter _state_reporter { _env, *this }; + + Heartbeat _heartbeat { _env, _children, _state_reporter }; + + void _update_aliases_from_config(Xml_node const &); + void _update_parent_services_from_config(Xml_node const &); + void _abandon_obsolete_children(Xml_node const &); + void _update_children_config(Xml_node const &); + void _destroy_abandoned_parent_services(); + + Server _server { _env, _heap, _child_services, _state_reporter }; + + Library(Env &env, Heap &heap, Registry &local_services) + : + _env(env), _heap(heap), _local_services(local_services) + { } + + void apply_config(Xml_node const &); +}; + + +void Genode::Sandbox::Library::_update_parent_services_from_config(Xml_node const &config) +{ + Xml_node const node = config.has_sub_node("parent-provides") + ? config.sub_node("parent-provides") + : Xml_node(""); + + /* remove services that are no longer present in config */ + _parent_services.for_each([&] (Parent_service &service) { + + Service::Name const name = service.name(); + + bool obsolete = true; + node.for_each_sub_node("service", [&] (Xml_node service) { + if (name == service.attribute_value("name", Service::Name())) { + obsolete = false; }}); + + if (obsolete) + service.abandon(); + }); + + /* used to prepend the list of new parent services with title */ + bool first_log = true; + + /* register new services */ + node.for_each_sub_node("service", [&] (Xml_node service) { + + Service::Name const name = service.attribute_value("name", Service::Name()); + + bool registered = false; + _parent_services.for_each([&] (Parent_service const &service) { + if (service.name() == name) + registered = true; }); + + if (!registered) { + new (_heap) ::Sandbox::Parent_service(_parent_services, _env, name); + if (_verbose->enabled()) { + if (first_log) + log("parent provides"); + log(" service \"", name, "\""); + first_log = false; + } + } + }); +} + + +void Genode::Sandbox::Library::_destroy_abandoned_parent_services() +{ + _parent_services.for_each([&] (Parent_service &service) { + if (service.abandoned()) + destroy(_heap, &service); }); +} + + +void Genode::Sandbox::Library::_update_aliases_from_config(Xml_node const &config) +{ + /* remove all known aliases */ + while (_children.any_alias()) { + ::Sandbox::Alias *alias = _children.any_alias(); + _children.remove_alias(alias); + destroy(_heap, alias); + } + + /* create aliases */ + config.for_each_sub_node("alias", [&] (Xml_node alias_node) { + + try { + _children.insert_alias(new (_heap) Alias(alias_node)); } + catch (Alias::Name_is_missing) { + warning("missing 'name' attribute in '' entry"); } + catch (Alias::Child_is_missing) { + warning("missing 'child' attribute in '' entry"); } + }); +} + + +void Genode::Sandbox::Library::_abandon_obsolete_children(Xml_node const &config) +{ + _children.for_each_child([&] (Child &child) { + + bool obsolete = true; + config.for_each_sub_node("start", [&] (Xml_node node) { + if (child.has_name (node.attribute_value("name", Child_policy::Name())) + && child.has_version(node.attribute_value("version", Child::Version()))) + obsolete = false; }); + + if (obsolete) + child.abandon(); + }); +} + + +void Genode::Sandbox::Library::_update_children_config(Xml_node const &config) +{ + for (;;) { + + /* + * Children are abandoned if any of their client sessions can no longer + * be routed or result in a different route. As each child may be a + * service, an avalanche effect may occur. It stops if no update causes + * a potential side effect in one iteration over all chilren. + */ + bool side_effects = false; + + config.for_each_sub_node("start", [&] (Xml_node node) { + + Child_policy::Name const start_node_name = + node.attribute_value("name", Child_policy::Name()); + + _children.for_each_child([&] (Child &child) { + if (!child.abandoned() && child.name() == start_node_name) { + switch (child.apply_config(node)) { + case Child::NO_SIDE_EFFECTS: break; + case Child::MAY_HAVE_SIDE_EFFECTS: side_effects = true; break; + }; + } + }); + }); + + if (!side_effects) + break; + } +} + + +void Genode::Sandbox::Library::apply_config(Xml_node const &config) +{ + bool update_state_report = false; + + _preserved_ram = _preserved_ram_from_config(config); + _preserved_caps = _preserved_caps_from_config(config); + + _verbose.construct(config); + _state_reporter.apply_config(config); + _heartbeat.apply_config(config); + + /* determine default route for resolving service requests */ + try { + _default_route.construct(_heap, config.sub_node("default-route")); } + catch (...) { } + + _default_caps = Cap_quota { 0 }; + try { + _default_caps = Cap_quota { config.sub_node("default") + .attribute_value("caps", 0UL) }; } + catch (...) { } + + Prio_levels const prio_levels = ::Sandbox::prio_levels_from_xml(config); + Affinity::Space const affinity_space = ::Sandbox::affinity_space_from_xml(config); + bool const space_defined = config.has_sub_node("affinity-space"); + + _update_aliases_from_config(config); + _update_parent_services_from_config(config); + _abandon_obsolete_children(config); + _update_children_config(config); + + /* kill abandoned children */ + _children.for_each_child([&] (Child &child) { + + if (!child.abandoned()) + return; + + /* make the child's services unavailable */ + child.destroy_services(); + child.close_all_sessions(); + update_state_report = true; + + /* destroy child once all environment sessions are gone */ + if (child.env_sessions_closed()) { + _children.remove(&child); + destroy(_heap, &child); + } + }); + + _destroy_abandoned_parent_services(); + + /* initial RAM and caps limit before starting new children */ + Ram_quota const avail_ram = _avail_ram(); + Cap_quota const avail_caps = _avail_caps(); + + /* variable used to track the RAM and caps taken by new started children */ + Ram_quota used_ram { 0 }; + Cap_quota used_caps { 0 }; + + /* create new children */ + try { + config.for_each_sub_node("start", [&] (Xml_node start_node) { + + bool exists = false; + + unsigned num_abandoned = 0; + + typedef Child_policy::Name Name; + Name const child_name = start_node.attribute_value("name", Name()); + + _children.for_each_child([&] (Child const &child) { + if (child.name() == child_name) { + if (child.abandoned()) + num_abandoned++; + else + exists = true; + } + }); + + /* skip start node if corresponding child already exists */ + if (exists) + return; + + /* prevent queuing up abandoned children with the same name */ + if (num_abandoned > 1) + return; + + if (used_ram.value > avail_ram.value) { + error("RAM exhausted while starting child: ", child_name); + return; + } + + if (used_caps.value > avail_caps.value) { + error("capabilities exhausted while starting child: ", child_name); + return; + } + + if (!space_defined && start_node.has_sub_node("affinity")) { + warning("affinity-space configuration missing, " + "but affinity defined for child: ", child_name); + } + + try { + Child &child = *new (_heap) + Child(_env, _heap, *_verbose, + Child::Id { ++_child_cnt }, _state_reporter, + start_node, *this, *this, _children, + Ram_quota { avail_ram.value - used_ram.value }, + Cap_quota { avail_caps.value - used_caps.value }, + *this, *this, prio_levels, affinity_space, + _parent_services, _child_services, _local_services); + _children.insert(&child); + + update_state_report = true; + + /* account for the start XML node buffered in the child */ + size_t const metadata_overhead = start_node.size() + sizeof(Child); + + /* track used memory and RAM limit */ + used_ram = Ram_quota { used_ram.value + + child.ram_quota().value + + metadata_overhead }; + + used_caps = Cap_quota { used_caps.value + + child.cap_quota().value }; + } + catch (Rom_connection::Rom_connection_failed) { + /* + * The binary does not exist. An error message is printed + * by the Rom_connection constructor. + */ + } + catch (Out_of_ram) { + warning("memory exhausted during child creation"); } + catch (Out_of_caps) { + warning("local capabilities exhausted during child creation"); } + catch (Child::Missing_name_attribute) { + warning("skipped startup of nameless child"); } + catch (Region_map::Region_conflict) { + warning("failed to attach dataspace to local address space " + "during child construction"); } + catch (Region_map::Invalid_dataspace) { + warning("attempt to attach invalid dataspace to local address space " + "during child construction"); } + catch (Service_denied) { + warning("failed to create session during child construction"); } + }); + } + catch (Xml_node::Nonexistent_sub_node) { error("no children to start"); } + catch (Xml_node::Invalid_syntax) { error("config has invalid syntax"); } + catch (Child_registry::Alias_name_is_not_unique) { } + + /* + * Initiate RAM sessions of all new children + */ + _children.for_each_child([&] (Child &child) { + if (!child.abandoned()) + child.initiate_env_pd_session(); }); + + /* + * Initiate remaining environment sessions of all new children + */ + _children.for_each_child([&] (Child &child) { + if (!child.abandoned()) + child.initiate_env_sessions(); }); + + /* + * (Re-)distribute RAM and capability quota among the children, given their + * resource assignments and the available slack memory. We first apply + * possible downgrades to free as much resources as we can. These resources + * are then incorporated in the subsequent upgrade step. + */ + _children.for_each_child([&] (Child &child) { child.apply_downgrade(); }); + _children.for_each_child([&] (Child &child) { child.apply_upgrade(); }); + + _server.apply_config(config); + + if (update_state_report) + _state_reporter.trigger_immediate_report_update(); +} + + +/********************************* + ** Sandbox::Local_service_base ** + *********************************/ + +void Genode::Sandbox::Local_service_base::_for_each_requested_session(Request_fn &fn) +{ + _server_id_space.for_each([&] (Session_state &session) { + + if (session.phase == Session_state::CREATE_REQUESTED) { + + Request request(session); + + fn.with_requested_session(request); + + bool wakeup_client = false; + + if (request._denied) { + session.phase = Session_state::SERVICE_DENIED; + wakeup_client = true; + } + + if (request._session_ptr) { + session.local_ptr = request._session_ptr; + session.cap = request._session_cap; + session.phase = Session_state::AVAILABLE; + wakeup_client = true; + } + + if (wakeup_client && session.ready_callback) + session.ready_callback->session_ready(session); + } + }); +} + + +void Genode::Sandbox::Local_service_base::_for_each_upgraded_session(Upgrade_fn &fn) +{ + _server_id_space.for_each([&] (Session_state &session) { + + if (session.phase != Session_state::UPGRADE_REQUESTED) + return; + + if (session.local_ptr == nullptr) + return; + + bool wakeup_client = false; + + Session::Resources const amount { session.ram_upgrade, + session.cap_upgrade }; + + switch (fn.with_upgraded_session(*session.local_ptr, amount)) { + + case Upgrade_response::CONFIRMED: + session.phase = Session_state::CAP_HANDED_OUT; + wakeup_client = true; + break; + + case Upgrade_response::DEFERRED: + break; + } + + if (wakeup_client && session.ready_callback) + session.ready_callback->session_ready(session); + }); +} + + +void Genode::Sandbox::Local_service_base::_for_each_session_to_close(Close_fn &close_fn) +{ + /* + * Collection of closed sessions to be destructed via callback + * + * For asynchronous sessions, the 'Session_state' object is destructed by + * the 'Closed_callback'. We cannot issue the callback from within + * '_server_id_space.for_each()' because the destruction of 'id_at_server' + * would deadlock. Instead be collect the 'Session_state' objects to be + * called back in the 'pending_callbacks' ID space. This is possible + * because the parent ID space is not used for local services. + */ + Id_space pending_callbacks { }; + + _server_id_space.for_each([&] (Session_state &session) { + + if (session.phase != Session_state::CLOSE_REQUESTED) + return; + + if (session.local_ptr == nullptr) + return; + + switch (close_fn.close_session(*session.local_ptr)) { + + case Close_response::CLOSED: + + session.phase = Session_state::CLOSED; + + if (session.closed_callback) + session.id_at_parent.construct(session, pending_callbacks); + break; + + case Close_response::DEFERRED: + break; + } + }); + + /* + * Purge 'Session_state' objects by calling 'closed_callback' + */ + while (pending_callbacks.apply_any([&] (Session_state &session) { + + session.id_at_parent.destruct(); + + if (session.closed_callback) + session.closed_callback->session_closed(session); + })); +} + + +Genode::Sandbox::Local_service_base::Local_service_base(Sandbox &sandbox, + Name const &name, + Wakeup &wakeup) +: + Service(name), + _element(sandbox._local_services, *this), + _session_factory(sandbox._heap, Session_state::Factory::Batch_size{16}), + _async_wakeup(wakeup), + _async_service(name, _server_id_space, _session_factory, _async_wakeup) +{ } + + +/************* + ** Sandbox ** + *************/ + +void Genode::Sandbox::apply_config(Xml_node const &config) +{ + _library.apply_config(config); +} + + +Genode::Sandbox::Sandbox(Env &env) +: + _heap(env.ram(), env.rm()), + _library(*new (_heap) Library(env, _heap, _local_services)) +{ } + diff --git a/repos/os/src/init/name_registry.h b/repos/os/src/lib/sandbox/name_registry.h similarity index 75% rename from repos/os/src/init/name_registry.h rename to repos/os/src/lib/sandbox/name_registry.h index 4e85b2924..f92f9e0ea 100644 --- a/repos/os/src/init/name_registry.h +++ b/repos/os/src/lib/sandbox/name_registry.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__NAME_REGISTRY_H_ -#define _SRC__INIT__NAME_REGISTRY_H_ +#ifndef _LIB__SANDBOX__NAME_REGISTRY_H_ +#define _LIB__SANDBOX__NAME_REGISTRY_H_ /* Genode includes */ #include @@ -20,9 +20,9 @@ /* local includes */ #include -namespace Init { struct Name_registry; } +namespace Sandbox { struct Name_registry; } -struct Init::Name_registry +struct Sandbox::Name_registry { virtual ~Name_registry() { } @@ -36,4 +36,4 @@ struct Init::Name_registry virtual Name deref_alias(Name const &) = 0; }; -#endif /* _SRC__INIT__NAME_REGISTRY_H_ */ +#endif /* _LIB__SANDBOX__NAME_REGISTRY_H_ */ diff --git a/repos/os/src/init/report.h b/repos/os/src/lib/sandbox/report.h similarity index 90% rename from repos/os/src/init/report.h rename to repos/os/src/lib/sandbox/report.h index 9118e3279..971cd73b5 100644 --- a/repos/os/src/init/report.h +++ b/repos/os/src/lib/sandbox/report.h @@ -11,19 +11,19 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__REPORT_H_ -#define _SRC__INIT__REPORT_H_ +#ifndef _LIB__SANDBOX__REPORT_H_ +#define _LIB__SANDBOX__REPORT_H_ #include #include -namespace Init { +namespace Sandbox { struct Report_update_trigger; struct Report_detail; } -class Init::Report_detail : Genode::Noncopyable +class Sandbox::Report_detail : Genode::Noncopyable { private: @@ -66,7 +66,7 @@ class Init::Report_detail : Genode::Noncopyable }; -struct Init::Report_update_trigger : Interface +struct Sandbox::Report_update_trigger : Interface { /** * Trigger regular (rate-limited) report update @@ -84,4 +84,4 @@ struct Init::Report_update_trigger : Interface virtual void trigger_immediate_report_update() = 0; }; -#endif /* _SRC__INIT__REPORT_H_ */ +#endif /* _LIB__SANDBOX__REPORT_H_ */ diff --git a/repos/os/src/init/server.cc b/repos/os/src/lib/sandbox/server.cc similarity index 89% rename from repos/os/src/init/server.cc rename to repos/os/src/lib/sandbox/server.cc index ac5dd3a26..e5a83d299 100644 --- a/repos/os/src/init/server.cc +++ b/repos/os/src/lib/sandbox/server.cc @@ -19,11 +19,11 @@ #include "server.h" -/*************************** - ** Init::Server::Service ** - ***************************/ +/****************************** + ** Sandbox::Server::Service ** + **********...*****************/ -struct Init::Server::Service +struct Sandbox::Server::Service { Registry::Element _registry_element; @@ -62,8 +62,8 @@ struct Init::Server::Service }; -Init::Server::Route -Init::Server::Service::resolve_session_request(Session_label const &label) +Sandbox::Server::Route +Sandbox::Server::Service::resolve_session_request(Session_label const &label) { try { Session_policy policy(label, _service_node.xml()); @@ -95,13 +95,13 @@ Init::Server::Service::resolve_session_request(Session_label const &label) } -/****************** - ** Init::Server ** - ******************/ +/********************* + ** Sandbox::Server ** + *********************/ -Init::Server::Route -Init::Server::_resolve_session_request(Service::Name const &service_name, - Session_label const &label) +Sandbox::Server::Route +Sandbox::Server::_resolve_session_request(Service::Name const &service_name, + Session_label const &label) { Service *matching_service = nullptr; _services.for_each([&] (Service &service) { @@ -123,7 +123,7 @@ static void close_session(Genode::Session_state &session) } -void Init::Server::session_ready(Session_state &session) +void Sandbox::Server::session_ready(Session_state &session) { _report_update_trigger.trigger_report_update(); @@ -154,8 +154,8 @@ void Init::Server::session_ready(Session_state &session) } -void Init::Server::_close_session(Session_state &session, - Parent::Session_response response) +void Sandbox::Server::_close_session(Session_state &session, + Parent::Session_response response) { _report_update_trigger.trigger_report_update(); @@ -176,14 +176,14 @@ void Init::Server::_close_session(Session_state &session, } -void Init::Server::session_closed(Session_state &session) +void Sandbox::Server::session_closed(Session_state &session) { _close_session(session, Parent::SESSION_CLOSED); } -void Init::Server::_handle_create_session_request(Xml_node request, - Parent::Client::Id id) +void Sandbox::Server::_handle_create_session_request(Xml_node request, + Parent::Client::Id id) { /* * Ignore requests that are already successfully forwarded (by a prior call @@ -287,8 +287,8 @@ void Init::Server::_handle_create_session_request(Xml_node request, } -void Init::Server::_handle_upgrade_session_request(Xml_node request, - Parent::Client::Id id) +void Sandbox::Server::_handle_upgrade_session_request(Xml_node request, + Parent::Client::Id id) { _client_id_space.apply(id, [&] (Session_state &session) { @@ -321,14 +321,14 @@ void Init::Server::_handle_upgrade_session_request(Xml_node request, } -void Init::Server::_handle_close_session_request(Xml_node, Parent::Client::Id id) +void Sandbox::Server::_handle_close_session_request(Xml_node, Parent::Client::Id id) { _client_id_space.apply(id, [&] (Session_state &session) { close_session(session); }); } -void Init::Server::_handle_session_request(Xml_node request) +void Sandbox::Server::_handle_session_request(Xml_node request) { if (!request.has_attribute("id")) return; @@ -350,7 +350,7 @@ void Init::Server::_handle_session_request(Xml_node request) } -void Init::Server::_handle_session_requests() +void Sandbox::Server::_handle_session_requests() { _session_requests->update(); @@ -363,7 +363,7 @@ void Init::Server::_handle_session_requests() } -void Init::Server::apply_config(Xml_node config) +void Sandbox::Server::apply_config(Xml_node config) { _services.for_each([&] (Service &service) { destroy(_alloc, &service); }); diff --git a/repos/os/src/init/server.h b/repos/os/src/lib/sandbox/server.h similarity index 89% rename from repos/os/src/init/server.h rename to repos/os/src/lib/sandbox/server.h index 26f8a032f..44777c7ce 100644 --- a/repos/os/src/init/server.h +++ b/repos/os/src/lib/sandbox/server.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__SERVER_H_ -#define _SRC__INIT__SERVER_H_ +#ifndef _LIB__SANDBOX__SERVER_H_ +#define _LIB__SANDBOX__SERVER_H_ /* Genode includes */ #include @@ -23,11 +23,11 @@ #include "service.h" #include "state_reporter.h" -namespace Init { class Server; } +namespace Sandbox { class Server; } -class Init::Server : Session_state::Ready_callback, - Session_state::Closed_callback +class Sandbox::Server : Session_state::Ready_callback, + Session_state::Closed_callback { private: @@ -47,7 +47,7 @@ class Init::Server : Session_state::Ready_callback, Id_space _server_id_space { }; /* - * ID space of requests issued to the children of init + * ID space of requests issued to the children */ Id_space _client_id_space { }; @@ -116,4 +116,4 @@ class Init::Server : Session_state::Ready_callback, void apply_config(Xml_node); }; -#endif /* _SRC__INIT__SERVER_H_ */ +#endif /* _LIB__SANDBOX__SERVER_H_ */ diff --git a/repos/os/src/init/service.h b/repos/os/src/lib/sandbox/service.h similarity index 89% rename from repos/os/src/init/service.h rename to repos/os/src/lib/sandbox/service.h index fc08c4565..eb629a4c2 100644 --- a/repos/os/src/init/service.h +++ b/repos/os/src/lib/sandbox/service.h @@ -11,14 +11,14 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__SERVICE_H_ -#define _SRC__INIT__SERVICE_H_ +#ifndef _LIB__SANDBOX__SERVICE_H_ +#define _LIB__SANDBOX__SERVICE_H_ /* Genode includes */ #include #include -namespace Init { +namespace Sandbox { class Abandonable; class Parent_service; class Routed_service; @@ -26,7 +26,7 @@ namespace Init { } -class Init::Abandonable : Interface +class Sandbox::Abandonable : Interface { private: @@ -40,7 +40,7 @@ class Init::Abandonable : Interface }; -class Init::Parent_service : public Genode::Parent_service, public Abandonable +class Sandbox::Parent_service : public Genode::Parent_service, public Abandonable { private: @@ -57,9 +57,9 @@ class Init::Parent_service : public Genode::Parent_service, public Abandonable /** - * Init-specific representation of a child service + * Sandbox-specific representation of a child service */ -class Init::Routed_service : public Async_service, public Abandonable +class Sandbox::Routed_service : public Async_service, public Abandonable { public: @@ -148,4 +148,4 @@ class Init::Routed_service : public Async_service, public Abandonable } }; -#endif /* _SRC__INIT__SERVICE_H_ */ +#endif /* _LIB__SANDBOX__SERVICE_H_ */ diff --git a/repos/os/src/init/state_reporter.h b/repos/os/src/lib/sandbox/state_reporter.h similarity index 91% rename from repos/os/src/init/state_reporter.h rename to repos/os/src/lib/sandbox/state_reporter.h index 75024a6ec..b354e6e51 100644 --- a/repos/os/src/init/state_reporter.h +++ b/repos/os/src/lib/sandbox/state_reporter.h @@ -1,5 +1,5 @@ /* - * \brief Init-state reporting mechanism + * \brief State reporting mechanism * \author Norman Feske * \date 2017-03-03 */ @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__STATE_REPORTER_H_ -#define _SRC__INIT__STATE_REPORTER_H_ +#ifndef _LIB__SANDBOX__STATE_REPORTER_H_ +#define _LIB__SANDBOX__STATE_REPORTER_H_ /* Genode includes */ #include @@ -21,9 +21,9 @@ /* local includes */ #include "report.h" -namespace Init { class State_reporter; } +namespace Sandbox { class State_reporter; } -class Init::State_reporter : public Report_update_trigger +class Sandbox::State_reporter : public Report_update_trigger { public: @@ -149,9 +149,9 @@ class Init::State_reporter : public Report_update_trigger * If the report features information about child-RAM quotas, we * update the report periodically. Even in the absence of any other * report-triggering event, a child may consume/free RAM from its - * RAM session without any interplay with init. The periodic - * reports ensure that such changes are reflected by init's state - * report. + * RAM session without any interplay with the sandbox. The periodic + * reports ensure that such changes are reflected by the sandbox' + * state report. * * By default, the interval is one second. However, when the * 'delay_ms' attribute is defined with a higher value than that, @@ -194,4 +194,4 @@ class Init::State_reporter : public Report_update_trigger } }; -#endif /* _SRC__INIT__STATE_REPORTER_H_ */ +#endif /* _LIB__SANDBOX__STATE_REPORTER_H_ */ diff --git a/repos/os/src/init/types.h b/repos/os/src/lib/sandbox/types.h similarity index 73% rename from repos/os/src/init/types.h rename to repos/os/src/lib/sandbox/types.h index 27c0d19c3..b049d0998 100644 --- a/repos/os/src/init/types.h +++ b/repos/os/src/lib/sandbox/types.h @@ -11,14 +11,14 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__TYPES_H_ -#define _SRC__INIT__TYPES_H_ +#ifndef _LIB__SANDBOX__TYPES_H_ +#define _LIB__SANDBOX__TYPES_H_ #include #include #include -namespace Init { +namespace Sandbox { class Child; @@ -28,8 +28,7 @@ namespace Init { struct Prio_levels { long value; }; - typedef List > Child_list; + typedef List > Child_list; } -#endif /* _SRC__INIT__TYPES_H_ */ - +#endif /* _LIB__SANDBOX__TYPES_H_ */ diff --git a/repos/os/src/init/utils.h b/repos/os/src/lib/sandbox/utils.h similarity index 98% rename from repos/os/src/init/utils.h rename to repos/os/src/lib/sandbox/utils.h index f3bb084cc..7afcaebf0 100644 --- a/repos/os/src/init/utils.h +++ b/repos/os/src/lib/sandbox/utils.h @@ -11,10 +11,10 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__UTIL_H_ -#define _SRC__INIT__UTIL_H_ +#ifndef _LIB__SANDBOX__UTILS_H_ +#define _LIB__SANDBOX__UTILS_H_ -namespace Init { +namespace Sandbox { static inline void warn_insuff_quota(size_t const avail) { @@ -270,4 +270,4 @@ namespace Init { } } -#endif /* _SRC__INIT__UTIL_H_ */ +#endif /* _LIB__SANDBOX__UTILS_H_ */ diff --git a/repos/os/src/init/verbose.h b/repos/os/src/lib/sandbox/verbose.h similarity index 59% rename from repos/os/src/init/verbose.h rename to repos/os/src/lib/sandbox/verbose.h index 6a88e3616..db0c7adb2 100644 --- a/repos/os/src/init/verbose.h +++ b/repos/os/src/lib/sandbox/verbose.h @@ -1,5 +1,5 @@ /* - * \brief Init verbosity + * \brief Sandbox verbosity * \author Norman Feske * \date 2017-01-03 */ @@ -11,27 +11,33 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SRC__INIT__VERBOSE_H_ -#define _SRC__INIT__VERBOSE_H_ +#ifndef _LIB__SANDBOX__VERBOSE_H_ +#define _LIB__SANDBOX__VERBOSE_H_ +/* Genode includes */ #include #include -namespace Init { struct Verbose; } +/* local includes */ +#include + +namespace Sandbox { struct Verbose; } -class Init::Verbose : Genode::Noncopyable +class Sandbox::Verbose : Genode::Noncopyable { private: - bool _enabled; + bool _enabled = false; public: + Verbose() { } + Verbose(Genode::Xml_node config) : _enabled(config.attribute_value("verbose", false)) { } bool enabled() const { return _enabled; } }; -#endif /* _SRC__INIT__VERBOSE_H_ */ +#endif /* _LIB__SANDBOX__VERBOSE_H_ */ diff --git a/repos/os/src/test/sandbox/main.cc b/repos/os/src/test/sandbox/main.cc new file mode 100644 index 000000000..e597df2f8 --- /dev/null +++ b/repos/os/src/test/sandbox/main.cc @@ -0,0 +1,147 @@ +/* + * \brief Test for the sandbox API + * \author Norman Feske + * \date 2020-01-09 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include +#include +#include + +namespace Test { + + using namespace Genode; + + struct Log_session_component; + struct Main; +} + + +struct Test::Log_session_component : Session_object +{ + template + Log_session_component(ARGS &&... args) : Session_object(args...) { } + + size_t write(String const &msg) override + { + /* omit line break and zero termination supplied by 'msg' */ + if (msg.size() > 1) + log("local LOG service: ", Cstring(msg.string(), msg.size() - 2)); + + return 0; + } +}; + + +struct Test::Main : Sandbox::Local_service_base::Wakeup +{ + Env &_env; + + Heap _heap { _env.ram(), _env.rm() }; + + Sandbox _sandbox { _env }; + + typedef Sandbox::Local_service Log_service; + + Log_service _log_service { _sandbox, *this }; + + void _generate_sandbox_config(Xml_generator &xml) const + { + xml.node("parent-provides", [&] () { + + auto service_node = [&] (char const *name) { + xml.node("service", [&] () { + xml.attribute("name", name); }); }; + + service_node("ROM"); + service_node("CPU"); + service_node("PD"); + service_node("LOG"); + }); + + xml.node("start", [&] () { + xml.attribute("name", "dummy"); + xml.attribute("caps", 100); + xml.node("resource", [&] () { + xml.attribute("name", "RAM"); + xml.attribute("quantum", "2M"); + }); + + xml.node("config", [&] () { + xml.node("log", [&] () { + xml.attribute("string", "started"); }); + xml.node("create_log_connections", [&] () { + xml.attribute("ram_upgrade", "100K"); + xml.attribute("count", "1"); }); + xml.node("destroy_log_connections", [&] () { }); + xml.node("log", [&] () { + xml.attribute("string", "done"); }); + xml.node("exit", [&] () { }); + }); + + xml.node("route", [&] () { + + xml.node("service", [&] () { + xml.attribute("name", "LOG"); + xml.node("local", [&] () { }); }); + + xml.node("any-service", [&] () { + xml.node("parent", [&] () { }); }); + }); + }); + } + + /** + * Sandbox::Local_service_base::Wakeup interface + */ + void wakeup_local_service() override + { + _log_service.for_each_requested_session([&] (Log_service::Request &request) { + + Log_session_component &session = *new (_heap) + Log_session_component(_env.ep(), + request.resources, + request.label, + request.diag); + + request.deliver_session(session); + }); + + _log_service.for_each_upgraded_session([&] (Log_session_component &, + Session::Resources const &amount) { + log("received RAM upgrade of ", amount.ram_quota); + return Log_service::Upgrade_response::CONFIRMED; + }); + + _log_service.for_each_session_to_close([&] (Log_session_component &session) { + destroy(_heap, &session); + return Log_service::Close_response::CLOSED; + }); + } + + Main(Env &env) : _env(env) + { + Buffered_xml const config { _heap, "config", [&] (Xml_generator &xml) { + _generate_sandbox_config(xml); } }; + + config.with_xml_node([&] (Xml_node const &config) { + + log("generated config: ", config); + + _sandbox.apply_config(config); + }); + } +}; + + +void Component::construct(Genode::Env &env) { static Test::Main main(env); } + diff --git a/repos/os/src/test/sandbox/target.mk b/repos/os/src/test/sandbox/target.mk new file mode 100644 index 000000000..85baa0938 --- /dev/null +++ b/repos/os/src/test/sandbox/target.mk @@ -0,0 +1,3 @@ +TARGET = test-sandbox +SRC_CC = main.cc +LIBS += base sandbox diff --git a/repos/ports/src/app/gdb_monitor/app_child.h b/repos/ports/src/app/gdb_monitor/app_child.h index 05a011886..be8e0685d 100644 --- a/repos/ports/src/app/gdb_monitor/app_child.h +++ b/repos/ports/src/app/gdb_monitor/app_child.h @@ -21,8 +21,8 @@ #include #include -/* init private includes */ -#include +/* sandbox library private includes */ +#include /* GDB monitor includes */ #include "genode_child_resources.h" @@ -39,16 +39,16 @@ namespace Gdb_monitor { class Gdb_monitor::App_child : public Child_policy, public Async_service::Wakeup, - public Init::Report_update_trigger, - public Init::Routed_service::Pd_accessor, - public Init::Routed_service::Ram_accessor + public Sandbox::Report_update_trigger, + public Sandbox::Routed_service::Pd_accessor, + public Sandbox::Routed_service::Ram_accessor { private: typedef Registered Parent_service; - typedef Registry Parent_services; - typedef Registry Child_services; + typedef Registry Parent_services; + typedef Registry Child_services; /** * gdbserver blocks in 'select()', so a separate entrypoint is used. @@ -144,7 +144,7 @@ class Gdb_monitor::App_child : public Child_policy, _env.ram(), _env.rm() }; - Init::Server _server { _env, _alloc, _child_services, *this }; + Sandbox::Server _server { _env, _alloc, _child_services, *this }; Child *_child; @@ -173,19 +173,19 @@ class Gdb_monitor::App_child : public Child_policy, } /** - * Init::Report_update_trigger callbacks + * Sandbox::Report_update_trigger callbacks */ void trigger_report_update() override { } void trigger_immediate_report_update() override { } /** - * Init::Routed_service::Pd_accessor interface + * Sandbox::Routed_service::Pd_accessor interface */ Pd_session &pd() override { return _child->pd(); } Pd_session_capability pd_cap() const override { return _child->pd_session_cap(); } /** - * Init::Routed_service::Ram_accessor interface + * Sandbox::Routed_service::Ram_accessor interface */ Pd_session &ram() override { return _child->pd(); } Pd_session_capability ram_cap() const override { return _child->pd_session_cap(); } @@ -260,7 +260,7 @@ class Gdb_monitor::App_child : public Child_policy, ~App_child() { - _child_services.for_each([&] (Init::Routed_service &service) { + _child_services.for_each([&] (Sandbox::Routed_service &service) { destroy(_alloc, &service); }); @@ -320,13 +320,13 @@ class Gdb_monitor::App_child : public Child_policy, return; } - new (_alloc) Init::Routed_service(_child_services, - "target", - *this, *this, - _session_requester.id_space(), - _child->session_factory(), - service_name, - *this); + new (_alloc) Sandbox::Routed_service(_child_services, + "target", + *this, *this, + _session_requester.id_space(), + _child->session_factory(), + service_name, + *this); char server_config[4096]; diff --git a/repos/ports/src/app/gdb_monitor/target.mk b/repos/ports/src/app/gdb_monitor/target.mk index e07f4c800..a142a7308 100644 --- a/repos/ports/src/app/gdb_monitor/target.mk +++ b/repos/ports/src/app/gdb_monitor/target.mk @@ -97,12 +97,12 @@ vpath %.cc $(PRG_DIR)/gdbserver # parent directory of the init source is used as reference. # -INIT_PARENT_DIR = $(abspath $(dir $(call select_from_repositories,src/init/server.cc))/..) +SANDBOX_PARENT_DIR = $(abspath $(dir $(call select_from_repositories,src/lib/sandbox/server.cc))/..) -INC_DIR += $(INIT_PARENT_DIR) +INC_DIR += $(SANDBOX_PARENT_DIR) -SRC_CC += init/server.cc +SRC_CC += sandbox/server.cc -vpath init/%.cc $(INIT_PARENT_DIR) +vpath sandbox/%.cc $(SANDBOX_PARENT_DIR) CC_CXX_WARN_STRICT =