if LIBPOSIX_PROCESS
-menuconfig LIBPOSIX_PROCESS_PIDS
- bool "Process and thread IDs"
- select LIBUKSCHED
-
-if LIBPOSIX_PROCESS_PIDS
+menuconfig LIBPOSIX_PROCESS_MULTITHREADING
+ bool "Multithreading support"
+if LIBPOSIX_PROCESS_MULTITHREADING
config LIBPOSIX_PROCESS_MAX_PID
- int "Largest PID"
+ int "Largest TID"
range 1 32767
default 31
+config LIBPOSIX_PROCESS_CLONE_PREFER_CHILD
+ bool "Prefer scheduling of child"
+ help
+ If enabled, clone will context switch away from the clone
+ caller. This is necessary for some applications that assume that
+ the new thread does progress while the clone caller is not
+ context switching.
+
+config LIBPOSIX_PROCESS_EXECVE
+ bool "execve() system call"
+ depends on HAVE_VFS
+ select LIBUKBINFMT
+
+endif
+
+menuconfig LIBPOSIX_PROCESS_MULTIPROCESS
+ bool "Multiprocess support"
+ depends on HAVE_VFS
+ select LIBPOSIX_PROCESS_MULTITHREADING
+ select LIBPOSIX_PROCESS_EXECVE
+
+if LIBPOSIX_PROCESS_MULTIPROCESS
+
config LIBPOSIX_PROCESS_INIT_PIDS
bool "Assign PID during boot"
config LIBPOSIX_PROCESS_SIGNAL
bool "POSIX signals (EXPERIMENTAL)"
- select LIBPOSIX_PROCESS_PIDS
+ select LIBPOSIX_PROCESS_MULTITHREADING
+ select LIBPOSIX_PROCESS_EXECVE
select LIBSYSCALL_SHIM
select LIBUKLOCK
-config LIBPOSIX_PROCESS_CLONE
- bool "clone() system call"
- select LIBPOSIX_PROCESS_PIDS
-
config LIBPOSIX_PROCESS_SIGNALFD
bool "signalfd4() and signalfd() syscalls"
depends on LIBPOSIX_PROCESS_SIGNAL
select LIBUKFILE_POLLED
-config LIBPOSIX_PROCESS_CLONE_PREFER_CHILD
- bool "Prefer scheduling of child"
- depends on LIBPOSIX_PROCESS_CLONE
- help
- If enabled, clone will context switch away from the clone
- caller. This is necessary for some applications that assume that
- the new thread does progress while the clone caller is not
- context switching.
-
-config LIBPOSIX_PROCESS_EXECVE
- bool "execve() system call"
- select LIBPOSIX_PROCESS_PIDS
- select LIBUKBINFMT
-
-config LIBPOSIX_PROCESS_VFORK
- bool "vfork() system call"
- select LIBPOSIX_PROCESS_PIDS
- select LIBPOSIX_PROCESS_CLONE
-
config LIBPOSIX_PROCESS_DEBUG
bool "Enable debug messages"
LIBPOSIX_PROCESS_CFLAGS-$(CONFIG_LIBPOSIX_PROCESS_DEBUG) += -DUK_DEBUG
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += $(LIBPOSIX_PROCESS_BASE)/execve.c
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/execve.c|arch
-
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_VFORK) += $(LIBPOSIX_PROCESS_BASE)/vfork.c
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_VFORK) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/vfork.S|arch
-
LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/deprecated.c
LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/process.c
LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/wait.c
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/execve.c|arch
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += $(LIBPOSIX_PROCESS_BASE)/execve.c
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/vfork.S|arch
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS) += $(LIBPOSIX_PROCESS_BASE)/vfork.c
+
LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_SIGNAL) += $(LIBPOSIX_PROCESS_BASE)/signal/signal.c
LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_SIGNAL) += $(LIBPOSIX_PROCESS_BASE)/signal/sigset.c
LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_SIGNAL) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/ucontext.c
LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/signal/tgkill.c
LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/signal/tkill.c
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += $(LIBPOSIX_PROCESS_BASE)/signal/clone.c|signal
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += $(LIBPOSIX_PROCESS_BASE)/clone.c
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/clone.S|arch
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += $(LIBPOSIX_PROCESS_BASE)/clonetab.ld
-LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/clone.c|$(CONFIG_UK_ARCH)
-CFLAGS-$(CONFIG_LIBPOSIX_PROCESS_PIDS) += -fno-builtin-exit -fno-builtin-exit-group
-CXXFLAGS-$(CONFIG_LIBPOSIX_PROCESS_PIDS) += -fno-builtin-exit -fno-builtin-exit-group
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += $(LIBPOSIX_PROCESS_BASE)/signal/clone.c|signal
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += $(LIBPOSIX_PROCESS_BASE)/clone.c
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += $(LIBPOSIX_PROCESS_BASE)/clonetab.ld
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/clone.c|$(CONFIG_UK_ARCH)
+LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/clone.S|arch
+CFLAGS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += -fno-builtin-exit -fno-builtin-exit-group
+CXXFLAGS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += -fno-builtin-exit -fno-builtin-exit-group
LIBPOSIX_PROCESS_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
LIBPOSIX_PROCESS_ASINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
LIBPOSIX_PROCESS_CXXINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += alarm-1
-UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_CLONE) += clone-5e
-UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += execve-3e
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += pause-0
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += sigaltstack-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += rt_sigpending-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += kill-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += tgkill-3
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += tkill-2
-UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_VFORK) += vfork-0e
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += wait4-4 waitid-4
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += getpgid-1
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += setpgid-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += getrlimit-2 setrlimit-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += getrusage-2
UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS) += prctl-5
-UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_PIDS) += exit-1 exit_group-1
+UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += execve-3e
+UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS) += vfork-0e
+UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += clone-5e
+UK_PROVIDED_SYSCALLS-$(CONFIG_LIBPOSIX_PROCESS_MULTITHREADING) += exit-1 exit_group-1
int uk_clone(struct clone_args *cl_args, size_t cl_args_len,
struct ukarch_execenv *execenv)
{
+ struct posix_process *pprocess;
struct posix_thread *pthread;
struct uk_thread *child = NULL;
struct uk_thread *t;
uk_pr_debug(")\n");
#endif /* UK_DEBUG */
+#if !CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
+ if (unlikely(flags & !CLONE_THREAD)) {
+ uk_pr_err("Multiprocess support not enabled\n");
+ return -ENOTSUP;
+ }
+#endif /* !CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
+
/* CLONE_VM requires that the child operates on the same memory
* space as the parent.
*
#endif /* CONFIG_LIBUKDEBUG_ENABLE_ASSERT */
if (flags & CLONE_VFORK) {
+#if CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
/* We will be blocking the parent and pass control to the child
* via the scheduler. Therefore we need to set the child's TLS
* pointer the Unikraft TLS.
/* Also inherit the parent's stack allocator */
child->_mem.stack_a = t->_mem.stack_a;
+#else /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
+ ret = -ENOTSUP;
+ goto err_free_child;
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
} else {
/* CLONE_SETTLS: Instead of just activating the Unikraft TLS
* we activate the passed TLS pointer as soon as the child
(void *) child->tlsp,
(child->tlsp != child->uktlsp) ? "custom" : "Unikraft");
- if (!(cl_args->flags & CLONE_THREAD)) {
- uk_pr_debug("Creating new process for child\n");
- ret = uk_posix_process_create(uk_alloc_get_default(), child, t);
+ if (cl_args->flags & CLONE_THREAD) {
+ pprocess = uk_pprocess_current();
+ UK_ASSERT(pprocess);
+
+ pthread = pprocess_create_pthread(pprocess, child);
+ if (unlikely(PTRISERR(pthread))) {
+ ret = PTR2ERR(pthread);
+ uk_pr_err("Could not create pthread (%d)\n", ret);
+ goto err_free_child;
+ }
+ } else {
+#if CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
+ ret = pprocess_create(uk_alloc_get_default(), child, t);
if (unlikely(ret)) {
- uk_pr_err("Could not create child process\n");
+ uk_pr_err("Could not create process (%d)\n", ret);
goto err_free_child;
}
+#else /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
+ ret = -ENOTSUP;
+ goto err_free_child;
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
}
/* Call clone handler table but treat CLONE_SETTLS as handled */
extern "C" {
#endif
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
/* Clone arguments for SYS_clone3
* long syscall(SYS_clone3, struct clone_args *cl_args, size_t size);
*/
* of child (since Linux 5.7)
*/
};
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#ifdef __cplusplus
}
#ifndef __UK_PROCESS_H__
#define __UK_PROCESS_H__
-#include <arch/clone.h>
-#include <uk/config.h>
#include <stdbool.h>
+#include <stddef.h> /* NULL */
#include <sys/resource.h>
#include <sys/types.h> /* pid_t */
-#if CONFIG_LIBUKSCHED
-#include <uk/thread.h>
-#endif
-#include <uk/prio.h>
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
+
+#include <uk/config.h>
+#include <uk/essentials.h>
+
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sched.h> /* CLONE_* constants */
#include <linux/sched.h> /* struct clone_args */
+#include <arch/clone.h>
+#include <uk/event.h>
+#include <uk/prio.h>
+#include <uk/thread.h>
+
/* In case a libC is defining only a subset of our currently supported clone
* flags, we provide here a completion of the list
*/
#ifndef CLONE_CLEAR_SIGHAND
#define CLONE_CLEAR_SIGHAND 0x100000000ULL
#endif
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
int uk_sys_prlimit64(int pid, unsigned int resource,
struct rlimit *new_limit, struct rlimit *old_limit);
pid_t uk_sys_getppid(void);
pid_t uk_sys_getpid(void);
-#if CONFIG_LIBUKSCHED
+#if CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
int uk_posix_process_create(struct uk_alloc *a,
struct uk_thread *thread,
struct uk_thread *parent);
void uk_posix_process_kill(struct uk_thread *thread);
-#endif /* CONFIG_LIBUKSCHED */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
typedef int (*uk_posix_clone_init_func_t)(const struct clone_args *cl_args,
size_t cl_args_len,
struct uk_thread *child,
_UK_POSIX_CLONETAB_ENTRY(flags_mask, presence_only, init_fn, term_fn, \
UK_PRIO_LATEST)
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#if CONFIG_LIBPOSIX_PROCESS_EXECVE
struct uk_thread *pprocess_thread_main;
-#if CONFIG_LIBPOSIX_PROCESS_PIDS
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
#include <uk/bitmap.h>
#include <uk/list.h>
#include <uk/alloc.h>
#include <uk/init.h>
#include <uk/errptr.h>
#include <uk/essentials.h>
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
#include <uk/process.h>
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
#if CONFIG_LIBPOSIX_PROCESS_SIGNAL
#include "signal/signal.h"
pprocess_kill(pprocess);
}
-#if CONFIG_LIBPOSIX_PROCESS_INIT_PIDS
static int posix_process_init(struct uk_init_ctx *ictx)
{
struct uk_thread *t;
}
uk_late_initcall(posix_process_init, 0x0);
-#endif /* CONFIG_LIBPOSIX_PROCESS_INIT_PIDS */
/* Thread initialization: Assign posix thread only if parent is part of a
* process
}
#endif /* UK_LIBC_SYSCALLS */
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
/* Store child PID at given location for parent */
static int pprocess_parent_settid(const struct clone_args *cl_args,
size_t cl_args_len __unused,
return 0;
}
UK_POSIX_CLONE_HANDLER(CLONE_THREAD, false, pprocess_clone_thread, 0x0);
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
-#else /* !CONFIG_LIBPOSIX_PROCESS_PIDS */
+#else /* !CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#define UNIKRAFT_PID 1
#define UNIKRAFT_TID 1
return UNIKRAFT_PPID;
}
-#endif /* !CONFIG_LIBPOSIX_PROCESS_PIDS */
+#endif /* !CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
UK_SYSCALL_R_DEFINE(pid_t, gettid)
{
#ifndef __PROCESS_H_INTERNAL__
#define __PROCESS_H_INTERNAL__
-#include <uk/config.h>
#include <sys/types.h>
+#include <uk/config.h>
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
#include <linux/sched.h>
#include <uk/arch/ctx.h>
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
-
-#if CONFIG_LIBPOSIX_PROCESS_PIDS
#include <uk/thread.h>
-
-#define TIDMAP_SIZE (CONFIG_LIBPOSIX_PROCESS_MAX_PID + 1)
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
extern struct uk_thread *pprocess_thread_main;
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
+
+#define TIDMAP_SIZE (CONFIG_LIBPOSIX_PROCESS_MAX_PID + 1)
+
/* Notice: The RUNNING state is not necessarily in sync with the state
* of the underlying uk_thread (may be blocked by the scheduler).
* On the other hand, the BLOCKED state implies that the underlying
pid_t ukthread2pid(struct uk_thread *thread);
void pprocess_kill_siblings(struct uk_thread *thread);
-#endif /* CONFIG_LIBPOSIX_PROCESS_PIDS */
-#if CONFIG_LIBPOSIX_PROCESS_CLONE
int uk_clone(struct clone_args *cl_args, size_t cl_args_len,
struct ukarch_execenv *execenv);
-#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#endif /* __PROCESS_H_INTERNAL__ */
__atomic refcnt;
};
-#if CONFIG_LIBPOSIX_PROCESS_PIDS
+#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
/* Descriptor of a pending signal.
*
#endif /* !CONFIG_LIBPOSIX_PROCESS_SIGNALFD */
#endif /* CONFIG_LIBPOSIX_PROCESS_SIGNAL */
-#endif /* CONFIG_LIBPOSIX_PROCESS_PIDS */
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#endif /* __UK_PROCESS_SIGNAL_H__ */