From: Michael Tokarev Date: Fri, 9 Jan 2026 09:09:37 +0000 (+0300) Subject: linux-user: implement epoll_pwait2 syscall X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a19fe4d3772431101e07765b1edbd9cf9eef0141;p=thirdparty%2Fqemu.git linux-user: implement epoll_pwait2 syscall epoll_pwait2 is the same as epoll_pwait but with timeout being (a pointer to) struct timespec instead of an integer. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3210 Signed-off-by: Michael Tokarev Reviewed-by: Pierrick Bouvier Signed-off-by: Richard Henderson Message-ID: <20260109090937.599881-3-mjt@tls.msk.ru> --- diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 2c7e1eb5b2..67ad681098 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -708,8 +708,11 @@ safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds, size_t, sigsetsize) #endif safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events, - int, maxevents, int, timeout, const sigset_t *, sigmask, - size_t, sigsetsize) + int, maxevents, int, timeout, + const sigset_t *, sigmask, size_t, sigsetsize) +safe_syscall6(int, epoll_pwait2, int, epfd, struct epoll_event *, events, + int, maxevents, struct timespec *, timeout_ts, + const sigset_t *, sigmask, size_t, sigsetsize) #if defined(__NR_futex) safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \ const struct timespec *,timeout,int *,uaddr2,int,val3) @@ -13623,12 +13626,20 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, case TARGET_NR_epoll_wait: #endif case TARGET_NR_epoll_pwait: + case TARGET_NR_epoll_pwait2: { struct target_epoll_event *target_ep; struct epoll_event *ep; int epfd = arg1; int maxevents = arg3; - int timeout = arg4; + struct timespec ts, *timeout_ts = NULL; + + if (num == TARGET_NR_epoll_pwait2 && arg4 != 0) { + if (target_to_host_timespec(&ts, arg4)) { + return -TARGET_EFAULT; + } + timeout_ts = &ts; + } if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) { return -TARGET_EINVAL; @@ -13648,6 +13659,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, switch (num) { case TARGET_NR_epoll_pwait: + case TARGET_NR_epoll_pwait2: { sigset_t *set = NULL; @@ -13658,8 +13670,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } } - ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout, - set, SIGSET_T_SIZE)); + if (num == TARGET_NR_epoll_pwait) { + ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, arg4, + set, SIGSET_T_SIZE)); + } else { + ret = get_errno(safe_epoll_pwait2(epfd, ep, maxevents, timeout_ts, + set, SIGSET_T_SIZE)); + } if (set) { finish_sigsuspend_mask(ret); @@ -13668,7 +13685,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } #if defined(TARGET_NR_epoll_wait) case TARGET_NR_epoll_wait: - ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout, + ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, arg4, NULL, 0)); break; #endif