diff --git a/repos/ealanos/include/sandbox/sandbox.h b/repos/ealanos/include/sandbox/sandbox.h index b9fd6bf4b3..1502d5b1ce 100644 --- a/repos/ealanos/include/sandbox/sandbox.h +++ b/repos/ealanos/include/sandbox/sandbox.h @@ -22,7 +22,9 @@ #include namespace Genode { class Sandbox; } - +namespace Sandbox { + class Child; +} class Genode::Sandbox : Noncopyable { @@ -43,6 +45,7 @@ class Genode::Sandbox : Noncopyable struct State_handler : Interface { virtual void handle_sandbox_state() = 0; + virtual void handle_child_state(::Sandbox::Child &child) = 0; }; /** @@ -108,8 +111,9 @@ class Genode::Sandbox : Noncopyable * \throw Xml_generator::Buffer_exceeded */ void generate_state_report(Xml_generator &) const; -}; + void update(::Sandbox::Child &child); +}; class Genode::Sandbox::Local_service_base : public Service { diff --git a/repos/ealanos/src/hoitaja/main.cc b/repos/ealanos/src/hoitaja/main.cc index 29924e0a8a..03d6045a9c 100644 --- a/repos/ealanos/src/hoitaja/main.cc +++ b/repos/ealanos/src/hoitaja/main.cc @@ -18,7 +18,7 @@ #include #include #include - +#include namespace Init { using namespace Genode; @@ -27,11 +27,11 @@ namespace Init { } -struct Init::Main : Sandbox::State_handler +struct Init::Main : Genode::Sandbox::State_handler { Env &_env; - Sandbox _sandbox { _env, *this }; + Genode::Sandbox _sandbox { _env, *this }; Attached_rom_dataspace _config { _env, "config" }; @@ -96,6 +96,16 @@ struct Init::Main : Sandbox::State_handler } } + void handle_child_state(::Sandbox::Child &child) override { + try { + Genode::log("Updating sandbox state"); + _sandbox.update(child); + } catch (Genode::Quota_guard::Limit_exceeded) { + Genode::log("Caps exceeded while handling child state"); + _env.parent().exit(1); + } + } + Main(Env &env) : _env(env) { _config.sigh(_config_handler); diff --git a/repos/ealanos/src/hoitaja/target.mk b/repos/ealanos/src/hoitaja/target.mk index d8089f8834..c94e0c088f 100644 --- a/repos/ealanos/src/hoitaja/target.mk +++ b/repos/ealanos/src/hoitaja/target.mk @@ -7,6 +7,7 @@ CONFIG_XSD = config.xsd # statically link sandbox library to avoid dependency from sandbox.lib.so SRC_CC += library.cc child.cc server.cc config_model.cc +INC_DIR += $(REP_DIR)/include INC_DIR += $(REP_DIR)/src/lib/sandbox vpath %.cc $(REP_DIR)/src/lib/sandbox diff --git a/repos/ealanos/src/lib/sandbox/child.cc b/repos/ealanos/src/lib/sandbox/child.cc index a86a0ef417..9de8c8f83f 100644 --- a/repos/ealanos/src/lib/sandbox/child.cc +++ b/repos/ealanos/src/lib/sandbox/child.cc @@ -755,10 +755,12 @@ Sandbox::Child::Child(Env &env, Registry &child_services, Registry &local_services, Pd_intrinsics &pd_intrinsics, - Ealan::Habitat_connection &habitat) + Ealan::Habitat_connection &habitat, + Genode::Sandbox::State_handler &habitat_handler) : _env(env), _alloc(alloc), _verbose(verbose), _id(id), _report_update_trigger(report_update_trigger), + _habitat_handler(habitat_handler), _list_element(this), _start_node(_alloc, start_node), _default_route_accessor(default_route_accessor), @@ -776,8 +778,7 @@ Sandbox::Child::Child(Env &env, _child_services(child_services), _local_services(local_services), _session_requester(_env.ep().rpc_ep(), _env.ram(), _env.rm()), - _habitat(habitat) -{ + _habitat(habitat){ log("Creating new cell <", _unique_name, ">"); if (_verbose.enabled()) { log("child \"", _unique_name, "\""); diff --git a/repos/ealanos/src/lib/sandbox/child.h b/repos/ealanos/src/lib/sandbox/child.h index 54e45f5662..70084ed7dd 100644 --- a/repos/ealanos/src/lib/sandbox/child.h +++ b/repos/ealanos/src/lib/sandbox/child.h @@ -35,9 +35,11 @@ #include #include #include +#include /* EalánOS includes */ #include +#include namespace Sandbox { class Child; } @@ -105,6 +107,46 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup { pd_intrinsics.with_intrinsics(cap, pd, Pd_intrinsics::With_intrinsics::Fn { fn }); } + + /** + * 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}; + } + }; + private: @@ -149,6 +191,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup Report_update_trigger &_report_update_trigger; + Genode::Sandbox::State_handler &_habitat_handler; + List_element _list_element; Reconstructible _start_node; @@ -237,45 +281,6 @@ 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, @@ -421,6 +426,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup Genode::Child _child { _env.rm(), _env.ep().rpc_ep(), *this }; + Ealan::Cell_capability _cell_cap { }; + struct Pd_accessor : Routed_service::Pd_accessor { Genode::Child &_child; @@ -528,6 +535,7 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup bool _exited { false }; int _exit_value { -1 }; + /** * Return true if it's safe to call the PD for requesting resource * information @@ -606,7 +614,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup Registry &child_services, Registry &local_services, Pd_intrinsics &pd_intrinsics, - Ealan::Habitat_connection &habitat); + Ealan::Habitat_connection &habitat, + Genode::Sandbox::State_handler &habitat_handler); virtual ~Child(); @@ -640,8 +649,9 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup _child.initiate_env_sessions(); if (_child.active()) { - _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast(_priority)); - _state = State::ALIVE; + _cell_cap = _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast(_priority), Genode::Session_label(_unique_name)); + Genode::log("Created new cell ", _unique_name, " ", _cell_cap); + _state = State::ALIVE; } else _uncertain_dependencies = true; } @@ -668,6 +678,8 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup bool restart_scheduled() const { return _state == State::RESTART_SCHEDULED; } bool stuck() const { return _state == State::STUCK; } + + bool exited() { return _exited; } bool env_sessions_closed() const { return _child.env_sessions_closed(); } @@ -726,19 +738,16 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup struct Resources &resources() { return _resources; } - void update_affinity(Genode::Affinity affinity) { - //Genode::log("Updating affinity to ", affinity.location(), " in space ", affinity.space()); + void update(Genode::Affinity affinity) { + Genode::log("Updating affinity to ", affinity.location(), " in space ", affinity.space()); _resources.affinity = affinity; //Genode::log("Moving CPU session ", _env.cpu_session_cap()); if (_child.active()) { - } - } - - void shrink_cores(Genode::Affinity::Location &cores) { - } - - void grow_cores(Genode::Affinity::Location &cores) { - } + Ealan::Cell_client cell(_cell_cap); + Genode::log("Updating cell ", _cell_cap); + cell.update(affinity); + } + } bool is_brick() { return false; } @@ -800,6 +809,9 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup * printed by the default implementation of 'Child_policy::exit'. */ Child_policy::exit(exit_value); + + Genode::log("Notifying Hoitaja"); + _habitat_handler.handle_child_state(*this); } void session_state_changed() override diff --git a/repos/ealanos/src/lib/sandbox/core_allocator.h b/repos/ealanos/src/lib/sandbox/core_allocator.h index 0ecb7f7fcf..564ab8db2e 100644 --- a/repos/ealanos/src/lib/sandbox/core_allocator.h +++ b/repos/ealanos/src/lib/sandbox/core_allocator.h @@ -86,7 +86,7 @@ class Hoitaja::Core_allocator void update(::Sandbox::Child &cell, int *xpos, int *lower_limit) { if (cell.abandoned()) return; - /*::Sandbox::Child::Resources resources = cell.resources(); + ::Sandbox::Child::Resources resources = cell.resources(); long priority = (resources.priority == 0)? 1 : resources.priority; unsigned int cores_share = _calculate_resource_share(priority); @@ -100,13 +100,14 @@ class Hoitaja::Core_allocator Genode::Affinity::Location location(*xpos - cores_share, resources.affinity.location().ypos(), cores_share, resources.affinity.location().height()); - if (resources.affinity.location() != location) { // Only update, if location has actually changed + /*if (resources.affinity.location() != location) { // Only update, if location has actually changed cell.update_affinity(Genode::Affinity(resources.affinity.space(), location)); } if (location.width() > resources.affinity.location().width()) { cell.grow_cores(location); - } + }*/ + *xpos = location.xpos(); // TODO: Update affinity of existing sessions for cell @@ -114,8 +115,9 @@ class Hoitaja::Core_allocator if (cores_to_reclaim > 0) { log("Need to reclaim ", cores_to_reclaim, " cores from ", cell.name()); - cell.shrink_cores(location); - }*/ + } + + cell.update(Genode::Affinity(resources.affinity.space(), location)); } diff --git a/repos/ealanos/src/lib/sandbox/library.cc b/repos/ealanos/src/lib/sandbox/library.cc index 422ddeef42..f71a641de9 100644 --- a/repos/ealanos/src/lib/sandbox/library.cc +++ b/repos/ealanos/src/lib/sandbox/library.cc @@ -79,6 +79,8 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, Constructible _affinity_space { }; Preservation _preservation { }; + State_handler &_habitat_handler; + Affinity::Space _effective_affinity_space() const { return _affinity_space.constructed() ? *_affinity_space @@ -289,7 +291,7 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, State_handler &state_handler, Pd_intrinsics &pd_intrinsics) : _env(env), _heap(heap), _core_allocator(), _pd_intrinsics(pd_intrinsics), - _local_services(local_services), _state_reporter(_env, *this, state_handler) + _local_services(local_services), _habitat_handler(state_handler), _state_reporter(_env, *this, state_handler) { } Library(Env &env, Heap &heap, Registry &local_services, @@ -304,8 +306,18 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, { _state_reporter.generate(xml); } -}; + void maintain_cells(); + + void update(Child &child) { + if (child.exited()) { + _children.remove(&child); + _core_allocator->free_cores_from_cell(child); + Genode::log("Starting new maintenance cycle"); + maintain_cells(); + } + } +}; void Genode::Sandbox::Library::_destroy_abandoned_parent_services() { @@ -400,9 +412,11 @@ bool Genode::Sandbox::Library::ready_to_create_child(Start_model::Name const start_node, *this, *this, _children, *this, *this, *this, *this, _prio_levels, _effective_affinity_space(), allocation, _parent_services, _child_services, _local_services, - _pd_intrinsics, *_habitat); + _pd_intrinsics, *_habitat, _habitat_handler); _children.insert(&child); + maintain_cells(); + _avail_cpu.percent -= min(_avail_cpu.percent, child.cpu_quota().percent); if (start_node.has_sub_node("provides")) @@ -537,6 +551,16 @@ void Genode::Sandbox::Library::apply_config(Xml_node const &config) _state_reporter.trigger_immediate_report_update(); } +void Genode::Sandbox::Library::maintain_cells() +{ + int xpos = _affinity_space->total(); + int lower_limit = _affinity_space->total() - _core_allocator->cores_available(); + _children.for_each_child([&](Child &child) + { + log(child.name(), " ram: ", child.ram_quota()); + if (!(child.is_brick())) + _core_allocator->update(child, &xpos, &lower_limit); }); +} /********************************* ** Sandbox::Local_service_base ** @@ -682,6 +706,10 @@ void Genode::Sandbox::generate_state_report(Xml_generator &xml) const _library.generate_state_report(xml); } +void Genode::Sandbox::update(::Sandbox::Child &child) +{ + _library.update(child); +} Genode::Sandbox::Sandbox(Env &env, State_handler &state_handler, Pd_intrinsics &pd_intrinsics) :