Implement pselect

This commit is contained in:
Theodore Dubois 2018-10-30 16:59:12 -07:00
parent 00ec13cb6e
commit db525dc2ad
5 changed files with 46 additions and 14 deletions

View File

@ -122,6 +122,7 @@ syscall_t syscall_table[] = {
[305] = (syscall_t) sys_readlinkat,
[306] = (syscall_t) sys_fchmodat,
[307] = (syscall_t) sys_faccessat,
[308] = (syscall_t) sys_pselect,
[320] = (syscall_t) sys_utimensat,
[324] = (syscall_t) sys_fallocate,
[340] = (syscall_t) sys_prlimit,

View File

@ -190,6 +190,7 @@ struct pollfd_ {
};
dword_t sys_poll(addr_t fds, dword_t nfds, dword_t timeout);
dword_t sys_select(fd_t nfds, addr_t readfds_addr, addr_t writefds_addr, addr_t exceptfds_addr, addr_t timeout_addr);
dword_t sys_pselect(fd_t nfds, addr_t readfds_addr, addr_t writefds_addr, addr_t exceptfds_addr, addr_t timeout_addr, addr_t sigmask_addr);
// misc
dword_t sys_futex(addr_t uaddr, dword_t op, dword_t val);

View File

@ -134,3 +134,23 @@ dword_t sys_poll(addr_t fds, dword_t nfds, dword_t timeout) {
return _EFAULT;
return err;
}
dword_t sys_pselect(fd_t nfds, addr_t readfds_addr, addr_t writefds_addr, addr_t exceptfds_addr, addr_t timeout_addr, addr_t sigmask_addr) {
// a system call can only take 6 parameters, so the last two need to be passed as a pointer to a struct
struct {
addr_t mask_addr;
dword_t mask_size;
} sigmask;
if (user_get(sigmask_addr, sigmask))
return _EFAULT;
if (sigmask.mask_size != sizeof(sigset_t_))
return _EINVAL;
sigset_t_ mask, old_mask;
if (user_get(sigmask.mask_addr, mask))
return _EFAULT;
do_sigprocmask(SIG_SETMASK_, mask, &old_mask);
dword_t res = sys_select(nfds, readfds_addr, writefds_addr, exceptfds_addr, timeout_addr);
do_sigprocmask(SIG_SETMASK_, old_mask, NULL);
return res;
}

View File

@ -213,22 +213,11 @@ dword_t sys_sigaction(dword_t signum, addr_t action_addr, addr_t oldaction_addr)
return sys_rt_sigaction(signum, action_addr, oldaction_addr, 1);
}
dword_t sys_rt_sigprocmask(dword_t how, addr_t set_addr, addr_t oldset_addr, dword_t size) {
if (size != sizeof(sigset_t_))
return _EINVAL;
sigset_t_ set;
if (user_get(set_addr, set))
return _EFAULT;
STRACE("rt_sigprocmask(%s, 0x%llx, 0x%x, %d)",
how == SIG_BLOCK_ ? "SIG_BLOCK" :
how == SIG_UNBLOCK_ ? "SIG_UNBLOCK" :
how == SIG_SETMASK_ ? "SIG_SETMASK" : "??",
(long long) set, oldset_addr, size);
sigset_t_ oldset = current->blocked;
int do_sigprocmask(dword_t how, sigset_t_ set, sigset_t_ *oldset_out) {
struct sighand *sighand = current->sighand;
lock(&sighand->lock);
sigset_t oldset = current->blocked;
if (how == SIG_BLOCK_)
current->blocked |= set;
else if (how == SIG_UNBLOCK_)
@ -245,7 +234,27 @@ dword_t sys_rt_sigprocmask(dword_t how, addr_t set_addr, addr_t oldset_addr, dwo
current->pending |= current->queued & unblocked;
current->queued &= ~unblocked;
unlock(&sighand->lock);
if (oldset_out != NULL)
*oldset_out = current->blocked;
return 0;
}
dword_t sys_rt_sigprocmask(dword_t how, addr_t set_addr, addr_t oldset_addr, dword_t size) {
if (size != sizeof(sigset_t_))
return _EINVAL;
sigset_t_ set, oldset;
if (user_get(set_addr, set))
return _EFAULT;
STRACE("rt_sigprocmask(%s, 0x%llx, 0x%x, %d)",
how == SIG_BLOCK_ ? "SIG_BLOCK" :
how == SIG_UNBLOCK_ ? "SIG_UNBLOCK" :
how == SIG_SETMASK_ ? "SIG_SETMASK" : "??",
(long long) set, oldset_addr, size);
int err = do_sigprocmask(how, set, &oldset);
if (err < 0)
return err;
if (oldset_addr != 0)
if (user_put(oldset_addr, oldset))
return _EFAULT;

View File

@ -81,6 +81,7 @@ dword_t sys_rt_sigreturn(dword_t sig);
#define SIG_UNBLOCK_ 1
#define SIG_SETMASK_ 2
typedef uint64_t sigset_t_;
int do_sigprocmask(dword_t how, sigset_t_ set, sigset_t_ *oldset);
dword_t sys_rt_sigprocmask(dword_t how, addr_t set, addr_t oldset, dword_t size);
struct stack_t_ {