diff --git a/repos/base/run/fpu.run b/repos/base/run/fpu.run new file mode 100644 index 000000000..6ad69d871 --- /dev/null +++ b/repos/base/run/fpu.run @@ -0,0 +1,60 @@ +# +# Build +# + +build "core init test/fpu" + +# +# Boot image +# + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init test-fpu" + +# +# Execution +# + +append qemu_args "-nographic -m 64" + +run_genode_until "test done.*\n" 60 + +grep_output {^\[init -\> test\]} + +compare_output_to { + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] FPU user started + [init -> test] test done +} + diff --git a/repos/base/src/test/fpu/main.cc b/repos/base/src/test/fpu/main.cc new file mode 100644 index 000000000..528b9e500 --- /dev/null +++ b/repos/base/src/test/fpu/main.cc @@ -0,0 +1,114 @@ +/* + * \brief Test pseudo-parallel use of FPU if available + * \author Martin Stein + * \date 2014-04-29 + */ + +/* + * Copyright (C) 2012-2014 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 */ +#include +#include +#include + +using namespace Genode; + +class Sync_signal_transmitter : public Signal_transmitter +{ + private: + + Lock _lock; + + public: + + Sync_signal_transmitter(Signal_context_capability context = Signal_context_capability()) + : + Signal_transmitter(context), + _lock(Lock::UNLOCKED) + { } + + void submit(unsigned cnt) + { + Lock::Guard guard(_lock); + Signal_transmitter::submit(cnt); + } +}; + +class Fpu_user : public Thread<4 * 1024> +{ + private: + + float _x; + Sync_signal_transmitter * _st; + + void _calc(float volatile & x, float volatile & y) + { + for (unsigned j = 0; j < 100; j++) { + x *= (y * 1.357); + x /= (y * 1.246); + } + } + + public: + + Fpu_user() : Thread("fpu_user"), _x(0), _st(0) { } + + void start(float const x, Sync_signal_transmitter * const st) + { + _x = x; + _st = st; + Thread::start(); + } + + void entry() + { + Genode::printf("FPU user started\n"); + bool submitted = false; + while (1) { + enum { TRIALS = 1000 }; + for (unsigned i = 0; i < TRIALS; i++) { + float volatile a = _x + (float)i * ((float)1 / TRIALS); + float volatile b = _x + (float)i * ((float)1 / TRIALS); + float volatile c = _x; + _calc(a, c); + _calc(b, c); + if (a != b) { + PERR("calculation error"); + _st->submit(1); + sleep_forever(); + } + } + if (!submitted) { + _st->submit(1); + submitted = true; + } + } + } +}; + +int main() +{ + /* create ack signal */ + Signal_context sc; + Signal_receiver sr; + Signal_context_capability const scc = sr.manage(&sc); + Sync_signal_transmitter st(scc); + + /* start pseudo-parallel FPU users */ + enum { FPU_USERS = 10 }; + Fpu_user fpu_users[FPU_USERS]; + for (unsigned i = 0; i < FPU_USERS; i++) { + float const x = (i + 1) * 1.234; + fpu_users[i].start(x, &st); + } + /* wait for an ack of every FPU user */ + for (unsigned i = 0; i < FPU_USERS;) { i += sr.wait_for_signal().num(); } + printf("test done\n"); + sleep_forever(); + return 0; +} diff --git a/repos/base/src/test/fpu/target.mk b/repos/base/src/test/fpu/target.mk new file mode 100644 index 000000000..754cf21f9 --- /dev/null +++ b/repos/base/src/test/fpu/target.mk @@ -0,0 +1,14 @@ +# +# \brief Test pseudo-parallel use of FPU if available +# \author Martin Stein +# \date 2012-04-25 +# + +# Set program name +TARGET = test-fpu + +# Add C++ sources +SRC_CC += main.cc + +# Add libraries +LIBS += base