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.
This commit is contained in:
Rich Felker 2024-02-22 18:50:34 -05:00
parent 7020e85fd7
commit 19563e1850
6 changed files with 71 additions and 4 deletions

View file

@ -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

View file

@ -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 *);

View file

@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
}
#endif
char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0;
r = __syscall(SYS_wait4, pid, status, options, dest);
r = __sys_wait4(pid, status, options, dest);
if (r>0 && ru && sizeof(time_t) > sizeof(long)) {
long kru[4];
memcpy(kru, dest, 4*sizeof(long));

View file

@ -3,5 +3,5 @@
pid_t waitpid(pid_t pid, int *status, int options)
{
return syscall_cp(SYS_wait4, pid, status, options, 0);
return sys_wait4_cp(pid, status, options, 0);
}

View file

@ -7,7 +7,7 @@ int pclose(FILE *f)
int status, r;
pid_t pid = f->pipe_pid;
fclose(f);
while ((r=__syscall(SYS_wait4, pid, &status, 0, 0)) == -EINTR);
while ((r=__sys_wait4(pid, &status, 0, 0)) == -EINTR);
if (r<0) return __syscall_ret(r);
return status;
}

View file

@ -53,7 +53,7 @@ int faccessat(int fd, const char *filename, int amode, int flag)
if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret))
ret = -EBUSY;
__syscall(SYS_close, p[0]);
__syscall(SYS_wait4, pid, &status, __WCLONE, 0);
__sys_wait4(pid, &status, __WCLONE, 0);
__restore_sigs(&set);