block_tester: use dynamic shared scratch buffer

The scratch buffer is now allocated from the heap and is shared
between the test as they are executed in a serial fashion. This
change saves memory as the test are constructed at start-up.

Fixes #3539.
This commit is contained in:
Josef Söntgen 2019-07-23 17:43:18 +02:00 committed by Christian Helmuth
parent dbecceec09
commit fafa409cf9
4 changed files with 43 additions and 13 deletions

View File

@ -26,6 +26,7 @@ namespace Test {
using namespace Genode; using namespace Genode;
struct Scratch_buffer;
struct Result; struct Result;
struct Test_base; struct Test_base;
struct Main; struct Main;
@ -35,6 +36,27 @@ namespace Test {
} }
class Test::Scratch_buffer
{
private:
Allocator &_alloc;
Scratch_buffer(Scratch_buffer const &);
Scratch_buffer &operator = (Scratch_buffer const&);
public:
char * const base;
size_t const size;
Scratch_buffer (Allocator &alloc, size_t size)
: _alloc(alloc), base((char*)alloc.alloc(size)), size(size) { }
~Scratch_buffer() { destroy(&_alloc, base); }
};
struct Test::Result struct Test::Result
{ {
uint64_t duration { 0 }; uint64_t duration { 0 };
@ -161,11 +183,11 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element
bool _finished { false }; bool _finished { false };
bool _success { false }; bool _success { false };
char _scratch_buffer[1u<<20] { }; Scratch_buffer &_scratch_buffer;
void _memcpy(char *dst, char const *src, size_t length) void _memcpy(char *dst, char const *src, size_t length)
{ {
if (length > sizeof(_scratch_buffer)) { if (length > _scratch_buffer.size) {
warning("scratch buffer too small for copying"); warning("scratch buffer too small for copying");
return; return;
} }
@ -187,7 +209,7 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element
log("job ", job.id, ": writing ", length, " bytes at ", offset); log("job ", job.id, ": writing ", length, " bytes at ", offset);
if (_copy) if (_copy)
_memcpy(dst, _scratch_buffer, length); _memcpy(dst, _scratch_buffer.base, length);
} }
/** /**
@ -203,7 +225,7 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element
log("job ", job.id, ": got ", length, " bytes at ", offset); log("job ", job.id, ": got ", length, " bytes at ", offset);
if (_copy) if (_copy)
_memcpy(_scratch_buffer, src, length); _memcpy(_scratch_buffer.base, src, length);
} }
/** /**
@ -256,7 +278,8 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element
friend class Genode::Fifo<Test_base>; friend class Genode::Fifo<Test_base>;
Test_base(Env &env, Allocator &alloc, Xml_node node, Test_base(Env &env, Allocator &alloc, Xml_node node,
Signal_context_capability finished_sig) Signal_context_capability finished_sig,
Scratch_buffer &scratch_buffer)
: :
_env(env), _alloc(alloc), _node(node), _env(env), _alloc(alloc), _node(node),
_verbose(node.attribute_value("verbose", false)), _verbose(node.attribute_value("verbose", false)),
@ -265,7 +288,8 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element
_progress_interval(_node.attribute_value("progress", (uint64_t)0)), _progress_interval(_node.attribute_value("progress", (uint64_t)0)),
_copy(_node.attribute_value("copy", true)), _copy(_node.attribute_value("copy", true)),
_batch(_node.attribute_value("batch", 1u)), _batch(_node.attribute_value("batch", 1u)),
_finished_sig(finished_sig) _finished_sig(finished_sig),
_scratch_buffer(scratch_buffer)
{ {
if (_progress_interval) if (_progress_interval)
_progress_timeout.construct(*_timer, *this, _progress_timeout.construct(*_timer, *this,
@ -335,6 +359,10 @@ struct Test::Main
bool const _stop_on_error { bool const _stop_on_error {
_config_rom.xml().attribute_value("stop_on_error", true) }; _config_rom.xml().attribute_value("stop_on_error", true) };
Genode::Number_of_bytes const _scratch_buffer_size {
_config_rom.xml().attribute_value("scratch_buffer_size",
Genode::Number_of_bytes(1U<<20)) };
Genode::Fifo<Test_base> _tests { }; Genode::Fifo<Test_base> _tests { };
struct Test_result : Genode::Fifo<Test_result>::Element struct Test_result : Genode::Fifo<Test_result>::Element
@ -430,6 +458,8 @@ struct Test::Main
Genode::Signal_handler<Main> _finished_sigh { Genode::Signal_handler<Main> _finished_sigh {
_env.ep(), *this, &Main::_handle_finished }; _env.ep(), *this, &Main::_handle_finished };
Scratch_buffer _scratch_buffer { _heap, _scratch_buffer_size };
void _construct_tests(Genode::Xml_node config) void _construct_tests(Genode::Xml_node config)
{ {
try { try {
@ -438,25 +468,25 @@ struct Test::Main
if (node.has_type("ping_pong")) { if (node.has_type("ping_pong")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Ping_pong(_env, _heap, node, _finished_sigh); Ping_pong(_env, _heap, node, _finished_sigh, _scratch_buffer);
_tests.enqueue(*t); _tests.enqueue(*t);
} else } else
if (node.has_type("random")) { if (node.has_type("random")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Random(_env, _heap, node, _finished_sigh); Random(_env, _heap, node, _finished_sigh, _scratch_buffer);
_tests.enqueue(*t); _tests.enqueue(*t);
} else } else
if (node.has_type("replay")) { if (node.has_type("replay")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Replay(_env, _heap, node, _finished_sigh); Replay(_env, _heap, node, _finished_sigh, _scratch_buffer);
_tests.enqueue(*t); _tests.enqueue(*t);
} else } else
if (node.has_type("sequential")) { if (node.has_type("sequential")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Sequential(_env, _heap, node, _finished_sigh); Sequential(_env, _heap, node, _finished_sigh, _scratch_buffer);
_tests.enqueue(*t); _tests.enqueue(*t);
} }
}); });

View File

@ -58,7 +58,7 @@ struct Test::Ping_pong : Test_base
void _init() override void _init() override
{ {
if (_size > sizeof(_scratch_buffer)) { if (_size > _scratch_buffer.size) {
error("request size exceeds scratch buffer size"); error("request size exceeds scratch buffer size");
throw Constructing_test_failed(); throw Constructing_test_failed();
} }

View File

@ -109,7 +109,7 @@ struct Test::Random : Test_base
void _init() override void _init() override
{ {
if (_size > sizeof(_scratch_buffer)) { if (_size > _scratch_buffer.size) {
error("request size exceeds scratch buffer size"); error("request size exceeds scratch buffer size");
throw Constructing_test_failed(); throw Constructing_test_failed();
} }

View File

@ -37,7 +37,7 @@ struct Test::Sequential : Test_base
void _init() override void _init() override
{ {
if (_size > sizeof(_scratch_buffer)) { if (_size > _scratch_buffer.size) {
error("request size exceeds scratch buffer size"); error("request size exceeds scratch buffer size");
throw Constructing_test_failed(); throw Constructing_test_failed();
} }