diff --git a/repos/base-tukija/include/cell/cell.h b/repos/base-tukija/include/cell/cell.h index 371f295b98..ed872dd440 100644 --- a/repos/base-tukija/include/cell/cell.h +++ b/repos/base-tukija/include/cell/cell.h @@ -27,13 +27,16 @@ namespace Ealan { struct Cell; struct Ealan::Cell : Genode::Interface { enum { CAP_QUOTA = 1 }; + class Cell_creation_error : public Genode::Exception {}; virtual void update(Genode::Affinity &affinity) = 0; virtual bool is_brick() = 0; + virtual void die() = 0; GENODE_RPC(Rpc_update, void, update, Genode::Affinity &); GENODE_RPC(Rpc_is_brick, bool, is_brick); + GENODE_RPC(Rpc_die, void, die); - GENODE_RPC_INTERFACE(Rpc_update, Rpc_is_brick); + GENODE_RPC_INTERFACE(Rpc_update, Rpc_is_brick, Rpc_die); }; #endif /* _INCLUDE__CELL__SESSION_H_ */ \ No newline at end of file diff --git a/repos/base-tukija/include/cell/client.h b/repos/base-tukija/include/cell/client.h index e24273b0ec..9d91fc3a34 100644 --- a/repos/base-tukija/include/cell/client.h +++ b/repos/base-tukija/include/cell/client.h @@ -33,6 +33,10 @@ struct Ealan::Cell_client : Genode::Rpc_client bool is_brick() override { return call(); } + + void die() override { + call(); + } }; #endif /* _INCLUDE__CELL__CLIENT_H_ */ \ No newline at end of file diff --git a/repos/base-tukija/include/habitat/client.h b/repos/base-tukija/include/habitat/client.h index f8bdab3726..533ac66622 100644 --- a/repos/base-tukija/include/habitat/client.h +++ b/repos/base-tukija/include/habitat/client.h @@ -35,5 +35,10 @@ struct Ealan::Habitat_client : Genode::Rpc_client { return call(); } + + void groom() override + { + call(); + } }; #endif \ No newline at end of file diff --git a/repos/base-tukija/include/habitat/connection.h b/repos/base-tukija/include/habitat/connection.h index f64739720b..917ee0cc87 100644 --- a/repos/base-tukija/include/habitat/connection.h +++ b/repos/base-tukija/include/habitat/connection.h @@ -36,6 +36,11 @@ struct Ealan::Habitat_connection : Genode::Connection, H { return Habitat_client::affinity(); } + + void groom() override + { + return Habitat_client::groom(); + } }; #endif diff --git a/repos/base-tukija/include/habitat/session.h b/repos/base-tukija/include/habitat/session.h index 0d73db0f88..93d6742bb9 100644 --- a/repos/base-tukija/include/habitat/session.h +++ b/repos/base-tukija/include/habitat/session.h @@ -27,18 +27,28 @@ struct Ealan::Habitat_session : Genode::Session { static const char *service_name() { return "Habitat"; } - enum { CAP_QUOTA = 1, RAM_QUOTA = 1024 }; + static constexpr Genode::size_t MAX_NUM_CELLS = 256; + // Same as Core::Platform::MAX_SUPPORTED_CPUS; + static constexpr unsigned CAP_QUOTA = MAX_NUM_CELLS; + static constexpr Genode::size_t RAM_QUOTA = MAX_NUM_CELLS*32*1024; /** * Attach cell info page to the cells virtual memory space */ virtual Cell_capability create_cell(Genode::Capability pd, Genode::Affinity &affinity, Genode::uint16_t prio, Genode::Session_label const &label) = 0; + /** + * @brief Clean up the habitat by removing terminated cells and freeing their memory + * + */ + virtual void groom() = 0; + virtual Genode::Affinity affinity() = 0; - GENODE_RPC(Rpc_create_cell, Cell_capability, create_cell, Genode::Capability, Genode::Affinity &, Genode::uint16_t, Genode::Session_label const &); + GENODE_RPC_THROW(Rpc_create_cell, Cell_capability, create_cell, GENODE_TYPE_LIST(Ealan::Cell::Cell_creation_error), Genode::Capability, Genode::Affinity &, Genode::uint16_t, Genode::Session_label const &); GENODE_RPC(Rpc_affinity, Genode::Affinity, affinity); + GENODE_RPC(Rpc_groom, void, groom); - GENODE_RPC_INTERFACE(Rpc_create_cell, Rpc_affinity); + GENODE_RPC_INTERFACE(Rpc_create_cell, Rpc_affinity, Rpc_groom); }; #endif \ No newline at end of file diff --git a/repos/base-tukija/src/core/include/cell_component.h b/repos/base-tukija/src/core/include/cell_component.h index a63358fe53..68c0c17a44 100644 --- a/repos/base-tukija/src/core/include/cell_component.h +++ b/repos/base-tukija/src/core/include/cell_component.h @@ -33,11 +33,16 @@ namespace Ealan { class Cell_component; } +namespace Core { + class Habitat_session_component; +} + class Ealan::Cell_component : public Genode::Rpc_object, private Genode::List::Element { private: friend class Genode::List; + friend class Core::Habitat_session_component; Genode::Rpc_entrypoint &_ep; Genode::Session_label const _session_label; @@ -49,7 +54,8 @@ class Ealan::Cell_component : public Genode::Rpc_object, Tukija::Cip *_cip{nullptr}; bool _is_brick{false}; - + bool _is_dead{false}; + void _calculate_mask_for_location(Tukija::Cpuset *coreset, const Genode::Affinity::Location &loc) { const_cast(loc).for_each( @@ -97,6 +103,7 @@ class Ealan::Cell_component : public Genode::Rpc_object, */ if (Tukija::create_cell(cell_pd_sel, static_cast(prio), cip_phys, cip_virt)) { Genode::error("Failed to create cell at Tukija."); + throw Cell_creation_error(); } /* We need to specify the pre-reserved CPU cores from this cell. @@ -124,9 +131,15 @@ class Ealan::Cell_component : public Genode::Rpc_object, ~Cell_component() { + Genode::log("Destroying Cell session"); + Core::platform().region_alloc().free(_cip); _ep.dissolve(this); } + bool is_dead() { + return _is_dead; + } + /******************** ** Cell interface ** ********************/ @@ -145,6 +158,10 @@ class Ealan::Cell_component : public Genode::Rpc_object, bool is_brick() override { return _is_brick; } + + void die() override { + _is_dead = true; + } }; #endif \ No newline at end of file diff --git a/repos/base-tukija/src/core/include/habitat_root.h b/repos/base-tukija/src/core/include/habitat_root.h index a72f9d482e..612ef41b81 100644 --- a/repos/base-tukija/src/core/include/habitat_root.h +++ b/repos/base-tukija/src/core/include/habitat_root.h @@ -20,18 +20,31 @@ namespace Core { Habitat_session_component *_create_session(char const *args, Genode::Affinity const &affinity) override { + size_t ram_quota = + Arg_string::find_arg(args, "ram_quota").ulong_value(0); + + if (ram_quota < Trace::Control_area::SIZE) + throw Insufficient_ram_quota(); + if (!affinity.valid()) { Genode::error("Invalid affinity space: ", affinity); throw Genode::Service_denied(); } - return new (md_alloc()) Habitat_session_component(session_label_from_args(args), _session_ep, _local_rm, _ram_alloc, affinity); + return new (md_alloc()) Habitat_session_component( + *this->ep(), + session_resources_from_args(args), + session_label_from_args(args), + session_diag_from_args(args), + _ram_alloc, + _local_rm, + affinity); } - void _upgrade_session(Habitat_session_component *, const char *) override + void _upgrade_session(Habitat_session_component *habitat, const char *args) override { - //habitat->upgrade(Genode::ram_quota_from_args(args)); - //habitat->upgrade(Genode::cap_quota_from_args(args)); + habitat->upgrade(Genode::ram_quota_from_args(args)); + habitat->upgrade(Genode::cap_quota_from_args(args)); } public: diff --git a/repos/base-tukija/src/core/include/habitat_session_component.h b/repos/base-tukija/src/core/include/habitat_session_component.h index 7e3e11a41b..06df1f42b5 100644 --- a/repos/base-tukija/src/core/include/habitat_session_component.h +++ b/repos/base-tukija/src/core/include/habitat_session_component.h @@ -30,12 +30,13 @@ namespace Core { class Habitat_session_component; } -class Core::Habitat_session_component : public Genode::Rpc_object +class Core::Habitat_session_component : public Genode::Session_object { private: Genode::Region_map &_local_rm; Genode::Affinity const &_affinity; Genode::Session_label const &_label; + Genode::Constrained_ram_allocator _ram_alloc; Genode::Sliced_heap _md_alloc; Genode::Rpc_entrypoint &_ep; Genode::List _managed_cells { }; @@ -51,7 +52,7 @@ class Core::Habitat_session_component : public Genode::Rpc_object(ep, resources, label, diag), _local_rm(rm), _affinity(affinity), _label(label), _ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()), _md_alloc(_ram_alloc, rm), _ep(ep) {} Ealan::Cell_capability create_cell(Genode::Capability pd_cap, [[maybe_unused]] Genode::Affinity &affinity, Genode::uint16_t prio, Genode::Session_label const &label) override { @@ -68,6 +69,28 @@ class Core::Habitat_session_component : public Genode::Rpc_object dead_cells{}; + for (Ealan::Cell_component *cell = _managed_cells.first(); cell != nullptr; cell = cell->next()) + { + if (cell->is_dead()) + dead_cells.insert(cell); + } + + Genode::size_t count = 0; + for (Ealan::Cell_component *cell = dead_cells.first(); cell != nullptr;) + { + Ealan::Cell_component *dead_cell = cell; + cell = dead_cell->next(); + _managed_cells.remove(dead_cell); + destroy(_md_alloc, dead_cell); + count++; + } + + Genode::log("Removed ", count, " dead cells from habitat"); + } }; #endif \ No newline at end of file diff --git a/repos/ealanos/src/lib/sandbox/child.h b/repos/ealanos/src/lib/sandbox/child.h index fa2ee2e6c3..df3007c556 100644 --- a/repos/ealanos/src/lib/sandbox/child.h +++ b/repos/ealanos/src/lib/sandbox/child.h @@ -649,7 +649,12 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup _child.initiate_env_sessions(); if (_child.active()) { - _cell_cap = _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast(_priority), Genode::Session_label(_unique_name)); + try { + _cell_cap = _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast(_priority), Genode::Session_label(_unique_name)); + } catch (Ealan::Cell::Cell_creation_error) { + Genode::error("Failed to create cell"); + abandon(); + } Genode::log("Created new cell ", _unique_name, " ", _cell_cap); _state = State::ALIVE; } else @@ -671,7 +676,9 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup void destroy_services(); - void close_all_sessions() { _child.close_all_sessions(); } + void close_all_sessions() { + + _child.close_all_sessions(); } bool abandoned() const { return _state == State::ABANDONED; } @@ -810,6 +817,9 @@ class Sandbox::Child : Child_policy, Routed_service::Wakeup */ Child_policy::exit(exit_value); + Ealan::Cell_client cell_client(_cell_cap); + cell_client.die(); + Genode::log("Notifying Hoitaja"); _habitat_handler.handle_child_state(*this); } diff --git a/repos/ealanos/src/lib/sandbox/library.cc b/repos/ealanos/src/lib/sandbox/library.cc index e84b75a735..b9b55f5915 100644 --- a/repos/ealanos/src/lib/sandbox/library.cc +++ b/repos/ealanos/src/lib/sandbox/library.cc @@ -356,6 +356,7 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, }; Genode::log("Removed child ", child.name()); + _habitat->groom(); apply_config(*config); maintain_cells(); }