about summary refs log tree commit diff
path: root/nptl/sysdeps
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
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')
-rw-r--r--nptl/sysdeps/generic/lowlevellock.h89
-rw-r--r--nptl/sysdeps/generic/pt-raise.c30
-rw-r--r--nptl/sysdeps/i386/i686/bits/atomic.h340
-rw-r--r--nptl/sysdeps/i386/i686/pthread_spin_trylock.S34
-rw-r--r--nptl/sysdeps/i386/i686/tls.h36
-rw-r--r--nptl/sysdeps/i386/pthread_sigmask.c34
-rw-r--r--nptl/sysdeps/i386/pthread_spin_destroy.c29
-rw-r--r--nptl/sysdeps/i386/pthread_spin_init.c20
-rw-r--r--nptl/sysdeps/i386/pthread_spin_lock.c48
-rw-r--r--nptl/sysdeps/i386/pthread_spin_unlock.S32
-rw-r--r--nptl/sysdeps/i386/pthreaddef.h55
-rw-r--r--nptl/sysdeps/i386/tls.h332
-rw-r--r--nptl/sysdeps/pthread/Makefile33
-rw-r--r--nptl/sysdeps/pthread/Subdirs1
-rw-r--r--nptl/sysdeps/pthread/allocalim.h29
-rw-r--r--nptl/sysdeps/pthread/bits/libc-lock.h335
-rw-r--r--nptl/sysdeps/pthread/bits/sigthread.h38
-rw-r--r--nptl/sysdeps/pthread/list.h116
-rw-r--r--nptl/sysdeps/pthread/posix-timer.h210
-rw-r--r--nptl/sysdeps/pthread/pt-initfini.c124
-rw-r--r--nptl/sysdeps/pthread/pthread.h743
-rw-r--r--nptl/sysdeps/pthread/pthread_getcpuclockid.c43
-rw-r--r--nptl/sysdeps/pthread/pthread_once.c54
-rw-r--r--nptl/sysdeps/pthread/pthread_sigmask.c44
-rw-r--r--nptl/sysdeps/pthread/sigaction.c24
-rw-r--r--nptl/sysdeps/pthread/timer_create.c179
-rw-r--r--nptl/sysdeps/pthread/timer_delete.c70
-rw-r--r--nptl/sysdeps/pthread/timer_getoverr.c45
-rw-r--r--nptl/sysdeps/pthread/timer_gettime.c71
-rw-r--r--nptl/sysdeps/pthread/timer_routines.c592
-rw-r--r--nptl/sysdeps/pthread/timer_settime.c137
-rw-r--r--nptl/sysdeps/pthread/tst-timer.c114
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Implies1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Makefile24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Versions12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/allocrtsig.c54
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/local_lim.h80
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h144
-rw-r--r--nptl/sysdeps/unix/sysv/linux/configure3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork-gen.c37
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.c124
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.h60
-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
-rw-r--r--nptl/sysdeps/unix/sysv/linux/internaltypes.h130
-rw-r--r--nptl/sysdeps/unix/sysv/linux/jmp-unwind.c33
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pt-fork.c28
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pt-raise.c31
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_kill.c36
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_yield.c30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/raise.c39
-rw-r--r--nptl/sysdeps/unix/sysv/linux/register-atfork.c87
-rw-r--r--nptl/sysdeps/unix/sysv/linux/unregister-atfork.c49
77 files changed, 7901 insertions, 0 deletions
diff --git a/nptl/sysdeps/generic/lowlevellock.h b/nptl/sysdeps/generic/lowlevellock.h
new file mode 100644
index 0000000000..9cffca83e6
--- /dev/null
+++ b/nptl/sysdeps/generic/lowlevellock.h
@@ -0,0 +1,89 @@
+/* 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 <atomic.h>
+
+
+/* Implement generic mutex.  Basic futex syscall support is required:
+
+     lll_futex_wait(futex, value) - call sys_futex with FUTEX_WAIT
+				    and third parameter VALUE
+
+     lll_futex_wake(futex, value) - call sys_futex with FUTEX_WAKE
+				    and third parameter VALUE
+*/
+
+
+/* Mutex lock counter:
+   bit 31 clear means unlocked;
+   bit 31 set means locked.
+
+   All code that looks at bit 31 first increases the 'number of
+   interested threads' usage counter, which is in bits 0-30.
+
+   All negative mutex values indicate that the mutex is still locked.  */
+
+
+static inline void
+__generic_mutex_lock (int *mutex)
+{
+  unsigned int v;
+
+  /* Bit 31 was clear, we got the mutex.  (this is the fastpath).  */
+  if (atomic_bit_test_set (mutex, 31) == 0)
+    return;
+
+  atomic_increment (mutex);
+
+  while (1)
+    {
+      if (atomic_bit_test_set (mutex, 31) == 0)
+	{
+	  atomic_decrement (mutex);
+	  return;
+	}
+
+      /* We have to wait now. First make sure the futex value we are
+	 monitoring is truly negative (i.e. locked). */
+      v = *mutex;
+      if (v >= 0)
+	continue;
+
+      lll_futex_wait (mutex, v);
+    }
+}
+
+
+static inline void
+__generic_mutex_unlock (int *mutex)
+{
+  /* Adding 0x80000000 to the counter results in 0 if and only if
+     there are not other interested threads - we can return (this is
+     the fastpath).  */
+  if (atomic_add_zero (0x80000000, mutex))
+    return;
+
+  /* There are other threads waiting for this mutex, wake one of them
+     up.  */
+  lll_futex_wake (mutex, 1);
+}
+
+
+#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex))
+#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex))
diff --git a/nptl/sysdeps/generic/pt-raise.c b/nptl/sysdeps/generic/pt-raise.c
new file mode 100644
index 0000000000..59d9590e6e
--- /dev/null
+++ b/nptl/sysdeps/generic/pt-raise.c
@@ -0,0 +1,30 @@
+/* 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 <pthread.h>
+#include <signal.h>
+
+
+int
+raise (sig)
+     int sig;
+{
+  /* This is what POSIX says must happen.  */
+  return pthread_kill (pthread_self (), sig);
+}
diff --git a/nptl/sysdeps/i386/i686/bits/atomic.h b/nptl/sysdeps/i386/i686/bits/atomic.h
new file mode 100644
index 0000000000..7eb7573265
--- /dev/null
+++ b/nptl/sysdeps/i386/i686/bits/atomic.h
@@ -0,0 +1,340 @@
+/* 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 <stdint.h>
+
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int16_t atomic16_t;
+typedef uint16_t uatomic16_t;
+typedef int_fast16_t atomic_fast16_t;
+typedef uint_fast16_t uatomic_fast16_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+
+#ifndef LOCK
+# ifdef UP
+#  define LOCK	/* nothing */
+# else
+#  define LOCK "lock;"
+# endif
+#endif
+
+
+#define __arch_compare_and_exchange_8_acq(mem, newval, oldval) \
+  ({ unsigned char ret;							      \
+     __asm __volatile (LOCK "cmpxchgb %2, %1; setne %0"			      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "q" (newval), "1" (*mem), "0" (oldval));	      \
+     ret; })
+
+#define __arch_compare_and_exchange_16_acq(mem, newval, oldval) \
+  ({ unsigned char ret;							      \
+     __asm __volatile (LOCK "cmpxchgw %2, %1; setne %0"			      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "r" (newval), "1" (*mem), "0" (oldval));	      \
+     ret; })
+
+#define __arch_compare_and_exchange_32_acq(mem, newval, oldval) \
+  ({ unsigned char ret;							      \
+     __asm __volatile (LOCK "cmpxchgl %2, %1; setne %0"			      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "r" (newval), "1" (*mem), "0" (oldval));	      \
+     ret; })
+
+/* XXX We do not really need 64-bit compare-and-exchange.  At least
+   not in the moment.  Using it would mean causing portability
+   problems since not many other 32-bit architectures have support for
+   such an operation.  So don't define any code for now.  If it is
+   really going to be used the code below can be used.  */
+#if 1
+# define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
+  (abort (), 0)
+#else
+# ifdef __PIC__
+#  define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
+  ({ unsigned char ret;							      \
+     int ignore;							      \
+     __asm __volatile ("xchgl %3, %%ebx\n\t"				      \
+		       LOCK "cmpxchg8b %2, %1\n\t"			      \
+		       "setne %0\n\t"					      \
+		       "xchgl %3, %%ebx"				      \
+		       : "=a" (ret), "=m" (*mem), "=d" (ignore)		      \
+		       : "DS" (((unsigned long long int) (newval))	      \
+			       & 0xffffffff),				      \
+			 "c" (((unsigned long long int) (newval)) >> 32),     \
+			 "1" (*mem), "0" (((unsigned long long int) (oldval)) \
+					  & 0xffffffff),		      \
+			 "2" (((unsigned long long int) (oldval)) >> 32));    \
+     ret; })
+# else
+#  define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
+  ({ unsigned char ret;							      \
+     int ignore;							      \
+     __asm __volatile (LOCK "cmpxchg8b %2, %1; setne %0"		      \
+		       : "=a" (ret), "=m" (*mem), "=d" (ignore)		      \
+		       : "b" (((unsigned long long int) (newval))	      \
+			      & 0xffffffff),				      \
+			  "c" (((unsigned long long int) (newval)) >> 32),    \
+			 "1" (*mem), "0" (((unsigned long long int) (oldval)) \
+					  & 0xffffffff),		      \
+			 "2" (((unsigned long long int) (oldval)) >> 32));    \
+     ret; })
+# endif
+#endif
+
+
+#define atomic_exchange_and_add(mem, value) \
+  ({ __typeof (*mem) result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "xaddb %0, %1"				      \
+			 : "=r" (result), "=m" (*mem)			      \
+			 : "0" (value), "1" (*mem));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "xaddw %0, %1"				      \
+			 : "=r" (result), "=m" (*mem)			      \
+			 : "0" (value), "1" (*mem));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "xaddl %0, %1"				      \
+			 : "=r" (result), "=m" (*mem)			      \
+			 : "0" (value), "1" (*mem));			      \
+     else								      \
+       {								      \
+	 __typeof (value) addval = (value);				      \
+	 __typeof (*mem) oldval;					      \
+	 __typeof (mem) memp = (mem);					      \
+	 do								      \
+	   result = (oldval = *memp) + addval;				      \
+	 while (! __arch_compare_and_exchange_64_acq (memp, result, oldval)); \
+       }								      \
+     result; })
+
+
+#define atomic_add(mem, value) \
+  (void) ({ if (__builtin_constant_p (value) && (value) == 1)		      \
+	      atomic_increment (mem);					      \
+	    else if (__builtin_constant_p (value) && (value) == 1)	      \
+	      atomic_decrement (mem);					      \
+	    else if (sizeof (*mem) == 1)				      \
+	      __asm __volatile (LOCK "addb %1, %0"			      \
+				: "=m" (*mem)				      \
+				: "ir" (value), "0" (*mem));		      \
+	    else if (sizeof (*mem) == 2)				      \
+	      __asm __volatile (LOCK "addw %1, %0"			      \
+				: "=m" (*mem)				      \
+				: "ir" (value), "0" (*mem));		      \
+	    else if (sizeof (*mem) == 4)				      \
+	      __asm __volatile (LOCK "addl %1, %0"			      \
+				: "=m" (*mem)				      \
+				: "ir" (value), "0" (*mem));		      \
+	    else							      \
+	      {								      \
+		__typeof (value) addval = (value);			      \
+		__typeof (*mem) oldval;					      \
+		__typeof (mem) memp = (mem);				      \
+		do							      \
+		  oldval = *memp;					      \
+		while (! __arch_compare_and_exchange_64_acq (memp,	      \
+							     oldval + addval, \
+							     oldval));	      \
+	      }								      \
+	    })
+
+
+#define atomic_add_negative(mem, value) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "addb %2, %0; sets %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "addw %2, %0; sets %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "addl %2, %0; sets %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_add_zero(mem, value) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "addb %2, %0; setz %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "addw %2, %0; setz %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "addl %2, %0; setz %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "ir" (value), "0" (*mem));			      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_increment(mem) \
+  (void) ({ if (sizeof (*mem) == 1)					      \
+	      __asm __volatile (LOCK "incb %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else if (sizeof (*mem) == 2)				      \
+	      __asm __volatile (LOCK "incw %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else if (sizeof (*mem) == 4)				      \
+	      __asm __volatile (LOCK "incl %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else							      \
+	      {								      \
+		__typeof (*mem) oldval;					      \
+		__typeof (mem) memp = (mem);				      \
+		do							      \
+		  oldval = *memp;					      \
+		while (! __arch_compare_and_exchange_64_acq (memp,	      \
+							     oldval + 1,      \
+							     oldval));	      \
+	      }								      \
+	    })
+
+
+#define atomic_increment_and_test(mem) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "incb %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "incw %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "incl %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_decrement(mem) \
+  (void) ({ if (sizeof (*mem) == 1)					      \
+	      __asm __volatile (LOCK "decb %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else if (sizeof (*mem) == 2)				      \
+	      __asm __volatile (LOCK "decw %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else if (sizeof (*mem) == 4)				      \
+	      __asm __volatile (LOCK "decl %0"				      \
+				: "=m" (*mem)				      \
+				: "0" (*mem));				      \
+	    else							      \
+	      {								      \
+		__typeof (*mem) oldval;					      \
+		__typeof (mem) memp = (mem);				      \
+		do							      \
+		  oldval = *memp;					      \
+		while (! __arch_compare_and_exchange_64_acq (memp,	      \
+							     oldval - 1,      \
+							     oldval));	      \
+	      }								      \
+	    })
+
+
+#define atomic_decrement_and_test(mem) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "decb %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "decw %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "decl %0; sete %1"			      \
+			 : "=m" (*mem), "=qm" (__result)		      \
+			 : "0" (*mem));					      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_bit_set(mem, bit) \
+  (void) ({ if (sizeof (*mem) == 1)					      \
+	      __asm __volatile (LOCK "orb %2, %0"			      \
+				: "=m" (*mem)				      \
+				: "0" (*mem), "i" (1 << (bit)));	      \
+	    else if (sizeof (*mem) == 2)				      \
+	      __asm __volatile (LOCK "orw %2, %0"			      \
+				: "=m" (*mem)				      \
+				: "0" (*mem), "i" (1 << (bit)));	      \
+	    else if (sizeof (*mem) == 4)				      \
+	      __asm __volatile (LOCK "orl %2, %0"			      \
+				: "=m" (*mem)				      \
+				: "0" (*mem), "i" (1 << (bit)));	      \
+	    else							      \
+	      abort ();							      \
+	    })
+
+
+#define atomic_bit_test_set(mem, bit) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile (LOCK "btsb %3, %1; setc %0"			      \
+			 : "=q" (__result), "=m" (*mem)			      \
+			 : "1" (*mem), "i" (bit));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile (LOCK "btsw %3, %1; setc %0"			      \
+			 : "=q" (__result), "=m" (*mem)			      \
+			 : "1" (*mem), "i" (bit));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile (LOCK "btsl %3, %1; setc %0"			      \
+			 : "=q" (__result), "=m" (*mem)			      \
+			 : "1" (*mem), "i" (bit));			      \
+     else							      	      \
+       abort ();							      \
+     __result; })
diff --git a/nptl/sysdeps/i386/i686/pthread_spin_trylock.S b/nptl/sysdeps/i386/i686/pthread_spin_trylock.S
new file mode 100644
index 0000000000..881976c4fe
--- /dev/null
+++ b/nptl/sysdeps/i386/i686/pthread_spin_trylock.S
@@ -0,0 +1,34 @@
+/* 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.  */
+
+#define EBUSY	16
+
+	.globl	pthread_spin_trylock
+	.type	pthread_spin_trylock,@function
+	.align	16
+pthread_spin_trylock:
+	movl	4(%esp), %edx
+	movl	$1, %eax
+	xorl	%ecx, %ecx
+	cmpxchgl %ecx, (%edx)
+	movl	$EBUSY, %ecx
+	movl	$0, %eax
+	cmovne	%ecx, %eax
+	ret
+	.size	pthread_spin_trylock,.-pthread_spin_trylock
diff --git a/nptl/sysdeps/i386/i686/tls.h b/nptl/sysdeps/i386/i686/tls.h
new file mode 100644
index 0000000000..4025ed8d21
--- /dev/null
+++ b/nptl/sysdeps/i386/i686/tls.h
@@ -0,0 +1,36 @@
+/* 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 _TLS_H
+
+/* Additional definitions for <tls.h> on i686 and up.  */
+
+
+/* Macros to load from and store into segment registers.  We can use
+   the 32-bit instructions.  */
+#define TLS_GET_GS() \
+  ({ int __seg; __asm ("movl %%gs, %0" : "=q" (__seg)); __seg; })
+#define TLS_SET_GS(val) \
+  __asm ("movl %0, %%gs" :: "q" (val))
+
+
+/* Get the full set of definitions.  */
+#include "../tls.h"
+
+#endif	/* tls.h */
diff --git a/nptl/sysdeps/i386/pthread_sigmask.c b/nptl/sysdeps/i386/pthread_sigmask.c
new file mode 100644
index 0000000000..2ae9198c02
--- /dev/null
+++ b/nptl/sysdeps/i386/pthread_sigmask.c
@@ -0,0 +1,34 @@
+/* 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 <errno.h>
+#include <signal.h>
+#include <pthreadP.h>
+#include <tls.h>
+#include <sysdep.h>
+
+
+int
+pthread_sigmask (how, newmask, oldmask)
+     int how;
+     const sigset_t *newmask;
+     sigset_t *oldmask;
+{
+  return INLINE_SYSCALL (sigprocmask, 3, how, newmask, oldmask);
+}
diff --git a/nptl/sysdeps/i386/pthread_spin_destroy.c b/nptl/sysdeps/i386/pthread_spin_destroy.c
new file mode 100644
index 0000000000..4d0109cf02
--- /dev/null
+++ b/nptl/sysdeps/i386/pthread_spin_destroy.c
@@ -0,0 +1,29 @@
+/* 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 "pthreadP.h"
+
+
+int
+pthread_spin_destroy (lock)
+     pthread_spinlock_t *lock;
+{
+  /* Nothing to do.  */
+  return 0;
+}
diff --git a/nptl/sysdeps/i386/pthread_spin_init.c b/nptl/sysdeps/i386/pthread_spin_init.c
new file mode 100644
index 0000000000..0a47981aa2
--- /dev/null
+++ b/nptl/sysdeps/i386/pthread_spin_init.c
@@ -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.  */
+
+/* Not needed.  pthread_spin_init is an alias for pthread_spin_unlock.  */
diff --git a/nptl/sysdeps/i386/pthread_spin_lock.c b/nptl/sysdeps/i386/pthread_spin_lock.c
new file mode 100644
index 0000000000..43a1831131
--- /dev/null
+++ b/nptl/sysdeps/i386/pthread_spin_lock.c
@@ -0,0 +1,48 @@
+/* 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 "pthreadP.h"
+
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK "lock;"
+#endif
+
+
+int
+pthread_spin_lock (lock)
+     pthread_spinlock_t *lock;
+{
+  asm ("\n"
+       "1:\t" LOCK "decl %0\n\t"
+       "jne 2f\n\t"
+       ".subsection 1\n\t"
+       ".align 16\n"
+       "2:\trep; nop\n\t"
+       "cmpl $0, %0\n\t"
+       "jg 1b\n\t"
+       "jmp 2b\n\t"
+       ".previous"
+       : "=m" (*lock)
+       : "0" (*lock));
+
+  return 0;
+}
diff --git a/nptl/sysdeps/i386/pthread_spin_unlock.S b/nptl/sysdeps/i386/pthread_spin_unlock.S
new file mode 100644
index 0000000000..d94f1e7b8c
--- /dev/null
+++ b/nptl/sysdeps/i386/pthread_spin_unlock.S
@@ -0,0 +1,32 @@
+/* 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.  */
+
+	.globl	pthread_spin_unlock
+	.type	pthread_spin_unlock,@function
+	.align	16
+pthread_spin_unlock:
+	movl	4(%esp), %eax
+	movl	$1, (%eax)
+	xorl	%eax, %eax
+	ret
+	.size	pthread_spin_unlock,.-pthread_spin_unlock
+
+	/* The implementation of pthread_spin_init is identical.  */
+	.globl	pthread_spin_init
+pthread_spin_init = pthread_spin_unlock
diff --git a/nptl/sysdeps/i386/pthreaddef.h b/nptl/sysdeps/i386/pthreaddef.h
new file mode 100644
index 0000000000..6efa1b6d82
--- /dev/null
+++ b/nptl/sysdeps/i386/pthreaddef.h
@@ -0,0 +1,55 @@
+/* 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.  */
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  SSE requires 16
+   bytes.  */
+#define STACK_ALIGN		16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	2048
+
+/* Alignment requirement for TCB.  */
+#define TCB_ALIGNMENT		16
+
+/* The signal used for asynchronous cancelation.  */
+#define SIGCANCEL		__SIGRTMIN
+
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME	__builtin_frame_address (0)
+
+
+/* XXX Until we have a better place keep the definitions here.  */
+
+/* While there is no such syscall.  */
+#define __exit_thread_inline(val) \
+  while (1) {								      \
+    if (__builtin_constant_p (val) && (val) == 0)			      \
+      asm volatile ("xorl %%ebx, %%ebx; int $0x80" :: "a" (__NR_exit));	      \
+    else								      \
+      asm volatile ("movl %1, %%ebx; int $0x80"				      \
+		    :: "a" (__NR_exit), "r" (val));			      \
+  }
+#define gettid()							      \
+  ({ int tid;								      \
+     __asm __volatile ("int $0x80" : "=a" (tid) : "0" (__NR_gettid));	      \
+     tid; })
diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h
new file mode 100644
index 0000000000..244a487bcb
--- /dev/null
+++ b/nptl/sysdeps/i386/tls.h
@@ -0,0 +1,332 @@
+/* Definition for thread-local data handling.  linuxthreads/i386 version.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _TLS_H
+#define _TLS_H	1
+
+#ifndef __ASSEMBLER__
+# include <stddef.h>
+# include <stdint.h>
+
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+} tcbhead_t;
+#endif
+
+
+/* We require TLS support in the tools.  */
+#ifndef HAVE_TLS_SUPPORT
+# error "TLS support is required."
+#endif
+
+/* Signal that TLS support is available.  */
+#define USE_TLS	1
+
+/* Alignment requirement for the stack.  For IA-32 this is govern by
+   the SSE memory functions.  */
+#define STACK_ALIGN	16
+
+
+#ifndef __ASSEMBLER__
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* The old way: using LDT.  */
+
+/* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls.  */
+struct user_desc
+{
+  unsigned int entry_number;
+  unsigned long int base_addr;
+  unsigned int limit;
+  unsigned int seg_32bit:1;
+  unsigned int contents:2;
+  unsigned int read_exec_only:1;
+  unsigned int limit_in_pages:1;
+  unsigned int seg_not_present:1;
+  unsigned int useable:1;
+  unsigned int empty:25;
+};
+
+/* Initializing bit fields is slow.  We speed it up by using a union.  */
+union user_desc_init
+{
+  struct user_desc desc;
+  unsigned int vals[4];
+};
+
+
+/* Get the thread descriptor definition.  */
+# include <nptl/descr.h>
+
+/* This is the size of the initial TCB.  */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+# define TLS_TCB_SIZE sizeof (struct pthread)
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+/* The TCB can have any size and the memory following the address the
+   thread pointer points to is unspecified.  Allocate the TCB there.  */
+# define TLS_TCB_AT_TP	1
+
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+# define INSTALL_DTV(descr, dtvp) \
+  ((tcbhead_t *) (descr))->dtv = dtvp + 1
+
+/* Install new dtv for current thread.  */
+# define INSTALL_NEW_DTV(dtv) \
+  ({ struct pthread *__pd;						      \
+     THREAD_SETMEM (__pd, header.data.dtvp, dtv); })
+
+/* Return dtv of given thread descriptor.  */
+# define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+
+/* Macros to load from and store into segment registers.  */
+# ifndef TLS_GET_GS
+#  define TLS_GET_GS() \
+  ({ int __seg; __asm ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; })
+# endif
+# ifndef TLS_SET_GS
+#  define TLS_SET_GS(val) \
+  __asm ("movw %w0, %%gs" :: "q" (val))
+# endif
+
+
+# ifndef __NR_set_thread_area
+#  define __NR_set_thread_area 243
+# endif
+# ifndef TLS_FLAG_WRITABLE
+#  define TLS_FLAG_WRITABLE		0x00000001
+# endif
+
+// XXX Enable for the real world.
+#if 0
+# ifndef __ASSUME_SET_THREAD_AREA
+#  error "we need set_thread_area"
+# endif
+#endif
+
+# ifdef __PIC__
+#  define TLS_EBX_ARG "r"
+#  define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
+# else
+#  define TLS_EBX_ARG "b"
+#  define TLS_LOAD_EBX
+# endif
+
+/* Code to initially initialize the thread pointer.  This might need
+   special attention since 'errno' is not yet available and if the
+   operation can cause a failure 'errno' must not be touched.  */
+# define TLS_INIT_TP(thrdescr, secondcall) \
+  ({ void *_thrdescr = (thrdescr);					      \
+     tcbhead_t *_head = _thrdescr;					      \
+     union user_desc_init _segdescr;					      \
+     int _result;							      \
+									      \
+     _head->tcb = _thrdescr;						      \
+     /* For now the thread descriptor is at the same address.  */	      \
+     _head->self = _thrdescr;						      \
+									      \
+     /* The 'entry_number' field.  Let the kernel pick a value.  */	      \
+     if (secondcall)							      \
+       _segdescr.vals[0] = TLS_GET_GS () >> 3;				      \
+     else								      \
+       _segdescr.vals[0] = -1;						      \
+     /* The 'base_addr' field.  Pointer to the TCB.  */			      \
+     _segdescr.vals[1] = (unsigned long int) _thrdescr;			      \
+     /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */	      \
+     _segdescr.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 */						      \
+     _segdescr.vals[3] = 0x51;						      \
+									      \
+     /* Install the TLS.  */						      \
+     asm volatile (TLS_LOAD_EBX						      \
+		   "int $0x80\n\t"					      \
+		   TLS_LOAD_EBX						      \
+		   : "=a" (_result), "=m" (_segdescr.desc.entry_number)	      \
+		   : "0" (__NR_set_thread_area),			      \
+		     TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc));    \
+									      \
+     if (_result == 0)							      \
+       /* We know the index in the GDT, now load the segment register.	      \
+	  The use of the GDT is described by the value 3 in the lower	      \
+	  three bits of the segment descriptor value.			      \
+									      \
+	  Note that we have to do this even if the numeric value of	      \
+	  the descriptor does not change.  Loading the segment register	      \
+	  causes the segment information from the GDT to be loaded	      \
+	  which is necessary since we have changed it.   */		      \
+       TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3);		      \
+									      \
+     _result; })
+
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+  ({ struct pthread *__pd;						      \
+     THREAD_GETMEM (__pd, header.data.dtvp); })
+
+
+/* Return the thread descriptor for the current thread.
+
+   The contained asm must *not* be marked volatile since otherwise
+   assignments like
+        pthread_descr self = thread_self();
+   do not get optimized away.  */
+# define THREAD_SELF \
+  ({ struct pthread *__self;						      \
+     asm ("movl %%gs:%c1,%0" : "=r" (__self)				      \
+	  : "i" (offsetof (struct pthread, header.data.self))); 	      \
+     __self;})
+
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) \
+  ({ __typeof (descr->member) __value;					      \
+     if (sizeof (__value) == 1)						      \
+       asm ("movb %%gs:%P2,%b0"						      \
+	    : "=q" (__value)						      \
+	    : "0" (0), "i" (offsetof (struct pthread, member)));	      \
+     else if (sizeof (__value) == 4)					      \
+       asm ("movl %%gs:%P1,%0"						      \
+	    : "=r" (__value)						      \
+	    : "i" (offsetof (struct pthread, member)));			      \
+     else								      \
+       {								      \
+	 if (sizeof (__value) != 8)					      \
+	   /* There should not be any value with a size other than 1,	      \
+	      4 or 8.  */						      \
+	   abort ();							      \
+									      \
+	 asm ("movl %%gs:%P1,%%eax\n\t"					      \
+	      "movl %%gs:%P2,%%edx"					      \
+	      : "=A" (__value)						      \
+	      : "i" (offsetof (struct pthread, member)),		      \
+		"i" (offsetof (struct pthread, member) + 4));		      \
+       }								      \
+     __value; })
+
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+# define THREAD_GETMEM_NC(descr, member) \
+  ({ __typeof (descr->member) __value;					      \
+     if (sizeof (__value) == 1)						      \
+       asm ("movb %%gs:(%2),%b0"					      \
+	    : "=q" (__value)						      \
+	    : "0" (0), "r" (offsetof (struct pthread, member)));	      \
+     else if (sizeof (__value) == 4)					      \
+       asm ("movl %%gs:(%1),%0"						      \
+	    : "=r" (__value)						      \
+	    : "r" (offsetof (struct pthread, member)));			      \
+     else								      \
+       {								      \
+	 if (sizeof (__value) != 8)					      \
+	   /* There should not be any value with a size other than 1,	      \
+	      4 or 8.  */						      \
+	   abort ();							      \
+									      \
+	 asm ("movl %%gs:(%1),%%eax\n\t"				      \
+	      "movl %%gs:4(%1),%%edx"					      \
+	      : "=&A" (__value)						      \
+	      : "r" (offsetof (struct pthread, member)));		      \
+       }								      \
+     __value; })
+
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM(descr, member, value) \
+  ({ if (sizeof (value) == 1)						      \
+       asm volatile ("movb %0,%%gs:%P1" :				      \
+		     : "iq" (value),					      \
+		       "i" (offsetof (struct pthread, member)));	      \
+     else if (sizeof (value) == 4)					      \
+       asm volatile ("movl %0,%%gs:%P1" :				      \
+		     : "ir" (value),					      \
+		       "i" (offsetof (struct pthread, member)));	      \
+     else								      \
+       {								      \
+	 if (sizeof (value) != 8)					      \
+	   /* There should not be any value with a size other than 1,	      \
+	      4 or 8.  */						      \
+	   abort ();							      \
+									      \
+	 asm volatile ("movl %%eax,%%gs:%P1\n\n"			      \
+		       "movl %%edx,%%gs:%P2" :				      \
+		       : "A" (value),					      \
+			 "i" (offsetof (struct pthread, member)),	      \
+			 "i" (offsetof (struct pthread, member) + 4));	      \
+       }})
+
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM_NC(descr, member, value) \
+  ({ if (sizeof (value) == 1)						      \
+       asm volatile ("movb %0,%%gs:(%1)" :				      \
+		     : "iq" (value),					      \
+		       "r" (offsetof (struct pthread, member)));	      \
+     else if (sizeof (value) == 4)					      \
+       asm volatile ("movl %0,%%gs:(%1)" :				      \
+		     : "ir" (value),					      \
+		       "r" (offsetof (struct pthread, member)));	      \
+     else								      \
+       {								      \
+	 if (sizeof (value) != 8)					      \
+	   /* There should not be any value with a size other than 1,	      \
+	      4 or 8.  */						      \
+	   abort ();							      \
+									      \
+	 asm volatile ("movl %%eax,%%gs:(%1)\n\t"			      \
+		       "movl %%edx,%%gs:4(%1)" :			      \
+		       : "A" (value),					      \
+			 "r" (offsetof (struct pthread, member)));	      \
+       }})
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff --git a/nptl/sysdeps/pthread/Makefile b/nptl/sysdeps/pthread/Makefile
new file mode 100644
index 0000000000..fade787877
--- /dev/null
+++ b/nptl/sysdeps/pthread/Makefile
@@ -0,0 +1,33 @@
+# 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.
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += errno-loc
+endif
+
+ifeq ($(subdir),rt)
+librt-sysdep_routines += timer_routines
+CPPFLAGS-timer_routines.c = -I../nptl
+
+ifeq (yes,$(build-shared))
+$(objpfx)tst-timer: $(objpfx)librt.so $(shared-thread-library)
+else
+$(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library)
+endif
+endif
diff --git a/nptl/sysdeps/pthread/Subdirs b/nptl/sysdeps/pthread/Subdirs
new file mode 100644
index 0000000000..4d1f4d876b
--- /dev/null
+++ b/nptl/sysdeps/pthread/Subdirs
@@ -0,0 +1 @@
+nptl_db
diff --git a/nptl/sysdeps/pthread/allocalim.h b/nptl/sysdeps/pthread/allocalim.h
new file mode 100644
index 0000000000..2d666c0b0a
--- /dev/null
+++ b/nptl/sysdeps/pthread/allocalim.h
@@ -0,0 +1,29 @@
+/* Determine whether block of given size can be allocated on the stack or not.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <alloca.h>
+#include <limits.h>
+
+
+extern inline int
+__libc_use_alloca (size_t size)
+{
+  return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1)
+	  || __libc_alloca_cutoff (size));
+}
diff --git a/nptl/sysdeps/pthread/bits/libc-lock.h b/nptl/sysdeps/pthread/bits/libc-lock.h
new file mode 100644
index 0000000000..0001676a3b
--- /dev/null
+++ b/nptl/sysdeps/pthread/bits/libc-lock.h
@@ -0,0 +1,335 @@
+/* libc-internal interface for mutex locks.  LinuxThreads version.
+   Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_LIBC_LOCK_H
+#define _BITS_LIBC_LOCK_H 1
+
+#include <pthread.h>
+#define __need_NULL
+#include <stddef.h>
+
+/* Mutex type.  */
+#if defined(_LIBC) || defined(_IO_MTSAFE_IO)
+typedef pthread_mutex_t __libc_lock_t;
+typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
+# ifdef __USE_UNIX98
+typedef pthread_rwlock_t __libc_rwlock_t;
+# else
+typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
+# endif
+#else
+typedef struct __libc_lock_opaque__ __libc_lock_t;
+typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
+typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
+#endif
+
+/* Type for key to thread-specific data.  */
+typedef pthread_key_t __libc_key_t;
+
+/* Define a lock variable NAME with storage class CLASS.  The lock must be
+   initialized with __libc_lock_init before it can be used (or define it
+   with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
+   declare a lock defined in another module.  In public structure
+   definitions you must use a pointer to the lock structure (i.e., NAME
+   begins with a `*'), because its storage size will not be known outside
+   of libc.  */
+#define __libc_lock_define(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#define __libc_rwlock_define(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME;
+#define __libc_lock_define_recursive(CLASS,NAME) \
+  CLASS __libc_lock_recursive_t NAME;
+
+/* Define an initialized lock variable NAME with storage class CLASS.
+
+   For the C library we take a deeper look at the initializer.  For
+   this implementation all fields are initialized to zero.  Therefore
+   we don't initialize the variable which allows putting it into the
+   BSS section.  (Except on PA-RISC and other odd architectures, where
+   initialized locks must be set to one due to the lack of normal
+   atomic operations.) */
+
+#if __LT_SPINLOCK_INIT == 0
+#  define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#else
+#  define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#define __libc_rwlock_define_initialized(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+
+/* Define an initialized recursive lock variable NAME with storage
+   class CLASS.  */
+#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
+#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
+  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+   state.  */
+#define __libc_lock_init(NAME) \
+  (__pthread_mutex_init != NULL ? __pthread_mutex_init (&(NAME), NULL) : 0);
+#define __libc_rwlock_init(NAME) \
+  (__pthread_rwlock_init != NULL ? __pthread_rwlock_init (&(NAME), NULL) : 0);
+
+/* Same as last but this time we initialize a recursive mutex.  */
+#define __libc_lock_init_recursive(NAME) \
+  do {									      \
+    if (__pthread_mutex_init != NULL)					      \
+      {									      \
+	pthread_mutexattr_t __attr;					      \
+	__pthread_mutexattr_init (&__attr);				      \
+	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
+	__pthread_mutex_init (&(NAME).mutex, &__attr);			      \
+	__pthread_mutexattr_destroy (&__attr);				      \
+      }									      \
+  } while (0);
+
+/* Finalize the named lock variable, which must be locked.  It cannot be
+   used again until __libc_lock_init is called again on it.  This must be
+   called on a lock variable before the containing storage is reused.  */
+#define __libc_lock_fini(NAME) \
+  (__pthread_mutex_destroy != NULL ? __pthread_mutex_destroy (&(NAME)) : 0);
+#define __libc_rwlock_fini(NAME) \
+  (__pthread_rwlock_destroy != NULL ? __pthread_rwlock_destroy (&(NAME)) : 0);
+
+/* Finalize recursive named lock.  */
+#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
+
+/* Lock the named lock variable.  */
+#define __libc_lock_lock(NAME) \
+  (__pthread_mutex_lock != NULL ? __pthread_mutex_lock (&(NAME)) : 0);
+#define __libc_rwlock_rdlock(NAME) \
+  (__pthread_rwlock_rdlock != NULL ? __pthread_rwlock_rdlock (&(NAME)) : 0);
+#define __libc_rwlock_wrlock(NAME) \
+  (__pthread_rwlock_wrlock != NULL ? __pthread_rwlock_wrlock (&(NAME)) : 0);
+
+/* Lock the recursive named lock variable.  */
+#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
+
+/* Try to lock the named lock variable.  */
+#define __libc_lock_trylock(NAME) \
+  (__pthread_mutex_trylock != NULL ? __pthread_mutex_trylock (&(NAME)) : 0)
+#define __libc_rwlock_tryrdlock(NAME) \
+  (__pthread_rwlock_tryrdlock != NULL \
+   ? __pthread_rwlock_tryrdlock (&(NAME)) : 0)
+#define __libc_rwlock_trywrlock(NAME) \
+  (__pthread_rwlock_trywrlock != NULL \
+   ? __pthread_rwlock_trywrlock (&(NAME)) : 0)
+
+/* Try to lock the recursive named lock variable.  */
+#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
+
+/* Unlock the named lock variable.  */
+#define __libc_lock_unlock(NAME) \
+  (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (&(NAME)) : 0);
+#define __libc_rwlock_unlock(NAME) \
+  (__pthread_rwlock_unlock != NULL ? __pthread_rwlock_unlock (&(NAME)) : 0);
+
+/* Unlock the recursive named lock variable.  */
+#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
+
+
+/* Define once control variable.  */
+#if PTHREAD_ONCE_INIT == 0
+/* Special case for static variables where we can avoid the initialization
+   if it is zero.  */
+# define __libc_once_define(CLASS, NAME) \
+  CLASS pthread_once_t NAME
+#else
+# define __libc_once_define(CLASS, NAME) \
+  CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
+#endif
+
+/* Call handler iff the first call.  */
+#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
+  do {									      \
+    if (__pthread_once != NULL)						      \
+      __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION));		      \
+    else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \
+      INIT_FUNCTION ();							      \
+      (ONCE_CONTROL) = !PTHREAD_ONCE_INIT;				      \
+    }									      \
+  } while (0)
+
+
+/* Start critical region with cleanup.  */
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL;		      \
+    if (_avail) {							      \
+      _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG));		      \
+    }
+
+/* End critical region with cleanup.  */
+#define __libc_cleanup_region_end(DOIT) \
+    if (_avail) {							      \
+      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+    }									      \
+  }
+
+/* Sometimes we have to exit the block in the middle.  */
+#define __libc_cleanup_end(DOIT) \
+    if (_avail) {							      \
+      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+    }
+
+/* Create thread-specific key.  */
+#define __libc_key_create(KEY, DESTRUCTOR) \
+  (__pthread_key_create != NULL ? __pthread_key_create (KEY, DESTRUCTOR) : 1)
+
+/* Get thread-specific data.  */
+#define __libc_getspecific(KEY) \
+  (__pthread_getspecific != NULL ? __pthread_getspecific (KEY) : NULL)
+
+/* Set thread-specific data.  */
+#define __libc_setspecific(KEY, VALUE) \
+  (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0)
+
+
+/* Register handlers to execute before and after `fork'.  Note that the
+   last parameter is NULL.  The handlers registered by the libc are
+   never removed so this is OK.  */
+#define __libc_atfork(PREPARE, PARENT, CHILD) \
+  __register_atfork (PREPARE, PARENT, CHILD, NULL)
+extern int __register_atfork (void (*__prepare) (void),
+			      void (*__parent) (void),
+			      void (*__child) (void),
+			      void *__dso_handle);
+
+/* Functions that are used by this file and are internal to the GNU C
+   library.  */
+
+extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
+				 __const pthread_mutexattr_t *__mutex_attr);
+
+extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
+
+extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
+
+extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
+					int __kind);
+
+#ifdef __USE_UNIX98
+extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
+				  __const pthread_rwlockattr_t *__attr);
+
+extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
+#endif
+
+extern int __pthread_key_create (pthread_key_t *__key,
+				 void (*__destr_function) (void *));
+
+extern int __pthread_setspecific (pthread_key_t __key,
+				  __const void *__pointer);
+
+extern void *__pthread_getspecific (pthread_key_t __key);
+
+extern int __pthread_once (pthread_once_t *__once_control,
+			   void (*__init_routine) (void));
+
+extern int __pthread_atfork (void (*__prepare) (void),
+			     void (*__parent) (void),
+			     void (*__child) (void));
+
+
+
+/* Make the pthread functions weak so that we can elide them from
+   single-threaded processes.  */
+#ifndef __NO_WEAK_PTHREAD_ALIASES
+# ifdef weak_extern
+#  if _LIBC
+#   include <bp-sym.h>
+#  else
+#   define BP_SYM (sym) sym
+#  endif
+weak_extern (BP_SYM (__pthread_mutex_init))
+weak_extern (BP_SYM (__pthread_mutex_destroy))
+weak_extern (BP_SYM (__pthread_mutex_lock))
+weak_extern (BP_SYM (__pthread_mutex_trylock))
+weak_extern (BP_SYM (__pthread_mutex_unlock))
+weak_extern (BP_SYM (__pthread_mutexattr_init))
+weak_extern (BP_SYM (__pthread_mutexattr_destroy))
+weak_extern (BP_SYM (__pthread_mutexattr_settype))
+weak_extern (BP_SYM (__pthread_rwlock_init))
+weak_extern (BP_SYM (__pthread_rwlock_destroy))
+weak_extern (BP_SYM (__pthread_rwlock_rdlock))
+weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
+weak_extern (BP_SYM (__pthread_rwlock_wrlock))
+weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
+weak_extern (BP_SYM (__pthread_rwlock_unlock))
+weak_extern (BP_SYM (__pthread_key_create))
+weak_extern (BP_SYM (__pthread_setspecific))
+weak_extern (BP_SYM (__pthread_getspecific))
+weak_extern (BP_SYM (__pthread_once))
+weak_extern (__pthread_initialize)
+weak_extern (__pthread_atfork)
+weak_extern (BP_SYM (_pthread_cleanup_push_defer))
+weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
+# else
+#  pragma weak __pthread_mutex_init
+#  pragma weak __pthread_mutex_destroy
+#  pragma weak __pthread_mutex_lock
+#  pragma weak __pthread_mutex_trylock
+#  pragma weak __pthread_mutex_unlock
+#  pragma weak __pthread_mutexattr_init
+#  pragma weak __pthread_mutexattr_destroy
+#  pragma weak __pthread_mutexattr_settype
+#  pragma weak __pthread_rwlock_destroy
+#  pragma weak __pthread_rwlock_rdlock
+#  pragma weak __pthread_rwlock_tryrdlock
+#  pragma weak __pthread_rwlock_wrlock
+#  pragma weak __pthread_rwlock_trywrlock
+#  pragma weak __pthread_rwlock_unlock
+#  pragma weak __pthread_key_create
+#  pragma weak __pthread_setspecific
+#  pragma weak __pthread_getspecific
+#  pragma weak __pthread_once
+#  pragma weak __pthread_initialize
+#  pragma weak __pthread_atfork
+#  pragma weak _pthread_cleanup_push_defer
+#  pragma weak _pthread_cleanup_pop_restore
+# endif
+#endif
+
+/* We need portable names for some functions.  E.g., when they are
+   used as argument to __libc_cleanup_region_start.  */
+#define __libc_mutex_unlock __pthread_mutex_unlock
+
+#endif	/* bits/libc-lock.h */
diff --git a/nptl/sysdeps/pthread/bits/sigthread.h b/nptl/sysdeps/pthread/bits/sigthread.h
new file mode 100644
index 0000000000..df2bcac291
--- /dev/null
+++ b/nptl/sysdeps/pthread/bits/sigthread.h
@@ -0,0 +1,38 @@
+/* Signal handling function for threaded programs.
+   Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_SIGTHREAD_H
+#define _BITS_SIGTHREAD_H	1
+
+#if !defined _SIGNAL_H && !defined _PTHREAD_H
+# error "Never include this file directly.  Use <pthread.h> instead"
+#endif
+
+/* Functions for handling signals. */
+
+/* Modify the signal mask for the calling thread.  The arguments have
+   the same meaning as for sigprocmask(2). */
+extern int pthread_sigmask (int __how,
+			    __const __sigset_t *__restrict __newmask,
+			    __sigset_t *__restrict __oldmask)__THROW;
+
+/* Send signal SIGNO to the given thread. */
+extern int pthread_kill (pthread_t __threadid, int __signo) __THROW;
+
+#endif	/* bits/sigthread.h */
diff --git a/nptl/sysdeps/pthread/list.h b/nptl/sysdeps/pthread/list.h
new file mode 100644
index 0000000000..1d6a4cfa65
--- /dev/null
+++ b/nptl/sysdeps/pthread/list.h
@@ -0,0 +1,116 @@
+/* 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 _LIST_H
+#define _LIST_H	1
+
+#include <assert.h>
+
+/* The definitions of this file are adopted from those which can be
+   found in the Linux kernel headers to enable people familiar with
+   the latter find their way in these sources as well.  */
+
+
+/* Basic type for the double-link list.  */
+typedef struct list_head
+{
+  struct list_head *next;
+  struct list_head *prev;
+} list_t;
+
+
+/* Define a variable with the head and tail of the list.  */
+#define LIST_HEAD(name) \
+  list_t name = { &(name), &(name) }
+
+/* Initialize a new list head.  */
+#define INIT_LIST_HEAD(ptr) \
+  (ptr)->next = (ptr)->prev = (ptr)
+
+
+/* Add new element at the head of the list.  */
+static inline void
+list_add (list_t *newp, list_t *head)
+{
+  head->next->prev = newp;
+  newp->next = head->next;
+  newp->prev = head;
+  head->next = newp;
+}
+
+
+/* Add new element at the tail of the list.  */
+static inline void
+list_add_tail (list_t *newp, list_t *head)
+{
+  head->prev->next = newp;
+  newp->next = head;
+  newp->prev = head->prev;
+  head->prev = newp;
+}
+
+
+/* Remove element from list.  */
+static inline void
+list_del (list_t *elem)
+{
+  elem->next->prev = elem->prev;
+  elem->prev->next = elem->next;
+}
+
+
+/* Join two lists.  */
+static inline void
+list_splice (list_t *add, list_t *head)
+{
+  /* Do nothing if the list which gets added is empty.  */
+  if (add != add->next)
+    {
+      add->next->prev = head;
+      add->prev->next = head->next;
+      head->next->prev = add->prev;
+      head->next = add->next;
+    }
+}
+
+
+/* Get typed element from list at a given position.  */
+#define list_entry(ptr, type, member) \
+  ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)))
+
+
+
+/* Iterate forward over the elements of the list.  */
+#define list_for_each(pos, head) \
+  for (pos = (head)->next; pos != (head); pos = pos->next)
+
+
+/* Iterate forward over the elements of the list.  */
+#define list_for_each_prev(pos, head) \
+  for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+
+/* Iterate backwards over the elements list.  The list elements can be
+   removed from the list while doing this.  */
+#define list_for_each_prev_safe(pos, p, head) \
+  for (pos = (head)->prev, p = pos->prev; \
+       pos != (head); \
+       pos = p, p = pos->prev)
+
+#endif	/* list.h */
diff --git a/nptl/sysdeps/pthread/posix-timer.h b/nptl/sysdeps/pthread/posix-timer.h
new file mode 100644
index 0000000000..6710291b9b
--- /dev/null
+++ b/nptl/sysdeps/pthread/posix-timer.h
@@ -0,0 +1,210 @@
+/* Definitions for POSIX timer implementation on top of LinuxThreads.
+   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <limits.h>
+#include <signal.h>
+
+/* Double linked list.  */
+struct list_links
+{
+  struct list_links *next;
+  struct list_links *prev;
+};
+
+
+/* Forward declaration.  */
+struct timer_node;
+
+
+/* Definitions for an internal thread of the POSIX timer implementation.  */
+struct thread_node
+{
+  struct list_links links;
+  pthread_attr_t attr;
+  pthread_t id;
+  unsigned int exists;
+  struct list_links timer_queue;
+  pthread_cond_t cond;
+  struct timer_node *current_timer;
+  pthread_t captured;
+  clockid_t clock_id;
+};
+
+
+/* Internal representation of a timer.  */
+struct timer_node
+{
+  struct list_links links;
+  struct sigevent event;
+  clockid_t clock;
+  struct itimerspec value;
+  struct timespec expirytime;
+  pthread_attr_t attr;
+  unsigned int abstime;
+  unsigned int armed;
+  enum {
+    TIMER_FREE, TIMER_INUSE, TIMER_DELETED
+  } inuse;
+  struct thread_node *thread;
+  pid_t creator_pid;
+  int refcount;
+  int overrun_count;
+};
+
+
+/* Static array with the structures for all the timers.  */
+extern struct timer_node __timer_array[TIMER_MAX];
+
+/* Global lock to protect operation on the lists.  */
+extern pthread_mutex_t __timer_mutex;
+
+/* Variable to protext initialization.  */
+extern pthread_once_t __timer_init_once_control;
+
+/* Nonzero if initialization of timer implementation failed.  */
+extern int __timer_init_failed;
+
+/* Nodes for the threads used to deliver signals.  */
+/* A distinct thread is used for each clock type.  */
+
+extern struct thread_node __timer_signal_thread_rclk;
+#ifdef _POSIX_CPUTIME
+extern struct thread_node __timer_signal_thread_pclk;
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+extern struct thread_node __timer_signal_thread_tclk;
+#endif
+
+
+/* Return pointer to timer structure corresponding to ID.  */
+static inline struct timer_node *
+timer_id2ptr (timer_t timerid)
+{
+  if (timerid >= 0 && timerid < TIMER_MAX)
+    return &__timer_array[timerid];
+
+  return NULL;
+}
+
+/* Return ID of TIMER.  */
+static inline int
+timer_ptr2id (struct timer_node *timer)
+{
+  return timer - __timer_array;
+}
+
+/* Check whether timer is valid; global mutex must be held. */
+static inline int
+timer_valid (struct timer_node *timer)
+{
+  return timer && timer->inuse == TIMER_INUSE;
+}
+
+/* Timer refcount functions; need global mutex. */
+extern void __timer_dealloc (struct timer_node *timer);
+
+static inline void
+timer_addref (struct timer_node *timer)
+{
+  timer->refcount++;
+}
+
+static inline void
+timer_delref (struct timer_node *timer)
+{
+  if (--timer->refcount == 0)
+    __timer_dealloc (timer);
+}
+
+/* Timespec helper routines.  */
+static inline int
+timespec_compare (const struct timespec *left, const struct timespec *right)
+{
+  if (left->tv_sec < right->tv_sec)
+    return -1;
+  if (left->tv_sec > right->tv_sec)
+    return 1;
+
+  if (left->tv_nsec < right->tv_nsec)
+    return -1;
+  if (left->tv_nsec > right->tv_nsec)
+    return 1;
+
+  return 0;
+}
+
+static inline void
+timespec_add (struct timespec *sum, const struct timespec *left,
+	      const struct timespec *right)
+{
+  sum->tv_sec = left->tv_sec + right->tv_sec;
+  sum->tv_nsec = left->tv_nsec + right->tv_nsec;
+
+  if (sum->tv_nsec >= 1000000000)
+    {
+      ++sum->tv_sec;
+      sum->tv_nsec -= 1000000000;
+    }
+}
+
+static inline void
+timespec_sub (struct timespec *diff, const struct timespec *left,
+	      const struct timespec *right)
+{
+  diff->tv_sec = left->tv_sec - right->tv_sec;
+  diff->tv_nsec = left->tv_nsec - right->tv_nsec;
+
+  if (diff->tv_nsec < 0)
+    {
+      --diff->tv_sec;
+      diff->tv_nsec += 1000000000;
+    }
+}
+
+
+/* We need one of the list functions in the other modules.  */
+static inline void
+list_unlink_ip (struct list_links *list)
+{
+  struct list_links *lnext = list->next, *lprev = list->prev;
+
+  lnext->prev = lprev;
+  lprev->next = lnext;
+
+  /* The suffix ip means idempotent; list_unlink_ip can be called
+   * two or more times on the same node.
+   */
+
+  list->next = list;
+  list->prev = list;
+}
+
+
+/* Functions in the helper file.  */
+extern void __timer_mutex_cancel_handler (void *arg);
+extern void __timer_init_once (void);
+extern struct timer_node *__timer_alloc (void);
+extern int __timer_thread_start (struct thread_node *thread);
+extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
+extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
+extern void __timer_thread_dealloc (struct thread_node *thread);
+extern int __timer_thread_queue_timer (struct thread_node *thread,
+				       struct timer_node *insert);
+extern void __timer_thread_wakeup (struct thread_node *thread);
diff --git a/nptl/sysdeps/pthread/pt-initfini.c b/nptl/sysdeps/pthread/pt-initfini.c
new file mode 100644
index 0000000000..55d9f31562
--- /dev/null
+++ b/nptl/sysdeps/pthread/pt-initfini.c
@@ -0,0 +1,124 @@
+/* Special .init and .fini section support.  Linuxthread version.
+   Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Library General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file.  (The Library General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   The GNU C Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This file is compiled into assembly code which is then munged by a sed
+   script into two files: crti.s and crtn.s.
+
+   * crti.s puts a function prologue at the beginning of the
+   .init and .fini sections and defines global symbols for
+   those addresses, so they can be called as functions.
+
+   * crtn.s puts the corresponding function epilogues
+   in the .init and .fini sections. */
+
+#include <stdlib.h>
+
+/* We use embedded asm for .section unconditionally, as this makes it
+   easier to insert the necessary directives into crtn.S. */
+#define SECTION(x) asm (".section " x )
+
+/* Embed an #include to pull in the alignment and .end directives. */
+asm ("\n#include \"defs.h\"");
+
+/* The initial common code ends here. */
+asm ("\n/*@HEADER_ENDS*/");
+
+/* To determine whether we need .end and .align: */
+asm ("\n/*@TESTS_BEGIN*/");
+extern void dummy (void (*foo) (void));
+void
+dummy (void (*foo) (void))
+{
+  if (foo)
+    (*foo) ();
+}
+asm ("\n/*@TESTS_END*/");
+
+/* The beginning of _init:  */
+asm ("\n/*@_init_PROLOG_BEGINS*/");
+
+static void
+call_initialize_minimal (void)
+{
+  extern void __pthread_initialize_minimal (void);
+
+  __pthread_initialize_minimal ();
+}
+
+SECTION (".init");
+extern void _init (void);
+void
+_init (void)
+{
+  /* The very first thing we must do is to set up the registers.  */
+  call_initialize_minimal ();
+
+  asm ("ALIGN");
+  asm("END_INIT");
+  /* Now the epilog. */
+  asm ("\n/*@_init_PROLOG_ENDS*/");
+  asm ("\n/*@_init_EPILOG_BEGINS*/");
+  SECTION(".init");
+}
+asm ("END_INIT");
+
+/* End of the _init epilog, beginning of the _fini prolog. */
+asm ("\n/*@_init_EPILOG_ENDS*/");
+asm ("\n/*@_fini_PROLOG_BEGINS*/");
+
+SECTION (".fini");
+extern void _fini (void);
+void
+_fini (void)
+{
+
+  /* End of the _fini prolog. */
+  asm ("ALIGN");
+  asm ("END_FINI");
+  asm ("\n/*@_fini_PROLOG_ENDS*/");
+
+  {
+    /* Let GCC know that _fini is not a leaf function by having a dummy
+       function call here.  We arrange for this call to be omitted from
+       either crt file.  */
+    extern void i_am_not_a_leaf (void);
+    i_am_not_a_leaf ();
+  }
+
+  /* Beginning of the _fini epilog. */
+  asm ("\n/*@_fini_EPILOG_BEGINS*/");
+  SECTION (".fini");
+}
+asm ("END_FINI");
+
+/* End of the _fini epilog.  Any further generated assembly (e.g. .ident)
+   is shared between both crt files. */
+asm ("\n/*@_fini_EPILOG_ENDS*/");
+asm ("\n/*@TRAILER_BEGINS*/");
+
+/* End of file. */
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
new file mode 100644
index 0000000000..d6b0966d40
--- /dev/null
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -0,0 +1,743 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _PTHREAD_H
+#define _PTHREAD_H	1
+
+#include <features.h>
+#include <sched.h>
+#include <time.h>
+
+#define __need_sigset_t
+#include <signal.h>
+#include <bits/pthreadtypes.h>
+
+
+/* Detach state.  */
+enum
+{
+  PTHREAD_CREATE_JOINABLE,
+#define PTHREAD_CREATE_JOINABLE	PTHREAD_CREATE_JOINABLE
+  PTHREAD_CREATE_DETACHED
+#define PTHREAD_CREATE_DETACHED	PTHREAD_CREATE_DETACHED
+};
+
+
+/* Mutex handling.  */
+
+#define PTHREAD_MUTEX_INITIALIZER \
+  { }
+
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
+  { .__data = { .__kind = PTHREAD_MUTEX_RECURSIVE_NP } }
+
+#define PTHREAD_RWLOCK_INITIALIZER \
+  { }
+
+#define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+  { .__data = { .__flags = PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } }
+
+enum
+{
+  PTHREAD_MUTEX_TIMED_NP,
+  PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_ADAPTIVE_NP
+#ifdef __USE_UNIX98
+  ,
+  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
+  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+#endif
+#ifdef __USE_GNU
+  /* For compatibility.  */
+  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
+#endif
+};
+
+
+/* Read-write lock types.  */
+#ifdef __USE_UNIX98
+enum
+{
+  PTHREAD_RWLOCK_PREFER_READER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+  PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP
+};
+#endif  /* Unix98 */
+
+
+/* Scheduler inheritance.  */
+enum
+{
+  PTHREAD_INHERIT_SCHED,
+#define PTHREAD_INHERIT_SCHED   PTHREAD_INHERIT_SCHED
+  PTHREAD_EXPLICIT_SCHED
+#define PTHREAD_EXPLICIT_SCHED  PTHREAD_EXPLICIT_SCHED
+};
+
+
+/* Scope handling.  */
+enum
+{
+  PTHREAD_SCOPE_SYSTEM,
+#define PTHREAD_SCOPE_SYSTEM    PTHREAD_SCOPE_SYSTEM
+  PTHREAD_SCOPE_PROCESS
+#define PTHREAD_SCOPE_PROCESS   PTHREAD_SCOPE_PROCESS
+};
+
+
+/* Process shared or private flag.  */
+enum
+{
+  PTHREAD_PROCESS_PRIVATE,
+#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
+  PTHREAD_PROCESS_SHARED
+#define PTHREAD_PROCESS_SHARED  PTHREAD_PROCESS_SHARED
+};
+
+
+
+/* Conditional variable handling.  */
+#define PTHREAD_COND_INITIALIZER { }
+
+
+/* Cleanup buffers */
+struct _pthread_cleanup_buffer
+{
+  void (*__routine) (void *);             /* Function to call.  */
+  void *__arg;                            /* Its argument.  */
+  int __canceltype;                       /* Saved cancellation type. */
+  struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions.  */
+};
+
+/* Cancellation */
+enum
+{
+  PTHREAD_CANCEL_ENABLE,
+#define PTHREAD_CANCEL_ENABLE   PTHREAD_CANCEL_ENABLE
+  PTHREAD_CANCEL_DISABLE
+#define PTHREAD_CANCEL_DISABLE  PTHREAD_CANCEL_DISABLE
+};
+enum
+{
+  PTHREAD_CANCEL_DEFERRED,
+#define PTHREAD_CANCEL_DEFERRED	PTHREAD_CANCEL_DEFERRED
+  PTHREAD_CANCEL_ASYNCHRONOUS
+#define PTHREAD_CANCEL_ASYNCHRONOUS	PTHREAD_CANCEL_ASYNCHRONOUS
+};
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/* Single execution handling.  */
+#define PTHREAD_ONCE_INIT 0
+
+
+#ifdef __USE_XOPEN2K
+/* Value returned by 'pthread_barrier_wait' for one of the threads after
+   the required number of threads have called this function.
+   -1 is distinct from 0 and all errno constants */
+# define PTHREAD_BARRIER_SERIAL_THREAD -1
+#endif
+
+
+__BEGIN_DECLS
+
+/* Create a new thread, starting with execution of START-ROUTINE
+   getting passed ARG.  Creation attributed come from ATTR.  The new
+   handle is stored in *NEWTHREAD.  */
+extern int pthread_create (pthread_t *__restrict __newthread,
+			   __const pthread_attr_t *__restrict __attr,
+			   void *(*__start_routine) (void *),
+			   void *__restrict __arg) __THROW;
+
+/* Terminate calling thread.  */
+extern void pthread_exit (void *__retval)
+     __THROW __attribute__ ((__noreturn__));
+
+/* Make calling thread wait for termination of the thread TH.  The
+   exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
+   is not NULL.  */
+extern int pthread_join (pthread_t __th, void **__thread_return) __THROW;
+
+#ifdef __USE_GNU
+/* Check whether thread TH has terminated.  If yes return the status of
+   the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL.  */
+extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
+
+/* Make calling thread wait for termination of the thread TH, but only
+   until TIMEOUT.  The exit status of the thread is stored in
+   *THREAD_RETURN, if THREAD_RETURN is not NULL.  */
+extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
+				 __const struct timespec *__abstime) __THROW;
+#endif
+
+/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
+   The resources of TH will therefore be freed immediately when it
+   terminates, instead of waiting for another thread to perform PTHREAD_JOIN
+   on it.  */
+extern int pthread_detach (pthread_t __th) __THROW;
+
+
+/* Obtain the identifier of the current thread.  */
+extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__));
+
+/* Compare two thread identifiers.  */
+extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW;
+
+
+/* Thread attribute handling.  */
+
+/* Initialize thread attribute *ATTR with default attributes
+   (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
+    no user-provided stack).  */
+extern int pthread_attr_init (pthread_attr_t *__attr) __THROW;
+
+/* Destroy thread attribute *ATTR.  */
+extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW;
+
+/* Get detach state attribute.  */
+extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr,
+					int *__detachstate) __THROW;
+
+/* Set detach state attribute.  */
+extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
+					int __detachstate) __THROW;
+
+
+/* Get the size of the guard area created for stack overflow protection.  */
+extern int pthread_attr_getguardsize (__const pthread_attr_t *__attr,
+				      size_t *__guardsize) __THROW;
+
+/* Set the size of the guard area created for stack overflow protection.  */
+extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
+				      size_t __guardsize) __THROW;
+
+
+/* Return in *PARAM the scheduling parameters of *ATTR.  */
+extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict
+				       __attr,
+				       struct sched_param *__restrict __param)
+     __THROW;
+
+/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM.  */
+extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
+				       __const struct sched_param *__restrict
+				       __param) __THROW;
+
+/* Return in *POLICY the scheduling policy of *ATTR.  */
+extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict
+					__attr, int *__restrict __policy)
+     __THROW;
+
+/* Set scheduling policy in *ATTR according to POLICY.  */
+extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
+     __THROW;
+
+/* Return in *INHERIT the scheduling inheritance mode of *ATTR.  */
+extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict
+					 __attr, int *__restrict __inherit)
+     __THROW;
+
+/* Set scheduling inheritance mode in *ATTR according to INHERIT.  */
+extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
+					 int __inherit) __THROW;
+
+
+/* Return in *SCOPE the scheduling contention scope of *ATTR.  */
+extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr,
+				  int *__restrict __scope) __THROW;
+
+/* Set scheduling contention scope in *ATTR according to SCOPE.  */
+extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
+     __THROW;
+
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict
+				      __attr, void **__restrict __stackaddr)
+     __THROW;
+
+/* Set the starting address of the stack of the thread to be created.
+   Depending on whether the stack grows up or down the value must either
+   be higher or lower than all the address in the memory block.  The
+   minimal size of the block must be PTHREAD_STACK_SIZE.  */
+extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
+				      void *__stackaddr) __THROW;
+
+/* Return the currently used minimal stack size.  */
+extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict
+				      __attr, size_t *__restrict __stacksize)
+     __THROW;
+
+/* Add information about the minimum stack size needed for the thread
+   to be started.  This size must never be less than PTHREAD_STACK_SIZE
+   and must also not exceed the system limits.  */
+extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
+				      size_t __stacksize) __THROW;
+
+#ifdef __USE_XOPEN2K
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr,
+				  void **__restrict __stackaddr,
+				  size_t *__restrict __stacksize) __THROW;
+
+/* The following two interfaces are intended to replace the last two.  They
+   require setting the address as well as the size since only setting the
+   address will make the implementation on some architectures impossible.  */
+extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
+				  size_t __stacksize) __THROW;
+#endif
+
+#ifdef __USE_GNU
+/* Get thread attributes corresponding to the already running thread TH.  */
+extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW;
+#endif
+
+
+/* Functions for scheduling control.  */
+
+/* Set the scheduling parameters for TARGET_THREAD according to POLICY
+   and *PARAM.  */
+extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
+				  __const struct sched_param *__param)
+     __THROW;
+
+/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */
+extern int pthread_getschedparam (pthread_t __target_thread,
+				  int *__restrict __policy,
+				  struct sched_param *__restrict __param)
+     __THROW;
+
+
+#ifdef __USE_UNIX98
+/* Determine level of concurrency.  */
+extern int pthread_getconcurrency (void) __THROW;
+
+/* Set new concurrency level to LEVEL.  */
+extern int pthread_setconcurrency (int __level) __THROW;
+#endif
+
+#ifdef __USE_GNU
+/* Yield the processor to another thread or process.
+   This function is similar to the POSIX `sched_yield' function but
+   might be differently implemented in the case of a m-on-n thread
+   implementation.  */
+extern int pthread_yield (void) __THROW;
+#endif
+
+
+/* Functions for handling initialization.  */
+
+/* Guarantee that the initialization function INIT_ROUTINE will be called
+   only once, even if pthread_once is executed several times with the
+   same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
+   extern variable initialized to PTHREAD_ONCE_INIT.  */
+extern int pthread_once (pthread_once_t *__once_control,
+			 void (*__init_routine) (void)) __THROW;
+
+
+/* Functions for handling cancellation.  */
+
+/* Set cancelability state of current thread to STATE, returning old
+   state in *OLDSTATE if OLDSTATE is not NULL.  */
+extern int pthread_setcancelstate (int __state, int *__oldstate) __THROW;
+
+/* Set cancellation state of current thread to TYPE, returning the old
+   type in *OLDTYPE if OLDTYPE is not NULL.  */
+extern int pthread_setcanceltype (int __type, int *__oldtype) __THROW;
+
+/* Cancel THREAD immediately or at the next possibility.  */
+extern int pthread_cancel (pthread_t __th) __THROW;
+
+/* Test for pending cancellation for the current thread and terminate
+   the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
+   cancelled.  */
+extern void pthread_testcancel (void) __THROW;
+
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+   when the thread is cancelled or calls pthread_exit.  ROUTINE will also
+   be called with arguments ARG when the matching pthread_cleanup_pop
+   is executed with non-zero EXECUTE argument.
+
+   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+   be used in matching pairs at the same nesting level of braces.  */
+#define pthread_cleanup_push(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+				   void (*__routine) (void *), void *__arg)
+     __THROW;
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+   If EXECUTE is non-zero, the handler function is called. */
+#define pthread_cleanup_pop(execute) \
+    _pthread_cleanup_pop (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+				  int __execute) __THROW;
+
+#ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and sets it to deferred
+   cancellation.  */
+# define pthread_cleanup_push_defer_np(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+					 void (*__routine) (void *),
+					 void *__arg) __THROW;
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+   restores the cancellation type that was in effect when the matching
+   pthread_cleanup_push_defer was called.  */
+# define pthread_cleanup_pop_restore_np(execute) \
+  _pthread_cleanup_pop_restore (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+					  int __execute) __THROW;
+#endif
+
+
+/* Mutex handling.  */
+
+/* Initialize a mutex.  */
+extern int pthread_mutex_init (pthread_mutex_t *__mutex,
+			       __const pthread_mutexattr_t *__mutexattr)
+     __THROW;
+
+/* Destroy a mutex.  */
+extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW;
+
+/* Try locking a mutex.  */
+extern int pthread_mutex_trylock (pthread_mutex_t *_mutex) __THROW;
+
+/* Lock a mutex.  */
+extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW;
+
+#ifdef __USE_XOPEN2K
+/* Wait until lock becomes available, or specified time passes. */
+extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
+                                    __const struct timespec *__restrict
+                                    __abstime) __THROW;
+#endif
+
+/* Unlock a mutex.  */
+extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW;
+
+
+/* Functions for handling mutex attributes.  */
+
+/* Initialize mutex attribute object ATTR with default attributes
+   (kind is PTHREAD_MUTEX_TIMED_NP).  */
+extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW;
+
+/* Destroy mutex attribute object ATTR.  */
+extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW;
+
+/* Get the process-shared flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t *
+					 __restrict __attr,
+					 int *__restrict __pshared) __THROW;
+
+/* Set the process-shared flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
+					 int __pshared) __THROW;
+
+#ifdef __USE_UNIX98
+/* Return in *KIND the mutex kind attribute in *ATTR.  */
+extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
+				      __attr, int *__restrict __kind) __THROW;
+
+/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
+   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
+   PTHREAD_MUTEX_DEFAULT).  */
+extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
+     __THROW;
+#endif
+
+
+#ifdef __USE_UNIX98
+/* Functions for handling read-write locks.  */
+
+/* Initialize read-write lock RWLOCK using attributes ATTR, or use
+   the default values if later is NULL.  */
+extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
+				__const pthread_rwlockattr_t *__restrict
+				__attr) __THROW;
+
+/* Destroy read-write lock RWLOCK.  */
+extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Acquire read lock for RWLOCK.  */
+extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Try to acquire read lock for RWLOCK.  */
+extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW;
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire read lock for RWLOCK or return after specfied time.  */
+extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
+				       __const struct timespec *__restrict
+				       __abstime) __THROW;
+# endif
+
+/* Acquire write lock for RWLOCK.  */
+extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Try to acquire write lock for RWLOCK.  */
+extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW;
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire write lock for RWLOCK or return after specfied time.  */
+extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
+				       __const struct timespec *__restrict
+				       __abstime) __THROW;
+# endif
+
+/* Unlock RWLOCK.  */
+extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW;
+
+
+/* Functions for handling read-write lock attributes.  */
+
+/* Initialize attribute object ATTR with default values.  */
+extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW;
+
+/* Destroy attribute object ATTR.  */
+extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW;
+
+/* Return current setting of process-shared attribute of ATTR in PSHARED.  */
+extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t *
+					  __restrict __attr,
+					  int *__restrict __pshared) __THROW;
+
+/* Set process-shared attribute of ATTR to PSHARED.  */
+extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
+					  int __pshared) __THROW;
+
+/* Return current setting of reader/writer preference.  */
+extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *
+					  __restrict __attr,
+					  int *__restrict __pref) __THROW;
+
+/* Set reader/write preference.  */
+extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
+					  int __pref) __THROW;
+#endif
+
+
+/* Functions for handling conditional variables.  */
+
+/* Initialize condition variable COND using attributes ATTR, or use
+   the default values if later is NULL.  */
+extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
+			      __const pthread_condattr_t *__restrict
+			      __cond_attr) __THROW;
+
+/* Destroy condition variable COND.  */
+extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW;
+
+/* Wake up one thread waiting for condition variable COND.  */
+extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW;
+
+/* Wake up all threads waiting for condition variables COND.  */
+extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW;
+
+/* Wait for condition variable COND to be signaled or broadcast.
+   MUTEX is assumed to be locked before.  */
+extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
+			      pthread_mutex_t *__restrict __mutex) __THROW;
+
+/* Wait for condition variable COND to be signaled or broadcast until
+   ABSTIME.  MUTEX is assumed to be locked before.  ABSTIME is an
+   absolute time specification; zero is the beginning of the epoch
+   (00:00:00 GMT, January 1, 1970).  */
+extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
+				   pthread_mutex_t *__restrict __mutex,
+				   __const struct timespec *__restrict
+				   __abstime) __THROW;
+
+/* Functions for handling condition variable attributes.  */
+
+/* Initialize condition variable attribute ATTR.  */
+extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW;
+
+/* Destroy condition variable attribute ATTR.  */
+extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW;
+
+/* Get the process-shared flag of the condition variable attribute ATTR.  */
+extern int pthread_condattr_getpshared (__const pthread_condattr_t *
+                                        __restrict __attr,
+                                        int *__restrict __pshared) __THROW;
+
+/* Set the process-shared flag of the condition variable attribute ATTR.  */
+extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
+                                        int __pshared) __THROW;
+
+
+
+#ifdef __USE_XOPEN2K
+/* Functions to handle spinlocks.  */
+
+/* Initialize the spinlock LOCK.  If PSHARED is nonzero the spinlock can
+   be shared between different processes.  */
+extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
+     __THROW;
+
+/* Destroy the spinlock LOCK.  */
+extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW;
+
+/* Wait until spinlock LOCK is retrieved.  */
+extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW;
+
+/* Try to lock spinlock LOCK.  */
+extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW;
+
+/* Release spinlock LOCK.  */
+extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW;
+
+
+/* Functions to handle barriers.  */
+
+/* Initialize BARRIER with the attributes in ATTR.  The barrier is
+   opened when COUNT waiters arrived.  */
+extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
+				 __const pthread_barrierattr_t *__restrict
+				 __attr, unsigned int __count) __THROW;
+
+/* Destroy a previously dynamically initialized barrier BARRIER.  */
+extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW;
+
+/* Wait on barrier BARRIER.  */
+extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW;
+
+
+/* Initialize barrier attribute ATTR.  */
+extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW;
+
+/* Destroy previously dynamically initialized barrier attribute ATTR.  */
+extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW;
+
+/* Get the process-shared flag of the barrier attribute ATTR.  */
+extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t *
+					   __restrict __attr,
+					   int *__restrict __pshared) __THROW;
+
+/* Set the process-shared flag of the barrier attribute ATTR.  */
+extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
+                                           int __pshared) __THROW;
+#endif
+
+
+/* Functions for handling thread-specific data.  */
+
+/* Create a key value identifying a location in the thread-specific
+   data area.  Each thread maintains a distinct thread-specific data
+   area.  DESTR_FUNCTION, if non-NULL, is called with the value
+   associated to that key when the key is destroyed.
+   DESTR_FUNCTION is not called if the value associated is NULL when
+   the key is destroyed.  */
+extern int pthread_key_create (pthread_key_t *__key,
+			       void (*__destr_function) (void *)) __THROW;
+
+/* Destroy KEY.  */
+extern int pthread_key_delete (pthread_key_t __key) __THROW;
+
+/* Return current value of the thread-specific data slot identified by KEY.  */
+extern void *pthread_getspecific (pthread_key_t __key) __THROW;
+
+/* Store POINTER in the thread-specific data slot identified by KEY. */
+extern int pthread_setspecific (pthread_key_t __key,
+				__const void *__pointer) __THROW;
+
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+   when the thread is cancelled or calls pthread_exit.  ROUTINE will also
+   be called with arguments ARG when the matching pthread_cleanup_pop
+   is executed with non-zero EXECUTE argument.
+   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+   be used in matching pairs at the same nesting level of braces. */
+#define pthread_cleanup_push(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+				   void (*__routine) (void *),
+				   void *__arg) __THROW;
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+   If EXECUTE is non-zero, the handler function is called. */
+#define pthread_cleanup_pop(execute) \
+    _pthread_cleanup_pop (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+				  int __execute) __THROW;
+
+
+#ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and set it to deferred cancellation.  */
+# define pthread_cleanup_push_defer_np(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+					 void (*__routine) (void *),
+					 void *__arg) __THROW;
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+   restores the cancellation type that was in effect when the matching
+   pthread_cleanup_push_defer was called.  */
+# define pthread_cleanup_pop_restore_np(execute) \
+  _pthread_cleanup_pop_restore (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+					  int __execute) __THROW;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* Get ID of CPU-time clock for thread THREAD_ID.  */
+extern int pthread_getcpuclockid (pthread_t __thread_id,
+				  clockid_t *__clock_id) __THROW;
+#endif
+
+
+/* Install handlers to be called when a new process is created with FORK.
+   The PREPARE handler is called in the parent process just before performing
+   FORK. The PARENT handler is called in the parent process just after FORK.
+   The CHILD handler is called in the child process.  Each of the three
+   handlers can be NULL, meaning that no handler needs to be called at that
+   point.
+   PTHREAD_ATFORK can be called several times, in which case the PREPARE
+   handlers are called in LIFO order (last added with PTHREAD_ATFORK,
+   first called before FORK), and the PARENT and CHILD handlers are called
+   in FIFO (first added, first called).  */
+
+extern int pthread_atfork (void (*__prepare) (void),
+			   void (*__parent) (void),
+			   void (*__child) (void)) __THROW;
+
+__END_DECLS
+
+#endif	/* pthread.h */
diff --git a/nptl/sysdeps/pthread/pthread_getcpuclockid.c b/nptl/sysdeps/pthread/pthread_getcpuclockid.c
new file mode 100644
index 0000000000..62761f9d7a
--- /dev/null
+++ b/nptl/sysdeps/pthread/pthread_getcpuclockid.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <tls.h>
+
+
+int
+pthread_getcpuclockid (thread_id, clock_id)
+     pthread_t thread_id;
+     clockid_t *clock_id;
+{
+  /* We don't allow any process ID but our own.  */
+  if ((struct pthread *) thread_id != THREAD_SELF)
+    return EPERM;
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+  /* Store the number.  */
+  *clock_id = CLOCK_THREAD_CPUTIME_ID;
+
+  return 0;
+#else
+  /* We don't have a timer for that.  */
+  return ENOENT;
+#endif
+}
diff --git a/nptl/sysdeps/pthread/pthread_once.c b/nptl/sysdeps/pthread/pthread_once.c
new file mode 100644
index 0000000000..9b2cef8645
--- /dev/null
+++ b/nptl/sysdeps/pthread/pthread_once.c
@@ -0,0 +1,54 @@
+/* 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 "pthreadP.h"
+#include <lowlevellock.h>
+
+
+
+static lll_lock_t once_lock = LLL_LOCK_INITIALIZER;
+
+
+int
+__pthread_once (once_control, init_routine)
+     pthread_once_t *once_control;
+     void (*init_routine) (void);
+{
+  /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a
+     global lock variable or one which is part of the pthread_once_t
+     object.  */
+  if (*once_control == PTHREAD_ONCE_INIT)
+    {
+      lll_lock (once_lock);
+
+      /* XXX This implementation is not complete.  It doesn't take
+	 cancelation and fork into account.  */
+      if (*once_control == PTHREAD_ONCE_INIT)
+	{
+	  init_routine ();
+
+	  *once_control = !PTHREAD_ONCE_INIT;
+	}
+
+      lll_unlock (once_lock);
+    }
+
+  return 0;
+}
+strong_alias (__pthread_once, pthread_once)
diff --git a/nptl/sysdeps/pthread/pthread_sigmask.c b/nptl/sysdeps/pthread/pthread_sigmask.c
new file mode 100644
index 0000000000..8ec7cf81ee
--- /dev/null
+++ b/nptl/sysdeps/pthread/pthread_sigmask.c
@@ -0,0 +1,44 @@
+/* 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 <signal.h>
+#include <pthreadP.h>
+
+
+int
+pthread_sigmask (how, newmask, oldmask)
+     int how;
+     const sigset_t *newmask;
+     sigset_t *oldmask;
+{
+  sigset_t local_newmask;
+
+  /* The only thing we have to make sure here is that SIGCANCEL is not
+     blocked.  */
+  if (newmask != NULL
+      && (how == SIG_SETMASK || how == SIG_BLOCK)
+      && sigismember (newmask, SIGCANCEL))
+    {
+      local_newmask = *newmask;
+      sigdelset (&local_newmask, SIGCANCEL);
+      newmask = &local_newmask;
+    }
+
+  return sigprocmask (how, newmask, oldmask);
+}
diff --git a/nptl/sysdeps/pthread/sigaction.c b/nptl/sysdeps/pthread/sigaction.c
new file mode 100644
index 0000000000..c3f6f435dd
--- /dev/null
+++ b/nptl/sysdeps/pthread/sigaction.c
@@ -0,0 +1,24 @@
+/* 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.  */
+
+/* We use the libc implementation but we tell it to not allow
+   SIGCANCEL to be handled.  */
+#define SIGCANCEL __SIGRTMIN
+
+#include_next <sigaction.c>
diff --git a/nptl/sysdeps/pthread/timer_create.c b/nptl/sysdeps/pthread/timer_create.c
new file mode 100644
index 0000000000..b34f70e8c1
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_create.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "posix-timer.h"
+
+
+/* Create new per-process timer using CLOCK.  */
+int
+timer_create (clock_id, evp, timerid)
+     clockid_t clock_id;
+     struct sigevent *evp;
+     timer_t *timerid;
+{
+  int retval = -1;
+  struct timer_node *newtimer = NULL;
+  struct thread_node *thread = NULL;
+
+  if (clock_id != CLOCK_REALTIME
+#ifdef _POSIX_CPUTIME
+      && clock_id != CLOCK_PROCESS_CPUTIME_ID
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+      && clock_id != CLOCK_THREAD_CPUTIME_ID
+#endif
+      )
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  pthread_once (&__timer_init_once_control, __timer_init_once);
+
+  if (__timer_init_failed)
+    {
+      __set_errno (ENOMEM);
+      return -1;
+    }
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  newtimer = __timer_alloc ();
+  if (__builtin_expect (newtimer == NULL, 0))
+    {
+      __set_errno (EAGAIN);
+      goto unlock_bail;
+    }
+
+  if (evp != NULL)
+    newtimer->event = *evp;
+  else
+    {
+      newtimer->event.sigev_notify = SIGEV_SIGNAL;
+      newtimer->event.sigev_signo = SIGALRM;
+      newtimer->event.sigev_value.sival_int = timer_ptr2id (newtimer);
+      newtimer->event.sigev_notify_function = 0;
+    }
+
+  newtimer->event.sigev_notify_attributes = &newtimer->attr;
+  newtimer->creator_pid = getpid ();
+
+  switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL))
+    {
+    case SIGEV_NONE:
+      /* This is a strange choice!  */
+      break;
+
+    case SIGEV_SIGNAL:
+      /* We have a global thread for delivering timed signals.
+	 If it is not running, try to start it up.  */
+      switch (clock_id)
+	{
+	case CLOCK_REALTIME:
+	default:
+	  thread = &__timer_signal_thread_rclk;
+	  break;
+#ifdef _POSIX_CPUTIME
+	case CLOCK_PROCESS_CPUTIME_ID:
+	  thread = &__timer_signal_thread_pclk;
+	  break;
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+	case CLOCK_THREAD_CPUTIME_ID:
+	  thread = &__timer_signal_thread_tclk;
+	  break;
+#endif
+	}
+
+      if (! thread->exists)
+	{
+	  if (__builtin_expect (__timer_thread_start (thread),
+				1) < 0)
+	    {
+	      __set_errno (EAGAIN);
+	      goto unlock_bail;
+            }
+        }
+      break;
+
+    case SIGEV_THREAD:
+      /* Copy over thread attributes or set up default ones.  */
+      if (evp->sigev_notify_attributes)
+	newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes;
+      else
+	pthread_attr_init (&newtimer->attr);
+
+      /* Ensure thread attributes call for deatched thread.  */
+      pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED);
+
+      /* Try to find existing thread having the right attributes.  */
+      thread = __timer_thread_find_matching (&newtimer->attr, clock_id);
+
+      /* If no existing thread has these attributes, try to allocate one.  */
+      if (thread == NULL)
+	thread = __timer_thread_alloc (&newtimer->attr, clock_id);
+
+      /* Out of luck; no threads are available.  */
+      if (__builtin_expect (thread == NULL, 0))
+	{
+	  __set_errno (EAGAIN);
+	  goto unlock_bail;
+	}
+
+      /* If the thread is not running already, try to start it.  */
+      if (! thread->exists
+	  && __builtin_expect (! __timer_thread_start (thread), 0))
+	{
+	  __set_errno (EAGAIN);
+	  goto unlock_bail;
+	}
+      break;
+
+    default:
+      __set_errno (EINVAL);
+      goto unlock_bail;
+    }
+
+  newtimer->clock = clock_id;
+  newtimer->abstime = 0;
+  newtimer->armed = 0;
+  newtimer->thread = thread;
+
+  *timerid = timer_ptr2id (newtimer);
+  retval = 0;
+
+  if (__builtin_expect (retval, 0) == -1)
+    {
+    unlock_bail:
+      if (thread != NULL)
+	__timer_thread_dealloc (thread);
+      if (newtimer != NULL)
+	__timer_dealloc (newtimer);
+    }
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  return retval;
+}
diff --git a/nptl/sysdeps/pthread/timer_delete.c b/nptl/sysdeps/pthread/timer_delete.c
new file mode 100644
index 0000000000..48ba1f2726
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_delete.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "posix-timer.h"
+
+
+/* Delete timer TIMERID.  */
+int
+timer_delete (timerid)
+     timer_t timerid;
+{
+  struct timer_node *timer;
+  int retval = -1;
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  timer = timer_id2ptr (timerid);
+  if (! timer_valid (timer))
+    /* Invalid timer ID or the timer is not in use.  */
+    __set_errno (EINVAL);
+  else
+    {
+      if (timer->armed && timer->thread != NULL)
+	{
+	  struct thread_node *thread = timer->thread;
+	  assert (thread != NULL);
+
+	  /* If thread is cancelled while waiting for handler to terminate,
+	     the mutex is unlocked and timer_delete is aborted.  */
+	  pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex);
+
+	  /* If timer is currently being serviced, wait for it to finish.  */
+	  while (thread->current_timer == timer)
+	    pthread_cond_wait (&thread->cond, &__timer_mutex);
+
+	  pthread_cleanup_pop (0);
+        }
+
+      /* Remove timer from whatever queue it may be on and deallocate it.  */
+      timer->inuse = TIMER_DELETED;
+      list_unlink_ip (&timer->links);
+      timer_delref (timer);
+      retval = 0;
+    }
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  return retval;
+}
diff --git a/nptl/sysdeps/pthread/timer_getoverr.c b/nptl/sysdeps/pthread/timer_getoverr.c
new file mode 100644
index 0000000000..f3e22215b2
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_getoverr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "posix-timer.h"
+
+
+/* Get expiration overrun for timer TIMERID.  */
+int
+timer_getoverrun (timerid)
+     timer_t timerid;
+{
+  struct timer_node *timer;
+  int retval = -1;
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  if (! timer_valid (timer = timer_id2ptr (timerid)))
+    __set_errno (EINVAL);
+  else
+    retval = timer->overrun_count;
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  return retval;
+}
diff --git a/nptl/sysdeps/pthread/timer_gettime.c b/nptl/sysdeps/pthread/timer_gettime.c
new file mode 100644
index 0000000000..99a080311c
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_gettime.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "posix-timer.h"
+
+
+/* Get current value of timer TIMERID and store it in VLAUE.  */
+int
+timer_gettime (timerid, value)
+     timer_t timerid;
+     struct itimerspec *value;
+{
+  struct timer_node *timer;
+  struct timespec now, expiry;
+  int retval = -1, armed = 0, valid;
+  clock_t clock = 0;
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  timer = timer_id2ptr (timerid);
+  valid = timer_valid (timer);
+
+  if (valid) {
+    armed = timer->armed;
+    expiry = timer->expirytime;
+    clock = timer->clock;
+    value->it_interval = timer->value.it_interval;
+  }
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  if (valid)
+    {
+      if (armed)
+	{
+	  clock_gettime (clock, &now);
+	  timespec_sub (&value->it_value, &expiry, &now);
+	}
+      else
+	{
+	  value->it_value.tv_sec = 0;
+	  value->it_value.tv_nsec = 0;
+	}
+
+      retval = 0;
+    }
+  else
+    __set_errno (EINVAL);
+
+  return retval;
+}
diff --git a/nptl/sysdeps/pthread/timer_routines.c b/nptl/sysdeps/pthread/timer_routines.c
new file mode 100644
index 0000000000..ddd8afe988
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_routines.c
@@ -0,0 +1,592 @@
+/* Helper code for POSIX timer implementation on LinuxThreads.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "posix-timer.h"
+#include <pthreadP.h>
+
+
+/* Number of threads used.  */
+#define THREAD_MAXNODES	16
+
+/* Array containing the descriptors for the used threads.  */
+static struct thread_node thread_array[THREAD_MAXNODES];
+
+/* Static array with the structures for all the timers.  */
+struct timer_node __timer_array[TIMER_MAX];
+
+/* Global lock to protect operation on the lists.  */
+pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Variable to protext initialization.  */
+pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT;
+
+/* Nonzero if initialization of timer implementation failed.  */
+int __timer_init_failed;
+
+/* Node for the thread used to deliver signals.  */
+struct thread_node __timer_signal_thread_rclk;
+#ifdef _POSIX_CPUTIME
+struct thread_node __timer_signal_thread_pclk;
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+struct thread_node __timer_signal_thread_tclk;
+#endif
+
+/* Lists to keep free and used timers and threads.  */
+struct list_links timer_free_list;
+struct list_links thread_free_list;
+struct list_links thread_active_list;
+
+
+#ifdef __NR_rt_sigqueueinfo
+extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *);
+#endif
+
+
+/* List handling functions.  */
+static inline void
+list_init (struct list_links *list)
+{
+  list->next = list->prev = list;
+}
+
+static inline void
+list_append (struct list_links *list, struct list_links *newp)
+{
+  newp->prev = list->prev;
+  newp->next = list;
+  list->prev->next = newp;
+  list->prev = newp;
+}
+
+static inline void
+list_insbefore (struct list_links *list, struct list_links *newp)
+{
+  list_append (list, newp);
+}
+
+/*
+ * Like list_unlink_ip, except that calling it on a node that
+ * is already unlinked is disastrous rather than a noop.
+ */
+
+static inline void
+list_unlink (struct list_links *list)
+{
+  struct list_links *lnext = list->next, *lprev = list->prev;
+
+  lnext->prev = lprev;
+  lprev->next = lnext;
+}
+
+static inline struct list_links *
+list_first (struct list_links *list)
+{
+  return list->next;
+}
+
+static inline struct list_links *
+list_null (struct list_links *list)
+{
+  return list;
+}
+
+static inline struct list_links *
+list_next (struct list_links *list)
+{
+  return list->next;
+}
+
+static inline int
+list_isempty (struct list_links *list)
+{
+  return list->next == list;
+}
+
+
+/* Functions build on top of the list functions.  */
+static inline struct thread_node *
+thread_links2ptr (struct list_links *list)
+{
+  return (struct thread_node *) ((char *) list
+				 - offsetof (struct thread_node, links));
+}
+
+static inline struct timer_node *
+timer_links2ptr (struct list_links *list)
+{
+  return (struct timer_node *) ((char *) list
+				- offsetof (struct timer_node, links));
+}
+
+
+/* Initialize a newly allocated thread structure.  */
+static void
+thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id)
+{
+  if (attr != NULL)
+    thread->attr = *attr;
+  else
+    {
+      pthread_attr_init (&thread->attr);
+      pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED);
+    }
+
+  thread->exists = 0;
+  list_init (&thread->timer_queue);
+  pthread_cond_init (&thread->cond, 0);
+  thread->current_timer = 0;
+  thread->captured = pthread_self ();
+  thread->clock_id = clock_id;
+}
+
+
+/* Initialize the global lists, and acquire global resources.  Error
+   reporting is done by storing a non-zero value to the global variable
+   timer_init_failed.  */
+static void
+init_module (void)
+{
+  int i;
+
+  list_init (&timer_free_list);
+  list_init (&thread_free_list);
+  list_init (&thread_active_list);
+
+  for (i = 0; i < TIMER_MAX; ++i)
+    {
+      list_append (&timer_free_list, &__timer_array[i].links);
+      __timer_array[i].inuse = TIMER_FREE;
+    }
+
+  for (i = 0; i < THREAD_MAXNODES; ++i)
+    list_append (&thread_free_list, &thread_array[i].links);
+
+  thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME);
+#ifdef _POSIX_CPUTIME
+  thread_init (&__timer_signal_thread_pclk, 0, CLOCK_PROCESS_CPUTIME_ID);
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+  thread_init (&__timer_signal_thread_tclk, 0, CLOCK_THREAD_CPUTIME_ID);
+#endif
+}
+
+
+/* This is a handler executed in a child process after a fork()
+   occurs.  It reinitializes the module, resetting all of the data
+   structures to their initial state.  The mutex is initialized in
+   case it was locked in the parent process.  */
+static void
+reinit_after_fork (void)
+{
+  init_module ();
+  pthread_mutex_init (&__timer_mutex, 0);
+}
+
+
+/* Called once form pthread_once in timer_init. This initializes the
+   module and ensures that reinit_after_fork will be executed in any
+   child process.  */
+void
+__timer_init_once (void)
+{
+  init_module ();
+  pthread_atfork (0, 0, reinit_after_fork);
+}
+
+
+/* Deinitialize a thread that is about to be deallocated.  */
+static void
+thread_deinit (struct thread_node *thread)
+{
+  assert (list_isempty (&thread->timer_queue));
+  pthread_cond_destroy (&thread->cond);
+}
+
+
+/* Allocate a thread structure from the global free list.  Global
+   mutex lock must be held by caller.  The thread is moved to
+   the active list. */
+struct thread_node *
+__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id)
+{
+  struct list_links *node = list_first (&thread_free_list);
+
+  if (node != list_null (&thread_free_list))
+    {
+      struct thread_node *thread = thread_links2ptr (node);
+      list_unlink (node);
+      thread_init (thread, desired_attr, clock_id);
+      list_append (&thread_active_list, node);
+      return thread;
+    }
+
+  return 0;
+}
+
+
+/* Return a thread structure to the global free list.  Global lock
+   must be held by caller.  */
+void
+__timer_thread_dealloc (struct thread_node *thread)
+{
+  thread_deinit (thread);
+  list_unlink (&thread->links);
+  list_append (&thread_free_list, &thread->links);
+}
+
+
+/* Each of our threads which terminates executes this cleanup
+   handler. We never terminate threads ourselves; if a thread gets here
+   it means that the evil application has killed it.  If the thread has
+   timers, these require servicing and so we must hire a replacement
+   thread right away.  We must also unblock another thread that may
+   have been waiting for this thread to finish servicing a timer (see
+   timer_delete()).  */
+
+static void
+thread_cleanup (void *val)
+{
+  if (val != NULL)
+    {
+      struct thread_node *thread = val;
+
+      /* How did the signal thread get killed?  */
+      assert (thread != &__timer_signal_thread_rclk);
+#ifdef _POSIX_CPUTIME
+      assert (thread != &__timer_signal_thread_pclk);
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+      assert (thread != &__timer_signal_thread_tclk);
+#endif
+
+      pthread_mutex_lock (&__timer_mutex);
+
+      thread->exists = 0;
+
+      /* We are no longer processing a timer event.  */
+      thread->current_timer = 0;
+
+      if (list_isempty (&thread->timer_queue))
+	  __timer_thread_dealloc (thread);
+      else
+	(void) __timer_thread_start (thread);
+
+      pthread_mutex_unlock (&__timer_mutex);
+
+      /* Unblock potentially blocked timer_delete().  */
+      pthread_cond_broadcast (&thread->cond);
+    }
+}
+
+
+/* Handle a timer which is supposed to go off now.  */
+static void
+thread_expire_timer (struct thread_node *self, struct timer_node *timer)
+{
+  self->current_timer = timer; /* Lets timer_delete know timer is running. */
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL))
+    {
+    case SIGEV_NONE:
+      assert (! "timer_create should never have created such a timer");
+      break;
+
+    case SIGEV_SIGNAL:
+#ifdef __NR_rt_sigqueueinfo
+      {
+	siginfo_t info;
+
+	/* First, clear the siginfo_t structure, so that we don't pass our
+	   stack content to other tasks.  */
+	memset (&info, 0, sizeof (siginfo_t));
+	/* We must pass the information about the data in a siginfo_t
+           value.  */
+	info.si_signo = timer->event.sigev_signo;
+	info.si_code = SI_TIMER;
+	info.si_pid = timer->creator_pid;
+	info.si_uid = getuid ();
+	info.si_value = timer->event.sigev_value;
+
+	INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info);
+      }
+#else
+      if (pthread_kill (self->captured, timer->event.sigev_signo) != 0)
+	{
+	  if (pthread_kill (self->id, timer->event.sigev_signo) != 0)
+	    abort ();
+        }
+#endif
+      break;
+
+    case SIGEV_THREAD:
+      timer->event.sigev_notify_function (timer->event.sigev_value);
+      break;
+
+    default:
+      assert (! "unknown event");
+      break;
+    }
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  self->current_timer = 0;
+
+  pthread_cond_broadcast (&self->cond);
+}
+
+
+/* Thread function; executed by each timer thread. The job of this
+   function is to wait on the thread's timer queue and expire the
+   timers in chronological order as close to their scheduled time as
+   possible.  */
+static void
+__attribute__ ((noreturn))
+thread_func (void *arg)
+{
+  struct thread_node *self = arg;
+
+  /* Register cleanup handler, in case rogue application terminates
+     this thread.  (This cannot happen to __timer_signal_thread, which
+     doesn't invoke application callbacks). */
+
+  pthread_cleanup_push (thread_cleanup, self);
+
+  pthread_mutex_lock (&__timer_mutex);
+
+  while (1)
+    {
+      struct list_links *first;
+      struct timer_node *timer = NULL;
+
+      /* While the timer queue is not empty, inspect the first node.  */
+      first = list_first (&self->timer_queue);
+      if (first != list_null (&self->timer_queue))
+	{
+	  struct timespec now;
+
+	  timer = timer_links2ptr (first);
+
+	  /* This assumes that the elements of the list of one thread
+	     are all for the same clock.  */
+	  clock_gettime (timer->clock, &now);
+
+	  while (1)
+	    {
+	      /* If the timer is due or overdue, remove it from the queue.
+		 If it's a periodic timer, re-compute its new time and
+		 requeue it.  Either way, perform the timer expiry. */
+	      if (timespec_compare (&now, &timer->expirytime) < 0)
+		break;
+
+	      list_unlink_ip (first);
+
+	      if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0
+		  || timer->value.it_interval.tv_nsec != 0)
+		{
+		  timer->overrun_count = 0;
+		  timespec_add (&timer->expirytime, &timer->expirytime,
+				&timer->value.it_interval);
+		  while (timespec_compare (&timer->expirytime, &now) < 0)
+		    {
+		      timespec_add (&timer->expirytime, &timer->expirytime,
+				    &timer->value.it_interval);
+		      if (timer->overrun_count < DELAYTIMER_MAX)
+			++timer->overrun_count;
+		    }
+		  __timer_thread_queue_timer (self, timer);
+		}
+
+	      thread_expire_timer (self, timer);
+
+	      first = list_first (&self->timer_queue);
+	      if (first == list_null (&self->timer_queue))
+		break;
+
+	      timer = timer_links2ptr (first);
+	    }
+	}
+
+      /* If the queue is not empty, wait until the expiry time of the
+	 first node.  Otherwise wait indefinitely.  Insertions at the
+	 head of the queue must wake up the thread by broadcasting
+	 this condition variable.  */
+      if (timer != NULL)
+	pthread_cond_timedwait (&self->cond, &__timer_mutex,
+				&timer->expirytime);
+      else
+	pthread_cond_wait (&self->cond, &__timer_mutex);
+    }
+  /* This macro will never be executed since the while loop loops
+     forever - but we have to add it for proper nesting.  */
+  pthread_cleanup_pop (1);
+}
+
+
+/* Enqueue a timer in wakeup order in the thread's timer queue.
+   Returns 1 if the timer was inserted at the head of the queue,
+   causing the queue's next wakeup time to change. */
+
+int
+__timer_thread_queue_timer (struct thread_node *thread,
+			    struct timer_node *insert)
+{
+  struct list_links *iter;
+  int athead = 1;
+
+  for (iter = list_first (&thread->timer_queue);
+       iter != list_null (&thread->timer_queue);
+        iter = list_next (iter))
+    {
+      struct timer_node *timer = timer_links2ptr (iter);
+
+      if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0)
+	  break;
+      athead = 0;
+    }
+
+  list_insbefore (iter, &insert->links);
+  return athead;
+}
+
+
+/* Start a thread and associate it with the given thread node.  Global
+   lock must be held by caller.  */
+int
+__timer_thread_start (struct thread_node *thread)
+{
+  int retval = 1;
+
+  assert (!thread->exists);
+  thread->exists = 1;
+
+  if (pthread_create (&thread->id, &thread->attr,
+		      (void *(*) (void *)) thread_func, thread) != 0)
+    {
+      thread->exists = 0;
+      retval = -1;
+    }
+
+  return retval;
+}
+
+
+void
+__timer_thread_wakeup (struct thread_node *thread)
+{
+  pthread_cond_broadcast (&thread->cond);
+}
+
+
+/* Compare two pthread_attr_t thread attributes for exact equality.
+   Returns 1 if they are equal, otherwise zero if they are not equal or
+   contain illegal values.  This version is LinuxThreads-specific for
+   performance reason.  One could use the access functions to get the
+   values of all the fields of the attribute structure.  */
+static int
+thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right)
+{
+  struct pthread_attr *ileft = (struct pthread_attr *) left;
+  struct pthread_attr *iright = (struct pthread_attr *) right;
+
+  return (ileft->flags == iright->flags
+	  && ileft->schedpolicy == iright->schedpolicy
+	  && (ileft->schedparam.sched_priority
+	      == iright->schedparam.sched_priority));
+}
+
+
+/* Search the list of active threads and find one which has matching
+   attributes.  Global mutex lock must be held by caller.  */
+struct thread_node *
+__timer_thread_find_matching (const pthread_attr_t *desired_attr,
+			      clockid_t desired_clock_id)
+{
+  struct list_links *iter = list_first (&thread_active_list);
+
+  while (iter != list_null (&thread_active_list))
+    {
+      struct thread_node *candidate = thread_links2ptr (iter);
+
+      if (thread_attr_compare (desired_attr, &candidate->attr)
+	  && desired_clock_id == candidate->clock_id)
+	{
+	  list_unlink (iter);
+	  return candidate;
+        }
+
+      iter = list_next (iter);
+    }
+
+  return NULL;
+}
+
+
+/* Grab a free timer structure from the global free list.  The global
+   lock must be held by the caller.  */
+struct timer_node *
+__timer_alloc (void)
+{
+  struct list_links *node = list_first (&timer_free_list);
+
+  if (node != list_null (&timer_free_list))
+    {
+      struct timer_node *timer = timer_links2ptr (node);
+      list_unlink_ip (node);
+      timer->inuse = TIMER_INUSE;
+      timer->refcount = 1;
+      return timer;
+    }
+
+  return NULL;
+}
+
+
+/* Return a timer structure to the global free list.  The global lock
+   must be held by the caller.  */
+void
+__timer_dealloc (struct timer_node *timer)
+{
+  assert (timer->refcount == 0);
+  timer->thread = NULL;	/* Break association between timer and thread.  */
+  timer->inuse = TIMER_FREE;
+  list_append (&timer_free_list, &timer->links);
+}
+
+
+/* Thread cancellation handler which unlocks a mutex.  */
+void
+__timer_mutex_cancel_handler (void *arg)
+{
+  pthread_mutex_unlock (arg);
+}
diff --git a/nptl/sysdeps/pthread/timer_settime.c b/nptl/sysdeps/pthread/timer_settime.c
new file mode 100644
index 0000000000..592b5271ba
--- /dev/null
+++ b/nptl/sysdeps/pthread/timer_settime.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "posix-timer.h"
+
+
+/* Set timer TIMERID to VALUE, returning old value in OVLAUE.  */
+int
+timer_settime (timerid, flags, value, ovalue)
+     timer_t timerid;
+     int flags;
+     const struct itimerspec *value;
+     struct itimerspec *ovalue;
+{
+  struct timer_node *timer;
+  struct thread_node *thread = NULL;
+  struct timespec now;
+  int have_now = 0, need_wakeup = 0;
+  int retval = -1;
+
+  timer = timer_id2ptr (timerid);
+  if (timer == NULL)
+    {
+      __set_errno (EINVAL);
+      goto bail;
+    }
+
+  if (value->it_interval.tv_nsec < 0
+      || value->it_interval.tv_nsec >= 1000000000
+      || value->it_value.tv_nsec < 0
+      || value->it_value.tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      goto bail;
+    }
+
+  /* Will need to know current time since this is a relative timer;
+     might as well make the system call outside of the lock now! */
+
+  if ((flags & TIMER_ABSTIME) == 0)
+    {
+      clock_gettime (timer->clock, &now);
+      have_now = 1;
+    }
+
+  pthread_mutex_lock (&__timer_mutex);
+  timer_addref (timer);
+
+  /* One final check of timer validity; this one is possible only
+     until we have the mutex, because it accesses the inuse flag. */
+
+  if (! timer_valid(timer))
+    {
+      __set_errno (EINVAL);
+      goto unlock_bail;
+    }
+
+  if (ovalue != NULL)
+    {
+      ovalue->it_interval = timer->value.it_interval;
+
+      if (timer->armed)
+	{
+	  if (! have_now)
+	    {
+	      pthread_mutex_unlock (&__timer_mutex);
+	      clock_gettime (timer->clock, &now);
+	      have_now = 1;
+	      pthread_mutex_lock (&__timer_mutex);
+	      timer_addref (timer);
+	    }
+
+	  timespec_sub (&ovalue->it_value, &timer->expirytime, &now);
+	}
+      else
+	{
+	  ovalue->it_value.tv_sec = 0;
+	  ovalue->it_value.tv_nsec = 0;
+	}
+    }
+
+  timer->value = *value;
+
+  list_unlink_ip (&timer->links);
+  timer->armed = 0;
+
+  thread = timer->thread;
+
+  /* A value of { 0, 0 } causes the timer to be stopped. */
+  if (value->it_value.tv_sec != 0
+      || __builtin_expect (value->it_value.tv_nsec != 0, 1))
+    {
+      if ((flags & TIMER_ABSTIME) != 0)
+	/* The user specified the expiration time.  */
+	timer->expirytime = value->it_value;
+      else
+	timespec_add (&timer->expirytime, &now, &value->it_value);
+
+      /* Only need to wake up the thread if timer is inserted
+	 at the head of the queue. */
+      if (thread != NULL)
+	need_wakeup = __timer_thread_queue_timer (thread, timer);
+      timer->armed = 1;
+    }
+
+  retval = 0;
+
+unlock_bail:
+  timer_delref (timer);
+  pthread_mutex_unlock (&__timer_mutex);
+
+bail:
+  if (thread != NULL && need_wakeup)
+    __timer_thread_wakeup (thread);
+
+  return retval;
+}
diff --git a/nptl/sysdeps/pthread/tst-timer.c b/nptl/sysdeps/pthread/tst-timer.c
new file mode 100644
index 0000000000..7417bcd5f0
--- /dev/null
+++ b/nptl/sysdeps/pthread/tst-timer.c
@@ -0,0 +1,114 @@
+/* Tests for POSIX timer implementation.
+   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static void
+notify_func (union sigval sigval)
+{
+  puts ("notify_func");
+}
+
+
+static void
+signal_func (int sig)
+{
+  static const char text[] = "signal_func\n";
+  signal (sig, signal_func);
+  write (STDOUT_FILENO, text, sizeof text - 1);
+}
+
+static void
+intr_sleep (int sec)
+{
+  struct timespec ts;
+
+  ts.tv_sec = sec;
+  ts.tv_nsec = 0;
+
+  while (nanosleep (&ts, &ts) == -1 && errno == EINTR)
+    ;
+}
+
+#define ZSIGALRM 14
+
+
+int
+main (void)
+{
+  struct timespec ts;
+  timer_t timer_sig, timer_thr1, timer_thr2;
+  int retval;
+  struct sigevent sigev1 =
+  {
+    .sigev_notify = SIGEV_SIGNAL,
+    .sigev_signo = ZSIGALRM
+  };
+  struct sigevent sigev2;
+  struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } };
+  struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } };
+  struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } };
+  struct itimerspec old;
+
+  retval = clock_gettime (CLOCK_REALTIME, &ts);
+
+  sigev2.sigev_notify = SIGEV_THREAD;
+  sigev2.sigev_notify_function = notify_func;
+  sigev2.sigev_notify_attributes = NULL;
+
+  setvbuf (stdout, 0, _IOLBF, 0);
+
+  printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n",
+	  retval, ts.tv_sec, ts.tv_nsec);
+
+  retval = clock_getres (CLOCK_REALTIME, &ts);
+
+  printf ("clock_getres returned %d, timespec = { %ld, %ld }\n",
+	  retval, ts.tv_sec, ts.tv_nsec);
+
+  timer_create (CLOCK_REALTIME, &sigev1, &timer_sig);
+  timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1);
+  timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2);
+
+  timer_settime (timer_thr1, 0, &itimer2, &old);
+  timer_settime (timer_thr2, 0, &itimer3, &old);
+
+  signal (ZSIGALRM, signal_func);
+
+  timer_settime (timer_sig, 0, &itimer1, &old);
+
+  timer_delete (-1);
+
+  intr_sleep (3);
+
+  timer_delete (timer_sig);
+  timer_delete (timer_thr1);
+
+  intr_sleep (3);
+
+  timer_delete (timer_thr2);
+
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/Implies b/nptl/sysdeps/unix/sysv/linux/Implies
new file mode 100644
index 0000000000..f1b3e8939c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Implies
@@ -0,0 +1 @@
+pthread
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
new file mode 100644
index 0000000000..efe4ba4e9d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -0,0 +1,24 @@
+# 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.  */
+
+ifeq ($(subdir),nptl)
+sysdep_routines += register-atfork unregister-atfork fork-gen lowlevellock
+
+libpthread-sysdep_routines += pt-fork
+endif
diff --git a/nptl/sysdeps/unix/sysv/linux/Versions b/nptl/sysdeps/unix/sysv/linux/Versions
new file mode 100644
index 0000000000..117598c95f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Versions
@@ -0,0 +1,12 @@
+libc {
+  GLIBC_PRIVATE {
+    __register_atfork; __register_pthread_fork_handler;
+    __libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
+    __libc_allocate_rtsig_private;
+  }
+}
+libpthread {
+  GLIBC_2.0 {
+    fork; __fork;
+  }
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
new file mode 100644
index 0000000000..5badaea9ec
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
@@ -0,0 +1,54 @@
+/* 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 <signal.h>
+
+
+static int current_rtmin = __SIGRTMIN + 1;
+static int current_rtmax = __SIGRTMAX;
+
+
+/* We reserve __SIGRTMIN for use as the cancelation signal.  This
+   signal is used internally.  */
+int
+__libc_current_sigrtmin (void)
+{
+  return current_rtmin;
+}
+strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private)
+
+
+int
+__libc_current_sigrtmax (void)
+{
+  return current_rtmax;
+}
+strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private)
+
+
+int
+__libc_allocate_rtsig (int high)
+{
+  if (current_rtmin == -1 || current_rtmin > current_rtmax)
+    /* We don't have anymore signal available.  */
+    return -1;
+
+  return high ? current_rtmin++ : current_rtmax--;
+}
+strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private)
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
new file mode 100644
index 0000000000..63de09a1b0
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
@@ -0,0 +1,80 @@
+/* Minimum guaranteed maximum values for system limits.  Linux version.
+   Copyright (C) 1993,94,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* This is the value this implementation supports.  */
+#define PTHREAD_THREADS_MAX	1024
+
+/* Maximum amount by which a process can descrease its asynchronous I/O
+   priority level.  */
+#define AIO_PRIO_DELTA_MAX	20
+
+/* Minimum size for a thread.  We are free to choose a reasonable value.  */
+#define PTHREAD_STACK_MIN	16384
+
+/* Maximum number of POSIX timers available.  */
+#define TIMER_MAX	256
+
+/* Maximum number of timer expiration overruns.  */
+#define DELAYTIMER_MAX	2147483647
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
new file mode 100644
index 0000000000..8274f516be
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
@@ -0,0 +1,144 @@
+/* Define POSIX options for Linux.
+   Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef	_POSIX_OPT_H
+#define	_POSIX_OPT_H	1
+
+/* Job control is supported.  */
+#define	_POSIX_JOB_CONTROL	1
+
+/* Processes have a saved set-user-ID and a saved set-group-ID.  */
+#define	_POSIX_SAVED_IDS	1
+
+/* Priority scheduling is supported.  */
+#define	_POSIX_PRIORITY_SCHEDULING	200112L
+
+/* Synchronizing file data is supported.  */
+#define	_POSIX_SYNCHRONIZED_IO	200112L
+
+/* The fsync function is present.  */
+#define	_POSIX_FSYNC	200112L
+
+/* Mapping of files to memory is supported.  */
+#define	_POSIX_MAPPED_FILES	200112L
+
+/* Locking of all memory is supported.  */
+#define	_POSIX_MEMLOCK	200112L
+
+/* Locking of ranges of memory is supported.  */
+#define	_POSIX_MEMLOCK_RANGE	200112L
+
+/* Setting of memory protections is supported.  */
+#define	_POSIX_MEMORY_PROTECTION	200112L
+
+/* Implementation supports `poll' function.  */
+#define	_POSIX_POLL	1
+
+/* Implementation supports `select' and `pselect' functions.  */
+#define	_POSIX_SELECT	1
+
+/* Only root can change owner of file.  */
+#define	_POSIX_CHOWN_RESTRICTED	1
+
+/* `c_cc' member of 'struct termios' structure can be disabled by
+   using the value _POSIX_VDISABLE.  */
+#define	_POSIX_VDISABLE	'\0'
+
+/* Filenames are not silently truncated.  */
+#define	_POSIX_NO_TRUNC	1
+
+/* X/Open realtime support is available.  */
+#define _XOPEN_REALTIME	1
+
+/* X/Open realtime thread support is available.  */
+#define _XOPEN_REALTIME_THREADS	1
+
+/* XPG4.2 shared memory is supported.  */
+#define	_XOPEN_SHM	1
+
+/* Tell we have POSIX threads.  */
+#define _POSIX_THREADS	200112L
+
+/* We have the reentrant functions described in POSIX.  */
+#define _POSIX_REENTRANT_FUNCTIONS      1
+#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L
+
+/* We provide priority scheduling for threads.  */
+#define	_POSIX_THREAD_PRIORITY_SCHEDULING	200112L
+
+/* We support user-defined stack sizes.  */
+#define _POSIX_THREAD_ATTR_STACKSIZE	200112L
+
+/* We support user-defined stacks.  */
+#define _POSIX_THREAD_ATTR_STACKADDR	200112L
+
+/* We support POSIX.1b semaphores, but only the non-shared form for now.  */
+#define _POSIX_SEMAPHORES	1
+
+/* Real-time signals are supported.  */
+#define _POSIX_REALTIME_SIGNALS	1
+
+/* We support asynchronous I/O.  */
+#define _POSIX_ASYNCHRONOUS_IO	1
+#define _POSIX_ASYNC_IO		1
+/* Alternative name for Unix98.  */
+#define _LFS_ASYNCHRONOUS_IO	1
+
+/* The LFS support in asynchronous I/O is also available.  */
+#define _LFS64_ASYNCHRONOUS_IO	1
+
+/* The rest of the LFS is also available.  */
+#define _LFS_LARGEFILE		1
+#define _LFS64_LARGEFILE	1
+#define _LFS64_STDIO		1
+
+/* POSIX shared memory objects are implemented.  */
+#define _POSIX_SHARED_MEMORY_OBJECTS	200112L
+
+/* GNU libc provides regular expression handling.  */
+#define _POSIX_REGEXP	1
+
+/* Reader/Writer locks are available.  */
+#define _POSIX_READER_WRITER_LOCKS	200112L
+
+/* We have a POSIX shell.  */
+#define _POSIX_SHELL	1
+
+/* We support the Timeouts option.  */
+#define _POSIX_TIMEOUTS	200112L
+
+/* We support spinlocks.  */
+#define _POSIX_SPIN_LOCKS	200112L
+
+/* The `spawn' function family is supported.  */
+#define _POSIX_SPAWN	200112L
+
+/* We have POSIX timers.  */
+#define _POSIX_TIMERS	1
+
+/* The barrier functions are available.  */
+#define _POSIX_BARRIERS	200112L
+
+/* POSIX message queues are not yet supported.  */
+#undef	_POSIX_MESSAGE_PASSING
+
+/* Thread process-shared synchronization is supported.  */
+#define _POSIX_THREAD_PROCESS_SHARED	200112L
+
+#endif /* posix_opt.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/configure b/nptl/sysdeps/unix/sysv/linux/configure
new file mode 100644
index 0000000000..229414dd74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/configure
@@ -0,0 +1,3 @@
+# Local configure fragment for sysdeps/unix/sysv/linux.
+
+DEFINES="$DEFINES -D_LIBC_REENTRANT"
diff --git a/nptl/sysdeps/unix/sysv/linux/fork-gen.c b/nptl/sysdeps/unix/sysv/linux/fork-gen.c
new file mode 100644
index 0000000000..ff00261404
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork-gen.c
@@ -0,0 +1,37 @@
+/* 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 <list.h>
+#include "fork.h"
+
+
+static struct fork_handler pthread_child_handler;
+
+
+void
+__register_pthread_fork_handler (ptr, reclaim)
+     unsigned long int *ptr;
+     void (*reclaim) (void);
+{
+  __fork_generation_pointer = ptr;
+
+  pthread_child_handler.handler = reclaim;
+
+  list_add_tail (&pthread_child_handler.list, &__fork_child_list);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c
new file mode 100644
index 0000000000..c1aa23c5c5
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -0,0 +1,124 @@
+/* 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sysdep.h>
+#include <libio/libioP.h>
+#include <tls.h>
+#include "fork.h"
+
+
+unsigned long int *__fork_generation_pointer;
+
+
+lll_lock_t __fork_lock = LLL_LOCK_INITIALIZER;
+LIST_HEAD (__fork_prepare_list);
+LIST_HEAD (__fork_parent_list);
+LIST_HEAD (__fork_child_list);
+
+
+static void
+fresetlockfiles (void)
+{
+  _IO_ITER i;
+
+  for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
+    *((pthread_mutex_t *) _IO_iter_file(i)->_lock)
+      = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+}
+
+
+pid_t
+__libc_fork (void)
+{
+  pid_t pid;
+  list_t *runp;
+
+  /* Get the lock so that the set of registered handlers is not
+     inconsistent or changes beneath us.  */
+  lll_lock (__fork_lock);
+
+  /* Run all the registered preparation handlers.  In reverse order.  */
+  list_for_each_prev (runp, &__fork_prepare_list)
+    {
+      struct fork_handler *curp;
+
+      curp = list_entry (runp, struct fork_handler, list);
+
+      curp->handler ();
+    }
+
+  _IO_list_lock ();
+
+#ifdef ARCH_FORK
+  pid = ARCH_FORK ();
+#else
+# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used"
+  pid = INLINE_SYSCALL (fork, 0);
+#endif
+
+  if (pid == 0)
+    {
+      if (__fork_generation_pointer != NULL)
+	*__fork_generation_pointer += 4;
+
+      /* Reset the file list.  These are recursive mutexes.  */
+      fresetlockfiles ();
+
+      /* We execute this even if the 'fork' call failed.  */
+      _IO_list_resetlock ();
+
+      /* Run the handlers registered for the child.  */
+      list_for_each (runp, &__fork_child_list)
+	{
+	  struct fork_handler *curp;
+
+	  curp = list_entry (runp, struct fork_handler, list);
+
+	  curp->handler ();
+	}
+
+      /* Initialize the fork lock.  */
+      __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER;
+    }
+  else
+    {
+      /* We execute this even if the 'fork' call failed.  */
+      _IO_list_unlock ();
+
+      /* Run the handlers registered for the parent.  */
+      list_for_each (runp, &__fork_parent_list)
+	{
+	  struct fork_handler *curp;
+
+	  curp = list_entry (runp, struct fork_handler, list);
+
+	  curp->handler ();
+	}
+
+      /* Release the for lock.  */
+      lll_unlock (__fork_lock);
+    }
+
+  return pid;
+}
+weak_alias (__libc_fork, __fork)
+weak_alias (__libc_fork, fork)
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h
new file mode 100644
index 0000000000..85722a59eb
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork.h
@@ -0,0 +1,60 @@
+/* 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 <list.h>
+#include <lowlevellock.h>
+
+/* The fork generation counter, defined in libpthread.  */
+extern unsigned long int __fork_generation attribute_hidden;
+
+/* Pointer to the fork generation counter in the thread library.  */
+extern unsigned long int *__fork_generation_pointer attribute_hidden;
+
+/* Lock to protect handling of fork handlers.  */
+extern lll_lock_t __fork_lock attribute_hidden;
+
+/* Lists of registered fork handlers.  */
+extern list_t __fork_prepare_list attribute_hidden;
+extern list_t __fork_parent_list attribute_hidden;
+extern list_t __fork_child_list attribute_hidden;
+
+
+/* Elements of the fork handler lists.  */
+struct fork_handler
+{
+  list_t list;
+  void (*handler) (void);
+  void *dso_handle;
+};
+
+
+/* Function to call to unregister fork handlers.  */
+extern void __unregister_atfork (void *dso_handle) attribute_hidden;
+#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle)
+
+
+/* C library side function to register new fork handlers.  */
+extern int __register_atfork (void (*__prepare) (void),
+			      void (*__parent) (void),
+			      void (*__child) (void),
+			      void *dso_handle);
+
+/* Register the generation counter in the libpthread with the libc.  */
+extern void __register_pthread_fork_handler (unsigned long int *__ptr,
+					     void (*reclaim) (void));
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
diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
new file mode 100644
index 0000000000..24ead1b5ce
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
@@ -0,0 +1,130 @@
+/* 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 _INTERNALTYPES_H
+#define _INTERNALTYPES_H	1
+
+
+struct pthread_attr
+{
+  /* Scheduler parameters and priority.  */
+  struct sched_param schedparam;
+  int schedpolicy;
+  /* Various flags like detachstate, scope, etc.  */
+  int flags;
+  /* Size of guard area.  */
+  size_t guardsize;
+  /* Stack handling.  */
+  void *stackaddr;
+  size_t stacksize;
+
+  /* Chain of all initialized attributes.  Keep this last since it is
+     not always used.  */
+  struct pthread_attr *next;
+};
+
+#define ATTR_FLAG_DETACHSTATE		0x0001
+#define ATTR_FLAG_NOTINHERITSCHED	0x0002
+#define ATTR_FLAG_SCOPEPROCESS		0x0004
+#define ATTR_FLAG_STACKADDR		0x0008
+
+
+/* Mutex attribute data structure.  */
+struct pthread_mutexattr
+{
+  /* Identifier for the kind of mutex.
+
+     Bit 31 is set if the mutex is to be shared between processes.
+
+     Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify
+     the type of the mutex.  */
+  int mutexkind;
+};
+
+
+/* Conditional variable attribute data structure.  */
+struct pthread_condattr
+{
+  /* Flag whether coditional variable will be shareable between processes.  */
+  int pshared;
+};
+
+
+/* Read-write lock variable attribute data structure.  */
+struct pthread_rwlockattr
+{
+  int lockkind;
+  int pshared;
+};
+
+
+/* Barrier data structure.  */
+struct pthread_barrier
+{
+  unsigned int curr_event;
+  int lock;
+  unsigned int left;
+  unsigned int init_count;
+};
+
+
+/* Barrier variable attribute data structure.  */
+struct pthread_barrierattr
+{
+  int pshared;
+};
+
+
+/* Thread-local data handling.  */
+struct pthread_key_struct
+{
+  /* Sequence numbers.  Even numbers indicated vacant entries.  Note
+     that zero is even.  We use uintptr_t to not require padding on
+     32- and 64-bit machines.  On 64-bit machines it helps to avoid
+     wrapping, too.  */
+  uintptr_t seq;
+
+  /* Destructor for the data.  */
+  void (*destr) (void *);
+};
+
+/* Check whether an entry is unused.  */
+#define KEY_UNUSED(p) (((p) & 1) == 0)
+/* Check whether a key is usable.  We cannot reuse an allocated key if
+   the sequence counter would overflow after the next destroy call.
+   This would mean that we potentially free memory for a key with the
+   same sequence.  This is *very* unlikely to happen, A program would
+   have to create and destroy a key 2^31 times (on 32-bit platforms,
+   on 64-bit platforms that would be 2^63).  If it should happen we
+   simply don't use this specific key anymore.  */
+#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2)))
+
+
+/* Handling of read-write lock data.  */
+// XXX For now there is only one flag.  Maybe more in future.
+#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0)
+
+
+/* Semaphore variable structure.  */
+struct sem
+{
+  unsigned int count;
+};
+
+#endif	/* internaltypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
new file mode 100644
index 0000000000..0fd3c9aa58
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
@@ -0,0 +1,33 @@
+/* _longjmp_unwind -- Clean up stack frames unwound by longjmp.  Linux version.
+   Copyright (C) 1995, 1997, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <setjmp.h>
+#include <stddef.h>
+
+
+extern void __pthread_cleanup_upto (jmp_buf env, char *targetframe);
+#pragma weak __pthread_cleanup_upto
+
+
+void
+_longjmp_unwind (jmp_buf env, int val)
+{
+  if (__pthread_cleanup_upto != NULL)
+    __pthread_cleanup_upto (env, __builtin_frame_address (0));
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/nptl/sysdeps/unix/sysv/linux/pt-fork.c
new file mode 100644
index 0000000000..a1e228ee29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pt-fork.c
@@ -0,0 +1,28 @@
+/* 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 <unistd.h>
+
+
+pid_t
+__fork (void)
+{
+  return __libc_fork ();
+}
+strong_alias (__fork, fork)
diff --git a/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/nptl/sysdeps/unix/sysv/linux/pt-raise.c
new file mode 100644
index 0000000000..0c68960e5d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pt-raise.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 <errno.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+int
+raise (sig)
+     int sig;
+{
+  return INLINE_SYSCALL (tkill, 2, THREAD_SELF->tid, sig);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
new file mode 100644
index 0000000000..f5c2377e7e
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
@@ -0,0 +1,36 @@
+/* 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 <errno.h>
+#include <signal.h>
+#include <pthreadP.h>
+#include <tls.h>
+#include <sysdep.h>
+
+
+int
+pthread_kill (threadid, signo)
+     pthread_t threadid;
+     int signo;
+{
+  struct pthread *pd = (struct pthread *) threadid;
+
+  /* We have a special syscall to do the work.  */
+  return INLINE_SYSCALL (tkill, 2, pd->tid, signo);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/nptl/sysdeps/unix/sysv/linux/pthread_yield.c
new file mode 100644
index 0000000000..5aecffcf0d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_yield.c
@@ -0,0 +1,30 @@
+/* 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 <pthread.h>
+#include <sched.h>
+
+
+/* With the 1-on-1 model we implement this function is equivalent to
+   the 'sched_yield' function.  */
+int
+pthread_yield (void)
+{
+  return sched_yield ();
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/raise.c b/nptl/sysdeps/unix/sysv/linux/raise.c
new file mode 100644
index 0000000000..009f32ad30
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/raise.c
@@ -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.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <nptl/pthreadP.h>
+
+
+int
+raise (sig)
+     int sig;
+{
+  struct pthread *pd = THREAD_SELF;
+  pid_t selftid = pd->tid;
+  if (selftid == 0)
+    {
+      selftid = INLINE_SYSCALL (gettid, 0);
+      THREAD_SETMEM (pd, tid, selftid);
+    }
+
+  return INLINE_SYSCALL (tkill, 2, selftid, sig);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
new file mode 100644
index 0000000000..ef70dde8a2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
@@ -0,0 +1,87 @@
+/* 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 <errno.h>
+#include <stdlib.h>
+#include "fork.h"
+
+
+int
+__register_atfork (prepare, parent, child, dso_handle)
+     void (*prepare) (void);
+     void (*parent) (void);
+     void (*child) (void);
+     void *dso_handle;
+{
+  struct fork_handler *new_prepare = NULL;
+  struct fork_handler *new_parent = NULL;
+  struct fork_handler *new_child = NULL;
+
+  if (prepare != NULL)
+    {
+      new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare));
+      if (new_prepare == NULL)
+	goto out1;
+
+      new_prepare->handler = prepare;
+      new_prepare->dso_handle = dso_handle;
+    }
+
+  if (parent != NULL)
+    {
+      new_parent = (struct fork_handler *) malloc (sizeof (*new_parent));
+      if (new_parent == NULL)
+	goto out2;
+
+      new_parent->handler = parent;
+      new_parent->dso_handle = dso_handle;
+    }
+
+  if (child != NULL)
+    {
+      new_child = (struct fork_handler *) malloc (sizeof (*new_child));
+      if (new_child == NULL)
+	{
+	  free (new_parent);
+	out2:
+	  free (new_prepare);
+	out1:
+	  return errno;
+	}
+
+      new_child->handler = child;
+      new_child->dso_handle = dso_handle;
+    }
+
+  /* Get the lock to not conflict with running forks.  */
+  lll_lock (__fork_lock);
+
+  /* Now that we have all the handlers allocate enqueue them.  */
+  if (new_prepare != NULL)
+    list_add_tail (&new_prepare->list, &__fork_prepare_list);
+  if (new_parent != NULL)
+    list_add_tail (&new_parent->list, &__fork_parent_list);
+  if (new_child != NULL)
+    list_add_tail (&new_child->list, &__fork_child_list);
+
+  /* Release the lock.  */
+  lll_unlock (__fork_lock);
+
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
new file mode 100644
index 0000000000..470f80d05c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
@@ -0,0 +1,49 @@
+/* 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 <errno.h>
+#include <stdlib.h>
+#include "fork.h"
+
+
+void
+__unregister_atfork (dso_handle)
+     void *dso_handle;
+{
+  /* Get the lock to not conflict with running forks.  */
+  lll_lock (__fork_lock);
+
+  list_t *runp;
+  list_t *prevp;
+
+  list_for_each_prev_safe (runp, prevp, &__fork_prepare_list)
+    if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+      list_del (runp);
+
+  list_for_each_prev_safe (runp, prevp, &__fork_parent_list)
+    if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+      list_del (runp);
+
+  list_for_each_prev_safe (runp, prevp, &__fork_child_list)
+    if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+      list_del (runp);
+
+  /* Release the lock.  */
+  lll_unlock (__fork_lock);
+}