diff --git a/repos/base/recipes/pkg/test-entrypoint/README b/repos/base/recipes/pkg/test-entrypoint/README
new file mode 100644
index 000000000..484add3d2
--- /dev/null
+++ b/repos/base/recipes/pkg/test-entrypoint/README
@@ -0,0 +1 @@
+Scenario that tests Genode::Entrypoint functionality
diff --git a/repos/base/recipes/pkg/test-entrypoint/archives b/repos/base/recipes/pkg/test-entrypoint/archives
new file mode 100644
index 000000000..fb5223202
--- /dev/null
+++ b/repos/base/recipes/pkg/test-entrypoint/archives
@@ -0,0 +1,2 @@
+_/src/init
+_/src/test-entrypoint
diff --git a/repos/base/recipes/pkg/test-entrypoint/hash b/repos/base/recipes/pkg/test-entrypoint/hash
new file mode 100644
index 000000000..2f665538f
--- /dev/null
+++ b/repos/base/recipes/pkg/test-entrypoint/hash
@@ -0,0 +1 @@
+2020-03-21 c9ee8f61ce95fdfdb183ba48b73d66c05f24230e
diff --git a/repos/base/recipes/pkg/test-entrypoint/runtime b/repos/base/recipes/pkg/test-entrypoint/runtime
new file mode 100644
index 000000000..ec5da59e1
--- /dev/null
+++ b/repos/base/recipes/pkg/test-entrypoint/runtime
@@ -0,0 +1,28 @@
+
+
+
+
+ child "test-entrypoint" exited with exit value 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repos/base/recipes/src/test-entrypoint/content.mk b/repos/base/recipes/src/test-entrypoint/content.mk
new file mode 100644
index 000000000..c5bc3676d
--- /dev/null
+++ b/repos/base/recipes/src/test-entrypoint/content.mk
@@ -0,0 +1,2 @@
+SRC_DIR = src/test/entrypoint
+include $(GENODE_DIR)/repos/base/recipes/src/content.inc
diff --git a/repos/base/recipes/src/test-entrypoint/hash b/repos/base/recipes/src/test-entrypoint/hash
new file mode 100644
index 000000000..031e82e18
--- /dev/null
+++ b/repos/base/recipes/src/test-entrypoint/hash
@@ -0,0 +1 @@
+2020-03-21 3b4a05c0704d0259fb66ad1cea1166231a2f19dd
diff --git a/repos/base/recipes/src/test-entrypoint/used_apis b/repos/base/recipes/src/test-entrypoint/used_apis
new file mode 100644
index 000000000..df967b96a
--- /dev/null
+++ b/repos/base/recipes/src/test-entrypoint/used_apis
@@ -0,0 +1 @@
+base
diff --git a/repos/base/src/test/entrypoint/main.cc b/repos/base/src/test/entrypoint/main.cc
new file mode 100644
index 000000000..536c82ab4
--- /dev/null
+++ b/repos/base/src/test/entrypoint/main.cc
@@ -0,0 +1,167 @@
+/*
+ * \brief Entrypoint test
+ * \author Christian Helmuth
+ * \date 2020-03-20
+ */
+
+/*
+ * 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
+#include
+#include
+#include
+
+using namespace Genode;
+
+
+/**
+ * Test destruction of entrypoint with yet not dissolved components
+ */
+namespace Test_destruct {
+ struct Session;
+ struct Component;
+}
+
+struct Test_destruct::Session : Genode::Session
+{
+ static const char *service_name() { return "Test_destruct"; }
+
+ GENODE_RPC(Rpc_test_untyped, void, test_untyped, unsigned);
+ GENODE_RPC_INTERFACE(Rpc_test_untyped);
+};
+
+struct Test_destruct::Component : Genode::Rpc_object
+{
+ void test_untyped(unsigned) { }
+};
+
+
+/**
+ * Test signal handling with proxy and wait_and_dispatch_one_io_signal()
+ */
+namespace Test_signal {
+ struct Session;
+ struct Session_component;
+ struct Entrypoint;
+
+ enum { TIMER_DURATION = 10'000ul };
+}
+
+
+struct Test_signal::Session : Genode::Session
+{
+ static const char *service_name() { return "Test_signal"; }
+
+ GENODE_RPC(Rpc_rpc, void, rpc);
+ GENODE_RPC_INTERFACE(Rpc_rpc);
+};
+
+
+struct Test_signal::Session_component : Rpc_object
+{
+ Genode::Entrypoint &ep;
+
+ Session_component(Genode::Entrypoint &ep) : ep(ep) { }
+
+ void stats()
+ {
+ log("rpcs=", rpc_count, " signals=", sig_count, " timeout-signals=", sig_timeout_count);
+ }
+
+ unsigned rpc_count { 0 };
+ unsigned sig_count { 0 };
+ unsigned sig_timeout_count { 0 };
+
+ void rpc()
+ {
+ ++rpc_count;
+ ep.wait_and_dispatch_one_io_signal();
+ }
+
+ void sig() { ++sig_count; }
+ void sig_timeout() { ++sig_timeout_count; }
+};
+
+
+struct Test_signal::Entrypoint : Genode::Entrypoint
+{
+ Env &env;
+
+ Session_component sc { *this };
+
+ Capability cap { manage(sc) };
+
+ Io_signal_handler sigh {
+ *this, *this, &Test_signal::Entrypoint::handle_signal };
+
+ Timer::Connection timer { env };
+
+ Io_signal_handler timer_sigh {
+ *this, *this, &Test_signal::Entrypoint::handle_timer_signal };
+
+ Entrypoint(Env &env)
+ :
+ Genode::Entrypoint(env, 0x4000, "test_ep", Affinity::Location()),
+ env(env)
+ {
+ timer.sigh(timer_sigh);
+ timer.trigger_periodic(Test_signal::TIMER_DURATION/2);
+ }
+
+ void handle_signal() { sc.sig(); }
+ void handle_timer_signal() { sc.sig_timeout(); }
+};
+
+
+struct Main
+{
+ Env &env;
+
+ Test_signal::Entrypoint test_ep { env };
+
+ Timer::Connection timer { env };
+
+ Signal_handler sigh { env.ep(), *this, &Main::handle_signal };
+
+ unsigned rpc_count { 0 };
+
+ Main(Env &env) : env(env)
+ {
+ timer.sigh(sigh);
+ timer.trigger_periodic(Test_signal::TIMER_DURATION);
+ }
+
+ void handle_signal()
+ {
+ Signal_transmitter(test_ep.sigh).submit();
+ test_ep.cap.call();
+
+ if (++rpc_count % 100 == 0)
+ test_ep.sc.stats();
+ if (rpc_count == 3'000)
+ env.parent().exit(0);
+ }
+};
+
+
+void Component::construct(Env &env)
+{
+ /* test destruct */
+ Test_destruct::Component c;
+
+ {
+ Entrypoint ep(env, 0x4000, "test_destruct_ep", Affinity::Location());
+ ep.manage(c);
+ }
+
+ /* test signal */
+ static Main inst { env };
+}
diff --git a/repos/base/src/test/entrypoint/target.mk b/repos/base/src/test/entrypoint/target.mk
new file mode 100644
index 000000000..09ca94631
--- /dev/null
+++ b/repos/base/src/test/entrypoint/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-entrypoint
+SRC_CC = main.cc
+LIBS = base
diff --git a/repos/base/src/test/thread/main.cc b/repos/base/src/test/thread/main.cc
index c14536350..75c11a82f 100644
--- a/repos/base/src/test/thread/main.cc
+++ b/repos/base/src/test/thread/main.cc
@@ -683,38 +683,6 @@ static void test_successive_create_destroy_threads(Env &env)
}
}
-/**
- * Test destruction of entrypoint with yet not dissolved components
- */
-namespace Test {
- struct Session;
- struct Server;
- struct Component;
-}
-
-struct Test::Session : Genode::Session
-{
- static const char *service_name() { return "EP_TEST"; }
-
- GENODE_RPC(Rpc_test_untyped, void, test_untyped, unsigned);
- GENODE_RPC_INTERFACE(Rpc_test_untyped);
-};
-
-struct Test::Component : Genode::Rpc_object
-{
- void test_untyped(unsigned) { }
-};
-
-static void test_entrypoint_destruction(Genode::Env &env)
-{
- Test::Component c;
-
- {
- Entrypoint ep(env, 8192 /* STACK*/, "test_ep", Affinity::Location());
- ep.manage(c);
- }
-}
-
/******************************************************
** Test destruction of inter-dependent CPU sessions **
******************************************************/
@@ -755,7 +723,6 @@ void Component::construct(Env &env)
test_create_as_many_threads(env);
test_successive_create_destroy_threads(env);
- test_entrypoint_destruction(env);
} catch (int error) {
Genode::error("error ", error);
throw;
diff --git a/repos/gems/run/depot_autopilot.run b/repos/gems/run/depot_autopilot.run
index be72ec7b0..5a36ac806 100644
--- a/repos/gems/run/depot_autopilot.run
+++ b/repos/gems/run/depot_autopilot.run
@@ -656,6 +656,7 @@ set default_test_pkgs {
test-dynamic_config
test-dynamic_config_loader
test-dynamic_config_slave
+ test-entrypoint
test-expat
test-fault_detection
test-fs_log