* socket/sys/socket.h: Declare accept4.
authorUlrich Drepper <drepper@redhat.com>
Wed, 3 Dec 2008 04:23:18 +0000 (04:23 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 3 Dec 2008 04:23:18 +0000 (04:23 +0000)
* 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.

ChangeLog
Versions.def
nscd/connections.c
socket/Makefile
socket/Versions
socket/accept4.c [moved from socket/paccept.c with 84% similarity]
socket/sys/socket.h
sysdeps/unix/sysv/linux/accept4.c [moved from sysdeps/unix/sysv/linux/paccept.c with 73% similarity]
sysdeps/unix/sysv/linux/i386/accept4.S [moved from sysdeps/unix/sysv/linux/i386/paccept.S with 50% similarity]
sysdeps/unix/sysv/linux/i386/socket.S
sysdeps/unix/sysv/linux/kernel-features.h

index 776adcf36dbcf77f147f9a42af934c984d772822..9f8f52273d071269dcea5e3a40a14f545be34b6e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2008-12-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * 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.
+
 2008-12-01  Ulrich Drepper  <drepper@redhat.com>
 
        * resolv/res_send.c (send_dg): Create sockets with non-blocking
index 856d8780687da9dfadd6a082936a9fcc6c50cb92..031e2a3541788ea38783e9694d562b996eee3ace 100644 (file)
@@ -26,6 +26,7 @@ libc {
   GLIBC_2.7
   GLIBC_2.8
   GLIBC_2.9
+  GLIBC_2.10
 %ifdef USE_IN_LIBIO
   HURD_CTHREADS_0.3
 %endif
index e3a67386d0dd43903e68a28026fa67d285c01e8d..2b795494ea937c519911bf9c90eff56b8d23c89f 100644 (file)
@@ -238,8 +238,9 @@ static int resolv_conf_descr = -1;
 /* Negative if SOCK_CLOEXEC is not supported, positive if it is, zero
    before be know the result.  */
 static int have_sock_cloexec;
-/* The paccept syscall was introduced at the same time as SOCK_CLOEXEC.  */
-# define have_paccept -1       // XXX For the time being there is no such call
+#endif
+#ifndef __ASSUME_ACCEPT4
+static int have_accept4;
 #endif
 
 /* Number of times clients had to wait.  */
@@ -1609,8 +1610,8 @@ nscd_run_worker (void *p)
       /* We are done with the list.  */
       pthread_mutex_unlock (&readylist_lock);
 
-#ifndef __ASSUME_SOCK_CLOEXEC
-      if (have_sock_cloexec < 0)
+#ifndef __ASSUME_ACCEPT4
+      if (have_accept4 < 0)
        {
          /* We do not want to block on a short read or so.  */
          int fl = fcntl (fd, F_GETFL);
@@ -1819,22 +1820,20 @@ main_loop_poll (void)
              /* We have a new incoming connection.  Accept the connection.  */
              int fd;
 
-#ifndef __ASSUME_PACCEPT
+#ifndef __ASSUME_ACCEPT4
              fd = -1;
-             if (have_paccept >= 0)
+             if (have_accept4 >= 0)
 #endif
                {
-#if 0
-                 fd = TEMP_FAILURE_RETRY (paccept (sock, NULL, NULL, NULL,
+                 fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
                                                    SOCK_NONBLOCK));
-#ifndef __ASSUME_PACCEPT
-                 if (have_paccept == 0)
-                   have_paccept = fd != -1 || errno != ENOSYS ? 1 : -1;
-#endif
+#ifndef __ASSUME_ACCEPT4
+                 if (have_accept4 == 0)
+                   have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
 #endif
                }
-#ifndef __ASSUME_PACCEPT
-             if (have_paccept < 0)
+#ifndef __ASSUME_ACCEPT4
+             if (have_accept4 < 0)
                fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
 #endif
 
@@ -2000,7 +1999,7 @@ main_loop_epoll (int efd)
     /* We cannot use epoll.  */
     return;
 
-#ifdef HAVE_INOTIFY
+# ifdef HAVE_INOTIFY
   if (inotify_fd != -1)
     {
       ev.events = EPOLLRDNORM;
@@ -2010,7 +2009,7 @@ main_loop_epoll (int efd)
        return;
       nused = 2;
     }
-#endif
+# endif
 
   while (1)
     {
@@ -2025,8 +2024,26 @@ main_loop_epoll (int efd)
        if (revs[cnt].data.fd == sock)
          {
            /* A new connection.  */
-           int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
+           int fd;
+
+# ifndef __ASSUME_ACCEPT4
+           fd = -1;
+           if (have_accept4 >= 0)
+# endif
+             {
+               fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
+                                                 SOCK_NONBLOCK));
+# ifndef __ASSUME_ACCEPT4
+               if (have_accept4 == 0)
+                 have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
+# endif
+             }
+# ifndef __ASSUME_ACCEPT4
+           if (have_accept4 < 0)
+             fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
+# endif
 
+           /* Use the descriptor if we have not reached the limit.  */
            if (fd >= 0)
              {
                /* Try to add the  new descriptor.  */
@@ -2048,7 +2065,7 @@ main_loop_epoll (int efd)
                  }
              }
          }
-#ifdef HAVE_INOTIFY
+# ifdef HAVE_INOTIFY
        else if (revs[cnt].data.fd == inotify_fd)
          {
            bool to_clear[lastdb] = { false, };
@@ -2104,7 +2121,7 @@ main_loop_epoll (int efd)
                  pthread_cond_signal (&dbs[dbcnt].prune_cond);
                }
          }
-#endif
+# endif
        else
          {
            /* Remove the descriptor from the epoll descriptor.  */
index 92a87079e3f3c3846921d2c43ba429a63b513372..0e242b579cb116d7d89b65130acf916a72fd5eeb 100644 (file)
@@ -27,7 +27,7 @@ headers       := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \
 routines := accept bind connect getpeername getsockname getsockopt     \
            listen recv recvfrom recvmsg send sendmsg sendto            \
            setsockopt shutdown socket socketpair isfdtype opensock     \
-           sockatmark
+           sockatmark accept4
 
 aux     := have_sock_cloexec
 
index d282eff79e7344b66f949b89b8f666490bcd94c1..7a96b1e934cc6e63b1466a7513fdf0427ef19b2f 100644 (file)
@@ -31,4 +31,7 @@ libc {
     # Addition from P1003.1-200x
     sockatmark;
   }
+  GLIBC_2.10 {
+    accept4;
+  }
 }
similarity index 84%
rename from socket/paccept.c
rename to socket/accept4.c
index 777dd8c30036da6296c5bed321b82ef427073d5f..40709d5704cd41f190f35533556e767f0ccc5b81 100644 (file)
    When a connection arrives, open a new socket to communicate with it,
    set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
    peer and *ADDR_LEN to the address's actual length, and return the
-   new socket's descriptor, or -1 for errors.  SS is installed as
-   the thread's signal mask and FLAGS are additional flags.  */
+   new socket's descriptor, or -1 for errors.  The operation can be influenced
+   by the FLAGS parameter.  */
 int
-paccept (fd, addr, addr_len, ss, flags)
+accept4 (fd, addr, addr_len, flags)
      int fd;
      __SOCKADDR_ARG addr;
      socklen_t *addr_len;
-     const __sigset_t *ss;
      int flags;
 {
   __set_errno (ENOSYS);
   return -1;
 }
-libc_hidden_def (paccept)
+libc_hidden_def (accept4)
 
 
-stub_warning (paccept)
+stub_warning (accept4)
 #include <stub-tag.h>
index e0a6a5216aa2af6dc6238e330703cb593b2a1624..9b1f56f8b084139503854765a6319790ff5e25fb 100644 (file)
@@ -214,6 +214,15 @@ extern int listen (int __fd, int __n) __THROW;
 extern int accept (int __fd, __SOCKADDR_ARG __addr,
                   socklen_t *__restrict __addr_len);
 
+#ifdef __USE_GNU
+/* Similar to 'accept' but takes an additional parameter to specify flags.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW.  */
+extern int accept4 (int __fd, __SOCKADDR_ARG __addr,
+                   socklen_t *__restrict __addr_len, int __flags);
+#endif
+
 /* Shut down all or part of the connection open on socket FD.
    HOW determines what to shut down:
      SHUT_RD   = No more receptions;
similarity index 73%
rename from sysdeps/unix/sysv/linux/paccept.c
rename to sysdeps/unix/sysv/linux/accept4.c
index cc2979c0edba1c65b4ce829b74caaf8b747da79f..97f7b8ce627a14bb45a82c54d857be3562f8d805 100644 (file)
 #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
similarity index 50%
rename from sysdeps/unix/sysv/linux/i386/paccept.S
rename to sysdeps/unix/sysv/linux/i386/accept4.S
index 02ad78dd47657c1bb5f3d479928cbaf344fa4c34..087ccc456f76bded635f8da4da88d940d06bbda9 100644 (file)
@@ -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
 #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)
index 7c8ac29b86a69e3e8275d885a52cb18cc45bde59..889e5c706096fbb7e58479fdef46625c8320e4b6 100644 (file)
@@ -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
index 6031eae2d097e65aa5929297efc7a0ca2469fafc..900baf10c7cc094458e1f467e2bc842249f6b0cf 100644 (file)
 # 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