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