about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/i386
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-11-26 22:50:54 +0000
committerUlrich Drepper <drepper@redhat.com>2002-11-26 22:50:54 +0000
commit76a50749f7af5935ba3739e815aa6a16ae4440d1 (patch)
treec16eac47f220f03fea74d80ef0a4e774809e94b7 /nptl/sysdeps/unix/sysv/linux/i386
parent6938e63f714b15c377d8cbf8e97b6f15b0e1b692 (diff)
downloadglibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.tar.gz
glibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.tar.xz
glibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.zip
Initial revision cvs/initial
2002-11-26  Ulrich Drepper  <drepper@redhat.com>
	* allocatestack.c (queue_stack): Don't remove stack from list here.
	Do it in the caller.  Correct condition to prematurely terminate
	loop to free stacks.
	(__deallocate_stack): Remove stack from list here.
2002-11-26  Ulrich Drepper  <drepper@redhat.com>
	* Makefile (tests): Add tst-stack1.
	* tst-stack1.c: New file.
	* allocatestack.c (allocate_stack): Initialize the TCB on a user
	provided stack.
	* pthread_attr_getstack.c: Return bottom of the thread area.
2002-11-25  Ulrich Drepper  <drepper@redhat.com>
	* Makefile (libpthread-routines): Add pt-allocrtsig and
	pthread_kill_other_threads.
	* pt-allocrtsig.c: New file.
	* pthread_kill_other_threads.c: New file.
	* sysdeps/unix/sysv/linux/allocrtsig.c: Add additional aliases for
	all three functions.
	* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove
	allocrtsig.
	* sysdeps/unix/sysv/linux/Versions (libc:GLIBC_PRIVATE): Export
	__libc_current_sigrtmin_private, __libc_current_sigrtmax_private,
	and __libc_allocate_rtsig_private.
	* Versions (libpthread): Export pthread_kill_other_threads_np,
	__libc_current_sigrtmin, and __libc_current_sigrtmax.
2002-11-24  Ulrich Drepper  <drepper@redhat.com>

	* allocatestack.c (allocate_stack): stackaddr in attribute points to
	the end of the stack.  Adjust computations.
	When mprotect call fails dequeue stack and free it.
	* pthread_attr_setstack.c: Store top of the stack in stackaddr
	attribute.
	* pthread_getattr_np.c: Likewise.

	* descr.h (IS_DETACHED): Add some more parenthesis to prevent
	surprises.

2002-11-23  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/pthread/pthread.h (pthread_self): __THROW must come before
	attribute definitions.  Patch by Luca Barbieri <ldb@ldb.ods.org>.

2002-11-22  Ulrich Drepper  <drepper@redhat.com>

	* pthread_getspecific.c: Optimize access to first 2nd-level array.
	* pthread_setspecific.c: Likewise.

2002-11-21  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/i386/createthread.c: Remove CLONE_ flags
	definitions.  Get them from the official place.
	* sysdeps/unix/sysv/linux/i386/fork.c: Likewise.

	* sysdeps/unix/sysv/linux/i386/createthread.c: Update CLONE_* flags.
	Use new CLONE_ flags in clone() calls.

	* sysdeps/unix/sysv/linux/fork.c: Use ARCH_FORK to actually fork.
	* sysdeps/unix/sysv/linux/i386/fork.c: New file.

	* Versions: Add pthread_* functions for libc.
	* forward.c: New file.

	* sysdeps/pthread/Makefile (libpthread-sysdeps_routines): Add
	errno-loc.
	* herrno.c: New file.
	* res.c: New file.

	* Makefile (libpthread-routines): Remove sem_post, sem_wait,
	sem_trywait, and sem_timedwait.  Add herrno and res.
	* sem_init.c: Don't initialize lock and waiters members.
	* sem_open.c: Likewise.
	* sem_post.c: Removed.
	* sem_wait.c: Removed.
	* sem_trywait.c: Removed.
	* sem_timedwait.c: Removed.
	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Complete rewrite.
	Includes full implementations of sem_post, sem_wait, sem_trywait,
	and sem_timedwait.
	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Adjust
	for new implementation.
	* sysdeps/unix/sysv/linux/internaltypes.h (struct sem): Remove lock
	and waiters fields.

	* tst-sem3.c: Improve error message.
	* tst-signal3.c: Likewise.

	* init.c (__pthread_initialize_minimal): Use set_tid_address syscall
	to tell the kernel about the termination futex and to initialize tid
	member.  Don't initialize main_thread.
	* descr.h (struct pthread): Remove main_thread member.
	* cancelllation.c (__do_cancel): Remove code handling main thread.
	The main thread is not special anymore.

	* allocatestack.c (__reclaim_stacks): Mark stacks as unused.  Add
	size of the stacks to stack_cache_actsize.

	* pt-readv.c: Add missing "defined".
	* pt-sigwait.c: Likewise.
	* pt-writev.c: Likewise.

2002-11-09  Ulrich Drepper  <drepper@redhat.com>

	* Versions: Export __connect from libpthread.
	Patch by Luca Barbieri <ldb@ldb.ods.org>.

	* Makefile (libpthread-routines): Add pt-raise.
	* sysdeps/unix/sysv/linux/raise.c: New file.
	* sysdeps/unix/sysv/linux/pt-raise.c: New file.
	* sysdeps/generic/pt-raise.c: New file.

	* pthread_cond_init.c: Initialize all data elements of the condvar
	structure.  Patch by Luca Barbieri <ldb@ldb.ods.org>.

	* pthread_attr_init.c: Actually implement 2.0 compatibility version.
	* pthread_create.c: Likewise.

	* Makefile (tests): Add tst-key1, tst-key2, tst-key3.
	* tst-key1.c: New file.
	* tst-key2.c: New file.
	* tst-key3.c: New file.

	* Versions: Export pthread_detach for version GLIBC_2.0.
	Reported by Saurabh Desai <sdesai@austin.ibm.com>.

2002-11-08  Ulrich Drepper  <drepper@redhat.com>

	* pthread_key_create.c: Terminate search after an unused key was found.
	Patch by Luca Barbieri <ldb@ldb.ods.org>.

	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Return zero.
	Patch by Luca Barbieri <ldb@ldb.ods.org>.

2002-10-10  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Use slow generic
	dynamic lookup for errno in PIC.

	* allocatestack.c (get_cached_stack): Rearrange code slightly to
	release the stack lock as soon as possible.
	Call _dl_allocate_tls_init for TCB from the cache to re-initialize
	the static TLS block.
	(allocate_stack): Call _dl_allocate_tls_init for user-provided stack.

	* cancellation.c: Renamed from cancelation.c.
	* Makefile: Adjust accordingly.
	* pthreadP.h (CANCELLATION_P): Renamed from CANCELATION_P.
	* cleanup_defer.c: Use CANCELLATION_P.
	* pthread_testcancel.c: Likewise.
	* descr.h: Fix spelling in comments.
	* init.c: Likewise.
	* pthread_getattr_np.c: Likewise.
	* pthread_getschedparam.c: Likewise.
	* pthread_setschedparam.c: Likewise.
	* Versions: Likewise.

	* pt-pselect.c: New file.
	* Makefile (libpthread-routines): Add pt-pselect.
	* Versions: Add pselect.

	* tst-cancel4.c: New file.
	* Makefile (tests): Add tst-cancel4.

2002-10-09  Ulrich Drepper  <drepper@redhat.com>

	* pthread_mutex_lock.c: Always record lock ownership.
	* pthread_mutex_timedlock.c: Likewise.
	* pthread_mutex_trylock.c: Likewise.

	* pt-readv.c: New file.
	* pt-writev.c: New file.
	* pt-creat.c: New file.
	* pt-msgrcv.c: New file.
	* pt-msgsnd.c: New file.
	* pt-poll.c: New file.
	* pt-select.c: New file.
	* pt-sigpause.c: New file.
	* pt-sigsuspend.c: New file.
	* pt-sigwait.c: New file.
	* pt-sigwaitinfo.c: New file.
	* pt-waitid.c: New file.
	* Makefile (libpthread-routines): Add pt-readv, pt-writev, pt-creat,
	pt-msgrcv, pt-msgsnd, pt-poll, pt-select, pt-sigpause, pt-sigsuspend,
	pt-sigwait, pt-sigwaitinfo, and pt-waitid.
	* Versions: Add all the new functions.

	* tst-exit1.c: New file.
	* Makefile (tests): Add tst-exit1.

	* sem_timedwait.c: Minor optimization for more optimal fastpath.

2002-10-08  Ulrich Drepper  <drepper@redhat.com>

	* pt-fcntl.c: Only enable asynchronous cancellation for F_SETLKW.

	* pthread_join.c: Enable asynchronous cancellation around lll_wait_tid
	call.  pthread_join is an official cancellation point.
	* pthread_timedjoin.c: Likewise.

	* pthread_cond_wait.c: Revert order in which internal lock are dropped
	and the condvar's mutex are retrieved.
	* pthread_cond_timedwait.c: Likewise.
	Reported by dice@saros.East.Sun.COM.

2002-10-07  Ulrich Drepper  <drepper@redhat.com>

	* pthreadP.h: Cut out all type definitions and move them...
	* sysdeps/unix/sysv/linux/internaltypes.h: ...here.  New file.
	* pthreadP.h: Include <internaltypes.h>.

	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Little
	performance tweaks.

	* sem_trywait.c: Shuffle #includes around to get right order.
	* sem_timedwait.c: Likewise.
	* sem_post.c: Likewise.
	* sem_wait.c: Likewise.

	* nptl 0.3 released.

	* Makefile (tests): Add tst-signal3.
	* tst-signal3.c: New file.

2002-10-05  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Tell the compiler that
	the asms modify the sem object.
	(__lll_sem_timedwait): Now takes struct sem* as first parameter.

	* sysdeps/unix/sysv/linux/i386/bits/semaphore.h (sem_t): Don't expose
	the actual members.
	* pthreadP.h (struct sem): New type.  Actual semaphore type.
	* semaphoreP.h: Include pthreadP.h.
	* sem_getvalue.c: Adjust to sem_t change.
	* sem_init.c: Likewise.
	* sem_open.c: Likewise.
	* sem_post.c: Likewise.
	* sem_timedwait.c: Likewise.
	* sem_trywait.c: Likewise.
	* sem_wait.c: Likewise.

2002-10-04  Ulrich Drepper  <drepper@redhat.com>

	* Makefile (tests): Add tst-basic2, tst-exec1, tst-exec3, tst-exec3.
	* tst-basic2.c: New file.
	* tst-exec1.c: New file.
	* tst-exec2.c: New file.
	* tst-exec3.c: New file.

	* tst-fork1.c: Remove extra */.

	* nptl 0.2 released.  The API for IA-32 is complete.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h150
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h39
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/createthread.c146
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/fork.c31
-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
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h257
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h101
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S49
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S171
26 files changed, 2818 insertions, 0 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
new file mode 100644
index 0000000000..2167bbb988
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -0,0 +1,150 @@
+/* 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.  */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers.  The structure of the attribute type is not
+   exposed on purpose.  */
+typedef unsigned long int pthread_t;
+
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_ATTR_T];
+  long int __align;
+} pthread_attr_t;
+
+
+/* Data structures for mutex handling.  The structure of the attribute
+   type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __count;
+    struct pthread *__owner;
+    /* KIND must stay at this position in the structure to maintain
+       binary compatibility.  */
+    int __kind;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_MUTEX_T];
+  long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_wakers;
+    unsigned int __nr_sleepers;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  long int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#ifdef __USE_UNIX98
+/* Data structure for read-write lock variable handling.  The
+   structure of the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_readers;
+    unsigned int __readers_wakeup;
+    unsigned int __writer_wakeup;
+    unsigned int __nr_readers_queued;
+    unsigned int __nr_writers_queued;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned int __flags;
+    pthread_t __writer;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+  long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+  long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type.  The structure of the type is
+   deliberately not exposed.  */
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIER_T];
+  long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+  int __align;
+} pthread_barrierattr_t;
+#endif
+
+
+#endif	/* bits/pthreadtypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h
new file mode 100644
index 0000000000..ab46ac099b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h
@@ -0,0 +1,39 @@
+/* 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.  */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+
+#define __SIZEOF_SEM_T	16
+
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED      ((sem_t *) 0)
+
+/* Maximum value the semaphore can have.  */
+#define SEM_VALUE_MAX   ((int) ((~0u) >> 1))
+
+
+typedef union
+{
+  char __size[__SIZEOF_SEM_T];
+  long int __align;
+} sem_t;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
new file mode 100644
index 0000000000..3196a8c754
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
@@ -0,0 +1,146 @@
+/* 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 <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <ldsodefs.h>
+#include <tls.h>
+
+
+#define CLONE_SIGNAL    	(CLONE_SIGHAND | CLONE_THREAD)
+
+
+static int
+create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
+{
+  union user_desc_init desc;
+
+  /* Describe the thread-local storage segment.  */
+
+  /* The 'entry_number' field.  The first three bits of the segment
+     register value select the GDT, ignore them.  We get the index
+     from the value of the %gs register in the current thread.  */
+  desc.vals[0] = TLS_GET_GS () >> 3;
+  /* The 'base_addr' field.  Pointer to the TCB.  */
+  desc.vals[1] = (unsigned long int) pd;
+  /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */
+  desc.vals[2] = 0xfffff;
+  /* Collapsed value of the bitfield:
+       .seg_32bit = 1
+       .contents = 0
+       .read_exec_only = 0
+       .limit_in_pages = 1
+       .seg_not_present = 0
+       .useable = 1 */
+  desc.vals[3] = 0x51;
+
+
+  assert (pd->header.data.tcb != NULL);
+
+
+  if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
+    {
+      /* The parent thread is supposed to report events.  Check whether
+	 the TD_CREATE event is needed, too.  */
+      const int _idx = __td_eventword (TD_CREATE);
+      const uint32_t _mask = __td_eventmask (TD_CREATE);
+
+      if ((_mask & (__nptl_threads_events.event_bits[_idx]
+		    | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
+	{
+	  /* We have to report the new thread.  Make sure the thread
+	     does not run far by forcing it to get a lock.  We lock it
+	     here too so that the new thread cannot continue until we
+	     tell it to.  */
+	  lll_lock (pd->lock);
+
+	  /* Create the thread.  */
+	  if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
+		       CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+		       CLONE_SETTLS | CLONE_PARENT_SETTID |
+		       CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
+		       pd, &pd->tid, &desc.desc, &pd->tid) == -1)
+	    /* Failed.  */
+	    return errno;
+
+	  /* Now fill in the information about the new thread in
+	     the newly created thread's data structure.  We cannot let
+	     the new thread do this since we don't know whether it was
+	     already scheduled when we send the event.  */
+	  pd->eventbuf.eventnum = TD_CREATE;
+	  pd->eventbuf.eventdata = pd;
+
+	  /* Enqueue the descriptor.  */
+	  do
+	    pd->nextevent = __nptl_last_event;
+	  while (atomic_compare_and_exchange_acq (__nptl_last_event, pd,
+						  pd->nextevent) != 0);
+
+	  /* Now call the function which signals the event.  */
+	  __nptl_create_event ();
+
+	  /* And finally restart the new thread.  */
+	  lll_unlock (pd->lock);
+
+	  return 0;
+	}
+    }
+
+  /* We rely heavily on various flags the CLONE function understands:
+
+     CLONE_VM, CLONE_FS, CLONE_FILES
+	These flags select semantics with shared address space and
+	file descriptors according to what POSIX requires.
+
+     CLONE_SIGNAL
+	This flag selects the POSIX signal semantics.
+
+     CLONE_SETTLS
+	The sixth parameter to CLONE determines the TLS area for the
+	new thread.
+
+     CLONE_PARENT_SETTID
+	The kernels writes the thread ID of the newly created thread
+	into the location pointed to by the fifth parameters to CLONE.
+
+	Note that it would be semantically equivalent to use
+	CLONE_CHILD_SETTID but it is be more expensive in the kernel.
+
+     CLONE_CHILD_CLEARTID
+	The kernels clears the thread ID of a thread that has called
+	sys_exit() - using the same parameter as CLONE_SETTID.
+
+     CLONE_DETACHED
+	No signal is generated if the thread exists and it is
+	automatically reaped.
+
+     The termination signal is chosen to be zero which means no signal
+     is sent.  */
+  if (__clone (start_thread, STACK_VARIABLES_ARGS,
+	       CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+	       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+	       CLONE_DETACHED | 0, pd, &pd->tid, &desc.desc, &pd->tid) == -1)
+    /* Failed.  */
+    return errno;
+
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/fork.c b/nptl/sysdeps/unix/sysv/linux/i386/fork.c
new file mode 100644
index 0000000000..813e5299a6
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/fork.c
@@ -0,0 +1,31 @@
+/* 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 <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK() \
+  INLINE_SYSCALL (clone, 5,						      \
+		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
+		  NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"
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
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S
new file mode 100644
index 0000000000..3dc8403a29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelcond.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S
new file mode 100644
index 0000000000..e60dea89ef
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevellock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S
new file mode 100644
index 0000000000..50481991ff
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelmutex.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S
new file mode 100644
index 0000000000..6f4a8305ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelrwlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S
new file mode 100644
index 0000000000..cfaa36ac74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelsem.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S
new file mode 100644
index 0000000000..6d20b9a95c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/pthread_barrier_wait.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S
new file mode 100644
index 0000000000..3dc8403a29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelcond.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S
new file mode 100644
index 0000000000..e60dea89ef
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevellock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S
new file mode 100644
index 0000000000..50481991ff
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelmutex.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S
new file mode 100644
index 0000000000..6f4a8305ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelrwlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S
new file mode 100644
index 0000000000..cfaa36ac74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/lowlevelsem.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S
new file mode 100644
index 0000000000..6d20b9a95c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S
@@ -0,0 +1,20 @@
+/* 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 "../i486/pthread_barrier_wait.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
new file mode 100644
index 0000000000..71babd5c93
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -0,0 +1,257 @@
+/* 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.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H	1
+
+#include <time.h>
+#include <bits/pthreadtypes.h>
+
+#ifndef LOCK_INSTR
+# ifdef UP
+#  define LOCK_INSTR	/* nothing */
+# else
+#  define LOCK_INSTR "lock;"
+# endif
+#endif
+
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+
+/* Initializer for compatibility lock.  */
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
+
+
+/* Does not preserve %eax and %ecx.  */
+extern int __lll_mutex_lock_wait (int val, int *__futex)
+     __attribute ((regparm (2))) attribute_hidden;
+/* Does not preserver %eax, %ecx, and %edx.  */
+extern int __lll_mutex_timedlock_wait (int val, int *__futex,
+				 const struct timespec *abstime)
+     __attribute ((regparm (3))) attribute_hidden;
+/* Preserves all registers but %eax.  */
+extern int __lll_mutex_unlock_wait (int *__futex)
+     __attribute ((regparm (1))) attribute_hidden;
+
+
+#define lll_mutex_trylock(futex) \
+  ({ unsigned char ret;							      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0"		      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (1), "1" (futex), "0" (0));		      \
+     ret; })
+
+
+#define lll_mutex_lock(futex) \
+  (void) ({ int ignore1, ignore2;					      \
+	    __asm (LOCK_INSTR "xaddl %0, %2\n\t"			      \
+		   "testl %0, %0\n\t"					      \
+		   "jne 1f\n\t"						      \
+		   ".subsection 1\n"					      \
+		   "1:\tleal %2, %%ecx\n\t"				      \
+		   "call __lll_mutex_lock_wait\n\t"			      \
+		   "jmp 2f\n\t"						      \
+		   ".previous\n"					      \
+		   "2:"							      \
+		   : "=a" (ignore1), "=&c" (ignore2), "=m" (futex)	      \
+		   : "0" (1), "2" (futex)); })
+
+
+#define lll_mutex_timedlock(futex, timeout) \
+  ({ int result, ignore1, ignore2;					      \
+     __asm (LOCK_INSTR "xaddl %0, %3\n\t"				      \
+	    "testl %0, %0\n\t"						      \
+	    "jne 1f\n\t"						      \
+	    ".subsection 1\n"						      \
+	    "1:\tleal %3, %%ecx\n\t"					      \
+	    "movl %6, %%edx\n\t"					      \
+	    "call __lll_mutex_timedlock_wait\n\t"			      \
+	    "jmp 2f\n\t"						      \
+	    ".previous\n"						      \
+	    "2:"							      \
+	    : "=a" (result), "=&c" (ignore1), "=&d" (ignore2), "=m" (futex)   \
+	    : "0" (1), "3" (futex), "m" (timeout));			      \
+     result; })
+
+
+#define lll_mutex_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm (LOCK_INSTR "decl %0\n\t"				      \
+		   "jne 1f\n\t"						      \
+		   ".subsection 1\n"					      \
+		   "1:\tleal %0, %%eax\n\t"				      \
+		   "call __lll_mutex_unlock_wake\n\t"			      \
+		   "jmp 2f\n\t"						      \
+		   ".previous\n"					      \
+		   "2:"							      \
+		   : "=m" (futex), "=&a" (ignore)			      \
+		   : "0" (futex)); })
+
+
+#define lll_mutex_islocked(futex) \
+  (futex != 0)
+
+
+/* We have a separate internal lock implementation which is not tied
+   to binary compatibility.  */
+
+/* Type for lock object.  */
+typedef int lll_lock_t;
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER		(1)
+#define LLL_LOCK_INITIALIZER_LOCKED	(0)
+
+
+extern int __lll_lock_wait (int val, int *__futex)
+     __attribute ((regparm (2))) attribute_hidden;
+extern int __lll_unlock_wake (int *__futex)
+     __attribute ((regparm (1))) attribute_hidden;
+extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
+
+
+/* The states of a lock are:
+    1  -  untaken
+    0  -  taken by one user
+   <0  -  taken by more users */
+
+
+#define lll_trylock(futex) \
+  ({ unsigned char ret;							      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0"		      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (0), "1" (futex), "0" (1));		      \
+     ret; })
+
+
+#define lll_lock(futex) \
+  (void) ({ int ignore1, ignore2;					      \
+	    __asm (LOCK_INSTR "xaddl %0, %2\n\t"			      \
+		   "jne 1f\n\t"						      \
+		   ".subsection 1\n"					      \
+		   "1:\tleal %2, %%ecx\n\t"				      \
+		   "call __lll_lock_wait\n\t"				      \
+		   "jmp 2f\n\t"						      \
+		   ".previous\n"					      \
+		   "2:"							      \
+		   : "=a" (ignore1), "=&c" (ignore2), "=m" (futex)	      \
+		   : "0" (-1), "2" (futex)); })
+
+
+#define lll_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm (LOCK_INSTR "incl %0\n\t"				      \
+		   "jng 1f\n\t"						      \
+		   ".subsection 1\n"					      \
+		   "1:\tleal %0, %%eax\n\t"				      \
+		   "call __lll_unlock_wake\n\t"				      \
+		   "jmp 2f\n\t"						      \
+		   ".previous\n"					      \
+		   "2:"							      \
+		   : "=m" (futex), "=&a" (ignore)			      \
+		   : "0" (futex)); })
+
+
+#define lll_islocked(futex) \
+  (futex != 0)
+
+
+/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+   wakeup when the clone terminates.  The memory location contains the
+   thread ID while the clone is running and is reset to zero
+   afterwards.
+
+   The macro parameter must not have any side effect.  */
+#ifdef PIC
+# define LLL_TID_EBX_LOAD	"xchgl %2, %%ebx\n"
+# define LLL_TID_EBX_REG	"D"
+#else
+# define LLL_TID_EBX_LOAD
+# define LLL_TID_EBX_REG	"b"
+#endif
+#define lll_wait_tid(tid) \
+  do {									      \
+    int __ignore;							      \
+    register __typeof (tid) _tid asm ("edx") = (tid);			      \
+    if (_tid != 0)							      \
+      __asm __volatile (LLL_TID_EBX_LOAD				      \
+			"1:\tmovl %1, %%eax\n\t"			      \
+			"int $0x80\n\t"					      \
+			"cmpl $0, (%%ebx)\n\t"				      \
+			"jne,pn 1b\n\t"					      \
+			LLL_TID_EBX_LOAD				      \
+			: "=&a" (__ignore)				      \
+			: "i" (SYS_futex), LLL_TID_EBX_REG (&tid), "S" (0),   \
+			  "c" (FUTEX_WAIT), "d" (_tid));		      \
+  } while (0)
+
+extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
+     __attribute__ ((regparm (2))) attribute_hidden;
+#define lll_timedwait_tid(tid, abstime) \
+  ({									      \
+    int __result = 0;							      \
+    if (tid != 0)							      \
+      {									      \
+	if (abstime == NULL || abstime->tv_nsec >= 1000000000)		      \
+	  __result = EINVAL;						      \
+	else								      \
+	  __result = __lll_timedwait_tid (&tid, abstime);		      \
+      }									      \
+    __result; })
+
+
+#define lll_wake_tid(tid) \
+  do {									      \
+    int __ignore;							      \
+    (tid) = 0;								      \
+    __asm __volatile (LLL_TID_EBX_LOAD					      \
+		      "\tint $0x80\n\t"					      \
+		      LLL_TID_EBX_LOAD					      \
+		      : "=a" (__ignore)					      \
+		      : "0" (SYS_futex), LLL_TID_EBX_REG (&(tid)), "S" (0),   \
+			"c" (FUTEX_WAKE), "d" (0x7fffffff));		      \
+  } while (0)
+
+
+/* Conditional variable handling.  */
+
+extern void __lll_cond_wait (pthread_cond_t *cond)
+     __attribute ((regparm (1))) attribute_hidden;
+extern int __lll_cond_timedwait (pthread_cond_t *cond,
+				 const struct timespec *abstime)
+     __attribute ((regparm (2))) attribute_hidden;
+extern void __lll_cond_wake (pthread_cond_t *cond)
+     __attribute ((regparm (1))) attribute_hidden;
+extern void __lll_cond_broadcast (pthread_cond_t *cond)
+     __attribute ((regparm (1))) attribute_hidden;
+
+
+#define lll_cond_wait(cond) \
+  __lll_cond_wait (cond)
+#define lll_cond_timedwait(cond, abstime) \
+  __lll_cond_timedwait (cond, abstime)
+#define lll_cond_wake(cond) \
+  __lll_cond_wake (cond)
+#define lll_cond_broadcast(cond) \
+  __lll_cond_broadcast (cond)
+
+
+#endif	/* lowlevellock.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h
new file mode 100644
index 0000000000..bd5f96402b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h
@@ -0,0 +1,101 @@
+/* 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.  */
+
+#ifndef _LOWLEVELSEM_H
+#define _LOWLEVELSEM_H	1
+
+#ifndef LOCK
+# ifdef UP
+#  define LOCK	/* nothing */
+# else
+#  define LOCK "lock;"
+# endif
+#endif
+
+#define SYS_futex		240
+
+
+#define lll_sem_wait(sem) \
+  ({ int result, ignore1, ignore2;					      \
+     __asm __volatile ("1:\tincl 8(%4)\n\t"				      \
+		       LOCK "incl (%4)\n\t"				      \
+		       "jng 2f\n"					      \
+		       ".subsection 1\n"				      \
+		       "2:\tmovl %4, %%eax\n\t"				      \
+		       "call __lll_unlock_wake\n\t"			      \
+		       "jmp 3f\n\t"					      \
+		       ".previous\n"					      \
+		       "3:\tpushl %%ebx\n\t"				      \
+		       "movl %%esi, %%ecx\n\t"				      \
+		       "movl %%esi, %%edx\n\t"				      \
+		       "leal 4(%4), %%ebx\n\t"				      \
+		       "movl %5, %%eax\n\t"				      \
+		       "int $0x80\n\t"					      \
+		       "movl %%eax, %%edx\n\t"				      \
+		       "popl %%ebx\n\t"					      \
+		       "orl $-1, %%eax\n\t"				      \
+		       LOCK "xaddl %%eax, (%4)\n\t"			      \
+		       "jne 4f\n\t"					      \
+		       ".subsection 1\n"				      \
+		       "4:\tmovl %4, %%ecx\n\t"				      \
+		       "call __lll_lock_wait\n\t"			      \
+		       "jmp 5f\n\t"					      \
+		       ".previous\n"					      \
+		       "5:\tdecl 8(%4)\n\t"				      \
+		       "xorl %0, %0\n\t"				      \
+		       "cmpl $0, 4(%4)\n\t"				      \
+		       "jne,pt 6f\n\t"					      \
+		       "cmpl %7, %%edx\n\t"				      \
+		       "jne,pn 1b\n\t"					      \
+		       "addl %8, %0\n\t" /* Shorter than movl %7, %0 */	      \
+		       "6:"						      \
+		       : "=a" (result), "=c" (ignore1), "=d" (ignore2),	      \
+			 "=m" (*sem)					      \
+		       : "D" (sem), "i" (SYS_futex), "S" (0),		      \
+			 "i" (-EINTR), "i" (EINTR));			      \
+     result; })
+
+
+extern int __lll_sem_timedwait (struct sem *sem, const struct timespec *ts)
+     __attribute__ ((regparm (2))) attribute_hidden;
+#define lll_sem_timedwait(sem, timeout) \
+  __lll_sem_timedwait (sem, timeout)
+
+
+#define lll_sem_post(sem) \
+  (void) ({ int ignore1, ignore2, ignore3;				      \
+	    __asm __volatile ("movl $1, %%eax\n\t"			      \
+			      LOCK					      \
+			      "xaddl %%eax, (%4)\n\t"			      \
+			      "pushl %%esi\n\t"				      \
+			      "pushl %%ebx\n\t"				      \
+			      "movl %4, %%ebx\n\t"			      \
+			      "leal 1(%%eax), %%edx\n\t"		      \
+			      "xorl %%esi, %%esi\n\t"			      \
+			      "movl %5, %%eax\n\t"			      \
+			      /* movl $FUTEX_WAKE, %ecx */		      \
+			      "movl $1, %%ecx\n\t"			      \
+			      "int $0x80\n\t"				      \
+			      "popl %%ebx\n\t"				      \
+			      "popl %%esi"				      \
+			      : "=&a" (ignore1), "=c" (ignore2),	      \
+				"=m" (*sem), "=d" (ignore3)		      \
+			      : "r" (sem), "i" (SYS_futex)); })
+
+#endif	/* lowlevelsem.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
new file mode 100644
index 0000000000..6994c0d7fa
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
@@ -0,0 +1,49 @@
+/* Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@gnu.org>.
+
+   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 _ERRNO_H	1
+#include <bits/errno.h>
+#include <kernel-features.h>
+
+/* Clone the calling process, but without copying the whole address space.
+   The calling process is suspended until the new process exits or is
+   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
+   and the process ID of the new process to the old process.  */
+
+ENTRY (__vfork)
+	/* Pop the return PC value into ECX.  */
+	popl	%ecx
+
+	/* Stuff the syscall number in EAX and enter into the kernel.  */
+	movl	$SYS_ify (vfork), %eax
+	int	$0x80
+
+	/* Jump to the return PC.  Don't jump directly since this
+	   disturbs the branch target cache.  Instead push the return
+	   address back on the stack.  */
+	pushl	%ecx
+
+	cmpl	$-4095, %eax
+	jae	SYSCALL_ERROR_LABEL	/* Branch forward if it failed.  */
+.Lpseudo_end:
+	ret
+PSEUDO_END (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S
new file mode 100644
index 0000000000..747c8ec2d2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S
@@ -0,0 +1,171 @@
+/* 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>
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+#define SYS_futex	240
+#define FUTEX_WAKE	1
+
+	.comm	__fork_generation, 4, 4
+
+	.text
+
+
+	.globl	__pthread_once
+	.type	__pthread_once,@function
+	.align	16
+__pthread_once:
+	movl	4(%esp), %ecx
+	testl	$2, (%ecx)
+	jz	1f
+	xorl	%eax, %eax
+	ret
+
+1:	pushl	%ebx
+	pushl	%esi
+	movl	%ecx, %ebx
+	xorl	%esi, %esi
+
+	/* Not yet initialized or initialization in progress.
+	   Get the fork generation counter now.  */
+6:	movl	(%ebx), %eax
+#ifdef PIC
+	call	__i686.get_pc_thunk.cx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
+#endif
+
+5:	movl	%eax, %edx
+
+	testl	$2, %eax
+	jnz	4f
+
+	andl	$3, %edx
+#ifdef PIC
+	orl	__fork_generation@GOTOFF(%ecx), %edx
+#else
+	orl	__fork_generation, %edx
+#endif
+	orl	$1, %edx
+
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jnz	5b
+
+	/* Check whether another thread already runs the initializer.  */
+	testl	$1, %eax
+	jz	3f	/* No -> do it.  */
+
+	/* Check whether the initializer execution was interrupted
+	   by a fork.  */
+	xorl	%edx, %eax
+	testl	$0xfffffffc, %eax
+	jnz	3f	/* Different for generation -> run initializer.  */
+
+	/* Somebody else got here first.  Wait.  */
+	movl	%esi, %ecx		/* movl $FUTEX_WAIT, %ecx */
+	movl	$SYS_futex, %eax
+	int	$0x80
+	jmp	6b
+
+3:	/* Call the initializer function after setting up the
+	   cancellation handler.  */
+	subl	$16, %esp
+
+	/* Push the cleanup handler.  */
+#ifdef PIC
+	leal	clear_once_control@GOTOFF(%ecx), %eax
+#else
+	leal	clear_once_control, %eax
+#endif
+	movl	%esp, %edx
+	pushl	%ebx
+	pushl	%eax
+	pushl	%edx
+	call	_GI_pthread_cleanup_push	/* Note: no @PLT.  */
+
+	movl	44(%esp), %eax
+	call	*%eax
+
+	/* Pop the cleanup handler.  This code depends on the once
+	   handler and _pthread_cleanup_push not touch the content
+	   of the stack.  Otherwise the first parameter would have
+	   to be reloaded.  */
+	movl	$0, 4(%esp)
+	call	_GI_pthread_cleanup_pop	/* Note: no @PLT.  */
+
+	addl	$28, %esp
+
+	/* Sucessful run of the initializer.  Signal that we are done.  */
+	LOCK
+	incl	(%ebx)
+
+	/* Wake up all other threads.  */
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+4:	popl	%esi
+	popl	%ebx
+	xorl	%eax, %eax
+	ret
+
+	.size	__pthread_once,.-__pthread_once
+
+	.globl	pthread_once
+pthread_once = __pthread_once
+
+
+	.type	clear_once_control,@function
+	.align	16
+clear_once_control:
+	pushl	%esi
+	pushl	%ebx
+
+	movl	4(%esp), %eax
+	movl	$0, (%eax)
+
+	xorl	%esi, %esi
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	clear_once_control,.-clear_once_control
+
+
+#ifdef PIC
+	.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