mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
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:
parent
7020e85fd7
commit
19563e1850
6 changed files with 71 additions and 4 deletions
55
src/internal/emulate_wait4.c
Normal file
55
src/internal/emulate_wait4.c
Normal 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
|
|
@ -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_DISP(__sys_open_cp,,__VA_ARGS__)
|
||||||
#define sys_open_cp(...) __syscall_ret(__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 __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
|
||||||
|
|
||||||
hidden void *__vdsosym(const char *, const char *);
|
hidden void *__vdsosym(const char *, const char *);
|
||||||
|
|
|
@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0;
|
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)) {
|
if (r>0 && ru && sizeof(time_t) > sizeof(long)) {
|
||||||
long kru[4];
|
long kru[4];
|
||||||
memcpy(kru, dest, 4*sizeof(long));
|
memcpy(kru, dest, 4*sizeof(long));
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
|
|
||||||
pid_t waitpid(pid_t pid, int *status, int options)
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ int pclose(FILE *f)
|
||||||
int status, r;
|
int status, r;
|
||||||
pid_t pid = f->pipe_pid;
|
pid_t pid = f->pipe_pid;
|
||||||
fclose(f);
|
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);
|
if (r<0) return __syscall_ret(r);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret))
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
__syscall(SYS_close, p[0]);
|
__syscall(SYS_close, p[0]);
|
||||||
__syscall(SYS_wait4, pid, &status, __WCLONE, 0);
|
__sys_wait4(pid, &status, __WCLONE, 0);
|
||||||
|
|
||||||
__restore_sigs(&set);
|
__restore_sigs(&set);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue