Message ID | 20200908145738.640039-11-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | [v2,01/14] linux: Simplify clock_getres | expand |
On Tue, Sep 8, 2020 at 8:02 AM Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org> wrote: > > 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> Alistair > --- > include/sys/socket.h | 8 ++++ > 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..a29c91fb76 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) > + /* The remanining timeout will be always less the input TIMEOUT. */ > + *timeout = valid_timespec64_to_timespec (ts64); > + return r; > +} > +#endif > +weak_alias (__recvmmsg, recvmmsg) > -- > 2.25.1 >
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..a29c91fb76 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) + /* The remanining timeout will be always less the input TIMEOUT. */ + *timeout = valid_timespec64_to_timespec (ts64); + return r; +} +#endif +weak_alias (__recvmmsg, recvmmsg)