mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
parent
2acfacb639
commit
d186e4361e
@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
* Copyright (C) 2013-2020 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 Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <base/rpc_client.h>
|
#include <base/rpc_client.h>
|
||||||
|
#include <trace/timestamp.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
@ -323,6 +324,188 @@ namespace Tlb_shootdown_test {
|
|||||||
log("TLB: --- test finished ---");
|
log("TLB: --- test finished ---");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Tsc_test {
|
||||||
|
|
||||||
|
struct Tsc_thread : Genode::Thread
|
||||||
|
{
|
||||||
|
enum { STACK_SIZE = 4 * 4096 };
|
||||||
|
|
||||||
|
Genode::Affinity::Location const location;
|
||||||
|
Genode::Blockade barrier { };
|
||||||
|
Genode::uint64_t volatile cnt { 0 };
|
||||||
|
Genode::uint64_t volatile tsc_value { 0 };
|
||||||
|
Genode::uint64_t last_cnt { 0 };
|
||||||
|
Genode::uint64_t last_tsc { 0 };
|
||||||
|
Genode::uint64_t diff { 0 };
|
||||||
|
bool volatile loop { true };
|
||||||
|
bool volatile spin { true };
|
||||||
|
|
||||||
|
void entry() override
|
||||||
|
{
|
||||||
|
last_tsc = Genode::Trace::timestamp();
|
||||||
|
|
||||||
|
Genode::log(this, " ", Genode::Hex(last_tsc));
|
||||||
|
barrier.wakeup();
|
||||||
|
|
||||||
|
while (loop) {
|
||||||
|
while (spin && loop) cnt++;
|
||||||
|
|
||||||
|
measure();
|
||||||
|
spin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure() { tsc_value = Genode::Trace::timestamp(); }
|
||||||
|
|
||||||
|
Tsc_thread(Genode::Env &env, Location location)
|
||||||
|
: Genode::Thread(env, Name("tsc_thread"), STACK_SIZE, location,
|
||||||
|
Weight(), env.cpu()), location(location)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int T>
|
||||||
|
Genode::String<T> _align_right(Genode::String<T> const &s)
|
||||||
|
{
|
||||||
|
Genode::String<T> result = s;
|
||||||
|
|
||||||
|
for (Genode::uint64_t i = s.length(); i < T; i++)
|
||||||
|
result = Genode::String<T>(" ", result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int T>
|
||||||
|
Genode::String<T> _align_right(Genode::uint64_t const value)
|
||||||
|
{
|
||||||
|
Genode::String<T> result("",Genode::Hex(value));
|
||||||
|
|
||||||
|
Genode::uint64_t pow = 16;
|
||||||
|
|
||||||
|
for (Genode::uint64_t i = 3; i < (T - 1); i++, pow *= 16) {
|
||||||
|
if (value < pow) {
|
||||||
|
result = Genode::String<T>(" ", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > pow) {
|
||||||
|
result = Genode::String<T>("?");
|
||||||
|
for (Genode::uint64_t i = 1; i < (T - 1); i++)
|
||||||
|
result = Genode::String<T>(" ", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(Genode::Env &env, Genode::Heap &heap,
|
||||||
|
Genode::Affinity::Space &cpus)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
log("TSC: --- test started ---");
|
||||||
|
|
||||||
|
/* get some memory for the thread objects */
|
||||||
|
Tsc_thread ** threads = new (heap) Tsc_thread*[cpus.total()];
|
||||||
|
|
||||||
|
/* construct the thread objects */
|
||||||
|
for (unsigned i = 0; i < cpus.total(); i++) {
|
||||||
|
threads[i] = new (heap) Tsc_thread(env, cpus.location_of_index(i));
|
||||||
|
/* skip first thread, current thread will do the measurement */
|
||||||
|
if (i) threads[i]->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait until all threads are up and running */
|
||||||
|
for (unsigned i = 1; i < cpus.total(); i++) threads[i]->barrier.block();
|
||||||
|
|
||||||
|
{
|
||||||
|
String<128> legend(" ");
|
||||||
|
for (unsigned i = 0; i < cpus.total(); i++) {
|
||||||
|
legend = String<128>(legend, _align_right<15>(String<128>("cpu (", threads[i]->affinity(),")")));
|
||||||
|
}
|
||||||
|
legend = String<128>(legend, _align_right<13>("diff-min"));
|
||||||
|
legend = String<128>(legend, _align_right<13>("diff-max"));
|
||||||
|
log(legend);
|
||||||
|
}
|
||||||
|
|
||||||
|
log("round / tsc per cpu");
|
||||||
|
|
||||||
|
/* we handle the first cpu */
|
||||||
|
threads[0]->measure();
|
||||||
|
threads[0]->last_tsc = threads[0]->tsc_value;
|
||||||
|
|
||||||
|
/* make some rounds */
|
||||||
|
for (unsigned round = 0; round < 20; round++) {
|
||||||
|
|
||||||
|
/* stop spinning */
|
||||||
|
for (unsigned i = 1; i < cpus.total(); i++)
|
||||||
|
threads[i]->spin = false;
|
||||||
|
|
||||||
|
/* wait for valid results */
|
||||||
|
for (unsigned i = 1; i < cpus.total(); i++)
|
||||||
|
while (!threads[i]->spin) { };
|
||||||
|
|
||||||
|
/* do measure for cpu 0 */
|
||||||
|
threads[0]->measure();
|
||||||
|
|
||||||
|
/* calculate results */
|
||||||
|
String<128> show;
|
||||||
|
String<128> show_diff;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < cpus.total(); i++) {
|
||||||
|
uint64_t diff = threads[i]->tsc_value - threads[i]->last_tsc;
|
||||||
|
if (round) {
|
||||||
|
bool plus = diff > threads[i]->diff;
|
||||||
|
show_diff = String<128>(show_diff, " ", plus ? "+" : "-",
|
||||||
|
_align_right<13>(plus ?
|
||||||
|
(diff - threads[i]->diff) :
|
||||||
|
(threads[i]->diff - diff)));
|
||||||
|
}
|
||||||
|
|
||||||
|
threads[i]->diff = diff;
|
||||||
|
threads[i]->last_cnt = threads[i]->cnt;
|
||||||
|
threads[i]->last_tsc = threads[i]->tsc_value;
|
||||||
|
|
||||||
|
show = String<128>(show, " ", _align_right<14>(threads[i]->diff));
|
||||||
|
|
||||||
|
}
|
||||||
|
uint64_t min_diff = ~0ULL;
|
||||||
|
uint64_t max_diff = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < cpus.total(); i++) {
|
||||||
|
for (unsigned j = 0; j < cpus.total(); j++) {
|
||||||
|
if (i == j) continue;
|
||||||
|
|
||||||
|
uint64_t diff = (threads[i]->diff > threads[j]->diff) ?
|
||||||
|
(threads[i]->diff - threads[j]->diff) :
|
||||||
|
(threads[j]->diff - threads[i]->diff);
|
||||||
|
|
||||||
|
if (diff < min_diff) min_diff = diff;
|
||||||
|
if (diff > max_diff) max_diff = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show result */
|
||||||
|
if (round)
|
||||||
|
log(" ", show_diff); /* diff to prev column */
|
||||||
|
log(round, round < 10 ? " " : " ", show,
|
||||||
|
" ", _align_right<12>(min_diff),
|
||||||
|
" ", _align_right<12>(max_diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break loop and stop spinning */
|
||||||
|
for (unsigned i = 1; i < cpus.total(); i++) threads[i]->loop = false;
|
||||||
|
|
||||||
|
/* join finished worker threads */
|
||||||
|
for (unsigned i = 1; i < cpus.total(); i++) threads[i]->join();
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
for (unsigned i = 0; i < cpus.total(); i++) destroy(heap, threads[i]);
|
||||||
|
destroy(heap, threads);
|
||||||
|
|
||||||
|
log("TSC: --- test finished ---");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Component::construct(Genode::Env & env)
|
void Component::construct(Genode::Env & env)
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
@ -335,6 +518,7 @@ void Component::construct(Genode::Env & env)
|
|||||||
|
|
||||||
Heap heap(env.ram(), env.rm());
|
Heap heap(env.ram(), env.rm());
|
||||||
|
|
||||||
|
Tsc_test::execute(env, heap, cpus);
|
||||||
Mp_server_test::execute(env, heap, cpus);
|
Mp_server_test::execute(env, heap, cpus);
|
||||||
Affinity_test::execute(env, heap, cpus);
|
Affinity_test::execute(env, heap, cpus);
|
||||||
Tlb_shootdown_test::execute(env, heap, cpus);
|
Tlb_shootdown_test::execute(env, heap, cpus);
|
||||||
|
Loading…
Reference in New Issue
Block a user