mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
parent
90bea1499e
commit
e61f6cfd38
62
repos/base/run/migrate.run
Normal file
62
repos/base/run/migrate.run
Normal file
@ -0,0 +1,62 @@
|
||||
build "core init test/migrate timer"
|
||||
|
||||
if {![have_include "power_on/qemu"]} {
|
||||
puts "Run script is not supported on this platform"
|
||||
exit 0
|
||||
}
|
||||
if {[have_spec foc] && ([have_spec pbxa9] || [have_spec rpi3])} {
|
||||
# foc kernel does detect solely 1 CPU */
|
||||
puts "Run script is not supported on this platform"
|
||||
exit 0
|
||||
}
|
||||
if {![have_spec nova] && ![have_spec foc] && ![have_spec sel4]} {
|
||||
puts "Run script is not supported on this platform"
|
||||
exit 0
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
append config {
|
||||
<config prio_levels="2">
|
||||
<parent-provides>
|
||||
<service name="LOG"/>
|
||||
<service name="CPU"/>
|
||||
<service name="ROM"/>
|
||||
<service name="PD"/>
|
||||
<service name="IO_PORT"/> <!-- on some kernels for timer -->
|
||||
<service name="IRQ"/> <!-- on some kernels for timer -->
|
||||
<service name="TRACE"/> <!-- used by migration test -->
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<start name="timer" caps="100">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="test-migrate" caps="100">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<config />
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
build_boot_image "core ld.lib.so init test-migrate timer"
|
||||
|
||||
append qemu_args "-nographic "
|
||||
append qemu_args "-smp 4,cores=4,threads=1"
|
||||
|
||||
run_genode_until {.*test completed successfully.*\n} 70
|
||||
|
||||
grep_output {^\[init -> test-migrate\] \[ep\] thread 'migrate' migrated, .*}
|
||||
|
||||
compare_output_to {
|
||||
[init -> test-migrate] [ep] thread 'migrate' migrated, location=1x0
|
||||
[init -> test-migrate] [ep] thread 'migrate' migrated, location=2x0
|
||||
[init -> test-migrate] [ep] thread 'migrate' migrated, location=3x0
|
||||
[init -> test-migrate] [ep] thread 'migrate' migrated, location=0x0
|
||||
}
|
173
repos/base/src/test/migrate/main.cc
Normal file
173
repos/base/src/test/migrate/main.cc
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* \brief Testing thread migration
|
||||
* \author Alexander Boettcher
|
||||
* \date 2020-08-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <cpu_session/connection.h>
|
||||
#include <cpu_thread/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <trace_session/connection.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
enum { STACK_SIZE = 0x3000 };
|
||||
|
||||
/************************************************
|
||||
** Migrate thread over all available CPU test **
|
||||
************************************************/
|
||||
|
||||
struct Migrate_thread : Thread
|
||||
{
|
||||
Blockade blockade { };
|
||||
Env &env;
|
||||
|
||||
Migrate_thread(Env &env)
|
||||
: Thread(env, "migrate", STACK_SIZE), env(env)
|
||||
{ }
|
||||
|
||||
void entry() override
|
||||
{
|
||||
Cpu_thread_client thread_client(cap());
|
||||
|
||||
/* we are ready */
|
||||
blockade.wakeup();
|
||||
|
||||
while (true) {
|
||||
log("[migrate] going to sleep");
|
||||
|
||||
blockade.block();
|
||||
|
||||
log("[migrate] woke up - got migrated ?");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Migrate
|
||||
{
|
||||
Env &env;
|
||||
Timer::Connection timer { env };
|
||||
Migrate_thread thread { env };
|
||||
Trace::Connection trace { env, 15 * 4096 /* RAM quota */,
|
||||
11 * 4096 /* ARG_BUFFER RAM quota */,
|
||||
0 /* parent levels */ };
|
||||
|
||||
Signal_handler<Migrate> timer_handler { env.ep(), *this,
|
||||
&Migrate::check_traces };
|
||||
|
||||
Trace::Subject_id trace_id { };
|
||||
Affinity::Location location { };
|
||||
unsigned loc_same { 0 };
|
||||
unsigned loc_pos { 0 };
|
||||
|
||||
unsigned test_rounds { 0 };
|
||||
|
||||
enum State {
|
||||
LOOKUP_TRACE_ID, CHECK_AFFINITY, MIGRATE
|
||||
} state { LOOKUP_TRACE_ID };
|
||||
|
||||
Migrate(Env &env) : env(env)
|
||||
{
|
||||
Affinity::Space cpus = env.cpu().affinity_space();
|
||||
log("Detected ", cpus.width(), "x", cpus.height(), " CPU",
|
||||
cpus.total() > 1 ? "s." : ".");
|
||||
|
||||
timer.sigh(timer_handler);
|
||||
|
||||
thread.start();
|
||||
thread.blockade.block();
|
||||
|
||||
timer.trigger_periodic( 500 * 1000 /* us */);
|
||||
}
|
||||
|
||||
void check_traces()
|
||||
{
|
||||
switch (state) {
|
||||
case LOOKUP_TRACE_ID:
|
||||
{
|
||||
auto count = trace.for_each_subject_info([&](Trace::Subject_id const &id,
|
||||
Trace::Subject_info const &info)
|
||||
{
|
||||
if (info.thread_name() != "migrate")
|
||||
return;
|
||||
|
||||
trace_id = id;
|
||||
location = info.affinity();
|
||||
state = CHECK_AFFINITY;
|
||||
|
||||
log("[ep] thread '", info.thread_name(), "' started,",
|
||||
" location=", location.xpos(), "x", location.ypos());
|
||||
});
|
||||
|
||||
if (count.count == count.limit && state == LOOKUP_TRACE_ID) {
|
||||
error("trace argument buffer too small for the test");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHECK_AFFINITY:
|
||||
{
|
||||
Trace::Subject_info const info = trace.subject_info(trace_id);
|
||||
|
||||
loc_same ++;
|
||||
|
||||
if ((location.xpos() == info.affinity().xpos()) &&
|
||||
(location.ypos() == info.affinity().ypos()) &&
|
||||
(location.width() == info.affinity().width()) &&
|
||||
(location.height() == info.affinity().height()))
|
||||
{
|
||||
if (loc_same >= 1) {
|
||||
loc_same = 0;
|
||||
state = MIGRATE;
|
||||
}
|
||||
log ("[ep] .");
|
||||
break;
|
||||
}
|
||||
|
||||
loc_same = 0;
|
||||
location = info.affinity();
|
||||
|
||||
log("[ep] thread '", info.thread_name(), "' migrated,",
|
||||
" location=", location.xpos(), "x", location.ypos());
|
||||
|
||||
test_rounds ++;
|
||||
if (test_rounds == 4)
|
||||
log("--- test completed successfully ---");
|
||||
break;
|
||||
}
|
||||
case MIGRATE:
|
||||
state = CHECK_AFFINITY;
|
||||
|
||||
loc_pos ++;
|
||||
Affinity::Location const loc = env.cpu().affinity_space().location_of_index(loc_pos);
|
||||
|
||||
/* trigger migration */
|
||||
Cpu_thread_client client(thread.cap());
|
||||
client.affinity(loc);
|
||||
|
||||
log("[ep] thread 'migrate' scheduled to migrate to location=",
|
||||
loc.xpos(), "x", loc.ypos());
|
||||
|
||||
thread.blockade.wakeup();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Env &env)
|
||||
{
|
||||
log("--- migrate thread test started ---");
|
||||
|
||||
static Migrate migrate_test(env);
|
||||
}
|
3
repos/base/src/test/migrate/target.mk
Normal file
3
repos/base/src/test/migrate/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = test-migrate
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
@ -22,6 +22,7 @@ lx_hybrid_ctors
|
||||
lx_hybrid_exception
|
||||
lx_hybrid_pthread_ipc
|
||||
microcode
|
||||
migrate
|
||||
moon
|
||||
netperf_lwip
|
||||
netperf_lwip_bridge
|
||||
|
Loading…
x
Reference in New Issue
Block a user