From 15f08794021c59d4e059100b6ab0b799c03a17b1 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 15 Feb 2012 19:51:13 +0100 Subject: [PATCH] Noux: skeleton for getpid and fork --- ports/include/noux_session/noux_session.h | 4 ++ ports/include/noux_session/sysio.h | 6 +++ ports/src/lib/libc_noux/plugin.cc | 58 +++++++++++++++++++++++ ports/src/noux/main.cc | 13 +++++ 4 files changed, 81 insertions(+) diff --git a/ports/include/noux_session/noux_session.h b/ports/include/noux_session/noux_session.h index 2bfed4dc7..f3a79e4fb 100644 --- a/ports/include/noux_session/noux_session.h +++ b/ports/include/noux_session/noux_session.h @@ -46,6 +46,8 @@ namespace Noux { SYSCALL_FCHDIR, SYSCALL_EXECVE, SYSCALL_SELECT, + SYSCALL_FORK, + SYSCALL_GETPID, SYSCALL_INVALID = -1 }; @@ -66,6 +68,8 @@ namespace Noux { NOUX_DECL_SYSCALL_NAME(FCHDIR) NOUX_DECL_SYSCALL_NAME(EXECVE) NOUX_DECL_SYSCALL_NAME(SELECT) + NOUX_DECL_SYSCALL_NAME(FORK) + NOUX_DECL_SYSCALL_NAME(GETPID) case SYSCALL_INVALID: return 0; } return 0; diff --git a/ports/include/noux_session/sysio.h b/ports/include/noux_session/sysio.h index 80be157e7..c04ce7a5d 100644 --- a/ports/include/noux_session/sysio.h +++ b/ports/include/noux_session/sysio.h @@ -247,6 +247,12 @@ namespace Noux { SYSIO_DECL(select, { Select_fds fds; Select_timeout timeout; }, { Select_fds fds; }); + + SYSIO_DECL(fork, { Genode::addr_t ip; Genode::addr_t sp; + Genode::addr_t parent_cap_addr; }, + { int pid; }); + + SYSIO_DECL(getpid, { }, { int pid; }); }; }; }; diff --git a/ports/src/lib/libc_noux/plugin.cc b/ports/src/lib/libc_noux/plugin.cc index 1b7b58692..4d8d2b556 100644 --- a/ports/src/lib/libc_noux/plugin.cc +++ b/ports/src/lib/libc_noux/plugin.cc @@ -293,6 +293,64 @@ extern "C" int select(int nfds, fd_set *readfds, fd_set *writefds, } +#include + +#include /* for '_parent_cap', needed by 'fork' */ +#include + + +static jmp_buf fork_jmp_buf; + + +/* + * The new process created via fork will start its execution here. + */ +extern "C" void fork_trampoline() +{ + static_cast(Genode::env())->reload_parent_cap(); + + longjmp(fork_jmp_buf, 1); +} + + +extern "C" pid_t fork(void) +{ + /* stack used for executing 'fork_trampoline' */ + enum { STACK_SIZE = 1024 }; + static long stack[STACK_SIZE]; + + if (setjmp(fork_jmp_buf)) { + + /* got here via longjmp from 'fork_trampoline' */ + + PDBG("fork: got here via longjmp"); + return 0; + + } else { + + PDBG("fork: got here via normal control flow"); + + /* got here during the normal control flow of the fork call */ + sysio()->fork_in.ip = (Genode::addr_t)(&fork_trampoline); + sysio()->fork_in.sp = (Genode::addr_t)(&stack[STACK_SIZE]); + sysio()->fork_in.parent_cap_addr = (Genode::addr_t)(&_parent_cap); + + if (!noux()->syscall(Noux::Session::SYSCALL_FORK)) { + PERR("fork error %d", sysio()->error.general); + } + + return sysio()->fork_out.pid; + } +} + + +extern "C" pid_t getpid(void) +{ + noux()->syscall(Noux::Session::SYSCALL_GETPID); + return sysio()->getpid_out.pid; +} + + /********************* ** File operations ** *********************/ diff --git a/ports/src/noux/main.cc b/ports/src/noux/main.cc index ec56abb18..ba0c0568e 100644 --- a/ports/src/noux/main.cc +++ b/ports/src/noux/main.cc @@ -283,6 +283,19 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) return true; } + case SYSCALL_FORK: + { + PDBG("fork called - not implemented"); + _sysio->fork_out.pid = 77; + return true; + } + + case SYSCALL_GETPID: + { + _sysio->getpid_out.pid = _pid; + return true; + } + case SYSCALL_INVALID: break; } }