diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2020-07-06 16:55:46 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2020-09-28 17:28:39 -0300 |
commit | b16f282cb079980ddb4de5c9a2350e8b1919d023 (patch) | |
tree | 86c0b22b83aa9a9e8aebc6fd7b906e51a88aa02c | |
parent | c3a020eedde907e7df69159a54bf59d39db85709 (diff) | |
download | glibc-b16f282cb079980ddb4de5c9a2350e8b1919d023.tar.gz glibc-b16f282cb079980ddb4de5c9a2350e8b1919d023.tar.xz glibc-b16f282cb079980ddb4de5c9a2350e8b1919d023.zip |
linux: Add time64 recvmmsg support
The wire-up syscall __NR_recvmmsg_time64 (for 32-bit) or __NR_recvmmsg (for 64-bit) is used as default. The 32-bit fallback is used iff __ASSUME_TIME64_SYSCALLS is not defined, which assumes the kernel ABI provides either __NR_socketcall or __NR_recvmmsg (32-bit time_t). It does not handle the timestamps on ancillary data (SCM_TIMESTAMPING records). Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
-rw-r--r-- | include/sys/socket.h | 8 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/recvmmsg.c | 63 |
2 files changed, 60 insertions, 11 deletions
diff --git a/include/sys/socket.h b/include/sys/socket.h index 26db0e0d77..0e39dd2a3a 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -104,6 +104,14 @@ extern ssize_t __libc_recvmsg (int __fd, struct msghdr *__message, int __flags); extern ssize_t __recvmsg (int __fd, struct msghdr *__message, int __flags) attribute_hidden; +#if __TIMESIZE == 64 +# define __recvmmsg64 __recvmmsg +#else +extern int __recvmmsg64 (int __fd, struct mmsghdr *vmessages, + unsigned int vlen, int flags, + struct __timespec64 *timeout); +libc_hidden_proto (__recvmmsg64) +#endif /* Set socket FD's option OPTNAME at protocol level LEVEL to *OPTVAL (which is OPTLEN bytes long). diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c index 42c80c59c3..641f7e17b9 100644 --- a/sysdeps/unix/sysv/linux/recvmmsg.c +++ b/sysdeps/unix/sysv/linux/recvmmsg.c @@ -16,21 +16,62 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#include <errno.h> #include <sys/socket.h> - -#include <sysdep-cancel.h> -#include <sys/syscall.h> +#include <sysdep.h> #include <socketcall.h> -#include <kernel-features.h> int -recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, - struct timespec *tmo) +__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, + struct __timespec64 *timeout) { -#ifdef __ASSUME_RECVMMSG_SYSCALL - return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo); -#else - return SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo); +#ifndef __NR_recvmmsg_time64 +# define __NR_recvmmsg_time64 __NR_recvmmsg #endif + int r = SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen, flags, + timeout); +#ifndef __ASSUME_TIME64_SYSCALLS + if (r >= 0 || errno != ENOSYS) + return r; + + struct timespec ts32, *pts32 = NULL; + if (timeout != NULL) + { + if (! in_time_t_range (timeout->tv_sec)) + { + __set_errno (EINVAL); + return -1; + } + ts32 = valid_timespec64_to_timespec (*timeout); + pts32 = &ts32; + } +# ifdef __ASSUME_RECVMMSG_SYSCALL + r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32); +# else + r = SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32); +# endif + if (r >= 0 && timeout != NULL) + *timeout = valid_timespec_to_timespec64 (ts32); +#endif /* __ASSUME_TIME64_SYSCALLS */ + return r; } +#if __TIMESIZE != 64 +libc_hidden_def (__recvmmsg64) + +int +__recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, + struct timespec *timeout) +{ + struct __timespec64 ts64, *pts64 = NULL; + if (timeout != NULL) + { + ts64 = valid_timespec_to_timespec64 (*timeout); + pts64 = &ts64; + } + int r = __recvmmsg64 (fd, vmessages, vlen, flags, pts64); + if (r >= 0 && timeout != NULL) + /* The remanining timeout will be always less the input TIMEOUT. */ + *timeout = valid_timespec64_to_timespec (ts64); + return r; +} +#endif +weak_alias (__recvmmsg, recvmmsg) |