f45cf49405
fix #1126
115 lines
2.3 KiB
C++
115 lines
2.3 KiB
C++
/*
|
|
* \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;
|
|
}
|