Introduce a new set of utility functions that can be used to create pthread-based helpers. Helper threads created in this way will ensure thread safety for errno while sharing memory address space.
Signed-off-by: Tiwei Bie <tiwei....@antgroup.com> --- arch/um/include/shared/os.h | 3 ++ arch/um/os-Linux/helper.c | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 5babad8c5f75..1f62e793bce3 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -225,6 +225,9 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long *stack_out); extern int helper_wait(int pid); +int os_run_helper_thread(void *(*routine)(void *), void *arg, void **handle_out); +void os_kill_helper_thread(void *); +void os_fix_helper_thread_signals(void); /* umid.c */ extern int umid_file_name(char *name, char *buf, int len); diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 3cb8ac63be6e..c6a0ef8beb29 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -8,6 +8,7 @@ #include <unistd.h> #include <errno.h> #include <sched.h> +#include <pthread.h> #include <linux/limits.h> #include <sys/socket.h> #include <sys/wait.h> @@ -167,3 +168,62 @@ int helper_wait(int pid) } else return 0; } + +int os_run_helper_thread(void *(*routine)(void *), void *arg, void **handle_out) +{ + pthread_t *td; + sigset_t sigset, oset; + int err, flags; + + flags = __uml_cant_sleep() ? UM_GFP_ATOMIC : UM_GFP_KERNEL; + td = uml_kmalloc(sizeof(*td), flags); + if (!td) + return -ENOMEM; + + sigfillset(&sigset); + if (sigprocmask(SIG_SETMASK, &sigset, &oset) < 0) { + err = -errno; + kfree(td); + return err; + } + + err = pthread_create(td, NULL, routine, arg); + + if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) + panic("Failed to restore the signal mask: %d", errno); + + if (err != 0) + kfree(td); + else + *handle_out = td; + + return -err; +} + +void os_kill_helper_thread(void *handle) +{ + pthread_t *td = handle; + + pthread_kill(*td, SIGKILL); + CATCH_EINTR(pthread_join(*td, NULL)); + kfree(td); +} + +void os_fix_helper_thread_signals(void) +{ + sigset_t sigset; + + sigemptyset(&sigset); + + sigaddset(&sigset, SIGWINCH); + sigaddset(&sigset, SIGPIPE); + sigaddset(&sigset, SIGPROF); + sigaddset(&sigset, SIGINT); + sigaddset(&sigset, SIGTERM); + sigaddset(&sigset, SIGCHLD); + sigaddset(&sigset, SIGALRM); + sigaddset(&sigset, SIGIO); + sigaddset(&sigset, SIGUSR1); + + pthread_sigmask(SIG_SETMASK, &sigset, NULL); +} -- 2.34.1