about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-12-03 04:23:18 +0000
committerUlrich Drepper <drepper@redhat.com>2008-12-03 04:23:18 +0000
commitf93fc0b75a50d3ba8d4d69313e3c84ac0b62905b (patch)
tree4199d6969f17f2e0c78e46383bd1fcfe7a2cf06f /sysdeps
parent9744268c10e9ddea5972aa50ac9bf7f778bbf7e7 (diff)
downloadglibc-f93fc0b75a50d3ba8d4d69313e3c84ac0b62905b.tar.gz
glibc-f93fc0b75a50d3ba8d4d69313e3c84ac0b62905b.tar.xz
glibc-f93fc0b75a50d3ba8d4d69313e3c84ac0b62905b.zip
* socket/sys/socket.h: Declare accept4.
	* socket/accept4.c: New file.
	* sysdeps/unix/sysv/linux/accept4.c: New file.
	* sysdeps/unix/sysv/linux/i386/accept4.S: New file.
	* socket/Makefile (routines): Add accept4.
	* socket/Versions: Export accept4 with version GLIBC_2.10.
	* socket/paccept.c: Removed.
	* sysdeps/unix/sysv/linux/paccept.c: Removed.
	* sysdeps/unix/sysv/linux/i386/paccept.S: Removed.
	* Versions.def: Define GLIBC_2.10 for libc.
	* sysdeps/unix/sysv/linux/kernel-features.h: Define __ASSUME_ACCEPT4.

	* nscd/connections.c: Use accept4.

	* sysdeps/unix/sysv/linux/i386/socket.S: Fix comment.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/sysv/linux/accept4.c (renamed from sysdeps/unix/sysv/linux/paccept.c)20
-rw-r--r--sysdeps/unix/sysv/linux/i386/accept4.S (renamed from sysdeps/unix/sysv/linux/i386/paccept.S)164
-rw-r--r--sysdeps/unix/sysv/linux/i386/socket.S4
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h8
4 files changed, 125 insertions, 71 deletions
diff --git a/sysdeps/unix/sysv/linux/paccept.c b/sysdeps/unix/sysv/linux/accept4.c
index cc2979c0ed..97f7b8ce62 100644
--- a/sysdeps/unix/sysv/linux/paccept.c
+++ b/sysdeps/unix/sysv/linux/accept4.c
@@ -24,19 +24,20 @@
 #include <sysdep-cancel.h>
 #include <sys/syscall.h>
 
-#ifdef __NR_paccept
+#define __NR_accept4                            288
+
+
+#ifdef __NR_accept4
 int
-paccept (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len,
-	 const __sigset_t *ss, int flags)
+accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
 {
   if (SINGLE_THREAD_P)
-    return INLINE_SYSCALL (paccept, 6, fd, addr.__sockaddr__, addr_len, ss,
-			   _NSIG / 8, flags);
+    return INLINE_SYSCALL (accept4, 4, fd, addr.__sockaddr__, addr_len, flags);
 
   int oldtype = LIBC_CANCEL_ASYNC ();
 
-  int result = INLINE_SYSCALL (paccept, 6, fd, addr.__sockaddr__, addr_len, ss,
-			       _NSIG / 8, flags);
+  int result = INLINE_SYSCALL (accept4, 4, fd, addr.__sockaddr__, addr_len,
+			       flags);
 
   LIBC_CANCEL_RESET (oldtype);
 
@@ -44,11 +45,10 @@ paccept (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len,
 }
 #else
 int
-paccept (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len,
-	 const __sigset_t *ss, int flags)
+accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
 {
   __set_errno (ENOSYS);
   return -1;
-stub_warning (epoll_pwait)
 }
+stub_warning (accept4)
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/paccept.S b/sysdeps/unix/sysv/linux/i386/accept4.S
index 02ad78dd47..087ccc456f 100644
--- a/sysdeps/unix/sysv/linux/i386/paccept.S
+++ b/sysdeps/unix/sysv/linux/i386/accept4.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-1998,2002,2003,2005,2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995-1998,2002,2003,2005, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -19,67 +19,33 @@
 #include <sysdep-cancel.h>
 #include <socketcall.h>
 #include <tls.h>
+#include <kernel-features.h>
 
-#define _NSIG 64
+#define EINVAL	22
+#define ENOSYS	38
 
-#define P(a, b) P2(a, b)
-#define P2(a, b) a##b
+#ifndef SOCKOP_accept4
+# define SOCKOP_accept4 18
+#endif
+
+#ifdef __ASSUME_ACCEPT4
+# define errlabel SYSCALL_ERROR_LABEL
+#else
+# define errlabel .Lerr
+	.data
+have_accept4:
+	.long	0
+#endif
 
 	.text
-/* The socket-oriented system calls are handled unusally in Linux.
+/* The socket-oriented system calls are handled unusally in Linux/i386.
    They are all gated through the single `socketcall' system call number.
    `socketcall' takes two arguments: the first is the subcode, specifying
    which socket function is being called; and the second is a pointer to
    the arguments to the specific function.  */
 
-ENTRY(do_paccept)
-#ifdef SOCKOP_paccept
-	subl $6*4, %esp
-	cfi_adjust_cfa_offset(6*4)
-
-	movl (%eax), %ecx
-	movl %ecx, (%esp)
-	movl 4(%eax), %ecx
-	movl %ecx, 4(%esp)
-	movl 8(%eax), %ecx
-	movl %ecx, 8(%esp)
-	movl 12(%eax), %ecx
-	movl %ecx, 12(%esp)
-	movl $(_NSIG / 8), 16(%esp)
-	movl 16(%eax), %ecx
-	movl %ecx, 20(%esp)
-
-	movl $SYS_ify(socketcall), %eax	/* System call number in %eax.  */
-
-	movl $SOCKOP_paccept, %ebx	/* Subcode is first arg to syscall.  */
-	movl %esp, %ecx			/* Address of args is 2nd arg.  */
-
-        /* Do the system call trap.  */
-	ENTER_KERNEL
-
-	addl $6*4, %esp
-	cfi_adjust_cfa_offset(-6*4)
-
-	/* %eax is < 0 if there was an error.  */
-	cmpl $-125, %eax
-	jae SYSCALL_ERROR_LABEL
-#else
-	movl $-ENOSYS, %eax
-	jmp SYSCALL_ERROR_LABEL
-
-	.section .gnu.glibc-stub.paccept
-	.previous
-	.section .gnu.warning.paccept
-	.string "warning: paccept is not implemented and will always fail"
-	.previous
-#endif
-L(pseudo_end):
-	ret
-PSEUDO_END(do_paccept)
-
-
-	.globl paccept
-ENTRY (paccept)
+.globl __libc_accept4
+ENTRY (__libc_accept4)
 #ifdef CENABLE
 	SINGLE_THREAD_P
 	jne 1f
@@ -89,15 +55,27 @@ ENTRY (paccept)
 	movl %ebx, %edx
 	cfi_register (3, 2)
 
-	lea 4(%esp), %eax
-	call do_paccept
+	movl $SYS_ify(socketcall), %eax	/* System call number in %eax.  */
+
+	movl $SOCKOP_accept4, %ebx	/* Subcode is first arg to syscall.  */
+	lea 4(%esp), %ecx		/* Address of args is 2nd arg.  */
+
+        /* Do the system call trap.  */
+	ENTER_KERNEL
 
 	/* Restore registers.  */
 	movl %edx, %ebx
 	cfi_restore (3)
 
+	/* %eax is < 0 if there was an error.  */
+	cmpl $-125, %eax
+	jae errlabel
+
+	/* Successful; return the syscall's value.  */
+L(pseudo_end):
 	ret
 
+
 #ifdef CENABLE
 	/* We need one more register.  */
 1:	pushl %esi
@@ -112,8 +90,13 @@ ENTRY (paccept)
 	movl %ebx, %edx
 	cfi_register (3, 2)
 
-	lea 8(%esp), %eax
-	call do_paccept
+	movl $SYS_ify(socketcall), %eax	/* System call number in %eax.  */
+
+	movl $SOCKOP_accept4, %ebx	/* Subcode is first arg to syscall.  */
+	lea 8(%esp), %ecx		/* Address of args is 2nd arg.  */
+
+        /* Do the system call trap.  */
+	ENTER_KERNEL
 
 	/* Restore registers.  */
 	movl %edx, %ebx
@@ -129,7 +112,72 @@ ENTRY (paccept)
 	cfi_restore (6)
 	cfi_adjust_cfa_offset(-4)
 
+	/* %eax is < 0 if there was an error.  */
+	cmpl $-125, %eax
+	jae errlabel
+
 	/* Successful; return the syscall's value.  */
 	ret
 #endif
-PSEUDO_END (paccept)
+
+#ifndef __ASSUME_ACCEPT4
+	/* The kernel returns -EINVAL for unknown socket operations.
+	   We need to convert that error to an ENOSYS error.  */
+.Lerr:	cmpl $-EINVAL, %eax
+	jne SYSCALL_ERROR_LABEL
+
+	/* Save registers.  */
+	pushl %ebx
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(ebx, -8)
+
+# ifdef PIC
+	SETUP_PIC_REG (dx)
+	addl $_GLOBAL_OFFSET_TABLE_, %edx
+	movl have_accept4@GOTOFF(%edx), %eax
+# else
+	movl have_accept4, %eax
+# endif
+	testl %eax, %eax
+	jne 1f
+
+	/* 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.  */
+	movl $-1, 8(%esp)
+	movl $0, 20(%esp)
+
+	movl $SYS_ify(socketcall), %eax	/* System call number in %eax.  */
+
+	movl $SOCKOP_accept4, %ebx	/* Subcode is first arg to syscall.  */
+	lea 8(%esp), %ecx		/* Address of args is 2nd arg.  */
+
+        /* Do the system call trap.  */
+	ENTER_KERNEL
+
+	cmpl $-EINVAL, %eax
+	movl $-1, %eax
+	je 3f
+	movl $1, %eax
+3:
+# ifdef PIC
+	movl %eax, have_accept4@GOTOFF(%edx)
+# else
+	movl %eax, have_accept4
+# endif
+
+	testl %eax, %eax
+
+1:	movl $-EINVAL, %eax
+	jns 2f
+	movl $-ENOSYS, %eax
+
+	/* Restore registers.  */
+2:	popl %ebx
+	cfi_restore (ebx)
+
+	jmp SYSCALL_ERROR_LABEL
+#endif
+PSEUDO_END (__libc_accept4)
+
+weak_alias (__libc_accept4, accept4)
diff --git a/sysdeps/unix/sysv/linux/i386/socket.S b/sysdeps/unix/sysv/linux/i386/socket.S
index 7c8ac29b86..889e5c7060 100644
--- a/sysdeps/unix/sysv/linux/i386/socket.S
+++ b/sysdeps/unix/sysv/linux/i386/socket.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-1998,2002,2003,2005 Free Software Foundation, Inc.
+/* Copyright (C) 1995-1998,2002,2003,2005,2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@
 #define P2(a, b) a##b
 
 	.text
-/* The socket-oriented system calls are handled unusally in Linux.
+/* The socket-oriented system calls are handled unusally in Linux/i386.
    They are all gated through the single `socketcall' system call number.
    `socketcall' takes two arguments: the first is the subcode, specifying
    which socket function is being called; and the second is a pointer to
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 6031eae2d0..900baf10c7 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -509,5 +509,11 @@
 # define __ASSUME_SOCK_CLOEXEC	1
 # define __ASSUME_IN_NONBLOCK	1
 # define __ASSUME_PIPE2		1
-# define __ASSUME_PACCEPT	1
+#endif
+
+/* Support for the accept4 syscall was added in 2.6.28.  */
+#if __LINUX_KERNEL_VERSION >= 0x02061b \
+    && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \
+	|| defined __ia64__ || defined __sparc__ || __s390__)
+# define __ASSUME_ACCEPT4	1
 #endif