From 2e58428b51b854a3ddae2196158fc968a09fc887 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 19 Jul 2013 15:46:24 +0200 Subject: [PATCH] run: Rpc_entrypoint test running on multiple CPUs Add run script to autopilot list Issue #814 --- base/run/mp_server.run | 78 +++++++++++++++++ base/src/test/mp_server/main.cc | 138 ++++++++++++++++++++++++++++++ base/src/test/mp_server/target.mk | 3 + tool/autopilot.list | 1 + 4 files changed, 220 insertions(+) create mode 100644 base/run/mp_server.run create mode 100644 base/src/test/mp_server/main.cc create mode 100644 base/src/test/mp_server/target.mk diff --git a/base/run/mp_server.run b/base/run/mp_server.run new file mode 100644 index 000000000..6d4816bae --- /dev/null +++ b/base/run/mp_server.run @@ -0,0 +1,78 @@ +# +# \brief Test to start and call RPC entrypoint on all available CPUs +# \author Norman Feske +# \author Alexander Boettcher +# + +if {![have_spec nova] && ![have_spec foc]} { + puts "Platform is unsupported." + exit 0 +} + +build "core init test/mp_server" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + +} + +build_boot_image "core init test-server-mp" + +if {[is_qemu_available]} { + set want_cpus 2 + append qemu_args " -nographic -m 64 -smp $want_cpus,cores=$want_cpus " +} + +# run the test +run_genode_until {\[init -\> test-server-mp\] done.*\n} 20 + +set cpus [regexp -inline {Detected [0-9]+ CPU[ s].*\n} $output] +set cpus [regexp -inline {[0-9]+} $cpus] + +if {[is_qemu_available]} { + if {$want_cpus != $cpus} { + puts "CPU count is not as expected: $want_cpus != $cpus" + exit 1; + } +} + +# pay only attention to the output of init and its children +grep_output {^\[init } + +unify_output {transfer cap [a-f0-9]+} "transfer cap UNIFIED" +unify_output {yes - idx [a-f0-9]+} "yes - idx UNIFIED" +unify_output {\- received cap [a-f0-9]+} "- received cap UNIFIED" + +compare_output_to { + [init -> test-server-mp] --- test-mp_server started --- + [init -> test-server-mp] Detected 2 CPUs. + [init -> test-server-mp] call server on CPU 0 + [init -> test-server-mp] function test_untyped: got value 0 + [init -> test-server-mp] call server on CPU 1 + [init -> test-server-mp] function test_untyped: got value 1 + [init -> test-server-mp] call server on CPU 0 - transfer cap UNIFIED + [init -> test-server-mp] function test_cap: capability is valid ? yes - idx UNIFIED + [init -> test-server-mp] call server on CPU 1 - transfer cap UNIFIED + [init -> test-server-mp] function test_cap: capability is valid ? yes - idx UNIFIED + [init -> test-server-mp] call server on CPU 0 - transfer cap UNIFIED + [init -> test-server-mp] function test_cap_reply: capability is valid ? yes - idx UNIFIED + [init -> test-server-mp] got from server on CPU 0 - received cap UNIFIED + [init -> test-server-mp] call server on CPU 1 - transfer cap UNIFIED + [init -> test-server-mp] function test_cap_reply: capability is valid ? yes - idx UNIFIED + [init -> test-server-mp] got from server on CPU 1 - received cap UNIFIED + [init -> test-server-mp] done +} diff --git a/base/src/test/mp_server/main.cc b/base/src/test/mp_server/main.cc new file mode 100644 index 000000000..2fbfa8a95 --- /dev/null +++ b/base/src/test/mp_server/main.cc @@ -0,0 +1,138 @@ +/* + * \brief Multiprocessor test for a server having multiple Rpc_entrypoints on + * different CPUs + * \author Alexander Boettcher + * \date 2013-07-19 + */ + +/* + * Copyright (C) 2013 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 +#include + +#include +#include + +namespace Test { + + /** + * Test session interface definition + */ + struct Session : Genode::Session + { + static const char *service_name() { return "MP_RPC_TEST"; } + + GENODE_RPC(Rpc_test_untyped, void, test_untyped, unsigned); + GENODE_RPC(Rpc_test_cap, void, test_cap, Genode::Native_capability); + GENODE_RPC(Rpc_test_cap_reply, Genode::Native_capability, + test_cap_reply, Genode::Native_capability); + GENODE_RPC_INTERFACE(Rpc_test_untyped, Rpc_test_cap, Rpc_test_cap_reply); + }; + + struct Client : Genode::Rpc_client + { + Client(Capability cap) : Rpc_client(cap) { } + + void test_untyped(unsigned value) { call(value); } + void test_cap(Genode::Native_capability cap) { call(cap); } + Genode::Native_capability test_cap_reply(Genode::Native_capability cap) { + return call(cap); } + }; + + struct Component : Genode::Rpc_object + { + /* Test to just sent plain words (untyped items) */ + void test_untyped(unsigned); + /* Test to transfer a object capability during send */ + void test_cap(Genode::Native_capability); + /* Test to transfer a object capability during send+reply */ + Genode::Native_capability test_cap_reply(Genode::Native_capability); + }; + + typedef Genode::Capability Capability; + + /** + * Session implementation + */ + void Component::test_untyped(unsigned value) { + Genode::printf("function %s: got value %u\n", __FUNCTION__, value); + } + + void Component::test_cap(Genode::Native_capability cap) { + Genode::printf("function %s: capability is valid ? %s - idx %lx\n", + __FUNCTION__, cap.valid() ? "yes" : "no", + cap.local_name()); + } + + Genode::Native_capability Component::test_cap_reply(Genode::Native_capability cap) { + Genode::printf("function %s: capability is valid ? %s - idx %lx\n", + __FUNCTION__, cap.valid() ? "yes" : "no", + cap.local_name()); + return cap; + } +} + +/** + * Set up a server running on every CPU one Rpc_entrypoint + */ +int main(int argc, char **argv) +{ + using namespace Genode; + + printf("--- test-mp_server started ---\n"); + + unsigned cpus = env()->cpu_session()->num_cpus(); + printf("Detected %u CPU%c.\n", cpus, cpus > 1 ? 's' : ' '); + + enum { STACK_SIZE = 4096 }; + + static Cap_connection cap; + Rpc_entrypoint ** eps = new (env()->heap()) Rpc_entrypoint*[cpus]; + for (unsigned i = 0; i < cpus; i++) + eps[i] = new (env()->heap()) Rpc_entrypoint(&cap, STACK_SIZE, "rpc en", + true, i); + + /* XXX using the same object and putting it to different queues fails XXX */ + Test::Component * components = new (env()->heap()) Test::Component[cpus]; + + Test::Capability * caps = new (env()->heap()) Test::Capability[cpus]; + for (unsigned i = 0; i < cpus; i++) + caps[i] = eps[i]->manage(&components[i]); + + Test::Client ** clients = new (env()->heap()) Test::Client*[cpus]; + for (unsigned i = 0; i < cpus; i++) + clients[i] = new (env()->heap()) Test::Client(caps[i]); + + /* Test: Invoke RPC entrypoint on different CPUs */ + for (unsigned i = 0; i < cpus; i++) { + printf("call server on CPU %u\n", i); + clients[i]->test_untyped(i); + } + + /* Test: Transfer a capability to RPC Entrypoints on different CPUs */ + for (unsigned i = 0; i < cpus; i++) { + Native_capability cap = caps[0]; + printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name()); + clients[i]->test_cap(cap); + } + + /* Test: Transfer a capability to RPC Entrypoints and back */ + for (unsigned i = 0; i < cpus; i++) { + Native_capability cap = caps[0]; + printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name()); + Native_capability rcap = clients[i]->test_cap_reply(cap); + printf("got from server on CPU %u - received cap %lx\n", i, rcap.local_name()); + } + + printf("done\n"); + + sleep_forever(); +} diff --git a/base/src/test/mp_server/target.mk b/base/src/test/mp_server/target.mk new file mode 100644 index 000000000..6661ff450 --- /dev/null +++ b/base/src/test/mp_server/target.mk @@ -0,0 +1,3 @@ +TARGET = test-server-mp +SRC_CC = main.cc +LIBS = base diff --git a/tool/autopilot.list b/tool/autopilot.list index b0e0b38ca..22943b6a9 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -26,3 +26,4 @@ l4linux_netperf_usb30 l4linux_netperf_bridge noux_tool_chain_auto affinity +mp_server