mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 15:02:25 +00:00
bomb: drop sleep_forever and signal_receiver
This commit is contained in:
parent
f613cd2aa9
commit
d8f2610e9c
@ -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); }
|
||||||
|
Loading…
Reference in New Issue
Block a user