mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
306 lines
7.9 KiB
C++
306 lines
7.9 KiB
C++
|
|
#include <sandbox/child.h>
|
|
#include <sandbox/alias.h>
|
|
#include <sandbox/server.h>
|
|
#include <sandbox/heartbeat.h>
|
|
#include <sandbox/config_model.h>
|
|
#include <sandbox/sandbox.h>
|
|
|
|
#include <base/env.h>
|
|
#include <base/heap.h>
|
|
#include <base/attached_rom_dataspace.h>
|
|
#include <util/xml_node.h>
|
|
#include <util/noncopyable.h>
|
|
#include <base/registry.h>
|
|
#include <base/service.h>
|
|
|
|
#pragma once
|
|
namespace Sandbox {
|
|
class Library;
|
|
}
|
|
|
|
namespace Genode {
|
|
class Sandbox;
|
|
}
|
|
struct Sandbox::Library : ::Sandbox::State_reporter::Producer,
|
|
::Sandbox::Child::Default_route_accessor,
|
|
::Sandbox::Child::Default_caps_accessor,
|
|
::Sandbox::Child::Ram_limit_accessor,
|
|
::Sandbox::Child::Cap_limit_accessor,
|
|
::Sandbox::Child::Cpu_limit_accessor,
|
|
::Sandbox::Child::Cpu_quota_transfer,
|
|
::Sandbox::Start_model::Factory,
|
|
::Sandbox::Parent_provides_model::Factory
|
|
{
|
|
using Routed_service = ::Sandbox::Routed_service;
|
|
using Parent_service = ::Sandbox::Parent_service;
|
|
using Local_service = ::Genode::Sandbox::Local_service_base;
|
|
using Report_detail = ::Sandbox::Report_detail;
|
|
using Child_registry = ::Sandbox::Child_registry;
|
|
using Verbose = ::Sandbox::Verbose;
|
|
using State_reporter = ::Sandbox::State_reporter;
|
|
using Heartbeat = ::Sandbox::Heartbeat;
|
|
using Server = ::Sandbox::Server;
|
|
using Alias = ::Sandbox::Alias;
|
|
using Child = ::Sandbox::Child;
|
|
using Prio_levels = ::Sandbox::Prio_levels;
|
|
using Ram_info = ::Sandbox::Ram_info;
|
|
using Cap_info = ::Sandbox::Cap_info;
|
|
using Cpu_quota = ::Sandbox::Cpu_quota;
|
|
using Config_model = ::Sandbox::Config_model;
|
|
using Start_model = ::Sandbox::Start_model;
|
|
using Preservation = ::Sandbox::Preservation;
|
|
using Pd_intrinsics = Genode::Sandbox::Pd_intrinsics;
|
|
|
|
using State_handler = Genode::Sandbox::State_handler;
|
|
|
|
Env &_env;
|
|
Heap &_heap;
|
|
|
|
Pd_intrinsics &_pd_intrinsics;
|
|
|
|
Registry<Parent_service> _parent_services{};
|
|
Registry<Routed_service> _child_services{};
|
|
Registry<Local_service> &_local_services;
|
|
Child_registry _children{};
|
|
|
|
/*
|
|
* Global parameters obtained from config
|
|
*/
|
|
Reconstructible<Verbose> _verbose{};
|
|
Config_model::Version _version{};
|
|
Constructible<Buffered_xml> _default_route{};
|
|
Cap_quota _default_caps{0};
|
|
Prio_levels _prio_levels{};
|
|
Constructible<Affinity::Space> _affinity_space{};
|
|
Preservation _preservation{};
|
|
|
|
Affinity::Space _effective_affinity_space() const
|
|
{
|
|
return _affinity_space.constructed() ? *_affinity_space
|
|
: Affinity::Space{1, 1};
|
|
}
|
|
|
|
State_reporter _state_reporter;
|
|
|
|
Heartbeat _heartbeat{_env, _children, _state_reporter};
|
|
|
|
/*
|
|
* Internal representation of the XML configuration
|
|
*/
|
|
Config_model _config_model{};
|
|
|
|
/*
|
|
* Variables for tracking the side effects of updating the config model
|
|
*/
|
|
bool _server_appeared_or_disappeared = false;
|
|
bool _state_report_outdated = false;
|
|
|
|
unsigned _child_cnt = 0;
|
|
|
|
Cpu_quota _avail_cpu{.percent = 100};
|
|
Cpu_quota _transferred_cpu{.percent = 0};
|
|
|
|
Ram_quota _avail_ram() const
|
|
{
|
|
Ram_quota avail_ram = _env.pd().avail_ram();
|
|
|
|
if (_preservation.ram.value > avail_ram.value)
|
|
{
|
|
error("RAM preservation exceeds available memory");
|
|
return Ram_quota{0};
|
|
}
|
|
|
|
/* deduce preserved quota from available quota */
|
|
return Ram_quota{avail_ram.value - _preservation.ram.value};
|
|
}
|
|
|
|
Cap_quota _avail_caps() const
|
|
{
|
|
Cap_quota avail_caps{_env.pd().avail_caps().value};
|
|
|
|
if (_preservation.caps.value > avail_caps.value)
|
|
{
|
|
error("Capability preservation exceeds available capabilities");
|
|
return Cap_quota{0};
|
|
}
|
|
|
|
/* deduce preserved quota from available quota */
|
|
return Cap_quota{avail_caps.value - _preservation.caps.value};
|
|
}
|
|
|
|
/**
|
|
* Child::Ram_limit_accessor interface
|
|
*/
|
|
Ram_quota resource_limit(Ram_quota const &) const override
|
|
{
|
|
return _avail_ram();
|
|
}
|
|
|
|
/**
|
|
* Child::Cap_limit_accessor interface
|
|
*/
|
|
Cap_quota resource_limit(Cap_quota const &) const override { return _avail_caps(); }
|
|
|
|
/**
|
|
* Child::Cpu_limit_accessor interface
|
|
*/
|
|
Cpu_quota resource_limit(Cpu_quota const &) const override { return _avail_cpu; }
|
|
|
|
/**
|
|
* Child::Cpu_quota_transfer interface
|
|
*/
|
|
void transfer_cpu_quota(Capability<Pd_session> pd_cap, Pd_session &pd,
|
|
Capability<Cpu_session> cpu, Cpu_quota quota) override
|
|
{
|
|
Cpu_quota const remaining{100 - min(100u, _transferred_cpu.percent)};
|
|
|
|
/* prevent division by zero in 'quota_lim_upscale' */
|
|
if (remaining.percent == 0)
|
|
return;
|
|
|
|
size_t const fraction =
|
|
Cpu_session::quota_lim_upscale(quota.percent, remaining.percent);
|
|
|
|
Child::with_pd_intrinsics(_pd_intrinsics, pd_cap, pd, [&](auto &intrinsics)
|
|
{ intrinsics.ref_cpu.transfer_quota(cpu, fraction); });
|
|
|
|
_transferred_cpu.percent += quota.percent;
|
|
}
|
|
|
|
/**
|
|
* State_reporter::Producer interface
|
|
*/
|
|
void produce_state_report(Xml_generator &xml, Report_detail const &detail) const override
|
|
{
|
|
if (detail.init_ram())
|
|
xml.node("ram", [&]()
|
|
{ Ram_info::from_pd(_env.pd()).generate(xml); });
|
|
|
|
if (detail.init_caps())
|
|
xml.node("caps", [&]()
|
|
{ Cap_info::from_pd(_env.pd()).generate(xml); });
|
|
|
|
if (detail.children())
|
|
_children.report_state(xml, detail);
|
|
}
|
|
|
|
/**
|
|
* State_reporter::Producer interface
|
|
*/
|
|
Child::Sample_state_result sample_children_state() override
|
|
{
|
|
return _children.sample_state();
|
|
}
|
|
|
|
/**
|
|
* Default_route_accessor interface
|
|
*/
|
|
Xml_node default_route() override
|
|
{
|
|
return _default_route.constructed() ? _default_route->xml()
|
|
: Xml_node("<empty/>");
|
|
}
|
|
|
|
/**
|
|
* Default_caps_accessor interface
|
|
*/
|
|
Cap_quota default_caps() override { return _default_caps; }
|
|
|
|
void _update_aliases_from_config(Xml_node const &);
|
|
void _update_parent_services_from_config(Xml_node const &);
|
|
void _update_children_config(Xml_node const &);
|
|
void _destroy_abandoned_parent_services();
|
|
void _destroy_abandoned_children();
|
|
|
|
Server _server{_env, _heap, _child_services, _state_reporter};
|
|
|
|
/**
|
|
* Sandbox::Start_model::Factory
|
|
*/
|
|
Child &create_child(Xml_node const &) override;
|
|
|
|
/**
|
|
* Sandbox::Start_model::Factory
|
|
*/
|
|
void update_child(Child &, Xml_node const &) override;
|
|
|
|
/**
|
|
* Sandbox::Start_model::Factory
|
|
*/
|
|
Alias &create_alias(Child_policy::Name const &name) override
|
|
{
|
|
Alias &alias = *new (_heap) Alias(name);
|
|
_children.insert_alias(&alias);
|
|
return alias;
|
|
}
|
|
|
|
/**
|
|
* Sandbox::Start_model::Factory
|
|
*/
|
|
void destroy_alias(Alias &alias) override
|
|
{
|
|
_children.remove_alias(&alias);
|
|
destroy(_heap, &alias);
|
|
}
|
|
|
|
/**
|
|
* Sandbox::Start_model::Factory
|
|
*/
|
|
bool ready_to_create_child(Start_model::Name const &,
|
|
Start_model::Version const &) const override;
|
|
|
|
/**
|
|
* Sandbox::Parent_provides_model::Factory
|
|
*/
|
|
Parent_service &create_parent_service(Service::Name const &name) override
|
|
{
|
|
return *new (_heap) Parent_service(_parent_services, _env, name);
|
|
}
|
|
|
|
/**
|
|
* Default way of using the 'Env::pd' as the child's 'ref_pd' and accessing
|
|
* the child's address space via RPC.
|
|
*/
|
|
struct Default_pd_intrinsics : Pd_intrinsics
|
|
{
|
|
Env &_env;
|
|
|
|
void with_intrinsics(Capability<Pd_session>, Pd_session &pd, Fn const &fn) override
|
|
{
|
|
Region_map_client region_map(pd.address_space());
|
|
|
|
Intrinsics intrinsics{_env.pd(), _env.pd_session_cap(),
|
|
_env.cpu(), _env.cpu_session_cap(), region_map};
|
|
fn.call(intrinsics);
|
|
}
|
|
|
|
void start_initial_thread(Capability<Cpu_thread> cap, addr_t ip) override
|
|
{
|
|
Cpu_thread_client(cap).start(ip, 0);
|
|
}
|
|
|
|
Default_pd_intrinsics(Env &env) : _env(env) {}
|
|
|
|
} _default_pd_intrinsics{_env};
|
|
|
|
Library(Env &env, Heap &heap, Registry<Local_service> &local_services,
|
|
State_handler &state_handler, Pd_intrinsics &pd_intrinsics)
|
|
: _env(env), _heap(heap), _pd_intrinsics(pd_intrinsics),
|
|
_local_services(local_services), _state_reporter(_env, *this, state_handler)
|
|
{
|
|
}
|
|
|
|
Library(Env &env, Heap &heap, Registry<Local_service> &local_services,
|
|
State_handler &state_handler)
|
|
: Library(env, heap, local_services, state_handler, _default_pd_intrinsics)
|
|
{
|
|
}
|
|
|
|
void apply_config(Xml_node const &);
|
|
|
|
void generate_state_report(Xml_generator &xml) const
|
|
{
|
|
_state_reporter.generate(xml);
|
|
}
|
|
}; |