Commit Message
Here is a revised version of the patch that avoids losing the socketcall.h
#include, so that it actually builds for configurations that use the
socketcall case (tested build for m68k-linux-gnu).
Simplify recvmmsg code.
Now we can assume a kernel with recvmmsg support, this patch
simplifies the implementation to be similar to that for accept4:
either using socketcall or the syscall according to whether the
syscall is known to be available, without further fallback
implementations.
(In fact further simplification is possible, getting rid of the
__ASSUME_*_SYSCALL_WITH_SOCKETCALL macros now that the minimum kernel
is guaranteed support for all of accept4, recvmmsg, sendmmsg, whether
through syscalls or through socketcall. I intend to do that for all
of accept4 / recvmmsg / sendmmsg together - so making their
implementations just like those for older socket functions - once the
basic cleanup for 3.2 minimum kernel is done for sendmmsg as well as
recvmmsg.)
Tested for x86_64 and x86.
2017-05-09 Joseph Myers <joseph@codesourcery.com>
* sysdeps/unix/sysv/linux/kernel-features.h
(__ASSUME_RECVMMSG_SYSCALL): Define unconditionally.
(__ASSUME_RECVMMSG_SOCKETCALL): Remove macro.
(__ASSUME_RECVMMSG): Likewise.
* sysdeps/unix/sysv/linux/recvmmsg.c (recvmmsg): Define using
recvmmsg syscall if it can be assumed to be present, socketcall
otherwise, with no fallback for runtime failure.
Comments
On 09/05/2017 12:33, Joseph Myers wrote:
> Here is a revised version of the patch that avoids losing the socketcall.h
> #include, so that it actually builds for configurations that use the
> socketcall case (tested build for m68k-linux-gnu).
>
>
>
> Simplify recvmmsg code.
>
> Now we can assume a kernel with recvmmsg support, this patch
> simplifies the implementation to be similar to that for accept4:
> either using socketcall or the syscall according to whether the
> syscall is known to be available, without further fallback
> implementations.
>
> (In fact further simplification is possible, getting rid of the
> __ASSUME_*_SYSCALL_WITH_SOCKETCALL macros now that the minimum kernel
> is guaranteed support for all of accept4, recvmmsg, sendmmsg, whether
> through syscalls or through socketcall. I intend to do that for all
> of accept4 / recvmmsg / sendmmsg together - so making their
> implementations just like those for older socket functions - once the
> basic cleanup for 3.2 minimum kernel is done for sendmmsg as well as
> recvmmsg.)
I was about to work on it, but since you already planning it I will
drop it.
>
> Tested for x86_64 and x86.
>
> 2017-05-09 Joseph Myers <joseph@codesourcery.com>
>
> * sysdeps/unix/sysv/linux/kernel-features.h
> (__ASSUME_RECVMMSG_SYSCALL): Define unconditionally.
> (__ASSUME_RECVMMSG_SOCKETCALL): Remove macro.
> (__ASSUME_RECVMMSG): Likewise.
> * sysdeps/unix/sysv/linux/recvmmsg.c (recvmmsg): Define using
> recvmmsg syscall if it can be assumed to be present, socketcall
> otherwise, with no fallback for runtime failure.
LGTM, thanks.
>
> diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
> index 74ac627..a5c2263 100644
> --- a/sysdeps/unix/sysv/linux/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/kernel-features.h
> @@ -90,13 +90,7 @@
>
> /* Support for recvmmsg functionality was added in 2.6.33. The macros
> defined correspond to those for accept4. */
> -#if __LINUX_KERNEL_VERSION >= 0x020621
> -# ifdef __ASSUME_SOCKETCALL
> -# define __ASSUME_RECVMMSG_SOCKETCALL 1
> -# endif
> -# define __ASSUME_RECVMMSG_SYSCALL 1
> -# define __ASSUME_RECVMMSG 1
> -#endif
> +#define __ASSUME_RECVMMSG_SYSCALL 1
>
> /* statfs fills in f_flags since 2.6.36. */
> #if __LINUX_KERNEL_VERSION >= 0x020624
> diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c
> index 28eb678..de44129 100644
> --- a/sysdeps/unix/sysv/linux/recvmmsg.c
> +++ b/sysdeps/unix/sysv/linux/recvmmsg.c
> @@ -21,73 +21,21 @@
>
> #include <sysdep-cancel.h>
> #include <sys/syscall.h>
> +#include <socketcall.h>
> #include <kernel-features.h>
>
> -/* Do not use the recvmmsg syscall on socketcall architectures unless
> - it was added at the same time as the socketcall support or can be
> - assumed to be present. */
> -#if defined __ASSUME_SOCKETCALL \
> - && !defined __ASSUME_RECVMMSG_SYSCALL_WITH_SOCKETCALL \
> - && !defined __ASSUME_RECVMMSG_SYSCALL
> -# undef __NR_recvmmsg
> -#endif
> -
> -#ifdef __NR_recvmmsg
> -int
> -recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
> - struct timespec *tmo)
> -{
> - return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
> -}
> -#elif defined __NR_socketcall
> -# include <socketcall.h>
> -# ifdef __ASSUME_RECVMMSG_SOCKETCALL
> int
> recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
> struct timespec *tmo)
> {
> + /* Do not use the recvmmsg syscall on socketcall architectures unless
> + it was added at the same time as the socketcall support or can be
> + assumed to be present. */
> +#if defined __ASSUME_SOCKETCALL \
> + && !defined __ASSUME_RECVMMSG_SYSCALL_WITH_SOCKETCALL \
> + && !defined __ASSUME_RECVMMSG_SYSCALL
> return SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
> -}
> -# else
> -static int have_recvmmsg;
> -
> -int
> -recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
> - struct timespec *tmo)
> -{
> - if (__glibc_likely (have_recvmmsg >= 0))
> - {
> - int ret = SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags,
> - tmo);
> - /* The kernel returns -EINVAL for unknown socket operations.
> - We need to convert that error to an ENOSYS error. */
> - if (__builtin_expect (ret < 0, 0)
> - && have_recvmmsg == 0
> - && errno == EINVAL)
> - {
> - /* Try another call, this time with an invalid file
> - descriptor and all other parameters cleared. This call
> - will not cause any harm and it will return
> - immediately. */
> - ret = SOCKETCALL_CANCEL (invalid, -1);
> - if (errno == EINVAL)
> - {
> - have_recvmmsg = -1;
> - __set_errno (ENOSYS);
> - }
> - else
> - {
> - have_recvmmsg = 1;
> - __set_errno (EINVAL);
> - }
> - return -1;
> - }
> - return ret;
> - }
> - __set_errno (ENOSYS);
> - return -1;
> -}
> -# endif /* __ASSUME_RECVMMSG_SOCKETCALL */
> #else
> -# include <socket/recvmmsg.c>
> + return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
> #endif
> +}
>
@@ -90,13 +90,7 @@
/* Support for recvmmsg functionality was added in 2.6.33. The macros
defined correspond to those for accept4. */
-#if __LINUX_KERNEL_VERSION >= 0x020621
-# ifdef __ASSUME_SOCKETCALL
-# define __ASSUME_RECVMMSG_SOCKETCALL 1
-# endif
-# define __ASSUME_RECVMMSG_SYSCALL 1
-# define __ASSUME_RECVMMSG 1
-#endif
+#define __ASSUME_RECVMMSG_SYSCALL 1
/* statfs fills in f_flags since 2.6.36. */
#if __LINUX_KERNEL_VERSION >= 0x020624
@@ -21,73 +21,21 @@
#include <sysdep-cancel.h>
#include <sys/syscall.h>
+#include <socketcall.h>
#include <kernel-features.h>
-/* Do not use the recvmmsg syscall on socketcall architectures unless
- it was added at the same time as the socketcall support or can be
- assumed to be present. */
-#if defined __ASSUME_SOCKETCALL \
- && !defined __ASSUME_RECVMMSG_SYSCALL_WITH_SOCKETCALL \
- && !defined __ASSUME_RECVMMSG_SYSCALL
-# undef __NR_recvmmsg
-#endif
-
-#ifdef __NR_recvmmsg
-int
-recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
- struct timespec *tmo)
-{
- return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
-}
-#elif defined __NR_socketcall
-# include <socketcall.h>
-# ifdef __ASSUME_RECVMMSG_SOCKETCALL
int
recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
struct timespec *tmo)
{
+ /* Do not use the recvmmsg syscall on socketcall architectures unless
+ it was added at the same time as the socketcall support or can be
+ assumed to be present. */
+#if defined __ASSUME_SOCKETCALL \
+ && !defined __ASSUME_RECVMMSG_SYSCALL_WITH_SOCKETCALL \
+ && !defined __ASSUME_RECVMMSG_SYSCALL
return SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
-}
-# else
-static int have_recvmmsg;
-
-int
-recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
- struct timespec *tmo)
-{
- if (__glibc_likely (have_recvmmsg >= 0))
- {
- int ret = SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags,
- tmo);
- /* The kernel returns -EINVAL for unknown socket operations.
- We need to convert that error to an ENOSYS error. */
- if (__builtin_expect (ret < 0, 0)
- && have_recvmmsg == 0
- && errno == EINVAL)
- {
- /* Try another call, this time with an invalid file
- descriptor and all other parameters cleared. This call
- will not cause any harm and it will return
- immediately. */
- ret = SOCKETCALL_CANCEL (invalid, -1);
- if (errno == EINVAL)
- {
- have_recvmmsg = -1;
- __set_errno (ENOSYS);
- }
- else
- {
- have_recvmmsg = 1;
- __set_errno (EINVAL);
- }
- return -1;
- }
- return ret;
- }
- __set_errno (ENOSYS);
- return -1;
-}
-# endif /* __ASSUME_RECVMMSG_SOCKETCALL */
#else
-# include <socket/recvmmsg.c>
+ return SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, tmo);
#endif
+}