summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
commit0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch)
tree2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /nptl/sysdeps/unix/sysv
parent7d58530341304d403a6626d7f7a1913165fe2f32 (diff)
downloadglibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.xz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip
2.5-18.1
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Makefile8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/aio_misc.h10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h81
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/local_lim.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/configure3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.c9
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.h4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S63
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S227
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S7
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S47
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S28
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S17
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h332
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h42
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/smp.h56
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h288
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/vfork.S19
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/clone2.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/createthread.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h39
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h85
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c95
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/kernel-features.h6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c113
-rw-r--r--nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/mq_notify.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h90
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h118
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h41
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c51
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c48
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c111
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_kill.c18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/register-atfork.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h153
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h99
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h142
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S224
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h128
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sleep.c12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/smp.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/Makefile2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h95
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c131
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c62
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c100
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c63
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c54
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c117
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c59
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c74
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h97
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S9
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h91
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/timer_create.c13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/timer_routines.c50
-rw-r--r--nptl/sysdeps/unix/sysv/linux/unregister-atfork.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h35
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/clone.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S97
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h352
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S229
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S15
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S19
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S33
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S34
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S45
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S26
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S14
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S16
133 files changed, 4426 insertions, 1126 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
index 991398242a..cfcdb6d97f 100644
--- a/nptl/sysdeps/unix/sysv/linux/Makefile
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -24,7 +24,8 @@ sysdep_routines += register-atfork unregister-atfork libc_pthread_init \
 libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
 
 gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \
-			lowlevelbarrier.sym unwindbuf.sym
+			lowlevelbarrier.sym unwindbuf.sym \
+			lowlevelrobustlock.sym pthread-pi-defines.sym
 endif
 
 ifeq ($(subdir),posix)
@@ -32,3 +33,6 @@ CFLAGS-fork.c = -D_IO_MTSAFE_IO
 CFLAGS-getpid.o = -fomit-frame-pointer
 CFLAGS-getpid.os = -fomit-frame-pointer
 endif
+
+# Needed in both the signal and nptl subdir.
+CFLAGS-sigaction.c = -DWRAPPER_INCLUDE='<nptl/sigaction.c>'
diff --git a/nptl/sysdeps/unix/sysv/linux/aio_misc.h b/nptl/sysdeps/unix/sysv/linux/aio_misc.h
index 7b0bac75f2..406d96e865 100644
--- a/nptl/sysdeps/unix/sysv/linux/aio_misc.h
+++ b/nptl/sysdeps/unix/sysv/linux/aio_misc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
 
@@ -19,9 +19,10 @@
 
 #ifndef _AIO_MISC_H
 # include_next <aio_misc.h>
+# include <limits.h>
+# include <pthread.h>
 # include <signal.h>
 # include <sysdep.h>
-# include <pthread.h>
 
 # define aio_start_notify_thread __aio_start_notify_thread
 # define aio_create_helper_thread __aio_create_helper_thread
@@ -36,7 +37,8 @@ __aio_start_notify_thread (void)
 }
 
 extern inline int
-__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
+__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
+			    void *arg)
 {
   pthread_attr_t attr;
 
@@ -63,5 +65,5 @@ __aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
 
   (void) pthread_attr_destroy (&attr);
   return ret;
-}                                                                                 
+}
 #endif
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
index d13d6e86a4..41a54d4b0d 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  Alpha version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 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
@@ -43,11 +43,18 @@ typedef union
 } pthread_attr_t;
 
 
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is deliberately not exposed.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -57,6 +64,8 @@ typedef union
        binary compatibility.  */
     int __kind;
     int __spins;
+    __pthread_list_t __list;
+#define __PTHREAD_MUTEX_HAVE_PREV	1
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
@@ -117,8 +126,9 @@ typedef union
     unsigned int __nr_readers_queued;
     unsigned int __nr_writers_queued;
     int __writer;
-
-    unsigned int __reserved[6];
+    int __pad1;
+    unsigned long int __pad2;
+    unsigned long int __pad3;
     /* FLAGS must stay at this position in the structure to maintain
        binary compatibility.  */
     unsigned int __flags;
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/clone.S b/nptl/sysdeps/unix/sysv/linux/alpha/clone.S
index eea1cbeed1..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/alpha/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
index fd4a7ca4bb..58b4806eb2 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 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
@@ -31,6 +31,11 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -62,6 +67,15 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \
   })
 
+#define lll_robust_mutex_dead(futexv) \
+  do									      \
+    {									      \
+      int *__futexp = &(futexv);					      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      lll_futex_wake (__futexp, 1);					      \
+    }									      \
+  while (0)
+
 /* Returns non-zero if error happened, zero if success.  */
 #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
   ({									      \
@@ -73,6 +87,20 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_WAKE_OP, (nr_wake),	      \
+			      (nr_wake2), (futexp2),			      \
+			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
+  })
+
+
+
 
 static inline int __attribute__((always_inline))
 __lll_mutex_trylock(int *futex)
@@ -90,7 +118,16 @@ __lll_mutex_cond_trylock(int *futex)
 #define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock))
 
 
+static inline int __attribute__((always_inline))
+__lll_robust_mutex_trylock(int *futex, int id)
+{
+  return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0;
+}
+#define lll_robust_mutex_trylock(lock, id) \
+  __lll_robust_mutex_trylock (&(lock), id)
+
 extern void __lll_lock_wait (int *futex) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
 
 static inline void __attribute__((always_inline))
 __lll_mutex_lock(int *futex)
@@ -101,6 +138,18 @@ __lll_mutex_lock(int *futex)
 #define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
 
 
+static inline int __attribute__ ((always_inline))
+__lll_robust_mutex_lock (int *futex, int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_lock_wait (futex);
+  return result;
+}
+#define lll_robust_mutex_lock(futex, id) \
+  __lll_robust_mutex_lock (&(futex), id)
+
+
 static inline void __attribute__ ((always_inline))
 __lll_mutex_cond_lock (int *futex)
 {
@@ -110,8 +159,14 @@ __lll_mutex_cond_lock (int *futex)
 #define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
 
 
+#define lll_robust_mutex_cond_lock(futex, id) \
+  __lll_robust_mutex_lock (&(futex), (id) | FUTEX_WAITERS)
+
+
 extern int __lll_timedlock_wait (int *futex, const struct timespec *)
 	attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *)
+	attribute_hidden;
 
 static inline int __attribute__ ((always_inline))
 __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
@@ -125,6 +180,19 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
   __lll_mutex_timedlock (&(futex), abstime)
 
 
+static inline int __attribute__ ((always_inline))
+__lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime,
+			      int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_timedlock_wait (futex, abstime);
+  return result;
+}
+#define lll_robust_mutex_timedlock(futex, abstime, id) \
+  __lll_robust_mutex_timedlock (&(futex), abstime, id)
+
+
 static inline void __attribute__ ((always_inline))
 __lll_mutex_unlock (int *futex)
 {
@@ -136,6 +204,17 @@ __lll_mutex_unlock (int *futex)
 
 
 static inline void __attribute__ ((always_inline))
+__lll_robust_mutex_unlock (int *futex, int mask)
+{
+  int val = atomic_exchange_rel (futex, 0);
+  if (__builtin_expect (val & mask, 0))
+    lll_futex_wake (futex, 1);
+}
+#define lll_robust_mutex_unlock(futex) \
+  __lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS)
+
+
+static inline void __attribute__ ((always_inline))
 __lll_mutex_unlock_force (int *futex)
 {
   (void) atomic_exchange_rel (futex, 0);
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
index f3f7718e3e..aa42768f70 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2006 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
@@ -167,3 +167,9 @@ extern int __local_multiple_threads attribute_hidden;
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
index 0bc8e048af..b639ba44af 100644
--- a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
+++ b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
@@ -3,16 +3,16 @@
    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 Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
+   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
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
+   You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; see the file COPYING.LIB.  If not,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
index 09f3df11cb..dd0798a073 100644
--- a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
+++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
@@ -1,18 +1,18 @@
 /* Define POSIX options for Linux.
-   Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996-2004, 2006 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 Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
+   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
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
+   You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; see the file COPYING.LIB.  If not,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
@@ -60,6 +60,9 @@
 /* X/Open realtime support is available.  */
 #define _XOPEN_REALTIME	1
 
+/* X/Open thread realtime support is available.  */
+#define _XOPEN_REALTIME_THREADS	1
+
 /* XPG4.2 shared memory is supported.  */
 #define	_XOPEN_SHM	1
 
@@ -79,6 +82,13 @@
 /* We support user-defined stacks.  */
 #define _POSIX_THREAD_ATTR_STACKADDR	200112L
 
+/* We support priority inheritence.  */
+#define _POSIX_THREAD_PRIO_INHERIT	200112L
+
+/* We support priority protection, though only for non-robust
+   mutexes.  */
+#define _POSIX_THREAD_PRIO_PROTECT	200112L
+
 /* We support POSIX.1b semaphores.  */
 #define _POSIX_SEMAPHORES	200112L
 
@@ -171,8 +181,4 @@
 /* Typed memory objects are not available.  */
 #define _POSIX_TYPED_MEMORY_OBJECTS	-1
 
-/* No support for priority inheritance or protection so far.  */
-#define _POSIX_THREAD_PRIO_INHERIT	-1
-#define _POSIX_THREAD_PRIO_PROTECT	-1
-
 #endif /* posix_opt.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/configure b/nptl/sysdeps/unix/sysv/linux/configure
deleted file mode 100644
index 229414dd74..0000000000
--- a/nptl/sysdeps/unix/sysv/linux/configure
+++ /dev/null
@@ -1,3 +0,0 @@
-# Local configure fragment for sysdeps/unix/sysv/linux.
-
-DEFINES="$DEFINES -D_LIBC_REENTRANT"
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c
index 840974401b..98bb237c06 100644
--- a/nptl/sysdeps/unix/sysv/linux/fork.c
+++ b/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -167,8 +167,11 @@ __libc_fork (void)
 	    allp->handler->child_handler ();
 
 	  /* Note that we do not have to wake any possible waiter.
-	     This is the only thread in the new process.  */
-	  --allp->handler->refcntr;
+ 	     This is the only thread in the new process.  The count
+ 	     may have been bumped up by other threads doing a fork.
+ 	     We reset it to 1, to avoid waiting for non-existing
+ 	     thread(s) to release the count.  */
+	  allp->handler->refcntr = 1;
 
 	  /* XXX We could at this point look through the object pool
 	     and mark all objects not on the __fork_handlers list as
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h
index d093ccc907..6458977b99 100644
--- a/nptl/sysdeps/unix/sysv/linux/fork.h
+++ b/nptl/sysdeps/unix/sysv/linux/fork.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -41,7 +41,7 @@ struct fork_handler
 };
 
 /* The single linked list of all currently registered for handlers.  */
-extern struct fork_handler *__fork_handlers;
+extern struct fork_handler *__fork_handlers attribute_hidden;
 
 
 /* Function to call to unregister fork handlers.  */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
index 4d1c9450b5..f53d0e5a72 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 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
@@ -43,11 +43,17 @@ typedef union
 } pthread_attr_t;
 
 
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -56,7 +62,11 @@ typedef union
        binary compatibility.  */
     int __kind;
     unsigned int __nusers;
-    int __spins;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
@@ -155,6 +165,6 @@ typedef union
 
 
 /* Extra attributes for the cleanup functions.  */
-#define __cleanup_fct_attribute __attribute ((regparm (1)))
+#define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
 
 #endif	/* bits/pthreadtypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/clone.S b/nptl/sysdeps/unix/sysv/linux/i386/clone.S
index 95c17f18e4..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/i386/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
index 223b111083..88885b735d 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
@@ -22,7 +22,7 @@
 #ifndef UP
 # define LOCK \
 	cmpl	$0, %gs:MULTIPLE_THREADS_OFFSET; 			      \
-	je,pt	0f;							      \
+	je	0f;							      \
 	lock;								      \
 0:
 #endif
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
index dc65b709a1..e2da5b04cf 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -41,9 +41,16 @@
 	.hidden	__lll_mutex_lock_wait
 	.align	16
 __lll_mutex_lock_wait:
+	cfi_startproc
 	pushl	%edx
+	cfi_adjust_cfa_offset(4)
 	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
 	pushl	%esi
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(%edx, -8)
+	cfi_offset(%ebx, -12)
+	cfi_offset(%esi, -16)
 
 	movl	$2, %edx
 	movl	%ecx, %ebx
@@ -60,12 +67,19 @@ __lll_mutex_lock_wait:
 	xchgl	%eax, (%ebx)	/* NB:	 lock is implied */
 
 	testl	%eax, %eax
-	jnz,pn	1b
+	jnz	1b
 
 	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%esi)
 	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebx)
 	popl	%edx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%edx)
 	ret
+	cfi_endproc
 	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait
 
 
@@ -75,17 +89,27 @@ __lll_mutex_lock_wait:
 	.hidden	__lll_mutex_timedlock_wait
 	.align	16
 __lll_mutex_timedlock_wait:
+	cfi_startproc
 	/* Check for a valid timeout value.  */
 	cmpl	$1000000000, 4(%edx)
 	jae	3f
 
 	pushl	%edi
+	cfi_adjust_cfa_offset(4)
 	pushl	%esi
+	cfi_adjust_cfa_offset(4)
 	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
 	pushl	%ebp
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(%edi, -8)
+	cfi_offset(%esi, -12)
+	cfi_offset(%ebx, -16)
+	cfi_offset(%ebp, -20)
 
 	/* Stack frame for the timespec and timeval structs.  */
 	subl	$8, %esp
+	cfi_adjust_cfa_offset(8)
 
 	movl	%ecx, %ebp
 	movl	%edx, %edi
@@ -140,12 +164,29 @@ __lll_mutex_timedlock_wait:
 	jnz	7f
 
 6:	addl	$8, %esp
+	cfi_adjust_cfa_offset(-8)
 	popl	%ebp
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebp)
 	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebx)
 	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%esi)
 	popl	%edi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%edi)
 	ret
 
+3:	movl	$EINVAL, %eax
+	ret
+
+	cfi_adjust_cfa_offset(24)
+	cfi_offset(%edi, -8)
+	cfi_offset(%esi, -12)
+	cfi_offset(%ebx, -16)
+	cfi_offset(%ebp, -20)
 	/* Check whether the time expired.  */
 7:	cmpl	$-ETIMEDOUT, %ecx
 	je	5f
@@ -157,11 +198,9 @@ __lll_mutex_timedlock_wait:
 	jz	6b
 	jmp	1b
 
-3:	movl	$EINVAL, %eax
-	ret
-
 5:	movl	$ETIMEDOUT, %eax
 	jmp	6b
+	cfi_endproc
 	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
 #endif
 
@@ -200,9 +239,16 @@ lll_unlock_wake_cb:
 	.hidden	__lll_mutex_unlock_wake
 	.align	16
 __lll_mutex_unlock_wake:
+	cfi_startproc
 	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
 	pushl	%ecx
+	cfi_adjust_cfa_offset(4)
 	pushl	%edx
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(%ebx, -8)
+	cfi_offset(%ecx, -12)
+	cfi_offset(%edx, -16)
 
 	movl	%eax, %ebx
 	movl	$0, (%eax)
@@ -212,9 +258,16 @@ __lll_mutex_unlock_wake:
 	ENTER_KERNEL
 
 	popl	%edx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%edx)
 	popl	%ecx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ecx)
 	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebx)
 	ret
+	cfi_endproc
 	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
 
 
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
new file mode 100644
index 0000000000..73d8bc4ccc
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
@@ -0,0 +1,227 @@
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <sysdep.h>
+#include <pthread-errnos.h>
+#include <lowlevelrobustlock.h>
+
+	.text
+
+#ifndef LOCK
+# ifdef UP
+#  define LOCK
+# else
+#  define LOCK lock
+# endif
+#endif
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+#define FUTEX_WAITERS		0x80000000
+#define FUTEX_OWNER_DIED	0x40000000
+
+
+	.globl	__lll_robust_mutex_lock_wait
+	.type	__lll_robust_mutex_lock_wait,@function
+	.hidden	__lll_robust_mutex_lock_wait
+	.align	16
+__lll_robust_mutex_lock_wait:
+	cfi_startproc
+	pushl	%edx
+	cfi_adjust_cfa_offset(4)
+	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
+	pushl	%esi
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(%edx, -8)
+	cfi_offset(%ebx, -12)
+	cfi_offset(%esi, -16)
+
+	movl	%ecx, %ebx
+	xorl	%esi, %esi	/* No timeout.  */
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+
+4:	movl	%eax, %edx
+	orl	$FUTEX_WAITERS, %edx
+
+	testl	$FUTEX_OWNER_DIED, %eax
+	jnz	3f
+
+	cmpl	%edx, %eax	/* NB:	 %edx == 2 */
+	je	1f
+
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jnz	2f
+
+1:	movl	$SYS_futex, %eax
+	ENTER_KERNEL
+
+	movl	(%ebx), %eax
+
+2:	test	%eax, %eax
+	jne	4b
+
+	movl	%gs:TID, %edx
+	orl	$FUTEX_WAITERS, %edx
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jnz	4b
+	/* NB:	 %eax == 0 */
+
+3:	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%esi)
+	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebx)
+	popl	%edx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%edx)
+	ret
+	cfi_endproc
+	.size	__lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
+
+
+	.globl	__lll_robust_mutex_timedlock_wait
+	.type	__lll_robust_mutex_timedlock_wait,@function
+	.hidden	__lll_robust_mutex_timedlock_wait
+	.align	16
+__lll_robust_mutex_timedlock_wait:
+	cfi_startproc
+	/* Check for a valid timeout value.  */
+	cmpl	$1000000000, 4(%edx)
+	jae	3f
+
+	pushl	%edi
+	cfi_adjust_cfa_offset(4)
+	pushl	%esi
+	cfi_adjust_cfa_offset(4)
+	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
+	pushl	%ebp
+	cfi_adjust_cfa_offset(4)
+	cfi_offset(%edi, -8)
+	cfi_offset(%esi, -12)
+	cfi_offset(%ebx, -16)
+	cfi_offset(%ebp, -20)
+
+	/* Stack frame for the timespec and timeval structs.  */
+	subl	$12, %esp
+	cfi_adjust_cfa_offset(12)
+
+	movl	%ecx, %ebp
+	movl	%edx, %edi
+
+1:	movl	%eax, 8(%esp)
+
+	/* Get current time.  */
+	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	ENTER_KERNEL
+
+	/* Compute relative timeout.  */
+	movl	4(%esp), %eax
+	movl	$1000, %edx
+	mul	%edx		/* Milli seconds to nano seconds.  */
+	movl	(%edi), %ecx
+	movl	4(%edi), %edx
+	subl	(%esp), %ecx
+	subl	%eax, %edx
+	jns	4f
+	addl	$1000000000, %edx
+	subl	$1, %ecx
+4:	testl	%ecx, %ecx
+	js	8f		/* Time is already up.  */
+
+	/* Store relative timeout.  */
+	movl	%ecx, (%esp)
+	movl	%edx, 4(%esp)
+
+	movl	%ebp, %ebx
+
+	movl	8(%esp), %edx
+	movl	%edx, %eax
+	orl	$FUTEX_WAITERS, %edx
+
+	testl	$FUTEX_OWNER_DIED, %eax
+	jnz	6f
+
+	cmpl	%eax, %edx
+	je	2f
+
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	movl	$0, %ecx	/* Must use mov to avoid changing cc.  */
+	jnz	5f
+
+2:
+	/* Futex call.  */
+	movl	%esp, %esi
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	$SYS_futex, %eax
+	ENTER_KERNEL
+	movl	%eax, %ecx
+
+	movl	(%ebx), %eax
+
+5:	testl	%eax, %eax
+	jne	7f
+
+	movl	%gs:TID, %edx
+	orl	$FUTEX_WAITERS, %edx
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jnz	7f
+
+6:	addl	$12, %esp
+	cfi_adjust_cfa_offset(-12)
+	popl	%ebp
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebp)
+	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%ebx)
+	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%esi)
+	popl	%edi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(%edi)
+	ret
+
+3:	movl	$EINVAL, %eax
+	ret
+
+	cfi_adjust_cfa_offset(28)
+	cfi_offset(%edi, -8)
+	cfi_offset(%esi, -12)
+	cfi_offset(%ebx, -16)
+	cfi_offset(%ebp, -20)
+	/* Check whether the time expired.  */
+7:	cmpl	$-ETIMEDOUT, %ecx
+	jne	1b
+
+8:	movl	$ETIMEDOUT, %eax
+	jmp	6b
+	cfi_endproc
+	.size	__lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
index 114284c44c..fe7a8b9c66 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
@@ -82,7 +82,7 @@ pthread_barrier_wait:
 #else
 	cmpl	%edx, CURR_EVENT(%ebx)
 #endif
-	je,pn	8b
+	je	8b
 
 	/* Increment LEFT.  If this brings the count back to the
 	   initial count unlock the object.  */
@@ -92,7 +92,7 @@ pthread_barrier_wait:
 	xaddl	%edx, LEFT(%ebx)
 	subl	$1, %ecx
 	cmpl	%ecx, %edx
-	jne,pt	10f
+	jne	10f
 
 	/* Release the mutex.  We cannot release the lock before
 	   waking the waiting threads since otherwise a new thread might
@@ -131,7 +131,7 @@ pthread_barrier_wait:
 	xaddl	%edx, LEFT(%ebx)
 	subl	$1, %ecx
 	cmpl	%ecx, %edx
-	jne,pt	5f
+	jne	5f
 
 	/* Release the mutex.  We cannot release the lock before
 	   waking the waiting threads since otherwise a new thread might
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
index 5471c1c927..56f7be8246 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -21,6 +21,7 @@
 #include <shlib-compat.h>
 #include <lowlevelcond.h>
 #include <kernel-features.h>
+#include <pthread-pi-defines.h>
 
 #ifdef UP
 # define LOCK
@@ -94,6 +95,10 @@ __pthread_cond_broadcast:
 8:	cmpl	$-1, %edi
 	je	9f
 
+	/* XXX: The kernel so far doesn't support requeue to PI futex.  */
+	testl	$PI_BIT, MUTEX_KIND(%edi)
+	jne	9f
+
 	/* Wake up all threads.  */
 	movl	$FUTEX_CMP_REQUEUE, %ecx
 	movl	$SYS_futex, %eax
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
index 3c5a1db59c..d0f931ff15 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -31,7 +31,9 @@
 #define SYS_futex		240
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
-#define FUTEX_REQUEUE		3
+#define FUTEX_WAKE_OP		5
+
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
 
 #define EINVAL			22
 
@@ -79,21 +81,46 @@ __pthread_cond_signal:
 	addl	$1, (%ebx)
 
 	/* Wake up one thread.  */
-	movl	$FUTEX_WAKE, %ecx
+	pushl	%esi
+	pushl	%ebp
+	movl	$FUTEX_WAKE_OP, %ecx
 	movl	$SYS_futex, %eax
 	movl	$1, %edx
+	movl	$1, %esi
+	movl	$FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp
+	/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
+	   sysenter.
+	ENTER_KERNEL  */
+	int	$0x80
+	popl	%ebp
+	popl	%esi
+
+	/* For any kind of error, we try again with WAKE.
+	   The general test also covers running on old kernels.  */
+	cmpl	$-4095, %eax
+	jae	7f
+
+6:	xorl	%eax, %eax
+	popl	%edi
+	popl	%ebx
+	ret
+
+7:	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	/* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
+	movl	$1, %edx  */
 	ENTER_KERNEL
 
 	/* Unlock.  Note that at this point %edi always points to
 	   cond_lock.  */
 4:	LOCK
 	subl	$1, (%edi)
-	jne	5f
+	je	6b
 
-6:	xorl	%eax, %eax
-	popl	%edi
-	popl	%ebx
-	ret
+	/* Unlock in loop requires wakeup.  */
+5:	movl	%edi, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	6b
 
 	/* Initial locking failed.  */
 1:
@@ -105,10 +132,6 @@ __pthread_cond_signal:
 	call	__lll_mutex_lock_wait
 	jmp	2b
 
-	/* Unlock in loop requires wakeup.  */
-5:	movl	%edi, %eax
-	call	__lll_mutex_unlock_wake
-	jmp	6b
 	.size	__pthread_cond_signal, .-__pthread_cond_signal
 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
 		  GLIBC_2_3_2)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
index 699c2cb227..f481a8e43c 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -406,12 +406,22 @@ __condvar_tw_cleanup:
 	cmpl	20(%esp), %eax
 	jne	3f
 
-	addl	$1, wakeup_seq(%ebx)
+	/* We increment the wakeup_seq counter only if it is lower than
+	   total_seq.  If this is not the case the thread was woken and
+	   then canceled.  In this case we ignore the signal.  */
+	movl	total_seq(%ebx), %eax
+	movl	total_seq+4(%ebx), %edi
+	cmpl	wakeup_seq+4(%ebx), %edi
+	jb	6f
+	ja	7f
+	cmpl	wakeup_seq(%ebx), %eax
+	jbe	7f
+
+6:	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
-
 	addl	$1, cond_futex(%ebx)
 
-	addl	$1, woken_seq(%ebx)
+7:	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
 3:	subl	$(1 << clock_bits), cond_nwaiters(%ebx)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index d282785151..f16c7d9198 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -297,12 +297,22 @@ __condvar_w_cleanup:
 	cmpl	12(%esp), %eax
 	jne	3f
 
-	addl	$1, wakeup_seq(%ebx)
+	/* We increment the wakeup_seq counter only if it is lower than
+	   total_seq.  If this is not the case the thread was woken and
+	   then canceled.  In this case we ignore the signal.  */
+	movl	total_seq(%ebx), %eax
+	movl	total_seq+4(%ebx), %edi
+	cmpl	wakeup_seq+4(%ebx), %edi
+	jb	6f
+	ja	7f
+	cmpl	wakeup_seq(%ebx), %eax
+	jbe	7f
+
+6:	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
-
 	addl	$1, cond_futex(%ebx)
 
-	addl	$1, woken_seq(%ebx)
+7:	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
 3:	subl	$(1 << clock_bits), cond_nwaiters(%ebx)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
index 3d67329bd1..71e96d2228 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -65,9 +65,14 @@ __new_sem_post:
 #endif
 	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
 #if USE___THREAD
-	movl	%gs:0, %edx
-	subl	errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+	movl	errno@gotntpoff(%ebx), %edx
+	addl	%gs:0, %edx
 	movl	$EINVAL, (%edx)
+# else
+	movl	errno@gotntpoff(%ebx), %edx
+	movl	$EINVAL, %gs:(%edx)
+# endif
 #else
 	call	__errno_location@plt
 	movl	$EINVAL, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
index 5b24476936..bf70e17fca 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -49,12 +49,12 @@ sem_timedwait:
 
 	movl	(%ecx), %eax
 2:	testl	%eax, %eax
-	je,pn	1f
+	je	1f
 
 	leal	-1(%eax), %edx
 	LOCK
 	cmpxchgl %edx, (%ecx)
-	jne,pn	2b
+	jne	2b
 
 	xorl	%eax, %eax
 	ret
@@ -79,10 +79,7 @@ sem_timedwait:
 	jae	6f
 
 	cfi_offset(3, -16)		/* %ebx */
-7:	call	__pthread_enable_asynccancel
-	movl	%eax, 8(%esp)
-
-	xorl	%ecx, %ecx
+7:	xorl	%ecx, %ecx
 	movl	%esp, %ebx
 	movl	%ecx, %edx
 	movl	$SYS_gettimeofday, %eax
@@ -105,6 +102,10 @@ sem_timedwait:
 
 	movl	%ecx, (%esp)	/* Store relative timeout.  */
 	movl	%edx, 4(%esp)
+
+	call	__pthread_enable_asynccancel
+	movl	%eax, 8(%esp)
+
 	movl	28(%esp), %ebx
 	xorl	%ecx, %ecx
 	movl	%esp, %esi
@@ -117,7 +118,7 @@ sem_timedwait:
 	call	__pthread_disable_asynccancel
 
 	testl	%esi, %esi
-	je,pt	9f
+	je	9f
 	cmpl	$-EWOULDBLOCK, %esi
 	jne	3f
 
@@ -128,7 +129,7 @@ sem_timedwait:
 	leal	-1(%eax), %ecx
 	LOCK
 	cmpxchgl %ecx, (%ebx)
-	jne,pn	8b
+	jne	8b
 
 	addl	$12, %esp
 	cfi_adjust_cfa_offset(-12)
@@ -158,9 +159,14 @@ sem_timedwait:
 #endif
 	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
 #if USE___THREAD
-	movl	%gs:0, %edx
-	subl	errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+	movl	errno@gotntpoff(%ebx), %edx
+	addl	%gs:0, %edx
 	movl	%esi, (%edx)
+# else
+	movl	errno@gotntpoff(%ebx), %edx
+	movl	%esi, %gs:(%edx)
+# endif
 #else
 	call	__errno_location@plt
 	movl	%esi, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
index a7c405d95f..fbc3b3c932 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -42,7 +42,7 @@ __new_sem_trywait:
 	leal	-1(%eax), %edx
 	LOCK
 	cmpxchgl %edx, (%ecx)
-	jne,pn	2b
+	jne	2b
 	xorl	%eax, %eax
 	ret
 
@@ -55,9 +55,14 @@ __new_sem_trywait:
 #endif
 	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
 #if USE___THREAD
-	movl	%gs:0, %edx
-	subl	errno@gottpoff(%ecx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+	movl	errno@gotntpoff(%ecx), %edx
+	addl	%gs:0, %edx
 	movl	$EAGAIN, (%edx)
+# else
+	movl	errno@gotntpoff(%ecx), %edx
+	movl	$EAGAIN, %gs:(%edx)
+# endif
 #else
 	call	__errno_location@plt
 	movl	$EAGAIN, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
index b7674dc3ba..b1296275d0 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -57,12 +57,12 @@ __new_sem_wait:
 	cfi_offset(6, -12)		/* %esi */
 3:	movl	(%ebx), %eax
 2:	testl	%eax, %eax
-	je,pn	1f
+	je	1f
 
 	leal	-1(%eax), %edx
 	LOCK
 	cmpxchgl %edx, (%ebx)
-	jne,pn	2b
+	jne	2b
 	xorl	%eax, %eax
 
 	movl	4(%esp), %esi
@@ -73,7 +73,7 @@ __new_sem_wait:
 	cfi_adjust_cfa_offset(-12)
 	ret
 
-	cfi_adjust_cfa_offset(8)
+	cfi_adjust_cfa_offset(12)
 	cfi_offset(3, -8)		/* %ebx */
 	cfi_offset(6, -12)		/* %esi */
 1:	call	__pthread_enable_asynccancel
@@ -102,9 +102,14 @@ __new_sem_wait:
 #endif
 	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
 #if USE___THREAD
-	movl	%gs:0, %edx
-	subl	errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+	movl	errno@gotntpoff(%ebx), %edx
+	addl	%gs:0, %edx
 	movl	%esi, (%edx)
+# else
+	movl	errno@gotntpoff(%ebx), %edx
+	movl	%esi, %gs:(%edx)
+# endif
 #else
 	call	__errno_location@plt
 	movl	%esi, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
new file mode 100644
index 0000000000..f768e16a7d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 "../i486/lowlevelrobustlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
new file mode 100644
index 0000000000..f768e16a7d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 "../i486/lowlevelrobustlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index b86f11c9b4..21de09fe91 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -35,6 +35,9 @@
 #define SYS_futex		240
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 
 /* Initializer for compatibility lock.  */
@@ -65,18 +68,112 @@
 #define BUSY_WAIT_NOP          asm ("rep; nop")
 
 
+#define LLL_STUB_UNWIND_INFO_START \
+	".section	.eh_frame,\"a\",@progbits\n"		\
+"5:\t"	".long	7f-6f	# Length of Common Information Entry\n"	\
+"6:\t"	".long	0x0	# CIE Identifier Tag\n\t"		\
+	".byte	0x1	# CIE Version\n\t"			\
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"		\
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"	\
+	".sleb128 -4	# CIE Data Alignment Factor\n\t"	\
+	".byte	0x8	# CIE RA Column\n\t"			\
+	".uleb128 0x1	# Augmentation size\n\t"		\
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"	\
+	".byte	0xc	# DW_CFA_def_cfa\n\t"			\
+	".uleb128 0x4\n\t"					\
+	".uleb128 0x0\n\t"					\
+	".align 4\n"						\
+"7:\t"	".long	17f-8f	# FDE Length\n"				\
+"8:\t"	".long	8b-5b	# FDE CIE offset\n\t"			\
+	".long	1b-.	# FDE initial location\n\t"		\
+	".long	4b-1b	# FDE address range\n\t"		\
+	".uleb128 0x0	# Augmentation size\n\t"		\
+	".byte	0x16	# DW_CFA_val_expression\n\t"		\
+	".uleb128 0x8\n\t"					\
+	".uleb128 10f-9f\n"					\
+"9:\t"	".byte	0x78	# DW_OP_breg8\n\t"			\
+	".sleb128 3b-1b\n"
+#define LLL_STUB_UNWIND_INFO_END \
+	".byte	0x16	# DW_CFA_val_expression\n\t"		\
+	".uleb128 0x8\n\t"					\
+	".uleb128 12f-11f\n"					\
+"11:\t"	".byte	0x78	# DW_OP_breg8\n\t"			\
+	".sleb128 3b-2b\n"					\
+"12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"	\
+	".byte	0x16	# DW_CFA_val_expression\n\t"		\
+	".uleb128 0x8\n\t"					\
+	".uleb128 16f-13f\n"					\
+"13:\t"	".byte	0x78	# DW_OP_breg8\n\t"			\
+	".sleb128 15f-14f\n\t"					\
+	".byte	0x0d	# DW_OP_const4s\n"			\
+"14:\t"	".4byte	3b-.\n\t"					\
+	".byte	0x1c	# DW_OP_minus\n\t"			\
+	".byte	0x0d	# DW_OP_const4s\n"			\
+"15:\t"	".4byte	18f-.\n\t"					\
+	".byte	0x22	# DW_OP_plus\n"				\
+"16:\t"	".align 4\n"						\
+"17:\t"	".previous\n"
+
+/* Unwind info for
+   1: lea ..., ...
+   2: call ...
+   3: jmp 18f
+   4:
+   snippet.  */
+#define LLL_STUB_UNWIND_INFO_3 \
+LLL_STUB_UNWIND_INFO_START					\
+"10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"	\
+LLL_STUB_UNWIND_INFO_END
+
+/* Unwind info for
+   1: lea ..., ...
+   0: movl ..., ...
+   2: call ...
+   3: jmp 18f
+   4:
+   snippet.  */
+#define LLL_STUB_UNWIND_INFO_4 \
+LLL_STUB_UNWIND_INFO_START					\
+"10:\t"	".byte	0x40 + (0b-1b) # DW_CFA_advance_loc\n\t"	\
+	".byte	0x16	# DW_CFA_val_expression\n\t"		\
+	".uleb128 0x8\n\t"					\
+	".uleb128 20f-19f\n"					\
+"19:\t"	".byte	0x78	# DW_OP_breg8\n\t"			\
+	".sleb128 3b-0b\n"					\
+"20:\t"	".byte	0x40 + (2b-0b) # DW_CFA_advance_loc\n\t"	\
+LLL_STUB_UNWIND_INFO_END
+
+
 #define lll_futex_wait(futex, val) \
-  do {									      \
-    int __ignore;							      \
+  ({									      \
+    int __status;							      \
     register __typeof (val) _val asm ("edx") = (val);			      \
     __asm __volatile (LLL_EBX_LOAD					      \
 		      LLL_ENTER_KERNEL					      \
 		      LLL_EBX_LOAD					      \
-		      : "=a" (__ignore)					      \
+		      : "=a" (__status)					      \
 		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),	      \
 			"c" (FUTEX_WAIT), "d" (_val),			      \
-			"i" (offsetof (tcbhead_t, sysinfo)));		      \
-  } while (0)
+			"i" (offsetof (tcbhead_t, sysinfo))		      \
+		      : "memory");					      \
+    __status;								      \
+  })
+
+
+#define lll_futex_timed_wait(futex, val, timeout)			      \
+  ({									      \
+    int __status;							      \
+    register __typeof (val) _val asm ("edx") = (val);			      \
+    __asm __volatile (LLL_EBX_LOAD					      \
+		      LLL_ENTER_KERNEL					      \
+		      LLL_EBX_LOAD					      \
+		      : "=a" (__status)					      \
+		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout),  \
+			"c" (FUTEX_WAIT), "d" (_val),			      \
+			"i" (offsetof (tcbhead_t, sysinfo))		      \
+		      : "memory");					      \
+    __status;								      \
+  })
 
 
 #define lll_futex_wake(futex, nr) \
@@ -121,6 +218,16 @@ extern int __lll_mutex_unlock_wake (int *__futex)
      ret; })
 
 
+#define lll_robust_mutex_trylock(futex, id) \
+  ({ int ret;								      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (id), "m" (futex),				      \
+			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \
+		       : "memory");					      \
+     ret; })
+
+
 #define lll_mutex_cond_trylock(futex) \
   ({ int ret;								      \
      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
@@ -137,18 +244,39 @@ extern int __lll_mutex_unlock_wake (int *__futex)
 			      "jnz _L_mutex_lock_%=\n\t"		      \
 			      ".subsection 1\n\t"			      \
 			      ".type _L_mutex_lock_%=,@function\n"	      \
-			      "_L_mutex_lock_%=:\n\t"			      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
+			      "_L_mutex_lock_%=:\n"			      \
+			      "1:\tleal %2, %%ecx\n"			      \
+			      "2:\tcall __lll_mutex_lock_wait\n"	      \
+			      "3:\tjmp 18f\n"				      \
+			      "4:\t.size _L_mutex_lock_%=, 4b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "1:"					      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
 			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
 			      : "0" (0), "1" (1), "m" (futex)		      \
 			      : "memory"); })
 
 
+#define lll_robust_mutex_lock(futex, id) \
+  ({ int result, ignore;						      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"			      \
+		       "jnz _L_robust_mutex_lock_%=\n\t"		      \
+		       ".subsection 1\n\t"				      \
+		       ".type _L_robust_mutex_lock_%=,@function\n"	      \
+		       "_L_robust_mutex_lock_%=:\n"			      \
+		       "1:\tleal %2, %%ecx\n"				      \
+		       "2:\tcall __lll_robust_mutex_lock_wait\n"	      \
+		       "3:\tjmp 18f\n"					      \
+		       "4:\t.size _L_robust_mutex_lock_%=, 4b-1b\n\t"	      \
+		       ".previous\n"					      \
+		       LLL_STUB_UNWIND_INFO_3				      \
+		       "18:"						      \
+		       : "=a" (result), "=c" (ignore), "=m" (futex)	      \
+		       : "0" (0), "1" (id), "m" (futex)			      \
+		       : "memory");					      \
+     result; })
+
+
 /* Special version of lll_mutex_lock which causes the unlock function to
    always wakeup waiters.  */
 #define lll_mutex_cond_lock(futex) \
@@ -157,32 +285,54 @@ extern int __lll_mutex_unlock_wake (int *__futex)
 			      "jnz _L_mutex_cond_lock_%=\n\t"		      \
 			      ".subsection 1\n\t"			      \
 			      ".type _L_mutex_cond_lock_%=,@function\n"	      \
-			      "_L_mutex_cond_lock_%=:\n\t"		      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"   \
+			      "_L_mutex_cond_lock_%=:\n"		      \
+			      "1:\tleal %2, %%ecx\n"			      \
+			      "2:\tcall __lll_mutex_lock_wait\n"	      \
+			      "3:\tjmp 18f\n"				      \
+			      "4:\t.size _L_mutex_cond_lock_%=, 4b-1b\n\t"    \
 			      ".previous\n"				      \
-			      "1:"					      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
 			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
 			      : "0" (0), "1" (2), "m" (futex)		      \
 			      : "memory"); })
 
 
+#define lll_robust_mutex_cond_lock(futex, id) \
+  ({ int result, ignore;						      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"			      \
+		       "jnz _L_robust_mutex_cond_lock_%=\n\t"		      \
+		       ".subsection 1\n\t"				      \
+		       ".type _L_robust_mutex_cond_lock_%=,@function\n"	      \
+		       "_L_robust_mutex_cond_lock_%=:\n"		      \
+		       "1:\tleal %2, %%ecx\n"				      \
+		       "2:\tcall __lll_robust_mutex_lock_wait\n"	      \
+		       "3:\tjmp 18f\n"					      \
+		       "4:\t.size _L_robust_mutex_cond_lock_%=, 4b-1b\n\t"    \
+		       ".previous\n"					      \
+		       LLL_STUB_UNWIND_INFO_3				      \
+		       "18:"						      \
+		       : "=a" (result), "=c" (ignore), "=m" (futex)	      \
+		       : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex)	      \
+		       : "memory");					      \
+     result; })
+
+
 #define lll_mutex_timedlock(futex, timeout) \
   ({ int result, ignore1, ignore2;					      \
      __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"			      \
 		       "jnz _L_mutex_timedlock_%=\n\t"			      \
 		       ".subsection 1\n\t"				      \
 		       ".type _L_mutex_timedlock_%=,@function\n"	      \
-		       "_L_mutex_timedlock_%=:\n\t"			      \
-		       "leal %3, %%ecx\n\t"				      \
-		       "movl %7, %%edx\n\t"				      \
-		       "call __lll_mutex_timedlock_wait\n\t"		      \
-		       "jmp 1f\n\t"					      \
-		       ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\
+		       "_L_mutex_timedlock_%=:\n"			      \
+		       "1:\tleal %3, %%ecx\n"				      \
+		       "0:\tmovl %7, %%edx\n"				      \
+		       "2:\tcall __lll_mutex_timedlock_wait\n"		      \
+		       "3:\tjmp 18f\n"					      \
+		       "4:\t.size _L_mutex_timedlock_%=, 4b-1b\n\t"	      \
 		       ".previous\n"					      \
-		       "1:"						      \
+		       LLL_STUB_UNWIND_INFO_4				      \
+		       "18:"						      \
 		       : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
 			 "=m" (futex)					      \
 		       : "0" (0), "1" (1), "m" (futex), "m" (timeout)	      \
@@ -190,24 +340,95 @@ extern int __lll_mutex_unlock_wake (int *__futex)
      result; })
 
 
+#define lll_robust_mutex_timedlock(futex, timeout, id) \
+  ({ int result, ignore1, ignore2;					      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"			      \
+		       "jnz _L_robust_mutex_timedlock_%=\n\t"		      \
+		       ".subsection 1\n\t"				      \
+		       ".type _L_robust_mutex_timedlock_%=,@function\n"	      \
+		       "_L_robust_mutex_timedlock_%=:\n"		      \
+		       "1:\tleal %3, %%ecx\n"				      \
+		       "0:\tmovl %7, %%edx\n"				      \
+		       "2:\tcall __lll_robust_mutex_timedlock_wait\n"	      \
+		       "3:\tjmp 18f\n"					      \
+		       "4:\t.size _L_robust_mutex_timedlock_%=, 4b-1b\n\t"    \
+		       ".previous\n"					      \
+		       LLL_STUB_UNWIND_INFO_4				      \
+		       "18:"						      \
+		       : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
+			 "=m" (futex)					      \
+		       : "0" (0), "1" (id), "m" (futex), "m" (timeout)	      \
+		       : "memory");					      \
+     result; })
+
+
 #define lll_mutex_unlock(futex) \
   (void) ({ int ignore;							      \
-            __asm __volatile (LOCK_INSTR "subl $1,%0\n\t"		      \
+            __asm __volatile (LOCK_INSTR "subl $1, %0\n\t"		      \
 			      "jne _L_mutex_unlock_%=\n\t"		      \
 			      ".subsection 1\n\t"			      \
 			      ".type _L_mutex_unlock_%=,@function\n"	      \
-			      "_L_mutex_unlock_%=:\n\t"			      \
-			      "leal %0, %%eax\n\t"			      \
-			      "call __lll_mutex_unlock_wake\n\t"	      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
+			      "_L_mutex_unlock_%=:\n"			      \
+			      "1:\tleal %0, %%eax\n"			      \
+			      "2:\tcall __lll_mutex_unlock_wake\n"	      \
+			      "3:\tjmp 18f\n"				      \
+			      "4:\t.size _L_mutex_unlock_%=, 4b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "1:"					      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
 			      : "=m" (futex), "=&a" (ignore)		      \
 			      : "m" (futex)				      \
 			      : "memory"); })
 
 
+#define lll_robust_mutex_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm __volatile (LOCK_INSTR "andl %2, %0\n\t"		      \
+			      "jne _L_robust_mutex_unlock_%=\n\t"	      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_robust_mutex_unlock_%=,@function\n"   \
+			      "_L_robust_mutex_unlock_%=:\n\t"		      \
+			      "1:\tleal %0, %%eax\n"			      \
+			      "2:\tcall __lll_mutex_unlock_wake\n"	      \
+			      "3:\tjmp 18f\n"				      \
+			      "4:\t.size _L_robust_mutex_unlock_%=, 4b-1b\n\t"\
+			      ".previous\n"				      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
+			      : "=m" (futex), "=&a" (ignore)		      \
+			      : "i" (FUTEX_WAITERS), "m" (futex)	      \
+			      : "memory"); })
+
+
+#define lll_robust_mutex_dead(futex) \
+  (void) ({ int __ignore;						      \
+	    register int _nr asm ("edx") = 1;				      \
+	    __asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t"		      \
+			      LLL_EBX_LOAD				      \
+			      LLL_ENTER_KERNEL				      \
+			      LLL_EBX_LOAD				      \
+			      : "=a" (__ignore)				      \
+			      : "0" (SYS_futex), LLL_EBX_REG (&(futex)),      \
+				"c" (FUTEX_WAKE), "d" (_nr),		      \
+				"i" (FUTEX_OWNER_DIED),			      \
+				"i" (offsetof (tcbhead_t, sysinfo))); })
+
+
+#define lll_futex_wake(futex, nr) \
+  do {									      \
+    int __ignore;							      \
+    register __typeof (nr) _nr asm ("edx") = (nr);			      \
+    __asm __volatile (LLL_EBX_LOAD					      \
+		      LLL_ENTER_KERNEL					      \
+		      LLL_EBX_LOAD					      \
+		      : "=a" (__ignore)					      \
+		      : "0" (SYS_futex), LLL_EBX_REG (futex),		      \
+			"c" (FUTEX_WAKE), "d" (_nr),			      \
+			"i" (0) /* phony, to align next arg's number */,      \
+			"i" (offsetof (tcbhead_t, sysinfo)));		      \
+  } while (0)
+
+
 #define lll_mutex_islocked(futex) \
   (futex != 0)
 
@@ -250,7 +471,7 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 # define lll_trylock(futex) \
   ({ unsigned char ret;							      \
      __asm __volatile ("cmpl $0, %%gs:%P5\n\t"				      \
-		       "je,pt 0f\n\t"					      \
+		       "je 0f\n\t"					      \
 		       "lock\n"						      \
 		       "0:\tcmpxchgl %2, %1; setne %0"			      \
 		       : "=a" (ret), "=m" (futex)			      \
@@ -264,19 +485,20 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 # define lll_lock(futex) \
   (void) ({ int ignore1, ignore2;					      \
 	    __asm __volatile ("cmpl $0, %%gs:%P6\n\t"			      \
-			      "je,pt 0f\n\t"				      \
+			      "je 0f\n\t"				      \
 			      "lock\n"					      \
 			      "0:\tcmpxchgl %1, %2\n\t"			      \
-			      "jnz _L_mutex_lock_%=\n\t"		      \
+			      "jnz _L_lock_%=\n\t"			      \
 			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_lock_%=,@function\n"	      \
-			      "_L_mutex_lock_%=:\n\t"			      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
+			      ".type _L_lock_%=,@function\n"		      \
+			      "_L_lock_%=:\n"				      \
+			      "1:\tleal %2, %%ecx\n"			      \
+			      "2:\tcall __lll_mutex_lock_wait\n"	      \
+			      "3:\tjmp 18f\n"				      \
+			      "4:\t.size _L_lock_%=, 4b-1b\n\t"		      \
 			      ".previous\n"				      \
-			      "1:"					      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
 			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
 			      : "0" (0), "1" (1), "m" (futex),		      \
 		                "i" (offsetof (tcbhead_t, multiple_threads))  \
@@ -286,19 +508,20 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 # define lll_unlock(futex) \
   (void) ({ int ignore;							      \
             __asm __volatile ("cmpl $0, %%gs:%P3\n\t"			      \
-			      "je,pt 0f\n\t"				      \
+			      "je 0f\n\t"				      \
 			      "lock\n"					      \
-			      "0:\tsubl $1,%0\n\t"		      \
-			      "jne _L_mutex_unlock_%=\n\t"		      \
+			      "0:\tsubl $1,%0\n\t"			      \
+			      "jne _L_unlock_%=\n\t"			      \
 			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_unlock_%=,@function\n"	      \
-			      "_L_mutex_unlock_%=:\n\t"			      \
-			      "leal %0, %%eax\n\t"			      \
-			      "call __lll_mutex_unlock_wake\n\t"	      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
+			      ".type _L_unlock_%=,@function\n"		      \
+			      "_L_unlock_%=:\n"				      \
+			      "1:\tleal %0, %%eax\n"			      \
+			      "2:\tcall __lll_mutex_unlock_wake\n"	      \
+			      "3:\tjmp 18f\n\t"				      \
+			      "4:\t.size _L_unlock_%=, 4b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "1:"					      \
+			      LLL_STUB_UNWIND_INFO_3			      \
+			      "18:"					      \
 			      : "=m" (futex), "=&a" (ignore)		      \
 			      : "m" (futex),				      \
 				"i" (offsetof (tcbhead_t, multiple_threads))  \
@@ -325,12 +548,13 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 			"1:\tmovl %1, %%eax\n\t"			      \
 			LLL_ENTER_KERNEL				      \
 			"cmpl $0, (%%ebx)\n\t"				      \
-			"jne,pn 1b\n\t"					      \
+			"jne 1b\n\t"					      \
 			LLL_EBX_LOAD					      \
 			: "=&a" (__ignore)				      \
 			: "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),	      \
 			  "c" (FUTEX_WAIT), "d" (_tid),			      \
-			  "i" (offsetof (tcbhead_t, sysinfo)));		      \
+			  "i" (offsetof (tcbhead_t, sysinfo))		      \
+			: "memory");					      \
   } while (0)
 
 extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h
index cc3282fbdd..6557359b43 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h
@@ -1,5 +1,5 @@
 /* Uncancelable versions of cancelable interfaces.  Linux/NPTL version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -26,13 +26,21 @@ extern int __close_nocancel (int) attribute_hidden;
 extern int __read_nocancel (int, void *, size_t) attribute_hidden;
 extern int __write_nocancel (int, const void *, size_t) attribute_hidden;
 extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden;
+extern int __openat_nocancel (int fd, const char *fname, int oflag,
+				mode_t mode) attribute_hidden;
+extern int __openat64_nocancel (int fd, const char *fname, int oflag,
+				  mode_t mode) attribute_hidden;
 #else
-#define __open_nocancel(name, ...) __open (name, __VA_ARGS__)
-#define __close_nocancel(fd) __close (fd)
-#define __read_nocancel(fd, buf, len) __read (fd, buf, len)
-#define __write_nocancel(fd, buf, len) __write (fd, buf, len)
-#define __waitpid_nocancel(pid, stat_loc, options) \
+# define __open_nocancel(name, ...) __open (name, __VA_ARGS__)
+# define __close_nocancel(fd) __close (fd)
+# define __read_nocancel(fd, buf, len) __read (fd, buf, len)
+# define __write_nocancel(fd, buf, len) __write (fd, buf, len)
+# define __waitpid_nocancel(pid, stat_loc, options) \
   __waitpid (pid, stat_loc, options)
+# define __openat_nocancel(fd, fname, oflag, mode) \
+  openat (fd, fname, oflag, mode)
+# define __openat64_nocancel(fd, fname, oflag, mode) \
+  openat64 (fd, fname, oflag, mode)
 #endif
 
 /* Uncancelable open.  */
@@ -41,6 +49,16 @@ extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden;
 #define open_not_cancel_2(name, flags) \
    __open_nocancel (name, flags)
 
+/* Uncancelable openat.  */
+#define openat_not_cancel(fd, fname, oflag, mode) \
+  __openat_nocancel (fd, fname, oflag, mode)
+#define openat_not_cancel_3(fd, fname, oflag) \
+  __openat_nocancel (fd, fname, oflag, 0)
+#define openat64_not_cancel(fd, fname, oflag, mode) \
+  __openat64_nocancel (fd, fname, oflag, mode)
+#define openat64_not_cancel_3(fd, fname, oflag) \
+  __openat64_nocancel (fd, fname, oflag, 0)
+
 /* Uncancelable close.  */
 #define close_not_cancel(fd) \
   __close_nocancel (fd)
@@ -73,3 +91,15 @@ extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden;
 # define waitpid_not_cancel(pid, stat_loc, options) \
   INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL)
 #endif
+
+/* Uncancelable pause.  */
+#define pause_not_cancel() \
+  __pause_nocancel ()
+
+/* Uncancelable nanosleep.  */
+#define nanosleep_not_cancel(requested_time, remaining) \
+  __nanosleep_nocancel (requested_time, remaining)
+
+/* Uncancelable sigsuspend.  */
+#define sigsuspend_not_cancel(set) \
+  __sigsuspend_nocancel (set)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/smp.h b/nptl/sysdeps/unix/sysv/linux/i386/smp.h
new file mode 100644
index 0000000000..f68a0c0758
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/smp.h
@@ -0,0 +1,56 @@
+/* Determine whether the host has multiple processors.  Linux version.
+   Copyright (C) 1996, 2002, 2004, 2006 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  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 <string.h>
+#include <sys/utsname.h>
+#include <not-cancel.h>
+
+/* Test whether the machine has more than one processor.  This is not the
+   best test but good enough.  More complicated tests would require `malloc'
+   which is not available at that time.  */
+static inline int
+is_smp_system (void)
+{
+  union
+  {
+    struct utsname uts;
+    char buf[512];
+  } u;
+  char *cp;
+
+  /* Try reading the number using `sysctl' first.  */
+  if (uname (&u.uts) == 0)
+    cp = u.uts.version;
+  else
+    {
+      /* This was not successful.  Now try reading the /proc filesystem.  */
+      int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY);
+      if (__builtin_expect (fd, 0) == -1
+	  || read_not_cancel (fd, u.buf, sizeof (u.buf)) <= 0)
+	/* This also didn't work.  We give up and say it's a UP machine.  */
+	u.buf[0] = '\0';
+
+      close_not_cancel_no_status (fd);
+      cp = u.buf;
+    }
+
+  return strstr (cp, "SMP") != NULL;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
index 8142455781..d60dcd33d5 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -29,7 +29,6 @@
 # define PSEUDO(name, syscall_name, args)				      \
   .text;								      \
   ENTRY (name)								      \
-  L(name##START):							      \
     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;				      \
     jne L(pseudo_cancel);						      \
   .type __##syscall_name##_nocancel,@function;				      \
@@ -51,258 +50,11 @@
     POPSTATE_##args							      \
     cmpl $-4095, %eax;							      \
     jae SYSCALL_ERROR_LABEL;						      \
-  L(pseudo_end):							      \
-									      \
-  /* Create unwinding information for the syscall wrapper.  */		      \
-  .section .eh_frame,"a",@progbits;					      \
-  L(STARTFRAME):							      \
-    /* Length of the CIE.  */						      \
-    .long L(ENDCIE)-L(STARTCIE);					      \
-  L(STARTCIE):								      \
-    /* CIE ID.  */							      \
-    .long 0;								      \
-    /* Version number.  */						      \
-    .byte 1;								      \
-    /* NUL-terminated augmentation string.  */				      \
-    AUGMENTATION_STRING;						      \
-    /* Code alignment factor.  */					      \
-    .uleb128 1;								      \
-    /* Data alignment factor.  */					      \
-    .sleb128 -4;							      \
-    /* Return address register column.  */				      \
-    .byte 8;								      \
-    /* Optional augmentation parameter.  */				      \
-    AUGMENTATION_PARAM							      \
-    /* Start of the table initialization.  */				      \
-    .byte 0xc;			/* DW_CFA_def_cfa */			      \
-    .uleb128 4;								      \
-    .uleb128 4;								      \
-    .byte 0x88;			/* DW_CFA_offset, column 0x8 */		      \
-    .uleb128 1;								      \
-    .align 4;								      \
-  L(ENDCIE):								      \
-    /* Length of the FDE.  */						      \
-    .long L(ENDFDE)-L(STARTFDE);					      \
-  L(STARTFDE):								      \
-    /* CIE pointer.  */							      \
-    .long L(STARTFDE)-L(STARTFRAME);					      \
-    /* Start address of the code.  */					      \
-    START_SYMBOL_REF (name);						      \
-    /* Length of the code.  */						      \
-    .long L(name##END)-L(name##START);					      \
-    /* Augmentation data.  */						      \
-    AUGMENTATION_PARAM_FDE						      \
-    /* The rest of the code depends on the number of parameters the syscall   \
-       takes.  */							      \
-    EH_FRAME_##args(name);						      \
-    .align 4;								      \
-  L(ENDFDE):								      \
-  .previous
-
-# ifdef SHARED
-/* NUL-terminated augmentation string.  Note "z" means there is an
-   augmentation value later on.  */
-#  define AUGMENTATION_STRING .string "zR"
-#  define AUGMENTATION_PARAM \
-    /* Augmentation value length.  */					      \
-    .uleb128 1;								      \
-    /* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4.  */			      \
-    .byte 0x1b;
-#  define AUGMENTATION_PARAM_FDE \
-    /* No augmentation data.  */					      \
-    .uleb128 0;
-#  define START_SYMBOL_REF(name) \
-    /* PC-relative start address of the code.  */			      \
-    .long L(name##START)-.
-# else
-/* No augmentation.  */
-#  define AUGMENTATION_STRING .ascii "\0"
-#  define AUGMENTATION_PARAM /* nothing */
-#  define AUGMENTATION_PARAM_FDE /* nothing */
-#  define START_SYMBOL_REF(name) \
-    /* Absolute start address of the code.  */				      \
-    .long L(name##START)
-# endif
-
-/* Callframe description for syscalls without parameters.  This is very
-   simple.  The only place the stack pointer is changed is when the old
-   cancellation state value is saved.  */
-# define EH_FRAME_0(name) \
-    .byte 0x40+L(PUSHSTATE)-L(name##START);	/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x40+L(POPSTATE)-L(PUSHSTATE);	/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4
-
-/* For syscalls with one and two parameters the code is the same as for
-   those which take no parameter.  */
-# define EH_FRAME_1(name) \
-    .byte 0x40+L(SAVEBX1)-L(name##START);	/* DW_CFA_advance_loc+N */    \
-    .byte 9;					/* DW_CFA_register */	      \
-    .uleb128 3;					/* %ebx */		      \
-    .uleb128 2;					/* %edx */		      \
-    .byte 0x40+L(RESTBX1)-L(SAVEBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(PUSHSTATE)-L(RESTBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x40+L(SAVEBX2)-L(PUSHSTATE);		/* DW_CFA_advance_loc+N */    \
-    .byte 9;					/* DW_CFA_register */	      \
-    .uleb128 3;					/* %ebx */		      \
-    .uleb128 2;					/* %edx */		      \
-    .byte 0x40+L(RESTBX2)-L(SAVEBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSTATE)-L(RESTBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4
-
-# define EH_FRAME_2(name) EH_FRAME_1 (name)
-
-/* For syscalls with three parameters the stack pointer is changed
-   also to save the content of the %ebx register.  */
-# define EH_FRAME_3(name) \
-    .byte 0x40+L(PUSHBX1)-L(name##START);	/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 2;								      \
-    .byte 0x40+L(POPBX1)-L(PUSHBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4;								      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(PUSHSTATE)-L(POPBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x40+L(PUSHBX2)-L(PUSHSTATE);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 3;								      \
-    .byte 0x40+L(POPBX2)-L(PUSHBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSTATE)-L(POPBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4
-
-/* With four parameters the syscall wrappers have to save %ebx and %esi.  */
-# define EH_FRAME_4(name) \
-    .byte 0x40+L(PUSHSI1)-L(name##START);	/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x86;					/* DW_CFA_offset %esi */      \
-    .uleb128 2;								      \
-    .byte 0x40+L(PUSHBX1)-L(PUSHSI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 3;								      \
-    .byte 0x40+L(POPBX1)-L(PUSHBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSI1)-L(POPBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4;								      \
-    .byte 0xc6;					/* DW_CFA_restore %esi */     \
-    .byte 0x40+L(PUSHSTATE)-L(POPSI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x40+L(PUSHSI2)-L(PUSHSTATE);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0x86;					/* DW_CFA_offset %esi */      \
-    .uleb128 3;								      \
-    .byte 0x40+L(PUSHBX2)-L(PUSHSI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 16;							      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 4;								      \
-    .byte 0x40+L(POPBX2)-L(PUSHBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSI2)-L(POPBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0xc6;					/* DW_CFA_restore %esi */     \
-    .byte 0x40+L(POPSTATE)-L(POPSI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4
-
-/* With five parameters the syscall wrappers have to save %ebx, %esi,
-   and %edi.  */
-# define EH_FRAME_5(name) \
-    .byte 0x40+L(PUSHDI1)-L(name##START);	/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x87;					/* DW_CFA_offset %edi */      \
-    .uleb128 2;								      \
-    .byte 0x40+L(PUSHSI1)-L(PUSHDI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0x86;					/* DW_CFA_offset %esi */      \
-    .uleb128 3;								      \
-    .byte 0x40+L(PUSHBX1)-L(PUSHSI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 16;							      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 4;								      \
-    .byte 0x40+L(POPBX1)-L(PUSHBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSI1)-L(POPBX1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0xc6;					/* DW_CFA_restore %esi */     \
-    .byte 0x40+L(POPDI1)-L(POPSI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4;								      \
-    .byte 0xc7;					/* DW_CFA_restore %edi */     \
-    .byte 0x40+L(PUSHSTATE)-L(POPDI1);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0x40+L(PUSHDI2)-L(PUSHSTATE);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0x87;					/* DW_CFA_offset %edi */      \
-    .uleb128 3;								      \
-    .byte 0x40+L(PUSHSI2)-L(PUSHDI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 16;							      \
-    .byte 0x86;					/* DW_CFA_offset %esi */      \
-    .uleb128 4;								      \
-    .byte 0x40+L(PUSHBX2)-L(PUSHSI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 20;							      \
-    .byte 0x83;					/* DW_CFA_offset %ebx */      \
-    .uleb128 5;								      \
-    .byte 0x40+L(POPBX2)-L(PUSHBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 16;							      \
-    .byte 0xc3;					/* DW_CFA_restore %ebx */     \
-    .byte 0x40+L(POPSI2)-L(POPBX2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 12;							      \
-    .byte 0xc6;					/* DW_CFA_restore %esi */     \
-    .byte 0x40+L(POPDI2)-L(POPSI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 8;								      \
-    .byte 0xc7;					/* DW_CFA_restore %edi */     \
-    .byte 0x40+L(POPSTATE)-L(POPDI2);		/* DW_CFA_advance_loc+N */    \
-    .byte 14;					/* DW_CFA_def_cfa_offset */   \
-    .uleb128 4
-
-
-# undef ASM_SIZE_DIRECTIVE
-# define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name;
+  L(pseudo_end):
 
 # define SAVE_OLDTYPE_0	movl %eax, %ecx;
 # define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0
-# define SAVE_OLDTYPE_2	pushl %eax; L(PUSHSTATE):
+# define SAVE_OLDTYPE_2	pushl %eax; cfi_adjust_cfa_offset (4);
 # define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2
 # define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2
 # define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2
@@ -313,11 +65,13 @@
 # define _PUSHCARGS_0	/* No arguments to push.  */
 # define _POPCARGS_0	/* No arguments to pop.  */
 
-# define PUSHCARGS_1	movl %ebx, %edx; L(SAVEBX2): PUSHCARGS_0
+# define PUSHCARGS_1	movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0
 # define DOCARGS_1	_DOARGS_1 (4)
-# define POPCARGS_1	POPCARGS_0; movl %edx, %ebx; L(RESTBX2):
-# define _PUSHCARGS_1	pushl %ebx; L(PUSHBX2): _PUSHCARGS_0
-# define _POPCARGS_1	_POPCARGS_0; popl %ebx; L(POPBX2):
+# define POPCARGS_1	POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx);
+# define _PUSHCARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \
+			cfi_rel_offset (ebx, 0); _PUSHCARGS_0
+# define _POPCARGS_1	_POPCARGS_0; popl %ebx; \
+			cfi_adjust_cfa_offset (-4); cfi_restore (ebx);
 
 # define PUSHCARGS_2	PUSHCARGS_1
 # define DOCARGS_2	_DOARGS_2 (12)
@@ -334,14 +88,18 @@
 # define PUSHCARGS_4	_PUSHCARGS_4
 # define DOCARGS_4	_DOARGS_4 (28)
 # define POPCARGS_4	_POPCARGS_4
-# define _PUSHCARGS_4	pushl %esi; L(PUSHSI2): _PUSHCARGS_3
-# define _POPCARGS_4	_POPCARGS_3; popl %esi; L(POPSI2):
+# define _PUSHCARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \
+			cfi_rel_offset (esi, 0); _PUSHCARGS_3
+# define _POPCARGS_4	_POPCARGS_3; popl %esi; \
+			cfi_adjust_cfa_offset (-4); cfi_restore (esi);
 
 # define PUSHCARGS_5	_PUSHCARGS_5
 # define DOCARGS_5	_DOARGS_5 (36)
 # define POPCARGS_5	_POPCARGS_5
-# define _PUSHCARGS_5	pushl %edi; L(PUSHDI2): _PUSHCARGS_4
-# define _POPCARGS_5	_POPCARGS_4; popl %edi; L(POPDI2):
+# define _PUSHCARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \
+			cfi_rel_offset (edi, 0); _PUSHCARGS_4
+# define _POPCARGS_5	_POPCARGS_4; popl %edi; \
+			cfi_adjust_cfa_offset (-4); cfi_restore (edi);
 
 # ifdef IS_IN_libpthread
 #  define CENABLE	call __pthread_enable_asynccancel;
@@ -356,9 +114,11 @@
 #  error Unsupported library
 # endif
 # define POPSTATE_0 \
- pushl %eax; L(PUSHSTATE): movl %ecx, %eax; CDISABLE; popl %eax; L(POPSTATE):
+ pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \
+ CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4);
 # define POPSTATE_1	POPSTATE_0
-# define POPSTATE_2	xchgl (%esp), %eax; CDISABLE; popl %eax; L(POPSTATE):
+# define POPSTATE_2	xchgl (%esp), %eax; CDISABLE; popl %eax; \
+			cfi_adjust_cfa_offset (-4);
 # define POPSTATE_3	POPSTATE_2
 # define POPSTATE_4	POPSTATE_3
 # define POPSTATE_5	POPSTATE_4
@@ -377,3 +137,9 @@
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/vfork.S b/nptl/sysdeps/unix/sysv/linux/i386/vfork.S
index 52336102c7..37f0842051 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/vfork.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999,2002,2004,2006 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,10 +16,17 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <tcb-offsets.h>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <vfork.S>
+#else
+
+# include <tcb-offsets.h>
 
 /* Save the PID value.  */
-#define SAVE_PID \
+# define SAVE_PID \
 	movl	%gs:PID, %edx; 						      \
 	movl	%edx, %eax;						      \
 	negl	%eax;							      \
@@ -28,11 +35,11 @@
 1:	movl	%eax, %gs:PID
 
 /* Restore the old PID value in the parent.  */
-#define RESTORE_PID \
+# define RESTORE_PID \
 	testl	%eax, %eax;						      \
 	je	1f;							      \
 	movl	%edx, %gs:PID;						      \
 1:
 
-
-#include <sysdeps/unix/sysv/linux/i386/vfork.S>
+# include_next <vfork.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S b/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S
index 1ceb210c2f..a1120d4d72 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -102,6 +102,9 @@ LEAF(__ia64_longjmp)
 	;;
 	ld8.nta r20=[r2],16		// b4
 	ld8.nta r21=[r3],16		// b5
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (r16, r24)
+#endif
 	;;
 	ld8.nta r11=[r2],16		// ar.pfs
 	ld8.nta r22=[r3],56		// ar.lc
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
index afb8800ac9..892769dca4 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -43,11 +43,18 @@ typedef union
 } pthread_attr_t;
 
 
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -57,6 +64,8 @@ typedef union
        binary compatibility.  */
     int __kind;
     int __spins;
+    __pthread_list_t __list;
+#define __PTHREAD_MUTEX_HAVE_PREV	1
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S b/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S
index 8664056f27..91f28bab37 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/ia64/clone2.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone2.S>
+#else
+# define RESET_PID
+# include_next <clone2.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c b/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c
index 8ac06e8101..cd5f8137d5 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
@@ -18,7 +18,7 @@
    02111-1307 USA.  */
 
 /* Value passed to 'clone' for initialization of the thread register.  */
-#define TLS_VALUE (pd + 1)
+#define TLS_VALUE ((char *) pd + TLS_PRE_TCB_SIZE)
 
 #define ARCH_CLONE __clone2
 
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
index af835c44b1..525b622a68 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
@@ -1,5 +1,5 @@
 /* System-specific settings for dynamic linker code.  IA-64 version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 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
@@ -57,7 +57,7 @@ extern int _dl_sysinfo_break attribute_hidden;
        ".body\n\t"				\
        "break 0x100000;\n\t"			\
        "br.ret.sptk.many b6;\n\t"		\
-       ".endp _dl_sysinfo_break"		\
+       ".endp _dl_sysinfo_break\n\t"		\
        ".previous");
 #endif
 
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h b/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h
deleted file mode 100644
index c6ef5f7fbd..0000000000
--- a/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
-
-   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 <setjmp.h>
-#include <stdint.h>
-#include <unwind.h>
-
-#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
-  ({ uintptr_t _cfa = (uintptr_t) _Unwind_GetCFA (_context) - (_adj);	\
-     (_cfa < (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj)		\
-      || (_cfa == (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj)		\
-	  && (uintptr_t) _Unwind_GetBSP (_context) - (_adj)		\
-	     >= (uintptr_t)(((long *)(_jmpbuf))[17]) - (_adj)));	\
-  })
-
-#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
-  ((uintptr_t)(_address) - (_adj) < (uintptr_t)(((long *)_jmpbuf)[0]) - (_adj))
-
-/* We use a longjmp() which can cross from the alternate signal-stack
-   to the normal stack.  */
-extern void __libc_unwind_longjmp (sigjmp_buf env, int val)
-          __attribute__ ((noreturn));
-hidden_proto (__libc_unwind_longjmp)
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
index e13358ffef..8df997a262 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -31,6 +31,11 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /* Delay in spinlock loop.  */
 #define BUSY_WAIT_NOP          asm ("hint @pause")
@@ -53,6 +58,15 @@
    _r10 == -1 ? -_retval : _retval;					\
 })
 
+#define lll_robust_mutex_dead(futexv)					\
+do									\
+  {									\
+    int *__futexp = &(futexv);						\
+    atomic_or (__futexp, FUTEX_OWNER_DIED);				\
+    DO_INLINE_SYSCALL(futex, 3, (long) __futexp, FUTEX_WAKE, 1);	\
+  }									\
+while (0)
+
 /* Returns non-zero if error happened, zero if success.  */
 #define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val)		     \
 ({									     \
@@ -62,18 +76,34 @@
    _r10 == -1;								     \
 })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(ftx, nr_wake, nr_wake2, ftx2)		     \
+({									     \
+   DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_WAKE_OP,		     \
+		     (int) (nr_wake), (int) (nr_wake2), (long) (ftx2),	     \
+		     FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);			     \
+   _r10 == -1;								     \
+})
+
 
 #define __lll_mutex_trylock(futex) \
   (atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0)
 #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
 
 
+#define __lll_robust_mutex_trylock(futex, id) \
+  (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
+#define lll_robust_mutex_trylock(futex, id) \
+  __lll_robust_mutex_trylock (&(futex), id)
+
+
 #define __lll_mutex_cond_trylock(futex) \
   (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0)
 #define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
 
 
 extern void __lll_lock_wait (int *futex) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
 
 
 #define __lll_mutex_lock(futex)						\
@@ -85,6 +115,18 @@ extern void __lll_lock_wait (int *futex) attribute_hidden;
 #define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
 
 
+#define __lll_robust_mutex_lock(futex, id)				\
+  ({									\
+    int *__futex = (futex);						\
+    int __val = 0;							\
+									\
+    if (atomic_compare_and_exchange_bool_acq (__futex, id, 0) != 0)	\
+      __val = __lll_robust_lock_wait (__futex);				\
+    __val;								\
+  })
+#define lll_robust_mutex_lock(futex, id) __lll_robust_mutex_lock (&(futex), id)
+
+
 #define __lll_mutex_cond_lock(futex)					\
   ((void) ({								\
     int *__futex = (futex);						\
@@ -94,8 +136,24 @@ extern void __lll_lock_wait (int *futex) attribute_hidden;
 #define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
 
 
+#define __lll_robust_mutex_cond_lock(futex, id)				\
+  ({									\
+    int *__futex = (futex);						\
+    int __val = 0;							\
+    int __id = (id) | FUTEX_WAITERS;					\
+									\
+    if (atomic_compare_and_exchange_bool_acq (__futex, __id, 0) != 0)	\
+      __val = __lll_robust_lock_wait (__futex);				\
+    __val;								\
+  })
+#define lll_robust_mutex_cond_lock(futex, id) \
+  __lll_robust_mutex_cond_lock (&(futex), id)
+
+
 extern int __lll_timedlock_wait (int *futex, const struct timespec *)
      attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *)
+     attribute_hidden;
 
 
 #define __lll_mutex_timedlock(futex, abstime)				\
@@ -111,6 +169,19 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *)
   __lll_mutex_timedlock (&(futex), abstime)
 
 
+#define __lll_robust_mutex_timedlock(futex, abstime, id)		\
+  ({									\
+    int *__futex = (futex);						\
+    int __val = 0;							\
+									\
+    if (atomic_compare_and_exchange_bool_acq (__futex, id, 0) != 0)	\
+      __val = __lll_robust_timedlock_wait (__futex, abstime);		\
+    __val;								\
+  })
+#define lll_robust_mutex_timedlock(futex, abstime, id) \
+  __lll_robust_mutex_timedlock (&(futex), abstime, id)
+
+
 #define __lll_mutex_unlock(futex)			\
   ((void) ({						\
     int *__futex = (futex);				\
@@ -123,6 +194,18 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *)
   __lll_mutex_unlock(&(futex))
 
 
+#define __lll_robust_mutex_unlock(futex)		\
+  ((void) ({						\
+    int *__futex = (futex);				\
+    int __val = atomic_exchange_rel (__futex, 0);	\
+							\
+    if (__builtin_expect (__val & FUTEX_WAITERS, 0))	\
+      lll_futex_wake (__futex, 1);			\
+  }))
+#define lll_robust_mutex_unlock(futex) \
+  __lll_robust_mutex_unlock(&(futex))
+
+
 #define __lll_mutex_unlock_force(futex)		\
   ((void) ({					\
     int *__futex = (futex);			\
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
index b7d4e57945..b6d2cec0d0 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
@@ -1,5 +1,5 @@
 /* Special .init and .fini section support for ia64. NPTL version.
-   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it
@@ -38,7 +38,6 @@
 
 #include <stddef.h>
 
-#ifdef HAVE_INITFINI_ARRAY
 
 __asm__ ("\n\
 #include \"defs.h\"\n\
@@ -49,95 +48,3 @@ __asm__ ("\n\
 	.xdata8 \".init_array\",@fptr(__pthread_initialize_minimal_internal)\n\
 /*@_init_PROLOG_ENDS*/\n\
 ");
-
-#else
-
-__asm__ ("\n\
-\n\
-#include \"defs.h\"\n\
-\n\
-/*@HEADER_ENDS*/\n\
-\n\
-/*@_init_PROLOG_BEGINS*/\n\
-	.section .init\n\
-	.align 16\n\
-	.global _init#\n\
-	.proc _init#\n\
-_init:\n\
-	.prologue\n\
-	.save ar.pfs, r34\n\
-	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
-	.vframe r32\n\
-	mov r32 = r12\n\
-	.save rp, r33\n\
-	mov r33 = b0\n\
-	.body\n\
-	adds r12 = -16, r12\n\
-	;;\n\
-	st8 [r12] = gp, -16\n\
-	br.call.sptk.many b0 = __pthread_initialize_minimal_internal# ;;\n\
-	;;\n\
-	adds r12 = 16, r12\n\
-	;;\n\
-	ld8 gp = [r12]\n\
-	;;\n\
-	.endp _init#\n\
-\n\
-/*@_init_PROLOG_ENDS*/\n\
-\n\
-/*@_init_EPILOG_BEGINS*/\n\
-	.section .init\n\
-	.proc _init#\n\
-	.prologue\n\
-	.save ar.pfs, r34\n\
-	.vframe r32\n\
-	.save rp, r33\n\
-	.body\n\
-	mov r12 = r32\n\
-	mov ar.pfs = r34\n\
-	mov b0 = r33\n\
-	br.ret.sptk.many b0\n\
-	.endp _init#\n\
-/*@_init_EPILOG_ENDS*/\n\
-\n\
-/*@_fini_PROLOG_BEGINS*/\n\
-	.section .fini\n\
-	.align 16\n\
-	.global _fini#\n\
-	.proc _fini#\n\
-_fini:\n\
-	.prologue\n\
-	.save ar.pfs, r34\n\
-	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
-	.vframe r32\n\
-	mov r32 = r12\n\
-	.save rp, r33\n\
-	mov r33 = b0\n\
-	.body\n\
-	adds r12 = -16, r12\n\
-	;;\n\
-	.endp _fini#\n\
-\n\
-/*@_fini_PROLOG_ENDS*/\n\
-\n\
-/*@_fini_EPILOG_BEGINS*/\n\
-	.section .fini\n\
-	.proc _fini#\n\
-	.prologue\n\
-	.save ar.pfs, r34\n\
-	.vframe r32\n\
-	.save rp, r33\n\
-	.body\n\
-	mov r12 = r32\n\
-	mov ar.pfs = r34\n\
-	mov b0 = r33\n\
-	br.ret.sptk.many b0\n\
-	.endp _fini#\n\
-\n\
-/*@_fini_EPILOG_ENDS*/\n\
-\n\
-/*@TRAILER_BEGINS*/\n\
-	.weak	__gmon_start__#\n\
-");
-
-#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
index 63aaa96eb0..c4d52860dd 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -220,3 +220,9 @@ __GC_##name:								      \
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c b/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
index fb44b426bc..d0c77a62e6 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
@@ -34,5 +34,6 @@ _Unwind_GetBSP (struct _Unwind_Context *context)
 {
   if (__builtin_expect (libgcc_s_getbsp == NULL, 0))
     pthread_cancel_init ();
+
   return libgcc_s_getbsp (context);
 }
diff --git a/nptl/sysdeps/unix/sysv/linux/kernel-features.h b/nptl/sysdeps/unix/sysv/linux/kernel-features.h
new file mode 100644
index 0000000000..162d73e388
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/kernel-features.h
@@ -0,0 +1,6 @@
+#include_next <kernel-features.h>
+
+/* NPTL can always assume all clone thread flags work.  */
+#ifndef __ASSUME_CLONE_THREAD_FLAGS
+# define __ASSUME_CLONE_THREAD_FLAGS	1
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
index 3d1c021819..714ad49428 100644
--- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,7 +19,7 @@
 
 #include <unistd.h>
 #include <list.h>
-#include "fork.h"
+#include <fork.h>
 #include <dl-sysdep.h>
 #include <tls.h>
 #include <string.h>
@@ -57,3 +57,11 @@ __libc_pthread_init (ptr, reclaim, functions)
   return &__libc_multiple_threads;
 #endif
 }
+
+#ifdef SHARED
+libc_freeres_fn (freeres_libptread)
+{
+  if (__libc_pthread_functions.ptr_freeres != NULL)
+    __libc_pthread_functions.ptr_freeres ();
+}
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
new file mode 100644
index 0000000000..30ef991bd0
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+#include <pthreadP.h>
+
+
+int
+__lll_robust_lock_wait (int *futex)
+{
+  int oldval = *futex;
+  int tid = THREAD_GETMEM (THREAD_SELF, tid);
+
+  /* If the futex changed meanwhile try locking again.  */
+  if (oldval == 0)
+    goto try;
+
+  do
+    {
+      if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0))
+	return oldval;
+
+      int newval = oldval | FUTEX_WAITERS;
+      if (oldval != newval
+	  && atomic_compare_and_exchange_bool_acq (futex, newval, oldval))
+	continue;
+
+      lll_futex_wait (futex, newval);
+
+    try:
+      ;
+    }
+  while ((oldval = atomic_compare_and_exchange_val_acq (futex,
+							tid | FUTEX_WAITERS,
+							0)) != 0);
+  return 0;
+}
+
+
+int
+__lll_robust_timedlock_wait (int *futex, const struct timespec *abstime)
+{
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  int tid = THREAD_GETMEM (THREAD_SELF, tid);
+  int oldval = *futex;
+
+  /* If the futex changed meanwhile try locking again.  */
+  if (oldval == 0)
+    goto try;
+
+  do
+    {
+      struct timeval tv;
+      struct timespec rt;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+	{
+	  rt.tv_nsec += 1000000000;
+	  --rt.tv_sec;
+	}
+
+      /* Already timed out?  */
+      if (rt.tv_sec < 0)
+	return ETIMEDOUT;
+
+      /* Wait.  */
+      if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0))
+	return oldval;
+
+      int newval = oldval | FUTEX_WAITERS;
+      if (oldval != newval
+	  && atomic_compare_and_exchange_bool_acq (futex, newval, oldval))
+	continue;
+
+      lll_futex_timed_wait (futex, newval, &rt);
+
+    try:
+      ;
+    }
+  while ((oldval = atomic_compare_and_exchange_val_acq (futex,
+							tid | FUTEX_WAITERS,
+							0)) != 0);
+
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym
new file mode 100644
index 0000000000..2f1e9da52b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym
@@ -0,0 +1,6 @@
+#include <stddef.h>
+#include <pthreadP.h>
+
+--
+
+TID		offsetof (struct pthread, tid)
diff --git a/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/nptl/sysdeps/unix/sysv/linux/mq_notify.c
index e9c2b6e79a..2ec11bf686 100644
--- a/nptl/sysdeps/unix/sysv/linux/mq_notify.c
+++ b/nptl/sysdeps/unix/sysv/linux/mq_notify.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contribute by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -283,5 +283,5 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification)
 }
 
 #else
-# include <sysdeps/generic/mq_notify.c>
+# include <rt/mq_notify.c>
 #endif
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h
new file mode 100644
index 0000000000..ab95fb57ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h
@@ -0,0 +1,90 @@
+/* Minimum guaranteed maximum values for system limits.  Linux/PPC version.
+   Copyright (C) 1993-1998,2000,2002-2004,2006 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; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* We have no predefined limit on the number of threads.  */
+#undef PTHREAD_THREADS_MAX
+
+/* Maximum amount by which a process can descrease its asynchronous I/O
+   priority level.  */
+#define AIO_PRIO_DELTA_MAX	20
+
+/* Minimum size for a thread.  At least two pages for systems with 64k
+   pages.  */
+#define PTHREAD_STACK_MIN	131072
+
+/* Maximum number of timer expiration overruns.  */
+#define DELAYTIMER_MAX	2147483647
+
+/* Maximum tty name length.  */
+#define TTY_NAME_MAX		32
+
+/* Maximum login name length.  This is arbitrary.  */
+#define LOGIN_NAME_MAX		256
+
+/* Maximum host name length.  */
+#define HOST_NAME_MAX		64
+
+/* Maximum message queue priority level.  */
+#define MQ_PRIO_MAX		32768
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
index 90c0695697..a7150f6aef 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  PowerPC version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
 
@@ -58,11 +58,25 @@ typedef union
 } pthread_attr_t;
 
 
+#if __WORDSIZE == 64
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is deliberately not exposed.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -73,10 +87,18 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
-#if __WORDSIZE != 64
+#if __WORDSIZE == 64
+    int __spins;
+    __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV	1
+#else
     unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
 #endif
-    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
index 2bee000730..0136b97595 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
 
@@ -13,7 +13,7 @@
    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 Libr	\ary; if not, write to the Free
+   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.  */
 
@@ -33,6 +33,11 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -67,6 +72,17 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \
   })
 
+#define lll_robust_mutex_dead(futexv) \
+  do									      \
+    {									      \
+      INTERNAL_SYSCALL_DECL (__err);					      \
+      int *__futexp = &(futexv);					      \
+									      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      INTERNAL_SYSCALL (futex, __err, 4, __futexp, FUTEX_WAKE, 1, 0);	      \
+    }									      \
+  while (0)
+
 /* Returns non-zero if error happened, zero if success.  */
 #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
   ({									      \
@@ -79,16 +95,43 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_WAKE_OP, (nr_wake),	      \
+			      (nr_wake2), (futexp2),			      \
+			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
+  })
+
 #ifdef UP
 # define __lll_acq_instr	""
 # define __lll_rel_instr	""
 #else
 # define __lll_acq_instr	"isync"
-# define __lll_rel_instr	"sync"
+# ifdef _ARCH_PWR4
+/*
+ * Newer powerpc64 processors support the new "light weight" sync (lwsync)
+ * So if the build is using -mcpu=[power4,power5,power5+,970] we can
+ * safely use lwsync.
+ */
+#  define __lll_rel_instr	"lwsync"
+# else
+/*
+ * Older powerpc32 processors don't support the new "light weight"
+ * sync (lwsync).  So the only safe option is to use normal sync
+ * for all powerpc32 applications.
+ */
+#  define __lll_rel_instr	"sync"
+# endif
 #endif
 
-/* Set *futex to 1 if it is 0, atomically.  Returns the old value */
-#define __lll_trylock(futex) \
+/* Set *futex to ID if it is 0, atomically.  Returns the old value */
+#define __lll_robust_trylock(futex, id) \
   ({ int __val;								      \
      __asm __volatile ("1:	lwarx	%0,0,%2\n"			      \
 		       "	cmpwi	0,%0,0\n"			      \
@@ -97,31 +140,26 @@
 		       "	bne-	1b\n"				      \
 		       "2:	" __lll_acq_instr			      \
 		       : "=&r" (__val), "=m" (*futex)			      \
-		       : "r" (futex), "r" (1), "m" (*futex)		      \
+		       : "r" (futex), "r" (id), "m" (*futex)		      \
 		       : "cr0", "memory");				      \
      __val;								      \
   })
 
+#define lll_robust_mutex_trylock(lock, id) __lll_robust_trylock (&(lock), id)
+
+/* Set *futex to 1 if it is 0, atomically.  Returns the old value */
+#define __lll_trylock(futex) __lll_robust_trylock (futex, 1)
+
 #define lll_mutex_trylock(lock)	__lll_trylock (&(lock))
 
 /* Set *futex to 2 if it is 0, atomically.  Returns the old value */
-#define __lll_cond_trylock(futex) \
-  ({ int __val;								      \
-     __asm __volatile ("1:	lwarx	%0,0,%2\n"			      \
-		       "	cmpwi	0,%0,0\n"			      \
-		       "	bne	2f\n"				      \
-		       "	stwcx.	%3,0,%2\n"			      \
-		       "	bne-	1b\n"				      \
-		       "2:	" __lll_acq_instr			      \
-		       : "=&r" (__val), "=m" (*futex)			      \
-		       : "r" (futex), "r" (2), "m" (*futex)		      \
-		       : "cr0", "memory");				      \
-     __val;								      \
-  })
+#define __lll_cond_trylock(futex) __lll_robust_trylock (futex, 2)
+
 #define lll_mutex_cond_trylock(lock)	__lll_cond_trylock (&(lock))
 
 
 extern void __lll_lock_wait (int *futex) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
 
 #define lll_mutex_lock(lock) \
   (void) ({								      \
@@ -131,6 +169,16 @@ extern void __lll_lock_wait (int *futex) attribute_hidden;
       __lll_lock_wait (__futex);					      \
   })
 
+#define lll_robust_mutex_lock(lock, id) \
+  ({									      \
+    int *__futex = &(lock);						      \
+    int __val = 0;							      \
+    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 0))	      \
+      __val = __lll_robust_lock_wait (__futex);				      \
+    __val;								      \
+  })
+
 #define lll_mutex_cond_lock(lock) \
   (void) ({								      \
     int *__futex = &(lock);						      \
@@ -139,8 +187,22 @@ extern void __lll_lock_wait (int *futex) attribute_hidden;
       __lll_lock_wait (__futex);					      \
   })
 
+#define lll_robust_mutex_cond_lock(lock, id) \
+  ({									      \
+    int *__futex = &(lock);						      \
+    int __val = 0;							      \
+    int __id = id | FUTEX_WAITERS;					      \
+    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, __id,\
+								0), 0))	      \
+      __val = __lll_robust_lock_wait (__futex);				      \
+    __val;								      \
+  })
+
+
 extern int __lll_timedlock_wait
   (int *futex, const struct timespec *) attribute_hidden;
+extern int __lll_robust_timedlock_wait
+  (int *futex, const struct timespec *) attribute_hidden;
 
 #define lll_mutex_timedlock(lock, abstime) \
   ({									      \
@@ -152,6 +214,16 @@ extern int __lll_timedlock_wait
     __val;								      \
   })
 
+#define lll_robust_mutex_timedlock(lock, abstime, id) \
+  ({									      \
+    int *__futex = &(lock);						      \
+    int __val = 0;							      \
+    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 0))	      \
+      __val = __lll_robust_timedlock_wait (__futex, abstime);		      \
+    __val;								      \
+  })
+
 #define lll_mutex_unlock(lock) \
   ((void) ({								      \
     int *__futex = &(lock);						      \
@@ -160,6 +232,14 @@ extern int __lll_timedlock_wait
       lll_futex_wake (__futex, 1);					      \
   }))
 
+#define lll_robust_mutex_unlock(lock) \
+  ((void) ({								      \
+    int *__futex = &(lock);						      \
+    int __val = atomic_exchange_rel (__futex, 0);			      \
+    if (__builtin_expect (__val & FUTEX_WAITERS, 0))			      \
+      lll_futex_wake (__futex, 1);					      \
+  }))
+
 #define lll_mutex_unlock_force(lock) \
   ((void) ({								      \
     int *__futex = &(lock);						      \
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
index e19579e842..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
@@ -1,3 +1,9 @@
-#define RESET_PID
-#include <tcb-offsets.h>
-#include <sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
index 7f5ba4aeef..3752abc870 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
@@ -1,5 +1,5 @@
 /* Cancellable system call stubs.  Linux/PowerPC version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
 
@@ -15,8 +15,8 @@
 
    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.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
+   02110-1301 USA.  */
 
 #include <sysdep.h>
 #include <tls.h>
@@ -30,7 +30,6 @@
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
   ENTRY (name)								\
-    cfi_startproc;							\
     SINGLE_THREAD_P;							\
     bne- .Lpseudo_cancel;						\
   .type __##syscall_name##_nocancel,@function;				\
@@ -45,6 +44,7 @@
     mflr 9;								\
     stw 9,52(1);							\
     cfi_offset (lr, 4);							\
+    CGOTSETUP;								\
     DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
     CENABLE;								\
     stw 3,16(1);	/* store CENABLE return value (MASK).  */	\
@@ -58,10 +58,10 @@
     lwz 4,52(1);							\
     lwz 0,12(1);	/* restore CR/R3. */				\
     lwz 3,8(1);								\
+    CGOTRESTORE;							\
     mtlr 4;								\
     mtcr 0;								\
-    addi 1,1,48;							\
-    cfi_endproc;
+    addi 1,1,48;
 
 # define DOCARGS_0
 # define UNDOCARGS_0
@@ -84,15 +84,30 @@
 # define DOCARGS_6	stw 8,40(1); DOCARGS_5
 # define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5
 
+# define CGOTSETUP
+# define CGOTRESTORE
+
 # ifdef IS_IN_libpthread
-#  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
-#  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
+#  define CENABLE	bl __pthread_enable_asynccancel@local
+#  define CDISABLE	bl __pthread_disable_asynccancel@local
 # elif !defined NOT_IN_libc
-#  define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel)
-#  define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel)
+#  define CENABLE	bl __libc_enable_asynccancel@local
+#  define CDISABLE	bl __libc_disable_asynccancel@local
 # elif defined IS_IN_librt
 #  define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel)
 #  define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel)
+#  if defined HAVE_AS_REL16 && defined PIC
+#   undef CGOTSETUP
+#   define CGOTSETUP							\
+    bcl 20,31,1f;							\
+ 1: stw 30,44(1);							\
+    mflr 30;								\
+    addis 30,30,_GLOBAL_OFFSET_TABLE-1b@ha;				\
+    addi 30,30,_GLOBAL_OFFSET_TABLE-1b@l
+#   undef CGOTRESTORE
+#   define CGOTRESTORE							\
+    lwz 30,44(1)
+#  endif
 # else
 #  error Unsupported library
 # endif
@@ -113,3 +128,9 @@
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
index f87adf4737..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -1,3 +1,9 @@
-#define RESET_PID
-#include <tcb-offsets.h>
-#include <sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
index 226aaafdce..707765ab58 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
@@ -1,5 +1,5 @@
 /* Cancellable system call stubs.  Linux/PowerPC64 version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
 
@@ -15,8 +15,8 @@
 
    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.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
+   02110-1301 USA.  */
 
 #include <sysdep.h>
 #include <tls.h>
@@ -36,7 +36,6 @@
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
   ENTRY (name)								\
-    cfi_startproc;							\
     SINGLE_THREAD_P;							\
     bne- .Lpseudo_cancel;						\
   .type DASHDASHPFX(syscall_name##_nocancel),@function;			\
@@ -66,8 +65,7 @@
     ld   3,64(1);							\
     mtlr 9;								\
     mtcr 0;								\
-    addi 1,1,128;							\
-    cfi_endproc;
+    addi 1,1,128;
 
 # define DOCARGS_0
 # define UNDOCARGS_0
@@ -119,3 +117,9 @@
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c
new file mode 100644
index 0000000000..8aa971ab9a
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include "pthreadP.h"
+
+
+int
+__pthread_attr_setstack (attr, stackaddr, stacksize)
+     pthread_attr_t *attr;
+     void *stackaddr;
+     size_t stacksize;
+{
+  struct pthread_attr *iattr;
+
+  assert (sizeof (*attr) >= sizeof (struct pthread_attr));
+  iattr = (struct pthread_attr *) attr;
+
+  /* Catch invalid sizes.  */
+  if (stacksize < 16384)
+    return EINVAL;
+
+#ifdef EXTRA_PARAM_CHECKS
+  EXTRA_PARAM_CHECKS;
+#endif
+
+  iattr->stacksize = stacksize;
+  iattr->stackaddr = (char *) stackaddr + stacksize;
+  iattr->flags |= ATTR_FLAG_STACKADDR;
+
+  return 0;
+}
+strong_alias (__pthread_attr_setstack, pthread_attr_setstack)
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c
new file mode 100644
index 0000000000..ea8c95981e
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include "pthreadP.h"
+
+
+int
+__pthread_attr_setstacksize (attr, stacksize)
+     pthread_attr_t *attr;
+     size_t stacksize;
+{
+  struct pthread_attr *iattr;
+
+  assert (sizeof (*attr) >= sizeof (struct pthread_attr));
+  iattr = (struct pthread_attr *) attr;
+
+  /* Catch invalid sizes.  */
+  if (stacksize < 16384)
+    return EINVAL;
+
+  size_t ps = __getpagesize ();
+  if (stacksize < 2 * ps)
+    stacksize = 2 * ps;
+
+  iattr->stacksize = stacksize;
+
+  return 0;
+}
+strong_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym b/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym
new file mode 100644
index 0000000000..a1b6794260
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym
@@ -0,0 +1,6 @@
+#include <pthreadP.h>
+
+-- These PI macros are used by assembly code.
+
+MUTEX_KIND	offsetof (pthread_mutex_t, __data.__kind)
+PI_BIT		PTHREAD_MUTEX_PRIO_INHERIT_NP
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c
index ca84f1c9bd..355e695ec2 100644
--- a/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -27,7 +27,7 @@
 
 
 /* Defined in pthread_setaffinity.c.  */
-extern size_t __kernel_cpumask_size;
+extern size_t __kernel_cpumask_size attribute_hidden;
 extern int __determine_cpumask_size (pid_t tid);
 
 
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
new file mode 100644
index 0000000000..82c2446d55
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
@@ -0,0 +1,111 @@
+/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t.  Linux version
+   Copyright (C) 2000,2001,2002,2003,2004,2005 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; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <pthreadP.h>
+#include <sys/time.h>
+#include <tls.h>
+#include <kernel-features.h>
+#include <kernel-posix-cpu-timers.h>
+
+
+#if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+int __libc_missing_posix_cpu_timers attribute_hidden;
+#endif
+#if !(__ASSUME_POSIX_TIMERS > 0)
+int __libc_missing_posix_timers attribute_hidden;
+#endif
+
+int
+pthread_getcpuclockid (threadid, clockid)
+     pthread_t threadid;
+     clockid_t *clockid;
+{
+  struct pthread *pd = (struct pthread *) threadid;
+
+  /* Make sure the descriptor is valid.  */
+  if (INVALID_TD_P (pd))
+    /* Not a valid thread handle.  */
+    return ESRCH;
+
+#ifdef __NR_clock_getres
+  /* The clockid_t value is a simple computation from the TID.
+     But we do a clock_getres call to validate it if we aren't
+     yet sure we have the kernel support.  */
+
+  const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED);
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+#  if !(__ASSUME_POSIX_TIMERS > 0)
+  if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
+    __libc_missing_posix_cpu_timers = 1;
+#  endif
+  if (!__libc_missing_posix_cpu_timers)
+    {
+      INTERNAL_SYSCALL_DECL (err);
+      int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL);
+      if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+# endif
+	{
+	  *clockid = tidclock;
+	  return 0;
+	}
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+#  if !(__ASSUME_POSIX_TIMERS > 0)
+      if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+	{
+	  /* The kernel doesn't support these calls at all.  */
+	  __libc_missing_posix_timers = 1;
+	  __libc_missing_posix_cpu_timers = 1;
+	}
+      else
+#  endif
+	if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
+	  {
+	    /* The kernel doesn't support these clocks at all.  */
+	    __libc_missing_posix_cpu_timers = 1;
+	  }
+      else
+	return INTERNAL_SYSCALL_ERRNO (r, err);
+    }
+# endif
+#endif
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+  /* We need to store the thread ID in the CLOCKID variable together
+     with a number identifying the clock.  We reserve the low 3 bits
+     for the clock ID and the rest for the thread ID.  This is
+     problematic if the thread ID is too large.  But 29 bits should be
+     fine.
+
+     If some day more clock IDs are needed the ID part can be
+     enlarged.  The IDs are entirely internal.  */
+  if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE))
+    return ERANGE;
+
+  /* Store the number.  */
+  *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE);
+
+  return 0;
+#else
+  /* We don't have a timer for that.  */
+  return ENOENT;
+#endif
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
index 9115d6f40b..75089365c3 100644
--- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -33,7 +33,15 @@ __pthread_kill (threadid, signo)
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (DEBUGGING_P && INVALID_TD_P (pd))
+    /* Not a valid thread handle.  */
+    return ESRCH;
+
+  /* Force load of pd->tid into local variable or register.  Otherwise
+     if a thread exits between ESRCH test and tgkill, we might return
+     EINVAL, because pd->tid would be cleared by the kernel.  */
+  pid_t tid = atomic_forced_read (pd->tid);
+  if (__builtin_expect (tid <= 0, 0))
     /* Not a valid thread handle.  */
     return ESRCH;
 
@@ -53,15 +61,15 @@ __pthread_kill (threadid, signo)
   int val;
 #if __ASSUME_TGKILL
   val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
-			  pd->tid, signo);
+			  tid, signo);
 #else
 # ifdef __NR_tgkill
   val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
-			  pd->tid, signo);
+			  tid, signo);
   if (INTERNAL_SYSCALL_ERROR_P (val, err)
       && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
 # endif
-    val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, signo);
+    val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo);
 #endif
 
   return (INTERNAL_SYSCALL_ERROR_P (val, err)
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
index 990db87416..a97351f880 100644
--- a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
@@ -1,7 +1,8 @@
 #include <pthreadP.h>
 
-#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex)
-#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex)
+#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock (mutex)
+#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock (mutex)
+#define LLL_ROBUST_MUTEX_LOCK(mutex, id) lll_robust_mutex_cond_lock (mutex, id)
 #define __pthread_mutex_lock __pthread_mutex_cond_lock
 #define NO_INCR
 
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c
index 5b24c694a9..3776e26e4b 100644
--- a/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -25,7 +25,7 @@
 #include <shlib-compat.h>
 
 
-size_t __kernel_cpumask_size;
+size_t __kernel_cpumask_size attribute_hidden;
 
 
 /* Determine the current affinity.  As a side affect we learn
diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
index 9707e4663c..cb5b2b832f 100644
--- a/nptl/sysdeps/unix/sysv/linux/register-atfork.c
+++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include "fork.h"
+#include <fork.h>
 
 
 /* Lock to protect allocation and deallocation of fork handlers.  */
diff --git a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
new file mode 100644
index 0000000000..39db5a3bd4
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h
@@ -0,0 +1,153 @@
+/* Defintions for lowlevel handling in ld.so.
+   Copyright (C) 2006, 2007 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.  */
+
+#ifndef _RTLD_LOWLEVEL_H
+#define  _RTLD_LOWLEVEL_H 1
+
+#include <atomic.h>
+#include <lowlevellock.h>
+
+
+/* Special multi-reader lock used in ld.so.  */
+#define __RTLD_MRLOCK_WRITER 1
+#define __RTLD_MRLOCK_RWAIT 2
+#define __RTLD_MRLOCK_WWAIT 4
+#define __RTLD_MRLOCK_RBITS \
+  ~(__RTLD_MRLOCK_WRITER | __RTLD_MRLOCK_RWAIT | __RTLD_MRLOCK_WWAIT)
+#define __RTLD_MRLOCK_INC 8
+#define __RTLD_MRLOCK_TRIES 5
+
+
+typedef int __rtld_mrlock_t;
+
+
+#define __rtld_mrlock_define(CLASS,NAME) \
+  CLASS __rtld_mrlock_t NAME;
+
+
+#define _RTLD_MRLOCK_INITIALIZER 0
+#define __rtld_mrlock_initialize(NAME) \
+  (void) ((NAME) = 0)
+
+
+#define __rtld_mrlock_lock(lock) \
+  do {									      \
+    __label__ out;							      \
+    while (1)								      \
+      {									      \
+	int oldval;							      \
+	for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries)	      \
+	  {								      \
+	    oldval = lock;						      \
+	    while (__builtin_expect ((oldval				      \
+				      & (__RTLD_MRLOCK_WRITER		      \
+					 | __RTLD_MRLOCK_WWAIT))	      \
+				     == 0, 1))				      \
+	      {								      \
+		int newval = ((oldval & __RTLD_MRLOCK_RBITS)		      \
+			      + __RTLD_MRLOCK_INC);			      \
+		int ret = atomic_compare_and_exchange_val_acq (&(lock),	      \
+							       newval,	      \
+							       oldval);	      \
+		if (__builtin_expect (ret == oldval, 1))		      \
+		  goto out;						      \
+		oldval = ret;						      \
+	      }								      \
+	    atomic_delay ();						      \
+	  }								      \
+	if ((oldval & __RTLD_MRLOCK_RWAIT) == 0)			      \
+	  {								      \
+	    atomic_or (&(lock), __RTLD_MRLOCK_RWAIT);			      \
+	    oldval |= __RTLD_MRLOCK_RWAIT;				      \
+	  }								      \
+	lll_futex_wait (lock, oldval);					      \
+      }									      \
+  out:;									      \
+  } while (0)
+
+
+#define __rtld_mrlock_unlock(lock) \
+  do {									      \
+    int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_INC);	      \
+    if (__builtin_expect ((oldval					      \
+			   & (__RTLD_MRLOCK_RBITS | __RTLD_MRLOCK_WWAIT))     \
+			  == (__RTLD_MRLOCK_INC | __RTLD_MRLOCK_WWAIT), 0))   \
+      /* We have to wake all threads since there might be some queued	      \
+	 readers already.  */						      \
+      lll_futex_wake (&(lock), 0x7fffffff);				      \
+  } while (0)
+
+
+/* There can only ever be one thread trying to get the exclusive lock.  */
+#define __rtld_mrlock_change(lock) \
+  do {									      \
+    __label__ out;							      \
+    while (1)								      \
+      {									      \
+	int oldval;							      \
+	for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries)	      \
+	  {								      \
+	    oldval = lock;						      \
+	    while (__builtin_expect ((oldval & __RTLD_MRLOCK_RBITS) == 0, 1)) \
+	      {								      \
+		int newval = ((oldval & __RTLD_MRLOCK_RWAIT)		      \
+			      + __RTLD_MRLOCK_WRITER);			      \
+		int ret = atomic_compare_and_exchange_val_acq (&(lock),	      \
+							       newval,	      \
+							       oldval);	      \
+		if (__builtin_expect (ret == oldval, 1))		      \
+		  goto out;						      \
+		oldval = ret;						      \
+	      }								      \
+	    atomic_delay ();						      \
+	  }								      \
+	atomic_or (&(lock), __RTLD_MRLOCK_WWAIT);			      \
+	oldval |= __RTLD_MRLOCK_WWAIT;					      \
+	lll_futex_wait (lock, oldval);					      \
+      }									      \
+  out:;									      \
+  } while (0)
+
+
+#define __rtld_mrlock_done(lock) \
+  do {				 \
+    int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_WRITER);    \
+    if (__builtin_expect ((oldval & __RTLD_MRLOCK_RWAIT) != 0, 0))	      \
+      lll_futex_wake (&(lock), 0x7fffffff);				      \
+  } while (0)
+
+
+/* Function to wait for variable become zero.  Used in ld.so for
+   reference counters.  */
+#define __rtld_waitzero(word) \
+  do {									      \
+    while (1)								      \
+      {									      \
+	int val = word;							      \
+	if (val == 0)							      \
+	  break;							      \
+	lll_futex_wait (&(word), val);					      \
+      }									      \
+  } while (0)
+
+
+#define __rtld_notify(word) \
+  lll_futex_wake (&(word), 1)
+
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
index 6b3618cd57..c77031d7bb 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -57,11 +57,25 @@ typedef union
 } pthread_attr_t;
 
 
+#if __WORDSIZE == 64
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -72,10 +86,18 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
-#if __WORDSIZE != 64
+#if __WORDSIZE == 64
+    int __spins;
+    __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV	1
+#else
     unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
 #endif
-    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
index f4ed98a503..38d9f2ac41 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -30,6 +30,11 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -83,6 +88,17 @@
   })
 
 
+#define lll_robust_mutex_dead(futexv) \
+  do									      \
+    {									      \
+      int *__futexp = &(futexv);					      \
+									      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      lll_futex_wake (__futexp, 1);					      \
+    }									      \
+  while (0)
+
+
 /* Returns non-zero if error happened, zero if success.  */
 #define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) \
   ({									      \
@@ -103,6 +119,27 @@
   })
 
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futex, nr_wake, nr_wake2, futex2) \
+  ({									      \
+    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \
+    register unsigned long int __r3 asm ("3") = FUTEX_WAKE_OP;	      \
+    register unsigned long int __r4 asm ("4") = (long int) (nr_wake);	      \
+    register unsigned long int __r5 asm ("5") = (long int) (nr_wake2);	      \
+    register unsigned long int __r6 asm ("6") = (unsigned long int) (futex2); \
+    register unsigned long int __r7 asm ("7")				      \
+      = (int) FUTEX_OP_CLEAR_WAKE_IF_GT_ONE;				      \
+    register unsigned long __result asm ("2");				      \
+									      \
+    __asm __volatile ("svc %b1"						      \
+		      : "=d" (__result)					      \
+		      : "i" (SYS_futex), "0" (__r2), "d" (__r3),	      \
+			"d" (__r4), "d" (__r5), "d" (__r6), "d" (__r7)	      \
+		      : "cc", "memory" );				      \
+    __result > -4096UL;							      \
+  })
+
+
 #define lll_compare_and_swap(futex, oldval, newval, operation) \
   do {									      \
     __typeof (futex) __futex = (futex);					      \
@@ -144,7 +181,23 @@ __lll_mutex_cond_trylock (int *futex)
 #define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
 
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_trylock (int *futex, int id)
+{
+    unsigned int old;
+
+    __asm __volatile ("cs %0,%3,%1"
+		       : "=d" (old), "=Q" (*futex)
+		       : "0" (0), "d" (id), "m" (*futex) : "cc", "memory" );
+    return old != 0;
+}
+#define lll_robust_mutex_trylock(futex, id) \
+  __lll_robust_mutex_trylock (&(futex), id)
+
+
 extern void __lll_lock_wait (int *futex) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
 
 static inline void
 __attribute__ ((always_inline))
@@ -155,6 +208,17 @@ __lll_mutex_lock (int *futex)
 }
 #define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_lock (int *futex, int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_lock_wait (futex);
+  return result;
+}
+#define lll_robust_mutex_lock(futex, id) __lll_robust_mutex_lock (&(futex), id)
+
 static inline void
 __attribute__ ((always_inline))
 __lll_mutex_cond_lock (int *futex)
@@ -164,8 +228,13 @@ __lll_mutex_cond_lock (int *futex)
 }
 #define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
 
+#define lll_robust_mutex_cond_lock(futex, id) \
+  __lll_robust_mutex_lock (&(futex), (id) | FUTEX_WAITERS)
+
 extern int __lll_timedlock_wait
   (int *futex, const struct timespec *) attribute_hidden;
+extern int __lll_robust_timedlock_wait
+  (int *futex, const struct timespec *) attribute_hidden;
 
 static inline int
 __attribute__ ((always_inline))
@@ -179,6 +248,19 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
 #define lll_mutex_timedlock(futex, abstime) \
   __lll_mutex_timedlock (&(futex), abstime)
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime,
+			      int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_timedlock_wait (futex, abstime);
+  return result;
+}
+#define lll_robust_mutex_timedlock(futex, abstime, id) \
+  __lll_robust_mutex_timedlock (&(futex), abstime, id)
+
 
 static inline void
 __attribute__ ((always_inline))
@@ -197,6 +279,21 @@ __lll_mutex_unlock (int *futex)
 
 static inline void
 __attribute__ ((always_inline))
+__lll_robust_mutex_unlock (int *futex, int mask)
+{
+  int oldval;
+  int newval = 0;
+
+  lll_compare_and_swap (futex, oldval, newval, "slr %2,%2");
+  if (oldval & mask)
+    lll_futex_wake (futex, 1);
+}
+#define lll_robust_mutex_unlock(futex) \
+  __lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS)
+
+
+static inline void
+__attribute__ ((always_inline))
 __lll_mutex_unlock_force (int *futex)
 {
   *futex = 0;
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
index 682f94dae8..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/s390/s390-32/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
index 09dac2c90b..17ab562daa 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -113,3 +113,9 @@ L(pseudo_end):
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
index 87ee2e1846..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/s390/s390-64/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
index f8eb6a9ebc..77ce742495 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -126,3 +126,9 @@ extern int __local_multiple_threads attribute_hidden;
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
index 5125408dcb..969686dd5a 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -44,11 +44,17 @@ typedef union
 } pthread_attr_t;
 
 
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -57,7 +63,11 @@ typedef union
        binary compatibility.  */
     int __kind;
     unsigned int __nusers;
-    int __spins;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/clone.S b/nptl/sysdeps/unix/sysv/linux/sh/clone.S
index 62a11972d8..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/sh/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
index bcb15615e5..ac3169889f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005 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
@@ -32,8 +32,11 @@
 	.type	__lll_mutex_lock_wait,@function
 	.hidden	__lll_mutex_lock_wait
 	.align	5
+	cfi_startproc
 __lll_mutex_lock_wait:
 	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
 	mov	r4, r6
 	mov	r5, r8
 	mov	#0, r7		/* No timeout.  */
@@ -51,14 +54,15 @@ __lll_mutex_lock_wait:
 	SYSCALL_INST_PAD
 
 2:
-	mov	#2, r4
-	XCHG (r4, @r8, r2)
+	mov	#2, r6
+	XCHG (r6, @r8, r2)
 	tst	r2, r2
 	bf	1b
 
 	mov.l	@r15+, r8
 	ret
 	 mov	r2, r0
+	cfi_endproc
 	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait
 
 
@@ -67,6 +71,7 @@ __lll_mutex_lock_wait:
 	.type	__lll_mutex_timedlock_wait,@function
 	.hidden	__lll_mutex_timedlock_wait
 	.align	5
+	cfi_startproc
 __lll_mutex_timedlock_wait:
 	/* Check for a valid timeout value.  */
 	mov.l	@(4,r6), r1
@@ -75,14 +80,21 @@ __lll_mutex_timedlock_wait:
 	bt	3f
 
 	mov.l	r10, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r10, 0)
 	mov.l	r9, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r9, 0)
 	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
 	mov	r4, r10
 	mov	r6, r9
 	mov	r5, r8
 
 	/* Stack frame for the timespec and timeval structs.  */
 	add	#-8, r15
+	cfi_adjust_cfa_offset(8)
 
 1:
 	/* Get current time.  */
@@ -162,6 +174,7 @@ __lll_mutex_timedlock_wait:
 5:
 	bra	6b
 	 mov	#ETIMEDOUT, r0
+	cfi_endproc
 
 .L1k:
 	.word	1000
@@ -178,6 +191,7 @@ __lll_mutex_timedlock_wait:
 	.type	lll_unlock_wake_cb,@function
 	.hidden	lll_unlock_wake_cb
 	.align	5
+	cfi_startproc
 lll_unlock_wake_cb:
 	DEC	(@r4, r2)
 	tst	r2, r2
@@ -195,6 +209,7 @@ lll_unlock_wake_cb:
 1:	
 	rts
 	 nop
+	cfi_endproc
 	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb
 #endif
 
@@ -203,6 +218,7 @@ lll_unlock_wake_cb:
 	.type	__lll_mutex_unlock_wake,@function
 	.hidden	__lll_mutex_unlock_wake
 	.align	5
+	cfi_startproc
 __lll_mutex_unlock_wake:
 	mov	#FUTEX_WAKE, r5
 	mov	#1, r6		/* Wake one thread.  */
@@ -214,6 +230,7 @@ __lll_mutex_unlock_wake:
 	SYSCALL_INST_PAD
 	rts
 	 nop
+	cfi_endproc
 	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
 
 
@@ -222,14 +239,20 @@ __lll_mutex_unlock_wake:
 	.type	__lll_timedwait_tid,@function
 	.hidden	__lll_timedwait_tid
 	.align	5
+	cfi_startproc
 __lll_timedwait_tid:
 	mov.l	r9, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r9, 0)
 	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
 	mov	r4, r8
 	mov	r5, r9
 
 	/* Stack frame for the timespec and timeval structs.  */
 	add	#-8, r15
+	cfi_adjust_cfa_offset(8)
 
 2:
 	/* Get current time.  */
@@ -292,6 +315,7 @@ __lll_timedwait_tid:
 6:
 	bra	3b
 	 mov	#ETIMEDOUT, r0
+	cfi_endproc
 
 .L1k2:
 	.word	1000
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
index d9376d45a0..0eb1f0114c 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 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
@@ -26,6 +26,9 @@
 #define SYS_futex		240
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 
 /* Initializer for compatibility lock.  */
@@ -62,6 +65,28 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
 	: "r0", "r1", "r2", "t", "memory"); \
      __result; })
 
+#define lll_robust_mutex_trylock(futex, id)	\
+  ({ unsigned char __result; \
+     __asm __volatile ("\
+	.align 2\n\
+	mova 1f,r0\n\
+	nop\n\
+	mov r15,r1\n\
+	mov #-8,r15\n\
+     0: mov.l @%1,r2\n\
+	cmp/eq r2,%3\n\
+	bf 1f\n\
+	mov.l %2,@%1\n\
+     1: mov r1,r15\n\
+	mov #-1,%0\n\
+	negc %0,%0"\
+	: "=r" (__result) \
+	: "r" (&(futex)), \
+	  "r" (id), \
+	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \
+	: "r0", "r1", "r2", "t", "memory"); \
+     __result; })
+
 #define lll_mutex_cond_trylock(futex) \
   ({ unsigned char __result; \
      __asm __volatile ("\
@@ -102,6 +127,25 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
 	    if (__result) \
 	      __lll_mutex_lock_wait (__result, __futex); })
 
+#define lll_robust_mutex_lock(futex, id)		    \
+  ({ int __result, val, *__futex = &(futex); \
+     __asm __volatile ("\
+	.align 2\n\
+	mova 1f,r0\n\
+	nop\n\
+	mov r15,r1\n\
+	mov #-8,r15\n\
+      0: mov.l @%2,%0\n\
+	tst %0,%0\n\
+	bf 1f\n\
+	mov.l %1,@%2\n\
+      1: mov r1,r15"\
+	: "=&r" (__result) : "r" (id), "r" (__futex) \
+	: "r0", "r1", "t", "memory"); \
+     if (__result) \
+       __result = __lll_robust_mutex_lock_wait (__result, __futex); \
+     __result; })
+
 /* Special version of lll_mutex_lock which causes the unlock function to
    always wakeup waiters.  */
 #define lll_mutex_cond_lock(futex) \
@@ -122,6 +166,25 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
 	    if (__result) \
 	      __lll_mutex_lock_wait (__result, __futex); })
 
+#define lll_robust_mutex_cond_lock(futex, id)	    \
+  ({ int __result, val, *__futex = &(futex); \
+     __asm __volatile ("\
+	.align 2\n\
+	mova 1f,r0\n\
+	nop\n\
+	mov r15,r1\n\
+	mov #-8,r15\n\
+     0: mov.l @%2,%0\n\
+	tst %0,%0\n\
+	bf 1f\n\
+	mov.l %1,@%2\n\
+     1: mov r1,r15"\
+	: "=&r" (__result) : "r" (id | FUTEX_WAITERS), "r" (__futex) \
+	: "r0", "r1", "t", "memory"); \
+      if (__result) \
+	__result = __lll_robust_mutex_lock_wait (__result, __futex); \
+      __result; })
+
 #define lll_mutex_timedlock(futex, timeout) \
   ({ int __result, val, *__futex = &(futex); \
      __asm __volatile ("\
@@ -141,6 +204,26 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
       __result = __lll_mutex_timedlock_wait (__result, __futex, timeout); \
     __result; })
 
+#define lll_robust_mutex_timedlock(futex, timeout, id)	\
+  ({ int __result, val, *__futex = &(futex); \
+     __asm __volatile ("\
+	.align 2\n\
+	mova 1f,r0\n\
+	nop\n\
+	mov r15,r1\n\
+	mov #-8,r15\n\
+     0: mov.l @%2,%0\n\
+	tst %0,%0\n\
+	bf 1f\n\
+	mov.l %1,@%2\n\
+     1: mov r1,r15"\
+	: "=&r" (__result) : "r" (id), "r" (__futex) \
+	: "r0", "r1", "t", "memory"); \
+    if (__result) \
+      __result = __lll_robust_mutex_timedlock_wait (__result, __futex, \
+						    timeout);	       \
+    __result; })
+
 #define lll_mutex_unlock(futex) \
   (void) ({ int __result, *__futex = &(futex); \
 	    __asm __volatile ("\
@@ -157,6 +240,37 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
 	    if (__result) \
 	      __lll_mutex_unlock_wake (__futex); })
 
+#define lll_robust_mutex_unlock(futex) \
+  (void) ({ int __result, *__futex = &(futex); \
+	    __asm __volatile ("\
+		.align 2\n\
+		mova 1f,r0\n\
+		mov r15,r1\n\
+		mov #-6,r15\n\
+	     0: mov.l @%1,%0\n\
+		and %2,%0\n\
+		mov.l %0,@%1\n\
+	     1: mov r1,r15"\
+		: "=&r" (__result) : "r" (__futex), "r" (FUTEX_TID_MASK) \
+		: "r0", "r1", "memory");	\
+	    if (__result) \
+	      __lll_mutex_unlock_wake (__futex); })
+
+#define lll_robust_mutex_dead(futex) \
+  (void) ({ int __ignore, *__futex = &(futex); \
+	    __asm __volatile ("\
+		.align 2\n\
+		mova 1f,r0\n\
+		mov r15,r1\n\
+		mov #-6,r15\n\
+	     0: mov.l @%1,%0\n\
+		or %2,%0\n\
+		mov.l %0,@%1\n\
+	     1: mov r1,r15"\
+		: "=&r" (__ignore) : "r" (__futex), "r" (FUTEX_OWNER_DIED) \
+		: "r0", "r1", "memory");	\
+	    lll_futex_wake (__futex, 1); })
+
 #define lll_mutex_islocked(futex) \
   (futex != 0)
 
@@ -181,19 +295,37 @@ typedef int lll_lock_t;
 # endif
 
 #define lll_futex_wait(futex, val) \
-  do {									      \
-    int __ignore;							      \
+  ({									      \
+    int __status;							      \
     register unsigned long __r3 asm ("r3") = SYS_futex;			      \
     register unsigned long __r4 asm ("r4") = (unsigned long) (futex);	      \
     register unsigned long __r5 asm ("r5") = FUTEX_WAIT;		      \
     register unsigned long __r6 asm ("r6") = (unsigned long) (val);	      \
     register unsigned long __r7 asm ("r7") = 0;				      \
     __asm __volatile (SYSCALL_WITH_INST_PAD				      \
-		      : "=z" (__ignore)					      \
+		      : "=z" (__status)					      \
 		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \
 			"r" (__r6), "r" (__r7)				      \
 		      : "memory", "t");					      \
-  } while (0)
+    __status;								      \
+  })
+
+
+#define lll_futex_timed_wait(futex, val, timeout) \
+  ({									      \
+    int __status;							      \
+    register unsigned long __r3 asm ("r3") = SYS_futex;			      \
+    register unsigned long __r4 asm ("r4") = (unsigned long) (futex);	      \
+    register unsigned long __r5 asm ("r5") = FUTEX_WAIT;		      \
+    register unsigned long __r6 asm ("r6") = (unsigned long) (val);	      \
+    register unsigned long __r7 asm ("r7") = (timeout);			      \
+    __asm __volatile (SYSCALL_WITH_INST_PAD				      \
+		      : "=z" (__status)					      \
+		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \
+			"r" (__r6), "r" (__r7)				      \
+		      : "memory", "t");					      \
+    __status;								      \
+  })
 
 
 #define lll_futex_wake(futex, nr) \
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S
new file mode 100644
index 0000000000..c57d3cff18
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S
@@ -0,0 +1,224 @@
+/* Copyright (C) 2003, 2004, 2005, 2006 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 <sysdep.h>
+#include <pthread-errnos.h>
+#include <lowlevelrobustlock.h>
+#include "lowlevel-atomic.h"
+
+	.text
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+#define FUTEX_WAITERS		0x80000000
+#define FUTEX_OWNER_DIED	0x40000000
+
+
+	.globl	__lll_robust_mutex_lock_wait
+	.type	__lll_robust_mutex_lock_wait,@function
+	.hidden	__lll_robust_mutex_lock_wait
+	.align	5
+	cfi_startproc
+__lll_robust_mutex_lock_wait:
+	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
+	mov	r5, r8
+	mov	#0, r7		/* No timeout.  */
+	mov	#FUTEX_WAIT, r5
+
+4:
+	mov	r4, r6
+	mov.l	.L_FUTEX_WAITERS, r0
+	or	r0, r6
+	shlr	r0		/* r0 = FUTEX_OWNER_DIED */
+	tst	r0, r4
+	bf/s	3f
+	 cmp/eq	r4, r6
+	bt	1f
+
+	CMPXCHG (r4, @r8, r6, r2)
+	bf	2f
+
+1:
+	mov	r8, r4
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+
+	mov.l	@r8, r2
+
+2:
+	tst	r2, r2
+	bf/s	4b
+	 mov	r2, r4
+
+	stc	gbr, r1
+	mov.w	.Ltidoff, r2
+	add	r2, r1
+	mov.l	@r1, r6
+	mov	#0, r3
+	CMPXCHG (r3, @r8, r6, r4)
+	bf	4b
+	mov	#0, r4
+
+3:
+	mov.l	@r15+, r8
+	ret
+	 mov	r4, r0
+	cfi_endproc
+	.align	2
+.L_FUTEX_WAITERS:
+	.long	FUTEX_WAITERS
+.Ltidoff:
+	.word	TID - TLS_PRE_TCB_SIZE
+	.size	__lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
+
+
+	.globl	__lll_robust_mutex_timedlock_wait
+	.type	__lll_robust_mutex_timedlock_wait,@function
+	.hidden	__lll_robust_mutex_timedlock_wait
+	.align	5
+	cfi_startproc
+__lll_robust_mutex_timedlock_wait:
+	/* Check for a valid timeout value.  */
+	mov.l	@(4,r6), r1
+	mov.l	.L1g, r0
+	cmp/hs	r0, r1
+	bt	3f
+
+	mov.l	r10, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r10, 0)
+	mov.l	r9, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r9, 0)
+	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
+	mov	r4, r10
+	mov	r6, r9
+	mov	r5, r8
+
+	/* Stack frame for the timespec and timeval structs.  */
+	add	#-8, r15
+	cfi_adjust_cfa_offset(8)
+
+1:
+	/* Get current time.  */
+	mov	r15, r4
+	mov	#0, r5
+	mov	#SYS_gettimeofday, r3
+	trapa	#0x12
+	SYSCALL_INST_PAD
+
+	/* Compute relative timeout.  */
+	mov.l	@(4,r15), r0
+	mov.w	.L1k, r1
+	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */
+	mov.l	@r9, r2
+	mov.l	@(4,r9), r3
+	mov.l	@r15, r0
+	sts	macl, r1
+	sub	r0, r2
+	clrt
+	subc	r1, r3
+	bf	4f
+	mov.l	.L1g, r1
+	add	r1, r3
+	add	#-1, r2
+4:
+	cmp/pz	r2
+	bf	8f		/* Time is already up.  */
+
+	mov.l	r2, @r15	/* Store relative timeout.  */
+	mov.l	r3, @(4,r15)
+
+	mov	r10, r6
+	mov.l	.L_FUTEX_WAITERS2, r0
+	or	r0, r6
+	shlr	r0		/* r0 = FUTEX_OWNER_DIED */
+	tst	r0, r4
+	bf/s	6f
+	 cmp/eq	r4, r6
+	bt	2f
+
+	CMPXCHG (r4, @r8, r6, r2)
+	bf/s	5f
+	 mov	#0, r5
+
+2:
+	mov	r8, r4
+	mov	#FUTEX_WAIT, r5
+	mov	r10, r6
+	mov	r15, r7
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+	mov	r0, r5
+
+	mov.l	@r8, r2
+
+5:
+	tst	r2, r2
+	bf/s	7f
+	 mov	r2, r10
+
+	stc	gbr, r1
+	mov.w	.Ltidoff2, r2
+	add	r2, r1
+	mov.l	@r1, r4
+	mov	#0, r3
+	CMPXCHG (r3, @r8, r4, r10)
+	bf	7f
+	mov	#0, r0
+
+6:
+	add	#8, r15
+	mov.l	@r15+, r8
+	mov.l	@r15+, r9
+	rts
+	 mov.l	@r15+, r10
+
+7:
+	/* Check whether the time expired.  */
+	mov	#-ETIMEDOUT, r1
+	cmp/eq	r5, r1
+	bf	1b
+
+8:
+	bra	6b
+	 mov	#ETIMEDOUT, r0
+3:
+	rts
+	 mov	#EINVAL, r0
+	cfi_endproc
+	.align	2
+.L_FUTEX_WAITERS2:
+	.long	FUTEX_WAITERS
+.L1g:
+	.long	1000000000
+.Ltidoff2:
+	.word	TID - TLS_PRE_TCB_SIZE
+.L1k:
+	.word	1000
+	.size	__lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
index 6bd6e60ec1..56f0aa95de 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 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,6 +20,7 @@
 #include <shlib-compat.h>
 #include <lowlevelcond.h>
 #include <kernel-features.h>
+#include <pthread-pi-defines.h>
 #include "lowlevel-atomic.h"
 
 #define SYS_futex		240
@@ -98,6 +99,11 @@ __pthread_cond_broadcast:
 	bt/s	9f
 	 add	#cond_futex, r4
 
+	/* XXX: The kernel so far doesn't support requeue to PI futex.  */
+	mov.l	@(MUTEX_KIND,r9), r0
+	tst	#PI_BIT, r0
+	bf	9f
+
 	/* Wake up all threads.  */
 	mov	#FUTEX_CMP_REQUEUE, r5
 	mov	#1, r6
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
index 74206a71ec..6c782c8a76 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 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
@@ -521,6 +521,21 @@ __condvar_tw_cleanup:
 	mov	#1, r2
 	mov	#0, r3
 
+	/* We increment the wakeup_seq counter only if it is lower than
+	   total_seq.  If this is not the case the thread was woken and
+	   then canceled.  In this case we ignore the signal.  */
+	mov.l	@(total_seq+4,r8), r0
+	mov.l	@(wakeup_seq+4,r8), r1
+	cmp/hi	r1, r0
+	bt/s	6f
+	 cmp/hi	r0, r1
+	bt	7f
+	mov.l	@(total_seq,r8), r0
+	mov.l	@(wakeup_seq,r8), r1
+	cmp/hs	r0, r1
+	bt	7f
+
+6:
 	clrt
 	mov.l	@(wakeup_seq,r8),r0
 	mov.l	@(wakeup_seq+4,r8),r1
@@ -532,6 +547,7 @@ __condvar_tw_cleanup:
 	add	r2, r0
 	mov.l	r0,@(cond_futex,r8)
 
+7:
 	clrt
 	mov.l	@(woken_seq,r8),r0
 	mov.l	@(woken_seq+4,r8),r1
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
index 2d6b685668..6c59f3e6c0 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 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
@@ -385,6 +385,21 @@ __condvar_w_cleanup:
 	mov	#1, r2
 	mov	#0, r3
 
+	/* We increment the wakeup_seq counter only if it is lower than
+	   total_seq.  If this is not the case the thread was woken and
+	   then canceled.  In this case we ignore the signal.  */
+	mov.l	@(total_seq+4,r8), r0
+	mov.l	@(wakeup_seq+4,r8), r1
+	cmp/hi	r1, r0
+	bt/s	6f
+	 cmp/hi	r0, r1
+	bt	7f
+	mov.l	@(total_seq,r8), r0
+	mov.l	@(wakeup_seq,r8), r1
+	cmp/hs	r0, r1
+	bt	7f
+
+6:
 	clrt
 	mov.l	@(wakeup_seq,r8),r0
 	mov.l	@(wakeup_seq+4,r8),r1
@@ -396,6 +411,7 @@ __condvar_w_cleanup:
 	add	r2, r0
 	mov.l	r0,@(cond_futex,r8)
 
+7:
 	clrt
 	mov.l	@(woken_seq,r8),r0
 	mov.l	@(woken_seq+4,r8),r1
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h
index 8cdcac5560..90be7bd8d0 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h
@@ -1,4 +1,4 @@
 /*  4 instruction cycles not accessing cache and TLB are needed after
     trapa instruction to avoid an SH-4 silicon bug.  */
 #define NEED_SYSCALL_INST_PAD
-#include <sysdeps/unix/sysv/linux/sh/lowlevellock.h>
+#include_next <lowlevellock.h>
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
index fc3c2340b6..a8065c6a8c 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006 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
@@ -49,27 +49,32 @@
     .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
  .Lpseudo_cancel: \
     sts.l pr,@-r15; \
- .LCFI0: \
+    cfi_adjust_cfa_offset (4); \
+    cfi_rel_offset (pr, 0); \
     add _IMM16,r15; \
+    cfi_adjust_cfa_offset (16); \
     SAVE_ARGS_##args; \
- .LCFI1: \
     CENABLE; \
     LOAD_ARGS_##args; \
     add _IMP16,r15; \
- .LCFI2: \
+    cfi_adjust_cfa_offset (-16); \
     lds.l @r15+,pr; \
- .LCFI3: \
+    cfi_adjust_cfa_offset (-4); \
+    cfi_restore (pr); \
     DO_CALL(syscall_name, args); \
     SYSCALL_INST_PAD; \
     sts.l pr,@-r15; \
- .LCFI4: \
+    cfi_adjust_cfa_offset (4); \
+    cfi_rel_offset (pr, 0); \
     mov.l r0,@-r15; \
- .LCFI5: \
+    cfi_adjust_cfa_offset (4); \
+    cfi_rel_offset (r0, 0); \
     CDISABLE; \
     mov.l @r15+,r0; \
- .LCFI6: \
+    cfi_adjust_cfa_offset (-4); \
     lds.l @r15+,pr; \
- .LCFI7: \
+    cfi_adjust_cfa_offset (-4); \
+    cfi_restore (pr); \
     mov r0,r1; \
     mov _IMM12,r2; \
     shad r2,r1; \
@@ -78,106 +83,17 @@
     bf .Lpseudo_end; \
  .Lsyscall_error: \
     SYSCALL_ERROR_HANDLER; \
- .Lpseudo_end: \
- /* Create unwinding information for the syscall wrapper.  */ \
- .section .eh_frame,"a",@progbits; \
- .Lframe1: \
-    .ualong .LECIE1-.LSCIE1; \
- .LSCIE1: \
-    .ualong 0x0; \
-    .byte   0x1; \
-    AUGMENTATION_STRING; \
-    .uleb128 0x1; \
-    .sleb128 -4; \
-    .byte   0x11; \
-    AUGMENTATION_PARAM; \
-    .byte   0xc; \
-    .uleb128 0xf; \
-    .uleb128 0x0; \
-    .align 2; \
- .LECIE1: \
- .LSFDE1: \
-    .ualong .LEFDE1-.LASFDE1; \
- .LASFDE1: \
-    .ualong .LASFDE1-.Lframe1; \
-    START_SYMBOL_REF; \
-    .ualong .Lpseudo_end - .Lpseudo_start; \
-    AUGMENTATION_PARAM_FDE; \
-    .byte   0x4; \
-    .ualong .LCFI0-.Lpseudo_start; \
-    .byte   0xe; \
-    .uleb128 0x4; \
-    .byte   0x91; \
-    .uleb128 0x1; \
-    .byte   0x4; \
-    .ualong .LCFI1-.LCFI0; \
-    .byte   0xe; \
-    .uleb128 0x14; \
-    FRAME_REG_##args; \
-    .byte   0x4; \
-    .ualong .LCFI2-.LCFI1; \
-    .byte   0xe; \
-    .uleb128 0x4; \
-    .byte   0x4; \
-    .ualong .LCFI3-.LCFI2; \
-    .byte   0xe; \
-    .uleb128 0x0; \
-    .byte   0xd1; \
-    .byte   0x4; \
-    .ualong .LCFI4-.LCFI3; \
-    .byte   0xe; \
-    .uleb128 0x4; \
-    .byte   0x91; \
-    .uleb128 0x1; \
-    .byte   0x4; \
-    .ualong .LCFI5-.LCFI4; \
-    .byte   0xe; \
-    .uleb128 0x8; \
-    .byte   0x80; \
-    .uleb128 0x2; \
-    .byte   0x4; \
-    .ualong .LCFI6-.LCFI5; \
-    .byte   0xe; \
-    .uleb128 0x4; \
-    .byte   0xc0; \
-    .byte   0x4; \
-    .ualong .LCFI7-.LCFI6; \
-    .byte   0xe; \
-    .uleb128 0x0; \
-    .byte   0xd1; \
-    .align 2; \
- .LEFDE1: \
- .previous
-
-# ifdef SHARED
-#  define AUGMENTATION_STRING .string "zR"
-#  define AUGMENTATION_PARAM .uleb128 1; .byte 0x1b
-#  define AUGMENTATION_PARAM_FDE .uleb128 0
-#  define START_SYMBOL_REF .long .Lpseudo_start-.
-# else
-#  define AUGMENTATION_STRING .ascii "\0"
-#  define AUGMENTATION_PARAM
-#  define AUGMENTATION_PARAM_FDE
-#  define START_SYMBOL_REF .long .Lpseudo_start
-# endif
-
-# define FRAME_REG_0	/* Nothing.  */
-# define FRAME_REG_1	FRAME_REG_0; .byte 0x84; .uleb128 5
-# define FRAME_REG_2	FRAME_REG_1; .byte 0x85; .uleb128 4
-# define FRAME_REG_3	FRAME_REG_2; .byte 0x86; .uleb128 3
-# define FRAME_REG_4	FRAME_REG_3; .byte 0x87; .uleb128 2
-# define FRAME_REG_5	FRAME_REG_4
-# define FRAME_REG_6	FRAME_REG_5
+ .Lpseudo_end:
 
 # undef PSEUDO_END
 # define PSEUDO_END(sym) \
   END (sym)
 
 # define SAVE_ARGS_0	/* Nothing.  */
-# define SAVE_ARGS_1	SAVE_ARGS_0; mov.l r4,@(0,r15)
-# define SAVE_ARGS_2	SAVE_ARGS_1; mov.l r5,@(4,r15)
-# define SAVE_ARGS_3	SAVE_ARGS_2; mov.l r6,@(8,r15)
-# define SAVE_ARGS_4	SAVE_ARGS_3; mov.l r7,@(12,r15)
+# define SAVE_ARGS_1	SAVE_ARGS_0; mov.l r4,@(0,r15); cfi_offset (r4,-4)
+# define SAVE_ARGS_2	SAVE_ARGS_1; mov.l r5,@(4,r15); cfi_offset (r5,-8)
+# define SAVE_ARGS_3	SAVE_ARGS_2; mov.l r6,@(8,r15); cfi_offset (r6,-12)
+# define SAVE_ARGS_4	SAVE_ARGS_3; mov.l r7,@(12,r15); cfi_offset (r7,-16)
 # define SAVE_ARGS_5	SAVE_ARGS_4
 # define SAVE_ARGS_6	SAVE_ARGS_5
 
@@ -245,3 +161,9 @@
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sleep.c b/nptl/sysdeps/unix/sysv/linux/sleep.c
index c56b49b39f..2dce3210ca 100644
--- a/nptl/sysdeps/unix/sysv/linux/sleep.c
+++ b/nptl/sysdeps/unix/sysv/linux/sleep.c
@@ -1,2 +1,10 @@
-#include <nptl/pthreadP.h>
-#include <sysdeps/unix/sysv/linux/sleep.c>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <sleep.c>
+#else
+/* This defines the CANCELLATION_P macro, which sleep.c checks for.  */
+# include <pthreadP.h>
+# include_next <sleep.c>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/smp.h b/nptl/sysdeps/unix/sysv/linux/smp.h
index 4f4d358d32..fcc34f7681 100644
--- a/nptl/sysdeps/unix/sysv/linux/smp.h
+++ b/nptl/sysdeps/unix/sysv/linux/smp.h
@@ -1,5 +1,5 @@
 /* Determine whether the host has multiple processors.  Linux version.
-   Copyright (C) 1996, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996, 2002, 2004, 2006 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
@@ -17,36 +17,12 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/sysctl.h>
-#include <not-cancel.h>
-
 /* Test whether the machine has more than one processor.  This is not the
    best test but good enough.  More complicated tests would require `malloc'
    which is not available at that time.  */
 static inline int
 is_smp_system (void)
 {
-  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION };
-  char buf[512];
-  size_t reslen = sizeof (buf);
-
-  /* Try reading the number using `sysctl' first.  */
-  if (__sysctl ((int *) sysctl_args,
-		sizeof (sysctl_args) / sizeof (sysctl_args[0]),
-		buf, &reslen, NULL, 0) < 0)
-    {
-      /* This was not successful.  Now try reading the /proc filesystem.  */
-      int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY);
-      if (__builtin_expect (fd, 0) == -1
-	  || (reslen = read_not_cancel (fd, buf, sizeof (buf))) <= 0)
-	/* This also didn't work.  We give up and say it's a UP machine.  */
-	buf[0] = '\0';
-
-      close_not_cancel_no_status (fd);
-    }
-
-  return strstr (buf, "SMP") != NULL;
+  /* Assume all machines are SMP and/or CMT and/or SMT.  */
+  return 1;
 }
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/Makefile b/nptl/sysdeps/unix/sysv/linux/sparc/Makefile
new file mode 100644
index 0000000000..e98c9bd866
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/Makefile
@@ -0,0 +1,2 @@
+# pull in __syscall_error routine
+libpthread-routines += sysdep
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
index 3c5a289445..e734c1205e 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  SPARC version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -58,11 +58,25 @@ typedef union
 } pthread_attr_t;
 
 
+#if __WORDSIZE == 64
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is deliberately not exposed.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -73,10 +87,18 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
-#if __WORDSIZE != 64
+#if __WORDSIZE == 64
+    int __spins;
+    __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV	1
+#else
     unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
 #endif
-    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index 4626aec524..5013922a2f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -30,6 +30,11 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -76,15 +81,38 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })
 
+#define lll_robust_mutex_dead(futexv) \
+  do									      \
+    {									      \
+      int *__futexp = &(futexv);					      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      lll_futex_wake (__futexp, 1);					      \
+    }									      \
+  while (0)
+
+/* Returns non-zero if error happened, zero if success.  */
 #ifdef __sparc32_atomic_do_lock
-#error SPARC < v9 does not support compare and swap which is essential for futex based locking
+/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs.  */
+# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1
+#else
+# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_WAKE_OP, (nr_wake),	      \
+			      (nr_wake2), (futexp2),			      \
+			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
+  })
 #endif
 
 static inline int
 __attribute__ ((always_inline))
 __lll_mutex_trylock (int *futex)
 {
-  return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
+  return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0;
 }
 #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
 
@@ -92,47 +120,71 @@ static inline int
 __attribute__ ((always_inline))
 __lll_mutex_cond_trylock (int *futex)
 {
-  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
+  return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0;
 }
 #define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_trylock (int *futex, int id)
+{
+  return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0;
+}
+#define lll_robust_mutex_trylock(futex, id) \
+  __lll_robust_mutex_trylock (&(futex), id)
 
-extern void __lll_lock_wait (int *futex) attribute_hidden;
 
+extern void __lll_lock_wait (int *futex) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
 
 static inline void
 __attribute__ ((always_inline))
 __lll_mutex_lock (int *futex)
 {
-  int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
+  int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
 
   if (__builtin_expect (val != 0, 0))
     __lll_lock_wait (futex);
 }
 #define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_lock (int *futex, int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_lock_wait (futex);
+  return result;
+}
+#define lll_robust_mutex_lock(futex, id) \
+  __lll_robust_mutex_lock (&(futex), id)
 
 static inline void
 __attribute__ ((always_inline))
 __lll_mutex_cond_lock (int *futex)
 {
-  int val = atomic_compare_and_exchange_val_acq (futex, 2, 0);
+  int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0);
 
   if (__builtin_expect (val != 0, 0))
     __lll_lock_wait (futex);
 }
 #define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
 
+#define lll_robust_mutex_cond_lock(futex, id) \
+  __lll_robust_mutex_lock (&(futex), (id) | FUTEX_WAITERS)
+
 
 extern int __lll_timedlock_wait (int *futex, const struct timespec *)
      attribute_hidden;
-
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *)
+     attribute_hidden;
 
 static inline int
 __attribute__ ((always_inline))
 __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
 {
-  int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
+  int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
   int result = 0;
 
   if (__builtin_expect (val != 0, 0))
@@ -142,18 +194,39 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
 #define lll_mutex_timedlock(futex, abstime) \
   __lll_mutex_timedlock (&(futex), abstime)
 
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime,
+			      int id)
+{
+  int result = 0;
+  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+    result = __lll_robust_timedlock_wait (futex, abstime);
+  return result;
+}
+#define lll_robust_mutex_timedlock(futex, abstime, id) \
+  __lll_robust_mutex_timedlock (&(futex), abstime, id)
+
 #define lll_mutex_unlock(lock) \
   ((void) ({								      \
     int *__futex = &(lock);						      \
-    int __val = atomic_exchange_rel (__futex, 0);			      \
+    int __val = atomic_exchange_24_rel (__futex, 0);			      \
     if (__builtin_expect (__val > 1, 0))				      \
       lll_futex_wake (__futex, 1);					      \
   }))
 
+#define lll_robust_mutex_unlock(lock) \
+  ((void) ({								      \
+    int *__futex = &(lock);						      \
+    int __val = atomic_exchange_rel (__futex, 0);			      \
+    if (__builtin_expect (__val & FUTEX_WAITERS, 0))			      \
+      lll_futex_wake (__futex, 1);					      \
+  }))
+
 #define lll_mutex_unlock_force(lock) \
   ((void) ({								      \
     int *__futex = &(lock);						      \
-    (void) atomic_exchange_rel (__futex, 0);				      \
+    (void) atomic_exchange_24_rel (__futex, 0);				      \
     lll_futex_wake (__futex, 1);					      \
   }))
 
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
index da6197c00d..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/sparc/sparc32/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
new file mode 100644
index 0000000000..a7611d6a88
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
@@ -0,0 +1,131 @@
+/* low level locking for pthread library.  SPARC version.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+
+
+void
+__lll_lock_wait (int *futex)
+{
+  do
+    {
+      int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
+      if (oldval != 0)
+	lll_futex_wait (futex, 2);
+    }
+  while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
+}
+
+
+int
+__lll_timedlock_wait (int *futex, const struct timespec *abstime)
+{
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  do
+    {
+      struct timeval tv;
+      struct timespec rt;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+	{
+	  rt.tv_nsec += 1000000000;
+	  --rt.tv_sec;
+	}
+
+      /* Already timed out?  */
+      if (rt.tv_sec < 0)
+	return ETIMEDOUT;
+
+      /* Wait.  */
+      int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
+      if (oldval != 0)
+	lll_futex_timed_wait (futex, 2, &rt);
+    }
+  while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
+
+  return 0;
+}
+
+
+/* These don't get included in libc.so  */
+#ifdef IS_IN_libpthread
+int
+lll_unlock_wake_cb (int *futex)
+{
+  int val = atomic_exchange_24_rel (futex, 0);
+
+  if (__builtin_expect (val > 1, 0))
+    lll_futex_wake (futex, 1);
+
+  return 0;
+}
+
+
+int
+__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
+{
+  int tid;
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Repeat until thread terminated.  */
+  while ((tid = *tidp) != 0)
+    {
+      struct timeval tv;
+      struct timespec rt;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+	{
+	  rt.tv_nsec += 1000000000;
+	  --rt.tv_sec;
+	}
+
+      /* Already timed out?  */
+      if (rt.tv_sec < 0)
+	return ETIMEDOUT;
+
+      /* Wait until thread terminates.  */
+      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
+	return ETIMEDOUT;
+    }
+
+  return 0;
+}
+
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S
index 55229c9e66..fb01242b53 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S
@@ -21,6 +21,7 @@
 #include <tcb-offsets.h>
 
 	.text
+	.globl		__syscall_error
 ENTRY(__vfork)
 	ld	[%g7 + PID], %o5
 	sub	%g0, %o5, %o4
@@ -28,15 +29,17 @@ ENTRY(__vfork)
 
 	LOADSYSCALL(vfork)
 	ta	0x10
-	bcs,a	__syscall_error_handler
-	 st	%o5, [%g7 + PID]
-	SYSCALL_ERROR_HANDLER
-	sub	%o1, 1, %o1
+	bcc	2f
+	 mov	%o7, %g1
+	st	%o5, [%g7 + PID]
+	call	__syscall_error
+	 mov	%g1, %o7
+2:	sub	%o1, 1, %o1
 	andcc	%o0, %o1, %o0
 	bne,a	1f
 	 st	%o5, [%g7 + PID]
 1:	retl
 	 nop
+END(__vfork)
 
-PSEUDO_END (__vfork)
 weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c
new file mode 100644
index 0000000000..bbd08d0041
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 "pthreadP.h"
+#include <lowlevellock.h>
+
+struct sparc_pthread_barrier
+{
+  struct pthread_barrier b;
+  unsigned char left_lock;
+  unsigned char pshared;
+};
+
+int
+pthread_barrier_init (barrier, attr, count)
+     pthread_barrier_t *barrier;
+     const pthread_barrierattr_t *attr;
+     unsigned int count;
+{
+  struct sparc_pthread_barrier *ibarrier;
+
+  if (__builtin_expect (count == 0, 0))
+    return EINVAL;
+
+  struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr;
+  if (iattr != NULL)
+    {
+      if (iattr->pshared != PTHREAD_PROCESS_PRIVATE
+	  && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0))
+	/* Invalid attribute.  */
+	return EINVAL;
+    }
+
+  ibarrier = (struct sparc_pthread_barrier *) barrier;
+
+  /* Initialize the individual fields.  */
+  ibarrier->b.lock = LLL_LOCK_INITIALIZER;
+  ibarrier->b.left = count;
+  ibarrier->b.init_count = count;
+  ibarrier->b.curr_event = 0;
+  ibarrier->left_lock = 0;
+  ibarrier->pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED);
+
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c
new file mode 100644
index 0000000000..4dfd11dcbe
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <pthreadP.h>
+
+struct sparc_pthread_barrier
+{
+  struct pthread_barrier b;
+  unsigned char left_lock;
+  unsigned char pshared;
+};
+
+/* Wait on barrier.  */
+int
+pthread_barrier_wait (barrier)
+     pthread_barrier_t *barrier;
+{
+  struct sparc_pthread_barrier *ibarrier
+    = (struct sparc_pthread_barrier *) barrier;
+  int result = 0;
+
+  /* Make sure we are alone.  */
+  lll_lock (ibarrier->b.lock);
+
+  /* One more arrival.  */
+  --ibarrier->b.left;
+
+  /* Are these all?  */
+  if (ibarrier->b.left == 0)
+    {
+      /* Yes. Increment the event counter to avoid invalid wake-ups and
+	 tell the current waiters that it is their turn.  */
+      ++ibarrier->b.curr_event;
+
+      /* Wake up everybody.  */
+      lll_futex_wake (&ibarrier->b.curr_event, INT_MAX);
+
+      /* This is the thread which finished the serialization.  */
+      result = PTHREAD_BARRIER_SERIAL_THREAD;
+    }
+  else
+    {
+      /* The number of the event we are waiting for.  The barrier's event
+	 number must be bumped before we continue.  */
+      unsigned int event = ibarrier->b.curr_event;
+
+      /* Before suspending, make the barrier available to others.  */
+      lll_unlock (ibarrier->b.lock);
+
+      /* Wait for the event counter of the barrier to change.  */
+      do
+	lll_futex_wait (&ibarrier->b.curr_event, event);
+      while (event == ibarrier->b.curr_event);
+    }
+
+  /* Make sure the init_count is stored locally or in a register.  */
+  unsigned int init_count = ibarrier->b.init_count;
+
+  /* If this was the last woken thread, unlock.  */
+  if (__atomic_is_v9 || ibarrier->pshared == 0)
+    {
+      if (atomic_increment_val (&ibarrier->b.left) == init_count)
+	/* We are done.  */
+	lll_unlock (ibarrier->b.lock);
+    }
+  else
+    {
+      unsigned int left;
+      /* Slightly more complicated.  On pre-v9 CPUs, atomic_increment_val
+	 is only atomic for threads within the same process, not for
+	 multiple processes.  */
+      __sparc32_atomic_do_lock24 (&ibarrier->left_lock);
+      left = ++ibarrier->b.left;
+      __sparc32_atomic_do_unlock24 (&ibarrier->left_lock);
+      if (left == init_count)
+        /* We are done.  */
+        lll_unlock (ibarrier->b.lock);
+    }
+
+  return result;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c
new file mode 100644
index 0000000000..dffd8c7efa
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <semaphore.h>
+#include <lowlevellock.h>
+#include <shlib-compat.h>
+#include "semaphoreP.h"
+
+struct sparc_sem
+{
+  struct sem s;
+  unsigned char lock;
+};
+
+
+int
+__new_sem_init (sem, pshared, value)
+     sem_t *sem;
+     int pshared;
+     unsigned int value;
+{
+  /* Parameter sanity check.  */
+  if (__builtin_expect (value > SEM_VALUE_MAX, 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  /* Map to the internal type.  */
+  struct sparc_sem *isem = (struct sparc_sem *) sem;
+
+  /* Use the value the user provided.  */
+  isem->s.count = value;
+
+  isem->lock = 0;
+
+  /* We can completely ignore the PSHARED parameter since inter-process
+     use needs no special preparation.  */
+
+  return 0;
+}
+versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_init, __old_sem_init)
+compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
new file mode 100644
index 0000000000..be1cc60b11
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
@@ -0,0 +1,54 @@
+/* sem_post -- post to a POSIX semaphore.  SPARC version.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <shlib-compat.h>
+
+int
+__new_sem_post (sem_t *sem)
+{
+  int *futex = (int *) sem, nr;
+
+  if (__atomic_is_v9)
+    nr = atomic_increment_val (futex);
+  else
+    {
+      __sparc32_atomic_do_lock24 (futex + 1);
+      nr = ++*futex;
+      __sparc32_atomic_do_unlock24 (futex + 1);
+    }
+  int err = lll_futex_wake (futex, nr);
+  if (__builtin_expect (err, 0) < 0)
+    {
+      __set_errno (-err);
+      return -1;
+    }
+  return 0;
+}
+versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_post, __old_sem_post)
+compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
new file mode 100644
index 0000000000..efcc9e9aa8
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
@@ -0,0 +1,117 @@
+/* sem_timedwait -- wait on a semaphore.  SPARC version.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *abstime)
+{
+  /* First check for cancellation.  */
+  CANCELLATION_P (THREAD_SELF);
+
+  int *futex = (int *) sem;
+  int val;
+  int err;
+
+  if (*futex > 0)
+    {
+      if (__atomic_is_v9)
+	val = atomic_decrement_if_positive (futex);
+      else
+	{
+	  __sparc32_atomic_do_lock24 (futex + 1);
+	  val = *futex;
+	  if (val > 0)
+	    *futex = val - 1;
+	  __sparc32_atomic_do_unlock24 (futex + 1);
+	}
+      if (val > 0)
+	return 0;
+    }
+
+  err = -EINVAL;
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    goto error_return;
+
+  do
+    {
+      struct timeval tv;
+      struct timespec rt;
+      int sec, nsec;
+
+      /* Get the current time.  */
+      __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      sec = abstime->tv_sec - tv.tv_sec;
+      nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (nsec < 0)
+	{
+	  nsec += 1000000000;
+	  --sec;
+	}
+
+      /* Already timed out?  */
+      err = -ETIMEDOUT;
+      if (sec < 0)
+	goto error_return;
+
+      /* Do wait.  */
+      rt.tv_sec = sec;
+      rt.tv_nsec = nsec;
+
+      /* Enable asynchronous cancellation.  Required by the standard.  */
+      int oldtype = __pthread_enable_asynccancel ();
+
+      err = lll_futex_timed_wait (futex, 0, &rt);
+
+      /* Disable asynchronous cancellation.  */
+      __pthread_disable_asynccancel (oldtype);
+
+      if (err != 0 && err != -EWOULDBLOCK)
+	goto error_return;
+
+      if (__atomic_is_v9)
+	val = atomic_decrement_if_positive (futex);
+      else
+	{
+	  __sparc32_atomic_do_lock24 (futex + 1);
+	  val = *futex;
+	  if (val > 0)
+	    *futex = val - 1;
+	  __sparc32_atomic_do_unlock24 (futex + 1);
+	}
+    }
+  while (val <= 0);
+
+  return 0;
+
+ error_return:
+  __set_errno (-err);
+  return -1;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
new file mode 100644
index 0000000000..429494e257
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
@@ -0,0 +1,59 @@
+/* sem_trywait -- wait on a semaphore.  SPARC version.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <shlib-compat.h>
+
+
+int
+__new_sem_trywait (sem_t *sem)
+{
+  int *futex = (int *) sem;
+  int val;
+
+  if (*futex > 0)
+    {
+      if (__atomic_is_v9)
+	val = atomic_decrement_if_positive (futex);
+      else
+	{
+	  __sparc32_atomic_do_lock24 (futex + 1);
+	  val = *futex;
+	  if (val > 0)
+	    *futex = val - 1;
+	  __sparc32_atomic_do_unlock24 (futex + 1);
+	}
+      if (val > 0)
+	return 0;
+    }
+
+  __set_errno (EAGAIN);
+  return -1;
+}
+versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_trywait, __old_sem_trywait)
+compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
new file mode 100644
index 0000000000..d9fcdcd4ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
@@ -0,0 +1,74 @@
+/* sem_wait -- wait on a semaphore.  SPARC version.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
+
+   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 <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+int
+__new_sem_wait (sem_t *sem)
+{
+  /* First check for cancellation.  */
+  CANCELLATION_P (THREAD_SELF);
+
+  int *futex = (int *) sem;
+  int err;
+
+  do
+    {
+      int val;
+      if (__atomic_is_v9)
+	val = atomic_decrement_if_positive (futex);
+      else
+	{
+	  __sparc32_atomic_do_lock24 (futex + 1);
+	  val = *futex;
+	  if (val > 0)
+	    *futex = val - 1;
+	  __sparc32_atomic_do_unlock24 (futex + 1);
+	}
+      if (val > 0)
+	return 0;
+
+      /* Enable asynchronous cancellation.  Required by the standard.  */
+      int oldtype = __pthread_enable_asynccancel ();
+
+      err = lll_futex_wait (futex, 0);
+
+      /* Disable asynchronous cancellation.  */
+      __pthread_disable_asynccancel (oldtype);
+    }
+  while (err == 0 || err == -EWOULDBLOCK);
+
+  __set_errno (-err);
+  return -1;
+}
+
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_wait, __old_sem_wait)
+compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c
new file mode 100644
index 0000000000..b2b842336e
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c
@@ -0,0 +1 @@
+#include "../../../../../../../pthread_barrier_init.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c
new file mode 100644
index 0000000000..7613863bba
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c
@@ -0,0 +1 @@
+#include "../../../../../../pthread/pthread_barrier_wait.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c
new file mode 100644
index 0000000000..b2ebc4cbb5
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c
@@ -0,0 +1 @@
+#include "../../../../../../../sem_init.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c
new file mode 100644
index 0000000000..4a6eac88f5
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c
@@ -0,0 +1 @@
+#include "../../../sem_post.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c
new file mode 100644
index 0000000000..b2526db02c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c
@@ -0,0 +1 @@
+#include "../../../sem_timedwait.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c
new file mode 100644
index 0000000000..aae46f725e
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c
@@ -0,0 +1 @@
+#include "../../../sem_trywait.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c
new file mode 100644
index 0000000000..31157f636f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c
@@ -0,0 +1 @@
+#include "../../../sem_wait.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
index 5edf4b3772..f0349906b2 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -26,55 +26,48 @@
 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
 
 # undef PSEUDO
-# define PSEUDO(name, syscall_name, args)				      \
-	.text;								      \
-ENTRY(name)								      \
-	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;			      \
-	cmp %g1, 0;							      \
-	bne 1f;								      \
-.type	__##syscall_name##_nocancel,@function;				      \
-.globl	__##syscall_name##_nocancel;					      \
-__##syscall_name##_nocancel:						      \
-	 mov SYS_ify(syscall_name), %g1;				      \
-	ta 0x10;							      \
-	bcs __syscall_error_handler;					      \
-	 nop;								      \
-.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
-	.subsection 2;							      \
-	cfi_startproc;							      \
-1:	save %sp, -96, %sp;						      \
-	cfi_def_cfa_register (%fp);					      \
-	cfi_window_save;						      \
-	cfi_register (%o7, %i7);					      \
-	CENABLE;							      \
-	 nop;								      \
-	mov %o0, %l0;							      \
-	COPY_ARGS_##args						      \
-	mov SYS_ify(syscall_name), %g1;					      \
-	ta 0x10;							      \
-	bcs __syscall_error_handler2;					      \
-	 mov %o0, %l1;							      \
-	CDISABLE;							      \
-	 mov %l0, %o0;							      \
-	jmpl %i7 + 8, %g0;						      \
-	 restore %g0, %l1, %o0;						      \
-	cfi_endproc;							      \
-	.previous;							      \
-	SYSCALL_ERROR_HANDLER						      \
-	SYSCALL_ERROR_HANDLER2
+# define PSEUDO(name, syscall_name, args)	\
+	.text;					\
+	.globl		__syscall_error;	\
+ENTRY(name)					\
+	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
+	cmp %g1, 0;				\
+	bne 1f;					\
+.type	__##syscall_name##_nocancel,@function;	\
+.globl	__##syscall_name##_nocancel;		\
+__##syscall_name##_nocancel:			\
+	 mov SYS_ify(syscall_name), %g1;	\
+	ta 0x10;				\
+	bcc 8f;					\
+	 mov %o7, %g1;				\
+	call __syscall_error;			\
+	 mov %g1, %o7;				\
+8:	jmpl %o7 + 8, %g0;			\
+	 nop;					\
+.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
+1:	save %sp, -96, %sp;			\
+	cfi_def_cfa_register(%fp);		\
+	cfi_window_save;			\
+	cfi_register(%o7, %i7);			\
+	CENABLE;				\
+	 nop;					\
+	mov %o0, %l0;				\
+	COPY_ARGS_##args			\
+	mov SYS_ify(syscall_name), %g1;		\
+	ta 0x10;				\
+	bcc 1f;					\
+	 mov %o0, %l1;				\
+	CDISABLE;				\
+	 mov %l0, %o0;				\
+	call __syscall_error;			\
+	 mov %l1, %o0;				\
+	b 2f;					\
+	 mov -1, %l1;				\
+1:	CDISABLE;				\
+	 mov %l0, %o0;				\
+2:	jmpl %i7 + 8, %g0;			\
+	 restore %g0, %l1, %o0;
 
-#define SYSCALL_ERROR_HANDLER2						      \
-SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
-	.global __errno_location;					      \
-        .type   __errno_location,@function;				      \
-	CDISABLE;							      \
-	 mov	%l0, %o0;						      \
-	call	__errno_location;					      \
-	 nop;								      \
-	st	%l1, [%o0];						      \
-	jmpl	%i7 + 8, %g0;						      \
-	 restore %g0, -1, %o0;						      \
-	.previous;
 
 # ifdef IS_IN_libpthread
 #  define CENABLE	call __pthread_enable_asynccancel
@@ -111,3 +104,9 @@ SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
index 7229608142..a8e4dd5a43 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
@@ -21,6 +21,7 @@
 #include <tcb-offsets.h>
 
 	.text
+	.globl		__syscall_error
 ENTRY(__vfork)
 	ld	[%g7 + PID], %o5
 	cmp	%o5, 0
@@ -31,16 +32,18 @@ ENTRY(__vfork)
 
 	LOADSYSCALL(vfork)
 	ta	0x10
-	bcs,a	__syscall_error_handler
-	 st	%o5, [%g7 + PID]
-	SYSCALL_ERROR_HANDLER
-	sub	%o1, 1, %o1
+	bcc	2f
+	 mov	%o7, %g1
+	st	%o5, [%g7 + PID]
+	call	__syscall_error
+	 mov	%g1, %o7
+2:	sub	%o1, 1, %o1
 	andcc	%o0, %o1, %o0
 	bne,a	1f
 	 st	%o5, [%g7 + PID]
 1:	retl
 	 nop
+END(__vfork)
 
-PSEUDO_END (__vfork)
 libc_hidden_def (__vfork)
 weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
new file mode 100644
index 0000000000..675a997e97
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
@@ -0,0 +1,9 @@
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S
index e9018b2e99..8941043c3a 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S
@@ -21,6 +21,7 @@
 #include <tcb-offsets.h>
 
 	.text
+	.globl	__syscall_error
 ENTRY(__vfork)
 	ld	[%g7 + PID], %o5
 	sub	%g0, %o5, %o4
@@ -28,15 +29,17 @@ ENTRY(__vfork)
 
 	LOADSYSCALL(vfork)
 	ta	0x6d
-	bcs,a,pn %xcc, __syscall_error_handler
-	 st	%o5, [%g7 + PID]
-	SYSCALL_ERROR_HANDLER
-	sub	%o1, 1, %o1
+	bcc,pt	%xcc, 2f
+	 mov	%o7, %g1
+	st	%o5, [%g7 + PID]
+	call	__syscall_error
+	 mov	%g1, %o7
+2:	sub	%o1, 1, %o1
 	andcc	%o0, %o1, %o0
 	bne,a,pt %icc, 1f
 	 st	%o5, [%g7 + PID]
 1:	retl
 	 nop
+END(__vfork)
 
-PSEUDO_END (__vfork)
 weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
index d8c65aeffd..2c76d01715 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -26,49 +26,46 @@
 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
 
 # undef PSEUDO
-# define PSEUDO(name, syscall_name, args)				      \
-	.text;								      \
-ENTRY(name)								      \
-	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;			      \
-	brnz,pn %g1, 1f;						      \
-.type	__##syscall_name##_nocancel,@function;				      \
-.globl	__##syscall_name##_nocancel;					      \
-__##syscall_name##_nocancel:						      \
-	 mov SYS_ify(syscall_name), %g1;				      \
-	ta 0x6d;							      \
-	bcs,pn %xcc, __syscall_error_handler;				      \
-	 nop;								      \
-.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
-	.subsection 2;							      \
-1:	save %sp, -192, %sp;						      \
-	CENABLE;							      \
-	 nop;								      \
-	mov %o0, %l0;							      \
-	COPY_ARGS_##args						      \
-	mov SYS_ify(syscall_name), %g1;					      \
-	ta 0x6d;							      \
-	bcs,pn %xcc, __syscall_error_handler2;				      \
-	 mov %o0, %l1;							      \
-	CDISABLE;							      \
-	 mov %l0, %o0;							      \
-	jmpl %i7 + 8, %g0;						      \
-	 restore %g0, %l1, %o0;						      \
-	.previous;							      \
-	SYSCALL_ERROR_HANDLER						      \
-	SYSCALL_ERROR_HANDLER2
-
-#define SYSCALL_ERROR_HANDLER2						      \
-SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
-	.global __errno_location;					      \
-        .type   __errno_location,@function;				      \
-	CDISABLE;							      \
-	 mov	%l0, %o0;						      \
-	call	__errno_location;					      \
-	 nop;								      \
-	st	%l1, [%o0];						      \
-	jmpl	%i7 + 8, %g0;						      \
-	 restore %g0, -1, %o0;						      \
-	.previous;
+# define PSEUDO(name, syscall_name, args)	\
+	.text;					\
+	.globl		__syscall_error;	\
+ENTRY(name)					\
+	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
+	brnz,pn %g1, 1f;			\
+.type	__##syscall_name##_nocancel,@function;	\
+.globl	__##syscall_name##_nocancel;		\
+__##syscall_name##_nocancel:			\
+	 mov SYS_ify(syscall_name), %g1;	\
+	ta 0x6d;				\
+	bcc,pt %xcc, 8f;			\
+	 mov %o7, %g1;				\
+	call __syscall_error;			\
+	 mov %g1, %o7;				\
+8:	jmpl %o7 + 8, %g0;			\
+	 nop;					\
+.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
+1:	save %sp, -192, %sp;			\
+	cfi_def_cfa_register(%fp);		\
+	cfi_window_save;			\
+	cfi_register(%o7, %i7);			\
+	CENABLE;				\
+	 nop;					\
+	mov %o0, %l0;				\
+	COPY_ARGS_##args			\
+	mov SYS_ify(syscall_name), %g1;		\
+	ta 0x6d;				\
+	bcc,pt %xcc, 1f;			\
+	 mov %o0, %l1;				\
+	CDISABLE;				\
+	 mov %l0, %o0;				\
+	call __syscall_error;			\
+	 mov %l1, %o0;				\
+	ba,pt %xcc, 2f;				\
+	 mov -1, %l1;				\
+1:	CDISABLE;				\
+	 mov %l0, %o0;				\
+2:	jmpl %i7 + 8, %g0;			\
+	 restore %g0, %l1, %o0;
 
 # ifdef IS_IN_libpthread
 #  define CENABLE	call __pthread_enable_asynccancel
@@ -105,3 +102,9 @@ SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
index d6b2455d43..5597574304 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
@@ -21,6 +21,7 @@
 #include <tcb-offsets.h>
 
 	.text
+	.globl	__syscall_error
 ENTRY(__vfork)
 	ld	[%g7 + PID], %o5
 	sethi	%hi(0x80000000), %o3
@@ -31,16 +32,18 @@ ENTRY(__vfork)
 
 	LOADSYSCALL(vfork)
 	ta	0x6d
-	bcs,a,pn %xcc, __syscall_error_handler
-	 st	%o5, [%g7 + PID]
-	SYSCALL_ERROR_HANDLER
-	sub	%o1, 1, %o1
+	bcc,pt	%xcc, 2f
+	 mov	%o7, %g1
+	st	%o5, [%g7 + PID]
+	call	__syscall_error
+	 mov	%g1, %o7
+2:	sub	%o1, 1, %o1
 	andcc	%o0, %o1, %o0
 	bne,a,pt %icc, 1f
 	 st	%o5, [%g7 + PID]
 1:	retl
 	 nop
+END(__vfork)
 
-PSEUDO_END (__vfork)
 libc_hidden_def (__vfork)
 weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/timer_create.c b/nptl/sysdeps/unix/sysv/linux/timer_create.c
index ca6ff6c7ef..5e99513950 100644
--- a/nptl/sysdeps/unix/sysv/linux/timer_create.c
+++ b/nptl/sysdeps/unix/sysv/linux/timer_create.c
@@ -28,6 +28,7 @@
 #include <internaltypes.h>
 #include <nptl/pthreadP.h>
 #include "kernel-posix-timers.h"
+#include "kernel-posix-cpu-timers.h"
 
 
 #ifdef __NR_timer_create
@@ -58,6 +59,12 @@ timer_create (clock_id, evp, timerid)
   if  (__no_posix_timers >= 0)
 # endif
     {
+      clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID
+				   ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
+				   : clock_id == CLOCK_THREAD_CPUTIME_ID
+				   ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
+				   : clock_id);
+
       /* If the user wants notification via a thread we need to handle
 	 this special.  */
       if (evp == NULL
@@ -88,7 +95,7 @@ timer_create (clock_id, evp, timerid)
 	    }
 
 	  kernel_timer_t ktimerid;
-	  int retval = INLINE_SYSCALL (timer_create, 3, clock_id, evp,
+	  int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp,
 				       &ktimerid);
 
 # ifndef __ASSUME_POSIX_TIMERS
@@ -196,8 +203,8 @@ timer_create (clock_id, evp, timerid)
 	      /* Create the timer.  */
 	      INTERNAL_SYSCALL_DECL (err);
 	      int res;
-	      res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
-				      &newp->ktimerid);
+	      res = INTERNAL_SYSCALL (timer_create, err, 3,
+				      syscall_clockid, &sev, &newp->ktimerid);
 	      if (! INTERNAL_SYSCALL_ERROR_P (res, err))
 		{
 		  *timerid = (timer_t) newp;
diff --git a/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/nptl/sysdeps/unix/sysv/linux/timer_routines.c
index 23c800f98e..a5eb442251 100644
--- a/nptl/sysdeps/unix/sysv/linux/timer_routines.c
+++ b/nptl/sysdeps/unix/sysv/linux/timer_routines.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -27,6 +27,13 @@
 #include "kernel-posix-timers.h"
 
 
+struct thread_start_data
+{
+  void (*thrfunc) (sigval_t);
+  sigval_t sival;
+};
+
+
 #ifdef __NR_timer_create
 /* Helper thread to call the user-provided function.  */
 static void *
@@ -40,10 +47,16 @@ timer_sigev_thread (void *arg)
   INTERNAL_SYSCALL_DECL (err);
   INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8);
 
-  struct timer *tk = (struct timer *) arg;
+  struct thread_start_data *td = (struct thread_start_data *) arg;
+
+  void (*thrfunc) (sigval_t) = td->thrfunc;
+  sigval_t sival = td->sival;
+
+  /* The TD object was allocated in timer_helper_thread.  */
+  free (td);
 
   /* Call the user-provided function.  */
-  tk->thrfunc (tk->sival);
+  thrfunc (sival);
 
   return NULL;
 }
@@ -53,10 +66,11 @@ timer_sigev_thread (void *arg)
 static void *
 timer_helper_thread (void *arg)
 {
-  /* Wait for the SIGTIMER signal and none else.  */
+  /* Wait for the SIGTIMER signal, allowing the setXid signal, and
+     none else.  */
   sigset_t ss;
   sigemptyset (&ss);
-  sigaddset (&ss, SIGTIMER);
+  __sigaddset (&ss, SIGTIMER);
 
   /* Endless loop of waiting for signals.  The loop is only ended when
      the thread is canceled.  */
@@ -81,10 +95,19 @@ timer_helper_thread (void *arg)
 	  if (si.si_code == SI_TIMER)
 	    {
 	      struct timer *tk = (struct timer *) si.si_ptr;
-
-	      /* That the signal we are waiting for.  */
-	      pthread_t th;
-	      (void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk);
+	      struct thread_start_data *td = malloc (sizeof (*td));
+
+	      /* There is not much we can do if the allocation fails.  */
+	      if (td != NULL)
+		{
+		  /* That is the signal we are waiting for.  */
+		  td->thrfunc = tk->thrfunc;
+		  td->sival = tk->sival;
+
+		  pthread_t th;
+		  (void) pthread_create (&th, &tk->attr, timer_sigev_thread,
+					 td);
+		}
 	    }
 	  else if (si.si_code == SI_TKILL)
 	    /* The thread is canceled.  */
@@ -121,10 +144,11 @@ __start_helper_thread (void)
   (void) pthread_attr_init (&attr);
   (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
 
-  /* Block all signals in the helper thread.  To do this thoroughly we
-     temporarily have to block all signals here.  The helper can lose
-     wakeups if SIGCANCEL is not blocked throughout, but sigfillset omits
-     it.  So, we add it back explicitly here.  */
+  /* Block all signals in the helper thread but SIGSETXID.  To do this
+     thoroughly we temporarily have to block all signals here.  The
+     helper can lose wakeups if SIGCANCEL is not blocked throughout,
+     but sigfillset omits it SIGSETXID.  So, we add SIGCANCEL back
+     explicitly here.  */
   sigset_t ss;
   sigset_t oss;
   sigfillset (&ss);
diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
index 72c8d615eb..964f5b7094 100644
--- a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
+++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,7 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
-#include "fork.h"
+#include <fork.h>
 #include <atomic.h>
 
 
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
index 92fb08c951..693387a266 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -57,11 +57,25 @@ typedef union
 } pthread_attr_t;
 
 
+#if __WORDSIZE == 64
+typedef struct __pthread_internal_list
+{
+  struct __pthread_internal_list *__prev;
+  struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
 typedef union
 {
-  struct
+  struct __pthread_mutex_s
   {
     int __lock;
     unsigned int __count;
@@ -72,10 +86,18 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
-#if __WORDSIZE != 64
+#if __WORDSIZE == 64
+    int __spins;
+    __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV	1
+#else
     unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
 #endif
-    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
@@ -192,4 +214,9 @@ typedef union
 #endif
 
 
+#if __WORDSIZE == 32
+/* Extra attributes for the cleanup functions.  */
+# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
+#endif
+
 #endif	/* bits/pthreadtypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S b/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S
index dfa6adb3e2..675a997e97 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S
@@ -1,2 +1,9 @@
-#define RESET_PID
-#include <sysdeps/unix/sysv/linux/x86_64/clone.S>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <clone.S>
+#else
+# define RESET_PID
+# include_next <clone.S>
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
index d5c9345558..394dec8d82 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -43,17 +43,25 @@
 	.hidden	__lll_mutex_lock_wait
 	.align	16
 __lll_mutex_lock_wait:
+	cfi_startproc
 	pushq	%r10
+	cfi_adjust_cfa_offset(8)
 	pushq	%rdx
-
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%r10, -16)
+	cfi_offset(%rdx, -24)
 	xorq	%r10, %r10	/* No timeout.  */
 	movl	$2, %edx
-	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 
 	cmpl	%edx, %eax	/* NB:	 %edx == 2 */
 	jne	2f
 
-1:	movq	$SYS_futex, %rax
+1:	movl	$SYS_futex, %eax
 	syscall
 
 2:	movl	%edx, %eax
@@ -63,8 +71,13 @@ __lll_mutex_lock_wait:
 	jnz	1b
 
 	popq	%rdx
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%rdx)
 	popq	%r10
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r10)
 	retq
+	cfi_endproc
 	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait
 
 
@@ -74,18 +87,30 @@ __lll_mutex_lock_wait:
 	.hidden	__lll_mutex_timedlock_wait
 	.align	16
 __lll_mutex_timedlock_wait:
+	cfi_startproc
 	/* Check for a valid timeout value.  */
 	cmpq	$1000000000, 8(%rdx)
 	jae	3f
 
 	pushq	%r8
+	cfi_adjust_cfa_offset(8)
 	pushq	%r9
+	cfi_adjust_cfa_offset(8)
 	pushq	%r12
+	cfi_adjust_cfa_offset(8)
 	pushq	%r13
+	cfi_adjust_cfa_offset(8)
 	pushq	%r14
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%r8, -16)
+	cfi_offset(%r9, -24)
+	cfi_offset(%r12, -32)
+	cfi_offset(%r13, -40)
+	cfi_offset(%r14, -48)
 
 	/* Stack frame for the timespec and timeval structs.  */
 	subq	$16, %rsp
+	cfi_adjust_cfa_offset(16)
 
 	movq	%rdi, %r12
 	movq	%rdx, %r13
@@ -93,7 +118,7 @@ __lll_mutex_timedlock_wait:
 1:
 	/* Get current time.  */
 	movq	%rsp, %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	/* This is a regular function call, all caller-save registers
 	   might be clobbered.  */
@@ -101,7 +126,7 @@ __lll_mutex_timedlock_wait:
 
 	/* Compute relative timeout.  */
 	movq	8(%rsp), %rax
-	movq	$1000, %rdi
+	movl	$1000, %edi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rdi
 	movq	8(%r13), %rsi
@@ -126,26 +151,50 @@ __lll_mutex_timedlock_wait:
 	je	8f
 
 	movq	%rsp, %r10
-	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	movq	%r12, %rdi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 	movq	%rax, %rcx
 
 8:				/* NB: %edx == 2 */
 	xorl	%eax, %eax
 	LOCK
-	cmpxchgl %edx, (%rdi)
+	cmpxchgl %edx, (%r12)
 	jnz	7f
 
 6:	addq	$16, %rsp
+	cfi_adjust_cfa_offset(-16)
 	popq	%r14
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r14)
 	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r13)
 	popq	%r12
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r12)
 	popq	%r9
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r9)
 	popq	%r8
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r8)
 	retq
 
+3:	movl	$EINVAL, %eax
+	retq
+
+	cfi_adjust_cfa_offset(56)
+	cfi_offset(%r8, -16)
+	cfi_offset(%r9, -24)
+	cfi_offset(%r12, -32)
+	cfi_offset(%r13, -40)
+	cfi_offset(%r14, -48)
 	/* Check whether the time expired.  */
 7:	cmpq	$-ETIMEDOUT, %rcx
 	je	5f
@@ -157,11 +206,9 @@ __lll_mutex_timedlock_wait:
 	jz	6b
 	jmp	1b
 
-3:	movl	$EINVAL, %eax
-	retq
-
 5:	movl	$ETIMEDOUT, %eax
 	jmp	6b
+	cfi_endproc
 	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
 #endif
 
@@ -191,18 +238,28 @@ lll_unlock_wake_cb:
 	.hidden	__lll_mutex_unlock_wake
 	.align	16
 __lll_mutex_unlock_wake:
+	cfi_startproc
 	pushq	%rsi
+	cfi_adjust_cfa_offset(8)
 	pushq	%rdx
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%rsi, -16)
+	cfi_offset(%rdx, -24)
 
 	movl	$0, (%rdi)
-	movq	$FUTEX_WAKE, %rsi
+	movl	$FUTEX_WAKE, %esi
 	movl	$1, %edx	/* Wake one thread.  */
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 
 	popq	%rdx
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%rdx)
 	popq	%rsi
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%rsi)
 	retq
+	cfi_endproc
 	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
 
 
@@ -222,13 +279,13 @@ __lll_timedwait_tid:
 
 	/* Get current time.  */
 2:	movq	%rsp, %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	8(%rsp), %rax
-	movq	$1000, %rdi
+	movl	$1000, %edi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rdi
 	movq	8(%r13), %rsi
@@ -248,9 +305,13 @@ __lll_timedwait_tid:
 	jz	4f
 
 	movq	%rsp, %r10
-	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	movq	%r12, %rdi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 
 	cmpl	$0, (%rdi)
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
index 40c2518af6..97085bf018 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -35,6 +35,9 @@
 #define SYS_futex		202
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 
 /* Initializer for compatibility lock.  */
@@ -46,17 +49,130 @@
 #define BUSY_WAIT_NOP          asm ("rep; nop")
 
 
+#define LLL_STUB_UNWIND_INFO_START \
+	".section	.eh_frame,\"a\",@progbits\n" 		\
+"7:\t"	".long	9f-8f	# Length of Common Information Entry\n" \
+"8:\t"	".long	0x0	# CIE Identifier Tag\n\t" 		\
+	".byte	0x1	# CIE Version\n\t" 			\
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t" 	\
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t" 	\
+	".sleb128 -8	# CIE Data Alignment Factor\n\t" 	\
+	".byte	0x10	# CIE RA Column\n\t" 			\
+	".uleb128 0x1	# Augmentation size\n\t" 		\
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t" 	\
+	".byte	0x12	# DW_CFA_def_cfa_sf\n\t" 		\
+	".uleb128 0x7\n\t" 					\
+	".sleb128 16\n\t" 					\
+	".align 8\n" 						\
+"9:\t"	".long	23f-10f	# FDE Length\n" 			\
+"10:\t"	".long	10b-7b	# FDE CIE offset\n\t" 			\
+	".long	1b-.	# FDE initial location\n\t" 		\
+	".long	6b-1b	# FDE address range\n\t" 		\
+	".uleb128 0x0	# Augmentation size\n\t" 		\
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 12f-11f\n" 					\
+"11:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 4b-1b\n"
+#define LLL_STUB_UNWIND_INFO_END \
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 14f-13f\n" 					\
+"13:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 4b-2b\n" 					\
+"14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t" 	\
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t" 		\
+	".uleb128 0\n\t" 					\
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 16f-15f\n" 					\
+"15:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 4b-3b\n" 					\
+"16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t" 	\
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t" 		\
+	".uleb128 128\n\t" 					\
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 20f-17f\n" 					\
+"17:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 19f-18f\n\t" 					\
+	".byte	0x0d	# DW_OP_const4s\n" 			\
+"18:\t"	".4byte	4b-.\n\t" 					\
+	".byte	0x1c	# DW_OP_minus\n\t" 			\
+	".byte	0x0d	# DW_OP_const4s\n" 			\
+"19:\t"	".4byte	24f-.\n\t" 					\
+	".byte	0x22	# DW_OP_plus\n" 			\
+"20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t" 	\
+	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t" 	\
+	".sleb128 16\n\t" 					\
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 22f-21f\n" 					\
+"21:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 4b-5b\n" 					\
+"22:\t"	".align 8\n" 						\
+"23:\t"	".previous\n"
+
+/* Unwind info for
+   1: leaq ..., %rdi
+   2: subq $128, %rsp
+   3: callq ...
+   4: addq $128, %rsp
+   5: jmp 24f
+   6:
+   snippet.  */
+#define LLL_STUB_UNWIND_INFO_5 \
+LLL_STUB_UNWIND_INFO_START					\
+"12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" 	\
+LLL_STUB_UNWIND_INFO_END
+
+/* Unwind info for
+   1: leaq ..., %rdi
+   0: movq ..., %rdx
+   2: subq $128, %rsp
+   3: callq ...
+   4: addq $128, %rsp
+   5: jmp 24f
+   6:
+   snippet.  */
+#define LLL_STUB_UNWIND_INFO_6 \
+LLL_STUB_UNWIND_INFO_START					\
+"12:\t"	".byte	0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" 	\
+	".byte	0x16	# DW_CFA_val_expression\n\t" 		\
+	".uleb128 0x10\n\t" 					\
+	".uleb128 26f-25f\n" 					\
+"25:\t"	".byte	0x80	# DW_OP_breg16\n\t" 			\
+	".sleb128 4b-0b\n" 					\
+"26:\t"	".byte	0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" 	\
+LLL_STUB_UNWIND_INFO_END
+
+
 #define lll_futex_wait(futex, val) \
-  do {									      \
-    int __ignore;							      \
+  ({									      \
+    int __status;							      \
     register __typeof (val) _val asm ("edx") = (val);			      \
     __asm __volatile ("xorq %%r10, %%r10\n\t"				      \
 		      "syscall"						      \
-		      : "=a" (__ignore)					      \
+		      : "=a" (__status)					      \
 		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),	      \
 			"d" (_val)					      \
 		      : "memory", "cc", "r10", "r11", "cx");		      \
-  } while (0)
+    __status;								      \
+  })
+
+
+#define lll_futex_timed_wait(futex, val, timeout)			      \
+  ({									      \
+    register const struct timespec *__to __asm__ ("r10") = timeout;	      \
+    int __status;							      \
+    register __typeof (val) _val asm ("edx") = (val);			      \
+    __asm __volatile ("syscall"						      \
+		      : "=a" (__status)					      \
+		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),	      \
+		        "d" (_val), "r" (__to)				      \
+		      : "memory", "cc", "r11", "cx");			      \
+    __status;								      \
+  })
 
 
 #define lll_futex_wake(futex, nr) \
@@ -96,6 +212,16 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
      ret; })
 
 
+#define lll_robust_mutex_trylock(futex, id)				      \
+  ({ int ret;								      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (id), "m" (futex),				      \
+			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \
+		       : "memory");					      \
+     ret; })
+
+
 #define lll_mutex_cond_trylock(futex) \
   ({ int ret;								      \
      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
@@ -110,51 +236,109 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
   (void) ({ int ignore1, ignore2, ignore3;				      \
 	    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \
 			      "jnz 1f\n\t"				      \
-			      ".subsection 1\n"				      \
-			      "1:\tleaq %2, %%rdi\n\t"			      \
-			      "subq $128, %%rsp\n\t"			      \
-			      "callq __lll_mutex_lock_wait\n\t"		      \
-			      "addq $128, %%rsp\n\t"			      \
-			      "jmp 2f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_mutex_lock_%=, @function\n"	      \
+			      "_L_mutex_lock_%=:\n"			      \
+			      "1:\tleaq %2, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_lock_wait\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_mutex_lock_%=, 6b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "2:"					      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
 			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\
 				"=a" (ignore3)				      \
 			      : "0" (1), "m" (futex), "3" (0)		      \
 			      : "cx", "r11", "cc", "memory"); })
 
 
+#define lll_robust_mutex_lock(futex, id) \
+  ({ int result, ignore1, ignore2;					      \
+    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"			      \
+		      "jnz 1f\n\t"					      \
+		      ".subsection 1\n\t"				      \
+		      ".type  _L_robust_mutex_lock_%=, @function\n"	      \
+		      "_L_robust_mutex_lock_%=:\n"			      \
+		      "1:\tleaq %2, %%rdi\n"				      \
+		      "2:\tsubq $128, %%rsp\n"				      \
+		      "3:\tcallq __lll_robust_mutex_lock_wait\n"	      \
+		      "4:\taddq $128, %%rsp\n"				      \
+		      "5:\tjmp 24f\n"					      \
+		      "6:\t.size _L_robust_mutex_lock_%=, 6b-1b\n\t"	      \
+		      ".previous\n"					      \
+		      LLL_STUB_UNWIND_INFO_5				      \
+		      "24:"						      \
+		      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),	      \
+			"=a" (result)					      \
+		      : "0" (id), "m" (futex), "3" (0)			      \
+		      : "cx", "r11", "cc", "memory");			      \
+    result; })
+
+
 #define lll_mutex_cond_lock(futex) \
   (void) ({ int ignore1, ignore2, ignore3;				      \
 	    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \
 			      "jnz 1f\n\t"				      \
-			      ".subsection 1\n"				      \
-			      "1:\tleaq %2, %%rdi\n\t"			      \
-			      "subq $128, %%rsp\n\t"			      \
-			      "callq __lll_mutex_lock_wait\n\t"		      \
-			      "addq $128, %%rsp\n\t"			      \
-			      "jmp 2f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_mutex_cond_lock_%=, @function\n"     \
+			      "_L_mutex_cond_lock_%=:\n"		      \
+			      "1:\tleaq %2, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_lock_wait\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_mutex_cond_lock_%=, 6b-1b\n\t"    \
 			      ".previous\n"				      \
-			      "2:"					      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
 			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\
 				"=a" (ignore3)				      \
 			      : "0" (2), "m" (futex), "3" (0)		      \
 			      : "cx", "r11", "cc", "memory"); })
 
 
+#define lll_robust_mutex_cond_lock(futex, id) \
+  ({ int result, ignore1, ignore2;					      \
+    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"			      \
+		      "jnz 1f\n\t"					      \
+		      ".subsection 1\n\t"				      \
+		      ".type  _L_robust_mutex_cond_lock_%=, @function\n"      \
+		      "_L_robust_mutex_cond_lock_%=:\n"			      \
+		      "1:\tleaq %2, %%rdi\n"				      \
+		      "2:\tsubq $128, %%rsp\n"				      \
+		      "3:\tcallq __lll_robust_mutex_lock_wait\n"	      \
+		      "4:\taddq $128, %%rsp\n"				      \
+		      "5:\tjmp 24f\n"					      \
+		      "6:\t.size _L_robust_mutex_cond_lock_%=, 6b-1b\n\t"     \
+		      ".previous\n"					      \
+		      LLL_STUB_UNWIND_INFO_5				      \
+		      "24:"						      \
+		      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),	      \
+			"=a" (result)					      \
+		      : "0" (id | FUTEX_WAITERS), "m" (futex), "3" (0)	      \
+		      : "cx", "r11", "cc", "memory");			      \
+    result; })
+
+
 #define lll_mutex_timedlock(futex, timeout) \
   ({ int result, ignore1, ignore2, ignore3;				      \
      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t"			      \
 		       "jnz 1f\n\t"					      \
-		       ".subsection 1\n"				      \
-		       "1:\tleaq %4, %%rdi\n\t"				      \
-		       "movq %8, %%rdx\n\t"				      \
-		       "subq $128, %%rsp\n\t"				      \
-		       "callq __lll_mutex_timedlock_wait\n\t"		      \
-		       "addq $128, %%rsp\n\t"				      \
-		       "jmp 2f\n\t"					      \
+		       ".subsection 1\n\t"				      \
+		       ".type  _L_mutex_timedlock_%=, @function\n"	      \
+		       "_L_mutex_timedlock_%=:\n"			      \
+		       "1:\tleaq %4, %%rdi\n"				      \
+		       "0:\tmovq %8, %%rdx\n"				      \
+		       "2:\tsubq $128, %%rsp\n"				      \
+		       "3:\tcallq __lll_mutex_timedlock_wait\n"		      \
+		       "4:\taddq $128, %%rsp\n"				      \
+		       "5:\tjmp 24f\n"					      \
+		       "6:\t.size _L_mutex_timedlock_%=, 6b-1b\n\t"	      \
 		       ".previous\n"					      \
-		       "2:"						      \
+		       LLL_STUB_UNWIND_INFO_6				      \
+		       "24:"						      \
 		       : "=a" (result), "=&D" (ignore1), "=S" (ignore2),      \
 			 "=&d" (ignore3), "=m" (futex)			      \
 		       : "0" (0), "2" (1), "m" (futex), "m" (timeout)	      \
@@ -162,23 +346,83 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
      result; })
 
 
+#define lll_robust_mutex_timedlock(futex, timeout, id) \
+  ({ int result, ignore1, ignore2, ignore3;				      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t"			      \
+		       "jnz 1f\n\t"					      \
+		       ".subsection 1\n\t"				      \
+		       ".type  _L_robust_mutex_timedlock_%=, @function\n"     \
+		       "_L_robust_mutex_timedlock_%=:\n"		      \
+		       "1:\tleaq %4, %%rdi\n"				      \
+		       "0:\tmovq %8, %%rdx\n"				      \
+		       "2:\tsubq $128, %%rsp\n"				      \
+		       "3:\tcallq __lll_robust_mutex_timedlock_wait\n"	      \
+		       "4:\taddq $128, %%rsp\n"				      \
+		       "5:\tjmp 24f\n"					      \
+		       "6:\t.size _L_robust_mutex_timedlock_%=, 6b-1b\n\t"    \
+		       ".previous\n"					      \
+		       LLL_STUB_UNWIND_INFO_6				      \
+		       "24:"						      \
+		       : "=a" (result), "=&D" (ignore1), "=S" (ignore2),      \
+			 "=&d" (ignore3), "=m" (futex)			      \
+		       : "0" (0), "2" (id), "m" (futex), "m" (timeout)	      \
+		       : "memory", "cx", "cc", "r10", "r11");		      \
+     result; })
+
+
 #define lll_mutex_unlock(futex) \
   (void) ({ int ignore;							      \
             __asm __volatile (LOCK_INSTR "decl %0\n\t"			      \
 			      "jne 1f\n\t"				      \
-			      ".subsection 1\n"				      \
-			      "1:\tleaq %0, %%rdi\n\t"			      \
-			      "subq $128, %%rsp\n\t"			      \
-			      "callq __lll_mutex_unlock_wake\n\t"	      \
-			      "addq $128, %%rsp\n\t"			      \
-			      "jmp 2f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_mutex_unlock_%=, @function\n"	      \
+			      "_L_mutex_unlock_%=:\n"			      \
+			      "1:\tleaq %0, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_unlock_wake\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_mutex_unlock_%=, 6b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "2:"					      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
 			      : "=m" (futex), "=&D" (ignore)		      \
 			      : "m" (futex)				      \
 			      : "ax", "cx", "r11", "cc", "memory"); })
 
 
+#define lll_robust_mutex_unlock(futex) \
+  (void) ({ int ignore;							      \
+	    __asm __volatile (LOCK_INSTR "andl %2, %0\n\t"		      \
+			      "jne 1f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_robust_mutex_unlock_%=, @function\n" \
+			      "_L_robust_mutex_unlock_%=:\n"		      \
+			      "1:\tleaq %0, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_unlock_wake\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_robust_mutex_unlock_%=, 6b-1b\n\t"\
+			      ".previous\n"				      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
+			      : "=m" (futex), "=&D" (ignore)		      \
+			      : "i" (FUTEX_WAITERS), "m" (futex)	      \
+			      : "ax", "cx", "r11", "cc", "memory"); })
+
+
+#define lll_robust_mutex_dead(futex) \
+  (void) ({ int ignore;		     \
+	    __asm __volatile (LOCK_INSTR "orl %3, (%2)\n\t"		      \
+			      "syscall"					      \
+			      : "=m" (futex), "=a" (ignore)		      \
+			      : "D" (&(futex)), "i" (FUTEX_OWNER_DIED),	      \
+				"S" (FUTEX_WAKE), "1" (__NR_futex),	      \
+				"d" (1)					      \
+			      : "cx", "r11", "cc", "memory"); })
+
+
 #define lll_mutex_islocked(futex) \
   (futex != LLL_MUTEX_LOCK_INITIALIZER)
 
@@ -237,17 +481,21 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 			      "je 0f\n\t"				      \
 			      "lock; cmpxchgl %0, %2\n\t"		      \
 			      "jnz 1f\n\t"				      \
-		  	      "jmp 2f\n"				      \
+		  	      "jmp 24f\n"				      \
 			      "0:\tcmpxchgl %0, %2\n\t"			      \
 			      "jnz 1f\n\t"				      \
-			      ".subsection 1\n"				      \
-			      "1:\tleaq %2, %%rdi\n\t"			      \
-			      "subq $128, %%rsp\n\t"			      \
-			      "callq __lll_mutex_lock_wait\n\t"		      \
-			      "addq $128, %%rsp\n\t"			      \
-			      "jmp 2f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_lock_%=, @function\n"		      \
+			      "_L_lock_%=:\n"				      \
+			      "1:\tleaq %2, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_lock_wait\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_lock_%=, 6b-1b\n\t"		      \
 			      ".previous\n"				      \
-			      "2:"					      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
 			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\
 				"=a" (ignore3)				      \
 			      : "0" (1), "m" (futex), "3" (0)		      \
@@ -260,17 +508,21 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 			      "je 0f\n\t"				      \
 			      "lock; decl %0\n\t"			      \
 			      "jne 1f\n\t"				      \
-		  	      "jmp 2f\n"				      \
+		  	      "jmp 24f\n"				      \
 			      "0:\tdecl %0\n\t"				      \
 			      "jne 1f\n\t"				      \
-			      ".subsection 1\n"				      \
-			      "1:\tleaq %0, %%rdi\n\t"			      \
-			      "subq $128, %%rsp\n\t"			      \
-			      "callq __lll_mutex_unlock_wake\n\t"	      \
-			      "addq $128, %%rsp\n\t"			      \
-			      "jmp 2f\n\t"				      \
+			      ".subsection 1\n\t"			      \
+			      ".type  _L_unlock_%=, @function\n"	      \
+			      "_L_unlock_%=:\n"				      \
+			      "1:\tleaq %0, %%rdi\n"			      \
+			      "2:\tsubq $128, %%rsp\n"			      \
+			      "3:\tcallq __lll_mutex_unlock_wake\n"	      \
+			      "4:\taddq $128, %%rsp\n"			      \
+			      "5:\tjmp 24f\n"				      \
+			      "6:\t.size _L_unlock_%=, 6b-1b\n\t"	      \
 			      ".previous\n"				      \
-			      "2:"					      \
+			      LLL_STUB_UNWIND_INFO_5			      \
+			      "24:"					      \
 			      : "=m" (futex), "=&D" (ignore)		      \
 			      : "m" (futex)				      \
 			      : "ax", "cx", "r11", "cc", "memory"); })
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
new file mode 100644
index 0000000000..69243950d7
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
@@ -0,0 +1,229 @@
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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 <sysdep.h>
+#include <pthread-errnos.h>
+#include <lowlevelrobustlock.h>
+
+	.text
+
+#ifndef LOCK
+# ifdef UP
+#  define LOCK
+# else
+#  define LOCK lock
+# endif
+#endif
+
+#define SYS_futex		202
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+#define FUTEX_WAITERS		0x80000000
+#define FUTEX_OWNER_DIED	0x40000000
+
+/* For the calculation see asm/vsyscall.h.  */
+#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000
+
+
+	.globl	__lll_robust_mutex_lock_wait
+	.type	__lll_robust_mutex_lock_wait,@function
+	.hidden	__lll_robust_mutex_lock_wait
+	.align	16
+__lll_robust_mutex_lock_wait:
+	cfi_startproc
+	pushq	%r10
+	cfi_adjust_cfa_offset(8)
+	pushq	%rdx
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%r10, -16)
+	cfi_offset(%rdx, -24)
+
+	xorq	%r10, %r10	/* No timeout.  */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
+
+4:	movl	%eax, %edx
+	orl	$FUTEX_WAITERS, %edx
+
+	testl	$FUTEX_OWNER_DIED, %eax
+	jnz	3f
+
+	cmpl	%edx, %eax
+	je	1f
+
+	LOCK
+	cmpxchgl %edx, (%rdi)
+	jnz	2f
+
+1:	movl	$SYS_futex, %eax
+	syscall
+
+	movl	(%rdi), %eax
+
+2:	testl	%eax, %eax
+	jne	4b
+
+	movl	%fs:TID, %edx
+	orl	$FUTEX_WAITERS, %edx
+	LOCK
+	cmpxchgl %edx, (%rdi)
+	jnz	4b
+	/* NB:	 %rax == 0 */
+
+3:	popq	%rdx
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%rdx)
+	popq	%r10
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r10)
+	retq
+	cfi_endproc
+	.size	__lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
+
+
+	.globl	__lll_robust_mutex_timedlock_wait
+	.type	__lll_robust_mutex_timedlock_wait,@function
+	.hidden	__lll_robust_mutex_timedlock_wait
+	.align	16
+__lll_robust_mutex_timedlock_wait:
+	cfi_startproc
+	/* Check for a valid timeout value.  */
+	cmpq	$1000000000, 8(%rdx)
+	jae	3f
+
+	pushq	%r8
+	cfi_adjust_cfa_offset(8)
+	pushq	%r9
+	cfi_adjust_cfa_offset(8)
+	pushq	%r12
+	cfi_adjust_cfa_offset(8)
+	pushq	%r13
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%r8, -16)
+	cfi_offset(%r9, -24)
+	cfi_offset(%r12, -32)
+	cfi_offset(%r13, -40)
+
+	/* Stack frame for the timespec and timeval structs.  */
+	subq	$24, %rsp
+	cfi_adjust_cfa_offset(24)
+
+	movq	%rdi, %r12
+	movq	%rdx, %r13
+
+1:	movq	%rax, 16(%rsp)
+
+	/* Get current time.  */
+	movq	%rsp, %rdi
+	xorl	%esi, %esi
+	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
+	/* This is a regular function call, all caller-save registers
+	   might be clobbered.  */
+	callq	*%rax
+
+	/* Compute relative timeout.  */
+	movq	8(%rsp), %rax
+	movl	$1000, %edi
+	mul	%rdi		/* Milli seconds to nano seconds.  */
+	movq	(%r13), %rdi
+	movq	8(%r13), %rsi
+	subq	(%rsp), %rdi
+	subq	%rax, %rsi
+	jns	4f
+	addq	$1000000000, %rsi
+	decq	%rdi
+4:	testq	%rdi, %rdi
+	js	8f		/* Time is already up.  */
+
+	/* Futex call.  */
+	movq	%rdi, (%rsp)	/* Store relative timeout.  */
+	movq	%rsi, 8(%rsp)
+
+	movq	16(%rsp), %rdx
+	movl	%edx, %eax
+	orl	$FUTEX_WAITERS, %edx
+
+	testl	$FUTEX_OWNER_DIED, %eax
+	jnz	6f
+
+	cmpl	%eax, %edx
+	je	2f
+
+	LOCK
+	cmpxchgl %edx, (%r12)
+	movq	$0, %rcx	/* Must use mov to avoid changing cc.  */
+	jnz	5f
+
+2:	movq	%rsp, %r10
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
+	movq	%r12, %rdi
+	movl	$SYS_futex, %eax
+	syscall
+	movq	%rax, %rcx
+
+	movl	(%r12), %eax
+
+5:	testl	%eax, %eax
+	jne	7f
+
+	movl	%fs:TID, %edx
+	orl	$FUTEX_WAITERS, %edx
+	LOCK
+	cmpxchgl %edx, (%r12)
+	jnz	7f
+
+6:	addq	$24, %rsp
+	cfi_adjust_cfa_offset(-24)
+	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r13)
+	popq	%r12
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r12)
+	popq	%r9
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r9)
+	popq	%r8
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r8)
+	retq
+
+3:	movl	$EINVAL, %eax
+	retq
+
+	cfi_adjust_cfa_offset(56)
+	cfi_offset(%r8, -16)
+	cfi_offset(%r9, -24)
+	cfi_offset(%r12, -32)
+	cfi_offset(%r13, -40)
+	/* Check whether the time expired.  */
+7:	cmpq	$-ETIMEDOUT, %rcx
+	jne	1b
+
+8:	movl	$ETIMEDOUT, %eax
+	jmp	6b
+	cfi_endproc
+	.size	__lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
index e1593f32ff..fa8125dd87 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -63,9 +63,14 @@ pthread_barrier_wait:
 
 	/* Wait for the remaining threads.  The call will return immediately
 	   if the CURR_EVENT memory has meanwhile been changed.  */
-7:	xorq	%rsi, %rsi		/* movq $FUTEX_WAIT, %rsi */
+7:
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	xorq	%r10, %r10
-8:	movq	$SYS_futex, %rax
+8:	movl	$SYS_futex, %eax
 	syscall
 
 	/* Don't return on spurious wakeups.  The syscall does not change
@@ -110,8 +115,8 @@ pthread_barrier_wait:
 	/* Wake up all waiters.  The count is a signed number in the kernel
 	   so 0x7fffffff is the highest value.  */
 	movl	$0x7fffffff, %edx
-	movq	$FUTEX_WAKE, %rsi
-	movq	$SYS_futex, %rax
+	movl	$FUTEX_WAKE, %esi
+	movl	$SYS_futex, %eax
 	syscall
 
 	/* Increment LEFT.  If this brings the count back to the
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
index e8d7bd9bb6..006de2696e 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -21,6 +21,7 @@
 #include <shlib-compat.h>
 #include <lowlevelcond.h>
 #include <kernel-features.h>
+#include <pthread-pi-defines.h>
 
 #ifdef UP
 # define LOCK
@@ -80,11 +81,15 @@ __pthread_cond_broadcast:
 8:	cmpq	$-1, %r8
 	je	9f
 
+	/* XXX: The kernel so far doesn't support requeue to PI futex.  */
+	testl	$PI_BIT, MUTEX_KIND(%r8)
+	jne	9f
+
 	/* Wake up all threads.  */
-	movq	$FUTEX_CMP_REQUEUE, %rsi
-	movq	$SYS_futex, %rax
+	movl	$FUTEX_CMP_REQUEUE, %esi
+	movl	$SYS_futex, %eax
 	movl	$1, %edx
-	movq	$0x7fffffff, %r10
+	movl	$0x7fffffff, %r10d
 	syscall
 
 	/* For any kind of error, which mainly is EAGAIN, we try again
@@ -128,9 +133,9 @@ __pthread_cond_broadcast:
 	jmp	8b
 
 9:	/* The futex requeue functionality is not available.  */
-	movq	$0x7fffffff, %rdx
-	movq	$FUTEX_WAKE, %rsi
-	movq	$SYS_futex, %rax
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %esi
+	movl	$SYS_futex, %eax
 	syscall
 	jmp	10b
 	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
index 62bb74cc1a..3dbb9e81e3 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -31,7 +31,9 @@
 #define SYS_futex		202
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
-#define FUTEX_REQUEUE		3
+#define FUTEX_WAKE_OP		5
+
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
 
 #define EINVAL			22
 
@@ -66,9 +68,30 @@ __pthread_cond_signal:
 	addl	$1, (%rdi)
 
 	/* Wake up one thread.  */
-	movq	$FUTEX_WAKE, %rsi
-	movq	$SYS_futex, %rax
-	movq	$1, %rdx
+	movl	$FUTEX_WAKE_OP, %esi
+	movl	$SYS_futex, %eax
+	movl	$1, %edx
+	movl	$1, %r10d
+#if cond_lock != 0
+	addq	$cond_lock, %r8
+#endif
+	movl	$FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
+	syscall
+#if cond_lock != 0
+	subq	$cond_lock, %r8
+#endif
+	/* For any kind of error, we try again with WAKE.
+	   The general test also covers running on old kernels.  */
+	cmpq	$-4095, %rax
+	jae	7f
+
+	xorl	%eax, %eax
+	retq
+
+7:	movl	$FUTEX_WAKE, %esi
+	movl	$SYS_futex, %eax
+	/* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
+	movl	$1, %edx  */
 	syscall
 
 	/* Unlock.  */
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
index 67bec6caa7..ad3ae1e76e 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -56,7 +56,7 @@ __pthread_cond_timedwait:
 .Lsubq:
 
 	cmpq	$1000000000, 8(%rdx)
-	movq	$EINVAL, %rax
+	movl	$EINVAL, %eax
 	jae	18f
 
 	/* Stack frame:
@@ -102,7 +102,7 @@ __pthread_cond_timedwait:
 
 	/* Unlock the mutex.  */
 2:	movq	16(%rsp), %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	callq	__pthread_mutex_unlock_usercnt
 
 	testl	%eax, %eax
@@ -141,7 +141,7 @@ __pthread_cond_timedwait:
 	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the
 	   kernel.  */
 	leaq	24(%rsp), %rsi
-	movq	$__NR_clock_gettime, %rax
+	movl	$__NR_clock_gettime, %eax
 	syscall
 # ifndef __ASSUME_POSIX_TIMERS
 	cmpq	$-ENOSYS, %rax
@@ -155,13 +155,13 @@ __pthread_cond_timedwait:
 	subq	32(%rsp), %rdx
 #else
 	leaq	24(%rsp), %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	32(%rsp), %rax
-	movq	$1000, %rdx
+	movl	$1000, %edx
 	mul	%rdx		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rcx
 	movq	8(%r13), %rdx
@@ -195,10 +195,14 @@ __pthread_cond_timedwait:
 	movl	%eax, (%rsp)
 
 	leaq	24(%rsp), %r10
-	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	movq	%r12, %rdx
 	addq	$cond_futex, %rdi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 	movq	%rax, %r14
 
@@ -237,7 +241,7 @@ __pthread_cond_timedwait:
 
 13:	incq	wakeup_seq(%rdi)
 	incl	cond_futex(%rdi)
-	movq	$ETIMEDOUT, %r14
+	movl	$ETIMEDOUT, %r14d
 	jmp	14f
 
 23:	xorq	%r14, %r14
@@ -256,8 +260,8 @@ __pthread_cond_timedwait:
 	jne	25f
 
 	addq	$cond_nwaiters, %rdi
-	movq	$SYS_futex, %rax
-	movq	$FUTEX_WAKE, %rsi
+	movl	$SYS_futex, %eax
+	movl	$FUTEX_WAKE, %esi
 	movl	$1, %edx
 	syscall
 	subq	$cond_nwaiters, %rdi
@@ -349,13 +353,13 @@ __pthread_cond_timedwait:
 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
 	/* clock_gettime not available.  */
 19:	leaq	24(%rsp), %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	32(%rsp), %rax
-	movq	$1000, %rdx
+	movl	$1000, %edx
 	mul	%rdx		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rcx
 	movq	8(%r13), %rdx
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
index f5de0a280c..969e80da2a 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -67,9 +67,15 @@ __condvar_cleanup:
 	cmpl	4(%r8), %edx
 	jne	3f
 
+	/* We increment the wakeup_seq counter only if it is lower than
+	   total_seq.  If this is not the case the thread was woken and
+	   then canceled.  In this case we ignore the signal.  */
+	movq	total_seq(%rdi), %rax
+	cmpq	wakeup_seq(%rdi), %rax
+	jbe	6f
 	incq	wakeup_seq(%rdi)
-	incq	woken_seq(%rdi)
 	incl	cond_futex(%rdi)
+6:	incq	woken_seq(%rdi)
 
 3:	subl	$(1 << clock_bits), cond_nwaiters(%rdi)
 
@@ -82,12 +88,12 @@ __condvar_cleanup:
 	jne	4f
 
 	addq	$cond_nwaiters, %rdi
-	movq	$SYS_futex, %rax
-	movq	$FUTEX_WAKE, %rsi
+	movl	$SYS_futex, %eax
+	movl	$FUTEX_WAKE, %esi
 	movl	$1, %edx
 	syscall
 	subq	$cond_nwaiters, %rdi
-	movq	$1, %r12
+	movl	$1, %r12d
 
 4:	LOCK
 #if cond_lock == 0
@@ -105,9 +111,9 @@ __condvar_cleanup:
 2:	testq	%r12, %r12
 	jnz	5f
 	addq	$cond_futex, %rdi
-	movq	$FUTEX_WAKE, %rsi
+	movl	$FUTEX_WAKE, %esi
 	movl	$0x7fffffff, %edx
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 
 5:	movq	16(%r8), %rdi
@@ -170,7 +176,7 @@ __pthread_cond_wait:
 
 	/* Unlock the mutex.  */
 2:	movq	16(%rsp), %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	callq	__pthread_mutex_unlock_usercnt
 
 	testl	%eax, %eax
@@ -215,8 +221,12 @@ __pthread_cond_wait:
 	xorq	%r10, %r10
 	movq	%r12, %rdx
 	addq	$cond_futex-cond_lock, %rdi
-	movq	$SYS_futex, %rax
-	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
+	movl	$SYS_futex, %eax
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	syscall
 
 	movl	(%rsp), %edi
@@ -262,8 +272,8 @@ __pthread_cond_wait:
 	jne	17f
 
 	addq	$cond_nwaiters, %rdi
-	movq	$SYS_futex, %rax
-	movq	$FUTEX_WAKE, %rsi
+	movl	$SYS_futex, %eax
+	movl	$FUTEX_WAKE, %esi
 	movl	$1, %edx
 	syscall
 	subq	$cond_nwaiters, %rdi
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
index 3fec0f4205..9db5516913 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -74,17 +74,23 @@ __pthread_once:
 	jnz	3f	/* Different for generation -> run initializer.  */
 
 	/* Somebody else got here first.  Wait.  */
-	movq	%r10, %rsi		/* movq $FUTEX_WAIT, %rsi */
-	movq	$SYS_futex, %rax
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
+	movl	$SYS_futex, %eax
 	syscall
 	jmp	6b
 
 	/* Preserve the pointer to the control variable.  */
 3:	pushq	%rdi
 .Lpush_rdi:
+	pushq	%rdi
+.Lpush_rdi2:
 
 .LcleanupSTART:
-	callq	*8(%rsp)
+	callq	*16(%rsp)
 .LcleanupEND:
 
 	/* Get the control variable address back.  */
@@ -95,15 +101,18 @@ __pthread_once:
 	LOCK
 	incl	(%rdi)
 
+	addq	$8, %rsp
+.Ladd1:
+
 	/* Wake up all other threads.  */
 	movl	$0x7fffffff, %edx
 	movl	$FUTEX_WAKE, %esi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 
 4:	addq	$8, %rsp
-.Ladd:
-	xorq	%rax, %rax
+.Ladd2:
+	xorl	%eax, %eax
 	retq
 
 	.size	__pthread_once,.-__pthread_once
@@ -124,8 +133,8 @@ clear_once_control:
 	movl	$0, (%rdi)
 
 	movl	$0x7fffffff, %edx
-	movq	$FUTEX_WAKE, %rsi
-	movq	$SYS_futex, %rax
+	movl	$FUTEX_WAKE, %esi
+	movl	$SYS_futex, %eax
 	syscall
 
 	movq	%r8, %rdi
@@ -220,20 +229,28 @@ clear_once_control:
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 24
 	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpop_rdi-.Lpush_rdi
+	.long	.Lpush_rdi2-.Lpush_rdi
+	.byte	14				# DW_CFA_def_cfa_offset
+	.uleb128 32
+	.byte	4				# DW_CFA_advance_loc4
+	.long	.Lpop_rdi-.Lpush_rdi2
+	.byte	14				# DW_CFA_def_cfa_offset
+	.uleb128 24
+	.byte	4				# DW_CFA_advance_loc4
+	.long	.Ladd1-.Lpop_rdi
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 16
 	.byte	4				# DW_CFA_advance_loc4
-	.long	.Ladd-.Lpop_rdi
+	.long	.Ladd2-.Ladd1
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 8
 	.byte	4				# DW_CFA_advance_loc4
-	.long	clear_once_control-.Ladd
+	.long	clear_once_control-.Ladd2
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 24
+	.uleb128 32
 #if 0
 	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpop_rdi2-clear_once_control
+	.long	.Lpop_rdi3-clear_once_control
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 16
 #endif
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
index 43c8cae34c..5e9d8fb1d6 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -74,8 +74,12 @@ __pthread_rwlock_rdlock:
 	jne	10f
 
 11:	addq	$READERS_WAKEUP, %rdi
-	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
-	movq	$SYS_futex, %rax
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
+	movl	$SYS_futex, %eax
 	syscall
 
 	subq	$READERS_WAKEUP, %rdi
@@ -94,7 +98,7 @@ __pthread_rwlock_rdlock:
 13:	decl	READERS_QUEUED(%rdi)
 	jmp	2b
 
-5:	xorq	%rdx, %rdx
+5:	xorl	%edx, %edx
 	incl	NR_READERS(%rdi)
 	je	8f
 9:	LOCK
@@ -122,7 +126,7 @@ __pthread_rwlock_rdlock:
 14:	cmpl	%fs:TID, %eax
 	jne	3b
 	/* Deadlock detected.  */
-	movq	$EDEADLK, %rdx
+	movl	$EDEADLK, %edx
 	jmp	9b
 
 6:
@@ -137,12 +141,12 @@ __pthread_rwlock_rdlock:
 
 	/* Overflow.  */
 8:	decl	NR_READERS(%rdi)
-	movq	$EAGAIN, %rdx
+	movl	$EAGAIN, %edx
 	jmp	9b
 
 	/* Overflow.  */
 4:	decl	READERS_QUEUED(%rdi)
-	movq	$EAGAIN, %rdx
+	movl	$EAGAIN, %edx
 	jmp	9b
 
 10:
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
index aadc90c974..b44660418a 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -90,13 +90,13 @@ pthread_rwlock_timedrdlock:
 
 	/* Get current time.  */
 11:	movq	%rsp, %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	8(%rsp), %rax
-	movq	$1000, %rdi
+	movl	$1000, %edi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rcx
 	movq	8(%r13), %rdi
@@ -112,11 +112,15 @@ pthread_rwlock_timedrdlock:
 	movq	%rcx, (%rsp)	/* Store relative timeout.  */
 	movq	%rdi, 8(%rsp)
 
-	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	movq	%rsp, %r10
 	movl	%r14d, %edx
 	leaq	READERS_WAKEUP(%r12), %rdi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 	movq	%rax, %rdx
 17:
@@ -136,11 +140,11 @@ pthread_rwlock_timedrdlock:
 	cmpq	$-ETIMEDOUT, %rdx
 	jne	2b
 
-18:	movq	$ETIMEDOUT, %rdx
+18:	movl	$ETIMEDOUT, %edx
 	jmp	9f
 
 
-5:	xorq	%rdx, %rdx
+5:	xorl	%edx, %edx
 	incl	NR_READERS(%r12)
 	je	8f
 9:	LOCK
@@ -168,7 +172,7 @@ pthread_rwlock_timedrdlock:
 
 14:	cmpl	%fs:TID, %eax
 	jne	3b
-	movq	$EDEADLK, %rdx
+	movl	$EDEADLK, %edx
 	jmp	9b
 
 6:
@@ -182,12 +186,12 @@ pthread_rwlock_timedrdlock:
 
 	/* Overflow.  */
 8:	decl	NR_READERS(%r12)
-	movq	$EAGAIN, %rdx
+	movl	$EAGAIN, %edx
 	jmp	9b
 
 	/* Overflow.  */
 4:	decl	READERS_QUEUED(%r12)
-	movq	$EAGAIN, %rdx
+	movl	$EAGAIN, %edx
 	jmp	9b
 
 10:
@@ -211,6 +215,6 @@ pthread_rwlock_timedrdlock:
 16:	movq	$-ETIMEDOUT, %rdx
 	jmp	17b
 
-19:	movq	$EINVAL, %rdx
+19:	movl	$EINVAL, %edx
 	jmp	9b
 	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
index ccaef47070..525e5b6b93 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -86,13 +86,13 @@ pthread_rwlock_timedwrlock:
 
 	/* Get current time.  */
 11:	movq	%rsp, %rdi
-	xorq	%rsi, %rsi
+	xorl	%esi, %esi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	8(%rsp), %rax
-	movq	$1000, %rdi
+	movl	$1000, %edi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rcx
 	movq	8(%r13), %rdi
@@ -108,11 +108,15 @@ pthread_rwlock_timedwrlock:
 	movq	%rcx, (%rsp)	/* Store relative timeout.  */
 	movq	%rdi, 8(%rsp)
 
-	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
 	movq	%rsp, %r10
 	movl	%r14d, %edx
 	leaq	WRITERS_WAKEUP(%r12), %rdi
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	syscall
 	movq	%rax, %rdx
 17:
@@ -132,11 +136,11 @@ pthread_rwlock_timedwrlock:
 	cmpq	$-ETIMEDOUT, %rdx
 	jne	2b
 
-18:	movq	$ETIMEDOUT, %rdx
+18:	movl	$ETIMEDOUT, %edx
 	jmp	9f
 
 
-5:	xorq	%rdx, %rdx
+5:	xorl	%edx, %edx
 	movl	%fs:TID, %eax
 	movl	%eax, WRITER(%r12)
 9:	LOCK
@@ -164,7 +168,7 @@ pthread_rwlock_timedwrlock:
 
 14:	cmpl	%fs:TID, %eax
 	jne	3b
-20:	movq	$EDEADLK, %rdx
+20:	movl	$EDEADLK, %edx
 	jmp	9b
 
 6:
@@ -178,7 +182,7 @@ pthread_rwlock_timedwrlock:
 
 	/* Overflow.  */
 4:	decl	WRITERS_QUEUED(%r12)
-	movq	$EAGAIN, %rdx
+	movl	$EAGAIN, %edx
 	jmp	9b
 
 10:
@@ -202,6 +206,6 @@ pthread_rwlock_timedwrlock:
 16:	movq	$-ETIMEDOUT, %rdx
 	jmp	17b
 
-19:	movq	$EINVAL, %rdx
+19:	movl	$EINVAL, %edx
 	jmp	9b
 	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
index ac69fc0eae..3a6b9f0bad 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -56,7 +56,7 @@ __pthread_rwlock_unlock:
 
 5:	movl	$0, WRITER(%rdi)
 
-	movq	$1, %rsi
+	movl	$1, %esi
 	leaq	WRITERS_WAKEUP(%rdi), %r10
 	movq	%rsi, %rdx
 	cmpl	$0, WRITERS_QUEUED(%rdi)
@@ -78,11 +78,11 @@ __pthread_rwlock_unlock:
 #endif
 	jne	7f
 
-8:	movq	$SYS_futex, %rax
+8:	movl	$SYS_futex, %eax
 	movq	%r10, %rdi
 	syscall
 
-	xorq	%rax, %rax
+	xorl	%eax, %eax
 	retq
 
 	.align	16
@@ -94,7 +94,7 @@ __pthread_rwlock_unlock:
 #endif
 	jne	3f
 
-4:	xorq	%rax, %rax
+4:	xorl	%eax, %eax
 	retq
 
 1:
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
index 1fcb07eaef..0e82f890aa 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -72,8 +72,12 @@ __pthread_rwlock_wrlock:
 	jne	10f
 
 11:	addq	$WRITERS_WAKEUP, %rdi
-	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
-	movq	$SYS_futex, %rax
+#if FUTEX_WAIT == 0
+	xorl	%esi, %esi
+#else
+	movl	$FUTEX_WAIT, %esi
+#endif
+	movl	$SYS_futex, %eax
 	syscall
 
 	subq	$WRITERS_WAKEUP, %rdi
@@ -92,7 +96,7 @@ __pthread_rwlock_wrlock:
 13:	decl	WRITERS_QUEUED(%rdi)
 	jmp	2b
 
-5:	xorq	%rdx, %rdx
+5:	xorl	%edx, %edx
 	movl	%fs:TID, %eax
 	movl	%eax, WRITER(%rdi)
 9:	LOCK
@@ -119,7 +123,7 @@ __pthread_rwlock_wrlock:
 
 14:	cmpl	%fs:TID, %eax
 	jne	3b
-	movq	$EDEADLK, %rdx
+	movl	$EDEADLK, %edx
 	jmp	9b
 
 6:
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
index 21ec6fd226..7f608a5974 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -41,8 +41,8 @@ sem_post:
 	LOCK
 	xaddl	%edx, (%rdi)
 
-	movq	$SYS_futex, %rax
-	movq	$FUTEX_WAKE, %rsi
+	movl	$SYS_futex, %eax
+	movl	$FUTEX_WAKE, %esi
 	incl	%edx
 	syscall
 
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
index d90e03b55b..51136cf2dc 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -79,17 +79,14 @@ sem_timedwait:
 	cfi_offset(14, -24)		/* %r14 */
 	jae	6f
 
-7:	call	__pthread_enable_asynccancel
-	movl	%eax, 16(%rsp)
-
-	xorq	%rsi, %rsi
+7:	xorl	%esi, %esi
 	movq	%rsp, %rdi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
 
 	/* Compute relative timeout.  */
 	movq	8(%rsp), %rax
-	movq	$1000, %rdi
+	movl	$1000, %edi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rdi
 	movq	8(%r13), %rsi
@@ -105,10 +102,13 @@ sem_timedwait:
 	movq	%rdi, (%rsp)	/* Store relative timeout.  */
 	movq	%rsi, 8(%rsp)
 
+	call	__pthread_enable_asynccancel
+	movl	%eax, 16(%rsp)
+
 	movq	%rsp, %r10
 	movq	%r12, %rdi
-	xorq	%rsi, %rsi
-	movq	$SYS_futex, %rax
+	xorl	%esi, %esi
+	movl	$SYS_futex, %eax
 	xorl	%edx, %edx
 	syscall
 	movq	%rax, %r14
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S
index 31271bb94c..6b77dfc0d8 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -56,4 +56,3 @@ sem_trywait:
 	orl	$-1, %eax
 	retq
 	.size	sem_trywait,.-sem_trywait
-	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1)
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
index 76957bc139..63ecd063ab 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -77,7 +77,7 @@ sem_wait:
 	movl	%eax, %r8d
 
 	xorq	%r10, %r10
-	movq	$SYS_futex, %rax
+	movl	$SYS_futex, %eax
 	movq	%r13, %rdi
 	movq	%r10, %rsi
 	movq	%r10, %rdx
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
index d47c1b80dc..3e741da794 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -48,7 +48,7 @@
     POPARGS_##args							      \
     /* The return value from CENABLE is argument for CDISABLE.  */	      \
     movq %rax, (%rsp);							      \
-    movq $SYS_ify (syscall_name), %rax;					      \
+    movl $SYS_ify (syscall_name), %eax;					      \
     syscall;								      \
     movq (%rsp), %rdi;							      \
     /* Save %rax since it's the error code from the syscall.  */	      \
@@ -136,3 +136,9 @@ extern int __local_multiple_threads attribute_hidden;
 # define NO_CANCELLATION 1
 
 #endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S b/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S
index f68d40439e..9a9912ca85 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S
@@ -16,9 +16,16 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <tcb-offsets.h>
+/* We want an #include_next, but we are the main source file.
+   So, #include ourselves and in that incarnation we can use #include_next.  */
+#ifndef INCLUDED_SELF
+# define INCLUDED_SELF
+# include <vfork.S>
+#else
 
-#define SAVE_PID \
+# include <tcb-offsets.h>
+
+# define SAVE_PID \
 	movl	%fs:PID, %esi;						      \
 	movl	$0x80000000, %ecx;					      \
 	movl	%esi, %edx;						      \
@@ -26,10 +33,11 @@
 	cmove	%ecx, %edx;						      \
 	movl	%edx, %fs:PID
 
-#define RESTORE_PID \
+# define RESTORE_PID \
 	testq	%rax, %rax;						      \
 	je	1f;							      \
 	movl	%esi, %fs:PID;						      \
 1:
 
-#include <sysdeps/unix/sysv/linux/x86_64/vfork.S>
+# include_next <vfork.S>
+#endif