Update each cell's cores upon cell destruction.

This commit is contained in:
Michael Mueller
2025-02-24 17:37:18 +01:00
parent f35f6f65b9
commit c15bf4cc11
7 changed files with 126 additions and 68 deletions

View File

@@ -22,7 +22,9 @@
#include <base/heap.h>
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
{

View File

@@ -18,7 +18,7 @@
#include <os/reporter.h>
#include <base/log.h>
#include <tukija/syscall-generic.h>
#include <child.h>
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<Genode::Cap_quota>::Limit_exceeded) {
Genode::log("Caps exceeded while handling child state");
_env.parent().exit(1);
}
}
Main(Env &env) : _env(env)
{
_config.sigh(_config_handler);

View File

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

View File

@@ -755,10 +755,12 @@ Sandbox::Child::Child(Env &env,
Registry<Routed_service> &child_services,
Registry<Local_service> &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, "\"");

View File

@@ -35,9 +35,11 @@
#include <service.h>
#include <utils.h>
#include <route_model.h>
#include <sandbox/sandbox.h>
/* EalánOS includes */
#include <habitat/connection.h>
#include <cell/client.h>
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<Child> _list_element;
Reconstructible<Buffered_xml> _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<Routed_service> &child_services,
Registry<Local_service> &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<uint16_t>(_priority));
_state = State::ALIVE;
_cell_cap = _habitat.create_cell(_child.pd_session_cap(), _resources.affinity, static_cast<uint16_t>(_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

View File

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

View File

@@ -79,6 +79,8 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer,
Constructible<Affinity::Space> _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_service> &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)
: