about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/i386/i486
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386/i486')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S279
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S180
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S176
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S566
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S311
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S122
6 files changed, 1634 insertions, 0 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S
new file mode 100644
index 0000000000..9e2b9fec8d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S
@@ -0,0 +1,279 @@
+/* Copyright (C) 2002 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>
+
+	.text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+#define EWOULDBLOCK		11
+#define EINVAL			22
+#define ETIMEDOUT		110
+
+#define cond_lock	 0
+#define cond_nr_wakers	 4
+#define cond_nr_sleepers 8
+
+
+	.global	__lll_cond_wait
+	.type	__lll_cond_wait,@function
+	.hidden	__lll_cond_wait
+	.align	16
+__lll_cond_wait:
+	pushl	%esi
+	pushl	%ebx
+
+	xorl	%esi, %esi
+
+	leal	cond_nr_wakers(%eax), %ebx
+
+4:	movl	(%ebx), %edx
+	testl	%edx, %edx
+	jne	1f
+
+	LOCK
+	decl	cond_lock-cond_nr_wakers(%ebx)
+	jne	2f
+
+3:	xorl	%ecx, %ecx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, cond_lock-cond_nr_wakers(%ebx)
+	testl	%eax, %eax
+	je	4b
+
+	leal	cond_lock-cond_nr_wakers(%ebx), %ecx
+	/* Preserves %ebx, %edx, %edi, %esi.  */
+	call	__lll_mutex_lock_wait
+	jmp	4b
+
+1:	decl	(%ebx)
+
+	popl	%ebx
+	popl	%esi
+	ret
+
+2:	leal	cond_lock-cond_nr_wakers(%ebx), %eax
+	/* Preserves %ebx, %ecx, %edx, %edi, %esi.  */
+	call	__lll_mutex_unlock_wake
+	jmp	3b
+	.size	__lll_cond_wait,.-__lll_cond_wait
+
+
+	.global	__lll_cond_timedwait
+	.type	__lll_cond_timedwait,@function
+	.hidden	__lll_cond_timedwait
+	.align	16
+__lll_cond_timedwait:
+	/* Check for a valid timeout value.  */
+	cmpl	$1000000000, 4(%edx)
+	jae	1f
+
+	pushl	%ebp
+	pushl	%edi
+	pushl	%esi
+	pushl	%ebx
+
+	/* Stack frame for the timespec and timeval structs.  */
+	subl	$8, %esp
+
+	leal	cond_nr_wakers(%eax), %ebp	/* cond */
+	movl	%edx, %edi			/* timeout */
+
+9:	movl	(%ebp), %esi
+	testl	%esi, %esi
+	jne	5f
+
+	LOCK
+	decl	cond_lock-cond_nr_wakers(%ebp)
+	jne	6f
+
+	/* Get current time.  */
+7:	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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	3f
+	addl	$1000000000, %edx
+	decl	%ecx
+3:	testl	%ecx, %ecx
+	js	4f		/* Time is already up.  */
+
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+	movl	%esi, %edx
+	movl	%esp, %esi
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%ebp, %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	%eax, %edx
+
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, cond_lock-cond_nr_wakers(%ebp)
+	testl	%eax, %eax
+	jne	8f
+
+	cmpl	$-ETIMEDOUT, %edx
+	jne	9b
+
+4:	movl	$ETIMEDOUT, %eax
+	jmp	2f
+
+5:	decl	(%ebp)
+	xorl	%eax, %eax
+
+2:	addl	$8, %esp
+	popl	%ebx
+	popl	%esi
+	popl	%edi
+	popl	%ebp
+	ret
+
+6:	leal	cond_lock-cond_nr_wakers(%ebp), %eax
+	/* Preserves %ebx, %ecx, %edx, %edi, %esi.  */
+	call	__lll_mutex_unlock_wake
+	jmp	7b
+
+8:	leal	cond_lock-cond_nr_wakers(%ebp), %ecx
+	/* Preserves %ebx, %edx, %edi, %esi.  */
+	call	__lll_mutex_lock_wait
+	jmp	5b
+
+1:	movl	$EINVAL, %eax
+	ret
+	.size	__lll_cond_timedwait,.-__lll_cond_timedwait
+
+
+	.global	__lll_cond_wake
+	.type	__lll_cond_wake,@function
+	.hidden	__lll_cond_wake
+	.align	16
+__lll_cond_wake:
+	pushl	%esi
+	pushl	%ebx
+
+	movl	%eax, %ebx
+
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, (%ebx)
+	testl	%eax, %eax
+	jne	1f
+
+2:	leal	cond_nr_wakers(%ebx), %ebx
+	cmpl	$0, cond_nr_sleepers-cond_nr_wakers(%ebx)
+	je	3f
+
+	incl	(%ebx)
+	jz	5f
+
+6:	movl	$FUTEX_WAKE, %ecx
+	xorl	%esi, %esi
+	movl	%ecx, %edx	/* movl $1, %edx */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+3:	LOCK
+	decl	cond_lock-cond_nr_wakers(%ebx)
+	je,pt	4f
+
+	leal	cond_lock-cond_nr_wakers(%ebx), %eax
+	call	__lll_mutex_unlock_wake
+
+4:	popl	%ebx
+	popl	%esi
+	ret
+
+1:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+5:	movl	$0x80000000, (%ebx)
+	jmp	6b
+	.size	__lll_cond_wake,.-__lll_cond_wake
+
+
+	.global	__lll_cond_broadcast
+	.type	__lll_cond_broadcast,@function
+	.hidden	__lll_cond_broadcast
+	.align	16
+__lll_cond_broadcast:
+	pushl	%esi
+	pushl	%ebx
+
+	movl	%eax, %ebx
+	movl	$0x8000000, %edx
+
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, (%ebx)
+	testl	%eax, %eax
+	jne	1f
+
+2:	leal	cond_nr_wakers(%ebx), %ebx
+	cmpl	$0, cond_nr_sleepers-cond_nr_wakers(%ebx)
+	je	3f
+
+	orl	%edx, (%ebx)
+
+6:	movl	$FUTEX_WAKE, %ecx
+	xorl	%esi, %esi
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+3:	LOCK
+	decl	cond_lock-cond_nr_wakers(%ebx)
+	je,pt	4f
+
+	leal	cond_lock-cond_nr_wakers(%ebx), %eax
+	call	__lll_mutex_unlock_wake
+
+4:	popl	%ebx
+	popl	%esi
+	ret
+
+1:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+	.size	__lll_cond_broadcast,.-__lll_cond_broadcast
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
new file mode 100644
index 0000000000..400413d7c2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
@@ -0,0 +1,180 @@
+/* Copyright (C) 2002 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>
+
+	.text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+#define ETIMEDOUT               110
+
+
+	.globl	__lll_lock_wait
+	.type	__lll_lock_wait,@function
+	.hidden	__lll_lock_wait
+	.align	16
+__lll_lock_wait:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%edx
+
+	movl	%ecx, %ebx
+	xorl	%esi, %esi	/* No timeout.  */
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+1:
+	leal	-1(%eax), %edx	/* account for the preceeded xadd.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	orl	$-1, %eax	/* Load -1.  */
+	LOCK
+	xaddl	%eax, (%ebx)
+	jne	1b
+
+	movl	$-1, (%ebx)
+
+	popl	%edx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_lock_wait,.-__lll_lock_wait
+
+
+	.globl	lll_unlock_wake_cb
+	.type	lll_unlock_wake_cb,@function
+	.hidden	lll_unlock_wake_cb
+	.align	16
+lll_unlock_wake_cb:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+
+	movl	20(%esp), %ebx
+	LOCK
+	incl	(%ebx)
+	jng	1f
+
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb
+
+
+	.globl	__lll_unlock_wake
+	.type	__lll_unlock_wake,@function
+	.hidden	__lll_unlock_wake
+__lll_unlock_wake:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+
+	movl	%eax, %ebx
+1:	movl	$FUTEX_WAKE, %ecx
+	movl	$1, %edx	/* Wake one thread.  */
+	xorl	%esi, %esi
+	movl	%edx, (%ebx)	/* Stores '$1'.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_unlock_wake,.-__lll_unlock_wake
+
+
+	.globl	__lll_timedwait_tid
+	.type	__lll_timedwait_tid,@function
+	.hidden	__lll_timedwait_tid
+__lll_timedwait_tid:
+	pushl	%edi
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ebp
+
+	movl	%eax, %ebp
+	movl	%edx, %edi
+	subl	$8, %esp
+
+	/* Get current time.  */
+2:	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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	5f
+	addl	$1000000000, %edx
+	decl	%ecx
+5:	testl	%ecx, %ecx
+	js	6f		/* Time is already up.  */
+
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+
+	movl	(%ebp), %edx
+	testl	%edx, %edx
+	jz	4f
+
+	movl	%esp, %esi
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%ebp, %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	%eax, %edx
+
+	cmpl	$0, (%ebx)
+	jne	1f
+4:	xorl	%eax, %eax
+
+3:	addl	$8, %esp
+	popl	%ebp
+	popl	%ebx
+	popl	%esi
+	popl	%edi
+	ret
+
+1:	cmpl	$-ETIMEDOUT, %edx
+	jne	2b
+6:	movl	$ETIMEDOUT, %eax
+	jmp	3b
+	.size	__lll_timedwait_tid,.-__lll_timedwait_tid
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S
new file mode 100644
index 0000000000..a48cd88fa8
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S
@@ -0,0 +1,176 @@
+/* Copyright (C) 2002 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>
+
+	.text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+#define EWOULDBLOCK		11
+#define EINVAL			22
+#define ETIMEDOUT		110
+
+
+	.globl	__lll_mutex_lock_wait
+	.type	__lll_mutex_lock_wait,@function
+	.hidden	__lll_mutex_lock_wait
+	.align	16
+__lll_mutex_lock_wait:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%edx
+
+	movl	%ecx, %ebx
+	xorl	%esi, %esi	/* No timeout.  */
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+1:
+	leal	1(%eax), %edx	/* account for the preceeded xadd.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, (%ebx)
+	testl	%eax, %eax
+	jne	1b
+
+	movl	$2, (%ebx)
+
+	popl	%edx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait
+
+
+	.globl	__lll_mutex_timedlock_wait
+	.type	__lll_mutex_timedlock_wait,@function
+	.hidden	__lll_mutex_timedlock_wait
+	.align	16
+__lll_mutex_timedlock_wait:
+	/* Check for a valid timeout value.  */
+	cmpl	$1000000000, 4(%edx)
+	jae	3f
+
+	pushl	%edi
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ebp
+
+	/* Stack frame for the timespec and timeval structs.  */
+	subl	$8, %esp
+
+	movl	%ecx, %ebp
+	movl	%edx, %edi
+	leal	1(%eax), %esi
+
+	/* Get current time.  */
+1:
+	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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
+	decl	%ecx
+4:	testl	%ecx, %ecx
+	js	5f		/* Time is already up.  */
+
+	/* Futex call.  */
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+	movl	%esi, %edx
+	movl	%esp, %esi
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%ebp, %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	$1, %esi
+	LOCK
+	xaddl	%esi, (%ebx)
+	testl	%esi, %esi
+	jne	7f
+
+	movl	$2, (%ebx)
+	xorl	%eax, %eax
+
+6:	addl	$8, %esp
+	popl	%ebp
+	popl	%ebx
+	popl	%esi
+	popl	%edi
+	ret
+
+	/* Check whether the time expired.  */
+7:	cmpl	$-ETIMEDOUT, %eax
+	je	5f
+	jmp	1b
+
+3:	movl	$EINVAL, %eax
+	ret
+
+5:	movl	$ETIMEDOUT, %eax
+	jmp	6b
+	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
+
+
+	.globl	__lll_mutex_unlock_wake
+	.type	__lll_mutex_unlock_wake,@function
+	.hidden	__lll_mutex_unlock_wake
+	.align	16
+__lll_mutex_unlock_wake:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+
+	movl	$FUTEX_WAKE, %ecx
+	movl	%eax, %ebx
+	xorl	%esi, %esi
+	movl	$0, (%ebx)
+	movl	$1, %edx	/* Wake one thread.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S
new file mode 100644
index 0000000000..2dde246d1f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S
@@ -0,0 +1,566 @@
+/* Copyright (C) 2002 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>
+
+	.text
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+#define EAGAIN		11
+#define EDEADLK		35
+#define ETIMEDOUT	110
+
+/* Offsets in the pthread_rwlock_t structure.  */
+#define MUTEX		0
+#define NR_READERS	4
+#define READERS_WAKEUP	8
+#define WRITERS_WAKEUP	12
+#define READERS_QUEUED	16
+#define WRITERS_QUEUED	20
+#define FLAGS		24
+#define WRITER	28
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+
+	.globl	__pthread_rwlock_rdlock
+	.type	__pthread_rwlock_rdlock,@function
+	.align	16
+__pthread_rwlock_rdlock:
+	pushl	%esi
+	pushl	%ebx
+
+	xorl	%esi, %esi
+	xorl	%edx, %edx
+	movl	12(%esp), %ebx
+
+	/* Get the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebx)
+	testl	%eax, %eax
+	jne	1f
+
+2:	movl	WRITER(%ebx), %eax
+	testl	%eax, %eax
+	jne	14f
+	cmp	$0, WRITERS_QUEUED(%ebx)
+	je	5f
+	cmpl	$0, FLAGS(%ebx)
+	je	5f
+
+3:	incl	READERS_QUEUED(%ebx)
+	je	4f
+
+	LOCK
+	decl	MUTEX(%ebx)
+	jne	10f
+
+11:	addl	$READERS_WAKEUP-MUTEX, %ebx
+	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	subl	$READERS_WAKEUP-MUTEX, %ebx
+
+	/* Reget the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebx)
+	testl	%eax, %eax
+	jne	12f
+
+13:	decl	READERS_QUEUED(%ebx)
+	jne	2b
+	movl	$0, READERS_WAKEUP(%ebx)
+	jmp	2b
+
+5:	xorl	%ecx, %ecx
+	incl	NR_READERS(%ebx)
+	je	8f
+9:	LOCK
+	decl	MUTEX(%ebx)
+	jne	6f
+7:
+
+	movl	%ecx, %eax
+	popl	%ebx
+	popl	%esi
+	ret
+
+1:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+14:	cmpl	%gs:8, %eax
+	jne	3b
+	/* Deadlock detected.  */
+	movl	$EDEADLK, %ecx
+	jmp	9b
+
+6:	movl	%ebx, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	7b
+
+	/* Overflow.  */
+8:	decl	NR_READERS(%ebx)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+	/* Overflow.  */
+4:	decl	READERS_QUEUED(%ebx)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+10:	movl	%ebx, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	11b
+
+12:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	13b
+	.size	__pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
+
+	.globl	pthread_rwlock_rdlock
+pthread_rwlock_rdlock = __pthread_rwlock_rdlock
+
+
+	.globl	pthread_rwlock_timedrdlock
+	.type	pthread_rwlock_timedrdlock,@function
+	.align	16
+pthread_rwlock_timedrdlock:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebx
+	pushl	%ebp
+	subl	$8, %esp
+
+	movl	28(%esp), %ebp
+	movl	32(%esp), %edi
+
+	/* Get the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebp)
+	testl	%eax, %eax
+	jne	1f
+
+2:	movl	WRITER(%ebp), %eax
+	testl	%eax, %eax
+	jne	14f
+	cmp	$0, WRITERS_QUEUED(%ebp)
+	je	5f
+	cmpl	$0, FLAGS(%ebp)
+	je	5f
+
+3:	incl	READERS_QUEUED(%ebp)
+	je	4f
+
+	LOCK
+	decl	MUTEX(%ebp)
+	jne	10f
+
+	/* Get current time.  */
+	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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	15f
+	addl	$1000000000, %edx
+	decl	%ecx
+15:	testl	%ecx, %ecx
+	js	16f		/* Time is already up.  */
+
+	/* Futex call.  */
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%esp, %esi
+	movl	%ecx, %edx
+	leal	READERS_WAKEUP(%ebp), %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+	movl	%eax, %edx
+17:
+
+	/* Reget the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebp)
+	testl	%eax, %eax
+	jne	12f
+
+13:	cmpl	$-ETIMEDOUT, %ecx
+	je	18f
+	decl	READERS_QUEUED(%ebp)
+	jne	2b
+	movl	$0, READERS_WAKEUP(%ebp)
+	jmp	2b
+
+
+5:	xorl	%ecx, %ecx
+	incl	NR_READERS(%ebp)
+	je	8f
+9:	LOCK
+	decl	MUTEX(%ebp)
+	jne	6f
+
+7:	movl	%ecx, %eax
+
+	addl	$8, %esp
+	popl	%ebp
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	ret
+
+1:	movl	%ebp, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+14:	cmpl	%gs:8, %eax
+	jne	3b
+	movl	$EDEADLK, %ecx
+	jmp	9b
+
+6:	movl	%ebp, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	7b
+
+	/* Overflow.  */
+8:	decl	NR_READERS(%ebp)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+	/* Overflow.  */
+4:	decl	READERS_QUEUED(%ebp)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+10:	movl	%ebp, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	11b
+
+12:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	13b
+
+16:	movl	$-ETIMEDOUT, %ecx
+	jmp	17b
+
+18:	movl	$ETIMEDOUT, %ecx
+	jmp	9b
+	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock
+
+
+	.globl	__pthread_rwlock_wrlock
+	.type	__pthread_rwlock_wrlock,@function
+	.align	16
+__pthread_rwlock_wrlock:
+	pushl	%esi
+	pushl	%ebx
+
+	xorl	%esi, %esi
+	xorl	%edx, %edx
+	movl	12(%esp), %ebx
+
+	/* Get the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebx)
+	testl	%eax, %eax
+	jne	1f
+
+2:	movl	WRITER(%ebx), %eax
+	testl	%eax, %eax
+	jne	14f
+	cmp	$0, NR_READERS(%ebx)
+	je	5f
+
+3:	incl	WRITERS_QUEUED(%ebx)
+	je	4f
+
+	LOCK
+	decl	MUTEX(%ebx)
+	jne	10f
+
+11:	addl	$WRITERS_WAKEUP-MUTEX, %ebx
+	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	subl	$WRITERS_WAKEUP-MUTEX, %ebx
+
+	/* Reget the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebx)
+	testl	%eax, %eax
+	jne	12f
+
+13:	decl	WRITERS_QUEUED(%ebx)
+	movl	$0, WRITERS_WAKEUP(%ebx)
+	jmp	2b
+
+5:	xorl	%ecx, %ecx
+	movl	%gs:8, %eax
+	movl	%eax, WRITER(%ebx)
+9:	LOCK
+	decl	MUTEX(%ebx)
+	jne	6f
+7:
+
+	movl	%ecx, %eax
+	popl	%ebx
+	popl	%esi
+	ret
+
+1:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+14:	cmpl	%gs:8, %eax
+	jne	3b
+	movl	$EDEADLK, %ecx
+	jmp	9b
+
+6:	movl	%ebx, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	7b
+
+4:	decl	WRITERS_QUEUED(%ebx)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+10:	movl	%ebx, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	11b
+
+12:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	13b
+	.size	__pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
+
+	.globl	pthread_rwlock_wrlock
+pthread_rwlock_wrlock = __pthread_rwlock_wrlock
+
+
+	.globl	pthread_rwlock_timedwrlock
+	.type	pthread_rwlock_timedwrlock,@function
+	.align	16
+pthread_rwlock_timedwrlock:
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebx
+	pushl	%ebp
+	subl	$8, %esp
+
+	movl	28(%esp), %ebp
+	movl	32(%esp), %edi
+
+	/* Get the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebp)
+	testl	%eax, %eax
+	jne	1f
+
+2:	movl	WRITER(%ebp), %eax
+	testl	%eax, %eax
+	jne	14f
+	cmp	$0, NR_READERS(%ebp)
+	je	5f
+
+3:	incl	WRITERS_QUEUED(%ebp)
+	je	4f
+
+	LOCK
+	decl	MUTEX(%ebp)
+	jne	10f
+
+	/* Get current time.  */
+	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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	15f
+	addl	$1000000000, %edx
+	decl	%ecx
+15:	testl	%ecx, %ecx
+	js	16f		/* Time is already up.  */
+
+	/* Futex call.  */
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%esp, %esi
+	movl	%ecx, %edx
+	leal	WRITERS_WAKEUP(%ebp), %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+	movl	%eax, %edx
+17:
+
+	/* Reget the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebp)
+	testl	%eax, %eax
+	jne	12f
+
+13:	cmpl	$-ETIMEDOUT, %ecx
+	je	18f
+	decl	WRITERS_QUEUED(%ebp)
+	movl	$0, WRITERS_WAKEUP(%ebp)
+	jmp	2b
+
+
+5:	xorl	%ecx, %ecx
+	movl	%gs:8, %eax
+	movl	%eax, WRITER(%ebp)
+9:	LOCK
+	decl	MUTEX(%ebp)
+	jne	6f
+
+7:	movl	%ecx, %eax
+
+	addl	$8, %esp
+	popl	%ebp
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	ret
+
+1:	movl	%ebp, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+14:	cmpl	%gs:8, %eax
+	jne	3b
+	movl	$EDEADLK, %ecx
+	jmp	9b
+
+6:	movl	%ebp, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	7b
+
+	/* Overflow.  */
+4:	decl	WRITERS_QUEUED(%ebp)
+	movl	$EAGAIN, %ecx
+	jmp	9b
+
+10:	movl	%ebp, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	11b
+
+12:	movl	%ebx, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	13b
+
+16:	movl	$-ETIMEDOUT, %ecx
+	jmp	17b
+
+18:	movl	$ETIMEDOUT, %ecx
+	jmp	9b
+	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock
+
+	.globl	__pthread_rwlock_unlock
+	.type	__pthread_rwlock_unlock,@function
+	.align	16
+__pthread_rwlock_unlock:
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+	xorl	%esi, %esi
+	xorl	%edx, %edx
+	movl	16(%esp), %edi
+
+	/* Get the lock.  */
+	movl	$1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%edi)
+	testl	%eax, %eax
+	jne	1f
+
+2:	cmpl	$0, WRITER(%edi)
+	jne	5f
+	decl	NR_READERS(%edi)
+	jnz	6f
+
+5:	movl	$0, WRITER(%edi)
+
+	movl	$0x7fffffff, %edx
+	leal	READERS_WAKEUP(%edi), %ebx
+	movl	$1, %ecx
+	leal	WRITERS_WAKEUP(%edi), %eax
+	cmpl	$0, WRITERS_QUEUED(%edi)
+	cmovne	%ecx, %edx
+	cmovne	%eax, %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+6:	LOCK
+	decl	MUTEX(%edi)
+	jne	3f
+
+4:	xorl	%eax, %eax
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	ret
+
+1:	movl	%edi, %ecx
+	call	__lll_mutex_lock_wait
+	jmp	2b
+
+3:	movl	%edi, %eax
+	call	__lll_mutex_unlock_wake
+	jmp	4b
+
+	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock
+
+	.globl	pthread_rwlock_unlock
+pthread_rwlock_unlock = __pthread_rwlock_unlock
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S
new file mode 100644
index 0000000000..18fb16f6f6
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S
@@ -0,0 +1,311 @@
+/* Copyright (C) 2002 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 <shlib-compat.h>
+
+	.text
+
+#ifndef UP
+# define LOCK lock
+#else
+# define
+#endif
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAKE		1
+
+#define EINTR			4
+#define EAGAIN			11
+#define EWOULDBLOCK		EAGAIN
+#define EINVAL			22
+#define ETIMEDOUT		110
+
+
+	.globl	__new_sem_wait
+	.type	__new_sem_wait,@function
+	.align	16
+__new_sem_wait:
+	pushl	%ebx
+	pushl	%esi
+
+	movl	12(%esp), %ebx
+
+3:	movl	(%ebx), %eax
+2:	testl	%eax, %eax
+	je,pn	1f
+
+	leal	-1(%eax), %edx
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jne,pn	2b
+	xorl	%eax, %eax
+
+	popl	%esi
+	popl	%ebx
+	ret
+
+1:	xorl	%esi, %esi
+	movl	$SYS_futex, %eax
+	movl	%esi, %ecx
+	movl	%esi, %edx
+	int	$0x80
+
+	testl	%eax, %eax
+	je	3b
+	cmpl	$-EWOULDBLOCK, %eax
+	je	3b
+	negl	%eax
+#ifdef PIC
+	call	__i686.get_pc_thunk.bx
+#else
+	movl	$4f, %ebx
+4:
+#endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	movl	%gs:0, %edx
+	subl	errno@gottpoff(%ebx), %edx
+	movl	%eax, (%edx)
+	orl	$-1, %eax
+	popl	%esi
+	popl	%ebx
+	ret
+	.size	__new_sem_wait,.-__new_sem_wait
+	.symver	__new_sem_wait, sem_wait@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+	.global	__old_sem_wait
+__old_sem_wait = __new_sem_wait
+	.symver	__old_sem_wait, sem_wait@GLIBC_2.0
+#endif
+
+
+	.globl	__new_sem_trywait
+	.type	__new_sem_trywait,@function
+	.align	16
+__new_sem_trywait:
+	movl	4(%esp), %ecx
+
+	movl	(%ecx), %eax
+2:	testl	%eax, %eax
+	jz	1f
+
+	leal	-1(%eax), %edx
+	LOCK
+	cmpxchgl %edx, (%ecx)
+	jne,pn	2b
+	xorl	%eax, %eax
+	ret
+
+1:
+#ifdef PIC
+	call	__i686.get_pc_thunk.cx
+#else
+	movl	$3f, %ecx
+3:
+#endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
+	movl	%gs:0, %edx
+	subl	errno@gottpoff(%ecx), %edx
+	movl	$EAGAIN, (%edx)
+	orl	$-1, %eax
+	ret
+	.size	__new_sem_trywait,.-__new_sem_trywait
+	.symver	__new_sem_trywait, sem_trywait@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+	.global	__old_sem_trywait
+__old_sem_trywait = __new_sem_trywait
+	.symver	__old_sem_trywait, sem_trywait@GLIBC_2.0
+#endif
+
+
+	.globl	sem_timedwait
+	.type	sem_timedwait,@function
+	.align	16
+sem_timedwait:
+	movl	4(%esp), %ecx
+
+	movl	(%ecx), %eax
+2:	testl	%eax, %eax
+	je,pn	1f
+
+	leal	-1(%eax), %edx
+	LOCK
+	cmpxchgl %edx, (%ecx)
+	jne,pn	2b
+
+	xorl	%eax, %eax
+	ret
+
+	/* Check whether the timeout value is valid.  */
+1:	pushl	%esi
+	pushl	%edi
+	pushl	%ebx
+	subl	$8, %esp
+
+	movl	%esp, %esi
+	movl	28(%esp), %edi
+
+	/* Check for invalid nanosecond field.  */
+	cmpl	$1000000000, 4(%edi)
+	movl	$EINVAL, %eax
+	jae	6f
+
+7:	xorl	%ecx, %ecx
+	movl	%esp, %ebx
+	movl	%ecx, %edx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* 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	5f
+	addl	$1000000000, %edx
+	decl	%ecx
+5:	testl	%ecx, %ecx
+	movl	$ETIMEDOUT, %eax
+	js	6f		/* Time is already up.  */
+
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+	movl	24(%esp), %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_futex, %eax
+	xorl	%edx, %edx
+	int	$0x80
+
+	testl	%eax, %eax
+	je,pt	9f
+	cmpl	$-EWOULDBLOCK, %eax
+	jne	3f
+
+9:	movl	(%ebx), %eax
+8:	testl	%eax, %eax
+	je	7b
+
+	leal	-1(%eax), %ecx
+	LOCK
+	cmpxchgl %ecx, (%ebx)
+	jne,pn	8b
+
+	addl	$8, %esp
+	xorl	%eax, %eax
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	ret
+
+3:	negl	%eax
+6:
+#ifdef PIC
+	call	__i686.get_pc_thunk.bx
+#else
+	movl	$4f, %ebx
+4:
+#endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	movl	%gs:0, %edx
+	subl	errno@gottpoff(%ebx), %edx
+	movl	%eax, (%edx)
+
+	addl	$8, %esp
+	orl	$-1, %eax
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	ret
+	.size	sem_timedwait,.-sem_timedwait
+
+
+	.globl	__new_sem_post
+	.type	__new_sem_post,@function
+	.align	16
+__new_sem_post:
+	pushl	%esi
+	pushl	%ebx
+
+	movl	12(%esp), %ebx
+	movl	$1, %edx
+	LOCK
+	xaddl	%edx, (%ebx)
+
+	xorl	%esi, %esi
+	movl	$SYS_futex, %eax
+	movl	$FUTEX_WAKE, %ecx
+	incl	%edx
+	int	$0x80
+
+	testl	%eax, %eax
+	js	1f
+
+	popl	%ebx
+	popl	%esi
+	ret
+
+1:
+#ifdef PIC
+	call	__i686.get_pc_thunk.bx
+#else
+	movl	$4f, %ebx
+4:
+#endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	movl	%gs:0, %edx
+	subl	errno@gottpoff(%ebx), %edx
+	movl	$EINVAL, (%edx)
+
+	orl	$-1, %eax
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__new_sem_post,.-__new_sem_post
+	.symver	__new_sem_post, sem_post@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+	.global	__old_sem_post
+__old_sem_post = __new_sem_post
+	.symver	__old_sem_post, sem_post@GLIBC_2.0
+#endif
+
+
+#ifdef PIC
+	.section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
+	.globl	__i686.get_pc_thunk.bx
+	.hidden	__i686.get_pc_thunk.bx
+	.type	__i686.get_pc_thunk.bx,@function
+__i686.get_pc_thunk.bx:
+	movl (%esp), %ebx;
+	ret
+	.size	__i686.get_pc_thunk.bx,.-__i686.get_pc_thunk.bx
+
+
+	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
+	.globl	__i686.get_pc_thunk.cx
+	.hidden	__i686.get_pc_thunk.cx
+	.type	__i686.get_pc_thunk.cx,@function
+__i686.get_pc_thunk.cx:
+	movl (%esp), %ecx;
+	ret
+	.size	__i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
+#endif
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
new file mode 100644
index 0000000000..a385adc5f9
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
@@ -0,0 +1,122 @@
+/* Copyright (C) 2002 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>
+
+#define SYS_futex	240
+#define FUTEX_WAIT	0
+#define FUTEX_WAKE	1
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+#define CURR_EVENT	0
+#define MUTEX		4
+#define LEFT		8
+#define	INIT_COUNT	12
+
+
+	.text
+
+	.globl	pthread_barrier_wait
+	.type	pthread_barrier_wait,@function
+	.align	16
+pthread_barrier_wait:
+	pushl	%esi
+	pushl	%ebx
+
+	movl	12(%esp), %ebx
+	xorl	%esi, %esi
+
+	/* Get the mutex.  */
+	orl	$-1, %eax
+	LOCK
+	xaddl	%eax, MUTEX(%ebx)
+	jne	1f
+
+	/* One less waiter.  If this was the last one needed wake
+	   everybody.  */
+2:	decl	LEFT(%ebx)
+	je	3f
+
+	/* There are more threads to come.  */
+	movl	CURR_EVENT(%ebx), %edx
+
+	/* Release the mutex.  */
+	LOCK
+	incl	MUTEX(%ebx)
+	jng	6f
+
+	/* Wait for the remaining threads.  The call will return immediately
+	   if the CURR_EVENT memory has meanwhile been changed.  */
+7:	movl	%esi, %ecx		/* movl $FUTEX_WAIT, %ecx */
+8:	movl	$SYS_futex, %eax
+	int	$0x80
+
+	/* Don't return on spurious wakeups.  The syscall does not change
+	   any register except %eax so there is no need to reload any of
+	   them.  */
+	cmpl	%edx, CURR_EVENT(%ebx)
+	je,pn	8b
+
+	/* Note: %esi is still zero.  */
+	movl	%esi, %eax		/* != PTHREAD_BARRIER_SERIAL_THREAD */
+
+	popl	%ebx
+	popl	%esi
+	ret
+
+	/* The necessary number of threads arrived.  */
+3:	movl	INIT_COUNT(%ebx), %eax
+	movl	%eax, LEFT(%ebx)
+	incl	CURR_EVENT(%ebx)
+
+	/* Wake up all waiters.  The count is a signed number in the kernel
+	   so 0x7fffffff is the highest value.  */
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	/* Release the mutex.  */
+	LOCK
+	incl	MUTEX(%ebx)
+	jng	4f
+
+5:	orl	$-1, %eax		/* == PTHREAD_BARRIER_SERIAL_THREAD */
+
+	popl	%ebx
+	popl	%esi
+	ret
+
+1:	leal	MUTEX(%ebx), %ecx
+	call	__lll_lock_wait
+	jmp	2b
+
+4:	leal	MUTEX(%ebx), %eax
+	call	__lll_unlock_wake
+	jmp	5b
+
+6:	leal	MUTEX(%ebx), %eax
+	call	__lll_unlock_wake
+	jmp	7b
+	.size	pthread_barrier_wait,.-pthread_barrier_wait