about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/i386
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/linux/i386
parent7d58530341304d403a6626d7f7a1913165fe2f32 (diff)
downloadglibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.xz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip
2.5-18.1
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386')
-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
21 files changed, 876 insertions, 387 deletions
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