diff --git a/repos/os/include/sandbox/child.h b/repos/os/include/sandbox/child.h index 890e0344b8..ad3d972278 100644 --- a/repos/os/include/sandbox/child.h +++ b/repos/os/include/sandbox/child.h @@ -36,6 +36,44 @@ namespace Sandbox { class Child; } class Sandbox::Child : Child_policy, Routed_service::Wakeup { public: + /** + * Resources assigned to the child + */ + struct Resources + { + long prio_levels_log2; + long priority; + Affinity affinity; + Ram_quota assigned_ram_quota; + Cap_quota assigned_cap_quota; + Cpu_quota assigned_cpu_quota; + + Ram_quota effective_ram_quota() const + { + return Genode::Child::effective_quota(assigned_ram_quota); + } + + Cap_quota effective_cap_quota() const + { + /* capabilities consumed by 'Genode::Child' */ + Cap_quota const effective = + Genode::Child::effective_quota(assigned_cap_quota); + + /* capabilities additionally consumed by init */ + enum { + STATIC_COSTS = 1 /* possible heap backing-store + allocation for session object */ + + 1 /* buffered XML start node */ + + 2 /* dynamic ROM for config */ + + 2 /* dynamic ROM for session requester */ + }; + + if (effective.value < STATIC_COSTS) + return Cap_quota{0}; + + return Cap_quota{effective.value - STATIC_COSTS}; + } + }; typedef String<80> Version; @@ -73,7 +111,7 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup enum class Sample_state_result { CHANGED, UNCHANGED }; - private: + protected: friend class Child_registry; @@ -109,7 +147,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup * The child is no longer referenced by config model and can * safely be destructed. */ - ABANDONED + ABANDONED, + }; State _state = State::INITIAL; @@ -202,48 +241,11 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup return _heartbeat_enabled && (_state == State::ALIVE); } - /** - * Resources assigned to the child - */ - struct Resources - { - long prio_levels_log2; - long priority; - Affinity affinity; - Ram_quota assigned_ram_quota; - Cap_quota assigned_cap_quota; - Cpu_quota assigned_cpu_quota; - - Ram_quota effective_ram_quota() const - { - return Genode::Child::effective_quota(assigned_ram_quota); - } - - Cap_quota effective_cap_quota() const - { - /* capabilities consumed by 'Genode::Child' */ - Cap_quota const effective = - Genode::Child::effective_quota(assigned_cap_quota); - - /* capabilities additionally consumed by init */ - enum { - STATIC_COSTS = 1 /* possible heap backing-store - allocation for session object */ - + 1 /* buffered XML start node */ - + 2 /* dynamic ROM for config */ - + 2 /* dynamic ROM for session requester */ - }; - - if (effective.value < STATIC_COSTS) - return Cap_quota{0}; - - return Cap_quota{effective.value - STATIC_COSTS}; - } - }; static Resources _resources_from_start_node(Xml_node start_node, Prio_levels prio_levels, Affinity::Space const &affinity_space, + Affinity::Location const &location, Cap_quota default_cap_quota) { unsigned cpu_percent = 0; @@ -269,7 +271,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup return Resources { log2(prio_levels.value), priority_from_xml(start_node, prio_levels), Affinity(affinity_space, - affinity_location_from_xml(affinity_space, start_node)), + (location.xpos() == -1 ? affinity_location_from_xml(affinity_space, start_node) : location)), + //affinity_location_from_xml(affinity_space, start_node)), Ram_quota { ram_bytes }, Cap_quota { caps }, Cpu_quota { cpu_percent } }; @@ -555,6 +558,7 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup Cpu_quota_transfer &cpu_quota_transfer, Prio_levels prio_levels, Affinity::Space const &affinity_space, + Affinity::Location const &location, Registry &parent_services, Registry &child_services, Registry &local_services); @@ -674,6 +678,7 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup Sample_state_result sample_state(); + /**************************** ** Child-policy interface ** ****************************/ diff --git a/repos/os/include/sandbox/library.h b/repos/os/include/sandbox/library.h index 34992ff068..3efdf7483c 100644 --- a/repos/os/include/sandbox/library.h +++ b/repos/os/include/sandbox/library.h @@ -13,6 +13,7 @@ #include #include +#pragma once namespace Sandbox { class Library; } @@ -200,7 +201,7 @@ public: void _update_parent_services_from_config(Xml_node const &); void _update_children_config(Xml_node const &); void _destroy_abandoned_parent_services(); - void _destroy_abandoned_children(); + virtual void _destroy_abandoned_children(); Server _server { _env, _heap, _child_services, _state_reporter }; diff --git a/repos/os/src/lib/sandbox/alias.h b/repos/os/src/lib/sandbox/alias.h deleted file mode 100644 index 7f05a5052d..0000000000 --- a/repos/os/src/lib/sandbox/alias.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * \brief Representation of an alias for a child - * \author Norman Feske - * \date 2010-04-27 - */ - -/* - * Copyright (C) 2010-2017 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 _LIB__SANDBOX__ALIAS_H_ -#define _LIB__SANDBOX__ALIAS_H_ - -/* local includes */ -#include - -namespace Sandbox { struct Alias; } - -struct Sandbox::Alias : List::Element, Noncopyable -{ - typedef Child_policy::Name Name; - typedef Child_policy::Name Child; - - Name const name; - - Child child { }; /* defined by 'update' */ - - Alias(Name const &name) : name(name) { } - - class Child_attribute_missing : Exception { }; - - /* - * \throw Child_attribute_missing - */ - void update(Xml_node const &alias) - { - if (!alias.has_attribute("child")) - warning("alias node \"", name, "\" lacks child attribute"); - - child = alias.attribute_value("child", Child()); - } -}; - -#endif /* _LIB__SANDBOX__ALIAS_H_ */ diff --git a/repos/os/src/lib/sandbox/child.cc b/repos/os/src/lib/sandbox/child.cc index cc13eac8ed..281b85368b 100644 --- a/repos/os/src/lib/sandbox/child.cc +++ b/repos/os/src/lib/sandbox/child.cc @@ -679,6 +679,7 @@ Genode::Affinity Sandbox::Child::filter_session_affinity(Affinity const &session Affinity::Space const &child_space = _resources.affinity.space(); Affinity::Location const &child_location = _resources.affinity.location(); + Genode::log("[Hoitaja->", this->name(),"] Using cell's affinity ", child_location, " in ", child_space, " for filtering session affinity."); /* check if no valid affinity space was specified */ if (session_affinity.space().total() == 0) return Affinity(child_space, child_location); @@ -686,18 +687,24 @@ Genode::Affinity Sandbox::Child::filter_session_affinity(Affinity const &session Affinity::Space const &session_space = session_affinity.space(); Affinity::Location const &session_location = session_affinity.location(); + Genode::log("Scaling to session affinity ", session_location, " in ", session_space); + /* scale resolution of resulting space */ Affinity::Space space(child_space.multiply(session_space)); Affinity::Location child_session(child_location.xpos(), child_location.ypos(), child_location.width() * session_location.width(), child_location.height() * session_location.height()); + Genode::log("Scaled session affinity to ", child_session, " in ", space); + /* subordinate session affinity to child affinity subspace */ Affinity::Location location(child_session .multiply_position(session_space) .transpose(session_location.xpos() * child_location.width(), session_location.ypos() * child_location.height())); + Genode::log("Session affinity subordinated to ", location, " in ", space); + return Affinity(space, location); } @@ -743,6 +750,7 @@ Sandbox::Child::Child(Env &env, Cpu_quota_transfer &cpu_quota_transfer, Prio_levels prio_levels, Affinity::Space const &affinity_space, + Affinity::Location const &location, Registry &parent_services, Registry &child_services, Registry &local_services) @@ -759,7 +767,7 @@ Sandbox::Child::Child(Env &env, _cpu_quota_transfer(cpu_quota_transfer), _name_registry(name_registry), _heartbeat_enabled(start_node.has_sub_node("heartbeat")), - _resources(_resources_from_start_node(start_node, prio_levels, affinity_space, + _resources(_resources_from_start_node(start_node, prio_levels, affinity_space, location, default_caps_accessor.default_caps())), _parent_services(parent_services), _child_services(child_services), diff --git a/repos/os/src/lib/sandbox/child.h b/repos/os/src/lib/sandbox/child.h deleted file mode 100644 index b4a612624a..0000000000 --- a/repos/os/src/lib/sandbox/child.h +++ /dev/null @@ -1,742 +0,0 @@ -/* - * \brief Child representation - * \author Norman Feske - * \date 2010-05-04 - */ - -/* - * Copyright (C) 2010-2017 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 _LIB__SANDBOX__CHILD_H_ -#define _LIB__SANDBOX__CHILD_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include - -/* local includes */ -#include -#include -#include -#include -#include -#include -#include - -namespace Sandbox { class Child; } - -class Sandbox::Child : Child_policy, Routed_service::Wakeup -{ - public: - - typedef String<80> Version; - - /** - * Exception types - */ - struct Child_name_is_not_unique : Exception { }; - struct Missing_name_attribute : Exception { }; - - /** - * Unique ID of the child, solely used for diagnostic purposes - */ - struct Id { unsigned value; }; - - struct Default_route_accessor : Interface { virtual Xml_node default_route() = 0; }; - struct Default_caps_accessor : Interface { virtual Cap_quota default_caps() = 0; }; - - template - struct Resource_limit_accessor : Interface - { - /* - * The argument is unused. It exists solely as an overload selector. - */ - virtual QUOTA resource_limit(QUOTA const &) const = 0; - }; - - typedef Resource_limit_accessor Ram_limit_accessor; - typedef Resource_limit_accessor Cap_limit_accessor; - typedef Resource_limit_accessor Cpu_limit_accessor; - - struct Cpu_quota_transfer : Interface - { - virtual void transfer_cpu_quota(Cpu_session_capability, Cpu_quota) = 0; - }; - - enum class Sample_state_result { CHANGED, UNCHANGED }; - - private: - - friend class Child_registry; - - Env &_env; - - Allocator &_alloc; - - Verbose const &_verbose; - - Id const _id; - - enum class State { - - /* - * States modelling the child's boostrap phase - */ - INITIAL, RAM_INITIALIZED, ALIVE, - - /* - * The child is present in the config model but its bootstrapping - * permanently failed. - */ - STUCK, - - /* - * The child must be restarted because a fundamental dependency - * changed. While the child is in this state, it is still - * referenced by the config model. - */ - RESTART_SCHEDULED, - - /* - * The child is no longer referenced by config model and can - * safely be destructed. - */ - ABANDONED - }; - - State _state = State::INITIAL; - - Report_update_trigger &_report_update_trigger; - - List_element _list_element; - - Reconstructible _start_node; - - Constructible _route_model { }; - - void _construct_route_model_from_start_node(Xml_node const &start) - { - _route_model.destruct(); - - start.with_sub_node("route", - [&] (Xml_node const &route) { - _route_model.construct(_alloc, route); }, - [&] () { - _route_model.construct(_alloc, _default_route_accessor.default_route()); }); - } - - /* - * Version attribute of the start node, used to force child restarts. - */ - Version _version { _start_node->xml().attribute_value("version", Version()) }; - - bool _uncertain_dependencies = false; - - /* - * True if the binary is loaded with ld.lib.so - */ - bool const _use_ld = _start_node->xml().attribute_value("ld", true); - - Default_route_accessor &_default_route_accessor; - Default_caps_accessor &_default_caps_accessor; - Ram_limit_accessor &_ram_limit_accessor; - Cap_limit_accessor &_cap_limit_accessor; - Cpu_limit_accessor &_cpu_limit_accessor; - Cpu_quota_transfer &_cpu_quota_transfer; - - Name_registry &_name_registry; - - /** - * Read name from XML and check for name confict with other children - * - * \throw Missing_name_attribute - */ - static Name _name_from_xml(Xml_node start_node) - { - Name const name = start_node.attribute_value("name", Name()); - if (name.valid()) - return name; - - warning("missing 'name' attribute in '' entry"); - throw Missing_name_attribute(); - } - - typedef String<64> Name; - Name const _unique_name { _name_from_xml(_start_node->xml()) }; - - static Binary_name _binary_from_xml(Xml_node start_node, - Name const &unique_name) - { - if (!start_node.has_sub_node("binary")) - return unique_name; - - return start_node.sub_node("binary").attribute_value("name", Name()); - } - - /* updated on configuration update */ - Binary_name _binary_name { _binary_from_xml(_start_node->xml(), _unique_name) }; - - /* initialized in constructor, updated by 'apply_config' */ - bool _heartbeat_enabled; - - /* - * Number of skipped heartbeats when last checked - * - * This variable is used for the triggering of state-report updates - * due to heartbeat events. - */ - unsigned _last_skipped_heartbeats = 0; - - /* return true if heartbeat tracking is active */ - bool _heartbeat_expected() const - { - /* don't expect heartbeats from a child that is not yet complete */ - return _heartbeat_enabled && (_state == State::ALIVE); - } - - /** - * Resources assigned to the child - */ - struct Resources - { - long prio_levels_log2; - long priority; - Affinity affinity; - Ram_quota assigned_ram_quota; - Cap_quota assigned_cap_quota; - Cpu_quota assigned_cpu_quota; - - Ram_quota effective_ram_quota() const - { - return Genode::Child::effective_quota(assigned_ram_quota); - } - - Cap_quota effective_cap_quota() const - { - /* capabilities consumed by 'Genode::Child' */ - Cap_quota const effective = - Genode::Child::effective_quota(assigned_cap_quota); - - /* capabilities additionally consumed by init */ - enum { - STATIC_COSTS = 1 /* possible heap backing-store - allocation for session object */ - + 1 /* buffered XML start node */ - + 2 /* dynamic ROM for config */ - + 2 /* dynamic ROM for session requester */ - }; - - if (effective.value < STATIC_COSTS) - return Cap_quota{0}; - - return Cap_quota{effective.value - STATIC_COSTS}; - } - }; - - static - Resources _resources_from_start_node(Xml_node start_node, Prio_levels prio_levels, - Affinity::Space const &affinity_space, - Cap_quota default_cap_quota) - { - unsigned cpu_percent = 0; - Number_of_bytes ram_bytes = 0; - - size_t caps = start_node.attribute_value("caps", default_cap_quota.value); - - start_node.for_each_sub_node("resource", [&] (Xml_node rsc) { - - typedef String<8> Name; - Name const name = rsc.attribute_value("name", Name()); - - if (name == "RAM") - ram_bytes = rsc.attribute_value("quantum", ram_bytes); - - if (name == "CPU") - cpu_percent = rsc.attribute_value("quantum", 0U); - - if (name == "CAP") - caps = rsc.attribute_value("quantum", 0UL); - }); - - return Resources { log2(prio_levels.value), - priority_from_xml(start_node, prio_levels), - Affinity(affinity_space, - affinity_location_from_xml(affinity_space, start_node)), - Ram_quota { ram_bytes }, - Cap_quota { caps }, - Cpu_quota { cpu_percent } }; - } - - Resources _resources; - - Ram_quota _configured_ram_quota() const; - Cap_quota _configured_cap_quota() const; - - 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 Genode::Local_service Service; - - Child &_child; - - Dynamic_rom_session _session { _child._env.ep().rpc_ep(), - _child.ref_pd(), _child._env.rm(), - *this }; - - Service::Single_session_factory _factory { _session }; - Service _service { _factory }; - - Inline_config_rom_service(Child &child) : _child(child) { } - - /** - * Dynamic_rom_session::Content_producer interface - */ - void produce_content(char *dst, Genode::size_t dst_len) override - { - Xml_node config = _child._start_node->xml().has_sub_node("config") - ? _child._start_node->xml().sub_node("config") - : Xml_node(""); - - size_t const config_len = config.size(); - - if (config_len + 1 /* null termination */ >= dst_len) - throw Buffer_capacity_exceeded(); - - config.with_raw_node([&] (char const *start, size_t length) { - - /* - * The 'length' is the number of bytes of the config-node - * content, which is not null-terminated. Since - * 'Genode::copy_cstring' always null-terminates the - * result, the last byte of the source string is not - * copied. Hence, it is safe to add '1' to 'length' and - * thereby include the last actual config-content character - * in the result. - */ - copy_cstring(dst, start, length + 1); - }); - } - - void trigger_update() { _session.trigger_update(); } - - Service &service() { return _service; } - }; - - Constructible _config_rom_service { }; - - Session_requester _session_requester; - - /** - * CPU-session priority parameters - */ - long const _prio_levels_log2 { _resources.prio_levels_log2 }; - long const _priority { _resources.priority }; - - Cpu_quota const _effective_cpu_quota { - min(_cpu_limit_accessor.resource_limit(Cpu_quota{}).percent, - _resources.assigned_cpu_quota.percent) }; - - /** - * If set to true, the child is allowed to do system management, - * e.g., constrain physical RAM allocations. - */ - bool const _managing_system { - _start_node->xml().attribute_value("managing_system", false) }; - - /** - * Resource request initiated by the child - */ - struct Requested_resources - { - Ram_quota const ram; - Cap_quota const caps; - - Requested_resources(Parent::Resource_args const &args) - : - ram (ram_quota_from_args(args.string())), - caps(cap_quota_from_args(args.string())) - { } - }; - - Constructible _requested_resources { }; - - Genode::Child _child { _env.rm(), _env.ep().rpc_ep(), *this }; - - struct Pd_accessor : Routed_service::Pd_accessor - { - Genode::Child &_child; - - Pd_accessor(Genode::Child &child) : _child(child) { } - - Pd_session &pd() override { return _child.pd(); } - Pd_session_capability pd_cap() const override { return _child.pd_session_cap(); } - - } _pd_accessor { _child }; - - struct Ram_accessor : Routed_service::Ram_accessor - { - Genode::Child &_child; - - Ram_accessor(Genode::Child &child) : _child(child) { } - - Pd_session &ram() override { return _child.pd(); } - Pd_session_capability ram_cap() const override { return _child.pd_session_cap(); } - - } _ram_accessor { _child }; - - /** - * Async_service::Wakeup callback - */ - void wakeup_async_service() override - { - _session_requester.trigger_update(); - } - - enum class Route_state { VALID, MISMATCH, UNAVAILABLE }; - - /** - * Return true if the policy results in the current route of the session - * - * This method is used to check if a policy change affects an existing - * client session of a child, i.e., to determine whether the child must - * be restarted. - */ - Route_state _route_valid(Session_state const &session) - { - try { - Route const route = - resolve_session_request(session.service().name(), - session.client_label(), - session.diag()); - - bool const valid = (session.service() == route.service) - && (route.label == session.label()); - - return valid ? Route_state::VALID : Route_state::MISMATCH; - } - catch (Service_denied) { return Route_state::UNAVAILABLE; } - } - - static Xml_node _provides_sub_node(Xml_node start_node) - { - return start_node.has_sub_node("provides") - ? start_node.sub_node("provides") : Xml_node(""); - } - - /** - * Return true if service is provided by this child - */ - bool _provided_by_this(Routed_service const &service) const - { - return service.has_id_space(_session_requester.id_space()); - } - - /** - * Return true if service of specified sub node is known - */ - bool _service_exists(Xml_node node) const - { - bool exists = false; - _child_services.for_each([&] (Routed_service const &service) { - if (_provided_by_this(service) && - service.name() == node.attribute_value("name", Service::Name())) - exists = true; }); - - return exists && !abandoned() && !restart_scheduled(); - } - - void _add_service(Xml_node service) - { - Service::Name const name = - service.attribute_value("name", Service::Name()); - - if (_verbose.enabled()) - log(" provides service ", name); - - new (_alloc) - Routed_service(_child_services, this->name(), - _pd_accessor, _ram_accessor, - _session_requester.id_space(), - _child.session_factory(), - name, *this); - } - - /* - * Exit state of the child set when 'exit()' is executed - * and reported afterwards through the state report. - */ - - bool _exited { false }; - int _exit_value { -1 }; - - /** - * Return true if it's safe to call the PD for requesting resource - * information - */ - bool _pd_alive() const - { - return !abandoned() && !restart_scheduled() && !_exited; - } - - void _destroy_services(); - - struct Sampled_state - { - Ram_info ram; - Cap_info caps; - - static Sampled_state from_pd(Pd_session &pd) - { - return { .ram = Ram_info::from_pd(pd), - .caps = Cap_info::from_pd(pd) }; - } - - bool operator != (Sampled_state const &other) const - { - return (ram != other.ram) || (caps != other.caps); - } - - } _sampled_state { }; - - void _abandon_services() - { - _child_services.for_each([&] (Routed_service &service) { - if (service.has_id_space(_session_requester.id_space())) - service.abandon(); }); - } - - void _schedule_restart() - { - _state = State::RESTART_SCHEDULED; - _abandon_services(); - } - - public: - - /** - * Constructor - * - * \param alloc allocator solely used for configuration- - * dependent allocations. It is not used for - * allocations on behalf of the child's - * behavior. - * - * \param ram_limit_accessor interface for querying the available - * RAM, used for dynamic RAM balancing at - * runtime. - * - * \throw Allocator::Out_of_memory could not buffer the XML start node - */ - 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_limit_accessor &ram_limit_accessor, - Cap_limit_accessor &cap_limit_accessor, - Cpu_limit_accessor &cpu_limit_accessor, - Cpu_quota_transfer &cpu_quota_transfer, - Prio_levels prio_levels, - Affinity::Space const &affinity_space, - Registry &parent_services, - Registry &child_services, - Registry &local_services); - - virtual ~Child(); - - /** - * Return true if the child has the specified name - */ - bool has_name(Child_policy::Name const &str) const { return str == name(); } - - bool has_version(Version const &version) const { return version == _version; } - - Ram_quota ram_quota() const { return _resources.assigned_ram_quota; } - Cap_quota cap_quota() const { return _resources.assigned_cap_quota; } - Cpu_quota cpu_quota() const { return _effective_cpu_quota; } - - void try_start() - { - if (_state == State::INITIAL) { - _child.initiate_env_pd_session(); - _state = State::RAM_INITIALIZED; - } - - /* - * Update the state if async env sessions have brought the child to - * life. Otherwise, we would wrongly call 'initiate_env_sessions()' - * another time. - */ - if (_state == State::RAM_INITIALIZED && _child.active()) - _state = State::ALIVE; - - if (_state == State::RAM_INITIALIZED) { - _child.initiate_env_sessions(); - - if (_child.active()) - _state = State::ALIVE; - else - _uncertain_dependencies = true; - } - } - - /* - * Mark child as to be removed because its was dropped from the - * config model. Either node disappeared or 'restart_scheduled' - * was handled. - */ - void abandon() - { - _state = State::ABANDONED; - _abandon_services(); - } - - void destroy_services(); - - void close_all_sessions() { _child.close_all_sessions(); } - - bool abandoned() const { return _state == State::ABANDONED; } - - bool restart_scheduled() const { return _state == State::RESTART_SCHEDULED; } - - bool stuck() const { return _state == State::STUCK; } - - bool env_sessions_closed() const { return _child.env_sessions_closed(); } - - enum Apply_config_result { PROVIDED_SERVICES_CHANGED, NO_SIDE_EFFECTS }; - - /** - * Apply new configuration to child - * - * \throw Allocator::Out_of_memory unable to allocate buffer for new - * config - */ - Apply_config_result apply_config(Xml_node start_node); - - bool uncertain_dependencies() const { return _uncertain_dependencies; } - - /** - * Validate that the routes of all existing sessions remain intact - * - * The child may become scheduled for restart or get stuck. - */ - void evaluate_dependencies(); - - /* common code for upgrading RAM and caps */ - template - void _apply_resource_upgrade(QUOTA &, QUOTA, LIMIT_ACCESSOR const &); - - template - void _apply_resource_downgrade(QUOTA &, QUOTA, QUOTA, - CHILD_AVAIL_QUOTA_FN const &); - - void apply_upgrade(); - void apply_downgrade(); - - void heartbeat() - { - if (_heartbeat_expected()) - _child.heartbeat(); - - unsigned const skipped_heartbeats = _child.skipped_heartbeats(); - - if (_last_skipped_heartbeats != skipped_heartbeats) - _report_update_trigger.trigger_report_update(); - - _last_skipped_heartbeats = skipped_heartbeats; - - } - - unsigned skipped_heartbeats() const - { - return _heartbeat_expected() ? _child.skipped_heartbeats() : 0; - } - - void report_state(Xml_generator &, Report_detail const &) const; - - Sample_state_result sample_state(); - - - /**************************** - ** Child-policy interface ** - ****************************/ - - Child_policy::Name name() const override { return _unique_name; } - - Pd_session &ref_pd() override { return _env.pd(); } - Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); } - - void init(Pd_session &, Pd_session_capability) override; - void init(Cpu_session &, Cpu_session_capability) override; - - Id_space &server_id_space() override { - return _session_requester.id_space(); } - - Route resolve_session_request(Service::Name const &, - Session_label const &, Session::Diag) override; - - void filter_session_args(Service::Name const &, char *, size_t) override; - Affinity filter_session_affinity(Affinity const &) override; - void announce_service(Service::Name const &) override; - void resource_request(Parent::Resource_args const &) override; - - void exit(int exit_value) override - { - try { - if (_start_node->xml().sub_node("exit").attribute_value("propagate", false)) { - _env.parent().exit(exit_value); - return; - } - } catch (...) { } - - /* - * Trigger a new report for exited children so that any management - * component may react upon it. - */ - _exited = true; - _exit_value = exit_value; - - _child.close_all_sessions(); - - _report_update_trigger.trigger_report_update(); - - /* - * Print a message as the exit is not handled otherwise. There are - * a number of automated tests that rely on this message. It is - * printed by the default implementation of 'Child_policy::exit'. - */ - Child_policy::exit(exit_value); - } - - void session_state_changed() override - { - _report_update_trigger.trigger_report_update(); - } - - bool initiate_env_sessions() const override { return false; } - - void yield_response() override - { - apply_downgrade(); - _report_update_trigger.trigger_report_update(); - } -}; - -#endif /* _LIB__SANDBOX__CHILD_H_ */ diff --git a/repos/os/src/lib/sandbox/child_registry.h b/repos/os/src/lib/sandbox/child_registry.h deleted file mode 100644 index b13e7527fa..0000000000 --- a/repos/os/src/lib/sandbox/child_registry.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * \brief Child registry - * \author Norman Feske - * \date 2010-04-27 - */ - -/* - * Copyright (C) 2010-2017 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 _LIB__SANDBOX__CHILD_REGISTRY_H_ -#define _LIB__SANDBOX__CHILD_REGISTRY_H_ - -/* local includes */ -#include -#include -#include -#include - -namespace Sandbox { struct Child_registry; } - - -class Sandbox::Child_registry : public Name_registry, Child_list -{ - private: - - List _aliases { }; - - public: - - /** - * Register child - */ - void insert(Child *child) - { - Child_list::insert(&child->_list_element); - } - - /** - * Unregister child - */ - void remove(Child *child) - { - Child_list::remove(&child->_list_element); - } - - /** - * Register alias - */ - void insert_alias(Alias *alias) - { - _aliases.insert(alias); - } - - /** - * Unregister alias - */ - void remove_alias(Alias *alias) - { - _aliases.remove(alias); - } - - template - void for_each_child(FN const &fn) const - { - Genode::List_element const *curr = first(); - for (; curr; curr = curr->next()) - fn(*curr->object()); - } - - template - void for_each_child(FN const &fn) - { - Genode::List_element *curr = first(), *next = nullptr; - for (; curr; curr = next) { - next = curr->next(); - fn(*curr->object()); - } - } - - void report_state(Xml_generator &xml, Report_detail const &detail) const - { - for_each_child([&] (Child &child) { child.report_state(xml, detail); }); - - for (Alias const *a = _aliases.first(); a; a = a->next()) { - xml.node("alias", [&] () { - xml.attribute("name", a->name); - xml.attribute("child", a->child); - }); - } - } - - Child::Sample_state_result sample_state() - { - auto result = Child::Sample_state_result::UNCHANGED; - - for_each_child([&] (Child &child) { - if (result == Child::Sample_state_result::UNCHANGED) - result = child.sample_state(); }); - - return result; - } - - Child::Name deref_alias(Child::Name const &name) override - { - for (Alias const *a = _aliases.first(); a; a = a->next()) - if (name == a->name) - return a->child; - - return name; - } -}; - -#endif /* _LIB__SANDBOX__CHILD_REGISTRY_H_ */ diff --git a/repos/os/src/lib/sandbox/config_model.h b/repos/os/src/lib/sandbox/config_model.h deleted file mode 100644 index 5a007970fe..0000000000 --- a/repos/os/src/lib/sandbox/config_model.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * \brief Internal model of the XML configuration - * \author Norman Feske - * \date 2021-04-01 - */ - -/* - * Copyright (C) 2021 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 _CONFIG_MODEL_H_ -#define _CONFIG_MODEL_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Sandbox { - - struct Parent_provides_model; - struct Start_model; - struct Service_model; - struct Config_model; -} - - -struct Sandbox::Parent_provides_model : Noncopyable -{ - struct Factory : Interface, Noncopyable - { - virtual Parent_service &create_parent_service(Service::Name const &) = 0; - }; - - Allocator &_alloc; - Verbose const &_verbose; - Factory &_factory; - - struct Node : Noncopyable, List_model::Element - { - Parent_service &service; - - Node(Factory &factory, Service::Name const &name) - : - service(factory.create_parent_service(name)) - { } - - ~Node() - { - /* - * The destruction of the 'Parent_service' is deferred to the - * handling of abandoned entries of the 'Registry'. - */ - service.abandon(); - } - - static bool type_matches(Xml_node const &) { return true; } - - bool matches(Xml_node const &xml) const - { - return xml.attribute_value("name", Service::Name()) == service.name(); - }; - }; - - List_model _model { }; - - Parent_provides_model(Allocator &alloc, Verbose const &verbose, Factory &factory) - : - _alloc(alloc), _verbose(verbose), _factory(factory) - { } - - ~Parent_provides_model() - { - update_from_xml(Xml_node("")); - } - - void update_from_xml(Xml_node const &xml) - { - bool first_log = true; - - auto create = [&] (Xml_node const &xml) -> Node & - { - Service::Name const name = xml.attribute_value("name", Service::Name()); - - if (_verbose.enabled()) { - if (first_log) - log("parent provides"); - - log(" service \"", name, "\""); - first_log = false; - } - - return *new (_alloc) Node(_factory, name); - }; - - auto destroy = [&] (Node &node) { Genode::destroy(_alloc, &node); }; - - auto update = [&] (Node &, Xml_node const &) { }; - - try { - update_list_model_from_xml(_model, xml, create, destroy, update); - } catch (...) { - error("unable to apply complete configuration"); - } - } -}; - - -struct Sandbox::Start_model : Noncopyable -{ - /* - * The 'Start_model' represents both '' nodes and '' nodes - * because both node types share the same name space. - */ - - typedef Child_policy::Name Name; - typedef Child::Version Version; - - static char const *start_type() { return "start"; } - static char const *alias_type() { return "alias"; } - - struct Factory : Interface - { - class Creation_failed : Exception { }; - - virtual bool ready_to_create_child(Name const &, Version const &) const = 0; - - /* - * \throw Creation_failed - */ - virtual Child &create_child(Xml_node const &start) = 0; - - virtual void update_child(Child &child, Xml_node const &start) = 0; - - /* - * \throw Creation_failed - */ - virtual Alias &create_alias(Name const &) = 0; - - virtual void destroy_alias(Alias &) = 0; - }; - - Name const _name; - Version const _version; - - Factory &_factory; - - bool _alias = false; - - struct { Child *_child_ptr = nullptr; }; - struct { Alias *_alias_ptr = nullptr; }; - - void _reset() - { - if (_child_ptr) _child_ptr->abandon(); - if (_alias_ptr) _factory.destroy_alias(*_alias_ptr); - - _child_ptr = nullptr; - _alias_ptr = nullptr; - } - - bool matches(Xml_node const &xml) const - { - return _name == xml.attribute_value("name", Name()) - && _version == xml.attribute_value("version", Version()); - } - - Start_model(Factory &factory, Xml_node const &xml) - : - _name(xml.attribute_value("name", Name())), - _version(xml.attribute_value("version", Version())), - _factory(factory) - { } - - ~Start_model() { _reset(); } - - void update_from_xml(Xml_node const &xml) - { - /* handle case where the node keeps the name but changes the type */ - - bool const orig_alias = _alias; - _alias = xml.has_type("alias"); - if (orig_alias != _alias) - _reset(); - - /* create alias or child depending of the node type */ - - if (_alias) { - - if (!_alias_ptr) - _alias_ptr = &_factory.create_alias(_name); - - } else { - - if (!_child_ptr && _factory.ready_to_create_child(_name, _version)) - _child_ptr = &_factory.create_child(xml); - } - - /* update */ - - if (_alias_ptr) - _alias_ptr->update(xml); - - if (_child_ptr) - _factory.update_child(*_child_ptr, xml); - } - - void apply_child_restart(Xml_node const &xml) - { - if (_child_ptr && _child_ptr->restart_scheduled()) { - - /* tear down */ - _child_ptr->abandon(); - _child_ptr = nullptr; - - /* respawn */ - update_from_xml(xml); - } - } - - void trigger_start_child() - { - if (_child_ptr) - _child_ptr->try_start(); - } -}; - - -struct Sandbox::Service_model : Interface, Noncopyable -{ - struct Factory : Interface, Noncopyable - { - virtual Service_model &create_service(Xml_node const &) = 0; - virtual void destroy_service(Service_model &) = 0; - }; - - virtual void update_from_xml(Xml_node const &) = 0; - - virtual bool matches(Xml_node const &) = 0; -}; - - -class Sandbox::Config_model : Noncopyable -{ - private: - - struct Node; - - List_model _model { }; - - struct Parent_provides_node; - struct Default_route_node; - struct Default_node; - struct Affinity_space_node; - struct Start_node; - struct Report_node; - struct Resource_node; - struct Heartbeat_node; - struct Service_node; - - public: - - typedef State_reporter::Version Version; - - void update_from_xml(Xml_node const &, - Allocator &, - Reconstructible &, - Version &, - Preservation &, - Constructible &, - Cap_quota &, - Prio_levels &, - Constructible &, - Start_model::Factory &, - Parent_provides_model::Factory &, - Service_model::Factory &, - State_reporter &, - Heartbeat &); - - void apply_children_restart(Xml_node const &); - - /* - * Call 'Child::try_start' for each child in start-node order - */ - void trigger_start_children(); -}; - -#endif /* _CONFIG_MODEL_H_ */ diff --git a/repos/os/src/lib/sandbox/heartbeat.h b/repos/os/src/lib/sandbox/heartbeat.h deleted file mode 100644 index d62679a83f..0000000000 --- a/repos/os/src/lib/sandbox/heartbeat.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * \brief Heartbeat monitoring - * \author Norman Feske - * \date 2018-11-15 - */ - -/* - * Copyright (C) 2018 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 _LIB__SANDBOX__HEARTBEAT_H_ -#define _LIB__SANDBOX__HEARTBEAT_H_ - -/* local includes */ -#include -#include -#include - -namespace Sandbox { class Heartbeat; } - - -class Sandbox::Heartbeat : Noncopyable -{ - private: - - Env &_env; - - Child_registry &_children; - - Report_update_trigger &_report_update_trigger; - - Constructible _timer { }; - - uint64_t _rate_ms = 0; - - Signal_handler _timer_handler; - - void _handle_timer() - { - bool any_skipped_heartbeats = false; - - _children.for_each_child([&] (Child &child) { - - if (child.skipped_heartbeats()) - any_skipped_heartbeats = true; - - child.heartbeat(); - }); - - if (any_skipped_heartbeats) - _report_update_trigger.trigger_report_update(); - } - - public: - - Heartbeat(Env &env, Child_registry &children, - Report_update_trigger &report_update_trigger) - : - _env(env), _children(children), - _report_update_trigger(report_update_trigger), - _timer_handler(_env.ep(), *this, &Heartbeat::_handle_timer) - { } - - void disable() - { - _timer.destruct(); - _rate_ms = 0; - } - - void apply_config(Xml_node heartbeat) - { - if (!_timer.constructed()) { - _timer.construct(_env); - _timer->sigh(_timer_handler); - } - - unsigned const rate_ms = heartbeat.attribute_value("rate_ms", 1000U); - - if (rate_ms != _rate_ms) { - _rate_ms = rate_ms; - _timer->trigger_periodic(_rate_ms*1000); - } - } -}; - -#endif /* _LIB__SANDBOX__HEARTBEAT_H_ */ diff --git a/repos/os/src/lib/sandbox/library.cc b/repos/os/src/lib/sandbox/library.cc index 84f632dce1..91f2847d8c 100644 --- a/repos/os/src/lib/sandbox/library.cc +++ b/repos/os/src/lib/sandbox/library.cc @@ -97,7 +97,7 @@ bool Sandbox::Library::ready_to_create_child(Start_model::Name const &name, Child(_env, _heap, *_verbose, Child::Id { ++_child_cnt }, _state_reporter, start_node, *this, *this, _children, *this, *this, *this, *this, - _prio_levels, _effective_affinity_space(), + _prio_levels, _effective_affinity_space(), Affinity::Location(-1, -1, 0, 0), _parent_services, _child_services, _local_services); _children.insert(&child); diff --git a/repos/os/src/lib/sandbox/name_registry.h b/repos/os/src/lib/sandbox/name_registry.h deleted file mode 100644 index f92f9e0ead..0000000000 --- a/repos/os/src/lib/sandbox/name_registry.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \brief Interface for database of child names - * \author Norman Feske - * \date 2017-03-03 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__NAME_REGISTRY_H_ -#define _LIB__SANDBOX__NAME_REGISTRY_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Sandbox { struct Name_registry; } - -struct Sandbox::Name_registry -{ - virtual ~Name_registry() { } - - typedef Child_policy::Name Name; - - /** - * Return child name for a given alias name - * - * If there is no alias, the function returns the original name. - */ - virtual Name deref_alias(Name const &) = 0; -}; - -#endif /* _LIB__SANDBOX__NAME_REGISTRY_H_ */ diff --git a/repos/os/src/lib/sandbox/report.h b/repos/os/src/lib/sandbox/report.h deleted file mode 100644 index 7531f2a7ee..0000000000 --- a/repos/os/src/lib/sandbox/report.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * \brief Report configuration - * \author Norman Feske - * \date 2017-01-16 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__REPORT_H_ -#define _LIB__SANDBOX__REPORT_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include - -namespace Sandbox { - struct Report_update_trigger; - struct Report_detail; -} - - -class Sandbox::Report_detail : Genode::Noncopyable -{ - private: - - bool _children = false; - bool _ids = false; - bool _requested = false; - bool _provided = false; - bool _session_args = false; - bool _child_ram = false; - bool _child_caps = false; - bool _init_ram = false; - bool _init_caps = false; - - public: - - Report_detail() { } - - Report_detail(Genode::Xml_node report) - { - _children = true; - _ids = report.attribute_value("ids", false); - _requested = report.attribute_value("requested", false); - _provided = report.attribute_value("provided", false); - _session_args = report.attribute_value("session_args", false); - _child_ram = report.attribute_value("child_ram", false); - _child_caps = report.attribute_value("child_caps", false); - _init_ram = report.attribute_value("init_ram", false); - _init_caps = report.attribute_value("init_caps", false); - } - - bool children() const { return _children; } - bool ids() const { return _ids; } - bool requested() const { return _requested; } - bool provided() const { return _provided; } - bool session_args() const { return _session_args; } - bool child_ram() const { return _child_ram; } - bool child_caps() const { return _child_caps; } - bool init_ram() const { return _init_ram; } - bool init_caps() const { return _init_caps; } -}; - - -struct Sandbox::Report_update_trigger : Interface -{ - /** - * Trigger regular (rate-limited) report update - */ - virtual void trigger_report_update() = 0; - - /** - * Trigger immediate report update - * - * This method is intended for situations that require a timely response of - * the consumer of the report. This is particularly important for resource - * requests that would otherwise unnecessarily stall the execution of the - * respective child. - */ - virtual void trigger_immediate_report_update() = 0; -}; - -#endif /* _LIB__SANDBOX__REPORT_H_ */ diff --git a/repos/os/src/lib/sandbox/route_model.h b/repos/os/src/lib/sandbox/route_model.h deleted file mode 100644 index f2a01ab7f1..0000000000 --- a/repos/os/src/lib/sandbox/route_model.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * \brief Internal model of routing rules - * \author Norman Feske - * \date 2021-04-05 - */ - -/* - * Copyright (C) 2021 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 _ROUTE_MODEL_H_ -#define _ROUTE_MODEL_H_ - -/* local includes */ -#include - -namespace Sandbox { - - struct Checksum; - class Route_model; -} - - -struct Sandbox::Checksum -{ - unsigned long value = 0; - - bool valid; - - /** - * Constructor - */ - Checksum(char const *s) : valid(s != nullptr) - { - if (!s) - return; - - while (uint8_t const byte = *s++) { - - /* rotate value */ - unsigned long const sign_bit = ((long)value < 0); - value = (value << 1) | sign_bit; - - /* xor byte to lowest 8 bit */ - value = value ^ (unsigned long)byte; - } - } - - template - Checksum(String const &s) : Checksum(s.string()) { } - - bool operator != (Checksum const &other) const - { - return (other.value != value) || !valid; - } -}; - - -class Sandbox::Route_model : Noncopyable -{ - public: - - struct Query : Noncopyable - { - Child_policy::Name const &child; - Service::Name const &service; - Session_label const &label; - - Checksum const service_checksum { service }; - Checksum const label_checksum { skip_label_prefix(child.string(), - label.string()) }; - - Query(Child_policy::Name const &child, - Service::Name const &service, - Session_label const &label) - : - child(child), service(service), label(label) - { } - }; - - class Rule : Noncopyable, List::Element - { - private: - - friend class List; - friend class Route_model; - friend void Genode::destroy(Allocator &, Rule *); - - Allocator &_alloc; - - Xml_node const _node; /* points to 'Route_model::_route_node' */ - - struct Selector - { - typedef String Label; - - enum class Type - { - NO_LABEL, SPECIFIC_LABEL, - - /* - * Presence of 'label_last', 'label_prefix', - * 'label_suffix', 'unscoped_label', or even - * a combination of attributes. - */ - COMPLICATED - - } type = Type::NO_LABEL; - - Checksum label_checksum { "" }; - - Selector(Xml_node const &node) - { - bool const complicated = - node.has_attribute("label_prefix") || - node.has_attribute("label_suffix") || - node.has_attribute("label_last") || - node.has_attribute("unscoped_label"); - - if (complicated) { - type = Type::COMPLICATED; - return; - } - - Label const label = node.attribute_value("label", Label()); - if (label.valid()) { - type = Type::SPECIFIC_LABEL; - label_checksum = Checksum(label); - } - } - }; - - Selector const _selector; - Checksum const _service_checksum; - bool const _specific_service { _node.has_type("service") }; - - struct Target : Noncopyable, private List::Element - { - friend class List; - friend class Rule; - - Xml_node const node; /* points to 'Route_model::_route_node' */ - - Target(Xml_node const &node) : node(node) { } - }; - - List _targets { }; - - /** - * Constructor is private to 'Route_model' - */ - Rule(Allocator &alloc, Xml_node const &node) - : - _alloc(alloc), _node(node), _selector(node), - _service_checksum(node.attribute_value("name", Service::Name())) - { - Target const *at_ptr = nullptr; - node.for_each_sub_node([&] (Xml_node sub_node) { - Target &target = *new (_alloc) Target(sub_node); - _targets.insert(&target, at_ptr); - at_ptr = ⌖ - }); - } - - ~Rule() - { - while (Target *target_ptr = _targets.first()) { - _targets.remove(target_ptr); - destroy(_alloc, target_ptr); - } - } - - /** - * Quick check for early detection of definite mismatches - * - * \return true if query definitely mismatches the rule, - * false if the undecided - */ - bool _mismatches(Query const &query) const - { - if (_specific_service - && query.service_checksum != _service_checksum) - return true; - - if (_selector.type == Selector::Type::SPECIFIC_LABEL - && query.label_checksum != _selector.label_checksum) - return true; - - return false; - } - - public: - - bool matches(Query const &query) const - { - /* handle common case */ - if (_mismatches(query)) - return false; - - return service_node_matches(_node, - query.label, - query.child, - query.service); - } - - template - Child_policy::Route resolve(FN const &fn) const - { - for (Target const *t = _targets.first(); t; t = t->next()) { - try { return fn(t->node); } - catch (Service_denied) { /* try next target */ } - } - - /* query is not accepted by any of the targets */ - throw Service_denied(); - } - }; - - private: - - Allocator &_alloc; - - Buffered_xml const _route_node; - - List _rules { }; - - public: - - Route_model(Allocator &alloc, Xml_node const &route) - : - _alloc(alloc), _route_node(_alloc, route) - { - Rule const *at_ptr = nullptr; - _route_node.xml().for_each_sub_node([&] (Xml_node const &node) { - Rule &rule = *new (_alloc) Rule(_alloc, node); - _rules.insert(&rule, at_ptr); /* append */ - at_ptr = &rule; - }); - } - - ~Route_model() - { - while (Rule *rule_ptr = _rules.first()) { - _rules.remove(rule_ptr); - destroy(_alloc, rule_ptr); - } - } - - template - Child_policy::Route resolve(Query const &query, FN const &fn) const - { - for (Rule const *r = _rules.first(); r; r = r->next()) - if (r->matches(query)) { - try { - return r->resolve(fn); - } - catch (Service_denied) { - if (r->_specific_service) - throw; - - /* - * If none of the targets of a wildcard rule was - * satisfied with the query, continue with the next - * rule. - */ - } - } - - warning(query.child, ": no route to " - "service \"", query.service, "\" " - "(label=\"", query.label, "\")"); - - throw Service_denied(); - } -}; - -#endif /* _ROUTE_MODEL_H_ */ diff --git a/repos/os/src/lib/sandbox/server.h b/repos/os/src/lib/sandbox/server.h deleted file mode 100644 index ce231ce28f..0000000000 --- a/repos/os/src/lib/sandbox/server.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * \brief Server role of init, forwarding session requests to children - * \author Norman Feske - * \date 2017-03-07 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__SERVER_H_ -#define _LIB__SANDBOX__SERVER_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include -#include -#include -#include - -namespace Sandbox { class Server; } - - -class Sandbox::Server : Session_state::Ready_callback, - Session_state::Closed_callback, - public Service_model::Factory -{ - private: - - struct Route - { - Routed_service &service; - Session_label label; - }; - - Env &_env; - - Allocator &_alloc; - - /* - * ID space of requests originating from the parent - */ - Id_space _server_id_space { }; - - /* - * ID space of requests issued to the children - */ - Id_space _client_id_space { }; - - /** - * Exception type - */ - class Service_not_present : Exception { }; - - /** - * Meta data of service provided to our parent - */ - struct Service; - - Registry _services { }; - - /** - * Services provided by our children - */ - Registry &_child_services; - - Report_update_trigger &_report_update_trigger; - - Constructible _session_requests { }; - Constructible > _session_request_handler { }; - - /** - * \throw Service_denied - */ - Route _resolve_session_request(Genode::Service::Name const &, - Session_label const &); - - void _handle_create_session_request (Xml_node, Parent::Client::Id); - void _handle_upgrade_session_request(Xml_node, Parent::Client::Id); - void _handle_close_session_request (Xml_node, Parent::Client::Id); - - void _handle_session_request(Xml_node); - void _handle_session_requests(); - - void _close_session(Session_state &, Parent::Session_response response); - - /** - * Session_state::Closed_callback interface - */ - void session_closed(Session_state &) override; - - /** - * Session_state::Ready_callback interface - */ - void session_ready(Session_state &) override; - - public: - - /** - * Constructor - * - * \param alloc allocator used for buffering XML config data and - * for allocating per-service meta data - */ - Server(Env &env, Allocator &alloc, Registry &services, - Report_update_trigger &report_update_trigger) - : - _env(env), _alloc(alloc), _child_services(services), - _report_update_trigger(report_update_trigger) - { } - - void apply_updated_policy(); - - /** - * Service_model::Factory - */ - Service_model &create_service(Xml_node const &) override; - - /** - * Service_model::Factory - */ - void destroy_service(Service_model &) override; -}; - -#endif /* _LIB__SANDBOX__SERVER_H_ */ diff --git a/repos/os/src/lib/sandbox/service.h b/repos/os/src/lib/sandbox/service.h deleted file mode 100644 index 9589de91b5..0000000000 --- a/repos/os/src/lib/sandbox/service.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * \brief Services as targeted by session routes - * \author Norman Feske - * \date 2017-03-03 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__SERVICE_H_ -#define _LIB__SANDBOX__SERVICE_H_ - -/* Genode includes */ -#include -#include - -namespace Sandbox { - class Abandonable; - class Parent_service; - class Routed_service; - class Forwarded_service; -} - - -class Sandbox::Abandonable : Interface -{ - private: - - bool _abandoned = false; - - public: - - void abandon() { _abandoned = true; } - - bool abandoned() const { return _abandoned; } -}; - - -class Sandbox::Parent_service : public Genode::Try_parent_service, public Abandonable -{ - private: - - Registry::Element _reg_elem; - - public: - - Parent_service(Registry ®istry, Env &env, - Service::Name const &name) - : - Genode::Try_parent_service(env, name), _reg_elem(registry, *this) - { } -}; - - -/** - * Sandbox-specific representation of a child service - */ -class Sandbox::Routed_service : public Async_service, public Abandonable -{ - public: - - typedef Child_policy::Name Child_name; - - struct Pd_accessor : Interface - { - virtual Pd_session &pd() = 0; - virtual Pd_session_capability pd_cap() const = 0; - }; - - struct Ram_accessor : Interface - { - virtual Pd_session &ram() = 0; - virtual Pd_session_capability ram_cap() const = 0; - }; - - private: - - Child_name _child_name; - - Pd_accessor &_pd_accessor; - - Session_state::Factory &_factory; - - Registry::Element _registry_element; - - public: - - /** - * Constructor - * - * \param services registry of all services provides by children - * \param child_name child name of server, used for session routing - * - * The other arguments correspond to the arguments of 'Async_service'. - */ - Routed_service(Registry &services, - Child_name const &child_name, - Pd_accessor &pd_accessor, - Ram_accessor &, - Id_space &server_id_space, - Session_state::Factory &factory, - Service::Name const &name, - Wakeup &wakeup) - : - Async_service(name, server_id_space, factory, wakeup), - _child_name(child_name), _pd_accessor(pd_accessor), - _factory(factory), _registry_element(services, *this) - { } - - Child_name const &child_name() const { return _child_name; } - - Session_state::Factory &factory() { return _factory; } - - /** - * Ram_transfer::Account interface - */ - void transfer(Pd_session_capability to, Ram_quota amount) override - { - if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount); - } - - /** - * Ram_transfer::Account interface - */ - Pd_session_capability cap(Ram_quota) const override - { - return _pd_accessor.pd_cap(); - } - - /** - * Cap_transfer::Account interface - */ - void transfer(Pd_session_capability to, Cap_quota amount) override - { - if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount); - } - - /** - * Cap_transfer::Account interface - */ - Pd_session_capability cap(Cap_quota) const override - { - return _pd_accessor.pd_cap(); - } -}; - -#endif /* _LIB__SANDBOX__SERVICE_H_ */ diff --git a/repos/os/src/lib/sandbox/state_reporter.h b/repos/os/src/lib/sandbox/state_reporter.h deleted file mode 100644 index dc91498e2a..0000000000 --- a/repos/os/src/lib/sandbox/state_reporter.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * \brief State reporting mechanism - * \author Norman Feske - * \date 2017-03-03 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__STATE_REPORTER_H_ -#define _LIB__SANDBOX__STATE_REPORTER_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include "report.h" -#include "child.h" - -namespace Sandbox { class State_reporter; } - - -class Sandbox::State_reporter : public Report_update_trigger -{ - public: - - typedef String<64> Version; - - struct Producer : Interface - { - virtual void produce_state_report(Xml_generator &xml, - Report_detail const &) const = 0; - - virtual Child::Sample_state_result sample_children_state() = 0; - }; - - private: - - using State_handler = Genode::Sandbox::State_handler; - - Env &_env; - - Producer &_producer; - - Reconstructible _report_detail { }; - - uint64_t _report_delay_ms = 0; - - /* interval used when child-ram reporting is enabled */ - uint64_t _report_period_ms = 0; - - /* version string from config, to be reflected in the report */ - Version _version { }; - - Constructible _timer { }; - Constructible _timer_periodic { }; - - Signal_handler _timer_handler { - _env.ep(), *this, &State_reporter::_handle_timer }; - - Signal_handler _timer_periodic_handler { - _env.ep(), *this, &State_reporter::_handle_periodic_timer }; - - Signal_handler _immediate_handler { - _env.ep(), *this, &State_reporter::_handle_timer }; - - bool _scheduled = false; - - State_handler &_state_handler; - - bool _periodic_sampling_needed() const - { - return _report_detail->child_ram() - || _report_detail->child_caps(); - } - - void _handle_periodic_timer() - { - if (!_periodic_sampling_needed()) - return; - - if (_producer.sample_children_state() == Child::Sample_state_result::CHANGED) - _handle_timer(); - } - - void _handle_timer() - { - _scheduled = false; - - _state_handler.handle_sandbox_state(); - } - - public: - - State_reporter(Env &env, Producer &producer, State_handler &state_handler) - : - _env(env), _producer(producer), - _state_handler(state_handler) - { } - - void generate(Xml_generator &xml) const - { - if (_version.valid()) - xml.attribute("version", _version); - - if (_report_detail.constructed()) - _producer.produce_state_report(xml, *_report_detail); - } - - void apply_config(Version const &version, Xml_node const &report) - { - if (report.type() == "report") { - _report_detail.construct(report); - _report_delay_ms = report.attribute_value("delay_ms", 100UL); - } else { - _report_detail.construct(); - _report_delay_ms = 0; - } - - bool trigger_update = false; - - if (version != _version) { - _version = version; - trigger_update = true; - } - - if (_report_delay_ms) { - if (!_timer.constructed()) { - _timer.construct(_env); - _timer->sigh(_timer_handler); - } - trigger_update = true; - } - - if (trigger_update) - trigger_report_update(); - - /* - * 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 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, - * the user intends to limit the rate of state reports. If so, we - * use the value of 'delay_ms' as interval. - */ - uint64_t const period_ms = max((uint64_t)1000, _report_delay_ms); - bool const period_changed = (_report_period_ms != period_ms); - bool const report_periodically = _periodic_sampling_needed(); - - if (report_periodically && !_timer_periodic.constructed()) { - _timer_periodic.construct(_env); - _timer_periodic->sigh(_timer_periodic_handler); - } - - if (!report_periodically && _timer_periodic.constructed()) { - _report_period_ms = 0; - _timer_periodic.destruct(); - } - - if (period_changed && _timer_periodic.constructed()) { - _report_period_ms = period_ms; - _timer_periodic->trigger_periodic(1000*_report_period_ms); - } - } - - void trigger_report_update() override - { - if (!_scheduled && _timer.constructed() && _report_delay_ms) { - _timer->trigger_once(_report_delay_ms*1000); - _scheduled = true; - } - } - - void trigger_immediate_report_update() override - { - if (_report_delay_ms) - Signal_transmitter(_immediate_handler).submit(); - } -}; - -#endif /* _LIB__SANDBOX__STATE_REPORTER_H_ */ diff --git a/repos/os/src/lib/sandbox/types.h b/repos/os/src/lib/sandbox/types.h deleted file mode 100644 index 56fd8ddd0d..0000000000 --- a/repos/os/src/lib/sandbox/types.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * \brief Common types used within init - * \author Norman Feske - * \date 2017-03-03 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__TYPES_H_ -#define _LIB__SANDBOX__TYPES_H_ - -#include -#include -#include - -namespace Sandbox { - - class Child; - - using namespace Genode; - using Genode::size_t; - using Genode::strlen; - - struct Prio_levels { long value; }; - - struct Cpu_quota - { - unsigned percent; - - void print(Output &out) const { Genode::print(out, percent, "%"); } - }; - - typedef List > Child_list; - - template - struct Resource_info - { - T quota, used, avail; - - static Resource_info from_pd(Pd_session const &pd); - - void generate(Xml_generator &xml) const - { - typedef String<32> Value; - xml.attribute("quota", Value(quota)); - xml.attribute("used", Value(used)); - xml.attribute("avail", Value(avail)); - } - - bool operator != (Resource_info const &other) const - { - return quota.value != other.quota.value - || used.value != other.used.value - || avail.value != other.avail.value; - } - }; - - typedef Resource_info Ram_info; - typedef Resource_info Cap_info; - - template <> - inline Ram_info Ram_info::from_pd(Pd_session const &pd) - { - return { .quota = pd.ram_quota(), - .used = pd.used_ram(), - .avail = pd.avail_ram() }; - } - - template <> - inline Cap_info Cap_info::from_pd(Pd_session const &pd) - { - return { .quota = pd.cap_quota(), - .used = pd.used_caps(), - .avail = pd.avail_caps() }; - } - - struct Preservation : private Noncopyable - { - static Ram_quota default_ram() { return { 40*sizeof(long)*1024 }; } - static Cap_quota default_caps() { return { 20 }; } - - Ram_quota ram { }; - Cap_quota caps { }; - - void reset() - { - ram = default_ram(); - caps = default_caps(); - } - - Preservation() { reset(); } - }; -} - -#endif /* _LIB__SANDBOX__TYPES_H_ */ diff --git a/repos/os/src/lib/sandbox/utils.h b/repos/os/src/lib/sandbox/utils.h deleted file mode 100644 index cba9ca5d2c..0000000000 --- a/repos/os/src/lib/sandbox/utils.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * \brief Utilities - * \author Norman Feske - * \date 2010-05-04 - */ - -/* - * Copyright (C) 2010-2017 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 _LIB__SANDBOX__UTILS_H_ -#define _LIB__SANDBOX__UTILS_H_ - -namespace Sandbox { - - static inline void warn_insuff_quota(size_t const avail) - { - warning("specified quota exceeds available quota, " - "proceeding with a quota of ", avail); - } - - - /** - * Return sub string of label with the leading child name stripped out - * - * \return character pointer to the scoped part of the label, - * or nullptr if the label is not correctly prefixed with the child's - * name - */ - inline char const *skip_label_prefix(char const *child_name, char const *label) - { - size_t const child_name_len = strlen(child_name); - - if (strcmp(child_name, label, child_name_len) != 0) - return nullptr; - - label += child_name_len; - - /* - * Skip label separator. This condition should be always satisfied. - */ - if (strcmp(" -> ", label, 4) != 0) - return nullptr; - - return label + 4; - } - - - /** - * Return true if service XML node matches service request - * - * \param args session arguments, inspected for the session label - * \param child_name name of the originator of the session request - * \param service_name name of the requested service - */ - inline bool service_node_matches(Xml_node const service_node, - Session_label const &label, - Child_policy::Name const &child_name, - Service::Name const &service_name) - { - bool const service_matches = - service_node.has_type("any-service") || - (service_node.has_type("service") && - service_node.attribute_value("name", Service::Name()) == service_name); - - if (!service_matches) - return false; - - typedef String Label; - - char const *unscoped_attr = "unscoped_label"; - char const *label_last_attr = "label_last"; - - bool const route_depends_on_child_provided_label = - service_node.has_attribute("label") || - service_node.has_attribute("label_prefix") || - service_node.has_attribute("label_suffix") || - service_node.has_attribute(label_last_attr); - - if (service_node.has_attribute(unscoped_attr)) { - - /* - * If an 'unscoped_label' attribute is provided, don't consider any - * scoped label attribute. - */ - if (route_depends_on_child_provided_label) - warning("service node contains both scoped and unscoped label attributes"); - - return label == service_node.attribute_value(unscoped_attr, Label()); - } - - if (service_node.has_attribute(label_last_attr)) - return service_node.attribute_value(label_last_attr, Label()) == label.last_element(); - - if (!route_depends_on_child_provided_label) - return true; - - char const * const scoped_label = skip_label_prefix( - child_name.string(), label.string()); - - if (!scoped_label) - return false; - - Session_label const session_label(scoped_label); - - return !Xml_node_label_score(service_node, session_label).conflict(); - } - - - /** - * Check if service name is ambiguous - * - * \return true if the same service is provided multiple - * times - * - * \deprecated - */ - template - inline bool is_ambiguous(Registry const &services, Service::Name const &name) - { - /* count number of services with the specified name */ - unsigned cnt = 0; - services.for_each([&] (T const &service) { - if (!service.abandoned()) - cnt += (service.name() == name); }); - - return cnt > 1; - } - - /** - * Find service with certain values in given registry - * - * \param services service registry - * \param name name of wanted service - * \param filter_fn function that applies additional filters - * - * \throw Service_denied - */ - template - inline T &find_service(Registry &services, - Service::Name const &name, - FILTER_FN const &filter_fn) - { - T *service = nullptr; - services.for_each([&] (T &s) { - - if (service || s.name() != name || filter_fn(s)) - return; - - service = &s; - }); - - if (!service) - throw Service_denied(); - - if (service->abandoned()) - throw Service_denied(); - - return *service; - } - - /** - * Read priority-levels declaration from config - */ - inline Prio_levels prio_levels_from_xml(Xml_node const &config) - { - long const prio_levels = config.attribute_value("prio_levels", 0L); - - if (prio_levels && ((prio_levels >= (long)sizeof(prio_levels)*8) || - (prio_levels != (1L << log2(prio_levels))))) { - warning("prio levels is not power of two, priorities are disabled"); - return Prio_levels { 0 }; - } - return Prio_levels { prio_levels }; - } - - - inline long priority_from_xml(Xml_node start_node, Prio_levels prio_levels) - { - long const default_priority = Cpu_session::DEFAULT_PRIORITY; - - long priority = start_node.attribute_value("priority", default_priority); - - /* - * All priority declarations in the config file are - * negative because child priorities can never be higher - * than parent priorities. To simplify priority - * calculations, we use inverted values. Lower values - * correspond to higher priorities. - */ - priority = -priority; - - if (priority && (priority >= prio_levels.value)) { - long new_prio = prio_levels.value ? prio_levels.value - 1 : 0; - - Service::Name const name = start_node.attribute_value("name", Service::Name()); - warning(name, ": invalid priority, upgrading " - "from ", -priority, " to ", -new_prio); - return new_prio; - } - - return priority; - } - - - inline Affinity::Location - affinity_location_from_xml(Affinity::Space const &space, Xml_node start_node) - { - typedef Affinity::Location Location; - - Location result = Location(0, 0, space.width(), space.height()); - - start_node.with_optional_sub_node("affinity", [&] (Xml_node node) { - - Location const location = Location::from_xml(space, node); - - if (!location.within(space)) { - Service::Name const name = start_node.attribute_value("name", Service::Name()); - warning(name, ": affinity location exceeds affinity-space boundary"); - return; - } - - result = location; - }); - - return result; - } -} - -#endif /* _LIB__SANDBOX__UTILS_H_ */ diff --git a/repos/os/src/lib/sandbox/verbose.h b/repos/os/src/lib/sandbox/verbose.h deleted file mode 100644 index ab3e6050a6..0000000000 --- a/repos/os/src/lib/sandbox/verbose.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * \brief Sandbox verbosity - * \author Norman Feske - * \date 2017-01-03 - */ - -/* - * Copyright (C) 2017 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 _LIB__SANDBOX__VERBOSE_H_ -#define _LIB__SANDBOX__VERBOSE_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include - -namespace Sandbox { struct Verbose; } - - -class Sandbox::Verbose : Genode::Noncopyable -{ - private: - - bool _enabled = false; - - public: - - Verbose() { } - - Verbose(Xml_node const &config) - : _enabled(config.attribute_value("verbose", false)) { } - - bool enabled() const { return _enabled; } -}; - -#endif /* _LIB__SANDBOX__VERBOSE_H_ */