return 0;
}
/** Iterates over registered thread initialization functions */
-static int _uk_posix_clonetab_init(const struct clone_args *cl_args,
- size_t cl_args_len,
- __u64 cl_flags_optional,
- struct uk_thread *child,
- struct uk_thread *parent)
+int pprocess_clonetab_init(const struct clone_args *cl_args,
+ size_t cl_args_len,
+ __u64 cl_flags_optional,
+ struct uk_thread *child,
+ struct uk_thread *parent)
{
struct uk_posix_clonetab_entry *itr;
struct _clonetab_init_call_args init_args;
* were created with clone
* NOTE: This function is called from child TLS context
*/
-static void uk_posix_clonetab_term(struct uk_thread *child)
+void pprocess_clonetab_term(struct uk_thread *child)
{
struct uk_posix_clonetab_entry *itr;
cl_status.is_cloned = false;
cl_status.cl_flags = 0x0;
}
-UK_THREAD_INIT_PRIO(0x0, uk_posix_clonetab_term, UK_PRIO_LATEST);
+
+UK_THREAD_INIT_PRIO(0x0, pprocess_clonetab_term, UK_PRIO_LATEST);
/*
* NOTE: From man pages about clone(2)
}
/* Call clone handler table but treat CLONE_SETTLS as handled */
- ret = _uk_posix_clonetab_init(cl_args, cl_args_len,
- CLONE_SETTLS,
- child, t);
+ ret = pprocess_clonetab_init(cl_args, cl_args_len,
+ CLONE_SETTLS,
+ child, t);
if (ret < 0)
goto err_free_child;
uk_pr_debug("Thread cloned %p (%s) -> %p (%s): %d\n",
return 0;
}
+int pprocess_raise_execve_event(struct posix_process_execve_event_data *data)
+{
+ return uk_raise_event(POSIX_PROCESS_EXECVE_EVENT, data);
+}
+
UK_SYSCALL_R_E_DEFINE(int, execve, const char *, pathname,
char *const *, argv,
char *const *, envp)
* internal cleanup.
*/
event_data.thread = this_thread;
- rc = uk_raise_event(POSIX_PROCESS_EXECVE_EVENT, &event_data);
+ rc = pprocess_raise_execve_event(&event_data);
if (unlikely(rc < 0)) {
uk_pr_err("execve event error (%d)\n", rc);
goto err_free_stack_new;
tgkill
signalfd
uk_posix_process_create_pthread
+uk_posix_process_run
#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
-#if CONFIG_LIBPOSIX_PROCESS_EXECVE
+#if CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
+
+typedef int (*uk_posix_process_mainlike_func)(int argc, char *argv[]);
+
+/**
+ * Spawn a process that jumps into function.
+ *
+ * DO NOT USE. This is only necessary when we create a new process
+ * for main() in multiprocess.
+ *
+ * @param fn Function to jump to.
+ * @param argc Arg count
+ * @param argv Arg vector
+ * @return Child pid to parent, or negative value on failure.
+ */
+pid_t uk_posix_process_run(uk_posix_process_mainlike_func fn,
+ int argc, const char **argv);
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
+#if CONFIG_LIBPOSIX_PROCESS_EXECVE
/* Data delivered to the handlers of the POSIX_PROCESS_EXECVE_EVENT */
struct posix_process_execve_event_data {
struct uk_thread *thread;
struct uk_thread *pprocess_thread_main;
#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
+#include <signal.h> /* SIGCHLD */
+
#include <uk/bitmap.h>
#include <uk/list.h>
#include <uk/alloc.h>
#include <uk/init.h>
#include <uk/errptr.h>
#include <uk/essentials.h>
+#include <uk/plat/config.h>
#include <uk/process.h>
#if CONFIG_LIBPOSIX_PROCESS_SIGNAL
return ret;
}
+#if CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS
+pid_t uk_posix_process_run(uk_posix_process_mainlike_func fn,
+ int argc, const char *argv[])
+{
+ struct posix_process_execve_event_data event_data;
+ struct uk_sched *s = uk_sched_current();
+ struct clone_args cl_args;
+ struct uk_thread *thread;
+ struct uk_thread *parent;
+ pid_t parent_tid;
+ pid_t tid;
+ int ret;
+
+ UK_ASSERT(s);
+
+ parent = uk_thread_current();
+ parent_tid = ukthread2tid(parent);
+ UK_ASSERT(parent_tid > 0);
+
+ /* Create container thread */
+ thread = uk_thread_create_container(uk_alloc_get_default(),
+ s->a_stack,
+ STACK_SIZE,
+ s->a_auxstack, 0, s->a_uktls,
+ false, "application", NULL, NULL);
+ if (unlikely(!thread)) {
+ uk_pr_err("Could not create thread\n");
+ return -ENOMEM;
+ }
+
+ /* Create new process */
+ ret = pprocess_create(uk_alloc_get_default(), thread, parent);
+ if (unlikely(ret)) {
+ uk_pr_err("Could not create process (%d)\n", ret);
+ goto err_free_thread;
+ }
+
+ tid = ukthread2tid(thread);
+
+ /* Iterate clonetab. We pass the flags used when creating
+ * a new process, i.e. CLONE_VM | CLONE_VFORK | SIGCHLD.
+ */
+ cl_args = (struct clone_args) {
+ .flags = CLONE_VM | CLONE_VFORK,
+ .child_tid = tid,
+ .parent_tid = parent_tid,
+ .exit_signal = SIGCHLD,
+ };
+ ret = pprocess_clonetab_init(&cl_args, sizeof(cl_args), 0,
+ thread, parent);
+ if (unlikely(ret)) {
+ uk_pr_err("clonetab execution error (%d)\n", ret);
+ goto err_free_process;
+ }
+
+ /* Raise the execve event */
+ event_data.thread = thread;
+ ret = pprocess_raise_execve_event(&event_data);
+ if (unlikely(ret < 0)) {
+ uk_pr_err("exeve event error (%d)\n", ret);
+ goto err_term_clonetab;
+ }
+
+ /* Schedule the process */
+ uk_thread_container_init_fn2(thread,
+ (uk_thread_fn2_t)fn,
+ (void *)(unsigned long)argc,
+ (void *)argv);
+ uk_sched_thread_add(s, thread);
+
+ return ukthread2pid(thread);
+
+err_term_clonetab:
+ pprocess_clonetab_term(thread);
+
+err_free_process:
+ pprocess_release(tid2pprocess(tid));
+
+err_free_thread:
+ uk_thread_release(thread);
+
+ return ret;
+}
+#endif /* CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS */
+
/* Releases pprocess memory and other resources.
* NOTE: All pthreads must be removed already
* from this pprocess. All chilren must
#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING
#include <linux/sched.h>
#include <uk/arch/ctx.h>
+#include <uk/process.h>
#include <uk/semaphore.h>
#include <uk/thread.h>
#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
int uk_clone(struct clone_args *cl_args, size_t cl_args_len,
struct ukarch_execenv *execenv);
+
+int pprocess_clonetab_init(const struct clone_args *cl_args, size_t cl_args_len,
+ __u64 cl_flags_optional, struct uk_thread *child,
+ struct uk_thread *parent);
+
+void pprocess_clonetab_term(struct uk_thread *child);
+
+#if CONFIG_LIBPOSIX_PROCESS_EXECVE
+int pprocess_raise_execve_event(struct posix_process_execve_event_data *data);
+#endif /* CONFIG_LIBPOSIX_PROCESS_EXECVE */
+
#endif /* CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */
#endif /* __PROCESS_H_INTERNAL__ */