2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Test for signalling framework
|
|
|
|
* \author Norman Feske
|
2017-01-17 12:58:00 +01:00
|
|
|
* \author Martin Stein
|
2011-12-22 16:19:25 +01:00
|
|
|
* \date 2008-09-06
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-01-17 12:58:00 +01:00
|
|
|
* Copyright (C) 2008-2017 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/* Genode includes */
|
2016-11-06 14:27:26 +01:00
|
|
|
#include <base/component.h>
|
|
|
|
#include <base/heap.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <base/thread.h>
|
2017-01-17 12:58:00 +01:00
|
|
|
#include <base/registry.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <timer_session/connection.h>
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
/**
|
2017-01-17 12:58:00 +01:00
|
|
|
* A thread that submits a signal context in a periodic fashion
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:27:26 +01:00
|
|
|
class Sender : Thread
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Timer::Connection _timer;
|
2016-11-06 14:27:26 +01:00
|
|
|
Signal_transmitter _transmitter;
|
2017-01-17 12:58:00 +01:00
|
|
|
unsigned const _interval_ms;
|
|
|
|
bool const _verbose;
|
|
|
|
bool _stop { false };
|
|
|
|
unsigned _submit_cnt { 0 };
|
|
|
|
bool _idle { false };
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
void entry()
|
|
|
|
{
|
|
|
|
while (!_stop) {
|
|
|
|
if (!_idle) {
|
|
|
|
_submit_cnt++;
|
2017-01-17 12:58:00 +01:00
|
|
|
if (_verbose) {
|
|
|
|
log("submit signal ", _submit_cnt); }
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
_transmitter.submit();
|
2017-01-17 12:58:00 +01:00
|
|
|
if (_interval_ms) {
|
|
|
|
_timer.msleep(_interval_ms); }
|
|
|
|
} else {
|
|
|
|
_timer.msleep(100); }
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Sender(Env &env,
|
|
|
|
Signal_context_capability context,
|
|
|
|
unsigned interval_ms,
|
|
|
|
bool verbose)
|
2011-12-22 16:19:25 +01:00
|
|
|
:
|
2017-01-17 12:58:00 +01:00
|
|
|
Thread(env, "sender", 4096 * sizeof(addr_t)), _timer(env),
|
|
|
|
_transmitter(context), _interval_ms(interval_ms), _verbose(verbose)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
Thread::start();
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
void idle(bool idle) { _idle = idle; }
|
|
|
|
unsigned submit_cnt() const { return _submit_cnt; }
|
2011-12-22 16:19:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2017-01-17 12:58:00 +01:00
|
|
|
* A thread that receives signals and takes some time to handle each
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-11-06 14:27:26 +01:00
|
|
|
class Handler : Thread
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Timer::Connection _timer;
|
|
|
|
unsigned const _dispatch_ms;
|
|
|
|
unsigned const _id;
|
|
|
|
bool const _verbose;
|
|
|
|
Signal_receiver &_receiver;
|
|
|
|
bool _stop { false };
|
|
|
|
unsigned _receive_cnt { 0 };
|
|
|
|
unsigned _activation_cnt { 0 };
|
|
|
|
bool _idle { false };
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
void entry()
|
|
|
|
{
|
|
|
|
while (!_stop) {
|
|
|
|
if (!_idle) {
|
2016-11-06 14:27:26 +01:00
|
|
|
Signal signal = _receiver.wait_for_signal();
|
2011-12-22 16:19:25 +01:00
|
|
|
if (_verbose)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
log("handler ", _id, " got ", signal.num(), " "
|
|
|
|
"signal", (signal.num() == 1 ? "" : "s"), " "
|
|
|
|
"with context ", signal.context());
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
_receive_cnt += signal.num();
|
|
|
|
_activation_cnt++;
|
|
|
|
}
|
|
|
|
if (_dispatch_ms)
|
|
|
|
_timer.msleep(_dispatch_ms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Handler(Env &env,
|
|
|
|
Signal_receiver &receiver,
|
|
|
|
unsigned dispatch_ms,
|
|
|
|
bool verbose,
|
|
|
|
unsigned id)
|
2011-12-22 16:19:25 +01:00
|
|
|
:
|
2017-01-17 12:58:00 +01:00
|
|
|
Thread(env, "handler", 4096 * sizeof(addr_t)), _timer(env),
|
|
|
|
_dispatch_ms(dispatch_ms), _id(id), _verbose(verbose),
|
|
|
|
_receiver(receiver)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
Thread::start();
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
void print(Output &output) const { Genode::print(output, "handler ", _id); }
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
void idle(bool idle) { _idle = idle; }
|
|
|
|
unsigned receive_cnt() const { return _receive_cnt; }
|
2013-01-10 20:56:48 +01:00
|
|
|
unsigned activation_cnt() const { return _activation_cnt; }
|
2011-12-22 16:19:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2017-01-17 12:58:00 +01:00
|
|
|
* Base of all signalling tests
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Signal_test
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
enum { SPEED = 10 };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
int id;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Signal_test(int id, char const *brief) : id(id) {
|
|
|
|
log("\nTEST ", id, ": ", brief, "\n"); }
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
~Signal_test() { log("\nTEST ", id, " finished\n"); }
|
2011-12-22 16:19:25 +01:00
|
|
|
};
|
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Fast_sender_test : Signal_test
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief =
|
|
|
|
"reliable delivery if the sender is faster than the handlers";
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
enum { HANDLER_INTERVAL_MS = 10 * SPEED,
|
|
|
|
SENDER_INTERVAL_MS = 2 * SPEED,
|
|
|
|
DURATION_MS = 50 * SPEED,
|
|
|
|
FINISH_IDLE_MS = 2 * HANDLER_INTERVAL_MS };
|
2013-11-25 09:30:51 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Unequal_sent_and_received_signals : Exception { };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Env &env;
|
|
|
|
Timer::Connection timer { env };
|
|
|
|
Signal_context context;
|
|
|
|
Signal_receiver receiver;
|
|
|
|
Handler handler { env, receiver, HANDLER_INTERVAL_MS, false, 1 };
|
|
|
|
Sender sender { env, receiver.manage(&context),
|
|
|
|
SENDER_INTERVAL_MS, false };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Fast_sender_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
|
|
|
{
|
|
|
|
timer.msleep(DURATION_MS);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/* stop emitting signals */
|
|
|
|
log("deactivate sender");
|
|
|
|
sender.idle(true);
|
|
|
|
timer.msleep(FINISH_IDLE_MS);
|
|
|
|
log("sender submitted a total of ", sender.submit_cnt(), " signals");
|
|
|
|
log("handler received a total of ", handler.receive_cnt(), " signals");
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
if (sender.submit_cnt() != handler.receive_cnt()) {
|
|
|
|
throw Unequal_sent_and_received_signals(); }
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Multiple_handlers_test : Signal_test
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief =
|
|
|
|
"get multiple handlers at one sender activated in a fair manner";
|
|
|
|
|
|
|
|
enum { HANDLER_INTERVAL_MS = 8 * SPEED,
|
|
|
|
SENDER_INTERVAL_MS = 1 * SPEED,
|
|
|
|
FINISH_IDLE_MS = 2 * HANDLER_INTERVAL_MS,
|
|
|
|
DURATION_MS = 50 * SPEED,
|
|
|
|
NR_OF_HANDLERS = 4 };
|
|
|
|
|
|
|
|
struct Unequal_sent_and_received_signals : Exception { };
|
|
|
|
struct Unequal_activation_of_handlers : Exception { };
|
|
|
|
|
|
|
|
Env &env;
|
|
|
|
Heap heap { env.ram(), env.rm() };
|
|
|
|
Timer::Connection timer { env };
|
|
|
|
Signal_context context;
|
|
|
|
Signal_receiver receiver;
|
|
|
|
Registry<Registered<Handler> > handlers;
|
|
|
|
Sender sender { env, receiver.manage(&context),
|
|
|
|
SENDER_INTERVAL_MS, true};
|
|
|
|
|
|
|
|
Multiple_handlers_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < NR_OF_HANDLERS; i++)
|
|
|
|
new (heap) Registered<Handler>(handlers, env, receiver,
|
|
|
|
HANDLER_INTERVAL_MS, true, i);
|
|
|
|
timer.msleep(DURATION_MS);
|
|
|
|
|
|
|
|
/* stop emitting signals */
|
|
|
|
log("stop generating new signals");
|
|
|
|
sender.idle(true);
|
|
|
|
timer.msleep(FINISH_IDLE_MS);
|
|
|
|
|
|
|
|
/* let handlers settle down */
|
|
|
|
handlers.for_each([&] (Handler &handler) { handler.idle(true); });
|
|
|
|
timer.msleep(FINISH_IDLE_MS);
|
|
|
|
|
|
|
|
/* print statistics and clean up */
|
|
|
|
unsigned total_rcv = 0, max_act = 0, min_act = ~0;;
|
|
|
|
handlers.for_each([&] (Handler &handler) {
|
|
|
|
unsigned const rcv = handler.receive_cnt();
|
|
|
|
unsigned const act = handler.activation_cnt();
|
|
|
|
log(handler, " received ", rcv, " signals, was activated ", act, " times");
|
|
|
|
total_rcv += rcv;
|
|
|
|
if (act > max_act) { max_act = act; }
|
|
|
|
if (act < min_act) { min_act = act; }
|
|
|
|
destroy(heap, &handler);
|
|
|
|
});
|
|
|
|
log("sender submitted a total of ", sender.submit_cnt(), " signals");
|
|
|
|
log("handlers received a total of ", total_rcv, " signals");
|
|
|
|
|
|
|
|
/* check if number of sent signals match the received ones */
|
|
|
|
if (sender.submit_cnt() != total_rcv) {
|
|
|
|
throw Unequal_sent_and_received_signals(); }
|
|
|
|
|
|
|
|
/* check if handlers had been activated equally (tolerance of one) */
|
|
|
|
if (max_act - min_act > 1) {
|
|
|
|
throw Unequal_activation_of_handlers(); }
|
2012-02-10 10:09:55 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Stress_test : Signal_test
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief =
|
|
|
|
"throughput when submitting/handling as fast as possible";
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
enum { DURATION_SEC = 5 };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Unequal_sent_and_received_signals : Exception { };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Env &env;
|
|
|
|
Timer::Connection timer { env };
|
|
|
|
Signal_context context;
|
|
|
|
Signal_receiver receiver;
|
|
|
|
Handler handler { env, receiver, 0, false, 1 };
|
|
|
|
Sender sender { env, receiver.manage(&context), 0, false };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Stress_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
for (unsigned i = 1; i <= DURATION_SEC; i++) {
|
|
|
|
log(i, "/", (unsigned)DURATION_SEC);
|
|
|
|
timer.msleep(1000);
|
|
|
|
}
|
|
|
|
log("deactivate sender");
|
|
|
|
sender.idle(true);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
while (handler.receive_cnt() < sender.submit_cnt()) {
|
|
|
|
log("waiting for signals still in flight...");
|
|
|
|
timer.msleep(1000);
|
|
|
|
}
|
|
|
|
log("");
|
|
|
|
log("sender submitted a total of ", sender.submit_cnt(), " signals");
|
|
|
|
log("handler received a total of ", handler.receive_cnt(), " signals");
|
|
|
|
log("");
|
|
|
|
log("handler received ", handler.receive_cnt() / DURATION_SEC, " signals per second");
|
|
|
|
log("handler was activated ", handler.activation_cnt() / DURATION_SEC, " times per second");
|
|
|
|
log("");
|
|
|
|
|
|
|
|
if (sender.submit_cnt() != handler.receive_cnt())
|
|
|
|
throw Unequal_sent_and_received_signals();
|
2013-01-14 18:24:32 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Lazy_receivers_test : Signal_test
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief = "lazy and out-of-order signal reception";
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Signal_context context_1, context_2;
|
|
|
|
Signal_receiver receiver_1, receiver_2;
|
|
|
|
Signal_transmitter transmitter_1 { receiver_1.manage(&context_1) };
|
|
|
|
Signal_transmitter transmitter_2 { receiver_2.manage(&context_2) };
|
2016-11-06 14:27:26 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Lazy_receivers_test(Env &env, int id) : Signal_test(id, brief)
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
log("submit and receive signals with multiple receivers in order");
|
|
|
|
transmitter_1.submit();
|
|
|
|
transmitter_2.submit();
|
|
|
|
{
|
|
|
|
Signal signal = receiver_1.wait_for_signal();
|
|
|
|
log("returned from wait_for_signal for receiver 1");
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
signal = receiver_2.wait_for_signal();
|
|
|
|
log("returned from wait_for_signal for receiver 2");
|
|
|
|
}
|
|
|
|
log("submit and receive signals with multiple receivers out of order");
|
|
|
|
transmitter_1.submit();
|
|
|
|
transmitter_2.submit();
|
|
|
|
{
|
|
|
|
Signal signal = receiver_2.wait_for_signal();
|
|
|
|
log("returned from wait_for_signal for receiver 2");
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
signal = receiver_1.wait_for_signal();
|
|
|
|
log("returned from wait_for_signal for receiver 1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Context_management_test : Signal_test
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief =
|
|
|
|
"correct initialization and cleanup of receiver and context";
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Env &env;
|
|
|
|
Timer::Connection timer { env };
|
|
|
|
Signal_context context;
|
|
|
|
Signal_receiver receiver;
|
|
|
|
Signal_context_capability context_cap { receiver.manage(&context) };
|
|
|
|
Sender sender { env, context_cap, 500, true };
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Context_management_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
|
|
|
{
|
|
|
|
/* stop sender after timeout */
|
|
|
|
timer.msleep(1000);
|
|
|
|
log("suspend sender");
|
|
|
|
sender.idle(true);
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/* collect pending signals and dissolve context from receiver */
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
Signal signal = receiver.wait_for_signal();
|
|
|
|
log("got ", signal.num(), " signal(s) from ", signal.context());
|
2013-01-14 18:24:32 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
receiver.dissolve(&context);
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
/* let sender spin for some time */
|
|
|
|
log("resume sender");
|
|
|
|
sender.idle(false);
|
|
|
|
timer.msleep(1000);
|
|
|
|
log("suspend sender");
|
|
|
|
sender.idle(true);
|
|
|
|
log("destroy sender");
|
|
|
|
}
|
|
|
|
};
|
2014-10-02 19:47:36 +02:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Synchronized_destruction_test : Signal_test, Thread
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
static constexpr char const *brief =
|
|
|
|
"does 'dissolve' block as long as the signal context is referenced?";
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Failed : Exception { };
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Env &env;
|
|
|
|
Timer::Connection timer { env };
|
|
|
|
Heap heap { env.ram(), env.rm() };
|
|
|
|
Signal_context &context { *new (heap) Signal_context };
|
|
|
|
Signal_receiver receiver;
|
|
|
|
Signal_transmitter transmitter { receiver.manage(&context) };
|
|
|
|
bool destroyed { false };
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
void entry()
|
2013-01-14 18:24:32 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
receiver.dissolve(&context);
|
|
|
|
log("dissolve finished");
|
|
|
|
destroyed = true;
|
|
|
|
destroy(heap, &context);
|
|
|
|
}
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Synchronized_destruction_test(Env &env, int id)
|
|
|
|
: Signal_test(id, brief), Thread(env, "destroyer", 1024 * sizeof(addr_t)), env(env)
|
|
|
|
{
|
|
|
|
transmitter.submit();
|
|
|
|
{
|
|
|
|
Signal signal = receiver.wait_for_signal();
|
|
|
|
log("start dissolving");
|
|
|
|
Thread::start();
|
|
|
|
timer.msleep(2000);
|
|
|
|
Signal signal_copy_1 = signal;
|
|
|
|
Signal signal_copy_2 = signal;
|
|
|
|
signal_copy_1 = signal_copy_2;
|
|
|
|
if (destroyed) {
|
|
|
|
throw Failed(); }
|
|
|
|
log("destruct signal");
|
2013-01-14 18:24:32 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
Thread::join();
|
2013-01-14 18:24:32 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Many_contexts_test : Signal_test
|
|
|
|
{
|
|
|
|
static constexpr char const *brief = "create and manage many contexts";
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Manage_failed : Exception { };
|
2013-01-14 18:24:32 +01:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Env &env;
|
|
|
|
Heap heap { env.ram(), env.rm() };
|
|
|
|
Registry<Registered<Signal_context> > contexts;
|
2014-10-02 19:47:36 +02:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Many_contexts_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
|
|
|
{
|
|
|
|
for (unsigned round = 0; round < 10; round++) {
|
2014-10-02 19:47:36 +02:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
unsigned const nr_of_contexts = 200 + 5 * round;
|
|
|
|
log("round ", round, ": manage ", nr_of_contexts, " contexts");
|
2014-10-02 19:47:36 +02:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
Signal_receiver receiver;
|
|
|
|
for (unsigned i = 0; i < nr_of_contexts; i++) {
|
|
|
|
if (!receiver.manage(new (heap) Registered<Signal_context>(contexts)).valid()) {
|
|
|
|
throw Manage_failed(); }
|
2015-03-05 13:00:08 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
contexts.for_each([&] (Registered<Signal_context> &context) {
|
|
|
|
receiver.dissolve(&context);
|
|
|
|
destroy(heap, &context);
|
|
|
|
});
|
2014-10-02 19:47:36 +02:00
|
|
|
}
|
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
2014-10-02 19:47:36 +02:00
|
|
|
|
2017-01-17 12:58:00 +01:00
|
|
|
struct Main
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-01-17 12:58:00 +01:00
|
|
|
Constructible<Fast_sender_test> test_1;
|
|
|
|
Constructible<Multiple_handlers_test> test_2;
|
|
|
|
Constructible<Stress_test> test_3;
|
|
|
|
Constructible<Lazy_receivers_test> test_4;
|
|
|
|
Constructible<Context_management_test> test_5;
|
|
|
|
Constructible<Synchronized_destruction_test> test_6;
|
|
|
|
Constructible<Many_contexts_test> test_7;
|
|
|
|
|
|
|
|
Main(Env &env)
|
|
|
|
{
|
|
|
|
log("--- Signalling test ---");
|
|
|
|
test_1.construct(env, 1); test_1.destruct();
|
|
|
|
test_2.construct(env, 2); test_2.destruct();
|
|
|
|
test_3.construct(env, 3); test_3.destruct();
|
|
|
|
test_4.construct(env, 4); test_4.destruct();
|
|
|
|
test_5.construct(env, 5); test_5.destruct();
|
|
|
|
test_6.construct(env, 6); test_6.destruct();
|
|
|
|
test_7.construct(env, 7); test_7.destruct();
|
|
|
|
log("--- Signalling test finished ---");
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2017-01-17 12:58:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
void Component::construct(Genode::Env &env) { static Main main(env); }
|