bomb: drop sleep_forever and signal_receiver

This commit is contained in:
Alexander Boettcher 2016-12-08 11:37:08 +01:00 committed by Norman Feske
parent f613cd2aa9
commit d8f2610e9c

View File

@ -2,10 +2,8 @@
* \brief Fork bomb to stress Genode * \brief Fork bomb to stress Genode
* \author Christian Helmuth * \author Christian Helmuth
* \author Norman Feske * \author Norman Feske
* \author Alexander Böttcher
* \date 2007-08-16 * \date 2007-08-16
*
* The better part of this code is derived from the original init
* implementation by Norman.
*/ */
/* /*
@ -17,7 +15,6 @@
#include <base/component.h> #include <base/component.h>
#include <base/child.h> #include <base/child.h>
#include <base/sleep.h>
#include <base/service.h> #include <base/service.h>
#include <base/attached_rom_dataspace.h> #include <base/attached_rom_dataspace.h>
#include <init/child_policy.h> #include <init/child_policy.h>
@ -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"); Genode::Env &env;
Xml_node node = config.xml();
unsigned const rounds = node.attribute_value("rounds", 1U); Constructible<Timer::Connection> timer;
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);
log("--- bomb started ---"); Genode::Signal_handler<Bomb> signal_timeout { env.ep(), *this, &Bomb::destruct_children };
Genode::Signal_handler<Bomb> signal_resource { env.ep(), *this, &Bomb::resource_request };
/* try to create timer session, if it fails, bomb is our parent */ Attached_rom_dataspace config { env, "config" };
static Constructible<Timer::Connection> timer;
try { timer.construct(env); } catch (Parent::Service_denied) { }
if (timer.constructed()) unsigned round = 0;
log("rounds=", rounds, " generations=", generation, " children=", unsigned const rounds = config.xml().attribute_value("rounds", 1U);
children, " sleep=", sleeptime, " demand=", demand/1024, "K"); 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 */ /* names of services provided by the parent */
static const char *names[] = { const char *names[6] = { "RAM", "PD", "CPU", "ROM", "LOG", 0};
"RAM", "PD", "CPU", "ROM", "LOG", 0 }; Registry<Registered<Parent_service> > parent_services;
static Heap heap(env.ram(), env.rm());
static Registry<Registered<Parent_service> > parent_services;
for (unsigned i = 0; names[i]; i++)
new (heap) Registered<Parent_service>(parent_services, names[i]);
void construct_children()
{
unsigned long avail = env.ram().avail(); unsigned long avail = env.ram().avail();
unsigned long amount = (avail - demand) / children; unsigned long amount = (avail - demand) / children;
if (amount < (demand * children)) { if (amount < (demand * children)) {
log("I'm a leaf node - generation ", generation, " - not enough memory."); log("I'm a leaf node - generation ", generation,
sleep_forever(); " - not enough memory.");
return;
} }
if (generation == 0) { if (generation == 0) {
log("I'm a leaf node - generation 0"); log("I'm a leaf node - generation 0");
sleep_forever(); return;
} }
static Children child_registry; log("[", round, "] It's time to start all my children...");
Bomb_child::Name const binary_name("bomb"); Bomb_child::Name const binary_name("bomb");
for (unsigned round = 0; round < rounds ; ++round) {
for (unsigned i = children; i; --i) { for (unsigned i = children; i; --i) {
new (heap) new (heap)
Registered<Bomb_child>(child_registry, env, binary_name, Registered<Bomb_child>(child_registry, env, binary_name,
unique_child_name(child_registry, binary_name, unique_child_name(child_registry,
binary_name,
generation - 1), generation - 1),
amount, parent_services, generation - 1); amount, parent_services, generation - 1);
} }
/* is init our parent? */ /* master if we have a timer connection */
if (!timer.constructed()) sleep_forever(); 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..."); log("[", round, "] It's time to kill all my children...");
child_registry.for_each([&] (Registered<Bomb_child> &child) { child_registry.for_each([&] (Registered<Bomb_child> &child) {
destroy(heap, &child); }); destroy(heap, &child); });
log("[", round, "] Done."); log("[", round, "] Done.");
}
++round;
/* master if we have a timer connection */ /* master if we have a timer connection */
if (timer.constructed()) if (round == rounds && timer.constructed())
log("Done. Going to sleep"); log("Done. Going to sleep");
sleep_forever(); construct_children();
} }
void resource_request()
{
Genode::error("resource request");
}
Bomb(Genode::Env &env) : env(env)
{
for (unsigned i = 0; names[i]; i++)
new (heap) Registered<Parent_service>(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); }