mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-25 19:54:26 +00:00
os/test: transition to new base API
For all tests * use Component::construct instead of main * use new connection constructors with env argument * use log instead of printf For some tests * replace signal receivers with signal handlers * replace global static variables with Main class members * remove unnecessary multithreading * model test steps as classes that are independent from each other and managed by Main as constructibles * use references instead of pointers and exceptions instead of error codes * use Attached_* helpers intead of doing attach/detach manually * use helpers like String, Id_space, Registry instead of arrays and lists * make the run script suitable for automated execution and conclusion Ref #1987
This commit is contained in:
parent
e0fef69cb3
commit
ad2d1fe586
@ -54,7 +54,6 @@ set config {
|
|||||||
<resource name="RAM" quantum="10M"/>
|
<resource name="RAM" quantum="10M"/>
|
||||||
</start>
|
</start>
|
||||||
</config>
|
</config>
|
||||||
</config>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install_config $config
|
install_config $config
|
||||||
@ -74,5 +73,11 @@ set boot_modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
run_genode_until forever
|
run_genode_until {.*Round 04: A A.*\n.*Setting CPU frequency low.*\n.*Setting CPU frequency high.*\n.*Round 05: A A} 60
|
||||||
|
|
||||||
|
grep_output {^\[init -> test-cpufreq\] }
|
||||||
|
|
||||||
|
compare_output_to {
|
||||||
|
[init -> test-cpufreq] Setting CPU frequency low
|
||||||
|
[init -> test-cpufreq] Setting CPU frequency high
|
||||||
|
}
|
||||||
|
@ -24,6 +24,12 @@ install_config {
|
|||||||
<start name="loader">
|
<start name="loader">
|
||||||
<resource name="RAM" quantum="1M"/>
|
<resource name="RAM" quantum="1M"/>
|
||||||
<provides><service name="Loader"/></provides>
|
<provides><service name="Loader"/></provides>
|
||||||
|
<config>
|
||||||
|
<policy label_prefix="test-dynamic_config_loader">
|
||||||
|
<parent-rom name="test-dynamic_config"/>
|
||||||
|
<parent-rom name="ld.lib.so"/>
|
||||||
|
</policy>
|
||||||
|
</config>
|
||||||
</start>
|
</start>
|
||||||
<start name="test-dynamic_config_loader">
|
<start name="test-dynamic_config_loader">
|
||||||
<resource name="RAM" quantum="10M"/>
|
<resource name="RAM" quantum="10M"/>
|
||||||
|
@ -69,13 +69,8 @@ install_config $config
|
|||||||
# Boot modules
|
# Boot modules
|
||||||
#
|
#
|
||||||
|
|
||||||
# generic modules
|
set boot_modules { core ld.lib.so init timer test-fb_bench }
|
||||||
set boot_modules {
|
|
||||||
core ld.lib.so init timer
|
|
||||||
test-fb_bench
|
|
||||||
}
|
|
||||||
|
|
||||||
# platform-specific modules
|
|
||||||
append_platform_drv_boot_modules
|
append_platform_drv_boot_modules
|
||||||
|
|
||||||
lappend_if [have_spec sdl] boot_modules fb_sdl
|
lappend_if [have_spec sdl] boot_modules fb_sdl
|
||||||
@ -83,5 +78,4 @@ lappend_if [have_spec framebuffer] boot_modules fb_drv
|
|||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
run_genode_until forever
|
run_genode_until {.*--- Framebuffer benchmark finished ---.*\n} 30
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ build_boot_image "core ld.lib.so init test-ram_fs_chunk"
|
|||||||
|
|
||||||
append qemu_args "-nographic -m 64"
|
append qemu_args "-nographic -m 64"
|
||||||
|
|
||||||
run_genode_until {child "test-ram_fs_chunk" exited with exit value 0.*\n} 10
|
run_genode_until {.*--- RAM filesystem chunk test finished ---.*\n} 10
|
||||||
|
|
||||||
grep_output {^\[init -> test-ram_fs_chunk\]}
|
grep_output {^\[init -> test-ram_fs_chunk\]}
|
||||||
unify_output { sizeof=[0-9]+} {}
|
unify_output { sizeof=[0-9]+} {}
|
||||||
|
|
||||||
compare_output_to {
|
compare_output_to {
|
||||||
[init -> test-ram_fs_chunk] --- ram_fs_chunk test ---
|
[init -> test-ram_fs_chunk] --- RAM filesystem chunk test ---
|
||||||
[init -> test-ram_fs_chunk] chunk sizes
|
[init -> test-ram_fs_chunk] chunk sizes
|
||||||
[init -> test-ram_fs_chunk] level 0: payload=120
|
[init -> test-ram_fs_chunk] level 0: payload=120
|
||||||
[init -> test-ram_fs_chunk] level 1: payload=24
|
[init -> test-ram_fs_chunk] level 1: payload=24
|
||||||
@ -77,6 +77,7 @@ compare_output_to {
|
|||||||
[init -> test-ram_fs_chunk] trunc(2) -> content (size=2): "fi"
|
[init -> test-ram_fs_chunk] trunc(2) -> content (size=2): "fi"
|
||||||
[init -> test-ram_fs_chunk] trunc(1) -> content (size=1): "f"
|
[init -> test-ram_fs_chunk] trunc(1) -> content (size=1): "f"
|
||||||
[init -> test-ram_fs_chunk] allocator: sum=0
|
[init -> test-ram_fs_chunk] allocator: sum=0
|
||||||
|
[init -> test-ram_fs_chunk] --- RAM filesystem chunk test finished ---
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,43 +25,43 @@ build_boot_image "core ld.lib.so init test-reconstructible"
|
|||||||
|
|
||||||
append qemu_args "-nographic -m 64"
|
append qemu_args "-nographic -m 64"
|
||||||
|
|
||||||
run_genode_until {child "test-reconstructible" exited with exit value 0.*\n} 10
|
run_genode_until {.*--- Reconstructible utility test finished ---.*\n} 10
|
||||||
|
|
||||||
grep_output {-> test-reconstructible}
|
grep_output {-> test-reconstructible}
|
||||||
|
|
||||||
compare_output_to {
|
compare_output_to {
|
||||||
[init -> test-reconstructible] --- test-reconstructible started ---
|
[init -> test-reconstructible] --- Reconstructible utility test ---
|
||||||
[init -> test-reconstructible] construct Object 1
|
[init -> test-reconstructible] construct Object 1
|
||||||
[init -> test-reconstructible] construct Object 2
|
[init -> test-reconstructible] construct Object 2
|
||||||
[init -> test-reconstructible] -- create Compound object --
|
[init -> test-reconstructible] create Compound object
|
||||||
[init -> test-reconstructible] construct Member_with_reference
|
[init -> test-reconstructible] construct Member_with_reference
|
||||||
[init -> test-reconstructible] construct Compound
|
[init -> test-reconstructible] construct Compound
|
||||||
[init -> test-reconstructible] compound.member.constructed returns 1
|
[init -> test-reconstructible] compound.member.constructed returns 1
|
||||||
[init -> test-reconstructible] compound.lazy_member.constructed returns 0
|
[init -> test-reconstructible] compound.lazy_member.constructed returns 0
|
||||||
[init -> test-reconstructible] -- construct lazy member --
|
[init -> test-reconstructible] construct lazy member
|
||||||
[init -> test-reconstructible] construct Member_with_reference
|
[init -> test-reconstructible] construct Member_with_reference
|
||||||
[init -> test-reconstructible] compound.lazy_member.constructed returns 1
|
[init -> test-reconstructible] compound.lazy_member.constructed returns 1
|
||||||
[init -> test-reconstructible] -- call method on member (with reference to Object 1) --
|
[init -> test-reconstructible] call method on member (with reference to Object 1)
|
||||||
[init -> test-reconstructible] const method called on Object 1
|
[init -> test-reconstructible] const method called on Object 1
|
||||||
[init -> test-reconstructible] -- reconstruct member with Object 2 as reference --
|
[init -> test-reconstructible] reconstruct member with Object 2 as reference
|
||||||
[init -> test-reconstructible] destruct Member_with_reference
|
[init -> test-reconstructible] destruct Member_with_reference
|
||||||
[init -> test-reconstructible] construct Member_with_reference
|
[init -> test-reconstructible] construct Member_with_reference
|
||||||
[init -> test-reconstructible] -- call method on member --
|
[init -> test-reconstructible] call method on member
|
||||||
[init -> test-reconstructible] const method called on Object 2
|
[init -> test-reconstructible] const method called on Object 2
|
||||||
[init -> test-reconstructible] -- destruct member --
|
[init -> test-reconstructible] destruct member
|
||||||
[init -> test-reconstructible] destruct Member_with_reference
|
[init -> test-reconstructible] destruct Member_with_reference
|
||||||
[init -> test-reconstructible] -- try to call method on member, catch exception --
|
[init -> test-reconstructible] try to call method on member, catch exception
|
||||||
[init -> test-reconstructible] got exception, as expected
|
[init -> test-reconstructible] got exception, as expected
|
||||||
[init -> test-reconstructible] -- destruct Compound and Objects 1 and 2 --
|
[init -> test-reconstructible] destruct Compound and Objects 1 and 2
|
||||||
[init -> test-reconstructible] destruct Compound
|
[init -> test-reconstructible] destruct Compound
|
||||||
[init -> test-reconstructible] destruct Member_with_reference
|
[init -> test-reconstructible] destruct Member_with_reference
|
||||||
[init -> test-reconstructible] destruct Object 2
|
[init -> test-reconstructible] destruct Object 2
|
||||||
[init -> test-reconstructible] destruct Object 1
|
[init -> test-reconstructible] destruct Object 1
|
||||||
[init -> test-reconstructible] -- construct Throwing object
|
[init -> test-reconstructible] construct Throwing object
|
||||||
[init -> test-reconstructible] construct Throwing -> don't throw
|
[init -> test-reconstructible] construct Throwing -> don't throw
|
||||||
[init -> test-reconstructible] destruct Throwing
|
[init -> test-reconstructible] destruct Throwing
|
||||||
[init -> test-reconstructible] construct Throwing -> throw exception
|
[init -> test-reconstructible] construct Throwing -> throw exception
|
||||||
[init -> test-reconstructible] -- catched exception as expected
|
[init -> test-reconstructible] got exception, as expected
|
||||||
[init -> test-reconstructible] --- test-reconstructible finished ---
|
[init -> test-reconstructible] --- Reconstructible utility test finished ---
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
#
|
|
||||||
# \brief Test for 'rom_blk' service
|
|
||||||
# \author Stefan Kalkowski
|
|
||||||
# \date 2011-05-10
|
|
||||||
#
|
|
||||||
|
|
||||||
build "core init server/rom_blk test/rom_blk"
|
build "core init server/rom_blk test/rom_blk"
|
||||||
|
|
||||||
create_boot_directory
|
create_boot_directory
|
||||||
@ -37,4 +31,4 @@ build_boot_image "core ld.lib.so init rom_blk test-rom_blk"
|
|||||||
|
|
||||||
append qemu_args "-m 64 -nographic "
|
append qemu_args "-m 64 -nographic "
|
||||||
|
|
||||||
run_genode_until "all done, finished!" 10
|
run_genode_until {.*--- ROM Block test finished ---.*\n} 10
|
||||||
|
@ -32,4 +32,4 @@ build_boot_image "core ld.lib.so init timer test-signal"
|
|||||||
|
|
||||||
append qemu_args "-nographic -m 64"
|
append qemu_args "-nographic -m 64"
|
||||||
|
|
||||||
run_genode_until {.*child "test-signal" exited with exit value 0.*} 200
|
run_genode_until {.*--- Signalling test finished ---.*\n} 200
|
||||||
|
@ -25,14 +25,15 @@ build_boot_image "core ld.lib.so init test-synced_interface"
|
|||||||
|
|
||||||
append qemu_args "-nographic -m 64"
|
append qemu_args "-nographic -m 64"
|
||||||
|
|
||||||
run_genode_until {child "test-synced_interface" exited with exit value 0} 10
|
run_genode_until {.*--- Synced interface test finished ---.*\n} 10
|
||||||
|
|
||||||
grep_output {-> test-synced_interface}
|
grep_output {-> test-synced_interface}
|
||||||
|
|
||||||
compare_output_to {
|
compare_output_to {
|
||||||
|
[init -> test-synced_interface] --- Synced interface test ---
|
||||||
[init -> test-synced_interface] lock
|
[init -> test-synced_interface] lock
|
||||||
[init -> test-synced_interface] adding 13 + 14
|
[init -> test-synced_interface] adding 13 + 14
|
||||||
[init -> test-synced_interface] unlock
|
[init -> test-synced_interface] unlock
|
||||||
[init -> test-synced_interface] result is 27
|
[init -> test-synced_interface] result is 27
|
||||||
|
[init -> test-synced_interface] --- Synced interface test finished ---
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ build_boot_image "core ld.lib.so init timer test-thread_join"
|
|||||||
|
|
||||||
append qemu_args "-nographic -m 64"
|
append qemu_args "-nographic -m 64"
|
||||||
|
|
||||||
run_genode_until {child "test-thread_join" exited with exit value 0.*\n} 10
|
run_genode_until {.*--- Thread join test finished ---.*\n} 10
|
||||||
|
@ -54,4 +54,4 @@ build_boot_image $boot_modules
|
|||||||
|
|
||||||
append qemu_args " -m 64 -nographic "
|
append qemu_args " -m 64 -nographic "
|
||||||
|
|
||||||
run_genode_until "end of timed-semaphore test" 10
|
run_genode_until {.*--- Timed semaphore test finished ---.*\n} 10
|
||||||
|
@ -64,5 +64,4 @@ build_boot_image $boot_modules
|
|||||||
|
|
||||||
append qemu_args " -nographic -serial mon:stdio -m 256 "
|
append qemu_args " -nographic -serial mon:stdio -m 256 "
|
||||||
|
|
||||||
run_genode_until forever
|
run_genode_until "--- test-trace finished ---" 30
|
||||||
#{.*child exited with exit value 0.* } 60
|
|
||||||
|
@ -1,42 +1,49 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Test for changing the CPU frequency
|
* \brief Test for changing the CPU frequency
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2013-06-14
|
* \date 2013-06-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Genode Labs GmbH
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/log.h>
|
#include <base/component.h>
|
||||||
#include <base/env.h>
|
|
||||||
#include <base/sleep.h>
|
|
||||||
|
|
||||||
#include <regulator/consts.h>
|
#include <regulator/consts.h>
|
||||||
#include <regulator_session/connection.h>
|
#include <regulator_session/connection.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
log("--- test-cpufreq started ---");
|
struct Main
|
||||||
|
{
|
||||||
|
enum { PERIOD_US = 8 * 1000 * 1000 };
|
||||||
|
|
||||||
static Timer::Connection timer;
|
Env &env;
|
||||||
static Regulator::Connection cpu_regulator(Regulator::CLK_CPU);
|
Timer::Connection timer { env };
|
||||||
bool high = true;
|
Regulator::Connection cpu_regulator { env, Regulator::CLK_CPU };
|
||||||
|
Signal_handler<Main> timer_handler { env.ep(), *this, &Main::handle_timer };
|
||||||
|
bool high { true };
|
||||||
|
|
||||||
while (true) {
|
void handle_timer()
|
||||||
timer.msleep(10000);
|
{
|
||||||
log("Setting CPU frequency ", high ? "low" : "high");
|
log("Setting CPU frequency ", high ? "low" : "high");
|
||||||
cpu_regulator.level(high ? Regulator::CPU_FREQ_200
|
cpu_regulator.level(high ? Regulator::CPU_FREQ_200 :
|
||||||
: Regulator::CPU_FREQ_1600);
|
Regulator::CPU_FREQ_1600);
|
||||||
high = !high;
|
high = !high;
|
||||||
|
timer.trigger_once(PERIOD_US);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
Main(Env &env) : env(env)
|
||||||
|
{
|
||||||
|
timer.sigh(timer_handler);
|
||||||
|
timer.trigger_once(PERIOD_US);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -12,53 +12,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/snprintf.h>
|
|
||||||
#include <base/sleep.h>
|
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <loader_session/connection.h>
|
#include <loader_session/connection.h>
|
||||||
|
#include <base/component.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
struct Main
|
||||||
|
{
|
||||||
enum { CONFIG_SIZE = 100 };
|
enum { CONFIG_SIZE = 100 };
|
||||||
|
|
||||||
static Loader::Connection loader(8*1024*1024);
|
Env &env;
|
||||||
|
int counter { -1 };
|
||||||
|
Loader::Connection loader { env, 8 * 1024 * 1024 };
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_handler<Main> timer_handler { env.ep(), *this, &Main::handle_timer };
|
||||||
|
|
||||||
|
void handle_timer()
|
||||||
static void update_config(int counter)
|
|
||||||
{
|
{
|
||||||
Dataspace_capability config_ds =
|
char *config_ds_addr =
|
||||||
loader.alloc_rom_module("config", CONFIG_SIZE);
|
env.rm().attach(loader.alloc_rom_module("config", CONFIG_SIZE));
|
||||||
|
|
||||||
char *config_ds_addr = env()->rm_session()->attach(config_ds);
|
|
||||||
|
|
||||||
snprintf(config_ds_addr, CONFIG_SIZE,
|
|
||||||
"<config><counter>%d</counter></config>",
|
|
||||||
counter);
|
|
||||||
|
|
||||||
env()->rm_session()->detach(config_ds_addr);
|
|
||||||
|
|
||||||
|
String<100> config("<config><counter>", counter++, "</counter></config>");
|
||||||
|
strncpy(config_ds_addr, config.string(), CONFIG_SIZE);
|
||||||
|
env.rm().detach(config_ds_addr);
|
||||||
loader.commit_rom_module("config");
|
loader.commit_rom_module("config");
|
||||||
|
timer.trigger_once(250 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Main(Env &env) : env(env)
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
update_config(-1);
|
timer.sigh(timer_handler);
|
||||||
|
handle_timer();
|
||||||
loader.start("test-dynamic_config", "test-label");
|
loader.start("test-dynamic_config", "test-label");
|
||||||
|
|
||||||
/* update slave config at regular intervals */
|
|
||||||
int counter = 0;
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
static Timer::Connection timer;
|
|
||||||
timer.msleep(250);
|
|
||||||
update_config(counter++);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
sleep_forever();
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -1,49 +1,45 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Test for changing configuration at runtime
|
* \brief Test for changing configuration at runtime
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2012-04-04
|
* \date 2012-04-04
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <os/config.h>
|
#include <base/component.h>
|
||||||
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
void parse_config()
|
struct Main
|
||||||
{
|
{
|
||||||
|
Env &env;
|
||||||
|
Attached_rom_dataspace config { env, "config" };
|
||||||
|
Signal_handler<Main> config_handler { env.ep(), *this, &Main::handle_config };
|
||||||
|
|
||||||
|
void handle_config()
|
||||||
|
{
|
||||||
|
config.update();
|
||||||
try {
|
try {
|
||||||
long counter = 1;
|
long counter = 1;
|
||||||
Genode::config()->xml_node().sub_node("counter").value(&counter);
|
config.xml().sub_node("counter").value(&counter);
|
||||||
Genode::log("obtained counter value ", counter, " from config");
|
log("obtained counter value ", counter, " from config");
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
Genode::error("could not parse configuration");
|
|
||||||
}
|
}
|
||||||
|
catch (...) { error("could not parse configuration"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Main(Env &env) : env(env)
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
parse_config();
|
handle_config();
|
||||||
|
config.sigh(config_handler);
|
||||||
/* register signal handler for config changes */
|
|
||||||
Genode::Signal_receiver sig_rec;
|
|
||||||
Genode::Signal_context sig_ctx;
|
|
||||||
Genode::config()->sigh(sig_rec.manage(&sig_ctx));
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
/* wait for config change */
|
|
||||||
sig_rec.wait_for_signal();
|
|
||||||
|
|
||||||
Genode::config()->reload();
|
|
||||||
parse_config();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Test for changing configuration at runtime (server-side)
|
* \brief Test for changing configuration at runtime (server-side)
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2012-04-04
|
* \date 2012-04-04
|
||||||
*
|
*
|
||||||
* This program provides a generated config file as ROM service. After
|
* This program provides a generated config file as ROM service. After
|
||||||
@ -8,65 +9,56 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/signal.h>
|
|
||||||
#include <os/attached_ram_dataspace.h>
|
#include <os/attached_ram_dataspace.h>
|
||||||
#include <os/static_root.h>
|
#include <os/static_root.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <rom_session/rom_session.h>
|
#include <rom_session/rom_session.h>
|
||||||
#include <cap_session/connection.h>
|
#include <base/component.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The implementation of this class follows the lines of
|
* The implementation of this class follows the lines of
|
||||||
* 'os/include/os/child_policy_dynamic_rom.h'.
|
* 'os/include/os/child_policy_dynamic_rom.h'.
|
||||||
*/
|
*/
|
||||||
class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
class Rom_session_component : public Rpc_object<Rom_session>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Attached_ram_dataspace _fg;
|
Env &_env;
|
||||||
Genode::Attached_ram_dataspace _bg;
|
Attached_ram_dataspace _fg { _env.ram(), _env.rm(), 0 };
|
||||||
|
Attached_ram_dataspace _bg { _env.ram(), _env.rm(), 0 };
|
||||||
bool _bg_has_pending_data;
|
bool _bg_pending_data { false };
|
||||||
|
Signal_context_capability _sigh;
|
||||||
Genode::Lock _lock;
|
|
||||||
|
|
||||||
Genode::Signal_context_capability _sigh;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
Rom_session_component(Env &env) : _env(env) { }
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Rom_session_component()
|
|
||||||
: _fg(0, 0), _bg(0, 0), _bg_has_pending_data(false) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the config file
|
* Update the config file
|
||||||
*/
|
*/
|
||||||
void configure(char const *data)
|
void configure(char const *data)
|
||||||
{
|
{
|
||||||
Genode::Lock::Guard guard(_lock);
|
size_t const data_len = strlen(data) + 1;
|
||||||
|
|
||||||
Genode::size_t const data_len = Genode::strlen(data) + 1;
|
|
||||||
|
|
||||||
/* let background buffer grow if needed */
|
/* let background buffer grow if needed */
|
||||||
if (_bg.size() < data_len)
|
if (_bg.size() < data_len)
|
||||||
_bg.realloc(Genode::env()->ram_session(), data_len);
|
_bg.realloc(&_env.ram(), data_len);
|
||||||
|
|
||||||
Genode::strncpy(_bg.local_addr<char>(), data, data_len);
|
strncpy(_bg.local_addr<char>(), data, data_len);
|
||||||
_bg_has_pending_data = true;
|
_bg_pending_data = true;
|
||||||
|
|
||||||
/* inform client about the changed data */
|
/* inform client about the changed data */
|
||||||
if (_sigh.valid())
|
if (_sigh.valid())
|
||||||
Genode::Signal_transmitter(_sigh).submit();
|
Signal_transmitter(_sigh).submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,67 +66,51 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
|||||||
** ROM session interface **
|
** ROM session interface **
|
||||||
***************************/
|
***************************/
|
||||||
|
|
||||||
Genode::Rom_dataspace_capability dataspace()
|
Rom_dataspace_capability dataspace() override
|
||||||
{
|
{
|
||||||
Genode::Lock::Guard guard(_lock);
|
if (!_fg.size() && !_bg_pending_data) {
|
||||||
|
error("no data loaded");
|
||||||
if (!_fg.size() && !_bg_has_pending_data) {
|
return Rom_dataspace_capability();
|
||||||
Genode::error("no data loaded");
|
|
||||||
return Genode::Rom_dataspace_capability();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep foreground if no background exists. Otherwise, use old
|
* Keep foreground if no background exists. Otherwise, use old
|
||||||
* background as new foreground.
|
* background as new foreground.
|
||||||
*/
|
*/
|
||||||
if (_bg_has_pending_data) {
|
if (_bg_pending_data) {
|
||||||
_fg.swap(_bg);
|
_fg.swap(_bg);
|
||||||
_bg_has_pending_data = false;
|
_bg_pending_data = false;
|
||||||
|
}
|
||||||
|
Dataspace_capability ds_cap = _fg.cap();
|
||||||
|
return static_cap_cast<Rom_dataspace>(ds_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::Dataspace_capability ds_cap = _fg.cap();
|
void sigh(Signal_context_capability sigh_cap) override { _sigh = sigh_cap; }
|
||||||
return Genode::static_cap_cast<Genode::Rom_dataspace>(ds_cap);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void sigh(Genode::Signal_context_capability sigh_cap)
|
struct Main
|
||||||
{
|
{
|
||||||
Genode::Lock::Guard guard(_lock);
|
enum { STACK_SIZE = 2 * 1024 * sizeof(addr_t) };
|
||||||
_sigh = sigh_cap;
|
|
||||||
|
Env &env;
|
||||||
|
Rom_session_component rom_session { env };
|
||||||
|
Static_root<Rom_session> rom_root { env.ep().manage(rom_session) };
|
||||||
|
int counter { -1 };
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_handler<Main> timer_handler { env.ep(), *this, &Main::handle_timer };
|
||||||
|
|
||||||
|
void handle_timer()
|
||||||
|
{
|
||||||
|
String<100> config("<config><counter>", counter++, "</counter></config>");
|
||||||
|
rom_session.configure(config.string());
|
||||||
|
timer.trigger_once(250 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main(Env &env) : env(env)
|
||||||
|
{
|
||||||
|
timer.sigh(timer_handler);
|
||||||
|
handle_timer();
|
||||||
|
env.parent().announce(env.ep().manage(rom_root));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
/* connection to capability service needed to create capabilities */
|
|
||||||
static Cap_connection cap;
|
|
||||||
|
|
||||||
enum { STACK_SIZE = 8*1024 };
|
|
||||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rom_ep");
|
|
||||||
|
|
||||||
static Rom_session_component rom_session;
|
|
||||||
static Static_root<Rom_session> rom_root(ep.manage(&rom_session));
|
|
||||||
|
|
||||||
rom_session.configure("<config><counter>-1</counter></config>");
|
|
||||||
|
|
||||||
/* announce server */
|
|
||||||
env()->parent()->announce(ep.manage(&rom_root));
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
static Timer::Connection timer;
|
|
||||||
timer.msleep(250);
|
|
||||||
|
|
||||||
/* re-generate configuration */
|
|
||||||
char buf[100];
|
|
||||||
Genode::snprintf(buf, sizeof(buf),
|
|
||||||
"<config><counter>%d</counter></config>",
|
|
||||||
counter++);
|
|
||||||
|
|
||||||
rom_session.configure(buf);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
@ -1,138 +1,141 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Framebuffer throughput test
|
* \brief Framebuffer throughput test
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2015-06-05
|
* \date 2015-06-05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2014 Genode Labs GmbH
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/env.h>
|
#include <base/component.h>
|
||||||
#include <base/printf.h>
|
#include <base/heap.h>
|
||||||
#include <os/attached_dataspace.h>
|
#include <os/attached_dataspace.h>
|
||||||
#include <blit/blit.h>
|
#include <blit/blit.h>
|
||||||
#include <framebuffer_session/connection.h>
|
#include <framebuffer_session/connection.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
|
|
||||||
static unsigned long now_ms()
|
|
||||||
{
|
|
||||||
static Timer::Connection timer;
|
|
||||||
return timer.elapsed_ms();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
printf("--- test-fb_bench started ---\n");
|
struct Test
|
||||||
|
|
||||||
static Framebuffer::Connection fb;
|
|
||||||
|
|
||||||
static Attached_dataspace fb_ds(fb.dataspace());
|
|
||||||
static Framebuffer::Mode const fb_mode = fb.mode();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate two memory buffers as big as the framebuffer.
|
|
||||||
*/
|
|
||||||
char *src_buf[2];
|
|
||||||
for (unsigned i = 0; i < 2; i++)
|
|
||||||
src_buf[i] = (char *)env()->heap()->alloc(fb_ds.size());
|
|
||||||
|
|
||||||
/* duration of individual test, in milliseconds */
|
|
||||||
unsigned long duration_ms = 2000;
|
|
||||||
|
|
||||||
printf("byte-wise memcpy from RAM to RAM...\n");
|
|
||||||
{
|
{
|
||||||
unsigned long transferred_kib = 0;
|
enum { DURATION_MS = 2000 };
|
||||||
unsigned long const start_ms = now_ms();
|
|
||||||
|
|
||||||
for (; now_ms() - start_ms < duration_ms;) {
|
Env &env;
|
||||||
memcpy(src_buf[0], src_buf[1], fb_ds.size());
|
int id;
|
||||||
transferred_kib += fb_ds.size() / 1024;
|
Timer::Connection timer { env };
|
||||||
}
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Framebuffer::Connection fb { env, Framebuffer::Mode() };
|
||||||
|
Attached_dataspace fb_ds { env.rm(), fb.dataspace() };
|
||||||
|
Framebuffer::Mode const fb_mode { fb.mode() };
|
||||||
|
char *buf[2];
|
||||||
|
|
||||||
unsigned long const end_ms = now_ms();
|
Test(Env &env, int id, char const *brief) : env(env), id(id)
|
||||||
|
|
||||||
printf("-> %ld MiB/sec\n",
|
|
||||||
(transferred_kib)/(end_ms - start_ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill one memory buffer with white pixels.
|
|
||||||
*/
|
|
||||||
memset(src_buf[1], ~0, fb_ds.size());
|
|
||||||
|
|
||||||
printf("byte-wise memcpy from RAM to framebuffer...\n");
|
|
||||||
{
|
{
|
||||||
unsigned long transferred_kib = 0;
|
log("\nTEST ", id, ": ", brief, "\n");
|
||||||
unsigned long const start_ms = now_ms();
|
for (unsigned i = 0; i < 2; i++) {
|
||||||
|
if (!heap.alloc(fb_ds.size(), (void **)&buf[i])) {
|
||||||
for (unsigned i = 0; now_ms() - start_ms < duration_ms; i++) {
|
env.parent().exit(-1); }
|
||||||
memcpy(fb_ds.local_addr<char>(), src_buf[i % 2], fb_ds.size());
|
}
|
||||||
transferred_kib += fb_ds.size() / 1024;
|
/* fill one memory buffer with white pixels */
|
||||||
|
memset(buf[1], ~0, fb_ds.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long const end_ms = now_ms();
|
void conclusion(unsigned kib, unsigned start_ms, unsigned end_ms) {
|
||||||
|
log("throughput: ", kib / (end_ms - start_ms), " MiB/sec"); }
|
||||||
|
|
||||||
printf("-> %ld MiB/sec\n",
|
~Test() { log("\nTEST ", id, " finished\n"); }
|
||||||
(transferred_kib)/(end_ms - start_ms));
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
struct Bytewise_ram_test : Test
|
||||||
* Blitting via the blit library from RAM to framebuffer
|
|
||||||
*/
|
|
||||||
printf("copy via blit library from RAM to framebuffer...\n");
|
|
||||||
{
|
{
|
||||||
unsigned long transferred_kib = 0;
|
static constexpr char const *brief = "byte-wise memcpy from RAM to RAM";
|
||||||
unsigned long const start_ms = now_ms();
|
|
||||||
|
|
||||||
/* line width in bytes */
|
Bytewise_ram_test(Env &env, int id) : Test(env, id, brief)
|
||||||
|
{
|
||||||
|
unsigned kib = 0;
|
||||||
|
unsigned const start_ms = timer.elapsed_ms();
|
||||||
|
for (; timer.elapsed_ms() - start_ms < DURATION_MS;) {
|
||||||
|
memcpy(buf[0], buf[1], fb_ds.size());
|
||||||
|
kib += fb_ds.size() / 1024;
|
||||||
|
}
|
||||||
|
conclusion(kib, start_ms, timer.elapsed_ms());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bytewise_fb_test : Test
|
||||||
|
{
|
||||||
|
static constexpr char const *brief = "byte-wise memcpy from RAM to FB";
|
||||||
|
|
||||||
|
Bytewise_fb_test(Env &env, int id) : Test(env, id, brief)
|
||||||
|
{
|
||||||
|
unsigned kib = 0;
|
||||||
|
unsigned const start_ms = timer.elapsed_ms();
|
||||||
|
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
|
||||||
|
memcpy(fb_ds.local_addr<char>(), buf[i % 2], fb_ds.size());
|
||||||
|
kib += fb_ds.size() / 1024;
|
||||||
|
}
|
||||||
|
conclusion(kib, start_ms, timer.elapsed_ms());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Blit_test : Test
|
||||||
|
{
|
||||||
|
static constexpr char const *brief = "copy via blit library from RAM to FB";
|
||||||
|
|
||||||
|
Blit_test(Env &env, int id) : Test(env, id, brief)
|
||||||
|
{
|
||||||
|
unsigned kib = 0;
|
||||||
|
unsigned const start_ms = timer.elapsed_ms();
|
||||||
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
|
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
|
||||||
unsigned const h = fb_mode.height();
|
unsigned const h = fb_mode.height();
|
||||||
|
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
|
||||||
for (unsigned i = 0; now_ms() - start_ms < duration_ms; i++) {
|
blit(buf[i % 2], w, fb_ds.local_addr<char>(), w, w, h);
|
||||||
blit(src_buf[i % 2], w, fb_ds.local_addr<char>(), w, w, h);
|
kib += (w * h) / 1024;
|
||||||
|
|
||||||
transferred_kib += (w*h) / 1024;
|
|
||||||
}
|
}
|
||||||
|
conclusion(kib, start_ms, timer.elapsed_ms());
|
||||||
unsigned long const end_ms = now_ms();
|
|
||||||
|
|
||||||
printf("-> %ld MiB/sec\n",
|
|
||||||
(transferred_kib)/(end_ms - start_ms));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
struct Unaligned_blit_test : Test
|
||||||
* Unaligned blitting via the blit library from RAM to framebuffer
|
|
||||||
*/
|
|
||||||
printf("unaligned copy via blit library from RAM to framebuffer...\n");
|
|
||||||
{
|
{
|
||||||
unsigned long transferred_kib = 0;
|
static constexpr char const *brief = "unaligned copy via blit library from RAM to FB";
|
||||||
unsigned long const start_ms = now_ms();
|
|
||||||
|
|
||||||
/* line width in bytes */
|
Unaligned_blit_test(Env &env, int id) : Test(env, id, brief)
|
||||||
|
{
|
||||||
|
unsigned kib = 0;
|
||||||
|
unsigned const start_ms = timer.elapsed_ms();
|
||||||
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
|
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
|
||||||
unsigned const h = fb_mode.height();
|
unsigned const h = fb_mode.height();
|
||||||
|
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
|
||||||
for (unsigned i = 0; now_ms() - start_ms < duration_ms; i++) {
|
blit(buf[i % 2] + 2, w, fb_ds.local_addr<char>() + 2, w, w - 2, h);
|
||||||
blit(src_buf[i % 2] + 2, w, fb_ds.local_addr<char>() + 2, w, w - 2, h);
|
kib += (w * h) / 1024;
|
||||||
|
|
||||||
transferred_kib += (w*h) / 1024;
|
|
||||||
}
|
}
|
||||||
|
conclusion(kib, start_ms, timer.elapsed_ms());
|
||||||
unsigned long const end_ms = now_ms();
|
|
||||||
|
|
||||||
printf("-> %ld MiB/sec\n",
|
|
||||||
(transferred_kib)/(end_ms - start_ms));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
printf("--- test-fb_bench finished ---\n");
|
struct Main
|
||||||
return 0;
|
{
|
||||||
|
Constructible<Bytewise_ram_test> test_1;
|
||||||
|
Constructible<Bytewise_fb_test> test_2;
|
||||||
|
Constructible<Blit_test> test_3;
|
||||||
|
Constructible<Unaligned_blit_test> test_4;
|
||||||
|
|
||||||
|
Main(Env &env)
|
||||||
|
{
|
||||||
|
log("--- Framebuffer benchmark ---");
|
||||||
|
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();
|
||||||
|
log("--- Framebuffer benchmark finished ---");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -5,22 +5,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2016 Genode Labs GmbH
|
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <base/env.h>
|
|
||||||
#include <base/log.h>
|
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <input_session/connection.h>
|
#include <input_session/connection.h>
|
||||||
#include <input/event.h>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
static char const * ev_type(Input::Event::Type type)
|
static char const * ev_type(Input::Event::Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -47,48 +45,33 @@ static char const * key_name(Input::Event const &ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Test_environment
|
struct Main
|
||||||
{
|
{
|
||||||
private:
|
Env &env;
|
||||||
|
Input::Connection input { env };
|
||||||
|
Signal_handler<Main> input_sigh { env.ep(), *this, &Main::handle_input };
|
||||||
|
unsigned event_cnt { 0 };
|
||||||
|
|
||||||
Genode::Env &_env;
|
void handle_input();
|
||||||
|
|
||||||
Input::Connection _input;
|
Main(Env &env) : env(env)
|
||||||
|
|
||||||
Genode::Signal_handler<Test_environment> _input_sigh;
|
|
||||||
|
|
||||||
unsigned int event_count = 0;
|
|
||||||
|
|
||||||
void _handle_input();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Test_environment(Genode::Env &env)
|
|
||||||
: _env(env),
|
|
||||||
_input_sigh(env.ep(), *this, &Test_environment::_handle_input)
|
|
||||||
{
|
{
|
||||||
log("--- Input test is up ---");
|
log("--- Input test ---");
|
||||||
|
input.sigh(input_sigh);
|
||||||
_input.sigh(_input_sigh);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void Test_environment::_handle_input()
|
void Main::handle_input()
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Handle input events
|
|
||||||
*/
|
|
||||||
int key_cnt = 0;
|
int key_cnt = 0;
|
||||||
|
input.for_each_event([&] (Input::Event const &ev) {
|
||||||
_input.for_each_event([&] (Input::Event const &ev) {
|
event_cnt++;
|
||||||
event_count++;
|
|
||||||
|
|
||||||
if (ev.type() == Input::Event::PRESS) key_cnt++;
|
if (ev.type() == Input::Event::PRESS) key_cnt++;
|
||||||
if (ev.type() == Input::Event::RELEASE) key_cnt--;
|
if (ev.type() == Input::Event::RELEASE) key_cnt--;
|
||||||
|
|
||||||
/* log event */
|
log("Input event #", event_cnt, "\t"
|
||||||
log("Input event #", event_count, "\t"
|
|
||||||
"type=", ev_type(ev.type()), "\t"
|
"type=", ev_type(ev.type()), "\t"
|
||||||
"code=", ev.code(), "\t"
|
"code=", ev.code(), "\t"
|
||||||
"rx=", ev.rx(), "\t"
|
"rx=", ev.rx(), "\t"
|
||||||
@ -99,10 +82,5 @@ void Test_environment::_handle_input()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Component::construct(Genode::Env &env)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
log("--- Test input ---\n");
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
static Test_environment te(env);
|
|
||||||
}
|
|
||||||
|
@ -61,7 +61,7 @@ struct Test::Base
|
|||||||
|
|
||||||
enum { BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128 };
|
enum { BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128 };
|
||||||
|
|
||||||
Nic::Connection _nic { &_tx_block_alloc, BUF_SIZE, BUF_SIZE };
|
Nic::Connection _nic { _env, &_tx_block_alloc, BUF_SIZE, BUF_SIZE };
|
||||||
|
|
||||||
void _handle_nic() { if (!_done) handle_nic(); }
|
void _handle_nic() { if (!_done) handle_nic(); }
|
||||||
|
|
||||||
|
@ -1,23 +1,52 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Unit test for RAM fs chunk data structure
|
* \brief Unit test for RAM fs chunk data structure
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2012-04-19
|
* \date 2012-04-19
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/env.h>
|
#include <base/heap.h>
|
||||||
#include <base/log.h>
|
#include <base/component.h>
|
||||||
#include <ram_fs/chunk.h>
|
#include <ram_fs/chunk.h>
|
||||||
|
|
||||||
namespace File_system {
|
using namespace File_system;
|
||||||
typedef Chunk<2> Chunk_level_3;
|
using namespace Genode;
|
||||||
typedef Chunk_index<3, Chunk_level_3> Chunk_level_2;
|
|
||||||
typedef Chunk_index<4, Chunk_level_2> Chunk_level_1;
|
using Chunk_level_3 = Chunk<2>;
|
||||||
typedef Chunk_index<5, Chunk_level_1> Chunk_level_0;
|
using Chunk_level_2 = Chunk_index<3, Chunk_level_3>;
|
||||||
|
using Chunk_level_1 = Chunk_index<4, Chunk_level_2>;
|
||||||
|
|
||||||
|
struct Chunk_level_0 : Chunk_index<5, Chunk_level_1>
|
||||||
|
{
|
||||||
|
Chunk_level_0(Allocator &alloc, seek_off_t off) : Chunk_index(alloc, off) { }
|
||||||
|
|
||||||
|
void print(Output &out) const
|
||||||
|
{
|
||||||
|
static char read_buf[Chunk_level_0::SIZE];
|
||||||
|
if (used_size() > Chunk_level_0::SIZE) {
|
||||||
|
throw Index_out_of_range(); }
|
||||||
|
|
||||||
|
read(read_buf, used_size(), 0);
|
||||||
|
Genode::print(out, "content (size=", used_size(), "): ");
|
||||||
|
Genode::print(out, "\"");
|
||||||
|
for (unsigned i = 0; i < used_size(); i++) {
|
||||||
|
char const c = read_buf[i];
|
||||||
|
if (c) {
|
||||||
|
Genode::print(out, Char(c)); }
|
||||||
|
else {
|
||||||
|
Genode::print(out, "."); }
|
||||||
}
|
}
|
||||||
|
Genode::print(out, "\"");
|
||||||
|
}
|
||||||
namespace Genode {
|
};
|
||||||
|
|
||||||
struct Allocator_tracer : Allocator
|
struct Allocator_tracer : Allocator
|
||||||
{
|
{
|
||||||
@ -32,105 +61,49 @@ namespace Genode {
|
|||||||
: id_space_elem(*this, space, id), size(size) { }
|
: id_space_elem(*this, space, id), size(size) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
Id_space<Alloc> _allocs;
|
Id_space<Alloc> allocs;
|
||||||
size_t _sum;
|
size_t sum { 0 };
|
||||||
Allocator &_wrapped;
|
Allocator &wrapped;
|
||||||
|
|
||||||
Allocator_tracer(Allocator &wrapped) : _sum(0), _wrapped(wrapped) { }
|
Allocator_tracer(Allocator &wrapped) : wrapped(wrapped) { }
|
||||||
|
|
||||||
size_t sum() const { return _sum; }
|
bool alloc(size_t size, void **out_addr) override
|
||||||
|
|
||||||
bool alloc(size_t size, void **out_addr)
|
|
||||||
{
|
{
|
||||||
_sum += size;
|
sum += size;
|
||||||
bool result = _wrapped.alloc(size, out_addr);
|
bool result = wrapped.alloc(size, out_addr);
|
||||||
new (_wrapped) Alloc(_allocs, Alloc::Id { (addr_t)*out_addr }, size);
|
new (wrapped) Alloc(allocs, Alloc::Id { (addr_t)*out_addr }, size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void *addr, size_t size)
|
void free(void *addr, size_t size) override
|
||||||
{
|
{
|
||||||
_allocs.apply<Alloc>(Alloc::Id { (addr_t)addr }, [&] (Alloc &alloc) {
|
allocs.apply<Alloc>(Alloc::Id { (addr_t)addr }, [&] (Alloc &alloc) {
|
||||||
_sum -= alloc.size;
|
sum -= alloc.size;
|
||||||
destroy(_wrapped, &alloc);
|
destroy(wrapped, &alloc);
|
||||||
_wrapped.free(addr, size);
|
wrapped.free(addr, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t overhead(size_t size) const override { return _wrapped.overhead(size); }
|
size_t overhead(size_t size) const override { return wrapped.overhead(size); }
|
||||||
bool need_size_for_free() const override { return _wrapped.need_size_for_free(); }
|
bool need_size_for_free() const override { return wrapped.need_size_for_free(); }
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Main
|
||||||
namespace Genode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for the formatted output of a chunk state
|
|
||||||
*/
|
|
||||||
static inline void print(Output &out, File_system::Chunk_level_0 const &chunk)
|
|
||||||
{
|
{
|
||||||
using namespace File_system;
|
Env &env;
|
||||||
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Allocator_tracer alloc { heap };
|
||||||
|
|
||||||
static char read_buf[Chunk_level_0::SIZE];
|
Main(Env &env) : env(env)
|
||||||
|
|
||||||
size_t used_size = chunk.used_size();
|
|
||||||
|
|
||||||
struct File_size_out_of_bounds { };
|
|
||||||
if (used_size > Chunk_level_0::SIZE)
|
|
||||||
throw File_size_out_of_bounds();
|
|
||||||
|
|
||||||
chunk.read(read_buf, used_size, 0);
|
|
||||||
|
|
||||||
Genode::print(out, "content (size=", used_size, "): ");
|
|
||||||
|
|
||||||
Genode::print(out, "\"");
|
|
||||||
for (unsigned i = 0; i < used_size; i++) {
|
|
||||||
char const c = read_buf[i];
|
|
||||||
if (c)
|
|
||||||
Genode::print(out, Genode::Char(c));
|
|
||||||
else
|
|
||||||
Genode::print(out, ".");
|
|
||||||
}
|
|
||||||
Genode::print(out, "\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void write(File_system::Chunk_level_0 &chunk,
|
|
||||||
char const *str, Genode::off_t seek_offset)
|
|
||||||
{
|
{
|
||||||
chunk.write(str, Genode::strlen(str), seek_offset);
|
log("--- RAM filesystem chunk test ---");
|
||||||
Genode::log("write \"", str, "\" at offset ", seek_offset, " -> ", chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void truncate(File_system::Chunk_level_0 &chunk,
|
|
||||||
File_system::file_size_t size)
|
|
||||||
{
|
|
||||||
chunk.truncate(size);
|
|
||||||
Genode::log("trunc(", size, ") -> ", chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int, char **)
|
|
||||||
{
|
|
||||||
using namespace File_system;
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
log("--- ram_fs_chunk test ---");
|
|
||||||
|
|
||||||
log("chunk sizes");
|
log("chunk sizes");
|
||||||
log(" level 0: payload=", (int)Chunk_level_0::SIZE, " sizeof=", sizeof(Chunk_level_0));
|
log(" level 0: payload=", (int)Chunk_level_0::SIZE, " sizeof=", sizeof(Chunk_level_0));
|
||||||
log(" level 1: payload=", (int)Chunk_level_1::SIZE, " sizeof=", sizeof(Chunk_level_1));
|
log(" level 1: payload=", (int)Chunk_level_1::SIZE, " sizeof=", sizeof(Chunk_level_1));
|
||||||
log(" level 2: payload=", (int)Chunk_level_2::SIZE, " sizeof=", sizeof(Chunk_level_2));
|
log(" level 2: payload=", (int)Chunk_level_2::SIZE, " sizeof=", sizeof(Chunk_level_2));
|
||||||
log(" level 3: payload=", (int)Chunk_level_3::SIZE, " sizeof=", sizeof(Chunk_level_3));
|
log(" level 3: payload=", (int)Chunk_level_3::SIZE, " sizeof=", sizeof(Chunk_level_3));
|
||||||
|
|
||||||
static Allocator_tracer alloc(*env()->heap());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Chunk_level_0 chunk(alloc, 0);
|
Chunk_level_0 chunk(alloc, 0);
|
||||||
|
|
||||||
write(chunk, "five-o-one", 0);
|
write(chunk, "five-o-one", 0);
|
||||||
|
|
||||||
/* overwrite part of the file */
|
/* overwrite part of the file */
|
||||||
@ -141,12 +114,24 @@ int main(int, char **)
|
|||||||
write(chunk, "YM-2149", 35);
|
write(chunk, "YM-2149", 35);
|
||||||
|
|
||||||
truncate(chunk, 30);
|
truncate(chunk, 30);
|
||||||
|
|
||||||
for (unsigned i = 29; i > 0; i--)
|
for (unsigned i = 29; i > 0; i--)
|
||||||
truncate(chunk, i);
|
truncate(chunk, i);
|
||||||
}
|
}
|
||||||
|
log("allocator: sum=", alloc.sum);
|
||||||
log("allocator: sum=", alloc.sum());
|
log("--- RAM filesystem chunk test finished ---");
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write(Chunk_level_0 &chunk, char const *str, off_t seek_offset)
|
||||||
|
{
|
||||||
|
chunk.write(str, strlen(str), seek_offset);
|
||||||
|
log("write \"", str, "\" at offset ", seek_offset, " -> ", chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void truncate(Chunk_level_0 &chunk, file_size_t size)
|
||||||
|
{
|
||||||
|
chunk.truncate(size);
|
||||||
|
log("trunc(", size, ") -> ", chunk);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { struct Main main(env); }
|
||||||
|
@ -13,26 +13,16 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <util/reconstructible.h>
|
#include <util/reconstructible.h>
|
||||||
#include <base/log.h>
|
#include <base/component.h>
|
||||||
|
|
||||||
using Genode::Reconstructible;
|
|
||||||
using Genode::Constructible;
|
|
||||||
using Genode::log;
|
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
struct Object
|
struct Object
|
||||||
{
|
{
|
||||||
unsigned const id;
|
unsigned const id;
|
||||||
|
|
||||||
Object(unsigned id) : id(id)
|
Object(unsigned id) : id(id) { log("construct Object ", id); }
|
||||||
{
|
~Object() { log("destruct Object ", id); }
|
||||||
log("construct Object ", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Object()
|
|
||||||
{
|
|
||||||
log("destruct Object ", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void method() { log("method called on Object ", id); }
|
void method() { log("method called on Object ", id); }
|
||||||
void const_method() const { log("const method called on Object ", id); }
|
void const_method() const { log("const method called on Object ", id); }
|
||||||
@ -42,18 +32,12 @@ struct Object
|
|||||||
struct Member_with_reference
|
struct Member_with_reference
|
||||||
{
|
{
|
||||||
Object &reference;
|
Object &reference;
|
||||||
|
int const c = 13;
|
||||||
|
|
||||||
const int c = 13;
|
Member_with_reference(Object &reference) : reference(reference) {
|
||||||
|
log("construct Member_with_reference"); }
|
||||||
|
|
||||||
Member_with_reference(Object &reference) : reference(reference)
|
~Member_with_reference() { log("destruct Member_with_reference"); }
|
||||||
{
|
|
||||||
log("construct Member_with_reference");
|
|
||||||
}
|
|
||||||
|
|
||||||
~Member_with_reference()
|
|
||||||
{
|
|
||||||
log("destruct Member_with_reference");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -62,17 +46,10 @@ struct Compound
|
|||||||
Reconstructible<Member_with_reference> member;
|
Reconstructible<Member_with_reference> member;
|
||||||
Constructible<Member_with_reference> lazy_member;
|
Constructible<Member_with_reference> lazy_member;
|
||||||
|
|
||||||
Compound(Object &object)
|
Compound(Object &object) : member(object) {
|
||||||
:
|
log("construct Compound"); }
|
||||||
member(object)
|
|
||||||
{
|
|
||||||
log("construct Compound");
|
|
||||||
}
|
|
||||||
|
|
||||||
~Compound()
|
~Compound() { log("destruct Compound"); }
|
||||||
{
|
|
||||||
log("destruct Compound");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -94,34 +71,26 @@ struct Throwing
|
|||||||
log("construct Throwing -> throw exception");
|
log("construct Throwing -> throw exception");
|
||||||
throw -1;
|
throw -1;
|
||||||
} else {
|
} else {
|
||||||
log("construct Throwing -> don't throw");
|
log("construct Throwing -> don't throw"); }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Throwing()
|
virtual ~Throwing() { log("destruct Throwing"); }
|
||||||
{
|
|
||||||
log("destruct Throwing");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void call_const_method(Compound const &compound)
|
struct Main
|
||||||
{
|
{
|
||||||
compound.member->reference.const_method();
|
void call_const_method(Compound const &compound) {
|
||||||
}
|
compound.member->reference.const_method(); }
|
||||||
|
|
||||||
|
Main(Env &env)
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
log("--- Reconstructible utility test ---");
|
||||||
|
|
||||||
log("--- test-reconstructible started ---");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Object object_1(1);
|
Object object_1(1);
|
||||||
Object object_2(2);
|
Object object_2(2);
|
||||||
|
|
||||||
log("-- create Compound object --");
|
log("create Compound object");
|
||||||
Compound compound(object_1);
|
Compound compound(object_1);
|
||||||
|
|
||||||
log("compound.member.constructed returns ",
|
log("compound.member.constructed returns ",
|
||||||
@ -129,44 +98,41 @@ int main(int, char **)
|
|||||||
log("compound.lazy_member.constructed returns ",
|
log("compound.lazy_member.constructed returns ",
|
||||||
compound.lazy_member.constructed());
|
compound.lazy_member.constructed());
|
||||||
|
|
||||||
log("-- construct lazy member --");
|
log("construct lazy member");
|
||||||
compound.lazy_member.construct(object_2);
|
compound.lazy_member.construct(object_2);
|
||||||
log("compound.lazy_member.constructed returns ",
|
log("compound.lazy_member.constructed returns ",
|
||||||
compound.lazy_member.constructed());
|
compound.lazy_member.constructed());
|
||||||
|
|
||||||
log("-- call method on member (with reference to Object 1) --");
|
log("call method on member (with reference to Object 1)");
|
||||||
call_const_method(compound);
|
call_const_method(compound);
|
||||||
|
|
||||||
log("-- reconstruct member with Object 2 as reference --");
|
log("reconstruct member with Object 2 as reference");
|
||||||
compound.member.construct(object_2);
|
compound.member.construct(object_2);
|
||||||
|
|
||||||
log("-- call method on member --");
|
log("call method on member");
|
||||||
call_const_method(compound);
|
call_const_method(compound);
|
||||||
|
|
||||||
log("-- destruct member --");
|
log("destruct member");
|
||||||
compound.member.destruct();
|
compound.member.destruct();
|
||||||
|
|
||||||
log("-- try to call method on member, catch exception --");
|
log("try to call method on member, catch exception");
|
||||||
try {
|
try { call_const_method(compound); }
|
||||||
call_const_method(compound); }
|
|
||||||
catch (typename Reconstructible<Member_with_reference>::Deref_unconstructed_object) {
|
catch (typename Reconstructible<Member_with_reference>::Deref_unconstructed_object) {
|
||||||
log("got exception, as expected"); }
|
log("got exception, as expected"); }
|
||||||
|
|
||||||
log("-- destruct Compound and Objects 1 and 2 --");
|
log("destruct Compound and Objects 1 and 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log("-- construct Throwing object");
|
log("construct Throwing object");
|
||||||
Bool const b_false(false), b_true(true);
|
Bool const b_false(false), b_true(true);
|
||||||
|
|
||||||
Reconstructible<Throwing> inst(b_false);
|
Reconstructible<Throwing> inst(b_false);
|
||||||
inst.construct(b_true);
|
inst.construct(b_true);
|
||||||
Genode::error("expected contructor to throw");
|
Genode::error("expected contructor to throw");
|
||||||
} catch (int i) {
|
} catch (int i) {
|
||||||
log("-- catched exception as expected");
|
log("got exception, as expected"); }
|
||||||
}
|
|
||||||
|
|
||||||
log("--- test-reconstructible finished ---");
|
log("--- Reconstructible utility test finished ---");
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Rom-file to block-session client test implementation
|
* \brief ROM-file to block-session client test implementation
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2010-07-07
|
* \date 2010-07-07
|
||||||
*
|
*
|
||||||
* The test program compares the values delivered by the block-service,
|
* The test program compares the values delivered by the block-service,
|
||||||
@ -8,120 +9,72 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/allocator_avl.h>
|
#include <base/allocator_avl.h>
|
||||||
#include <base/log.h>
|
#include <base/heap.h>
|
||||||
#include <base/sleep.h>
|
#include <base/component.h>
|
||||||
#include <base/exception.h>
|
|
||||||
#include <base/thread.h>
|
|
||||||
#include <os/config.h>
|
|
||||||
#include <block_session/connection.h>
|
#include <block_session/connection.h>
|
||||||
#include <rom_session/connection.h>
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
|
||||||
|
|
||||||
class Comparer : public Genode::Thread_deprecated<8192>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Block::Connection _blk_con;
|
|
||||||
Genode::Rom_connection _rom;
|
|
||||||
Genode::addr_t _addr;
|
|
||||||
|
|
||||||
class Block_file_differ : Genode::Exception {};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum {
|
|
||||||
BLOCK_REQ_PARALLEL = 10 /* number of blocks to handle per block-request */
|
|
||||||
};
|
|
||||||
|
|
||||||
Comparer(Genode::Allocator_avl *block_alloc,
|
|
||||||
const char* filename)
|
|
||||||
: Thread_deprecated("comparer"), _blk_con(block_alloc), _rom(filename),
|
|
||||||
_addr(Genode::env()->rm_session()->attach(_rom.dataspace())) { }
|
|
||||||
|
|
||||||
void entry()
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
Block::Session::Tx::Source *source = _blk_con.tx();
|
struct Main
|
||||||
size_t blk_size = 0;
|
{
|
||||||
Block::sector_t blk_cnt = 0;
|
enum { REQ_PARALLEL = 10 };
|
||||||
Genode::addr_t end =
|
|
||||||
_addr + Dataspace_client(_rom.dataspace()).size();
|
using File_name = String<64>;
|
||||||
|
using Packet_descriptor = Block::Packet_descriptor;
|
||||||
|
struct Files_differ : Exception { };
|
||||||
|
struct Device_not_readable : Exception { };
|
||||||
|
struct Read_request_failed : Exception { };
|
||||||
|
|
||||||
|
Env &env;
|
||||||
|
Attached_rom_dataspace config { env, "config" };
|
||||||
|
File_name file_name { config.xml().attribute_value("file", File_name()) };
|
||||||
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Allocator_avl block_alloc { &heap };
|
||||||
|
Block::Connection block { env, &block_alloc };
|
||||||
|
Attached_rom_dataspace rom { env, file_name.string() };
|
||||||
|
|
||||||
|
Main(Env &env) : env(env)
|
||||||
|
{
|
||||||
|
log("--- ROM Block test ---");
|
||||||
|
|
||||||
|
Block::Session::Tx::Source &src = *block.tx();
|
||||||
|
size_t blk_sz;
|
||||||
|
Block::sector_t blk_cnt;
|
||||||
Block::Session::Operations ops;
|
Block::Session::Operations ops;
|
||||||
_blk_con.info(&blk_cnt, &blk_size, &ops);
|
|
||||||
|
|
||||||
if (!ops.supported(Block::Packet_descriptor::READ)) {
|
block.info(&blk_cnt, &blk_sz, &ops);
|
||||||
error("Block device not readable!");
|
if (!ops.supported(Packet_descriptor::READ)) {
|
||||||
}
|
throw Device_not_readable(); }
|
||||||
|
|
||||||
log("We have ", blk_cnt, " blocks with a "
|
log("We have ", blk_cnt, " blocks with a size of ", blk_sz, " bytes");
|
||||||
"size of ", Hex(blk_size), " bytes");
|
for (size_t i = 0; i < blk_cnt; i += REQ_PARALLEL) {
|
||||||
|
size_t cnt = (blk_cnt - i > REQ_PARALLEL) ? REQ_PARALLEL : blk_cnt - i;
|
||||||
|
Packet_descriptor pkt(src.alloc_packet(cnt * blk_sz),
|
||||||
|
Packet_descriptor::READ, i, cnt);
|
||||||
|
|
||||||
for (size_t i = 0; i < blk_cnt; i += BLOCK_REQ_PARALLEL) {
|
log("Check blocks ", i, "..", i + cnt - 1);
|
||||||
try {
|
src.submit_packet(pkt);
|
||||||
size_t cnt = (blk_cnt - i > BLOCK_REQ_PARALLEL)
|
pkt = src.get_acked_packet();
|
||||||
? BLOCK_REQ_PARALLEL : blk_cnt - i;
|
if (!pkt.succeeded()) {
|
||||||
Block::Packet_descriptor p(source->alloc_packet(cnt * blk_size),
|
throw Read_request_failed(); }
|
||||||
Block::Packet_descriptor::READ, i, cnt);
|
|
||||||
|
|
||||||
source->submit_packet(p);
|
char const *rom_src = rom.local_addr<char>() + i * blk_sz;
|
||||||
p = source->get_acked_packet();
|
if (strcmp(rom_src, src.packet_content(pkt), rom.size())) {
|
||||||
|
throw Files_differ(); }
|
||||||
|
|
||||||
if (!p.succeeded()) {
|
src.release_packet(pkt);
|
||||||
error("could not read block ", Hex(i), "-", Hex(i + cnt));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
log("--- ROM Block test finished ---");
|
||||||
char* blk_src = source->packet_content(p);
|
|
||||||
char* rom_src = (char*) _addr + i * blk_size;
|
|
||||||
bool differ = false;
|
|
||||||
for (size_t j = 0; j < cnt; j++)
|
|
||||||
for (size_t k = 0; k < blk_size; k++) {
|
|
||||||
if (&rom_src[j*blk_size+k] >= (char*)end) {
|
|
||||||
error("end of image file reached!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (blk_src[j*blk_size+k] != rom_src[j*blk_size+k])
|
|
||||||
differ = true;
|
|
||||||
}
|
|
||||||
if (differ) {
|
|
||||||
warning("block ", i, " differs!");
|
|
||||||
throw Block_file_differ();
|
|
||||||
}
|
|
||||||
source->release_packet(p);
|
|
||||||
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
|
||||||
error("Mmh, strange we run out of packets");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log("all done, finished!");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
log("--- Block session test ---");
|
|
||||||
|
|
||||||
try {
|
|
||||||
static char filename[64];
|
|
||||||
config()->xml_node().attribute("file").value(filename, sizeof(filename));
|
|
||||||
Allocator_avl block_alloc(env()->heap());
|
|
||||||
Comparer th(&block_alloc, filename);
|
|
||||||
th.start();
|
|
||||||
sleep_forever();
|
|
||||||
} catch (Rom_connection::Rom_connection_failed) {
|
|
||||||
error("config file or file given by <filename> tag is missing.");
|
|
||||||
}
|
|
||||||
log("An error occured, exit now ...");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/log.h>
|
|
||||||
#include <base/printf.h>
|
|
||||||
#include <rtc_session/connection.h>
|
#include <rtc_session/connection.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
struct Main
|
struct Main
|
||||||
{
|
{
|
||||||
Main(Genode::Env &env)
|
Main(Genode::Env &env)
|
||||||
@ -31,9 +31,8 @@ struct Main
|
|||||||
for (unsigned i = 0; i < 4; ++i) {
|
for (unsigned i = 0; i < 4; ++i) {
|
||||||
Rtc::Timestamp now = rtc.current_time();
|
Rtc::Timestamp now = rtc.current_time();
|
||||||
|
|
||||||
Genode::printf("RTC: %u-%02u-%02u %02u:%02u:%02u\n",
|
log("RTC: ", now.year, "-", now.month, "-", now.day, " ",
|
||||||
now.year, now.month, now.day,
|
now.hour, ":", now.minute, ":", now.second);
|
||||||
now.hour, now.minute, now.second);
|
|
||||||
|
|
||||||
timer.msleep(1000);
|
timer.msleep(1000);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <os/attached_ram_dataspace.h>
|
#include <os/attached_ram_dataspace.h>
|
||||||
#include <os/config.h>
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <driver.h>
|
#include <driver.h>
|
||||||
@ -51,13 +51,13 @@ struct Main
|
|||||||
Env &env;
|
Env &env;
|
||||||
Packet_descriptor pkt;
|
Packet_descriptor pkt;
|
||||||
unsigned long time_before_ms;
|
unsigned long time_before_ms;
|
||||||
Timer::Connection timer;
|
Timer::Connection timer { env };
|
||||||
Operation operation { READ };
|
Operation operation { READ };
|
||||||
Signal_handler<Main> ack_handler { env.ep(), *this, &Main::update_state };
|
Signal_handler<Main> ack_handler { env.ep(), *this, &Main::update_state };
|
||||||
Driver_session drv_session { ack_handler };
|
Driver_session drv_session { ack_handler };
|
||||||
Sd_card::Driver drv { env };
|
Sd_card::Driver drv { env };
|
||||||
size_t const buf_size_kib { config()->xml_node()
|
size_t const buf_size_kib { Attached_rom_dataspace(env, "config")
|
||||||
.attribute_value("buffer_size_kib",
|
.xml().attribute_value("buffer_size_kib",
|
||||||
(size_t)0) };
|
(size_t)0) };
|
||||||
size_t const buf_size { buf_size_kib * 1024 };
|
size_t const buf_size { buf_size_kib * 1024 };
|
||||||
Attached_ram_dataspace buf { &env.ram(), buf_size, UNCACHED };
|
Attached_ram_dataspace buf { &env.ram(), buf_size, UNCACHED };
|
||||||
|
@ -1,142 +1,100 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Test for signalling framework
|
* \brief Test for signalling framework
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2008-09-06
|
* \date 2008-09-06
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2008-2013 Genode Labs GmbH
|
* Copyright (C) 2008-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
#include <base/log.h>
|
|
||||||
#include <base/signal.h>
|
|
||||||
#include <base/sleep.h>
|
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
#include <base/registry.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <util/misc_math.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmit signals in a periodic fashion
|
* A thread that submits a signal context in a periodic fashion
|
||||||
*/
|
*/
|
||||||
class Sender : Thread
|
class Sender : Thread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Timer::Connection _timer; /* timer connection for local use */
|
Timer::Connection _timer;
|
||||||
Signal_transmitter _transmitter;
|
Signal_transmitter _transmitter;
|
||||||
unsigned const _interval_ms; /* interval between signals in milliseconds */
|
unsigned const _interval_ms;
|
||||||
bool _stop; /* state for destruction protocol */
|
bool const _verbose;
|
||||||
unsigned _submit_cnt; /* statistics */
|
bool _stop { false };
|
||||||
bool _idle; /* suppress the submission of signals */
|
unsigned _submit_cnt { 0 };
|
||||||
bool const _verbose; /* print activities */
|
bool _idle { false };
|
||||||
|
|
||||||
/**
|
|
||||||
* Sender thread submits signals every '_interval_ms' milliseconds
|
|
||||||
*/
|
|
||||||
void entry()
|
void entry()
|
||||||
{
|
{
|
||||||
while (!_stop) {
|
while (!_stop) {
|
||||||
|
|
||||||
if (!_idle) {
|
if (!_idle) {
|
||||||
_submit_cnt++;
|
_submit_cnt++;
|
||||||
|
if (_verbose) {
|
||||||
if (_verbose)
|
log("submit signal ", _submit_cnt); }
|
||||||
log("submit signal ", _submit_cnt);
|
|
||||||
|
|
||||||
_transmitter.submit();
|
_transmitter.submit();
|
||||||
|
if (_interval_ms) {
|
||||||
if (_interval_ms)
|
_timer.msleep(_interval_ms); }
|
||||||
_timer.msleep(_interval_ms);
|
} else {
|
||||||
} else
|
_timer.msleep(100); }
|
||||||
_timer.msleep(100);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
Sender(Env &env,
|
||||||
* Constructor
|
Signal_context_capability context,
|
||||||
*
|
unsigned interval_ms,
|
||||||
* \param context signal destination
|
bool verbose)
|
||||||
* \param interval_ms interval between signals
|
|
||||||
* \param verbose print status information
|
|
||||||
*/
|
|
||||||
Sender(Env &env, Signal_context_capability context,
|
|
||||||
unsigned interval_ms, bool verbose = true)
|
|
||||||
:
|
:
|
||||||
Thread(env, "sender", 4096*sizeof(long)),
|
Thread(env, "sender", 4096 * sizeof(addr_t)), _timer(env),
|
||||||
_timer(env),
|
_transmitter(context), _interval_ms(interval_ms), _verbose(verbose)
|
||||||
_transmitter(context),
|
|
||||||
_interval_ms(interval_ms),
|
|
||||||
_stop(false),
|
|
||||||
_submit_cnt(0),
|
|
||||||
_idle(0),
|
|
||||||
_verbose(verbose)
|
|
||||||
{
|
{
|
||||||
/* start thread at 'entry' function */
|
Thread::start();
|
||||||
start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/***************
|
||||||
* Destructor
|
** Accessors **
|
||||||
*/
|
***************/
|
||||||
~Sender()
|
|
||||||
{
|
|
||||||
/* tell thread to stop iterating */
|
|
||||||
_stop = true;
|
|
||||||
|
|
||||||
/* wait for current 'msleep' call of the thread to finish */
|
void idle(bool idle) { _idle = idle; }
|
||||||
_timer.msleep(0);
|
unsigned submit_cnt() const { return _submit_cnt; }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suppress the transmission of further signals
|
|
||||||
*/
|
|
||||||
void idle(bool idle = true) { _idle = idle; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return total number of submitted notifications
|
|
||||||
*/
|
|
||||||
unsigned submit_cnt() { return _submit_cnt; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal handler receives signals and takes some time to handle each
|
* A thread that receives signals and takes some time to handle each
|
||||||
*/
|
*/
|
||||||
class Handler : Thread
|
class Handler : Thread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Timer::Connection _timer; /* timer connection for local use */
|
Timer::Connection _timer;
|
||||||
unsigned const _dispatch_ms; /* time needed for dispatching a signal */
|
unsigned const _dispatch_ms;
|
||||||
unsigned const _id; /* unique ID of signal handler for debug output */
|
unsigned const _id;
|
||||||
static unsigned _id_cnt; /* counter for producing unique IDs */
|
bool const _verbose;
|
||||||
Signal_receiver &_receiver; /* signal endpoint */
|
Signal_receiver &_receiver;
|
||||||
bool _stop; /* state for destruction protocol */
|
bool _stop { false };
|
||||||
unsigned _receive_cnt; /* number of received notifications */
|
unsigned _receive_cnt { 0 };
|
||||||
unsigned _activation_cnt; /* number of invocations of the signal handler */
|
unsigned _activation_cnt { 0 };
|
||||||
bool _idle; /* suppress the further handling of signals */
|
bool _idle { false };
|
||||||
bool const _verbose; /* print status information */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal handler needs '_dispatch_ms' milliseconds for each signal
|
|
||||||
*/
|
|
||||||
void entry()
|
void entry()
|
||||||
{
|
{
|
||||||
while (!_stop) {
|
while (!_stop) {
|
||||||
|
|
||||||
if (!_idle) {
|
if (!_idle) {
|
||||||
Signal signal = _receiver.wait_for_signal();
|
Signal signal = _receiver.wait_for_signal();
|
||||||
|
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
log("handler ", _id, " got ", signal.num(), " "
|
log("handler ", _id, " got ", signal.num(), " "
|
||||||
"signal", (signal.num() == 1 ? "" : "s"), " "
|
"signal", (signal.num() == 1 ? "" : "s"), " "
|
||||||
@ -145,7 +103,6 @@ class Handler : Thread
|
|||||||
_receive_cnt += signal.num();
|
_receive_cnt += signal.num();
|
||||||
_activation_cnt++;
|
_activation_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dispatch_ms)
|
if (_dispatch_ms)
|
||||||
_timer.msleep(_dispatch_ms);
|
_timer.msleep(_dispatch_ms);
|
||||||
}
|
}
|
||||||
@ -153,486 +110,351 @@ class Handler : Thread
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
Handler(Env &env,
|
||||||
* Constructor
|
Signal_receiver &receiver,
|
||||||
*
|
unsigned dispatch_ms,
|
||||||
* \param receiver receiver to request signals from
|
bool verbose,
|
||||||
* \param dispatch_ms duration of signal-handler activity
|
unsigned id)
|
||||||
* \param verbose print status information
|
|
||||||
*/
|
|
||||||
Handler(Env &env, Signal_receiver &receiver, unsigned dispatch_ms, bool verbose = true)
|
|
||||||
:
|
:
|
||||||
Thread(env, "handler", 4096*sizeof(long)),
|
Thread(env, "handler", 4096 * sizeof(addr_t)), _timer(env),
|
||||||
_timer(env),
|
_dispatch_ms(dispatch_ms), _id(id), _verbose(verbose),
|
||||||
_dispatch_ms(dispatch_ms),
|
_receiver(receiver)
|
||||||
_id(++_id_cnt),
|
|
||||||
_receiver(receiver),
|
|
||||||
_stop(false),
|
|
||||||
_receive_cnt(0),
|
|
||||||
_activation_cnt(0),
|
|
||||||
_idle(0),
|
|
||||||
_verbose(verbose)
|
|
||||||
{
|
{
|
||||||
start();
|
Thread::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void print(Output &output) const { Genode::print(output, "handler ", _id); }
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~Handler()
|
|
||||||
{
|
|
||||||
/* tell thread to stop iterating */
|
|
||||||
_stop = true;
|
|
||||||
|
|
||||||
/* wait for current 'msleep' call of the thread to finish */
|
/***************
|
||||||
_timer.msleep(0);
|
** Accessors **
|
||||||
}
|
***************/
|
||||||
|
|
||||||
/**
|
void idle(bool idle) { _idle = idle; }
|
||||||
* Suppress the handling of further signals
|
|
||||||
*/
|
|
||||||
void idle(bool idle = true) { _idle = idle; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return total number of received notifications
|
|
||||||
*/
|
|
||||||
unsigned receive_cnt() const { return _receive_cnt; }
|
unsigned receive_cnt() const { return _receive_cnt; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Return total number of signal-handler activations
|
|
||||||
*/
|
|
||||||
unsigned activation_cnt() const { return _activation_cnt; }
|
unsigned activation_cnt() const { return _activation_cnt; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counter for generating unique signal-handler IDs
|
* Base of all signalling tests
|
||||||
*/
|
*/
|
||||||
unsigned Handler::_id_cnt = 0;
|
struct Signal_test
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Counter for enumerating the tests
|
|
||||||
*/
|
|
||||||
static unsigned test_cnt = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Symbolic error codes
|
|
||||||
*/
|
|
||||||
class Test_failed { };
|
|
||||||
class Test_failed_with_unequal_sent_and_received_signals : public Test_failed { };
|
|
||||||
class Test_failed_with_unequal_activation_of_handlers : public Test_failed { };
|
|
||||||
|
|
||||||
|
|
||||||
class Id_signal_context : public Signal_context
|
|
||||||
{
|
{
|
||||||
private:
|
enum { SPEED = 10 };
|
||||||
|
|
||||||
int _id;
|
int id;
|
||||||
|
|
||||||
public:
|
Signal_test(int id, char const *brief) : id(id) {
|
||||||
|
log("\nTEST ", id, ": ", brief, "\n"); }
|
||||||
|
|
||||||
Id_signal_context(int id) : _id(id) { }
|
~Signal_test() { log("\nTEST ", id, " finished\n"); }
|
||||||
|
|
||||||
int id() const { return _id; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Fast_sender_test : Signal_test
|
||||||
/**
|
|
||||||
* Test for reliable notification delivery
|
|
||||||
*
|
|
||||||
* For this test, the produce more notification than that can be handled.
|
|
||||||
* Still, the total number of notifications gets transmitted because of the
|
|
||||||
* batching of notifications in one signal. This test fails if the number of
|
|
||||||
* submitted notifications on the sender side does not match the number of
|
|
||||||
* notifications received at the signal handler.
|
|
||||||
*/
|
|
||||||
static void fast_sender_test(Env &env)
|
|
||||||
{
|
{
|
||||||
enum { SPEED = 10 };
|
static constexpr char const *brief =
|
||||||
enum { TEST_DURATION = 50*SPEED };
|
"reliable delivery if the sender is faster than the handlers";
|
||||||
enum { HANDLER_INTERVAL = 10*SPEED };
|
|
||||||
enum { SENDER_INTERVAL = 2*SPEED };
|
|
||||||
enum { FINISH_IDLE_TIME = 2*HANDLER_INTERVAL };
|
|
||||||
|
|
||||||
log("");
|
enum { HANDLER_INTERVAL_MS = 10 * SPEED,
|
||||||
log("TEST ", ++test_cnt, ": one sender, one handler, sender is faster than handler");
|
SENDER_INTERVAL_MS = 2 * SPEED,
|
||||||
log("");
|
DURATION_MS = 50 * SPEED,
|
||||||
|
FINISH_IDLE_MS = 2 * HANDLER_INTERVAL_MS };
|
||||||
|
|
||||||
|
struct Unequal_sent_and_received_signals : Exception { };
|
||||||
|
|
||||||
|
Env &env;
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_context context;
|
||||||
Signal_receiver receiver;
|
Signal_receiver receiver;
|
||||||
Id_signal_context context_123(123);
|
Handler handler { env, receiver, HANDLER_INTERVAL_MS, false, 1 };
|
||||||
|
Sender sender { env, receiver.manage(&context),
|
||||||
|
SENDER_INTERVAL_MS, false };
|
||||||
|
|
||||||
Heap heap(env.ram(), env.rm());
|
Fast_sender_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
||||||
Timer::Connection timer(env);
|
{
|
||||||
|
timer.msleep(DURATION_MS);
|
||||||
Handler *handler = new (heap) Handler(env, receiver, HANDLER_INTERVAL, false);
|
|
||||||
Sender *sender = new (heap) Sender(env, receiver.manage(&context_123),
|
|
||||||
SENDER_INTERVAL, false);
|
|
||||||
|
|
||||||
timer.msleep(TEST_DURATION);
|
|
||||||
|
|
||||||
/* stop emitting signals */
|
/* stop emitting signals */
|
||||||
log("deactivate sender");
|
log("deactivate sender");
|
||||||
sender->idle();
|
sender.idle(true);
|
||||||
timer.msleep(FINISH_IDLE_TIME);
|
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");
|
||||||
|
|
||||||
log("");
|
if (sender.submit_cnt() != handler.receive_cnt()) {
|
||||||
log("sender submitted a total of ", sender->submit_cnt(), " signals");
|
throw Unequal_sent_and_received_signals(); }
|
||||||
log("handler received a total of ", handler->receive_cnt(), " signals");
|
|
||||||
log("");
|
|
||||||
|
|
||||||
if (sender->submit_cnt() != handler->receive_cnt())
|
|
||||||
throw Test_failed();
|
|
||||||
|
|
||||||
receiver.dissolve(&context_123);
|
|
||||||
|
|
||||||
destroy(heap, sender);
|
|
||||||
destroy(heap, handler);
|
|
||||||
|
|
||||||
log("TEST ", test_cnt, " FINISHED");
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Multiple_handlers_test : Signal_test
|
||||||
/**
|
|
||||||
* Fairness test if multiple signal-handler threads are present at one receiver
|
|
||||||
*
|
|
||||||
* We expect that all handler threads get activated in a fair manner. The test
|
|
||||||
* fails if the number of activations per handler differs by more than one.
|
|
||||||
* Furthermore, if operating in non-descrete mode, the total number of sent and
|
|
||||||
* handled notifications is checked.
|
|
||||||
*/
|
|
||||||
static void multiple_handlers_test(Env &env)
|
|
||||||
{
|
{
|
||||||
enum { SPEED = 10 };
|
static constexpr char const *brief =
|
||||||
enum { TEST_DURATION = 50*SPEED };
|
"get multiple handlers at one sender activated in a fair manner";
|
||||||
enum { HANDLER_INTERVAL = 8*SPEED };
|
|
||||||
enum { SENDER_INTERVAL = 1*SPEED };
|
|
||||||
enum { FINISH_IDLE_TIME = 2*HANDLER_INTERVAL };
|
|
||||||
enum { NUM_HANDLERS = 4 };
|
|
||||||
|
|
||||||
log("");
|
enum { HANDLER_INTERVAL_MS = 8 * SPEED,
|
||||||
log("TEST ", ++test_cnt, ": one busy sender, ", (int)NUM_HANDLERS, " handlers");
|
SENDER_INTERVAL_MS = 1 * SPEED,
|
||||||
log("");
|
FINISH_IDLE_MS = 2 * HANDLER_INTERVAL_MS,
|
||||||
|
DURATION_MS = 50 * SPEED,
|
||||||
|
NR_OF_HANDLERS = 4 };
|
||||||
|
|
||||||
Heap heap(env.ram(), env.rm());
|
struct Unequal_sent_and_received_signals : Exception { };
|
||||||
Timer::Connection timer(env);
|
struct Unequal_activation_of_handlers : Exception { };
|
||||||
|
|
||||||
|
Env &env;
|
||||||
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_context context;
|
||||||
Signal_receiver receiver;
|
Signal_receiver receiver;
|
||||||
|
Registry<Registered<Handler> > handlers;
|
||||||
|
Sender sender { env, receiver.manage(&context),
|
||||||
|
SENDER_INTERVAL_MS, true};
|
||||||
|
|
||||||
Handler *handler[NUM_HANDLERS];
|
Multiple_handlers_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++)
|
{
|
||||||
handler[i] = new (heap) Handler(env, receiver, HANDLER_INTERVAL);
|
for (unsigned i = 0; i < NR_OF_HANDLERS; i++)
|
||||||
|
new (heap) Registered<Handler>(handlers, env, receiver,
|
||||||
Id_signal_context context_123(123);
|
HANDLER_INTERVAL_MS, true, i);
|
||||||
Sender *sender = new (heap) Sender(env, receiver.manage(&context_123), SENDER_INTERVAL);
|
timer.msleep(DURATION_MS);
|
||||||
|
|
||||||
timer.msleep(TEST_DURATION);
|
|
||||||
|
|
||||||
/* stop emitting signals */
|
/* stop emitting signals */
|
||||||
log("stop generating new notifications");
|
log("stop generating new signals");
|
||||||
sender->idle();
|
sender.idle(true);
|
||||||
timer.msleep(FINISH_IDLE_TIME);
|
timer.msleep(FINISH_IDLE_MS);
|
||||||
|
|
||||||
/* let handlers settle down */
|
/* let handlers settle down */
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++)
|
handlers.for_each([&] (Handler &handler) { handler.idle(true); });
|
||||||
handler[i]->idle();
|
timer.msleep(FINISH_IDLE_MS);
|
||||||
timer.msleep(FINISH_IDLE_TIME);
|
|
||||||
|
|
||||||
/* print signal delivery statistics */
|
/* print statistics and clean up */
|
||||||
log("");
|
unsigned total_rcv = 0, max_act = 0, min_act = ~0;;
|
||||||
log("sender submitted a total of ", sender->submit_cnt(), " signals");
|
handlers.for_each([&] (Handler &handler) {
|
||||||
unsigned total_receive_cnt = 0;
|
unsigned const rcv = handler.receive_cnt();
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++) {
|
unsigned const act = handler.activation_cnt();
|
||||||
log("handler ", i, " "
|
log(handler, " received ", rcv, " signals, was activated ", act, " times");
|
||||||
"received a total of ", handler[i]->receive_cnt(), " signals");
|
total_rcv += rcv;
|
||||||
total_receive_cnt += handler[i]->receive_cnt();
|
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(); }
|
||||||
}
|
}
|
||||||
log("all handlers received a total of ", total_receive_cnt, " signals");
|
};
|
||||||
|
|
||||||
/* check if number of sent notifications match the received ones */
|
struct Stress_test : Signal_test
|
||||||
if (sender->submit_cnt() != total_receive_cnt)
|
|
||||||
throw Test_failed_with_unequal_sent_and_received_signals();
|
|
||||||
|
|
||||||
/* print activation statistics */
|
|
||||||
log("");
|
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++)
|
|
||||||
log("handler ", i, " was activated ", handler[i]->activation_cnt(), " times");
|
|
||||||
log("");
|
|
||||||
|
|
||||||
/* check if handlers had been activated equally (tolerating a difference of one) */
|
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++) {
|
|
||||||
|
|
||||||
int diff = handler[0]->activation_cnt()
|
|
||||||
- handler[(i + 1)/NUM_HANDLERS]->activation_cnt();
|
|
||||||
|
|
||||||
if (abs(diff) > 1)
|
|
||||||
throw Test_failed_with_unequal_activation_of_handlers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cleanup */
|
|
||||||
receiver.dissolve(&context_123);
|
|
||||||
destroy(heap, sender);
|
|
||||||
for (int i = 0; i < NUM_HANDLERS; i++)
|
|
||||||
destroy(heap, handler[i]);
|
|
||||||
|
|
||||||
log("TEST ", test_cnt, " FINISHED");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stress test to estimate signal throughput
|
|
||||||
*
|
|
||||||
* For this test, we disable status output and any simulated wait times.
|
|
||||||
* We produce and handle notifications as fast as possible via spinning
|
|
||||||
* loops at the sender and handler side.
|
|
||||||
*/
|
|
||||||
static void stress_test(Env &env)
|
|
||||||
{
|
{
|
||||||
enum { SPEED = 10 };
|
static constexpr char const *brief =
|
||||||
enum { DURATION_SECONDS = 5 };
|
"throughput when submitting/handling as fast as possible";
|
||||||
enum { FINISH_IDLE_TIME = 100*SPEED };
|
|
||||||
|
|
||||||
log("");
|
enum { DURATION_SEC = 5 };
|
||||||
log("TEST ", ++test_cnt, ": stress test, busy signal transmission and handling");
|
|
||||||
log("");
|
|
||||||
|
|
||||||
Timer::Connection timer(env);
|
struct Unequal_sent_and_received_signals : Exception { };
|
||||||
Heap heap(env.ram(), env.rm());
|
|
||||||
|
Env &env;
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_context context;
|
||||||
Signal_receiver receiver;
|
Signal_receiver receiver;
|
||||||
Id_signal_context context_123(123);
|
Handler handler { env, receiver, 0, false, 1 };
|
||||||
|
Sender sender { env, receiver.manage(&context), 0, false };
|
||||||
|
|
||||||
Handler *handler = new (heap) Handler(env, receiver, 0, false);
|
Stress_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
||||||
Sender *sender = new (heap) Sender(env, receiver.manage(&context_123),
|
{
|
||||||
0, false);
|
for (unsigned i = 1; i <= DURATION_SEC; i++) {
|
||||||
|
log(i, "/", (unsigned)DURATION_SEC);
|
||||||
for (int i = 1; i <= DURATION_SECONDS; i++) {
|
|
||||||
log(i, "/", (int)DURATION_SECONDS);
|
|
||||||
timer.msleep(1000);
|
timer.msleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop emitting signals */
|
|
||||||
log("deactivate sender");
|
log("deactivate sender");
|
||||||
sender->idle();
|
sender.idle(true);
|
||||||
|
|
||||||
while (handler->receive_cnt() < sender->submit_cnt()) {
|
while (handler.receive_cnt() < sender.submit_cnt()) {
|
||||||
log("waiting for signals still in flight...");
|
log("waiting for signals still in flight...");
|
||||||
timer.msleep(FINISH_IDLE_TIME);
|
timer.msleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
log("");
|
log("");
|
||||||
log("sender submitted a total of ", sender->submit_cnt(), " signals");
|
log("sender submitted a total of ", sender.submit_cnt(), " signals");
|
||||||
log("handler received a total of ", handler->receive_cnt(), " signals");
|
log("handler received a total of ", handler.receive_cnt(), " signals");
|
||||||
log("");
|
log("");
|
||||||
log("processed ", (handler->receive_cnt()/DURATION_SECONDS), " notifications per second");
|
log("handler received ", handler.receive_cnt() / DURATION_SEC, " signals per second");
|
||||||
log("handler was activated ", (handler->activation_cnt()/DURATION_SECONDS), " times per second");
|
log("handler was activated ", handler.activation_cnt() / DURATION_SEC, " times per second");
|
||||||
log("");
|
log("");
|
||||||
|
|
||||||
if (sender->submit_cnt() != handler->receive_cnt())
|
if (sender.submit_cnt() != handler.receive_cnt())
|
||||||
throw Test_failed_with_unequal_sent_and_received_signals();
|
throw Unequal_sent_and_received_signals();
|
||||||
|
|
||||||
receiver.dissolve(&context_123);
|
|
||||||
destroy(heap, sender);
|
|
||||||
destroy(heap, handler);
|
|
||||||
|
|
||||||
log("TEST ", test_cnt, " FINISHED");
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lazy_receivers_test : Signal_test
|
||||||
static void lazy_receivers_test(Env &env)
|
|
||||||
{
|
{
|
||||||
log("");
|
static constexpr char const *brief = "lazy and out-of-order signal reception";
|
||||||
log("TEST ", ++test_cnt, ": lazy and out-of-order signal reception test");
|
|
||||||
log("");
|
|
||||||
|
|
||||||
Signal_receiver rec_1, rec_2;
|
Signal_context context_1, context_2;
|
||||||
Signal_context rec_context_1, rec_context_2;
|
Signal_receiver receiver_1, receiver_2;
|
||||||
|
Signal_transmitter transmitter_1 { receiver_1.manage(&context_1) };
|
||||||
Signal_transmitter transmitter_1(rec_1.manage(&rec_context_1));
|
Signal_transmitter transmitter_2 { receiver_2.manage(&context_2) };
|
||||||
Signal_transmitter transmitter_2(rec_2.manage(&rec_context_2));
|
|
||||||
|
|
||||||
|
Lazy_receivers_test(Env &env, int id) : Signal_test(id, brief)
|
||||||
|
{
|
||||||
log("submit and receive signals with multiple receivers in order");
|
log("submit and receive signals with multiple receivers in order");
|
||||||
transmitter_1.submit();
|
transmitter_1.submit();
|
||||||
transmitter_2.submit();
|
transmitter_2.submit();
|
||||||
|
|
||||||
{
|
{
|
||||||
Signal signal = rec_1.wait_for_signal();
|
Signal signal = receiver_1.wait_for_signal();
|
||||||
log("returned from wait_for_signal for receiver 1");
|
log("returned from wait_for_signal for receiver 1");
|
||||||
|
|
||||||
signal = rec_2.wait_for_signal();
|
signal = receiver_2.wait_for_signal();
|
||||||
log("returned from wait_for_signal for receiver 2");
|
log("returned from wait_for_signal for receiver 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
log("submit and receive signals with multiple receivers out of order");
|
log("submit and receive signals with multiple receivers out of order");
|
||||||
transmitter_1.submit();
|
transmitter_1.submit();
|
||||||
transmitter_2.submit();
|
transmitter_2.submit();
|
||||||
|
|
||||||
{
|
{
|
||||||
Signal signal = rec_2.wait_for_signal();
|
Signal signal = receiver_2.wait_for_signal();
|
||||||
log("returned from wait_for_signal for receiver 2");
|
log("returned from wait_for_signal for receiver 2");
|
||||||
|
|
||||||
signal = rec_1.wait_for_signal();
|
signal = receiver_1.wait_for_signal();
|
||||||
log("returned from wait_for_signal for receiver 1");
|
log("returned from wait_for_signal for receiver 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
rec_1.dissolve(&rec_context_1);
|
|
||||||
rec_2.dissolve(&rec_context_2);
|
|
||||||
|
|
||||||
log("TEST ", test_cnt, " FINISHED");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try correct initialization and cleanup of receiver/context
|
|
||||||
*/
|
|
||||||
static void check_context_management(Env &env)
|
|
||||||
{
|
|
||||||
Id_signal_context *context;
|
|
||||||
Signal_receiver *rec;
|
|
||||||
Signal_context_capability cap;
|
|
||||||
|
|
||||||
Timer::Connection timer(env);
|
|
||||||
Heap heap(env.ram(), env.rm());
|
|
||||||
|
|
||||||
/* setup receiver side */
|
|
||||||
context = new (heap) Id_signal_context(321);
|
|
||||||
rec = new (heap) Signal_receiver;
|
|
||||||
cap = rec->manage(context);
|
|
||||||
|
|
||||||
/* spawn sender */
|
|
||||||
Sender *sender = new (heap) Sender(env, cap, 500);
|
|
||||||
|
|
||||||
/* stop sender after timeout */
|
|
||||||
timer.msleep(1000);
|
|
||||||
log("suspend sender");
|
|
||||||
sender->idle();
|
|
||||||
|
|
||||||
/* collect pending signals and dissolve context from receiver */
|
|
||||||
{
|
|
||||||
Signal signal = rec->wait_for_signal();
|
|
||||||
log("got ", signal.num(), " signal(s) from ", signal.context());
|
|
||||||
}
|
|
||||||
rec->dissolve(context);
|
|
||||||
|
|
||||||
/* let sender spin for some time */
|
|
||||||
log("resume sender");
|
|
||||||
sender->idle(false);
|
|
||||||
timer.msleep(1000);
|
|
||||||
log("suspend sender");
|
|
||||||
sender->idle();
|
|
||||||
|
|
||||||
log("destroy sender");
|
|
||||||
destroy(heap, sender);
|
|
||||||
|
|
||||||
destroy(heap, context);
|
|
||||||
destroy(heap, rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if 'Signal_receiver::dissolve()' blocks as long as the signal context
|
|
||||||
* is still referenced by one or more 'Signal' objects
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Lock signal_context_destroyer_lock(Lock::LOCKED);
|
|
||||||
static bool signal_context_destroyed = false;
|
|
||||||
|
|
||||||
class Signal_context_destroyer : public Thread_deprecated<4096>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Signal_receiver *_receiver;
|
|
||||||
Signal_context *_context;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Signal_context_destroyer(Signal_receiver *receiver, Signal_context *context)
|
|
||||||
: Thread_deprecated("signal_context_destroyer"),
|
|
||||||
_receiver(receiver), _context(context) { }
|
|
||||||
|
|
||||||
void entry()
|
|
||||||
{
|
|
||||||
signal_context_destroyer_lock.lock();
|
|
||||||
_receiver->dissolve(_context);
|
|
||||||
signal_context_destroyed = true;
|
|
||||||
destroy(env()->heap(), _context);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Context_management_test : Signal_test
|
||||||
static void synchronized_context_destruction_test(Env &env)
|
|
||||||
{
|
{
|
||||||
|
static constexpr char const *brief =
|
||||||
|
"correct initialization and cleanup of receiver and context";
|
||||||
|
|
||||||
|
Env &env;
|
||||||
|
Timer::Connection timer { env };
|
||||||
|
Signal_context context;
|
||||||
Signal_receiver receiver;
|
Signal_receiver receiver;
|
||||||
Timer::Connection timer(env);
|
Signal_context_capability context_cap { receiver.manage(&context) };
|
||||||
static Heap heap(env.ram(), env.rm());
|
Sender sender { env, context_cap, 500, true };
|
||||||
|
|
||||||
Signal_context *context = new (heap) Signal_context;
|
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);
|
||||||
|
|
||||||
Signal_transmitter transmitter(receiver.manage(context));
|
/* collect pending signals and dissolve context from receiver */
|
||||||
transmitter.submit();
|
|
||||||
|
|
||||||
Signal_context_destroyer signal_context_destroyer(&receiver, context);
|
|
||||||
signal_context_destroyer.start();
|
|
||||||
|
|
||||||
/* The signal context destroyer thread should not be able to destroy the
|
|
||||||
* signal context during the 'Signal' objects life time. */
|
|
||||||
{
|
{
|
||||||
Signal signal = receiver.wait_for_signal();
|
Signal signal = receiver.wait_for_signal();
|
||||||
|
log("got ", signal.num(), " signal(s) from ", signal.context());
|
||||||
|
}
|
||||||
|
receiver.dissolve(&context);
|
||||||
|
|
||||||
/* let the signal context destroyer thread try to destroy the signal context */
|
/* let sender spin for some time */
|
||||||
signal_context_destroyer_lock.unlock();
|
log("resume sender");
|
||||||
|
sender.idle(false);
|
||||||
timer.msleep(1000);
|
timer.msleep(1000);
|
||||||
|
log("suspend sender");
|
||||||
Signal signal_copy = signal;
|
sender.idle(true);
|
||||||
Signal signal_copy2 = signal;
|
log("destroy sender");
|
||||||
|
|
||||||
signal_copy = signal_copy2;
|
|
||||||
|
|
||||||
if (signal_context_destroyed) {
|
|
||||||
error("signal context destroyed too early");
|
|
||||||
sleep_forever();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
signal_context_destroyer.join();
|
struct Synchronized_destruction_test : Signal_test, Thread
|
||||||
signal_context_destroyed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void many_managed_contexts(Env &env)
|
|
||||||
{
|
{
|
||||||
static Heap heap(env.ram(), env.rm());
|
static constexpr char const *brief =
|
||||||
for (unsigned round = 0; round < 10; ++round) {
|
"does 'dissolve' block as long as the signal context is referenced?";
|
||||||
|
|
||||||
unsigned const num_contexts = 200 + 5*round;
|
struct Failed : Exception { };
|
||||||
log("round ", round, ": create and manage ", num_contexts, " contexts");
|
|
||||||
|
|
||||||
Signal_receiver rec;
|
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 };
|
||||||
|
|
||||||
for (unsigned i = 0; i < num_contexts; ++i) {
|
void entry()
|
||||||
Id_signal_context *context = new (heap) Id_signal_context(i);
|
|
||||||
if (!rec.manage(context).valid()) {
|
|
||||||
error("failed to manage signal context");
|
|
||||||
sleep_forever();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("many contexts finished");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Component::construct(Genode::Env &env)
|
|
||||||
{
|
{
|
||||||
log("--- signalling test ---");
|
receiver.dissolve(&context);
|
||||||
|
log("dissolve finished");
|
||||||
fast_sender_test(env);
|
destroyed = true;
|
||||||
multiple_handlers_test(env);
|
destroy(heap, &context);
|
||||||
stress_test(env);
|
|
||||||
lazy_receivers_test(env);
|
|
||||||
check_context_management(env);
|
|
||||||
synchronized_context_destruction_test(env);
|
|
||||||
many_managed_contexts(env);
|
|
||||||
|
|
||||||
log("--- signalling test finished ---");
|
|
||||||
env.parent().exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
Thread::join();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Many_contexts_test : Signal_test
|
||||||
|
{
|
||||||
|
static constexpr char const *brief = "create and manage many contexts";
|
||||||
|
|
||||||
|
struct Manage_failed : Exception { };
|
||||||
|
|
||||||
|
Env &env;
|
||||||
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Registry<Registered<Signal_context> > contexts;
|
||||||
|
|
||||||
|
Many_contexts_test(Env &env, int id) : Signal_test(id, brief), env(env)
|
||||||
|
{
|
||||||
|
for (unsigned round = 0; round < 10; round++) {
|
||||||
|
|
||||||
|
unsigned const nr_of_contexts = 200 + 5 * round;
|
||||||
|
log("round ", round, ": manage ", nr_of_contexts, " contexts");
|
||||||
|
|
||||||
|
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(); }
|
||||||
|
}
|
||||||
|
contexts.for_each([&] (Registered<Signal_context> &context) {
|
||||||
|
receiver.dissolve(&context);
|
||||||
|
destroy(heap, &context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Main
|
||||||
|
{
|
||||||
|
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 ---");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Genode::Env &env) { static Main main(env); }
|
||||||
|
@ -13,14 +13,16 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/synced_interface.h>
|
#include <base/synced_interface.h>
|
||||||
#include <base/log.h>
|
#include <base/component.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
struct Adder
|
struct Adder
|
||||||
{
|
{
|
||||||
int add(int a, int b)
|
int add(int a, int b)
|
||||||
{
|
{
|
||||||
Genode::log("adding ", a, " + ", b);
|
log("adding ", a, " + ", b);
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -28,22 +30,25 @@ struct Adder
|
|||||||
|
|
||||||
struct Pseudo_lock
|
struct Pseudo_lock
|
||||||
{
|
{
|
||||||
void lock() { Genode::log("lock"); }
|
void lock() { log("lock"); }
|
||||||
void unlock() { Genode::log("unlock"); }
|
void unlock() { log("unlock"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(int, char **)
|
struct Main
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
Pseudo_lock lock;
|
Pseudo_lock lock;
|
||||||
Adder adder;
|
Adder adder;
|
||||||
|
Synced_interface<Adder, Pseudo_lock> synced_adder { lock, &adder };
|
||||||
|
|
||||||
Synced_interface<Adder, Pseudo_lock> synced_adder(lock, &adder);
|
Main(Env &env)
|
||||||
|
{
|
||||||
|
log("--- Synced interface test ---");
|
||||||
int const res = synced_adder()->add(13, 14);
|
int const res = synced_adder()->add(13, 14);
|
||||||
|
|
||||||
log("result is ", res);
|
log("result is ", res);
|
||||||
return 0;
|
log("--- Synced interface test finished ---");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -1,57 +1,49 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Terminal echo program
|
* \brief Terminal echo program
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2009-10-16
|
* \date 2009-10-16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
* Copyright (C) 2009-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <base/log.h>
|
/* Genode includes */
|
||||||
#include <base/signal.h>
|
#include <base/component.h>
|
||||||
#include <terminal_session/connection.h>
|
#include <terminal_session/connection.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
static const bool verbose = false;
|
struct Main
|
||||||
|
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
static Terminal::Connection terminal;
|
Terminal::Connection terminal;
|
||||||
|
Signal_handler<Main> read_avail;
|
||||||
|
char read_buffer[100];
|
||||||
|
|
||||||
enum { READ_BUFFER_SIZE = 100 };
|
String<128> intro {
|
||||||
static char read_buffer[READ_BUFFER_SIZE];
|
"--- Terminal echo test started - now you can type characters to be echoed. ---\r\n" };
|
||||||
|
|
||||||
Signal_receiver sig_rec;
|
void handle_read_avail()
|
||||||
Signal_context sig_ctx;
|
{
|
||||||
|
unsigned num_bytes = terminal.read(read_buffer, sizeof(read_buffer));
|
||||||
terminal.read_avail_sigh(sig_rec.manage(&sig_ctx));
|
log("got ", num_bytes, " byte(s)");
|
||||||
|
for (unsigned i = 0; i < num_bytes; i++) {
|
||||||
static const char *intro_text =
|
|
||||||
"--- Terminal echo test started - now you can type characters to be echoed. ---\r\n";
|
|
||||||
terminal.write(intro_text, strlen(intro_text) + 1);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
sig_rec.wait_for_signal();
|
|
||||||
|
|
||||||
int num_bytes = terminal.read(read_buffer, sizeof(read_buffer));
|
|
||||||
|
|
||||||
if (verbose && (num_bytes > 0))
|
|
||||||
log("got ", num_bytes, " bytes");
|
|
||||||
|
|
||||||
for (int i = 0; i < num_bytes; i++) {
|
|
||||||
if (read_buffer[i] == '\r') {
|
if (read_buffer[i] == '\r') {
|
||||||
terminal.write("\n", 1);
|
terminal.write("\n", 1); }
|
||||||
}
|
|
||||||
|
|
||||||
terminal.write(&read_buffer[i], 1);
|
terminal.write(&read_buffer[i], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
Main(Env &env) : terminal(env),
|
||||||
|
read_avail(env.ep(), *this, &Main::handle_read_avail)
|
||||||
|
{
|
||||||
|
terminal.read_avail_sigh(read_avail);
|
||||||
|
terminal.write(intro.string(), intro.length() + 1);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -11,14 +11,15 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <base/log.h>
|
/* Genode includes */
|
||||||
|
#include <base/component.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
struct Worker : Genode::Thread_deprecated<4096>
|
struct Worker : Thread
|
||||||
{
|
{
|
||||||
Timer::Session &timer;
|
Timer::Session &timer;
|
||||||
unsigned const result_value;
|
unsigned const result_value;
|
||||||
@ -26,33 +27,31 @@ struct Worker : Genode::Thread_deprecated<4096>
|
|||||||
|
|
||||||
void entry()
|
void entry()
|
||||||
{
|
{
|
||||||
log("worker thread is up");
|
log("Worker thread is up");
|
||||||
timer.msleep(250);
|
timer.msleep(250);
|
||||||
|
|
||||||
log("worker is leaving the entry function with "
|
log("Worker is leaving the entry function with result=", result_value);
|
||||||
"result=", result_value, "...");
|
|
||||||
result = result_value;
|
result = result_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Worker(Timer::Session &timer, int result_value)
|
Worker(Env &env, Timer::Session &timer, unsigned result_value)
|
||||||
:
|
: Thread(env, "worker", 1024 * sizeof(addr_t)), timer(timer),
|
||||||
Thread_deprecated("worker"),
|
result_value(result_value), result(~0)
|
||||||
timer(timer), result_value(result_value), result(~0)
|
|
||||||
{
|
{
|
||||||
start();
|
Thread::start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
struct Main
|
||||||
* Main program
|
|
||||||
*/
|
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
log("--- thread join test ---");
|
struct Worker_unfinished_after_join : Exception { };
|
||||||
|
|
||||||
Timer::Connection timer;
|
Timer::Connection timer;
|
||||||
|
|
||||||
|
Main(Env &env) : timer(env)
|
||||||
|
{
|
||||||
|
log("--- Thread join test ---");
|
||||||
for (unsigned i = 0; i < 10; i++) {
|
for (unsigned i = 0; i < 10; i++) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -61,15 +60,14 @@ int main(int, char **)
|
|||||||
* to 'Worker::result' variable. By validating this value,
|
* to 'Worker::result' variable. By validating this value,
|
||||||
* we determine whether the worker has finished or not.
|
* we determine whether the worker has finished or not.
|
||||||
*/
|
*/
|
||||||
Worker worker(timer, i);
|
Worker worker(env, timer, i);
|
||||||
worker.join();
|
worker.join();
|
||||||
|
|
||||||
if (worker.result != i) {
|
if (worker.result != i) {
|
||||||
error("work remains unfinished after 'join()' returned");
|
throw Worker_unfinished_after_join(); }
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
log("--- Thread join test finished ---");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
log("--- signalling test finished ---");
|
|
||||||
return 0;
|
void Component::construct(Genode::Env &env) { static Main main(env); }
|
||||||
}
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Test for the timed-semaphore
|
* \brief Test for the timed-semaphore
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2010-03-05
|
* \date 2010-03-05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,93 +12,67 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <os/timed_semaphore.h>
|
#include <os/timed_semaphore.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
#include <base/component.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
class Wakeup_thread : public Thread_deprecated<4096>
|
|
||||||
|
struct Test : Thread
|
||||||
{
|
{
|
||||||
private:
|
struct Failed : Exception { };
|
||||||
|
|
||||||
Timed_semaphore *_sem;
|
unsigned id;
|
||||||
Timer::Session *_timer;
|
Timer::Connection wakeup_timer;
|
||||||
int _timeout;
|
unsigned const wakeup_period;
|
||||||
Lock _lock;
|
Timed_semaphore sem;
|
||||||
bool _stop;
|
bool stop_wakeup { false };
|
||||||
|
Lock wakeup_stopped { Lock::LOCKED };
|
||||||
public:
|
bool got_timeouts { false };
|
||||||
|
|
||||||
Wakeup_thread(Timed_semaphore *sem,
|
|
||||||
Timer::Session *timer,
|
|
||||||
Alarm::Time timeout)
|
|
||||||
: Thread_deprecated("wakeup"), _sem(sem), _timer(timer), _timeout(timeout),
|
|
||||||
_lock(Lock::LOCKED), _stop(false) { }
|
|
||||||
|
|
||||||
void entry()
|
void entry()
|
||||||
{
|
{
|
||||||
while(true) {
|
do {
|
||||||
_timer->msleep(_timeout);
|
wakeup_timer.msleep(wakeup_period);
|
||||||
_sem->up();
|
sem.up();
|
||||||
|
} while (!stop_wakeup);
|
||||||
if (_stop) {
|
wakeup_stopped.unlock();
|
||||||
_lock.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() { _stop = true; _lock.lock(); }
|
Test(Env &env, bool timeouts, unsigned id, char const *brief)
|
||||||
|
: Thread(env, "wakeup", 1024 * sizeof(addr_t)), id(id), wakeup_timer(env),
|
||||||
|
wakeup_period(timeouts ? 1000 : 100)
|
||||||
|
{
|
||||||
|
log("\nTEST ", id, ": ", brief, "\n");
|
||||||
|
Thread::start();
|
||||||
|
try { for (int i = 0; i < 10; i++) { sem.down(timeouts ? 100 : 1000); } }
|
||||||
|
catch (Timeout_exception) { got_timeouts = true; }
|
||||||
|
if (timeouts != got_timeouts) {
|
||||||
|
throw Failed(); }
|
||||||
|
|
||||||
|
stop_wakeup = true;
|
||||||
|
wakeup_stopped.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Test() { log("\nTEST ", id, " finished\n"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool test_loop(Timer::Session *timer, Alarm::Time timeout1, Alarm::Time timeout2, int loops)
|
struct Main
|
||||||
{
|
{
|
||||||
Timed_semaphore sem;
|
Constructible<Test> test;
|
||||||
Wakeup_thread thread(&sem, timer, timeout2);
|
|
||||||
bool ret = true;
|
|
||||||
|
|
||||||
thread.start();
|
Main(Env &env)
|
||||||
try{
|
|
||||||
for (int i = 0; i < loops; i++)
|
|
||||||
sem.down(timeout1);
|
|
||||||
} catch (Timeout_exception) {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Explicitly stop the thread, so the destructor does not get called in
|
|
||||||
* unfavourable situations, e.g. where the semaphore-meta lock is still
|
|
||||||
* held and the semaphore destructor stalls afterwards
|
|
||||||
*/
|
|
||||||
thread.stop();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int, char **)
|
|
||||||
{
|
{
|
||||||
log("--- timed-semaphore test ---");
|
log("--- Timed semaphore test ---");
|
||||||
|
test.construct(env, false, 1, "without timeouts"); test.destruct();
|
||||||
Timer::Connection timer;
|
test.construct(env, true, 2, "with timeouts"); test.destruct();
|
||||||
|
log("--- Timed semaphore test finished ---");
|
||||||
log("--- test 1: good case, no timeout triggers --");
|
|
||||||
if(!test_loop(&timer, 1000, 100, 10)) {
|
|
||||||
error("Test 1 failed!");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
log("--- everything went ok --");
|
};
|
||||||
|
|
||||||
log("--- test 2: triggers timeouts --");
|
|
||||||
if(test_loop(&timer, 100, 1000, 10)) {
|
|
||||||
error("Test 2 failed!");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
log("--- everything went ok --");
|
|
||||||
|
|
||||||
log("--- end of timed-semaphore test ---");
|
void Component::construct(Genode::Env &env) { static Main main(env); }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
* \brief Low-level test for TRACE service
|
* \brief Low-level test for TRACE service
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
* \author Josef Soentgen
|
* \author Josef Soentgen
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2013-08-12
|
* \date 2013-08-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Genode Labs GmbH
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
@ -15,56 +16,42 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <trace_session/connection.h>
|
#include <trace_session/connection.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <os/config.h>
|
#include <base/attached_rom_dataspace.h>
|
||||||
#include <base/sleep.h>
|
#include <base/component.h>
|
||||||
|
#include <base/heap.h>
|
||||||
|
|
||||||
static char const *state_name(Genode::Trace::Subject_info::State state)
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
struct Test_thread : Thread
|
||||||
{
|
{
|
||||||
switch (state) {
|
Env &env;
|
||||||
case Genode::Trace::Subject_info::INVALID: return "INVALID";
|
Timer::Connection timer { env };
|
||||||
case Genode::Trace::Subject_info::UNTRACED: return "UNTRACED";
|
|
||||||
case Genode::Trace::Subject_info::TRACED: return "TRACED";
|
|
||||||
case Genode::Trace::Subject_info::FOREIGN: return "FOREIGN";
|
|
||||||
case Genode::Trace::Subject_info::ERROR: return "ERROR";
|
|
||||||
case Genode::Trace::Subject_info::DEAD: return "DEAD";
|
|
||||||
}
|
|
||||||
return "undefined";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct Test_thread : Genode::Thread_deprecated<1024 * sizeof (unsigned long)>
|
|
||||||
{
|
|
||||||
Timer::Connection _timer;
|
|
||||||
|
|
||||||
void entry()
|
void entry()
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
for (unsigned i = 0; ; i++) {
|
||||||
|
|
||||||
for (size_t i = 0; ; i++) {
|
|
||||||
if (i & 0x3) {
|
if (i & 0x3) {
|
||||||
Ram_dataspace_capability ds_cap = env()->ram_session()->alloc(1024);
|
Ram_dataspace_capability ds_cap = env.ram().alloc(1024);
|
||||||
env()->ram_session()->free(ds_cap);
|
env.ram().free(ds_cap);
|
||||||
}
|
}
|
||||||
|
timer.msleep(250);
|
||||||
_timer.msleep(250);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Test_thread(const char *name)
|
Test_thread(Env &env, Name &name)
|
||||||
: Thread_deprecated(name) { start(); }
|
: Thread(env, name, 1024 * sizeof(addr_t)), env(env) { start(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
|
|
||||||
class Trace_buffer_monitor
|
class Trace_buffer_monitor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum { MAX_ENTRY_BUF = 256 };
|
enum { MAX_ENTRY_BUF = 256 };
|
||||||
char _buf[MAX_ENTRY_BUF];
|
|
||||||
|
|
||||||
|
char _buf[MAX_ENTRY_BUF];
|
||||||
|
Region_map &_rm;
|
||||||
Trace::Subject_id _id;
|
Trace::Subject_id _id;
|
||||||
Trace::Buffer *_buffer;
|
Trace::Buffer *_buffer;
|
||||||
Trace::Buffer::Entry _curr_entry;
|
Trace::Buffer::Entry _curr_entry;
|
||||||
@ -74,16 +61,16 @@ class Trace_buffer_monitor
|
|||||||
size_t len = min(entry.length() + 1, MAX_ENTRY_BUF);
|
size_t len = min(entry.length() + 1, MAX_ENTRY_BUF);
|
||||||
memcpy(_buf, entry.data(), len);
|
memcpy(_buf, entry.data(), len);
|
||||||
_buf[len-1] = '\0';
|
_buf[len-1] = '\0';
|
||||||
|
|
||||||
return _buf;
|
return _buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Trace_buffer_monitor(Trace::Subject_id id, Dataspace_capability ds_cap)
|
Trace_buffer_monitor(Region_map &rm,
|
||||||
|
Trace::Subject_id id,
|
||||||
|
Dataspace_capability ds_cap)
|
||||||
:
|
:
|
||||||
_id(id),
|
_rm(rm), _id(id), _buffer(rm.attach(ds_cap)),
|
||||||
_buffer(env()->rm_session()->attach(ds_cap)),
|
|
||||||
_curr_entry(_buffer->first())
|
_curr_entry(_buffer->first())
|
||||||
{
|
{
|
||||||
log("monitor subject:", _id.id, " buffer:", Hex((addr_t)_buffer));
|
log("monitor subject:", _id.id, " buffer:", Hex((addr_t)_buffer));
|
||||||
@ -92,7 +79,7 @@ class Trace_buffer_monitor
|
|||||||
~Trace_buffer_monitor()
|
~Trace_buffer_monitor()
|
||||||
{
|
{
|
||||||
if (_buffer)
|
if (_buffer)
|
||||||
env()->rm_session()->detach(_buffer);
|
_rm.detach(_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace::Subject_id id() { return _id; };
|
Trace::Subject_id id() { return _id; };
|
||||||
@ -100,7 +87,6 @@ class Trace_buffer_monitor
|
|||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
log("overflows: ", _buffer->wrapped());
|
log("overflows: ", _buffer->wrapped());
|
||||||
|
|
||||||
log("read all remaining events");
|
log("read all remaining events");
|
||||||
for (; !_curr_entry.last(); _curr_entry = _buffer->next(_curr_entry)) {
|
for (; !_curr_entry.last(); _curr_entry = _buffer->next(_curr_entry)) {
|
||||||
/* omit empty entries */
|
/* omit empty entries */
|
||||||
@ -111,14 +97,17 @@ class Trace_buffer_monitor
|
|||||||
if (data)
|
if (data)
|
||||||
log(data);
|
log(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset after we read all available entries */
|
/* reset after we read all available entries */
|
||||||
_curr_entry = _buffer->first();
|
_curr_entry = _buffer->first();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void test_out_of_metadata()
|
struct Test_out_of_metadata
|
||||||
|
{
|
||||||
|
Env &env;
|
||||||
|
|
||||||
|
Test_out_of_metadata(Env &env) : env(env)
|
||||||
{
|
{
|
||||||
log("test Out_of_metadata exception of Trace::Session::subjects call");
|
log("test Out_of_metadata exception of Trace::Session::subjects call");
|
||||||
|
|
||||||
@ -132,20 +121,21 @@ static void test_out_of_metadata()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum { MAX_SUBJECT_IDS = 16 };
|
enum { MAX_SUBJECT_IDS = 16 };
|
||||||
Genode::Trace::Subject_id subject_ids[MAX_SUBJECT_IDS];
|
Trace::Subject_id subject_ids[MAX_SUBJECT_IDS];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Genode::Trace::Connection trace(sizeof(subject_ids) + 4096, sizeof(subject_ids), 0);
|
Trace::Connection trace(env, sizeof(subject_ids) + 4096,
|
||||||
|
sizeof(subject_ids), 0);
|
||||||
|
|
||||||
/* we should never arrive here */
|
/* we should never arrive here */
|
||||||
struct Unexpectedly_got_no_exception{};
|
struct Unexpectedly_got_no_exception{};
|
||||||
throw Unexpectedly_got_no_exception();
|
throw Unexpectedly_got_no_exception();
|
||||||
} catch (Genode::Parent::Service_denied) {
|
} catch (Parent::Service_denied) {
|
||||||
log("got Genode::Parent::Service_denied exception as expected");
|
log("got Parent::Service_denied exception as expected"); }
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Genode::Trace::Connection trace(sizeof(subject_ids) + 5*4096, sizeof(subject_ids), 0);
|
Trace::Connection trace(env, sizeof(subject_ids) + 5*4096,
|
||||||
|
sizeof(subject_ids), 0);
|
||||||
trace.subjects(subject_ids, MAX_SUBJECT_IDS);
|
trace.subjects(subject_ids, MAX_SUBJECT_IDS);
|
||||||
|
|
||||||
/* we should never arrive here */
|
/* we should never arrive here */
|
||||||
@ -153,44 +143,52 @@ static void test_out_of_metadata()
|
|||||||
throw Unexpectedly_got_no_exception();
|
throw Unexpectedly_got_no_exception();
|
||||||
|
|
||||||
} catch (Trace::Out_of_metadata) {
|
} catch (Trace::Out_of_metadata) {
|
||||||
log("got Trace::Out_of_metadata exception as expected");
|
log("got Trace::Out_of_metadata exception as expected"); }
|
||||||
}
|
|
||||||
|
|
||||||
log("passed Out_of_metadata test");
|
log("passed Out_of_metadata test");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
struct Test_tracing
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
Env &env;
|
||||||
|
Attached_rom_dataspace config { env, "config" };
|
||||||
log("--- test-trace started ---");
|
Heap heap { env.ram(), env.rm() };
|
||||||
|
Trace::Connection trace { env, 1024*1024, 64*1024, 0 };
|
||||||
test_out_of_metadata();
|
Timer::Connection timer { env };
|
||||||
|
Test_thread::Name thread_name { "test-thread" };
|
||||||
static Genode::Trace::Connection trace(1024*1024, 64*1024, 0);
|
Test_thread thread { env, thread_name };
|
||||||
|
Trace_buffer_monitor *test_monitor { nullptr };
|
||||||
static Timer::Connection timer;
|
bool policy_set { false };
|
||||||
|
Trace::Policy_id policy_id;
|
||||||
static Test_thread test("test-thread");
|
|
||||||
|
|
||||||
static Trace_buffer_monitor *test_monitor = 0;
|
|
||||||
|
|
||||||
Genode::Trace::Policy_id policy_id;
|
|
||||||
bool policy_set = false;
|
|
||||||
|
|
||||||
char policy_label[64];
|
char policy_label[64];
|
||||||
char policy_module[64];
|
char policy_module[64];
|
||||||
Rom_dataspace_capability policy_module_rom_ds;
|
Rom_dataspace_capability policy_module_rom_ds;
|
||||||
|
|
||||||
|
char const *state_name(Trace::Subject_info::State state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case Trace::Subject_info::INVALID: return "INVALID";
|
||||||
|
case Trace::Subject_info::UNTRACED: return "UNTRACED";
|
||||||
|
case Trace::Subject_info::TRACED: return "TRACED";
|
||||||
|
case Trace::Subject_info::FOREIGN: return "FOREIGN";
|
||||||
|
case Trace::Subject_info::ERROR: return "ERROR";
|
||||||
|
case Trace::Subject_info::DEAD: return "DEAD";
|
||||||
|
}
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
|
Test_tracing(Env &env) : env(env)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
Xml_node policy = config()->xml_node().sub_node("trace_policy");
|
Xml_node policy = config.xml().sub_node("trace_policy");
|
||||||
for (;; policy = policy.next("trace_policy")) {
|
for (;; policy = policy.next("trace_policy")) {
|
||||||
try {
|
try {
|
||||||
policy.attribute("label").value(policy_label, sizeof (policy_label));
|
policy.attribute("label").value(policy_label, sizeof (policy_label));
|
||||||
policy.attribute("module").value(policy_module, sizeof (policy_module));
|
policy.attribute("module").value(policy_module, sizeof (policy_module));
|
||||||
|
|
||||||
static Rom_connection policy_rom(policy_module);
|
Rom_connection policy_rom(env, policy_module);
|
||||||
policy_module_rom_ds = policy_rom.dataspace();
|
policy_module_rom_ds = policy_rom.dataspace();
|
||||||
|
|
||||||
size_t rom_size = Dataspace_client(policy_module_rom_ds).size();
|
size_t rom_size = Dataspace_client(policy_module_rom_ds).size();
|
||||||
@ -199,12 +197,12 @@ int main(int argc, char **argv)
|
|||||||
Dataspace_capability ds_cap = trace.policy(policy_id);
|
Dataspace_capability ds_cap = trace.policy(policy_id);
|
||||||
|
|
||||||
if (ds_cap.valid()) {
|
if (ds_cap.valid()) {
|
||||||
void *ram = env()->rm_session()->attach(ds_cap);
|
void *ram = env.rm().attach(ds_cap);
|
||||||
void *rom = env()->rm_session()->attach(policy_module_rom_ds);
|
void *rom = env.rm().attach(policy_module_rom_ds);
|
||||||
memcpy(ram, rom, rom_size);
|
memcpy(ram, rom, rom_size);
|
||||||
|
|
||||||
env()->rm_session()->detach(ram);
|
env.rm().detach(ram);
|
||||||
env()->rm_session()->detach(rom);
|
env.rm().detach(rom);
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
error("could not load module '", Cstring(policy_module), "' for "
|
error("could not load module '", Cstring(policy_module), "' for "
|
||||||
@ -250,7 +248,8 @@ int main(int argc, char **argv)
|
|||||||
trace.trace(subjects[i].id, policy_id, 16384U);
|
trace.trace(subjects[i].id, policy_id, 16384U);
|
||||||
|
|
||||||
Dataspace_capability ds_cap = trace.buffer(subjects[i].id);
|
Dataspace_capability ds_cap = trace.buffer(subjects[i].id);
|
||||||
test_monitor = new (env()->heap()) Trace_buffer_monitor(subjects[i].id, ds_cap);
|
test_monitor = new (heap)
|
||||||
|
Trace_buffer_monitor(env.rm(), subjects[i].id, ds_cap);
|
||||||
|
|
||||||
} catch (Trace::Source_is_dead) { error("source is dead"); }
|
} catch (Trace::Source_is_dead) { error("source is dead"); }
|
||||||
|
|
||||||
@ -266,8 +265,25 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (test_monitor)
|
if (test_monitor)
|
||||||
destroy(env()->heap(), test_monitor);
|
destroy(heap, test_monitor);
|
||||||
|
|
||||||
log("--- test-trace finished ---");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Main
|
||||||
|
{
|
||||||
|
Constructible<Test_out_of_metadata> test_1;
|
||||||
|
Constructible<Test_tracing> test_2;
|
||||||
|
|
||||||
|
Main(Env &env)
|
||||||
|
{
|
||||||
|
log("--- test-trace started ---");
|
||||||
|
test_1.construct(env);
|
||||||
|
test_1.destruct();
|
||||||
|
test_2.construct(env);
|
||||||
|
test_2.destruct();
|
||||||
|
log("--- test-trace finished ---");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -5,35 +5,37 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/snprintf.h>
|
#include <base/snprintf.h>
|
||||||
#include <base/log.h>
|
#include <base/component.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <uart_session/connection.h>
|
#include <uart_session/connection.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
int main()
|
|
||||||
|
struct Main
|
||||||
|
{
|
||||||
|
Timer::Connection timer;
|
||||||
|
Uart::Connection uart;
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
Main(Env &env)
|
||||||
{
|
{
|
||||||
log("--- UART test started ---");
|
log("--- UART test started ---");
|
||||||
|
|
||||||
static Timer::Connection timer;
|
|
||||||
static Uart::Connection uart;
|
|
||||||
|
|
||||||
for (unsigned i = 0; ; ++i) {
|
for (unsigned i = 0; ; ++i) {
|
||||||
|
|
||||||
static char buf[100];
|
|
||||||
int n = snprintf(buf, sizeof(buf), "UART test message %d\n", i);
|
int n = snprintf(buf, sizeof(buf), "UART test message %d\n", i);
|
||||||
uart.write(buf, n);
|
uart.write(buf, n);
|
||||||
|
|
||||||
timer.msleep(2000);
|
timer.msleep(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
|
@ -477,7 +477,7 @@ void Component::construct(Genode::Env &env)
|
|||||||
MAX_DEPTH = config_xml.attribute_value("depth", 16U);
|
MAX_DEPTH = config_xml.attribute_value("depth", 16U);
|
||||||
|
|
||||||
unsigned long elapsed_ms;
|
unsigned long elapsed_ms;
|
||||||
Timer::Connection timer;
|
Timer::Connection timer(env);
|
||||||
|
|
||||||
/* populate the directory file system at / */
|
/* populate the directory file system at / */
|
||||||
vfs_root.num_dirent("/");
|
vfs_root.num_dirent("/");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user