mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
ealanos: Properly cleanup habitat after cells terminated. Also, limit quota for cell creation by quota available to the habitat.
This commit is contained in:
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user