ealanos: Properly cleanup habitat after cells terminated. Also, limit quota for cell creation by quota available to the habitat.

This commit is contained in:
Michael Mueller
2025-04-22 15:36:02 +02:00
parent 6f7cc95def
commit f279097716
10 changed files with 104 additions and 13 deletions

View File

@@ -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_ */

View File

@@ -33,6 +33,10 @@ struct Ealan::Cell_client : Genode::Rpc_client<Cell>
bool is_brick() override {
return call<Rpc_is_brick>();
}
void die() override {
call<Rpc_die>();
}
};
#endif /* _INCLUDE__CELL__CLIENT_H_ */

View File

@@ -35,5 +35,10 @@ struct Ealan::Habitat_client : Genode::Rpc_client<Ealan::Habitat_session>
{
return call<Rpc_affinity>();
}
void groom() override
{
call<Rpc_groom>();
}
};
#endif

View File

@@ -36,6 +36,11 @@ struct Ealan::Habitat_connection : Genode::Connection<Ealan::Habitat_session>, H
{
return Habitat_client::affinity();
}
void groom() override
{
return Habitat_client::groom();
}
};
#endif

View File

@@ -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<Genode::Pd_session> 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::Pd_session>, 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::Pd_session>, 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

View File

@@ -33,11 +33,16 @@ namespace Ealan {
class Cell_component;
}
namespace Core {
class Habitat_session_component;
}
class Ealan::Cell_component : public Genode::Rpc_object<Cell>,
private Genode::List<Cell_component>::Element
{
private:
friend class Genode::List<Cell_component>;
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<Cell>,
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<Genode::Affinity::Location&>(loc).for_each(
@@ -97,6 +103,7 @@ class Ealan::Cell_component : public Genode::Rpc_object<Cell>,
*/
if (Tukija::create_cell(cell_pd_sel, static_cast<Genode::uint8_t>(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>,
~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<Cell>,
bool is_brick() override {
return _is_brick;
}
void die() override {
_is_dead = true;
}
};
#endif

View File

@@ -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:

View File

@@ -30,12 +30,13 @@
namespace Core { class Habitat_session_component; }
class Core::Habitat_session_component : public Genode::Rpc_object<Ealan::Habitat_session, Habitat_session_component>
class Core::Habitat_session_component : public Genode::Session_object<Ealan::Habitat_session>
{
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<Ealan::Cell_component> _managed_cells { };
@@ -51,7 +52,7 @@ class Core::Habitat_session_component : public Genode::Rpc_object<Ealan::Habitat
}
public:
Habitat_session_component(Genode::Session_label const &label, Genode::Rpc_entrypoint &session_ep, Genode::Region_map &rm, Genode::Ram_allocator &alloc, Genode::Affinity const &affinity) : _local_rm(rm), _affinity(affinity), _label(label), _md_alloc(alloc, rm), _ep(session_ep) {}
Habitat_session_component(Genode::Rpc_entrypoint &ep, Genode::Session::Resources const &resources, Genode::Session_label const &label, Genode::Session::Diag const &diag, Genode::Ram_allocator &ram, Genode::Region_map &rm, Genode::Affinity const &affinity) : Genode::Session_object<Ealan::Habitat_session>(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<Genode::Pd_session> 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<Ealan::Habitat
return Genode::Affinity(core_space, _affinity.location());
}
void groom() override
{
Genode::List<Ealan::Cell_component> 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

View File

@@ -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<uint16_t>(_priority), Genode::Session_label(_unique_name));
try {
_cell_cap = _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast<uint16_t>(_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);
}

View File

@@ -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();
}