about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-05-22 08:25:34 -0700
committerUlrich Drepper <drepper@redhat.com>2009-05-22 08:25:34 -0700
commit1e1dc4e82dd4f31b87440388614c3e4bccdd5f3c (patch)
tree2222fa67e02e1b84f967a05a297794e83b21821e /sysdeps/unix
parentbe6b2e5cf302f984d8f405c0d40e7a3979c47bc3 (diff)
downloadglibc-1e1dc4e82dd4f31b87440388614c3e4bccdd5f3c.tar.gz
glibc-1e1dc4e82dd4f31b87440388614c3e4bccdd5f3c.tar.xz
glibc-1e1dc4e82dd4f31b87440388614c3e4bccdd5f3c.zip
Implement accept4 for more archs using socketcall.
So far accept4 was only supported on archs using socketcall for x86.
This patch adds support for the remaining archs.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/Makefile4
-rw-r--r--sysdeps/unix/sysv/linux/accept4.c45
-rw-r--r--sysdeps/unix/sysv/linux/i386/accept4.S4
-rw-r--r--sysdeps/unix/sysv/linux/internal_accept4.S14
4 files changed, 63 insertions, 4 deletions
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 170c042dd1..cee5d29255 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -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 \
diff --git a/sysdeps/unix/sysv/linux/accept4.c b/sysdeps/unix/sysv/linux/accept4.c
index 4be710f76d..9ef9f479b0 100644
--- a/sysdeps/unix/sysv/linux/accept4.c
+++ b/sysdeps/unix/sysv/linux/accept4.c
@@ -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)
diff --git a/sysdeps/unix/sysv/linux/i386/accept4.S b/sysdeps/unix/sysv/linux/i386/accept4.S
index 087ccc456f..1d05eff7f7 100644
--- a/sysdeps/unix/sysv/linux/i386/accept4.S
+++ b/sysdeps/unix/sysv/linux/i386/accept4.S
@@ -24,10 +24,6 @@
 #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
index 0000000000..ffc553624c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/internal_accept4.S
@@ -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