]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-process: Add uk_posix_process_run()
authorMichalis Pappas <michalis@unikraft.io>
Mon, 14 Apr 2025 15:05:19 +0000 (17:05 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Wed, 30 Apr 2025 10:07:29 +0000 (10:07 +0000)
This function spanws a process that jumps to main-like function passed
as an argument. It is intended to be used by the init process when
multiprocess is enabled, to spawn the application process and call
main(). As in native mode there is no path to pass to execve(), this
function allows spawning the application process in both native and
bincompat mode.

Signed-off-by: Michalis Pappas <michalis@unikraft.io>
Approved-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Andrei Tatar <andrei@unikraft.io>
GitHub-Closes: #1633

lib/posix-process/clone.c
lib/posix-process/execve.c
lib/posix-process/exportsyms.uk
lib/posix-process/include/uk/process.h
lib/posix-process/process.c
lib/posix-process/process.h

index de9a5388fe1b44eaa97c3d9ec3c1d0898cb55211..4949b02b82737c4fd03a952c47aeb7712ef9c43e 100644 (file)
@@ -122,11 +122,11 @@ static int _clonetab_term_call(void *argp)
        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;
@@ -227,7 +227,7 @@ out:
  *  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;
 
@@ -258,7 +258,8 @@ static void uk_posix_clonetab_term(struct uk_thread *child)
        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)
@@ -545,9 +546,9 @@ int uk_clone(struct clone_args *cl_args, size_t cl_args_len,
        }
 
        /* 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",
index 0ee8eb51e5e91ce45c6c8f66380d75047434dd1e..52bc7fa803dabd4fe6889409e4cc15c83b7da4b5 100644 (file)
@@ -83,6 +83,11 @@ static int pprocess_cleanup(struct posix_process *pprocess)
        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)
@@ -170,7 +175,7 @@ UK_SYSCALL_R_E_DEFINE(int, execve, const char *, pathname,
         * 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;
index d4d6f6fc94e3e98ff29b25801361e53703df3f45..034aa0c3aeea58d0db2534fe24e4d1b374ee149b 100644 (file)
@@ -53,3 +53,4 @@ sigprocmask
 tgkill
 signalfd
 uk_posix_process_create_pthread
+uk_posix_process_run
index dd48bf5008b0fe30496dab4a732b5884d056cb81..3faa9ac2e22c434605f7014b387c19b718cf976c 100644 (file)
@@ -226,8 +226,26 @@ int uk_posix_process_create_pthread(struct uk_thread *thread);
 
 #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;
index dcd811e980e90a2119fdb3ea6948e3bb5723b1ee..c535f5d5c71fbd505d4042018d1760b5e55dedf2 100644 (file)
@@ -18,6 +18,8 @@
 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>
@@ -26,6 +28,7 @@ struct uk_thread *pprocess_thread_main;
 #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
@@ -343,6 +346,91 @@ err_out:
        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
index 7505b7b702b8c0a392bb10a335cc7c748b66d3b2..c023be93cf5dbf6333ff8ab7ce8781437bc6a1be 100644 (file)
@@ -14,6 +14,7 @@
 #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 */
@@ -194,6 +195,17 @@ int pprocess_create(struct uk_alloc *a, struct uk_thread *thread,
 
 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__ */