From 5ec07614e84aeea69be2d2e178acba182af9dbb6 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 8 Aug 2013 14:18:20 +0200 Subject: [PATCH] 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: ... ... Subsystems can be constrained to parts of the affinity space using the '' sub node of a '' entry: ... ... ... --- os/include/init/child.h | 58 ++++++++++++++++++++++++++++++++++------- os/src/init/main.cc | 24 +++++++++++++++-- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/os/include/init/child.h b/os/include/init/child.h index fb762ed854..f008c3dcd2 100644 --- a/os/include/init/child.h +++ b/os/include/init/child.h @@ -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("width", default_width), + height = node.attribute_value("height", default_height); + + long const x1 = node.attribute_value("xpos", 0), + y1 = node.attribute_value("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 + @@ -439,13 +476,14 @@ namespace Init { public: - Child(Genode::Xml_node start_node, - Genode::Xml_node default_route_node, - Name_registry *name_registry, - long prio_levels_log2, - Genode::Service_registry *parent_services, - Genode::Service_registry *child_services, - Genode::Cap_session *cap_session) + Child(Genode::Xml_node start_node, + 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) : _list_element(this), _start_node(start_node), @@ -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), diff --git a/os/src/init/main.cc b/os/src/init/main.cc index d780379c6c..bcf50e28aa 100644 --- a/os/src/init/main.cc +++ b/os/src/init/main.cc @@ -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("width", 1), + node.attribute_value("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) {