about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog41
-rw-r--r--nptl/ChangeLog6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h62
-rw-r--r--sysdeps/generic/pselect.c35
-rw-r--r--sysdeps/generic/sysdep-cancel.h5
-rw-r--r--sysdeps/posix/open64.c12
-rw-r--r--sysdeps/posix/sigpause.c20
-rw-r--r--sysdeps/posix/sigwait.c23
-rw-r--r--sysdeps/posix/system.c12
-rw-r--r--sysdeps/posix/waitid.c31
-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
38 files changed, 730 insertions, 149 deletions
diff --git a/ChangeLog b/ChangeLog
index f45ba51ba3..f7d344f9c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2002-12-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/generic/sysdep-cancel.h: Add dummy definitions for
+	SINGLE_THREAD_P, LIBC_CANCEL_ASYNC, and LIBC_CANCEL_RESET.
+
+	* sysdeps/unix/sysv/linux/open64.c: New file.
+
+	* sysdeps/generic/pselect.c: Add support for cancellation handling.
+	* sysdeps/posix/open64.c: Likewise.
+	* sysdeps/posix/sigpause.c: Likewise.
+	* sysdeps/posix/sigwait.c: Likewise.
+	* sysdeps/posix/system.c: Likewise.
+	* sysdeps/posix/waitid.c: Likewise.
+	* sysdeps/unix/sysv/linux/accept.S: Likewise.
+	* sysdeps/unix/sysv/linux/connect.S: Likewise.
+	* sysdeps/unix/sysv/linux/llseek.c: Likewise.
+	* sysdeps/unix/sysv/linux/msgrcv.c: Likewise.
+	* sysdeps/unix/sysv/linux/msgsnd.c: Likewise.
+	* sysdeps/unix/sysv/linux/poll.c: Likewise.
+	* sysdeps/unix/sysv/linux/pread.c: Likewise.
+	* sysdeps/unix/sysv/linux/pread64.c: Likewise.
+	* sysdeps/unix/sysv/linux/pwrite.c: Likewise.
+	* sysdeps/unix/sysv/linux/pwrite64.c: Likewise.
+	* sysdeps/unix/sysv/linux/readv.c: Likewise.
+	* sysdeps/unix/sysv/linux/recv.S: Likewise.
+	* sysdeps/unix/sysv/linux/recvfrom.S: Likewise.
+	* sysdeps/unix/sysv/linux/recvmsg.S: Likewise.
+	* sysdeps/unix/sysv/linux/send.S: Likewise.
+	* sysdeps/unix/sysv/linux/sendmsg.S: Likewise.
+	* sysdeps/unix/sysv/linux/sendto.S: Likewise.
+	* sysdeps/unix/sysv/linux/sigsuspend.c: Likewise.
+	* sysdeps/unix/sysv/linux/sigtimedwait.c: Likewise.
+	* sysdeps/unix/sysv/linux/sigwait.c: Likewise.
+	* sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise.
+	* sysdeps/unix/sysv/linux/tcdrain.c: Likewise.
+	* sysdeps/unix/sysv/linux/wait.c: Likewise.
+	* sysdeps/unix/sysv/linux/waitpid.c: Likewise.
+	* sysdeps/unix/sysv/linux/writev.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/fcntl.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/socket.S: Likewise.
+
 2002-12-14  Jakub Jelinek  <jakub@redhat.com>
 
 	* sysdeps/generic/sysdep-cancel.h: New file.
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 24abd2b541..2296c17803 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,9 @@
+2002-12-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define
+	SINGLE_THREAD_P.  If in libc or libpthread examine multiple_thread
+	member of thread decriptor, otherwise return unconditionally 1.
+
 2002-12-14  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/unix/sysv/linux/i386/pt-socket.S: Changes folded into the
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
index ed9f9420e7..39bdfbea1d 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
@@ -19,11 +19,14 @@
 
 #include <sysdep.h>
 #include <tls.h>
+#ifndef ASSEMBLER
+# include <nptl/pthreadP.h>
+#endif
 
 #if !defined NOT_IN_libc || defined IS_IN_libpthread
 
-#undef PSEUDO
-#define PSEUDO(name, syscall_name, args)				      \
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
   .text;								      \
   ENTRY (name)								      \
     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;				      \
@@ -33,7 +36,7 @@
     jae SYSCALL_ERROR_LABEL;						      \
     ret;								      \
   L(pseudo_cancel):							      \
-    call __libc_enable_asynccancel;					      \
+    CENABLE								      \
     SAVE_OLDTYPE_##args							      \
     PUSHARGS_##args							      \
     DOCARGS_##args							      \
@@ -45,26 +48,41 @@
     jae SYSCALL_ERROR_LABEL;						      \
   L(pseudo_end):
 
-#define SAVE_OLDTYPE_0	movl %eax, %ecx;
-#define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0
-#define SAVE_OLDTYPE_2	pushl %eax;
-#define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2
-#define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2
-#define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2
+# define SAVE_OLDTYPE_0	movl %eax, %edx;
+# define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0
+# define SAVE_OLDTYPE_2	pushl %eax;
+# define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2
+# define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2
+# define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2
+
+# define DOCARGS_0	DOARGS_0
+# define DOCARGS_1	DOARGS_1
+# define DOCARGS_2	_DOARGS_2 (12)
+# define DOCARGS_3	_DOARGS_3 (20)
+# define DOCARGS_4	_DOARGS_4 (28)
+# define DOCARGS_5	_DOARGS_5 (36)
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel;
+#  define CDISABLE	call __pthread_disable_asynccancel
+# else
+#  define CENABLE	call __libc_enable_asynccancel;
+#  define CDISABLE	call __libc_disable_asynccancel
+# endif
+# define POPCARGS_0	pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax;
+# define POPCARGS_1	POPCARGS_0
+# define POPCARGS_2	xchgl (%esp), %eax; CDISABLE; popl %eax;
+# define POPCARGS_3	POPCARGS_2
+# define POPCARGS_4	POPCARGS_2
+# define POPCARGS_5	POPCARGS_2
+
+# define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   header.data.multiple_threads) == 0, 1)
 
-#define DOCARGS_0	DOARGS_0
-#define DOCARGS_1	DOARGS_1
-#define DOCARGS_2	_DOARGS_2 (12)
-#define DOCARGS_3	_DOARGS_3 (20)
-#define DOCARGS_4	_DOARGS_4 (28)
-#define DOCARGS_5	_DOARGS_5 (36)
+#else
 
-#define DISABLE		call __libc_disable_asynccancel
-#define POPCARGS_0	pushl %eax; movl %ecx, %eax; DISABLE; popl %eax;
-#define POPCARGS_1	POPCARGS_0
-#define POPCARGS_2	xchgl (%esp), %eax; DISABLE; popl %eax;
-#define POPCARGS_3	POPCARGS_2
-#define POPCARGS_4	POPCARGS_2
-#define POPCARGS_5	POPCARGS_2
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
 
 #endif
diff --git a/sysdeps/generic/pselect.c b/sysdeps/generic/pselect.c
index 6aa60e8e72..e090d6e526 100644
--- a/sysdeps/generic/pselect.c
+++ b/sysdeps/generic/pselect.c
@@ -22,6 +22,7 @@
 #include <stddef.h>	/* For NULL.  */
 #include <sys/time.h>
 #include <sys/select.h>
+#include <sysdep-cancel.h>
 
 /* Check the first NFDS descriptors each in READFDS (if not NULL) for read
    readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
@@ -29,14 +30,9 @@
    after waiting the interval specified therein.  Additionally set the sigmask
    SIGMASK for this call.  Returns the number of ready descriptors, or -1 for
    errors.  */
-int
-__pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask)
-     int nfds;
-     fd_set *readfds;
-     fd_set *writefds;
-     fd_set *exceptfds;
-     const struct timespec *timeout;
-     const sigset_t *sigmask;
+static int
+do_pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+	    const struct timespec *timeout, const sigset_t *sigmask)
 {
   struct timeval tval;
   int retval;
@@ -62,5 +58,28 @@ __pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask)
 
   return retval;
 }
+
+
+int
+__pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask)
+     int nfds;
+     fd_set *readfds;
+     fd_set *writefds;
+     fd_set *exceptfds;
+     const struct timespec *timeout;
+     const sigset_t *sigmask;
+{
+  if (SINGLE_THREAD_P)
+    return do_pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_pselect (nfds, readfds, writefds, exceptfds, timeout,
+			   sigmask);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 weak_alias (__pselect, pselect)
 strong_alias (__pselect, __libc_pselect)
diff --git a/sysdeps/generic/sysdep-cancel.h b/sysdeps/generic/sysdep-cancel.h
index 0eca1e927c..f065e6e437 100644
--- a/sysdeps/generic/sysdep-cancel.h
+++ b/sysdeps/generic/sysdep-cancel.h
@@ -1 +1,6 @@
 #include <sysdep.h>
+
+/* No multi-thread handling enabled.  */
+#define SINGLE_THREAD_P (1)
+#define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
+#define LIBC_CANCEL_RESET(val)  /* Nothing.  */
diff --git a/sysdeps/posix/open64.c b/sysdeps/posix/open64.c
index 3db5292ff5..8d8bdbac55 100644
--- a/sysdeps/posix/open64.c
+++ b/sysdeps/posix/open64.c
@@ -19,6 +19,7 @@
 #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.  */
@@ -35,7 +36,16 @@ __libc_open64 (const char *file, int oflag, ...)
       va_end (arg);
     }
 
-  return __libc_open (file, oflag | O_LARGEFILE, mode);
+  if (SINGLE_THREAD_P)
+    return __libc_open (file, oflag | O_LARGEFILE, mode);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = __libc_open (file, oflag | O_LARGEFILE, mode);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_open64, BP_SYM (__open64))
 libc_hidden_weak (BP_SYM (__open64))
diff --git a/sysdeps/posix/sigpause.c b/sysdeps/posix/sigpause.c
index dba6912e90..e85a813ab0 100644
--- a/sysdeps/posix/sigpause.c
+++ b/sysdeps/posix/sigpause.c
@@ -19,13 +19,14 @@
 #include <errno.h>
 #include <signal.h>
 #include <stddef.h>		/* For NULL.  */
+#include <sysdep-cancel.h>
 
 #include <sigset-cvt-mask.h>
 
 /* Set the mask of blocked signals to MASK,
    wait for a signal to arrive, and then restore the mask.  */
-int
-__sigpause (int sig_or_mask, int is_sig)
+static int
+do_sigpause (int sig_or_mask, int is_sig)
 {
   sigset_t set;
 
@@ -42,6 +43,21 @@ __sigpause (int sig_or_mask, int is_sig)
 
   return __sigsuspend (&set);
 }
+
+int
+__sigpause (int sig_or_mask, int is_sig)
+{
+  if (SINGLE_THREAD_P)
+    return do_sigpause (sig_or_mask, is_sig);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_sigpause (sig_or_mask, is_sig);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 libc_hidden_def (__sigpause)
 
 /* We have to provide a default version of this function since the
diff --git a/sysdeps/posix/sigwait.c b/sysdeps/posix/sigwait.c
index f2be3225c4..8b422d2b9d 100644
--- a/sysdeps/posix/sigwait.c
+++ b/sysdeps/posix/sigwait.c
@@ -1,5 +1,5 @@
 /* Implementation of sigwait function from POSIX.1c.
-   Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <stddef.h>		/* For NULL.  */
+#include <sysdep-cancel.h>
 
 /* This is our dummy signal handler we use here.  */
 static void ignore_signal (int sig);
@@ -31,8 +32,8 @@ static void ignore_signal (int sig);
 static int was_sig;
 
 
-int
-__sigwait (const sigset_t *set, int *sig)
+static int
+do_sigwait (const sigset_t *set, int *sig)
 {
   sigset_t tmp_mask;
   struct sigaction saved[NSIG];
@@ -80,6 +81,22 @@ __sigwait (const sigset_t *set, int *sig)
   *sig = was_sig;
   return was_sig == -1 ? -1 : 0;
 }
+
+
+int
+__sigwait (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)
 
diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
index 0881a3a431..bca1c2ec3e 100644
--- a/sysdeps/posix/system.c
+++ b/sysdeps/posix/system.c
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <bits/libc-lock.h>
+#include <sysdep-cancel.h>
 
 
 #ifndef	HAVE_GNU_LD
@@ -185,6 +186,15 @@ __libc_system (const char *line)
        not be available after a chroot(), for example.  */
     return do_system ("exit 0") == 0;
 
-  return do_system (line);
+  if (SINGLE_THREAD_P)
+    return do_system (line);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_system (line);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 weak_alias (__libc_system, system)
diff --git a/sysdeps/posix/waitid.c b/sysdeps/posix/waitid.c
index ef2ab2ed54..679d97d203 100644
--- a/sysdeps/posix/waitid.c
+++ b/sysdeps/posix/waitid.c
@@ -18,21 +18,18 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <assert.h>
 #include <errno.h>
 #include <signal.h>
 #define __need_NULL
 #include <stddef.h>
 #include <sys/wait.h>
 #include <sys/types.h>
+#include <sysdep-cancel.h>
 
-#include <assert.h>
 
-int
-__waitid (idtype, id, infop, options)
-     idtype_t idtype;
-     id_t id;
-     siginfo_t *infop;
-     int options;
+static int
+do_waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options)
 {
   pid_t pid, child;
   int status;
@@ -118,5 +115,25 @@ __waitid (idtype, id, infop, options)
 
   return 0;
 }
+
+
+int
+__waitid (idtype, id, infop, options)
+     idtype_t idtype;
+     id_t id;
+     siginfo_t *infop;
+     int options;
+{
+  if (SINGLE_THREAD_P)
+    return do_waitid (idtype, id, infop, options);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_waitid (idtype, id, infop, options);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
 weak_alias (__waitid, waitid)
 strong_alias (__waitid, __libc_waitid)
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)