From d8f2610e9c0417623d0e506e4428811d11a91f0c Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 8 Dec 2016 11:37:08 +0100 Subject: [PATCH] bomb: drop sleep_forever and signal_receiver --- repos/os/src/test/bomb/main.cc | 139 +++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 57 deletions(-) diff --git a/repos/os/src/test/bomb/main.cc b/repos/os/src/test/bomb/main.cc index aaff0d434b..907b5cec63 100644 --- a/repos/os/src/test/bomb/main.cc +++ b/repos/os/src/test/bomb/main.cc @@ -2,10 +2,8 @@ * \brief Fork bomb to stress Genode * \author Christian Helmuth * \author Norman Feske + * \author Alexander Böttcher * \date 2007-08-16 - * - * The better part of this code is derived from the original init - * implementation by Norman. */ /* @@ -17,7 +15,6 @@ #include #include -#include #include #include #include @@ -151,84 +148,112 @@ unique_child_name(Children const &children, Bomb_child::Name const &binary_name, } -void Component::construct(Genode::Env &env) +struct Bomb { - static Attached_rom_dataspace config(env, "config"); - Xml_node node = config.xml(); + Genode::Env &env; - unsigned const rounds = node.attribute_value("rounds", 1U); - unsigned const generation = node.attribute_value("generations", 1U); - unsigned const children = node.attribute_value("children", 2U); - unsigned const sleeptime = node.attribute_value("sleep", 2000U); - unsigned long const demand = node.attribute_value("demand", 1024UL * 1024); + Constructible timer; - log("--- bomb started ---"); + Genode::Signal_handler signal_timeout { env.ep(), *this, &Bomb::destruct_children }; + Genode::Signal_handler signal_resource { env.ep(), *this, &Bomb::resource_request }; - /* try to create timer session, if it fails, bomb is our parent */ - static Constructible timer; - try { timer.construct(env); } catch (Parent::Service_denied) { } + Attached_rom_dataspace config { env, "config" }; - if (timer.constructed()) - log("rounds=", rounds, " generations=", generation, " children=", - children, " sleep=", sleeptime, " demand=", demand/1024, "K"); + unsigned round = 0; + unsigned const rounds = config.xml().attribute_value("rounds", 1U); + unsigned const generation = config.xml().attribute_value("generations", 1U); + unsigned const children = config.xml().attribute_value("children", 2U); + unsigned const sleeptime = config.xml().attribute_value("sleep", 2000U); + unsigned long const demand = config.xml().attribute_value("demand", 1024UL * 1024); + + Heap heap { env.ram(), env.rm() }; + + Children child_registry; /* names of services provided by the parent */ - static const char *names[] = { - "RAM", "PD", "CPU", "ROM", "LOG", 0 }; + const char *names[6] = { "RAM", "PD", "CPU", "ROM", "LOG", 0}; + Registry > parent_services; - static Heap heap(env.ram(), env.rm()); + void construct_children() + { + unsigned long avail = env.ram().avail(); + unsigned long amount = (avail - demand) / children; + if (amount < (demand * children)) { + log("I'm a leaf node - generation ", generation, + " - not enough memory."); + return; + } + if (generation == 0) { + log("I'm a leaf node - generation 0"); + return; + } - static Registry > parent_services; - for (unsigned i = 0; names[i]; i++) - new (heap) Registered(parent_services, names[i]); + log("[", round, "] It's time to start all my children..."); - unsigned long avail = env.ram().avail(); - unsigned long amount = (avail - demand) / children; - if (amount < (demand * children)) { - log("I'm a leaf node - generation ", generation, " - not enough memory."); - sleep_forever(); - } - if (generation == 0) { - log("I'm a leaf node - generation 0"); - sleep_forever(); - } + Bomb_child::Name const binary_name("bomb"); - static Children child_registry; - - Bomb_child::Name const binary_name("bomb"); - - for (unsigned round = 0; round < rounds ; ++round) { for (unsigned i = children; i; --i) { new (heap) Registered(child_registry, env, binary_name, - unique_child_name(child_registry, binary_name, + unique_child_name(child_registry, + binary_name, generation - 1), amount, parent_services, generation - 1); } - /* is init our parent? */ - if (!timer.constructed()) sleep_forever(); + /* master if we have a timer connection */ + if (timer.constructed()) + timer->trigger_once(sleeptime * 1000); + } - /* don't ask parent for further resources if we ran out of memory */ - static Signal_receiver sig_rec; - static Signal_context sig_ctx_res_avail; - if (round == 0) { - /* prevent to block for resource upgrades caused by clients */ - env.parent().resource_avail_sigh(sig_rec.manage(&sig_ctx_res_avail)); - } - - timer->msleep(sleeptime); + void destruct_children() + { log("[", round, "] It's time to kill all my children..."); child_registry.for_each([&] (Registered &child) { destroy(heap, &child); }); log("[", round, "] Done."); + + ++round; + + /* master if we have a timer connection */ + if (round == rounds && timer.constructed()) + log("Done. Going to sleep"); + + construct_children(); } - /* master if we have a timer connection */ - if (timer.constructed()) - log("Done. Going to sleep"); + void resource_request() + { + Genode::error("resource request"); + } - sleep_forever(); -} + Bomb(Genode::Env &env) : env(env) + { + for (unsigned i = 0; names[i]; i++) + new (heap) Registered(parent_services, names[i]); + + /* + * Don't ask parent for further resources if we ran out of memory. + * Prevent us to block for resource upgrades caused by clients + */ + env.parent().resource_avail_sigh(signal_resource); + + log("--- bomb started ---"); + + /* try to create timer session, if it fails, bomb is our parent */ + try { timer.construct(env); } catch (Parent::Service_denied) { } + + if (timer.constructed()) { + timer->sigh(signal_timeout); + + log("rounds=", rounds, " generations=", generation, " children=", + children, " sleep=", sleeptime, " demand=", demand/1024, "K"); + } + + construct_children(); + } +}; + +void Component::construct(Genode::Env &env) { static Bomb bomb(env); }