diff options
author | Rich Felker <dalias@aerifal.cx> | 2024-02-22 18:50:34 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2024-02-22 18:50:34 -0500 |
commit | 19563e1850808af216b1b84263bb7e83cccce506 (patch) | |
tree | 76aa0be0c61791fcae503569477efb87401cb83e /src/internal | |
parent | 7020e85fd768be02e7f5971f1707229407cfa1e4 (diff) | |
download | musl-19563e1850808af216b1b84263bb7e83cccce506.zip musl-19563e1850808af216b1b84263bb7e83cccce506.tar.gz musl-19563e1850808af216b1b84263bb7e83cccce506.tar.bz2 |
add framework to support archs without a native wait4 syscall
this commit should make no codegen change for existing archs, but is a
prerequisite for new archs including riscv32. the wait4 emulation
backend provides both cancellable and non-cancellable variants because
waitpid is required to be a cancellation point, but all of our other
uses are not, and most of them cannot be.
based on patch by Stefan O'Rear.
Diffstat (limited to 'src/internal')
-rw-r--r-- | src/internal/emulate_wait4.c | 55 | ||||
-rw-r--r-- | src/internal/syscall.h | 12 |
2 files changed, 67 insertions, 0 deletions
diff --git a/src/internal/emulate_wait4.c b/src/internal/emulate_wait4.c new file mode 100644 index 0000000..f630341 --- /dev/null +++ b/src/internal/emulate_wait4.c @@ -0,0 +1,55 @@ +#include <sys/wait.h> +#include "syscall.h" + +#ifndef SYS_wait4 +hidden long __emulate_wait4(int pid, int *status, int options, void *kru, int cp) +{ + idtype_t t; + int r; + siginfo_t info; + + info.si_pid = 0; + if (pid < -1) { + t = P_PGID; + pid = -pid; + } else if (pid == -1) { + t = P_ALL; + } else if (pid == 0) { + t = P_PGID; + } else { + t = P_PID; + } + + if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru); + else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru); + + if (r<0) return r; + + if (info.si_pid && status) { + int sw=0; + switch (info.si_code) { + case CLD_CONTINUED: + sw = 0xffff; + break; + case CLD_DUMPED: + sw = info.si_status&0x7f | 0x80; + break; + case CLD_EXITED: + sw = (info.si_status&0xff) << 8; + break; + case CLD_KILLED: + sw = info.si_status&0x7f; + break; + case CLD_STOPPED: + case CLD_TRAPPED: + /* see ptrace(2); the high bits of si_status can contain */ + /* PTRACE_EVENT_ values which must be preserved */ + sw = (info.si_status << 8) + 0x7f; + break; + } + *status = sw; + } + + return info.si_pid; +} +#endif diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 4a44615..33d981f 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -391,6 +391,18 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, #define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) #define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) +#ifdef SYS_wait4 +#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d) +#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d) +#else +hidden long __emulate_wait4(int, int *, int, void *, int); +#define __sys_wait4(a,b,c,d) __emulate_wait4(a,b,c,d,0) +#define __sys_wait4_cp(a,b,c,d) __emulate_wait4(a,b,c,d,1) +#endif + +#define sys_wait4(a,b,c,d) __syscall_ret(__sys_wait4(a,b,c,d)) +#define sys_wait4_cp(a,b,c,d) __syscall_ret(__sys_wait4_cp(a,b,c,d)) + hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); hidden void *__vdsosym(const char *, const char *); |