about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r--sysdeps/unix/sysv/linux/accept.S1
-rw-r--r--sysdeps/unix/sysv/linux/connect.S1
-rw-r--r--sysdeps/unix/sysv/linux/i386/fcntl.c46
-rw-r--r--sysdeps/unix/sysv/linux/i386/socket.S56
-rw-r--r--sysdeps/unix/sysv/linux/llseek.c23
-rw-r--r--sysdeps/unix/sysv/linux/msgrcv.c15
-rw-r--r--sysdeps/unix/sysv/linux/msgsnd.c16
-rw-r--r--sysdeps/unix/sysv/linux/open64.c53
-rw-r--r--sysdeps/unix/sysv/linux/poll.c50
-rw-r--r--sysdeps/unix/sysv/linux/pread.c30
-rw-r--r--sysdeps/unix/sysv/linux/pread64.c32
-rw-r--r--sysdeps/unix/sysv/linux/pwrite.c35
-rw-r--r--sysdeps/unix/sysv/linux/pwrite64.c30
-rw-r--r--sysdeps/unix/sysv/linux/readv.c25
-rw-r--r--sysdeps/unix/sysv/linux/recv.S1
-rw-r--r--sysdeps/unix/sysv/linux/recvfrom.S1
-rw-r--r--sysdeps/unix/sysv/linux/recvmsg.S1
-rw-r--r--sysdeps/unix/sysv/linux/send.S1
-rw-r--r--sysdeps/unix/sysv/linux/sendmsg.S1
-rw-r--r--sysdeps/unix/sysv/linux/sendto.S1
-rw-r--r--sysdeps/unix/sysv/linux/sigsuspend.c45
-rw-r--r--sysdeps/unix/sysv/linux/sigtimedwait.c18
-rw-r--r--sysdeps/unix/sysv/linux/sigwait.c25
-rw-r--r--sysdeps/unix/sysv/linux/sigwaitinfo.c18
-rw-r--r--sysdeps/unix/sysv/linux/tcdrain.c16
-rw-r--r--sysdeps/unix/sysv/linux/wait.c48
-rw-r--r--sysdeps/unix/sysv/linux/waitpid.c16
-rw-r--r--sysdeps/unix/sysv/linux/writev.c27
28 files changed, 527 insertions, 105 deletions
diff --git a/sysdeps/unix/sysv/linux/accept.S b/sysdeps/unix/sysv/linux/accept.S
index 431dec0324..75d57368bc 100644
--- a/sysdeps/unix/sysv/linux/accept.S
+++ b/sysdeps/unix/sysv/linux/accept.S
@@ -1,4 +1,5 @@
 #define	socket	accept
 #define	__socket __libc_accept
 #define	NARGS	3
+#define NEED_CANCELLATION
 #include <socket.S>
diff --git a/sysdeps/unix/sysv/linux/connect.S b/sysdeps/unix/sysv/linux/connect.S
index 2de35180fc..7d1fa12b34 100644
--- a/sysdeps/unix/sysv/linux/connect.S
+++ b/sysdeps/unix/sysv/linux/connect.S
@@ -1,6 +1,7 @@
 #define	socket	connect
 #define __socket __libc_connect
 #define	NARGS	3
+#define NEED_CANCELLATION
 #include <socket.S>
 strong_alias (__libc_connect, __connect_internal)
 weak_alias (__libc_connect, __connect)
diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c
index 12bb291381..4ff5ee35b8 100644
--- a/sysdeps/unix/sysv/linux/i386/fcntl.c
+++ b/sysdeps/unix/sysv/linux/i386/fcntl.c
@@ -21,7 +21,7 @@
 #include <fcntl.h>
 #include <stdarg.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include "../kernel-features.h"
 
@@ -33,21 +33,11 @@ extern int __syscall_fcntl64 (int __fd, int __cmd, ...);
 #if __ASSUME_FCNTL64 == 0
 /* This variable is shared with all files that check for fcntl64.  */
 int __have_no_fcntl64;
-#endif
+
 
 int
 __libc_fcntl (int fd, int cmd, ...)
 {
-  va_list ap;
-  void *arg;
-
-  va_start (ap, cmd);
-  arg = va_arg (ap, void *);
-  va_end (ap);
-
-#if __ASSUME_FCNTL64 > 0
-  return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
-#else
 # ifdef __NR_fcntl64
   if (! __have_no_fcntl64)
     {
@@ -128,7 +118,39 @@ __libc_fcntl (int fd, int cmd, ...)
       return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);
     }
   return -1;
+}
 #endif  /* __ASSUME_FCNTL64  */
+
+
+int
+__libc_fcntl (int fd, int cmd, ...)
+{
+  va_list ap;
+  void *arg;
+
+  va_start (ap, cmd);
+  arg = va_arg (ap, void *);
+  va_end (ap);
+
+#if __ASSUME_FCNTL64 > 0
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+#else
+  if (SINGLE_THREAD_P)
+    return do_fcntl (fd, cmd, arg);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_fcntl (fd, cmd, arg);
+#endif
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 libc_hidden_def (__libc_fcntl)
 
diff --git a/sysdeps/unix/sysv/linux/i386/socket.S b/sysdeps/unix/sysv/linux/i386/socket.S
index d0607921ed..866a67462d 100644
--- a/sysdeps/unix/sysv/linux/i386/socket.S
+++ b/sysdeps/unix/sysv/linux/i386/socket.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 2002 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
@@ -16,8 +16,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <socketcall.h>
+#include <tls.h>
 
 #define P(a, b) P2(a, b)
 #define P2(a, b) a##b
@@ -32,15 +33,19 @@
    The .S files for the other calls just #define socket and #include this.  */
 
 #ifndef __socket
-#ifndef NO_WEAK_ALIAS
-#define __socket P(__,socket)
-#else
-#define __socket socket
-#endif
+# ifndef NO_WEAK_ALIAS
+#  define __socket P(__,socket)
+# else
+#  define __socket socket
+# endif
 #endif
 
 .globl __socket
 ENTRY (__socket)
+#if defined NEED_CANCELLATION && defined CENABLE
+	cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
+	jne 1f
+#endif
 
 	/* Save registers.  */
 	movl %ebx, %edx
@@ -65,6 +70,43 @@ ENTRY (__socket)
 L(pseudo_end):
 	ret
 
+
+#if defined NEED_CANCELLATION && defined CENABLE
+	/* We need one more register.  */
+1:	pushl %esi
+
+	/* Enable asynchronous cancellation.  */
+	call __libc_enable_asynccancel	/* No @plt */
+	movl %eax, %esi
+
+	/* Save registers.  */
+	movl %ebx, %edx
+
+	movl $SYS_ify(socketcall), %eax	/* System call number in %eax.  */
+
+	/* Use ## so `socket' is a separate token that might be #define'd.  */
+	movl $P(SOCKOP_,socket), %ebx	/* Subcode is first arg to syscall.  */
+	lea 8(%esp), %ecx		/* Address of args is 2nd arg.  */
+
+        /* Do the system call trap.  */
+	int $0x80
+
+	/* Restore the cancellation.  */
+	xchgl %esi, %eax
+	call __libc_disable_asynccancel	/* No @plt */
+
+	/* Restore registers.  */
+	movl %esi, %eax
+	movl %edx, %ebx
+	popl %esi
+
+	/* %eax is < 0 if there was an error.  */
+	cmpl $-125, %eax
+	jae SYSCALL_ERROR_LABEL
+
+	/* Successful; return the syscall's value.  */
+	ret
+#endif
 PSEUDO_END (__socket)
 
 #ifndef NO_WEAK_ALIAS
diff --git a/sysdeps/unix/sysv/linux/llseek.c b/sysdeps/unix/sysv/linux/llseek.c
index fa83f1057c..9ee340d476 100644
--- a/sysdeps/unix/sysv/linux/llseek.c
+++ b/sysdeps/unix/sysv/linux/llseek.c
@@ -1,5 +1,5 @@
 /* Long-long seek operation.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1996,1997,1998,1999,2000,2002 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
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <sys/types.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 
 extern int __syscall__llseek (int fd, off_t offset_hi, off_t offset_lo,
@@ -32,11 +32,22 @@ extern loff_t __llseek (int fd, loff_t offset, int whence);
 loff_t
 __llseek (int fd, loff_t offset, int whence)
 {
-  loff_t result;
+  loff_t retval;
 
-  return (loff_t) (INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32),
-				   (off_t) (offset & 0xffffffff),
-				   __ptrvalue (&result), whence) ?: result);
+  if (SINGLE_THREAD_P)
+    return (loff_t) (INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32),
+				     (off_t) (offset & 0xffffffff),
+				     __ptrvalue (&retval), whence) ?: retval);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = (loff_t) INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32),
+					(off_t) (offset & 0xffffffff),
+					__ptrvalue (&retval), whence);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return (loff_t) result ?: retval;
 }
 weak_alias (__llseek, llseek)
 strong_alias (__llseek, __libc_lseek64)
diff --git a/sysdeps/unix/sysv/linux/msgrcv.c b/sysdeps/unix/sysv/linux/msgrcv.c
index fdc13ff0fa..7d8a8e7859 100644
--- a/sysdeps/unix/sysv/linux/msgrcv.c
+++ b/sysdeps/unix/sysv/linux/msgrcv.c
@@ -21,7 +21,7 @@
 #include <sys/msg.h>
 #include <ipc_priv.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 
 #include <bp-checks.h>
@@ -50,6 +50,17 @@ __libc_msgrcv (msqid, msgp, msgsz, msgtyp, msgflg)
   tmp.msgp = CHECK_N (msgp, msgsz);
   tmp.msgtyp = msgtyp;
 
-  return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, __ptrvalue (&tmp));
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg,
+			   __ptrvalue (&tmp));
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg,
+			       __ptrvalue (&tmp));
+
+   LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_msgrcv, msgrcv)
diff --git a/sysdeps/unix/sysv/linux/msgsnd.c b/sysdeps/unix/sysv/linux/msgsnd.c
index 7beba6b198..c2031be71f 100644
--- a/sysdeps/unix/sysv/linux/msgsnd.c
+++ b/sysdeps/unix/sysv/linux/msgsnd.c
@@ -21,7 +21,7 @@
 #include <sys/msg.h>
 #include <ipc_priv.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 
 #include <bp-checks.h>
@@ -33,7 +33,17 @@ __libc_msgsnd (msqid, msgp, msgsz, msgflg)
      size_t msgsz;
      int msgflg;
 {
-  return INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz,
-			 msgflg, (void *) CHECK_N (msgp, msgsz));
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz,
+			   msgflg, (void *) CHECK_N (msgp, msgsz));
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz,
+			       msgflg, (void *) CHECK_N (msgp, msgsz));
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_msgsnd, msgsnd)
diff --git a/sysdeps/unix/sysv/linux/open64.c b/sysdeps/unix/sysv/linux/open64.c
new file mode 100644
index 0000000000..5fb5363e1e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/open64.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1991,1995-1997,1999,2000,2002 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <bp-sym.h>
+#include <sysdep-cancel.h>
+
+/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+   a third argument is the file protection.  */
+int
+__libc_open64 (const char *file, int oflag, ...)
+{
+  int mode = 0;
+
+  if (oflag & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+weak_alias (__libc_open64, BP_SYM (__open64))
+libc_hidden_weak (BP_SYM (__open64))
+weak_alias (__libc_open64, BP_SYM (open64))
diff --git a/sysdeps/unix/sysv/linux/poll.c b/sysdeps/unix/sysv/linux/poll.c
index 296893d4ca..c136c21dbd 100644
--- a/sysdeps/unix/sysv/linux/poll.c
+++ b/sysdeps/unix/sysv/linux/poll.c
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <sys/poll.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -36,20 +36,19 @@ static int __emulate_poll (struct pollfd *fds, nfds_t nfds,
 			   int timeout) internal_function;
 # endif
 
-/* The real implementation.  */
-int
-__poll (fds, nfds, timeout)
-     struct pollfd *fds;
-     nfds_t nfds;
-     int timeout;
-{
+
 # if __ASSUME_POLL_SYSCALL == 0
+/* For loser kernels.  */
+static int
+loser_poll (struct pollfd *fds, nfds_t nfds, int timeout)
+{
   static int must_emulate;
 
   if (!must_emulate)
     {
       int errno_saved = errno;
-      int retval = INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout);
+      int retval = INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds,
+				   timeout);
 
       if (retval >= 0 || errno != ENOSYS)
 	return retval;
@@ -59,8 +58,39 @@ __poll (fds, nfds, timeout)
     }
 
   return __emulate_poll (fds, nfds, timeout);
+}
+# endif
+
+
+/* The real implementation.  */
+int
+__poll (fds, nfds, timeout)
+     struct pollfd *fds;
+     nfds_t nfds;
+     int timeout;
+{
+# if __ASSUME_POLL_SYSCALL == 0
+  if (SINGLE_THREAD_P)
+    return loser_poll (CHECK_N (fds, nfds), nfds, timeout);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = loser_poll (CHECK_N (fds, nfds), nfds, timeout);
+
+   LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 # else
-  return INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout);
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout);
+
+   LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 # endif
 }
 libc_hidden_def (__poll)
diff --git a/sysdeps/unix/sysv/linux/pread.c b/sysdeps/unix/sysv/linux/pread.c
index 31abf7e886..a506c17e95 100644
--- a/sysdeps/unix/sysv/linux/pread.c
+++ b/sysdeps/unix/sysv/linux/pread.c
@@ -22,7 +22,7 @@
 #include <endian.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -47,12 +47,8 @@ static ssize_t __emulate_pread (int fd, void *buf, size_t count,
 # endif
 
 
-ssize_t
-__libc_pread (fd, buf, count, offset)
-     int fd;
-     void *buf;
-     size_t count;
-     off_t offset;
+static ssize_t
+do_pread (int fd, void *buf, size_t count, off_t offset)
 {
   ssize_t result;
 
@@ -69,6 +65,26 @@ __libc_pread (fd, buf, count, offset)
   return result;
 }
 
+
+ssize_t
+__libc_pread (fd, buf, count, offset)
+     int fd;
+     void *buf;
+     size_t count;
+     off_t offset;
+{
+  if (SINGLE_THREAD_P)
+    return do_pread (fd, buf, count, offset);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = do_pread (fd, buf, count, offset);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
 strong_alias (__libc_pread, __pread)
 weak_alias (__libc_pread, pread)
 
diff --git a/sysdeps/unix/sysv/linux/pread64.c b/sysdeps/unix/sysv/linux/pread64.c
index d27f9afad9..61ff7f5dd4 100644
--- a/sysdeps/unix/sysv/linux/pread64.c
+++ b/sysdeps/unix/sysv/linux/pread64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -21,7 +21,7 @@
 #include <endian.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -45,12 +45,8 @@ static ssize_t __emulate_pread64 (int fd, void *buf, size_t count,
 # endif
 
 
-ssize_t
-__libc_pread64 (fd, buf, count, offset)
-     int fd;
-     void *buf;
-     size_t count;
-     off64_t offset;
+static ssize_t
+do_pread64 (int fd, void *buf, size_t count, off64_t offset)
 {
   ssize_t result;
 
@@ -67,6 +63,26 @@ __libc_pread64 (fd, buf, count, offset)
   return result;
 }
 
+
+ssize_t
+__libc_pread64 (fd, buf, count, offset)
+     int fd;
+     void *buf;
+     size_t count;
+     off64_t offset;
+{
+  if (SINGLE_THREAD_P)
+    return do_pread64 (fd, buf, count, offset);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = do_pread64 (fd, buf, count, offset);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
 weak_alias (__libc_pread64, __pread64)
 weak_alias (__libc_pread64, pread64)
 
diff --git a/sysdeps/unix/sysv/linux/pwrite.c b/sysdeps/unix/sysv/linux/pwrite.c
index 13bbc76b3e..af4ac362b8 100644
--- a/sysdeps/unix/sysv/linux/pwrite.c
+++ b/sysdeps/unix/sysv/linux/pwrite.c
@@ -22,7 +22,7 @@
 #include <endian.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -38,8 +38,9 @@
 #if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0
 
 /* The order of hi, lo depends on endianness.  */
-extern ssize_t __syscall_pwrite (int fd, const void *__unbounded buf, size_t count,
-				 off_t offset_hi, off_t offset_lo);
+extern ssize_t __syscall_pwrite (int fd, const void *__unbounded buf,
+				 size_t count, off_t offset_hi,
+				 off_t offset_lo);
 
 # if __ASSUME_PWRITE_SYSCALL == 0
 static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count,
@@ -47,12 +48,8 @@ static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count,
 # endif
 
 
-ssize_t
-__libc_pwrite (fd, buf, count, offset)
-     int fd;
-     const void *buf;
-     size_t count;
-     off_t offset;
+static ssize_t
+do_pwrite (int fd, const void *buf, size_t count, off_t offset)
 {
   ssize_t result;
 
@@ -69,6 +66,26 @@ __libc_pwrite (fd, buf, count, offset)
   return result;
 }
 
+
+ssize_t
+__libc_pwrite (fd, buf, count, offset)
+     int fd;
+     const void *buf;
+     size_t count;
+     off_t offset;
+{
+  if (SINGLE_THREAD_P)
+    return do_pwrite (fd, buf, count, offset);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = do_pwrite (fd, buf, count, offset);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
 strong_alias (__libc_pwrite, __pwrite)
 weak_alias (__libc_pwrite, pwrite)
 
diff --git a/sysdeps/unix/sysv/linux/pwrite64.c b/sysdeps/unix/sysv/linux/pwrite64.c
index dc81cd6b31..91f48951b0 100644
--- a/sysdeps/unix/sysv/linux/pwrite64.c
+++ b/sysdeps/unix/sysv/linux/pwrite64.c
@@ -21,7 +21,7 @@
 #include <endian.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -45,12 +45,8 @@ static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count,
 # endif
 
 
-ssize_t
-__libc_pwrite64 (fd, buf, count, offset)
-     int fd;
-     const void *buf;
-     size_t count;
-     off64_t offset;
+static ssize_t
+do_pwrite64 (int fd, const void *buf, size_t count, off64_t offset)
 {
   ssize_t result;
 
@@ -67,6 +63,26 @@ __libc_pwrite64 (fd, buf, count, offset)
   return result;
 }
 
+
+ssize_t
+__libc_pwrite64 (fd, buf, count, offset)
+     int fd;
+     const void *buf;
+     size_t count;
+     off64_t offset;
+{
+  if (SINGLE_THREAD_P)
+    return do_pwrite64 (fd, buf, count, offset);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = do_pwrite64 (fd, buf, count, offset);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
 weak_alias (__libc_pwrite64, __pwrite64)
 libc_hidden_weak (__pwrite64)
 weak_alias (__libc_pwrite64, pwrite64)
diff --git a/sysdeps/unix/sysv/linux/readv.c b/sysdeps/unix/sysv/linux/readv.c
index eeba46a09d..e6f9fb0c4e 100644
--- a/sysdeps/unix/sysv/linux/readv.c
+++ b/sysdeps/unix/sysv/linux/readv.c
@@ -22,7 +22,7 @@
 #include <sys/param.h>
 #include <sys/uio.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -39,8 +39,8 @@ static ssize_t __atomic_readv_replacement (int, __const struct iovec *,
 
 /* We should deal with kernel which have a smaller UIO_FASTIOV as well
    as a very big count.  */
-ssize_t
-__libc_readv (fd, vector, count)
+static ssize_t
+do_readv (fd, vector, count)
      int fd;
      const struct iovec *vector;
      int count;
@@ -54,6 +54,25 @@ __libc_readv (fd, vector, count)
 
   return __atomic_readv_replacement (fd, vector, count);
 }
+
+
+ssize_t
+__libc_readv (fd, vector, count)
+     int fd;
+     const struct iovec *vector;
+     int count;
+{
+  if (SINGLE_THREAD_P)
+    return do_readv (fd, vector, count);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_readv (fd, vector, count);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 strong_alias (__libc_readv, __readv)
 weak_alias (__libc_readv, readv)
 
diff --git a/sysdeps/unix/sysv/linux/recv.S b/sysdeps/unix/sysv/linux/recv.S
index cb9eb91b8c..331844abc1 100644
--- a/sysdeps/unix/sysv/linux/recv.S
+++ b/sysdeps/unix/sysv/linux/recv.S
@@ -1,5 +1,6 @@
 #define	socket	recv
 #define	__socket __libc_recv
 #define	NARGS	4
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_recv, __recv)
diff --git a/sysdeps/unix/sysv/linux/recvfrom.S b/sysdeps/unix/sysv/linux/recvfrom.S
index 93a3110d0a..ccbb0a75da 100644
--- a/sysdeps/unix/sysv/linux/recvfrom.S
+++ b/sysdeps/unix/sysv/linux/recvfrom.S
@@ -1,5 +1,6 @@
 #define	socket	recvfrom
 #define	__socket __libc_recvfrom
 #define	NARGS	6
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_recvfrom, __recvfrom)
diff --git a/sysdeps/unix/sysv/linux/recvmsg.S b/sysdeps/unix/sysv/linux/recvmsg.S
index 98be36be5b..d44bc39f92 100644
--- a/sysdeps/unix/sysv/linux/recvmsg.S
+++ b/sysdeps/unix/sysv/linux/recvmsg.S
@@ -1,5 +1,6 @@
 #define	socket	recvmsg
 #define	__socket __libc_recvmsg
 #define	NARGS	3
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_recvmsg, __recvmsg)
diff --git a/sysdeps/unix/sysv/linux/send.S b/sysdeps/unix/sysv/linux/send.S
index 83d5938223..259748f44c 100644
--- a/sysdeps/unix/sysv/linux/send.S
+++ b/sysdeps/unix/sysv/linux/send.S
@@ -1,6 +1,7 @@
 #define	socket	send
 #define	__socket __libc_send
 #define	NARGS	4
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_send, __send)
 libc_hidden_def (__send)
diff --git a/sysdeps/unix/sysv/linux/sendmsg.S b/sysdeps/unix/sysv/linux/sendmsg.S
index c01d9b68e7..a220894cc6 100644
--- a/sysdeps/unix/sysv/linux/sendmsg.S
+++ b/sysdeps/unix/sysv/linux/sendmsg.S
@@ -1,5 +1,6 @@
 #define	socket	sendmsg
 #define	__socket __libc_sendmsg
 #define	NARGS	3
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_sendmsg, __sendmsg)
diff --git a/sysdeps/unix/sysv/linux/sendto.S b/sysdeps/unix/sysv/linux/sendto.S
index 8717b2bac1..a65e44fb61 100644
--- a/sysdeps/unix/sysv/linux/sendto.S
+++ b/sysdeps/unix/sysv/linux/sendto.S
@@ -1,5 +1,6 @@
 #define	socket	sendto
 #define	__socket __libc_sendto
 #define	NARGS	6
+#define NEED_CANCELLATION
 #include <socket.S>
 weak_alias (__libc_sendto, __sendto)
diff --git a/sysdeps/unix/sysv/linux/sigsuspend.c b/sysdeps/unix/sysv/linux/sigsuspend.c
index 443c855d6c..71c2baeda5 100644
--- a/sysdeps/unix/sysv/linux/sigsuspend.c
+++ b/sysdeps/unix/sysv/linux/sigsuspend.c
@@ -20,7 +20,7 @@
 #include <signal.h>
 #include <unistd.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -30,20 +30,15 @@ extern int __syscall_sigsuspend (int, unsigned long int, unsigned long int);
 extern int __syscall_rt_sigsuspend (const sigset_t *__unbounded, size_t);
 
 
+#if !__ASSUME_REALTIME_SIGNALS
 /* The variable is shared between all wrappers around signal handling
    functions which have RT equivalents.  The definition is in sigaction.c.  */
 extern int __libc_missing_rt_sigs;
 
 
-/* Change the set of blocked signals to SET,
-   wait until a signal arrives, and restore the set of blocked signals.  */
-int
-__sigsuspend (set)
-     const sigset_t *set;
+static int
+do_sigsuspend (const sigset_t *set)
 {
-#if __ASSUME_REALTIME_SIGNALS
-  return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8);
-#else
 # ifdef __NR_rt_sigsuspend
   /* First try the RT signals.  */
   if (!__libc_missing_rt_sigs)
@@ -62,6 +57,38 @@ __sigsuspend (set)
 # endif
 
   return INLINE_SYSCALL (sigsuspend, 3, 0, 0, set->__val[0]);
+}
+#endif
+
+/* Change the set of blocked signals to SET,
+   wait until a signal arrives, and restore the set of blocked signals.  */
+int
+__sigsuspend (set)
+     const sigset_t *set;
+{
+#if __ASSUME_REALTIME_SIGNALS
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set),
+			       _NSIG / 8);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+#else
+  if (SINGLE_THREAD_P)
+    return do_sigsuspend (set);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_sigsuspend (set);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 #endif
 }
 libc_hidden_def (__sigsuspend)
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index c374287ea6..5ace26102c 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -19,7 +19,7 @@
 #include <errno.h>
 #include <signal.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -35,10 +35,22 @@ __sigtimedwait (set, info, timeout)
      siginfo_t *info;
      const struct timespec *timeout;
 {
+  if (SINGLE_THREAD_P)
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+    return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+			   CHECK_1 (info), timeout, _NSIG / 8);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
-			 CHECK_1 (info), timeout, _NSIG / 8);
+  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+			       CHECK_1 (info), timeout, _NSIG / 8);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
diff --git a/sysdeps/unix/sysv/linux/sigwait.c b/sysdeps/unix/sysv/linux/sigwait.c
index 78e58524d5..f99c64056f 100644
--- a/sysdeps/unix/sysv/linux/sigwait.c
+++ b/sysdeps/unix/sysv/linux/sigwait.c
@@ -21,7 +21,7 @@
 #define __need_NULL
 #include <stddef.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -31,10 +31,8 @@ extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__
 
 
 /* Return any pending signal or wait for one for the given time.  */
-int
-__sigwait (set, sig)
-     const sigset_t *set;
-     int *sig;
+static int
+do_sigwait (const sigset_t *set, int *sig)
 {
   int ret;
 
@@ -64,6 +62,23 @@ __sigwait (set, sig)
 
   return ret;
 }
+
+int
+__sigwait (set, sig)
+     const sigset_t *set;
+     int *sig;
+{
+  if (SINGLE_THREAD_P)
+    return do_sigwait (set, sig);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_sigwait (set, sig);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
 #else
diff --git a/sysdeps/unix/sysv/linux/sigwaitinfo.c b/sysdeps/unix/sysv/linux/sigwaitinfo.c
index d1e7a8da28..102b924904 100644
--- a/sysdeps/unix/sysv/linux/sigwaitinfo.c
+++ b/sysdeps/unix/sysv/linux/sigwaitinfo.c
@@ -21,7 +21,7 @@
 #define __need_NULL
 #include <stddef.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -36,10 +36,22 @@ __sigwaitinfo (set, info)
      const sigset_t *set;
      siginfo_t *info;
 {
+  if (SINGLE_THREAD_P)
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+    return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+			   CHECK_1 (info), NULL, _NSIG / 8);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
-			 CHECK_1 (info), NULL, _NSIG / 8);
+  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+			       CHECK_1 (info), NULL, _NSIG / 8);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 libc_hidden_def (__sigwaitinfo)
 weak_alias (__sigwaitinfo, sigwaitinfo)
diff --git a/sysdeps/unix/sysv/linux/tcdrain.c b/sysdeps/unix/sysv/linux/tcdrain.c
index a7234b07f1..4868565ed1 100644
--- a/sysdeps/unix/sysv/linux/tcdrain.c
+++ b/sysdeps/unix/sysv/linux/tcdrain.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 2002 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
@@ -16,14 +16,26 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
 #include <termios.h>
 #include <sys/ioctl.h>
+#include <sysdep-cancel.h>
 
 /* Wait for pending output to be written on FD.  */
 int
 __libc_tcdrain (int fd)
 {
+  if (SINGLE_THREAD_P)
+    /* With an argument of 1, TCSBRK for output to be drain.  */
+    return INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
   /* With an argument of 1, TCSBRK for output to be drain.  */
-  return __ioctl (fd, TCSBRK, 1);
+  int result = INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_tcdrain, tcdrain)
diff --git a/sysdeps/unix/sysv/linux/wait.c b/sysdeps/unix/sysv/linux/wait.c
index 79d54580fd..f01d75cc38 100644
--- a/sysdeps/unix/sysv/linux/wait.c
+++ b/sysdeps/unix/sysv/linux/wait.c
@@ -1 +1,47 @@
-#include <sysdeps/unix/bsd/bsd4.4/wait.c>
+/* Copyright (C) 1991, 1995, 1996, 1997, 2002 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <stddef.h>
+#include <sysdep-cancel.h>
+#include <nptl/pthreadP.h>
+#include <tls.h>
+
+/* Wait for a child to die.  When one does, put its status in *STAT_LOC
+   and return its process ID.  For errors, return (pid_t) -1.  */
+__pid_t
+__libc_wait (__WAIT_STATUS_DEFN stat_loc)
+{
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0,
+			   (struct rusage *) NULL);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0,
+			       (struct rusage *) NULL);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
+weak_alias (__libc_wait, __wait)
+weak_alias (__libc_wait, wait)
diff --git a/sysdeps/unix/sysv/linux/waitpid.c b/sysdeps/unix/sysv/linux/waitpid.c
index 43a63f6ce5..275fb826b4 100644
--- a/sysdeps/unix/sysv/linux/waitpid.c
+++ b/sysdeps/unix/sysv/linux/waitpid.c
@@ -16,14 +16,26 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <errno.h>
+#include <sysdep-cancel.h>
 #include <stdlib.h>
 #include <sys/wait.h>
+#include <nptl/pthreadP.h>
+#include <tls.h>
 
 __pid_t
 __libc_waitpid (__pid_t pid, int *stat_loc, int options)
 {
-  return __wait4 (pid, stat_loc, options, NULL);
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_waitpid, __waitpid)
 libc_hidden_weak (__waitpid)
diff --git a/sysdeps/unix/sysv/linux/writev.c b/sysdeps/unix/sysv/linux/writev.c
index 76cc920dae..c8ecf5060f 100644
--- a/sysdeps/unix/sysv/linux/writev.c
+++ b/sysdeps/unix/sysv/linux/writev.c
@@ -22,7 +22,7 @@
 #include <sys/param.h>
 #include <sys/uio.h>
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
@@ -39,11 +39,8 @@ static ssize_t __atomic_writev_replacement (int, const struct iovec *,
 
 /* We should deal with kernel which have a smaller UIO_FASTIOV as well
    as a very big count.  */
-ssize_t
-__libc_writev (fd, vector, count)
-     int fd;
-     const struct iovec *vector;
-     int count;
+static ssize_t
+do_writev (int fd, const struct iovec *vector, int count)
 {
   ssize_t bytes_written;
 
@@ -54,6 +51,24 @@ __libc_writev (fd, vector, count)
 
   return __atomic_writev_replacement (fd, vector, count);
 }
+
+ssize_t
+__libc_writev (fd, vector, count)
+     int fd;
+     const struct iovec *vector;
+     int count;
+{
+  if (SINGLE_THREAD_P)
+    return do_writev (fd, vector, count);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = do_writev (fd, vector, count);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 strong_alias (__libc_writev, __writev)
 weak_alias (__libc_writev, writev)