diff --git a/repos/libports/run/libc_component.run b/repos/libports/run/libc_component.run
new file mode 100644
index 0000000000..c68aa42752
--- /dev/null
+++ b/repos/libports/run/libc_component.run
@@ -0,0 +1,103 @@
+#
+# Build
+#
+
+set build_components {
+ core init drivers/timer server/terminal_crosslink
+ test/libc_counter test/libc_component
+}
+
+build $build_components
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+
+set boot_modules {
+ core init timer terminal_crosslink
+ test-libc_counter-source test-libc_component
+ ld.lib.so libc.lib.so libm.lib.so
+}
+
+build_boot_image $boot_modules
+
+append qemu_args "-nographic -m 128"
+
+#
+# Execute test case
+#
+
+run_genode_until forever
+run_genode_until "child \"test-libc_counter-sink\" exited with exit value 0.*\n" 30
+
+# vi: set ft=tcl :
diff --git a/repos/libports/run/libc_vfs_component.run b/repos/libports/run/libc_vfs_component.run
new file mode 100644
index 0000000000..c8c06bd31a
--- /dev/null
+++ b/repos/libports/run/libc_vfs_component.run
@@ -0,0 +1,114 @@
+#
+# Build
+#
+
+set build_components {
+ core init drivers/timer server/terminal_crosslink server/vfs
+ test/libc_counter test/libc_component
+}
+
+build $build_components
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+
+set boot_modules {
+ core init timer terminal_crosslink vfs
+ test-libc_counter-source test-libc_component
+ ld.lib.so libc.lib.so libm.lib.so
+}
+
+build_boot_image $boot_modules
+
+append qemu_args "-nographic -m 128"
+
+#
+# Execute test case
+#
+
+run_genode_until forever
+run_genode_until "child \"test-libc_counter-sink\" exited with exit value 0.*\n" 30
+
+# vi: set ft=tcl :
diff --git a/repos/libports/src/lib/libc/task.cc b/repos/libports/src/lib/libc/task.cc
index 763b368ccf..217d12fe16 100644
--- a/repos/libports/src/lib/libc/task.cc
+++ b/repos/libports/src/lib/libc/task.cc
@@ -510,8 +510,9 @@ struct Libc::Kernel
return;
}
- _app_returned = false;
- _app_code = &app_code;
+ _resume_main_once = false;
+ _app_returned = false;
+ _app_code = &app_code;
/* save continuation of libc kernel (incl. current stack) */
if (!_setjmp(_kernel_context)) {
@@ -526,7 +527,7 @@ struct Libc::Kernel
while (!_app_returned) {
_env.ep().wait_and_dispatch_one_signal();
- if (_resume_main_once)
+ if (_resume_main_once && !_setjmp(_kernel_context))
_switch_to_user();
}
}
@@ -665,8 +666,6 @@ void Libc::schedule_suspend(void (*suspended) ())
void Libc::execute_in_application_context(Libc::Application_code &app_code)
{
- warning("executing code in application context, not implemented");
-
/*
* XXX We don't support a second entrypoint - pthreads should work as they
* don't use this code.
@@ -687,8 +686,6 @@ void Libc::execute_in_application_context(Libc::Application_code &app_code)
nested = true;
kernel->run(app_code);
nested = false;
-
- warning("leaving application context");
}
diff --git a/repos/libports/src/test/libc_component/main.cc b/repos/libports/src/test/libc_component/main.cc
new file mode 100644
index 0000000000..6f8d01309c
--- /dev/null
+++ b/repos/libports/src/test/libc_component/main.cc
@@ -0,0 +1,175 @@
+/*
+ * \brief Libc-component using select test
+ * \author Christian Helmuth
+ * \date 2017-02-09
+ */
+
+/*
+ * Copyright (C) 2017 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
+
+/* libc includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace Log {
+ using Genode::Static_root;
+ using Genode::Log_session;
+
+ struct Session_component;
+ struct Main;
+}
+
+
+static void die(char const *token) __attribute__((noreturn));
+static void die(char const *token)
+{
+ Genode::error("[", Genode::Cstring(token), "] ", Genode::Cstring(strerror(errno)));
+ exit(1);
+}
+
+
+static void use_file_system()
+{
+ int result = 0;
+
+ int const fd = open("/tmp/blub", O_RDWR | O_NONBLOCK | O_CREAT | O_APPEND);
+ if (fd == -1) die("open");
+
+ printf("open returned fd %d\n", fd);
+
+ static char buf[1024];
+
+ result = read(fd, buf, sizeof(buf));
+ if (result == -1) die("read");
+
+ printf("read %d bytes\n", result);
+
+ result = write(fd, "X", 1);
+ if (result == -1) die("write");
+
+ printf("wrote %d bytes\n", result);
+
+ result = close(fd);
+ if (result == -1) die("close");
+}
+
+
+struct Log::Session_component : Genode::Rpc_object
+{
+ char _buf[Log_session::MAX_STRING_LEN];
+ int _fd = -1;
+ fd_set _readfds;
+ fd_set _writefds;
+ fd_set _exceptfds;
+
+ void _select()
+ {
+ int nready = 0;
+ do {
+ fd_set readfds = _readfds;
+ fd_set writefds = _writefds;
+ fd_set exceptfds = _exceptfds;
+
+ nready = _select_handler.select(_fd + 1, readfds, writefds, exceptfds);
+ if (nready)
+ _select_ready(nready, readfds, writefds, exceptfds);
+ } while (nready);
+ }
+
+ Libc::Select_handler _select_handler {
+ *this, &Session_component::_select_ready };
+
+ void _select_ready(int nready, fd_set const &readfds, fd_set const &writefds, fd_set const &exceptfds)
+ {
+ Libc::with_libc([&] () {
+ if (nready <= 0) {
+ Genode::warning("select handler reported nready=", nready);
+ return;
+ }
+ if (!FD_ISSET(_fd, &readfds)) {
+ Genode::warning("select handler reported unexpected fd, nready=", nready);
+
+ for (unsigned i = 0; i < FD_SETSIZE; ++i)
+ if (FD_ISSET(i, &readfds)) Genode::log("fd ", i, " readable");
+ for (unsigned i = 0; i < FD_SETSIZE; ++i)
+ if (FD_ISSET(i, &writefds)) Genode::log("fd ", i, " writeable");
+ for (unsigned i = 0; i < FD_SETSIZE; ++i)
+ if (FD_ISSET(i, &exceptfds)) Genode::log("fd ", i, " exceptable?");
+
+ return;
+ }
+ int const result = read(_fd, _buf, sizeof(_buf)-1);
+ if (result <= 0) {
+ Genode::warning("read returned ", result, " in select handler");
+ return;
+ }
+ _buf[result] = 0;
+ Genode::log("read from file \"", Genode::Cstring(_buf), "\"");
+ });
+ }
+
+ Session_component()
+ {
+ Libc::with_libc([&] () {
+ _fd = open("/dev/terminal", O_RDWR);
+ if (_fd == -1) die("open");
+
+ FD_ZERO(&_readfds);
+ FD_ZERO(&_writefds);
+ FD_ZERO(&_exceptfds);
+ FD_SET(_fd, &_readfds);
+ });
+ }
+
+ Genode::size_t write(String const &string_buf)
+ {
+ if (!(string_buf.valid_string())) { return 0; }
+
+ strncpy(_buf, string_buf.string(), sizeof(_buf));
+ size_t len = strlen(_buf);
+
+ if (_buf[len-1] == '\n') _buf[len-1] = 0;
+
+ Genode::log("RPC with \"", Genode::Cstring(_buf), "\"");
+
+ _select();
+
+ return len;
+ }
+};
+
+
+struct Log::Main
+{
+ Libc::Env &_env;
+ Session_component _session { };
+ Static_root _root { _env.ep().manage(_session) };
+
+ Main(Libc::Env &env) : _env(env)
+ {
+ Libc::with_libc([] () { use_file_system(); });
+
+ _env.parent().announce(_env.ep().manage(_root));
+ }
+};
+
+
+void Libc::Component::construct(Libc::Env &env) { static Log::Main inst(env); }
diff --git a/repos/libports/src/test/libc_component/target.mk b/repos/libports/src/test/libc_component/target.mk
new file mode 100644
index 0000000000..2dd1983165
--- /dev/null
+++ b/repos/libports/src/test/libc_component/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-libc_component
+SRC_CC = main.cc
+LIBS = libc