Implement accept4 for more archs using socketcall.
authorJakub Jelinek <jakub@redhat.com>
Fri, 22 May 2009 15:25:34 +0000 (08:25 -0700)
committerUlrich Drepper <drepper@redhat.com>
Fri, 22 May 2009 15:25:34 +0000 (08:25 -0700)
So far accept4 was only supported on archs using socketcall for x86.
This patch adds support for the remaining archs.

ChangeLog
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/accept4.c
sysdeps/unix/sysv/linux/i386/accept4.S
sysdeps/unix/sysv/linux/internal_accept4.S [new file with mode: 0644]

index 5ff23ea..b5cc481 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-05-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/accept4.c: Include kernel-features.h.
+       (accept4): If __NR_accept4 is not defined, but __NR_socketcall
+       is, either do nothing at all if __ASSUME_ACCEPT4, or
+       call __internal_accept4 and handle EINVAL -> ENOSYS translation.
+       * sysdeps/unix/sysv/linux/internal_accept4.S: New file.
+       * sysdeps/unix/sysv/linux/i386/accept4.S (SOCKOP_accept4): Don't
+       define.
+       * sysdeps/unix/sysv/linux/i386/internal_accept4.S: New file.
+       * sysdeps/unix/sysv/linux/Makefile (sysdep-routines): Add
+       internal_accept4 in socket directory.
+
 2009-05-20  H.J. Lu  <hongjiu.lu@intel.com>
 
        * sysdeps/ia64/configure.in: New file.
index 170c042..cee5d29 100644 (file)
@@ -11,6 +11,10 @@ ifeq ($(subdir),malloc)
 CFLAGS-malloc.c += -DMORECORE_CLEARS=2
 endif
 
+ifeq ($(subdir),socket)
+sysdep_routines += internal_accept4
+endif
+
 ifeq ($(subdir),misc)
 sysdep_routines += sysctl clone llseek umount umount2 readahead \
                   setfsuid setfsgid makedev epoll_pwait signalfd \
index 4be710f..9ef9f47 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <sysdep-cancel.h>
 #include <sys/syscall.h>
+#include <kernel-features.h>
 
 
 #ifdef __NR_accept4
@@ -41,6 +42,50 @@ accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
 
   return result;
 }
+#elif defined __NR_socketcall
+# ifndef __ASSUME_ACCEPT4
+extern int __internal_accept4 (int fd, __SOCKADDR_ARG addr,
+                              socklen_t *addr_len, int flags)
+     attribute_hidden;
+
+static int have_accept4;
+
+int
+accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
+{
+  if (__builtin_expect (have_accept4 >= 0, 1))
+    {
+      int ret = __internal_accept4 (fd, addr, addr_len, flags);
+      /* 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_accept4 == 0
+         && errno == EINVAL)
+       {
+         /* Try another call, this time with the FLAGS parameter
+            cleared and an invalid file descriptor.  This call will not
+            cause any harm and it will return immediately.  */
+         ret = __internal_accept4 (-1, addr, addr_len, 0);
+         if (errno == EINVAL)
+           {
+             have_accept4 = -1;
+             __set_errno (ENOSYS);
+           }
+         else
+           {
+             have_accept4 = 1;
+             __set_errno (EINVAL);
+           }
+         return -1;
+       }
+      return ret;
+    }
+  __set_errno (ENOSYS);
+  return -1;
+}
+# else
+/* When __ASSUME_ACCEPT4 accept4 is defined in internal_accept4.S.  */
+# endif
 #else
 int
 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
index 087ccc4..1d05eff 100644 (file)
 #define EINVAL 22
 #define ENOSYS 38
 
-#ifndef SOCKOP_accept4
-# define SOCKOP_accept4 18
-#endif
-
 #ifdef __ASSUME_ACCEPT4
 # define errlabel SYSCALL_ERROR_LABEL
 #else
diff --git a/sysdeps/unix/sysv/linux/internal_accept4.S b/sysdeps/unix/sysv/linux/internal_accept4.S
new file mode 100644 (file)
index 0000000..ffc5536
--- /dev/null
@@ -0,0 +1,14 @@
+#include <kernel-features.h>
+#include <sys/syscall.h>
+#if !defined __NR_accept4 && defined __NR_socketcall
+# define socket        accept4
+# ifdef __ASSUME_ACCEPT4
+#  define __socket accept4
+# else
+#  define __socket __internal_accept4
+# endif
+# define NARGS 4
+# define NEED_CANCELLATION
+# define NO_WEAK_ALIAS
+# include <socket.S>
+#endif