init: Read affinity assignments from config

The assignment of affinities consists of two parts, the definition
of the affinity space dimensions as used for the init process, and
the association sub systems with affinity locations (relative to the
affinity space). The affinity space is configured as a sub node of the
config node. For example, the following declaration describes an
affinity space of 4x2:

<config>
  ...
  <affinity_space width="4" height="2" />
  ...
</config>

Subsystems can be constrained to parts of the affinity space using
the '<affinity>' sub node of a '<start>' entry:

<config>
  ...
  <start name="loader">
    <affinity xpos="0" ypos="1" width="2" height="1" />
    ...
  </start>
  ...
</config>
This commit is contained in:
Norman Feske 2013-08-08 14:18:20 +02:00
parent 9111f060f5
commit 5ec07614e8
2 changed files with 70 additions and 12 deletions

View File

@ -51,6 +51,37 @@ namespace Init {
}
inline Genode::Affinity::Location
read_affinity_location(Genode::Affinity::Space const &space,
Genode::Xml_node start_node)
{
typedef Genode::Affinity::Location Location;
try {
Genode::Xml_node node = start_node.sub_node("affinity");
/* if no position value is specified, select the whole row/column */
unsigned long const
default_width = node.has_attribute("xpos") ? 1 : space.width(),
default_height = node.has_attribute("ypos") ? 1 : space.height();
unsigned long const
width = node.attribute_value<unsigned long>("width", default_width),
height = node.attribute_value<unsigned long>("height", default_height);
long const x1 = node.attribute_value<long>("xpos", 0),
y1 = node.attribute_value<long>("ypos", 0),
x2 = x1 + width - 1,
y2 = y1 + height - 1;
/* clip location to space boundary */
return Location(Genode::max(x1, 0L), Genode::max(y1, 0L),
Genode::min((unsigned)(x2 - x1 + 1), space.width()),
Genode::min((unsigned)(y2 - y1 + 1), space.height()));
}
catch (...) { return Location(0, 0, space.width(), space.height()); }
}
inline Genode::size_t read_ram_quota(Genode::Xml_node start_node)
{
Genode::Number_of_bytes ram_quota = 0;
@ -371,19 +402,25 @@ namespace Init {
{
long prio_levels_log2;
long priority;
Genode::Affinity affinity;
Genode::size_t ram_quota;
Genode::Ram_connection ram;
Genode::Cpu_connection cpu;
Genode::Rm_connection rm;
Resources(Genode::Xml_node start_node, const char *label,
long prio_levels_log2)
long prio_levels_log2,
Genode::Affinity::Space const &affinity_space)
:
prio_levels_log2(prio_levels_log2),
priority(read_priority(start_node)),
affinity(affinity_space,
read_affinity_location(affinity_space, start_node)),
ram_quota(read_ram_quota(start_node)),
ram(label),
cpu(label, priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2))
cpu(label,
priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2),
affinity)
{
/* deduce session costs from usable ram quota */
Genode::size_t session_donations = Genode::Rm_connection::RAM_QUOTA +
@ -443,6 +480,7 @@ namespace Init {
Genode::Xml_node default_route_node,
Name_registry *name_registry,
long prio_levels_log2,
Genode::Affinity::Space const &affinity_space,
Genode::Service_registry *parent_services,
Genode::Service_registry *child_services,
Genode::Cap_session *cap_session)
@ -453,7 +491,7 @@ namespace Init {
_name_registry(name_registry),
_name(start_node, name_registry),
_pd_args(start_node),
_resources(start_node, _name.unique, prio_levels_log2),
_resources(start_node, _name.unique, prio_levels_log2, affinity_space),
_entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false),
_binary_rom(_name.file, _name.unique),
_config(_resources.ram.cap(), start_node),

View File

@ -24,7 +24,7 @@ namespace Init { bool config_verbose = false; }
***************/
/**
* Read priority-levels declaration from config file
* Read priority-levels declaration from config
*/
inline long read_prio_levels_log2()
{
@ -44,7 +44,26 @@ inline long read_prio_levels_log2()
/**
* Read parent-provided services from config file
* Read affinity-space parameters from config
*
* If no affinity space is declared, construct a space with a single element,
* width and height being 1. If only one of both dimensions is specified, the
* other dimension is set to 1.
*/
inline Genode::Affinity::Space read_affinity_space()
{
using namespace Genode;
try {
Xml_node node = config()->xml_node().sub_node("affinity-space");
return Affinity::Space(node.attribute_value<unsigned long>("width", 1),
node.attribute_value<unsigned long>("height", 1));
} catch (...) {
return Affinity::Space(1, 1); }
}
/**
* Read parent-provided services from config
*/
inline void determine_parent_services(Genode::Service_registry *services)
{
@ -192,6 +211,7 @@ int main(int, char **)
children.insert(new (env()->heap())
Init::Child(start_node, default_route_node,
&children, read_prio_levels_log2(),
read_affinity_space(),
&parent_services, &child_services, &cap));
}
catch (Rom_connection::Rom_connection_failed) {