base: test for the pseudo-parallel use of an FPU

fix #1126
This commit is contained in:
Martin Stein 2014-04-29 17:19:08 +02:00 committed by Norman Feske
parent 4b7d58fccc
commit f45cf49405
3 changed files with 188 additions and 0 deletions

60
repos/base/run/fpu.run Normal file
View File

@ -0,0 +1,60 @@
#
# Build
#
build "core init test/fpu"
#
# Boot image
#
create_boot_directory
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="CPU"/>
<service name="RM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<start name="test">
<binary name="test-fpu"/>
<resource name="RAM" quantum="10M"/>
</start>
</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
}

View File

@ -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 <base/thread.h>
#include <base/sleep.h>
#include <base/printf.h>
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;
}

View File

@ -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