about summary refs log tree commit diff
path: root/linuxthreads
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
committerUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
commita334319f6530564d22e775935d9c91663623a1b4 (patch)
treeb5877475619e4c938e98757d518bb1e9cbead751 /linuxthreads
parent0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff)
downloadglibc-a334319f6530564d22e775935d9c91663623a1b4.tar.gz
glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.xz
glibc-a334319f6530564d22e775935d9c91663623a1b4.zip
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/Banner1
-rw-r--r--linuxthreads/ChangeLog6468
-rw-r--r--linuxthreads/Changes85
-rw-r--r--linuxthreads/Examples/Makefile15
-rw-r--r--linuxthreads/Examples/ex1.c42
-rw-r--r--linuxthreads/Examples/ex10.c108
-rw-r--r--linuxthreads/Examples/ex11.c154
-rw-r--r--linuxthreads/Examples/ex12.c47
-rw-r--r--linuxthreads/Examples/ex13.c112
-rw-r--r--linuxthreads/Examples/ex14.c133
-rw-r--r--linuxthreads/Examples/ex15.c58
-rw-r--r--linuxthreads/Examples/ex16.c26
-rw-r--r--linuxthreads/Examples/ex17.c112
-rw-r--r--linuxthreads/Examples/ex18.c113
-rw-r--r--linuxthreads/Examples/ex2.c124
-rw-r--r--linuxthreads/Examples/ex3.c152
-rw-r--r--linuxthreads/Examples/ex4.c115
-rw-r--r--linuxthreads/Examples/ex5.c114
-rw-r--r--linuxthreads/Examples/ex6.c46
-rw-r--r--linuxthreads/Examples/ex7.c45
-rw-r--r--linuxthreads/Examples/ex8.c101
-rw-r--r--linuxthreads/Examples/ex9.c98
-rw-r--r--linuxthreads/Examples/tststatic.c1
-rw-r--r--linuxthreads/FAQ.html1039
-rw-r--r--linuxthreads/LICENSE501
-rw-r--r--linuxthreads/Makeconfig11
-rw-r--r--linuxthreads/Makefile345
-rw-r--r--linuxthreads/README166
-rw-r--r--linuxthreads/README.Xfree3.2352
-rw-r--r--linuxthreads/Versions188
-rw-r--r--linuxthreads/alloca_cutoff.c36
-rw-r--r--linuxthreads/attr.c485
-rw-r--r--linuxthreads/barrier.c128
-rw-r--r--linuxthreads/bug-sleep.c34
-rw-r--r--linuxthreads/cancel.c234
-rw-r--r--linuxthreads/condvar.c341
-rwxr-xr-xlinuxthreads/configure17
-rw-r--r--linuxthreads/configure.in14
-rw-r--r--linuxthreads/descr.h267
-rw-r--r--linuxthreads/ecmutex.c157
-rw-r--r--linuxthreads/errno.c47
-rw-r--r--linuxthreads/events.c37
-rw-r--r--linuxthreads/forward.c179
-rw-r--r--linuxthreads/internals.h550
-rw-r--r--linuxthreads/join.c220
-rw-r--r--linuxthreads/joinrace.c48
-rw-r--r--linuxthreads/libc-cancellation.c64
-rw-r--r--linuxthreads/libc-tls-loc.c49
-rw-r--r--linuxthreads/libc-tsd.c41
-rw-r--r--linuxthreads/libc_pthread_init.c46
-rw-r--r--linuxthreads/linuxthreads.texi1627
-rw-r--r--linuxthreads/lockfile.c82
-rw-r--r--linuxthreads/man/Makefile31
-rw-r--r--linuxthreads/man/pthread_atfork.man53
-rw-r--r--linuxthreads/man/pthread_attr_init.man221
-rw-r--r--linuxthreads/man/pthread_cancel.man155
-rw-r--r--linuxthreads/man/pthread_cleanup_push.man194
-rw-r--r--linuxthreads/man/pthread_cond_init.man234
-rw-r--r--linuxthreads/man/pthread_condattr_init.man39
-rw-r--r--linuxthreads/man/pthread_create.man46
-rw-r--r--linuxthreads/man/pthread_detach.man44
-rw-r--r--linuxthreads/man/pthread_equal.man23
-rw-r--r--linuxthreads/man/pthread_exit.man32
-rw-r--r--linuxthreads/man/pthread_join.man70
-rw-r--r--linuxthreads/man/pthread_key_create.man151
-rw-r--r--linuxthreads/man/pthread_kill_other_threads_np.man40
-rw-r--r--linuxthreads/man/pthread_mutex_init.man213
-rw-r--r--linuxthreads/man/pthread_mutexattr_init.man84
-rw-r--r--linuxthreads/man/pthread_mutexattr_setkind_np.man39
-rw-r--r--linuxthreads/man/pthread_once.man34
-rw-r--r--linuxthreads/man/pthread_self.man23
-rw-r--r--linuxthreads/man/pthread_setschedparam.man79
-rw-r--r--linuxthreads/man/pthread_sigmask.man123
-rw-r--r--linuxthreads/man/sem_init.man132
-rwxr-xr-xlinuxthreads/man/troffprepro68
-rw-r--r--linuxthreads/manager.c1112
-rw-r--r--linuxthreads/mutex.c362
-rw-r--r--linuxthreads/old_pthread_atfork.c27
-rw-r--r--linuxthreads/oldsemaphore.c241
-rw-r--r--linuxthreads/pt-allocrtsig.c50
-rw-r--r--linuxthreads/pt-machine.c25
-rw-r--r--linuxthreads/pt-system.c32
-rw-r--r--linuxthreads/ptcleanup.c52
-rw-r--r--linuxthreads/ptclock_gettime.c69
-rw-r--r--linuxthreads/ptclock_settime.c55
-rw-r--r--linuxthreads/ptfork.c93
-rw-r--r--linuxthreads/pthandles.c6
-rw-r--r--linuxthreads/pthread.c1407
-rw-r--r--linuxthreads/pthread_atfork.c63
-rw-r--r--linuxthreads/pthread_setegid.c27
-rw-r--r--linuxthreads/pthread_seteuid.c27
-rw-r--r--linuxthreads/pthread_setgid.c27
-rw-r--r--linuxthreads/pthread_setregid.c27
-rw-r--r--linuxthreads/pthread_setresgid.c27
-rw-r--r--linuxthreads/pthread_setresuid.c27
-rw-r--r--linuxthreads/pthread_setreuid.c27
-rw-r--r--linuxthreads/pthread_setuid.c27
-rw-r--r--linuxthreads/queue.h61
-rw-r--r--linuxthreads/restart.h49
-rw-r--r--linuxthreads/rwlock.c658
-rw-r--r--linuxthreads/semaphore.c307
-rw-r--r--linuxthreads/semaphore.h87
-rw-r--r--linuxthreads/shlib-versions11
-rw-r--r--linuxthreads/sighandler.c71
-rw-r--r--linuxthreads/signals.c213
-rw-r--r--linuxthreads/specific.c235
-rw-r--r--linuxthreads/spinlock.c720
-rw-r--r--linuxthreads/spinlock.h218
-rw-r--r--linuxthreads/sysdeps/alpha/elf/pt-initfini.c90
-rw-r--r--linuxthreads/sysdeps/alpha/pspinlock.c110
-rw-r--r--linuxthreads/sysdeps/alpha/pt-machine.h128
-rw-r--r--linuxthreads/sysdeps/alpha/tls.h129
-rw-r--r--linuxthreads/sysdeps/arm/pspinlock.c82
-rw-r--r--linuxthreads/sysdeps/arm/pt-machine.h55
-rw-r--r--linuxthreads/sysdeps/cris/pspinlock.c72
-rw-r--r--linuxthreads/sysdeps/cris/pt-machine.h58
-rw-r--r--linuxthreads/sysdeps/hppa/pspinlock.c81
-rw-r--r--linuxthreads/sysdeps/hppa/pt-machine.h62
-rw-r--r--linuxthreads/sysdeps/i386/Makefile23
-rw-r--r--linuxthreads/sysdeps/i386/i586/Versions5
-rw-r--r--linuxthreads/sysdeps/i386/i686/Versions5
-rw-r--r--linuxthreads/sysdeps/i386/i686/pt-machine.h79
-rw-r--r--linuxthreads/sysdeps/i386/pspinlock.c103
-rw-r--r--linuxthreads/sysdeps/i386/pt-machine.h108
-rw-r--r--linuxthreads/sysdeps/i386/tcb-offsets.sym7
-rw-r--r--linuxthreads/sysdeps/i386/tls.h225
-rw-r--r--linuxthreads/sysdeps/i386/useldt.h314
-rw-r--r--linuxthreads/sysdeps/ia64/Makefile3
-rw-r--r--linuxthreads/sysdeps/ia64/Versions5
-rw-r--r--linuxthreads/sysdeps/ia64/pspinlock.c79
-rw-r--r--linuxthreads/sysdeps/ia64/pt-machine.h133
-rw-r--r--linuxthreads/sysdeps/ia64/tcb-offsets.sym9
-rw-r--r--linuxthreads/sysdeps/ia64/tls.h141
-rw-r--r--linuxthreads/sysdeps/m68k/Makefile7
-rw-r--r--linuxthreads/sysdeps/m68k/pspinlock.c82
-rw-r--r--linuxthreads/sysdeps/m68k/pt-machine.h69
-rw-r--r--linuxthreads/sysdeps/mips/pspinlock.c98
-rw-r--r--linuxthreads/sysdeps/mips/pt-machine.h92
-rw-r--r--linuxthreads/sysdeps/powerpc/Makefile7
-rw-r--r--linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c70
-rw-r--r--linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h120
-rw-r--r--linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c70
-rw-r--r--linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h185
-rw-r--r--linuxthreads/sysdeps/powerpc/tcb-offsets.sym19
-rw-r--r--linuxthreads/sysdeps/powerpc/tls.h160
-rw-r--r--linuxthreads/sysdeps/pthread/Makefile14
-rw-r--r--linuxthreads/sysdeps/pthread/Subdirs1
-rw-r--r--linuxthreads/sysdeps/pthread/bits/initspin.h28
-rw-r--r--linuxthreads/sysdeps/pthread/bits/libc-lock.h413
-rw-r--r--linuxthreads/sysdeps/pthread/bits/libc-tsd.h59
-rw-r--r--linuxthreads/sysdeps/pthread/bits/pthreadtypes.h152
-rw-r--r--linuxthreads/sysdeps/pthread/bits/typesizes.h66
-rw-r--r--linuxthreads/sysdeps/pthread/errno-loc.c46
-rw-r--r--linuxthreads/sysdeps/pthread/flockfile.c33
-rw-r--r--linuxthreads/sysdeps/pthread/ftrylockfile.c33
-rw-r--r--linuxthreads/sysdeps/pthread/funlockfile.c33
-rw-r--r--linuxthreads/sysdeps/pthread/getcpuclockid.c49
-rw-r--r--linuxthreads/sysdeps/pthread/herrno-loc.c43
-rw-r--r--linuxthreads/sysdeps/pthread/list.h114
-rw-r--r--linuxthreads/sysdeps/pthread/malloc-machine.h67
-rw-r--r--linuxthreads/sysdeps/pthread/posix-timer.h204
-rw-r--r--linuxthreads/sysdeps/pthread/pt-initfini.c124
-rw-r--r--linuxthreads/sysdeps/pthread/pthread-functions.h96
-rw-r--r--linuxthreads/sysdeps/pthread/pthread.h686
-rw-r--r--linuxthreads/sysdeps/pthread/ptlongjmp.c39
-rw-r--r--linuxthreads/sysdeps/pthread/res-state.c47
-rw-r--r--linuxthreads/sysdeps/pthread/semaphore.h1
-rw-r--r--linuxthreads/sysdeps/pthread/sigaction.c55
-rw-r--r--linuxthreads/sysdeps/pthread/tcb-offsets.h1
-rw-r--r--linuxthreads/sysdeps/pthread/timer_create.c170
-rw-r--r--linuxthreads/sysdeps/pthread/timer_delete.c70
-rw-r--r--linuxthreads/sysdeps/pthread/timer_getoverr.c45
-rw-r--r--linuxthreads/sysdeps/pthread/timer_gettime.c77
-rw-r--r--linuxthreads/sysdeps/pthread/timer_routines.c573
-rw-r--r--linuxthreads/sysdeps/pthread/timer_settime.c137
-rw-r--r--linuxthreads/sysdeps/pthread/tst-timer.c114
-rw-r--r--linuxthreads/sysdeps/s390/Makefile6
-rw-r--r--linuxthreads/sysdeps/s390/pspinlock.c91
-rw-r--r--linuxthreads/sysdeps/s390/s390-32/pt-machine.h120
-rw-r--r--linuxthreads/sysdeps/s390/s390-64/pt-machine.h125
-rw-r--r--linuxthreads/sysdeps/s390/tcb-offsets.sym4
-rw-r--r--linuxthreads/sysdeps/s390/tls.h140
-rw-r--r--linuxthreads/sysdeps/sh/Makefile3
-rw-r--r--linuxthreads/sysdeps/sh/pspinlock.c80
-rw-r--r--linuxthreads/sysdeps/sh/pt-machine.h81
-rw-r--r--linuxthreads/sysdeps/sh/tcb-offsets.sym10
-rw-r--r--linuxthreads/sysdeps/sh/tls.h148
-rw-r--r--linuxthreads/sysdeps/sparc/Makefile3
-rw-r--r--linuxthreads/sysdeps/sparc/sparc32/pspinlock.c88
-rw-r--r--linuxthreads/sysdeps/sparc/sparc32/pt-machine.h83
-rw-r--r--linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions5
-rw-r--r--linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c94
-rw-r--r--linuxthreads/sysdeps/sparc/sparc64/Versions5
-rw-r--r--linuxthreads/sysdeps/sparc/sparc64/pspinlock.c93
-rw-r--r--linuxthreads/sysdeps/sparc/sparc64/pt-machine.h105
-rw-r--r--linuxthreads/sysdeps/sparc/tcb-offsets.sym4
-rw-r--r--linuxthreads/sysdeps/sparc/tls.h110
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/Implies1
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/Makefile3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/Versions5
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/allocalim.h26
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c87
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions6
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c33
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h92
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h66
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S28
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h146
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S70
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h145
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S80
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h92
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h181
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h38
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/execve.c73
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/fork.c43
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/fork.h60
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c33
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h27
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h73
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c109
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h189
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h64
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h179
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S95
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions6
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h92
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h49
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h25
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c140
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c33
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h144
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S54
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c34
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h129
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S84
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h144
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h143
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c287
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile2
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions5
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h131
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S78
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h127
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S91
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c70
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c56
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/raise.c36
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c88
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h72
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c154
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h137
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S69
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c137
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c1
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h116
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S54
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c143
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h24
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h227
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S77
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sigwait.c88
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/smp.h48
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions6
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c33
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h92
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h66
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h34
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h102
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S65
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile5
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c1
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h101
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S64
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c49
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile4
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c1
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h132
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S62
-rw-r--r--linuxthreads/sysdeps/x86_64/Makefile3
-rw-r--r--linuxthreads/sysdeps/x86_64/Versions5
-rw-r--r--linuxthreads/sysdeps/x86_64/pspinlock.c97
-rw-r--r--linuxthreads/sysdeps/x86_64/pt-machine.h225
-rw-r--r--linuxthreads/sysdeps/x86_64/tcb-offsets.sym4
-rw-r--r--linuxthreads/sysdeps/x86_64/tls.h129
-rw-r--r--linuxthreads/tst-_res1.c69
-rw-r--r--linuxthreads/tst-_res1mod1.c23
-rw-r--r--linuxthreads/tst-_res1mod2.c1
-rw-r--r--linuxthreads/tst-align.c71
-rw-r--r--linuxthreads/tst-attr1.c358
-rw-r--r--linuxthreads/tst-cancel-static.c1
-rw-r--r--linuxthreads/tst-cancel-wrappers.sh92
-rw-r--r--linuxthreads/tst-cancel.c214
-rw-r--r--linuxthreads/tst-cancel1.c150
-rw-r--r--linuxthreads/tst-cancel2.c100
-rw-r--r--linuxthreads/tst-cancel3.c98
-rw-r--r--linuxthreads/tst-cancel4.c469
-rw-r--r--linuxthreads/tst-cancel5.c1
-rw-r--r--linuxthreads/tst-cancel6.c79
-rw-r--r--linuxthreads/tst-cancel7.c111
-rw-r--r--linuxthreads/tst-cancel8.c287
-rw-r--r--linuxthreads/tst-clock1.c202
-rw-r--r--linuxthreads/tst-context.c116
-rw-r--r--linuxthreads/tst-popen.c37
-rw-r--r--linuxthreads/tst-popen2.c41
-rw-r--r--linuxthreads/tst-signal.c64
-rw-r--r--linuxthreads/tst-signal.sh28
-rw-r--r--linuxthreads/tst-stack1.c97
-rw-r--r--linuxthreads/tst-static-locale.c13
-rw-r--r--linuxthreads/tst-tls1.c91
-rw-r--r--linuxthreads/tst-tls1.h28
-rw-r--r--linuxthreads/tst-tls1mod.c6
-rw-r--r--linuxthreads/tst-tls1moda.c6
-rw-r--r--linuxthreads/tst-tls1modb.c6
-rw-r--r--linuxthreads/tst-tls1modc.c6
-rw-r--r--linuxthreads/tst-tls1modd.c6
-rw-r--r--linuxthreads/tst-tls1mode.c8
-rw-r--r--linuxthreads/tst-tls1modf.c9
-rw-r--r--linuxthreads/tst-tls2.sh53
-rw-r--r--linuxthreads/tststack.c74
-rw-r--r--linuxthreads/unload.c45
324 files changed, 42004 insertions, 0 deletions
diff --git a/linuxthreads/Banner b/linuxthreads/Banner
new file mode 100644
index 0000000000..f0be105a5d
--- /dev/null
+++ b/linuxthreads/Banner
@@ -0,0 +1 @@
+linuxthreads-0.10 by Xavier Leroy
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
new file mode 100644
index 0000000000..beaad8c6c5
--- /dev/null
+++ b/linuxthreads/ChangeLog
@@ -0,0 +1,6468 @@
+2004-12-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h: Include <stdbool.h> to match includes used in nptl.
+
+2004-12-01  Jakub Jelinek  <jakub@redhat.coM.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_CPUTIME,
+	_POSIX_THREAD_CPUTIME): Define to 0.
+	* sysdeps/pthread/timer_create.c (timer_create): Remove unused code
+	handling CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.
+	* sysdeps/pthread/timer_routines.c (__timer_signal_thread_pclk,
+	__timer_signal_thread_tclk): Remove.
+	(init_module): Remove their initialization.
+	(thread_cleanup): Remove their cleanup assertions.
+	* sysdeps/pthread/posix-timer.h (__timer_signal_thread_pclk,
+	__timer_signal_thread_tclk): Remove.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Removed.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Removed.
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Removed.
+	* tst-clock1.c (do_test): Check for availability of CPU clock.
+
+2004-11-18  Daniel Jacobowitz  <dan@codesourcery.com>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h: Update RETINSTR use.
+	* sysdeps/unix/sysv/linux/arm/vfork.S: Likewise.
+
+2004-12-02  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (libpthread-nonshared): Variable removed.
+	($(objpfx)libpthread_nonshared.a): Target removed.
+	($(inst_libdir)/libpthread_nonshared.a): Likewise.
+	These are now handled by generic magic from
+	libpthread-static-only-routines being set.
+
+2004-11-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_PRIORITIZED_IO,
+	_POSIX2_CHAR_TERM, _POSIX_THREAD_PRIO_INHERIT,
+	_POSIX_THREAD_PRIO_PROTECT): Define.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise.
+
+2004-11-26  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_ADVISORY_INFO,
+	_POSIX_SPORADIC_SERVER, _POSIX_THREAD_SPORADIC_SERVER, _POSIX_TRACE,
+	_POSIX_TRACE_EVENT_FILTER, _POSIX_TRACE_INHERIT, _POSIX_TRACE_LOG,
+	_POSIX_TYPED_MEMORY_OBJECTS): Define.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise.
+
+2004-11-05  Maciej W. Rozycki  <macro@mips.com>
+
+	* sysdeps/mips/pspinlock.c: Include <sgidefs.h>.  Use _ABIO32,
+	_ABIN32 and _ABI64 for ABI selection throughout.
+	* sysdeps/mips/pt-machine.h: Use _ABIO32, _ABIN32 and _ABI64 for
+	ABI selection throughout.
+
+2004-10-18  Roland McGrath  <roland@redhat.com>
+
+	[BZ #406]
+	* Makefile (linuxthreads-CPPFLAGS): New variable;
+	adds -DIS_IN_linuxthreads=1.
+	* sysdeps/i386/tls.h: Protect "useldt.h" with
+	[!IS_IN_linuxthreads && !DO_MODIFY_LDT].
+	* sysdeps/i386/i686/pt-machine.h: Revert last change.
+
+2004-10-14  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/errno-loc.c: Don't undef #errno
+	if RTLD_PRIVATE_ERRNO.
+
+2004-10-05  Dwayne Grant McConnell  <dgm69@us.ibm.com>
+
+	* pthread.c: Mask restart signal during cancel signal handler.
+
+2004-10-05  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h (_POSIX_CPUTIME,
+	_POSIX_THREAD_CPUTIME): Define to 0.
+
+2004-10-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Set _POSIX_CPUTIME
+	and _POSIX_THREAD_CPUTIME to zero.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
+	_POSIX_THREAD_PROCESS_SHARED and _POSIX_CLOCK_SELECTION as -1.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise.
+
+2004-09-25  Roland McGrath  <roland@redhat.com>
+
+	[BZ #406]
+	* sysdeps/i386/i686/pt-machine.h: Don't #include "../useldt.h" if
+	[_TLS_H], since sysdeps/i386/tls.h includes it after including us.
+
+2004-09-24  Roland McGrath  <roland@redhat.com>
+
+	[BZ #406]
+	* sysdeps/i386/tls.h: Move #include "useldt.h" outside
+	of [__ASSUME_LDT_WORKS > 0] test.
+	Reported by Carlos Velasco <carlos.velasco@newipnet.com>.
+
+2004-09-21  Roland McGrath  <roland@redhat.com>
+
+	* Versions: Add comment about linuxthreads' frozen ABI.
+
+2004-09-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions: Remove exports for pthread_set*id_np functions.
+	* sysdeps/pthread/pthread.h: Remove pthread_set*id_np prototypes
+	for now.
+	* Makefile: Don't build pthread_set*id code for now.
+
+2004-09-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Declare pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* pthread_setgid_np.c: New file.
+	* pthread_setuid_np.c: New file.
+	* pthread_setegid_np.c: New file.
+	* pthread_seteuid_np.c: New file.
+	* pthread_setregid_np.c: New file.
+	* pthread_setreuid_np.c: New file.
+	* pthread_setresgid_np.c: New file.
+	* pthread_setresuid_np.c: New file.
+	* Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid,
+	pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid,
+	pthread_setregid, and pthread_setresgid.
+
+2004-09-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Make rwlock prototypes available also
+	for __USE_XOPEN2K.
+	* sysdeps/pthread/bits/pthreadtypes.h: Define rwlock types also
+	for __USE_XOPEN2K.  [BZ #320]
+
+2004-09-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* tst-cancel4.c (tf_waitid): Use WEXITED flag bit if available.
+
+2004-09-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h (pthread_once): Remove __THROW since
+	the initialization function might throw.
+
+2004-08-30  Roland McGrath  <roland@frob.com>
+
+	* Makefile (libpthread-abi-frozen): New variable.
+
+2004-08-26  Roland McGrath  <roland@redhat.com>
+
+	* configure.in: New file.  If nptl add-on is also selected, barf if
+	explicit and elide ourselves if implicit.
+	* configure: Now generated.
+
+2004-08-25  Richard Sandiford  <rsandifo@redhat.com>
+
+	* sysdeps/unix/sysv/linux/mips/sysdep-cancel.h (CENABLE, CDISABLE,
+	__local_multiple_threads): Fix definitions for IS_IN_librt.
+	* sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h: Likewise.
+
+2004-08-22  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO) [IS_IN_librt]:
+	Save gp around CENABLE/CDISABLE calls.
+
+2004-08-15  Roland McGrath  <roland@frob.com>
+
+	* pthread_atfork.c: Update copyright terms including special exception
+	for these trivial files, which are statically linked into executables
+	that use dynamic linking for the significant library code.
+
+2004-08-09  Jakub Jelinek  <jakub@redhat.com>
+
+	* libc-tsd.c: Move resolv.h include before the #if.
+	(__res_maybe_init): New function.  Add libc_hidden_def.
+
+2004-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* linuxthreads.texi (Cleanup Handlers): Fix typo.
+	Reported by Bjoern Engelmann <bjengelmann@gmx.de>.
+
+2004-07-23  Jakub Jelinek  <jakub@redhat.com>
+
+	[BZ #284]
+	* sysdeps/pthread/pthread.h (pthread_getcpuclockid): Use __clockid_t
+	instead of clockid_t.
+
+2004-07-21  Roland McGrath  <roland@redhat.com>
+
+	* Makefile ($(objpfx)multidir.mk): Use $(make-target-directory).
+
+2004-07-02  Roland McGrath  <roland@redhat.com>
+
+	* configure: Don't exit.
+
+2004-07-20  Alexandre Oliva  <aoliva@redhat.com>
+
+	* sysdeps/mips/pt-machine.h: Use standard names for ABI macros,
+	include sgidefs.h.
+	* sysdeps/mips/atomicity.h: Likewise.
+
+2004-07-19  Alexandre Oliva  <aoliva@redhat.com>
+
+	* sysdeps/unix/sysv/linux/mips/Makefile (CFLAGS-pt-initfini.s):
+	Remove redundant override that missed -g0.
+
+2004-07-14  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
+	(__local_multiple_threads): Define for librt.
+	(SINGLE_THREAD_P): Likewise.
+
+2004-07-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/getcpuclockid.c (pthread_getcpuclockid): Allow
+	using other thread's clock.
+	* ptclock_gettime.c (__pthread_clock_gettime): Likewise.
+	* ptclock_settime.c (__pthread_clock_settime): Likewise.
+	* internals.h (__pthread_clock_gettime, __pthread_clock_settime):
+	Remove prototypes.
+	Reported by Bernd Schmidt <bernds@redhat.com>.
+	* Makefile (librt-tests): Add tst-clock1.
+	* tst-clock1.c: New test.
+
+	* sysdeps/x86_64/Versions: New file.
+	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file.
+	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file.
+
+2004-04-16  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/ia64/tls.h (INIT_SYSINFO): Cast dl_sysinfo to void*.
+
+2004-07-05  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/s390/pspinlock.c (__pthread_spin_lock,
+	__pthread_spin_trylock): Use constraint "m" instead of "0" for
+	futex.
+	* sysdeps/ia64/pt-machine.h (__compare_and_swap,
+	__compare_and_swap_with_release_semantic, testandset): Use
+	constraint "m" instead of "0" for futex.
+
+2004-06-29  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (CENABLE): Fix
+	branch offset for a PLT entry.
+	(CDISABLE): Likewise.
+
+2004-05-31  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/mips/Makefile (CFLAGS-pt-initfini.s):
+	Set to -fno-unit-at-a-time.
+	Patch by Dan Kegel <dank@kegel.com>.
+
+2004-05-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* tst-stack1.c: Don't include mcheck.h.
+	(do_test): Make sure user defined stacks aren't reused,
+	don't free them at the end.  [BZ #110]
+
+2004-05-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* manager.c: Include not-cancel.h.
+	(__pthread_manager): Use read_not_cancel instead of __libc_read.
+	(pthread_start_thread, __pthread_manager_sighandler): Use
+	write_not_cancel instead of __libc_write.
+	(pthread_reap_children): Use waitpid_not_cancel instead of
+	__libc_waitpid.
+	* pthread.c: Include not-cancel.h.
+	(__pthread_initialize_minimal, __pthread_create_2_1,
+	pthread_onexit_process, __pthread_message): Use
+	write_not_cancel instead of __libc_write.
+	(__pthread_initialize_manager): Likewise.  Use close_not_cancel
+	instead of __libc_close.
+	(__pthread_reset_main_thread): Use close_not_cancel instead of
+	__libc_close.
+	* join.c: Include not-cancel.h.
+	(__pthread_do_exit, pthread_join, pthread_detach): Use
+	write_not_cancel instead of __libc_write.
+	* semaphore.c: Include not-cancel.h.
+	(__new_sem_post): Use write_not_cancel instead of __libc_write.
+	* specific.c: Include not-cancel.h.
+	(pthread_key_delete): Use write_not_cancel instead of __libc_write.
+
+2004-05-01  Jakub Jelinek  <jakub@redhat.com>
+
+	* Versions (libc): Add __on_exit and __libc_sigaction.
+
+2004-04-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* semaphore.c (sem_timedwait): Return -1 and set errno instead of
+	returning error number [BZ #133].  Patch by <rmhaddad@yahoo.com>.
+
+2004-04-22  SUGIOKA Toshinobu  <sugioka@itonet.co.jp>
+
+	* sysdeps/unix/sysv/linux/sh/vfork.S: Fix wrong function pointer
+	reference in PIC case.
+
+2004-04-20  Jakub Jelinek  <jakub@redhat.com>
+
+	* oldsemaphore.c (SEM_VALUE_MAX): Remove.
+
+2004-04-19  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (CENABLE): Define
+	for librt.  Save the return value to a safe register.
+	(CDISABLE): Define for librt.  Set the function argument correctly.
+
+2004-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
+	(PSEUDO_CANCEL): Define.
+	(PSEUDO): Use it.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (CENABLE,
+	CDISABLE): For librt, append @PLT.
+
+2004-04-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/x86_64/tls.h [!__ASSEMBLER__]: Include tcb-offsets.h.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): For expired timer
+	return it_value { 0, 0 }.
+	* sysdeps/pthread/timer_create.c (timer_create): Handle SIGEV_NONE
+	like SIGEV_SIGNAL.
+	* sysdeps/pthread/timer_routines.c (thread_expire_timer): Remove
+	assertion for SIGEV_NONE.
+	(thread_attr_compare): Compare all attributes, not just a partial
+	subset.
+
+	* sysdeps/unix/sysv/linux/mq_notify.c: Include stdlib.h.
+
+2004-04-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* semaphore.h (SEM_VALUE_MAX): Just use a plain number.
+
+2004-04-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Fix last patch.
+
+2004-04-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/mq_notify.c: Shut up GCC warning.
+
+2004-04-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/mq_notify.c: New file.
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (CENABLE): Define
+	for librt.
+	(CDISABLE): Likewise.
+
+2004-04-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h (MQ_PRIO_MAX): Define.
+	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h (MQ_PRIO_MAX): Define.
+	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h (MQ_PRIO_MAX): Define.
+	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h (MQ_PRIO_MAX): Define.
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_MESSAGE_PASSING):
+	Define.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h
+	(_POSIX_MESSAGE_PASSING): Define.
+
+2004-04-10  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/pt-machine.h: Add used attribute to stack_pointer
+	to avoid warnings with GCC 3.5.
+
+2004-04-09  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/powerpc/tls.h (TLS_INIT_TP): Eliminate lvalue cast from
+	__thread_self assignment.
+	(THREAD_DTV): Replace __thread_register with __thread_self.
+	(INIT_THREAD_SELF): Eliminate lvalue cast from __thread_self
+	assignment.
+
+2004-04-08  Alexandre Oliva  <aoliva@redhat.com>
+
+	* signals.c (pthread_sigmask): Don't ever block or mask
+	__pthread_sig_debug.
+
+2004-03-11  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/powerpc/tls.h: Remove __powerpc64__ conditional.
+
+2004-03-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/ia64/pt-machine.h (BUSY_WAIT_NOP): Define.
+	* sysdeps/x86_64/pt-machine.h (BUSY_WAIT_NOP): Likewise.
+
+2004-03-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Add HOST_NAME_MAX.
+	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise.
+
+2004-03-08  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT_KERNEL_CHECK):
+	dl_osversion is readonly.
+
+2004-03-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h (INIT_SYSINFO): _dl_sysinfo is now in
+	_rtlf_global_ro.
+	* sysdeps/ia64/tls.h (INIT_SYSINFO): Likewise.
+
+2004-02-20  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c [SHARED]: Code only
+	valid for SHARED case.  Correct spelling of __vmx_longjmp.
+
+	* sysdeps/powerpc/pspinlock.c: Move from here.
+	* sysdeps/powerpc/powerpc32/pspinlock.c: To here.
+	* sysdeps/powerpc/powerpc64/pspinlock.c: New file.
+	* sysdeps/powerpc/powerpc64/pt-machine.h: Define __compare_and_swap32
+	and __compare_and_swap32_with_release_semantics.
+
+2004-02-20  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (generated): Remove tst-stack1.mtrace and tst-stack1-mem.
+	(tests): Remove $(objpfx)tst-stack1-mem.
+	(tst-stack1-ENV): Remove.
+	($(objpfx)tst-stack1-mem): Remove.
+
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
+	(__syscall_error_handler2): Call CDISABLE.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
+	(__syscall_error_handler2): Call CDISABLE.
+
+	* sysdeps/unix/sysv/linux/ia64/dl-sysdep.h (DL_ARGV_NOT_RELRO): Define.
+
+2004-02-10  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* Makefile (libpthread-routines): Add ptcleanup.
+	* ptlongjmp.c: Removed.
+	* ptcleanup.c: Copied __pthread_cleanup_upto to here. New file.
+	* sysdeps/pthread/ptlongjmp.c: Copied longjmp to here. New file.
+	* sysdeps/unix/sysv/linux/powerpc/Versions: New file.
+	Version longjmp, siglongjmp for GLIBC_2.3.4.
+	* sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c: New File.
+
+2004-01-22  Andreas Jaeger  <aj@suse.de>
+
+	* spinlock.c (__pthread_lock): Fix contraint to avoid warning.
+	(__pthread_release): Likewise.
+
+2004-01-16  Richard Henderson  <rth@redhat.com>
+
+	* attr.c: Include ldsodefs.h.
+	(pthread_getattr_np): Don't declare __libc_stack_end.
+
+2004-01-09  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
+	[!HAVE_TLS_SUPPORT]: Define SINGLE_THREAD_P using static
+	__lib*_multiple_threads.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+	[!HAVE_TLS_SUPPORT]: Likewise.
+
+2004-01-13  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/powerpc/tcb-offsets.sym: Put -- separator line before any
+	conditionals.
+
+2004-01-10  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/x86_64/vfork.S: Add cfi directives.
+
+2004-01-01  Andreas Jaeger  <aj@suse.de>
+
+	* Makefile (generated): Add missing files.
+
+2003-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (pthread_getattr_np): Make sure stack info returned for
+	main thread does not overlap with any other VMA.
+	Patch by Jakub Jelinek.
+
+2003-12-29  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/ia64/tls.h: Include dl-sysdep.h.
+	(INIT_SYSINFO): Define.
+	(TLS_INIT_TP): Use it.
+
+2003-12-28  Carlos O'Donell  <carlos@baldric.uwo.ca>
+
+	* attr.c (pthread_getattr_np): Add _STACK_GROWS_UP case.
+
+2003-12-26  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/pthread.h (pthread_setcancelstate,
+	pthread_setcanceltype, pthread_cancel, pthread_testcancel): Remove
+	__THROW.
+	* semaphore.h (sem_wait, sem_timedwait): Likewise.
+
+2003-12-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* manager.c (pthread_free): Call _dl_deallocate_tls even for
+	p_userstack threads.
+	* pthread.c (__pthread_initialize_manager): Call _dl_deallocate_tls
+	on error.
+	(pthread_onexit_process): Update comment.
+	* Makefile (tests): Add tst-stack1.  Depend on $(objpfx)tst-stack1-mem.
+	(generated): Add tst-stack1.mtrace and tst-stack1-mem.
+	(tst-stack1-ENV): Set.
+	($(objpfx)tst-stack1-mem): New.
+	* tst-stack1.c: New test.
+
+2003-12-16  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/powerpc/tcb-offsets.sym [!__powerpc64__]: Remove
+	conditional so MULTIPLE_THREADS_OFFSET is generated for both.
+	* sysdeps/powerpc/tls.h [!__powerpc64__]: Remove conditional
+	so TLS_MULTIPLE_THREADS_IN_TCB is generated for both.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h:
+	Include tls.h.
+
+2003-12-04  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+	(SINGLE_THREAD_P): Test using thread local p_multiple_threads field.
+
+2003-12-10  David Mosberger  <davidm@hpl.hp.com>
+
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Update copyright
+	message.  Add include of <stddef.h>.
+	(INIT_NEW_WAY): New macro.
+	(INIT_OLD_WAY): Likewise.
+	(_init): Add unwind directives.  Invoke
+	__pthread_initialize_minimal() via INIT_NEW_WAY or INIT_OLD_WAY,
+	respectively.
+	(_init_EPILOG_BEGINS): Add unwind-directives.  Drop unused .regstk
+	directive.
+	(_fini): Add unwind directives.  Drop unnecessary .align 16
+	directive (bundles are always 16-byte aligned).
+	(_fini_EPILOG_BEGINS): Add unwind-directives.
+
+2003-11-19  David Mosberger  <davidm@hpl.hp.com>
+
+	* sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: New file.
+
+2003-12-10  Andreas Jaeger  <aj@suse.de>
+	    Ruediger Oertel  <ro@suse.de>
+
+	* sysdeps/alpha/elf/pt-initfini.c (__asm__): Remove extra .prologue.
+
+2003-11-30  Andreas Jaeger  <aj@suse.de>
+
+	* Makefile (CFLAGS-pt-initfini.s): Add $(fno_unit_at_a_time).
+	* sysdeps/unix/sysv/linux/x86_64/Makefile (CFLAGS-pt-initfini.s):
+	Likewise.
+
+2003-11-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* signals.c (__pthread_sigaction): Set __sighandler[sig].old before
+	__libc_sigaction if it has been one of the special values before.
+
+2003-10-06  Carlos O'Donell <carlos@baldric.uwo.ca>
+
+	* pthread.c (__pthread_self_stack): _STACK_GROWS_UP case added.
+	(__pthread_find_self): Likewise.
+	* manager.c (thread_segment): _STACK_GROWS_UP case added.
+
+2003-10-10  Carlos O'Donell  <carlos@baldric.uwo.ca>
+
+	* linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h: New file.
+
+2003-10-10  Carlos O'Donell  <carlos@baldric.uwo.ca>
+
+	* sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h: New file.
+
+2003-10-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Backout 2003-10-02
+	changes.
+	(SAVE_OLDTYPE_0): Fix a typo.
+
+2003-10-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (DOCARGS_1): Use
+	correct offset.
+
+2003-10-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (tests): Add tst-cancel8.
+	* tst-cancel8.c: New test.
+
+2003-10-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Fix saving and
+	restoring of the old cancellation type.
+
+2003-09-10  Chris Demetriou  <cgd@broadcom.com>
+
+	* sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h: New file.
+
+2003-09-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/malloc-machine.h [!__libc_maybe_call2] (mutex_init,
+	mutex_lock, mutex_trylock, mutex_unlock): Remove.
+
+2003-09-27  Wolfram Gloger  <wg@malloc.de>
+
+	* sysdeps/pthread/malloc-machine.h: New file.
+
+2003-09-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* attr.c (__pthread_attr_init_2_1): Double __guardsize size
+	if NEED_SEPARATE_REGISTER_STACK is defined.
+
+2003-09-22  Philip Blundell  <philb@gnu.org>
+
+	* forward.c: Add _pthread_cleanup_push, _pthread_cleanup_pop.
+	* sysdeps/pthread/pthread-functions.h (struct pthread_functions):
+	Likewise.
+	* pthread.c (__pthread_elements): Initialise these new elements.
+	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_push): Use
+	__libc_maybe_call.
+	(__libc_cleanup_pop): Likewise.
+
+2003-09-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* attr.c: Include stdlib.h.
+
+2003-09-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/pthread.h (pthread_getattr_np): Clarify usage.
+
+	* tst-attr1.c: New test.
+	* Makefile (tests): Add tst-attr1.
+
+2003-09-17  Philip Blundell  <philb@gnu.org>
+
+	* sysdeps/unix/sysv/linux/arm/vfork.S: Branch to fork if
+	libpthread is loaded.  Elide backwards compatibility code when not
+	required.
+
+2003-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* descr.h (manager_thread): Rename to...
+	(__pthread_manager_threadp): ... this.
+	* pthread.c (manager_thread): Define to __pthread_manager_threadp.
+	(__pthread_manager_threadp): New variable.
+	* internals.h (__manager_thread): Define to
+	__pthread_manager_threadp if USE_TLS.
+
+2003-09-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/Makefile (CFLAGS-cancel.c, CFLAGS-manager.c,
+	CFLAGS-pthread.c, CFLAGS-sighandler.c): Add
+	-mpreferred-stack-boundary=4.
+
+2003-09-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (pthread_getattr_np): Correctly fill in the stack-related
+	values for the initial thread.
+
+2003-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (manager_thread): Remove static, add attribute_hidden.
+	(thread_self_stack): Rename to...
+	(__pthread_self_stack): ... this.  Remove static.
+	(pthread_handle_sigcancel): Use check_thread_self ().
+	(pthread_handle_sigrestart): Likewise.
+	* sighandler.c (__pthread_sighandler, __pthread_sighandler_rt):
+	Likewise.
+	* descr.h (manager_thread): Declare.
+	* internals.h (__pthread_self_stack): New prototype.
+	(__manager_thread): Define.
+	(check_thread_self): New function.
+
+2003-09-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (CFLAGS-mutex.c): Add $(uses-callbacks).
+	(CFLAGS-sighandler.c): Change $(exceptions) into $(uses-callbacks).
+
+2003-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/s390/bits/typesizes.h: New.
+	(__SSIZE_T_TYPE): Define to __SWORD_TYPE for gcc 2.95.x and
+	__SLONGWORD_TYPE otherwise.
+
+2003-09-11  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/pt-machine.h [MEMORY_BARRIER]: Use lwsync.
+	[READ_MEMORY_BARRIER]: Define.
+	[WRITE_MEMORY_BARRIER]: Define.
+
+2003-09-10  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): Move
+	ptr___pthread_cond_timedwait to the end of the structure to avoid
+	breaking Wine unnecessarily.
+
+2003-09-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/s390/bits/typesizes.h: Remove.
+
+2003-09-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: New file.
+	* sysdeps/unix/sysv/linux/alpha/Versions: New file.
+	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: New file.
+	* sysdeps/unix/sysv/linux/ia64/Versions: New file.
+	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: New file.
+	* sysdeps/unix/sysv/linux/sparc/Versions: New file.
+	* attr.c (__old_pthread_attr_setstacksize,
+	__old_pthread_attr_setstack): New functions.
+	(pthread_attr_setstacksize): If PTHREAD_STACK_MIN != 16384, export
+	as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.1.
+	(pthread_attr_setstack): If PTHREAD_STACK_MIN != 16384, export
+	as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.2.
+	* tststack.c: Include limits.h and sys/param.h.
+	(main): Set size to MAX (70 * 1024, PTHREAD_STACK_MIN).
+
+	* barrier.c (__pthread_barrierattr_getpshared): Always
+	return PTHREAD_PROCESS_PRIVATE.
+	(pthread_barrierattr_setpshared): Return EINVAL if pshared
+	is neither PTHREAD_PROCESS_PRIVATE nor PTHREAD_PROCESS_SHARED.
+
+2003-09-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h
+	(DL_SYSINFO_IMPLEMENTATION): Add CFI and make sure the code ends
+	up in .text.
+
+	* barrier.c (pthread_barrierattr_setpshared): We don't handle
+	inter-process barriers.
+
+2003-09-01  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (tests): Add tst-tls1.
+	(module-names): Add tst-tls1mod{,a,b,c,d,e,f}.
+	($(objpfx)tst-tls1mod{,a,b,c,d,e,f}.so-no-z-defs): Set to yes.
+	($(objpfx)tst-tls1): New.
+	($(objpfx)tst-tls2.out): Likewise.
+	(tests): Depend on $(objpfx)tst-tls2.out.
+	* tst-tls1.c: New test.
+	* tst-tls1.h: New.
+	* tst-tls1mod.c: New.
+	* tst-tls1moda.c: New.
+	* tst-tls1modb.c: New.
+	* tst-tls1modc.c: New.
+	* tst-tls1modd.c: New.
+	* tst-tls1mode.c: New.
+	* tst-tls1modf.c: New.
+	* tst-tls2.sh: New test.
+
+	* internals.h (__pthread_cond_timedwait): New prototype.
+	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): Add
+	ptr___pthread_cond_timedwait.
+	* pthread.c (__pthread_functions): Initialize them.
+	* forward.c (pthread_cond_timedwait@GLIBC_2.0,
+	pthread_cond_timedwait@@GLIBC_2.3.2): New forwards.
+	* Versions (libc): Export pthread_cond_timedwait@GLIBC_2.0,
+	pthread_cond_timedwait@@GLIBC_2.3.2.
+
+2003-08-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Don't mark pthread_exit,
+	pthread_join, pthread_cond_wait, and pthread_cond_timedwait with
+	__THROW to match NPTL.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/Makefile [subdir=rt] (CPPFLAGS): Add
+	-DBROKEN_THREAD_SIGNALS.
+
+2003-08-11  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* manager.c (pthread_start_thread) [!(USE_TLS && HAVE___THREAD)]:
+	Correct spelling of per thread resolver state.
+
+2003-08-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h [_LIBC && SHARED]
+	(__rtld_lock_default_lock_recursive,
+	__rtld_lock_default_unlock_recursive): Define.
+	[_LIBC && SHARED] (__rtld_lock_lock_recursive,
+	__rtld_lock_unlock_recursive): Define using
+	GL(_dl_rtld_*lock_recursive).
+	* pthread.c (pthread_initialize): Initialize _dl_rtld_lock_recursive
+	and _dl_rtld_unlock_recursive.  Lock GL(_dl_load_lock) the same
+	number of times as GL(_dl_load_lock) using non-mt implementation was
+	nested.
+
+2003-07-31  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/typesizes.h (__SSIZE_T_TYPE): Define.
+	* sysdeps/unix/sysv/linux/alpha/bits/typesizes.h (__SSIZE_T_TYPE):
+	Likewise.
+	* sysdeps/unix/sysv/linux/sparc/bits/typesizes.h (__SSIZE_T_TYPE):
+	Likewise.
+	* sysdeps/unix/sysv/linux/s390/bits/typesizes.h: New file.
+
+	* sysdeps/pthread/pthread.h (pthread_attr_setstackaddr,
+	pthread_attr_setstacksize): Change PTHREAD_STACK_SIZE to
+	PTHREAD_STACK_MIN in comments.
+
+	* sysdeps/alpha/pt-machine.h (PT_EI): Add
+	__attribute__((always_inline)).
+	* sysdeps/arm/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/cris/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/hppa/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/i386/i686/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/i386/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/ia64/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/m68k/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/mips/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/powerpc/powerpc32/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/powerpc/powerpc64/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/s390/s390-32/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/s390/s390-64/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/sh/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h (PT_EI): Likewise.
+	* sysdeps/x86_64/pt-machine.h (PT_EI): Likewise.
+	* spinlock.h (__pthread_set_own_extricate_if): Likewise.
+	* sysdeps/ia64/tls.h (TLS_INIT_TP): Cast tcbp to __typeof
+	(__thread_self).
+	* Examples/ex13.c (main): Change res type to void * to avoid
+	warnings.
+	* tst-cancel.c (cleanup, inner, tf1, tf2, tf3): Comment out.
+
+2003-07-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (init_one_static_tls, __pthread_init_static_tls): New
+	functions.
+	(pthread_initialize): Initialize GL(dl_init_static_tls).
+
+2003-06-19  Daniel Jacobowitz  <drow@mvista.com>
+
+	* sysdeps/pthread/timer_create.c (timer_create): Call timer_delref
+	before __timer_dealloc.
+	* sysdeps/pthread/timer_routines.c (__timer_thread_find_matching):
+	Don't call list_unlink.
+
+2003-07-29  Roland McGrath  <roland@redhat.com>
+
+	* Makefile [$(build-shared) = yes] (tests): Depend on $(test-modules).
+
+2003-07-25  Roland McGrath  <roland@redhat.com>
+
+	* manager.c (pthread_start_thread): Fix typo in last change.
+
+2003-07-14  Guido Guenther  <agx@sigxcpu.org>
+
+	* sysdeps/unix/sysv/linux/mips/sysdep-cancel.h: Add IS_IN_librt,
+	use L() for local labels.
+
+2003-07-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* descr.h (struct _pthread_descr_struct): Provide p_res member
+	even if USE_TLS && HAVE___THREAD.
+	* sysdeps/pthread/res-state.c (__res_state): Return __resp
+	if USE___THREAD.
+	* manager.c: Include resolv.h.
+	(pthread_start_thread): Initialize __resp.
+	* libc-tls-loc.c (__res_state): Return __resp.
+	* Makefile (tests): Add tst-_res1.
+	(modules-names, extra-objs, test-extras, test-modules): Add support
+	for test modules.
+	($(objpfx)tst-_res1mod2.so): Depend on $(objpfx)tst-_res1mod1.so.
+	($(objpfx)tst-_res1): Depend on $(objpfx)tst-_res1mod2.so and
+	-lpthread.
+	* tst-_res1.c: New test.
+	* tst-_res1mod1.c: New test.
+	* tst-_res1mod2.c: New test.
+
+2003-07-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h: Define __libc_cleanup_push and
+	__libc_cleanup_pop.
+
+	* tst-cancel-wrappers.sh: lseek and llseek are no cancellation points.
+
+2003-07-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Fix typo
+	in test for compilation in libc.
+
+2003-07-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Use
+	different symbol for the cancellation syscall wrapper and
+	non-cancellation syscall wrapper.
+	(PSEUDO_END): Define.
+
+2003-07-05  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/alpha/elf/pt-initfini.c: Avoid .ent/.end.
+
+2003-06-20  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Support cancellation
+	in librt.
+
+2003-06-21  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h: Support cancellation
+	in librt.
+
+2003-06-20  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/Makefile (libpthread-routines):
+	Remove ptw-osf_sigprocmask.
+
+2003-06-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (__librt_multiple_threads, __librt_enable_asynccancel,
+	__librt_disable_asynccancel): Declare.
+	(LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET, LIBC_CANCEL_HANDLED): Define
+	for IS_IN_librt.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Support cancellation
+	in librt.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise.
+	* sysdeps/x86_64/tcb-offsets.sym: New file.
+	* sysdeps/x86_64/Makefile: New file.
+	* sysdeps/x86_64/tls.h (tcbhead_t): Add multiple_threads.
+	* Versions (libc): Export __librt_enable_asynccancel,
+	__librt_disable_asynccancel and __librt_multiple_threads as
+	GLIBC_PRIVATE.
+	* libc-cancellation.c (__librt_multiple_threads,
+	__librt_enable_asynccancel, __librt_disable_asynccancel): New aliases.
+
+2003-06-12  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+	(SINGLE_THREAD_P): Replace @ got notation with @toc.
+
+2003-06-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/powerpc/pspinlock.c (__pthread_spin_init): Fix
+	initializer [PR libc/5052].
+
+2003-06-09  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile: Move inclusion of ../Rules down after extra-objs is
+	fully known.
+
+2003-06-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h: New sequences for
+	5+ arg syscalls only needed for PIC.
+	Patch by Ralph Siemsen <ralphs@netwinder.org>.
+
+2003-06-05  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (PSEUDO): Use
+	and require CFI assembler directives.
+	* sysdeps/unix/sysv/linux/alpha/vfork.S: Likewise.
+
+2003-05-30  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
+	(SAVESTK_0): Add CFI directives.
+	(SAVESTK_3): Likewise.
+	(SAVESTK_5): Likewise.
+	(RESTSTK_0): Likewise.
+	(RESTSTK_3): Likewise.
+	(RESTSTK_5): Likewise.
+
+2003-05-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_SET_THREAD_AREA): Add \n to error
+	messages.
+
+2003-05-04  Roland McGrath  <roland@redhat.com>
+
+	* Makefile ($(objpfx)../libc.so): New target.
+
+2003-04-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__pthread_initialize_manager): Remove one last
+	p_multiple_threads call.
+
+2003-04-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (__pthread_initialize_manager): Subtract
+	TLS_PRE_TCB_SIZE bytes from tcbp to get to descr.
+	* manager.c (pthread_handle_create): Subtract or add TLS_PRE_TCB_SIZE
+	instead of sizeof (pthread_descr).
+	(pthread_free): Add TLS_PRE_TCB_SIZE instead of sizeof (pthread_descr).
+	* sysdeps/powerpc/tls.h (TLS_INIT_TCB_SIZE, TLS_TCB_SIZE): Define to 0.
+	(TLS_INIT_TCB_ALIGN, TLS_TCB_ALIGN): Define to alignment of
+	pthread_descr.
+	(TLS_PRE_TCB_SIZE): Increase to cover tcbhead_t preceeded by pad
+	to TLS_TCB_ALIGN.
+	(INSTALL_DTV, GET_DTV, THREAD_DTV): tcbhead_t is immediately before
+	tcbp.
+	(TLS_INIT_TP, THREAD_SELF, INIT_THREAD_SELF): Don't add TLS_TCB_SIZE
+	unneccessarily.
+	(NO_TLS_OFFSET): Define.
+
+2003-04-22  Roland McGrath  <roland@redhat.com>
+
+	* Makeconfig (shared-thread-library): Reverse link order to work
+	around linker bug.
+
+2003-04-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/useldt.h (DO_SET_THREAD_AREA): Make sure the
+	compiler knows we use the ldt_entry variable and that the syscall
+	modifies the memory.
+
+	* internals.h: Split pthread_functions definition into...
+	* sysdeps/pthread/pthread-functions.h: ...new file.
+
+	* sysdeps/i386/useldt.h: Include <sysdep.h>.
+
+2003-04-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Rename macros to
+	match changes in NPTL sysdep-cancel.h.
+
+2003-04-11  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (multidir): Don't set the variable here with $(shell ...).
+	($(objpfx)multidir.mk): New target, generated makefile; include that.
+	(generated): Append it.
+
+2003-04-10  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (multidir, crti-objs, crtn-objs): New variables.
+	(generated-dirs): Add pathname component of multidir.
+	(omit-deps, extra-objs): Include $(multidir)/crt? as well.
+	($(objpfx)libpthread.so): Depend on $(multidir)/crt?.o as well.
+	($(objpfx)$(multidir), $(objpfx)$(multidir)/crti.o,
+	$(objpfx)$(multidir)/crtn.o): New.
+	* sysdeps/unix/sysv/linux/sparc/Makefile: Removed.
+	* sysdeps/unix/sysv/linux/x86_64/Makefile (LDFLAGS-pthread.so,
+	before-compile, generated): Don't generate and use specs.
+	($(objpfx)specs): Remove.
+
+2003-04-11  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/s390/pspinlock.c (__pthread_spin_unlock): Fix asm contraints.
+
+2003-04-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Add
+	missing ; after ENTRY use [PR libc/4997].
+
+2003-04-03  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (pthread_initialize): Unblock __pthread_sig_cancel
+	in case the parent blocked it.
+
+2003-04-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (libpthread-routines): Add pthread_atfork.
+	(libpthread-static-only-routines): Add pthread_atfork.
+
+2003-04-01  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (__pthread_wait_for_restart_signal): Use
+	__pthread_sigsuspend instead of sigsuspend.
+	* internals.h (__pthread_sigsuspend): New prototype.
+	* Makefile (libpthread-routines): Add pt-sigsuspend.
+	(tests): Add tst-cancel7.
+	* sysdeps/unix/sysv/linux/pt-sigsuspend.c: New file.
+	* sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S: New file.
+	* sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c: New file.
+	* sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c: New file.
+	* tst-cancel7.c: New test.
+
+2003-03-31  Alexandre Oliva  <aoliva@redhat.com>
+
+	* alloca_cutoff.c: Include internals.h.
+	* sysdeps/pthread/errno-loc.c: Include linuxthreads/internals.h.
+	* sysdeps/pthread/herrno-loc.c: Likewise.
+	* sysdeps/pthread/res-state.c: Likewise.
+
+2003-03-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/typesizes.h: New file.
+	* sysdeps/unix/sysv/linux/alpha/bits/typesizes.h: New file.
+	* sysdeps/unix/sysv/linux/sparc/bits/typesizes.h: New file.
+
+2003-03-24  Daniel Jacobowitz  <drow@mvista.com>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
+	(DOARGS_5, DOARGS_6, DOARGS_7): Rewritten.
+
+2003-03-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/fork.c (__fork): Add libc_hidden_def.
+
+2003-03-21  Daniel Jacobowitz  <drow@mvista.com>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
+	(SINGLE_THREAD_P_PIC): Use "reg" instead of "lr".
+
+2003-03-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/tls.h [__ASSUME_SET_THREAD_AREA_SYSCALL]
+	(TLS_SETUP_GS_SEGMENT): Fix a typo.
+
+2003-03-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/Makefile: Fix cut&paste error.
+
+2003-03-18  Roland McGrath  <roland@redhat.com>
+
+	* Versions (libpthread: GLIBC_2.2): Remove
+	pthread_barrierattr_getpshared, never really existed.
+	(libpthread: GLIBC_2.0): Move __pthread_initialize to ...
+	(libpthread: GLIBC_PRIVATE): ... here.
+
+2003-03-14  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: New file.
+	* sysdeps/unix/sysv/linux/sparc/Makefile ($(objpfx)specs): Use full
+	path for crt[in].o.
+
+2003-03-14  Alexandre Oliva  <aoliva@redhat.com>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Don't .set
+	mips2 on new abi.
+	* sysdeps/mips/pt-machine.h (__compare_and_swap): Likewise.
+	Handle 64-bit longs on n64.
+
+2003-03-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/ia64/pspinlock.c (__pthread_spin_lock,
+	__pthread_spin_trylock): Rewritten.
+
+2003-03-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-cancel4.c (tf_sleep): Lower sleep time a bit to not upset
+	recent kernels.
+
+2003-03-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_create.c (timer_create): Return correct
+	error for CPU clocks.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
+	_POSIX_MONOTONIC_CLOCK.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+2003-03-01  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/powerpc/powerpc64/pt-machine.h
+	(THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, THREAD_SETMEM_NC):
+	New macros.
+	* sysdeps/powerpc/tls.h: Don't define those here.
+
+	* sysdeps/powerpc/tls.h [! USE_TLS && !__powerpc64__]: Define
+	tcbhead_t with multiple_threads member.
+	[USE_TLS] (tcbhead_t): Define minimal one-word version.
+	[USE_TLS && !__powerpc64__] (TLS_MULTIPLE_THREADS_IN_TCB): Define.
+	* sysdeps/powerpc/tcb-offsets.sym [USE_TLS]: Use tls.h macros to
+	derive thread register offset of p_multiple_threads member.
+
+	* descr.h (struct _pthread_descr_struct) [!USE_TLS || !TLS_DTV_AT_TP]:
+	Conditionalize p_header member on this.
+	[TLS_MULTIPLE_THREADS_IN_TCB]: Add p_multiple_threads alternatively.
+	* sysdeps/ia64/tls.h [USE_TLS] (TLS_MULTIPLE_THREADS_IN_TCB): Define.
+	* sysdeps/sh/tls.h: Likewise.
+	* sysdeps/ia64/tcb-offsets.sym [USE_TLS]: Use p_multiple_threads.
+	* sysdeps/sh/tcb-offsets.sym: Likewise.
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
+	(SINGLE_THREAD_P): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
+	(SINGLE_THREAD_P): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
+	(SINGLE_THREAD_P): Likewise.
+	* pthread.c (__pthread_initialize_manager): Likewise.
+	* manager.c (pthread_handle_create): Likewise.
+
+	* sysdeps/powerpc/tls.h [HAVE_TLS_SUPPORT]: Define USE_TLS and all
+	related macros.
+
+2003-01-31  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S [SHARED]:
+	Conditionalize .toc section magic on this.
+
+2003-02-21  Roland McGrath  <roland@redhat.com>
+
+	* cancel.c (__pthread_perform_cleanup): Call __libc_thread_freeres
+	instead of __rpc_thread_destroy.
+
+2003-02-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Call
+	__fork instead of branching to it if BROKEN_SPARC_WDISP22.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO):
+	Fix typo.
+	* sysdeps/unix/sysv/linux/sparc/Makefile (specs): Add ./ prefix
+	to crti.o and crtn.o.
+	* sysdeps/unix/sysv/linux/x86_64/Makefile (specs): Likewise.
+
+2003-02-21  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (install-lib-ldscripts): New variable.
+
+2003-02-20  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: Avoid short
+	interprocedure branches.
+
+2003-02-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* specific.c (pthread_key_delete_helper): Don't use GETMEM, we
+	need the target thread's lock.
+
+2003-02-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Define TTY_NAME_MAX
+	and LOGIN_NAME_MAX.
+
+2003-02-17  Kevin B. Hendricks  <kevin.hendricks@sympatico.ca>
+	    Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+	* sysdeps/powerpc/Makefile: Handle tcb-offsets.sym.
+	* sysdeps/powerpc/tcb-offsets.sym: New file.
+	* sysdeps/powerpc/tls.h: New file.
+	* sysdeps/powerpc/powerpc32/pt-machine.h (FLOATING_STACKS): Define.
+	(ARCH_STACK_MAX_SIZE): Define.
+	(THREAD_SELF): Define.
+	(INIT_THREAD_SELF): Define.
+	(THREAD_GETMEM): Define.
+	(THREAD_GETMEM_NC): Define.
+	(THREAD_SETMEM): Define.
+	(THREAD_SETMEM_NC): Define.
+	(__thread_self): Declare.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Adjust
+	for thread register.
+
+2003-02-14  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S (__vfork):
+	Check pthread_create existance, not __pthread_fork.
+
+2003-02-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/Makefile: Define CFLAGS-confstr.c.
+
+2003-02-10  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/vfork.S (__vfork): Check
+	pthread_create existance, not __pthread_fork.
+	* sysdeps/unix/sysv/linux/i386/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork):
+	Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/sh/vfork.S (__vfork): Likewise.
+	Add .weak pthread_create.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Fix a typo.
+	Check pthread_create existance, not __pthread_fork.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S (__vfork): Branch to
+	__fork whenever libpthread.so is loaded.
+
+2003-02-09  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h:
+	Rework: %r9 is destroyed by functions so don't use it as
+	temporary, align stack correctly, fix parameter for CDISABLE.
+
+2003-02-07  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/Makefile: New file.
+	* sysdeps/sh/tcb-offsets.sym: Likewise.
+	* sysdeps/sh/tls.h: Don't include sysdep.h. Move include
+	of linuxthreads/descr.h after the definition of THREAD_SELF.
+	(tcbhead_t): Use IA64 type tcbhead_t for TLS case.
+	(TLS_TCB_SIZE): Set size of tcbhead_t.
+	(TLS_PRE_TCB_SIZE): Define.
+	(INSTALL_NEW_DTV): Set dtv of tcbhead_t structure instead of
+	a member of thread structure.
+	(THREAD_DTV): Likewise.
+	(TLS_INIT_TP_EXPENSIVE): Remove.
+	(TLS_INIT_TP): Set gbr register only.
+	(THREAD_SELF): New.
+	(INIT_THREAD_SELF): Likewise.
+	(NONTLS_INIT_TP): New.
+	* sysdeps/unix/sysv/linux/sh/pt-initfini.c (__fpscr_values):
+	Remove.
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (PSEUDO): Add
+	SYSCALL_INST_PAD macro after DO_CALL.
+	(SINGLE_THREAD_P): Fix non-PIC and TLS case so to read the
+	correct	variable.
+	* sysdeps/unix/sysv/linux/sh/vfork.S (__vfork): Branch to __fork
+	whenever libpthread.so is loaded.
+
+2003-02-08  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/m68k/vfork.S: Branch to __fork whenever
+	libpthread.so is loaded.
+
+2003-02-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/vfork.S: Make sure
+	__ASSUME_VFORK_SYSCALL is not defined if the kernel headers have
+	no __NR_vfork definition.
+
+2003-02-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* tst-popen2.c: New test.
+	* Makefile (tests): Add tst-popen2.
+	* sysdeps/unix/sysv/linux/alpha/vfork.S (__vfork): Branch to __fork
+	whenever libpthread.so is loaded.
+	* sysdeps/unix/sysv/linux/i386/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork):
+	Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/vfork.S (__vfork): Likewise.
+
+2003-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_once): Set control
+	variable for non-libpthread case to the same value the
+	pthread_once function would use.
+
+2003-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): If
+	BROKEN_SPARC_WDISP22, handle SHARED the same way as non-SHARED.
+
+2003-02-04  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/hppa/pt-initfini.c: Do not use
+	multi-line strings.
+
+2003-01-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/s390/tls.h (TLS_INIT_TP): Return NULL, not 0.
+
+2003-01-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/alpha/tls.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Avoid warnings about unused self
+	variable.
+	* sysdeps/ia64/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+	* sysdeps/s390/s390-32/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+	* sysdeps/s390/s390-64/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+	* sysdeps/sh/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Likewise.
+
+2003-01-27  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/s390/s390-32/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
+	Define TLS versions.
+	* sysdeps/s390/s390-64/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
+	Likewise.
+	* sysdeps/s390/tls.h [HAVE_TLS_SUPPORT]	(USE_TLS, TLS_INIT_TCB_SIZE,
+	TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, TLS_TCB_ALIGN, TLS_TCB_AT_TP,
+	INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_DTV):
+	Define.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Use
+	branch with 32 bit offset.
+	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: Likewise.
+
+2003-01-24  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/sparc/sparc32/pt-machine.h (__thread_self): Change to %g7,
+	as required by TLS ABI.
+	* sysdeps/sparc/sparc64/pt-machine.h (__thread_self): Likewise.
+	* sysdeps/sparc/tls.h [HAVE_TLS_SUPPORT] (USE_TLS, TLS_INIT_TCB_SIZE,
+	TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, TLS_TCB_ALIGN, TLS_TCB_AT_TP,
+	INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_DTV):
+	Define.
+	[HAVE_TLS_SUPPORT]: Include descr.h and sysdep.h.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Use %g7
+	instead of %g6 for thread pointer.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
+
+2003-01-25  Guido Guenther  <agx@sigxcpu.org>
+
+	* sysdeps/unix/sysv/linux/mips/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/mips/Makefile: New file.
+
+2003-01-20  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: Avoid non pc relative
+	reference to __fork.
+
+2003-01-17  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/alpha/tls.h (tcbhead_t): Clarify second member.
+	(TLS_TCB_SIZE, TLS_TCB_ALIGN): Set for tcbhead_t.
+	(TLS_PRE_TCB_SIZE): New.
+	(TLS_INIT_TP, THREAD_SELF, INIT_THREAD_SELF): Update for
+	new ia64-style thread pointer layout.
+	(THREAD_GETMEM, THREAD_GETMEM_NC): New.
+	(THREAD_SETMEM, THREAD_SETMEM_NC): New.
+	* sysdeps/unix/sysv/linux/alpha/vfork.S: Don't tail-call to __fork
+	if !SHARED.
+
+2003-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/ia64/tls.h (tcbhead_t): Use the TLS ABI required layout
+	if USE_TLS only.
+	(NONTLS_INIT_TP): Revert last change.
+	* sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define to
+	offsetof (tcbhead_t, multiple_threads) if USE_TLS not defined.
+
+2003-01-16  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (_pthread_initialize_minimal): Use
+	GL(dl_tls_dtv_slotinfo_list) != NULL to check whether TLS has
+	been already initialized.
+
+2003-01-16  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/tls.h (INIT_SYSINFO): Initialize head->sysinfo even
+	if not SHARED.
+
+2003-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_init,
+	__libc_lock_init_recursive): Initialize fields directly.
+
+2003-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/vfork.S (__vfork): Allow
+	__fork to be far away from __vfork ifndef SHARED.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork):
+	Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise.
+	Add a missing instruction.
+	* sysdeps/unix/sysv/linux/arm/vfork.S (__vfork): Conditionally
+	branch to __fork even if __NR_vfork is not defined.
+
+2003-01-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-cancel-wrappers.sh: Allow .__*_asynccancel functions names
+	as well.
+
+2003-01-14  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: New file.
+
+2003-01-14  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/ia64/vfork.S (JUMPTARGET): Remove.
+
+2003-01-13  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: Avoid
+	unterminated string literals.
+	* sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: Likewise.
+
+2003-01-13  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
+	(PSEUDO): Code reordering.  Move CENABLE and CDISABLE literals from
+	PSEUDO_END to PSEUDO.
+	(PSEUDO_END): Remove.
+	(SINGLE_THREAD_P): Save an instruction.
+	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S (__vfork): Add missing
+	parameter to SINGLE_THREAD_P call.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO):
+	Code reordering.
+
+2003-01-10  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/m68k/vfork.S: New file.
+
+2003-01-10  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Setup
+	backchain in pseudo_cancel.  Minor code improvements.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO):
+	Likewise.
+
+2003-01-10  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: New file.
+
+2002-01-12  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: New file.
+
+2002-01-09  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Assume only
+	ret follows pseudo, and thus avoid branch-to-branch in cancel
+	case.  Use SYSCALL_ERROR_LABEL.
+
+2003-01-11  Philip Blundell  <philb@gnu.org>
+
+	* sysdeps/unix/sysv/linux/arm/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO_RET):
+	Correctly unstack lr.
+	(UNDOARGS_5): Fix ordering of pushes and pops.
+	(SINGLE_THREAD_P_PIC): New.
+	(SINGLE_THREAD_P_INT): New.
+	(SINGLE_THREAD_P): Implement in terms of above.  Restore lr if it
+	was stacked.
+	(PSEUDO): Use SINGLE_THREAD_P_INT.
+
+2003-01-11  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/vfork.S: New file.
+
+2003-01-11  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/ia64/tls.h (tcbhead_t): Change into dtv_t *, void *.
+	[HAVE_TLS_SUPPORT] (USE_TLS, TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN,
+	TLS_TCB_SIZE, TLS_PRE_TCB_SIZE, TLS_TCB_ALIGN, TLS_DTV_AT_TP,
+	INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_SELF,
+	INIT_THREAD_SELF): Define.
+	[HAVE_TLS_SUPPORT]: Include descr.h.
+	(NONTLS_INIT_TP): Point __thread_self at the end of dummy
+	struct _pthread_descr_struct.
+	* sysdeps/ia64/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC,
+	THREAD_SETMEM, THREAD_SETMEM_NC): Define using THREAD_SELF,
+	not __thread_self.
+	* sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Adjust
+	computation.
+	* pthread.c (__pthread_initialize_minimal): Use tcbp, not self
+	for TCB pointer.
+	(__pthread_initialize_manager): Rename tcb to mgr.
+	Use tcbp for TCB pointer, if TLS_DTV_AT_TP set mgr to sizeof (struct
+	_pthread_descr) below tcbp, otherwise to tcbp.
+	* manager.c (pthread_handle_create): If TLS_DTV_AT_TP, set
+	new_thread to be below _dl_allocate_tls ().  Adjust new_thread back
+	before freeing.  Fix clone arguments if report_events and USE_TLS.
+	(pthread_free): Adjust th back before freeing.
+
+2003-01-10  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile: Moved to ...
+	* sysdeps/unix/sysv/linux/powerpc/Makefile: ...here.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New File.
+
+2003-01-09  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/ia64/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
+	[__ASSEMBLER__] (SINGLE_THREAD_P): Remove trailing ;;.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/x86_64/vfork.S: New file.
+	* sysdeps/unix/sysv/linux/alpha/vfork.S: New file.
+	* tst-popen.c: New test.
+	* Makefile (tests): Add tst-popen.
+
+2003-01-06  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sigwait.c (do_sigwait): Add
+	INTERNAL_SYSCALL_DECL, add err argument to INTERNAL_SYSCALL* macros.
+
+2003-01-06  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (PSEUDO): Use
+	PSEUDO_PREPARE_ARGS.  Fix branch condition after SINGLE_THREAD_P.
+
+2003-01-06  Philip Blundell  <philb@gnu.org>
+
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h: New file.
+
+2003-01-06  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (LIBC_CANCEL_HANDLED): Define.
+	* sysdeps/unix/sysv/linux/sigwait.c (LIBC_CANCEL_HANDLED): Add.
+	* signals.c (LIBC_CANCEL_HANDLED): Add.
+	* pt-system.c (LIBC_CANCEL_HANDLED): Add.
+	* tst-cancel-wrappers.sh: Remove all exceptions.
+
+	* sysdeps/unix/sysv/linux/alpha/Makefile: New file.
+
+2003-01-05  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/m68k/Makefile: New file, use -fPIC for nonshared
+	objects.
+
+	* sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h (SINGLE_THREAD_P):
+	Fix for PIC.
+	(CENABLE): Likewise.
+	(CDISABLE): Likewise.
+
+2003-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-cancel-wrappers.sh: Invoke gawk not awk since we use GNU awk
+	features.  Reported by Marijn Ros <marijn@mad.scientist.com>.
+
+	* Makefile (libc.so-no-z-defs): Define to yes.
+
+2003-01-05  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/tls.h: Include dl-sysdep.h	and stdint.h.
+	(tcbhead_t): Add multiple_threads member.
+	(TLS_INIT_TP_EXPENSIVE): Define.
+	* sysdeps/unix/sysv/linux/sh/pt-initfini.c: Don't use multi-line
+	strings.  Remove unused code.
+	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: New file.
+
+2003-01-04  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile: New file.
+
+2003-01-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (LIBC_THREAD_GETMEM, LIBC_THREAD_SETMEM): Define
+	even if NOT_IN_libc is defined.
+
+2003-01-05  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file.
+	* sysdeps/s390/Makefile: New file.
+	* sysdeps/s390/tcb-offsets.sym: New file.
+	* sysdeps/s390/tls.h: New file.
+
+2003-01-03  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file.
+
+2003-01-03  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/bits/libc-tsd.h: Declare weak_extern functions.
+
+2003-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile ($(objpfx)libpthread.so): Depend on ld.so.
+
+2003-01-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-cancel-wrappers.sh: Exclude sigwait.c as well, it does not have
+	cancellation tests.
+
+2003-01-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (struct pthread_functions): Rename
+	ptr_pthread_cond_* fields to ptr___pthread_cond_*.
+	* pthread.c (pthread_functions): Adjust.
+	* forward.c: Export both pthread_cond_*@@GLIBC_2.3.2 and
+	pthread_cond_*@GLIBC_2.0 compatibility symbols.
+	* Versions [libc] (GLIBC_2.3.2): Export pthread_cond_broadcast,
+	pthread_cond_destroy, pthread_cond_init, pthread_cond_signal
+	and pthread_cond_wait.
+
+	* sysdeps/pthread/bits/pthreadtypes.h (__pthread_cond_align_t): New
+	type.
+	(pthread_cond_t): Add __align member, shorten __padding.
+	* sysdeps/pthread/pthread.h (PHTREAD_COND_INITIALIZER): Initialize
+	__padding and __align too.
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call2): Add
+	__builtin_expect.
+	* sysdeps/pthread/sigaction.c: New file.
+	* sysdeps/unix/sysv/linux/raise.c: New file.
+	* sysdeps/unix/sysv/linux/sigwait.c: New file.
+	* sysdeps/unix/sysv/linux/fork.c (__pthread_fork): Protect
+	weak_extern with #ifndef SHARED.
+	* sysdeps/unix/sysv/linux/jmp-unwind.c (__pthread_cleanup_upto):
+	Likewise.
+	* signals.c (__sigaction): Renamed to...
+	(__pthread_sigaction): ... this.
+	(__sigaction): New strong alias, #ifdef SHARED only.
+	(sigaction): Protect with #ifdef SHARED.
+	(sigwait): Renamed to...
+	(__pthread_sigwait): ... this.
+	(sigwait): New strong alias, #ifdef SHARED only.
+	(raise): Renamed to...
+	(__pthread_raise): ... this.
+	(raise): New strong alias, #ifdef SHARED only.
+	* internals.h (__pthread_sigaction, __pthread_sigwait,
+	__pthread_raise): New prototypes.
+	(struct pthread_functions): Add ptr_pthread_sigaction,
+	ptr_pthread_sigwait, ptr_pthread_raise.
+	* pthread.c (pthread_functions): Renamed to...
+	(__pthread_functions): ... this.  No longer static, no longer
+	SHARED only.  Initialize ptr_pthread_sigaction, ptr_pthread_sigwait
+	and ptr_pthread_raise.
+	[SHARED] (ptr_pthread_functions): Change to &__pthread_functions.
+	* libc-cancellation.c (__pthread_thread_self): Remove weak_extern.
+	* ptfork.c (__fork, __vfork): Protect with #ifdef SHARED.
+	* ptlongjmp.c (siglongjmp, longjmp): Protect with #ifdef SHARED.
+
+	* Makefile (tests, tests-static): Add tst-cancel-static.
+	* tst-cancel-static.c: New test.
+
+2003-01-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (CFLAGS-pthread_atfork.c): Add -DNOT_IN_libc.
+
+2003-01-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/pthreadtypes.h (pthread_cond_t): Add padding.
+	* condvar.c: Add symbol versioning.  The compatibility versions
+	are the same as the change in the interface does not effect this
+	implementation.
+	* Versions [libpthread]: Add definitions for new pthread_cond_*
+	interfaces for version GLIBC_2.3.2.
+
+2002-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for
+	__register_atfork.
+	* sysdeps/unix/sysv/linux/register-atfork.c: Add libc_hidden_def
+	for __register_atfork.
+
+2002-12-31  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/i686/pt-machine.h: Use __ASSEMBLER__ instead of
+	ASSEMBLER test macro.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise.
+
+	* sysdeps/pthread/errno-loc.c (__errno_location): Add
+	libc_hidden_def.
+	* sysdeps/pthread/herrno-loc.c (__h_errno_location): Likewise.
+	* sysdeps/pthread/res-state.c (__res_state): Likewise.
+	* sysdeps/unix/sysv/linux/allocrtsig.c (__libc_current_sigrtmin,
+	__libc_current_sigrtmax): Likewise.
+	* Versions [libc] (GLIBC_PRIVATE): Remove __libc_internal_tsd_get,
+	__libc_internal_tsd_set, __libc_internal_tsd_address,
+	__libc_alloca_cutoff.
+	[libpthread] (GLIBC_PRIVATE): Remove __libc_internal_tsd_get,
+	__libc_internal_tsd_set, __libc_internal_tsd_address.
+
+	* sysdeps/pthread/list.h: Remove assert.h include.
+	* sysdeps/unix/sysv/linux/fork.c: Include <fork.h>, not "fork.h".
+
+	* sysdeps/pthread/list.h: New file.
+	* sysdeps/unix/sysv/linux/jmp-unwind.c: New file.
+	* sysdeps/unix/sysv/linux/fork.c: New file.
+	* sysdeps/unix/sysv/linux/fork.h: New file.
+	* sysdeps/unix/sysv/linux/ia64/fork.h: New file.
+	* sysdeps/unix/sysv/linux/sparc/fork.h: New file.
+	* sysdeps/unix/sysv/linux/register-atfork.c: New file.
+	* sysdeps/unix/sysv/linux/unregister-atfork.c: New file.
+	* sysdeps/unix/sysv/linux/Makefile: New file.
+	* sysdeps/unix/sysv/linux/Versions: New file.
+	* ptlongjmp.c (pthread_cleanup_upto): Rename to...
+	(__pthread_cleanup_upto): ...this. Add targetframe argument,
+	use it instead of currentframe.  No longer static.
+	(siglongjmp, longjmp): Remove pthread_cleanup_upto calls.
+	* internals.h (__pthread_cleanup_upto, __pthread_fork): New prototypes.
+	(struct pthread_functions): Add ptr_pthread_fork,
+	ptr_pthread_cleanup_upto.
+	* pthread.c (pthread_functions): Initialize ptr_pthread_fork and
+	ptr_pthread_cleanup_upto.
+	* ptfork.c: Include fork.h.
+	(struct handler_list, struct handler_list_block): Remove.
+	(pthread_atfork_lock, pthread_atfork_prepare, pthread_atfork_parent,
+	pthread_atfork_child): Remove.
+	(pthread_insert_list, __pthread_atfork, pthread_call_handlers): Remove.
+	(__pthread_fork): New function.
+	(__fork, __vfork): Call __libc_fork.
+	* Makefile (libpthread-routines): Add old_pthread_atfork.
+	(libpthread-nonshared): Add pthread_atfork.
+	(others): Depend on $(objpfx)libpthread_nonshared.a.
+	($(objpfx)libpthread_nonshared.a): New rule.
+	(install): Depend on $(inst_libdir)/libpthread.so.
+	($(inst_libdir)/libpthread.so, $(inst_libdir)/libpthread_nonshared.a):
+	New rules.
+	(tests): Depend on libpthread_nonshared.a too.
+	* old_pthread_atfork.c: New file.
+	* pthread_atfork.c: New file.
+	* Makeconfig (shared-thread-library): Include libpthread_nonshared.a
+	too.
+
+2002-12-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* forward.c: Make all functions available by default again.  It
+	caused too much trouble.
+	* internals.h (struct pthread_functions): Rename ptr_pthread_exit
+	and ptr_pthread_attr_init_2_* to ptr___pthread_exit and
+	ptr___pthread_attr_init_2_*.
+	* pthread.c (pthread_functions): Adjust.
+
+2002-12-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* libc_pthread_init.c (__libc_pthread_init): Remove
+	MULTIPLE_THREADS_OFFSET check.
+	* sysdeps/i386/tls.h: Include tcb-offsets.h in assembler.
+	(SYSINFO_OFFSET): Remove.
+	* sysdeps/i386/Makefile [csu] (gen-as-const-headers): Add
+	tcb-offsets.sym.
+	* sysdeps/i386/tcb-offsets.sym: New file.
+	* sysdeps/pthread/tcb-offsets.h: New file.
+	* sysdeps/sparc/sparc32/tls.h: Removed.
+	* sysdeps/sparc/sparc64/tls.h: Move...
+	* sysdeps/sparc/tls.h: ...here.  Include tcb-offsets.h in assembler.
+	* sysdeps/sparc/Makefile: New file.
+	* sysdeps/sparc/tcb-offsets.sym: New file.
+	* sysdeps/ia64/tls.h: Include tcb-offsets.h in assembler.
+	* sysdeps/ia64/Makefile: New file.
+	* sysdeps/ia64/tcb-offsets.sym: New file.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Remove.
+	Replace defined MULTIPLE_THREADS_OFFSET
+	with defined FLOATING_STACKS && USE___THREAD.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Remove.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Remove.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Remove.
+	* pthread.c (__pthread_initialize_manager): Remove
+	MULTIPLE_THREADS_OFFSET cbeck.
+
+	* tst-cancel-wrappers.sh: Add line continuations.
+
+2002-12-27  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-tsd.h: Include linuxthreads/descr.h
+	and bits/libc-lock.h.
+	(__libc_internal_tsd_get, __libc_internal_tsd_set,
+	__libc_internal_tsd_address): Remove.
+	(__pthread_internal_tsd_address, __pthread_internal_tsd_get,
+	__pthread_internal_tsd_set): New weak_externs.
+	(__libc_tsd_address, __libc_tsd_get, __libc_tsd_set): Define
+	using __libc_maybe_call2.
+	(__libc_tsd_key_t): Move to ...
+	* descr.h (__libc_tsd_key_t): ...here.
+	Remove bits/libc-tsd.h include.
+	* sysdeps/pthread/errno-loc.c: New file.
+	* sysdeps/pthread/herrno-loc.c: New file.
+	* sysdeps/pthread/res-state.c: New file.
+	* libc-cancellation.c (THREAD_GETMEM, THREAD_SETMEM): Remove.
+	(__libc_enable_asynccancel, __libc_disable_asynccancel): Use
+	thread_self unconditionally.  Use LIBC_THREAD_[SG]ETMEM instead
+	of THREAD_[SG]ETMEM.
+	* specific.c (libc_internal_tsd_set): Renamed to...
+	__pthread_internal_tsd_set.  Remove static.
+	(libc_internal_tsd_get): Renamed to...
+	__pthread_internal_tsd_get.  Remove static.
+	(libc_internal_tsd_address): Renamed to...
+	__pthread_internal_tsd_address.  Remove static.
+	(__libc_internal_tsd_set, __libc_internal_tsd_get,
+	__libc_internal_tsd_address, __libc_alloca_cutoff): Remove.
+	* internals.h [!NOT_IN_libc] (LIBC_THREAD_GETMEM, LIBC_THREAD_SETMEM):
+	Define.
+	(__pthread_internal_tsd_set, __pthread_internal_tsd_get,
+	__pthread_internal_tsd_address): New prototypes.
+	(struct pthread_functions): Add
+	ptr_pthread_internal_tsd_([sg]et|address) fields.
+	[!NOT_IN_libc && !FLOATING_STACKS] (thread_self): Define.
+	* pthread.c (pthread_functions) [!USE_TLS && !HAVE___THREAD]:
+	Initialize ptr_pthread_internal_tsd_([sg]et|address) fields.
+	* Versions (libpthread): Remove __libc_alloca_cutoff@GLIBC_PRIVATE.
+	* alloca_cutoff.c: New file.
+	* no-tsd.c: Removed.
+	* Makefile (routines): Remove no-tsd.  Add alloca_cutoff.
+	* pt-system.c (system): Remove cancellation handling.
+	* tst-cancel-wrappers.sh: Allow pt-system.o* to not use the
+	cancellation routines.
+
+	* sysdeps/i386/tls.h: Include dl-sysdep.h and stdint.h.
+	(tcbhead_t): Add sysinfo field.
+	(SYSINFO_OFFSET, INIT_SYSINFO): Define.
+	(TLS_INIT_TP): Use INIT_SYSINFO.
+	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: New file.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Adjust.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
+	(MULTIPLE_THREADS_OFFSET): Likewise.
+	* descr.h: Include stdint.h.
+	(struct _pthread_descr_struct): Add p_header.data.sysinfo field.
+
+2002-12-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* libc_pthread_init.c: Include stdlib.h.
+	* sysdeps/i386/tls.h (tcbhead_t): Add multiple_threads member.
+	(TLS_INIT_TP_EXPENSIVE): Define.
+	* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call,
+	__libc_maybe_call2): In _LIBC check SHARED define.
+	* sysdeps/ia64/tls.h: New file.
+	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/ia64/Makefile: New file.
+	* sysdeps/x86_64/tls.h (TLS_INIT_TP_EXPENSIVE): Define.
+	* sysdeps/sparc/sparc32/tls.h: New file.
+	* sysdeps/sparc/sparc64/tls.h: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: New file.
+	* Makefile (tests): Add tst-cancel[1-6].
+	(tests-reverse): Add tst-cancel5.
+	Link libc.so before libpthread.so for tests-reverse.
+	* tst-cancel1.c: New file.
+	* tst-cancel2.c: New file.
+	* tst-cancel3.c: New file.
+	* tst-cancel4.c: New file.
+	* tst-cancel5.c: New file.
+	* tst-cancel6.c: New file.
+
+2002-12-27  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h: New file.
+
+2002-12-22  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (omit-deps): Add $(unix-syscalls:%=ptw-%).
+
+2002-12-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (init_rtsigs): Remove incomplete __builtin_expect.
+	Reported by Art Hass <ahaas@airmail.net>.
+
+2002-12-19  Jakub Jelinek  <jakub@redhat.com>
+
+	* forward.c (pthread_attr_init_2_0, pthread_attr_init_2_1):
+	Use return 0 as 6th argument to FORWARD4.
+
+2002-12-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/useldt.h (FLOATING_STACKS, ARCH_STACK_MAX_SIZE): Only
+	define if __ASSUME_LDT_WORKS > 0.
+	* libc-cancellation.c (THREAD_GETMEM, THREAD_SETMEM): Redefine to
+	struct member access if !FLOATING_STACKS.
+	* sysdeps/pthread/flockfile.c (flockfile): Change into weak alias.
+
+2002-12-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (__pthread_thread_self): New prototype.
+	(struct pthread_functions): Add ptr_pthread_thread_self field.
+	* pthread.c (pthread_functions): Initialize ptr_pthread_thread_self.
+	(__pthread_thread_self): New function.
+	* libc-cancellation.c (__pthread_thread_self): Add weak_extern.
+	(__libc_enable_asynccancel, __libc_disable_asynccancel): Don't
+	use thread_self() directly if not FLOATING_STACKS.
+
+2002-12-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/x86_64/pt-machine.h: Guard most of the header
+	with #ifndef __ASSEMBLER__.
+	* pthread.c (pthread_functions): Use SHLIB_COMPAT around
+	pthread_attr_init_2_0 use.
+
+2002-12-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* wrapsyscall.c: Removed.
+	* weaks.c: Removed.
+	* Makefile (distribute): Add tst-cancel-wrappers.sh.
+	(routines): Remove weaks.  Add forward,
+	libc_pthread_init, libc-cancellation.
+	(shared-only-routines): Remove weaks.  Add forward.
+	(libpthread-routines): Remove wrapsyscall.
+	Add ptw-write, ptw-read, ptw-close, ptw-fcntl, ptw-accept,
+	ptw-connect, ptw-recv, ptw-recvfrom, ptw-recvmsg, ptw-send,
+	ptw-sendmsg, ptw-sendto, ptw-fsync, ptw-lseek, ptw-lseek64,
+	ptw-llseek, ptw-msync, ptw-nanosleep, ptw-open, ptw-open64,
+	ptw-pause, ptw-pread, ptw-pread64, ptw-pwrite, ptw-pwrite64,
+	ptw-tcdrain, ptw-wait, ptw-waitpid, pt-system, pt-allocrtsig.
+	(libpthread-shared-only-routines): Add pt-allocrtsig.
+	(tests): Depend on $(objpfx)tst-cancel-wrappers.out.
+	($(objpfx)tst-cancel-wrappers.out): New rule.
+	* sysdeps/pthread/bits/libc-lock.h: Include linuxthreads/internals.h
+	if in libc.
+	(__libc_maybe_call): In libpthread.* don't check for existance
+	of the function.
+	(__libc_maybe_call2): Define.
+	(__libc_lock_init, __libc_lock_fini, __libc_lock_lock,
+	__libc_lock_trylock, __libc_lock_unlock): Use it.
+	* sysdeps/pthread/flockfile.c: New file.
+	* sysdeps/pthread/ftrylockfile.c: New file.
+	* sysdeps/pthread/funlockfile.c: New file.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: New file.
+	* sysdeps/unix/sysv/linux/allocrtsig.c: New file.
+	* libc-cancellation.c: New file.
+	* forward.c: New file.
+	* libc_pthread_init.c: New file.
+	* pt-system.c: New file.
+	* pthread.c: Remove locale.h.
+	(__pthread_manager_thread): Initialize multiple_threads.
+	(__pthread_multiple_threads): Declare.
+	(pthread_functions): New variable.
+	(__pthread_initialize_minimal): Remove __uselocale call.
+	Call __libc_pthread_init.
+	(__pthread_initialize_manager): Initialize __pthread_multiple_threads,
+	initial thread's multiple_threads and __libc_multiple_threads.
+	Check MULTIPLE_THREADS_OFFSET value. Initialize manager thread's
+	multiple_threads.
+	(pthread_setschedparam, pthread_getschedparam): Rename to __
+	prefixed variants.  Add strong_alias.
+	(current_rtmin, current_rtmax, __libc_current_sigrtmin,
+	__libc_current_sigrtmax, __libc_allocate_rtsig): Remove.
+	(init_rtsigs): Use __libc_current_sigrtmin_private.
+	(pthread_initialize): Only call init_rtsigs if
+	!__ASSUME_REALTIME_SIGNALS.
+	(__pthread_require_wrappers, __pthread_require_lockfile): Remove.
+	* internals.h (__pthread_attr_destroy, __pthread_attr_setdetachstate,
+	__pthread_attr_getdetachstate, __pthread_attr_setschedparam,
+	__pthread_attr_getschedparam, __pthread_attr_setschedpolicy,
+	__pthread_attr_getschedpolicy, __pthread_attr_setinheritsched,
+	__pthread_attr_getinheritsched, __pthread_attr_setscope,
+	__pthread_attr_getscope, __pthread_cond_init,
+	__pthread_cond_destroy, __pthread_cond_wait,
+	__pthread_cond_signal, __pthread_cond_broadcast,
+	__pthread_condattr_init, __pthread_condattr_destroy,
+	__pthread_equal, __pthread_getschedparam,
+	__pthread_setschedparam, __pthread_setcancelstate,
+	__pthread_setcanceltype, __pthread_enable_asynccancel,
+	__libc_enable_asynccancel, __libc_pthread_init): New prototype.
+	(__pthread_mutex_init, __pthread_mutex_destroy,
+	__pthread_mutex_lock, __pthread_mutex_unlock,
+	__pthread_mutex_trylock): Likewise.
+	Add hidden_proto.
+	(struct pthread_functions): New type.
+	(__libc_pthread_functions): New variable.
+	(LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): Define.
+	* descr.h (struct _pthread_descr_struct): Add
+	p_header.data.multiple_threads field.
+	* manager.c (pthread_handle_create): Initialize multiple_threads.
+	* cancel.c (__pthread_enable_asynccancel,
+	__pthread_disable_asynccancel): New functions.
+	(__pthread_provide_wrappers): Remove.
+	(pthread_setcancelstate, pthread_setcanceltype): Rename to __
+	prefixed variants.  Add strong_alias.
+	* condvar.c (pthread_cond_init, pthread_cond_destroy,
+	pthread_cond_wait, pthread_cond_signal, pthread_cond_broadcast,
+	pthread_condattr_init, pthread_condattr_destroy): Likewise.
+	* join.c (pthread_exit): Likewise.
+	* attr.c (pthread_attr_destroy, pthread_attr_setdetachstate,
+	pthread_attr_getdetachstate, pthread_attr_setschedparam,
+	pthread_attr_getschedparam, pthread_attr_setschedpolicy,
+	pthread_attr_getschedpolicy, pthread_attr_setinheritsched,
+	pthread_attr_getinheritsched, pthread_attr_setscope,
+	pthread_attr_getscope): Likewise.
+	* mutex.c (__pthread_mutex_init, __pthread_mutex_destroy,
+	__pthread_mutex_lock, __pthread_mutex_unlock,
+	__pthread_mutex_trylock): Add hidden_def.
+	* Versions (libc): Add __libc_pthread_init,
+	__libc_current_sigrtmin_private, __libc_current_sigrtmax_private,
+	__libc_allocate_rtsig_private @@GLIBC_PRIVATE.
+	* lockfile.c: Remove some USE_IN_LIBIO guards.
+	(__pthread_provide_lockfile): Remove.
+	* pt-allocrtsig.c: New file.
+	* tst-cancel-wrappers.sh: New test.
+
+2002-12-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions [libpthread: GLIBC_2.3.2]: Remove creat, poll, pselect,
+	readv, select, sigpause, sigsuspend, sigwaitinfo, waitid, writev.
+	* wrapsyscall.c: Remove creat, poll, pselect, readv, select,
+	sigpause, sigsuspend, sigwaitinfo, waitid, and writev wrappers.
+
+2002-12-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* wrapsyscall.c (CANCELABLE_SYSCALL): Don't define function as
+	weak.  There is no reason for that.
+	(CANCELABLE_SYSCALL_VA): Likewise.
+
+2002-12-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* wrapsyscall.c: Add wrappers for creat, poll, pselect, readv, select,
+	sigpause, __xpg_sigpause, sigsuspend, sigwaitinfo, waitid, and writev.
+	* Versions: Export creat, poll, pselect, readv, select, sigpause,
+	__xpg_sigpause, sigsuspend, sigwaitinfo, waitid, and writev from
+	libpthread in version GLIBC_2.3.2.
+
+2002-12-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h: Define __rtld_lock_* macros.
+
+2002-12-05  Roland McGrath  <roland@redhat.com>
+
+	* pthread.c (__pthread_initialize_minimal)
+	[USE_TLS && SHARED && !USE___THREAD]: Initialize TLS and set up the
+	TCB if the dynamic linker didn't do it at startup.
+
+	* sysdeps/i386/tls.h (TLS_INIT_TP): Make it return zero or an error
+	string.
+	(TLS_DO_SET_THREAD_AREA, TLS_DO_MODIFY_LDT, TLS_SETUP_GS_SEGMENT):
+	Submacros updated.
+	* sysdeps/x86_64/tls.h (TLS_INIT_TP): Likewise.
+	* sysdeps/alpha/tls.h (TLS_INIT_TP): Likewise (always zero).
+
+2002-12-03  Roland McGrath  <roland@redhat.com>
+
+	* pthread.c (pthread_initialize) [SHARED]: Copy dl_error_tsd value
+	from dynamic linker internal cell to new libc cell.
+
+2002-11-28  Roland McGrath  <roland@redhat.com>
+
+	* tst-context.c: #define IS_IN_libpthread around #include <tls.h>
+	before other headers, so FLOATING_STACKS is not defined wrongly.
+
+	* sysdeps/i386/tls.h [!IS_IN_libpthread]: Enable TLS support
+	even if [! FLOATING_STACKS].
+	(TLS_DO_MODIFY_LDT_KERNEL_CHECK): New macro.
+	If not under [__ASSUME_LDT_WORKS > 0], then do a runtime check of
+	dl_osversion >= 2.3.99 and fatal if not.
+	(TLS_DO_MODIFY_LDT): Use it.
+
+2002-11-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define macros which
+	require it to 200112L.  Remove _POSIX_POLL and _POSIX_SELECT.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+2002-11-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions (libc: GLIBC_2.0): Remove names of functions which are
+	not defined in libc.
+	* Makefile (shared-only-routines): Add weaks.
+	* weaks.c: Remove functions which are not exported from libc.so.
+
+2002-11-14  Roland McGrath  <roland@redhat.com>
+
+	* libc-tsd.c: New file.
+	* Makefile (distribute): Add it.
+	(libc-link.so): New variable.
+	($(objpfx)libpthread.so): Depend on that instead of libc.so file name.
+	(libc-ok-for-link): New variable.
+	[$(versioning) = yes]: Include $(common-objpfx)tls.make and define
+	libc-ok-for-link to $(use-thread).
+	[$(libc-ok-for-link) = no]
+	(libc-link.so): Set to $(objpfx)libc.so, not $(common-objpfx)libc.so.
+	($(objpfx)libc_pic_lite.a,$(objpfx)libc_pic_lite.os, $(objpfx)libc.so):
+	New targets.
+	(generated): Append them.
+	(extra-objs): Append libc-tsd.os.
+
+	* libc-tls-loc.c: New file.
+	* Makefile (libpthread-routines): Add it.
+
+2002-11-14  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Fix unterminated
+	string.
+
+2002-11-13  Roland McGrath  <roland@redhat.com>
+
+	* Examples/ex6.c (main): Improve error reporting.
+
+2002-11-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/Makefile: Compile pthread.c and sighandler.c with
+	-fno-omit-frame-pointer.  Patch by Andreas Steinmetz <ast@domdv.de>.
+
+	* sysdeps/i386/useldt.h [PIC] (USETLS_LOAD_EBX): Use correct input
+	register number.
+	(DO_SET_THREAD_AREA): Mark asm output specifiers correctly.
+
+2002-10-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* manager.c (pthread_start_thread): Call __uselocale even
+	if [! SHARED].  Patch by Leon Kanter <leon@geon.donetsk.ua>.
+
+2002-10-17  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (unload): Don't link in libpthread.so.
+	($(objpfx)unload.out): Do depend on it.
+	* unload.c (main): Improve error reporting.
+
+2002-10-09  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call): New macro.
+	Under [__PIC__], call the function via the pointer fetched for
+	comparison rather than a call by name that uses the PLT.
+	(__libc_lock_init, __libc_rwlock_init, __libc_lock_fini)
+	(__libc_rwlock_fini, __libc_lock_lock, __libc_rwlock_rdlock)
+	(__libc_rwlock_wrlock, __libc_lock_trylock, __libc_rwlock_tryrdlock)
+	(__libc_rwlock_trywrlock, __libc_lock_unlock, __libc_rwlock_unlock)
+	(__libc_key_create, __libc_getspecific, __libc_setspecific)
+	(__libc_atfork): Use it.
+
+	* pthread.c [SHARED] (__libc_dl_error_tsd): New function.
+	(pthread_initialize) [SHARED]: Set _dl_error_catch_tsd to that.
+	* Versions (libc: GLIBC_PRIVATE): Add __libc_dl_error_tsd.
+	(ld: GLIBC_PRIVATE): Set removed.
+
+2002-10-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/execve.c: New file.
+
+2002-10-09  Jakub Jelinek  <jakub@redhat.com>
+
+	* no-tsd.c: Include stdlib.h.
+
+2002-10-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/allocalim.h: New file.
+	* descr.h (struct _pthread_descr_struct): Add p_alloca_cutoff
+	field.
+	* manager.c (__pthread_allocate_stack): Add out_stacksize argument.
+	Pass stack size to caller.
+	(pthread_handle_create): Set p_alloca_cutoff.
+	* pthread.c (__pthread_initial_thread): Use C99 designated
+	initializers.  Set p_alloca_cutoff.
+	(__pthread_manager_thread): Likewise.
+	(__pthread_initialize_minimal) [USE_TLS]: Set p_alloca_cutoff
+	for initial thread.
+	(__pthread_init_max_stacksize): Possibly decrease p_alloca_cutoff
+	for initial thread.
+	(__pthread_initialize_manager) [USE_TLS]: Set p_alloca_cutoff
+	for manager thread.
+	* specific.c (__libc_alloca_cutoff): New function.
+	* no-tsd.c (__libc_alloca_cutoff): New function.
+	* Versions: Export __libc_alloca_cutoff@@GLIBC_PRIVATE from libc
+	and libpthread.
+
+2002-10-02  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/pt-machine.h: Make C code ifndef'ed with __ASSEMBLER__.
+	* sysdeps/sh/tls.h: Likewise.
+	* sysdeps/unix/sysv/linux/sh/smp.h: New file.
+
+2002-09-29  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/tst-timer.c (main): Clear
+	SIGEV2.sigev_notify_attributes.
+
+2002-09-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/useldt.h (DO_SET_THREAD_AREA): Don't use
+	INLINE_SYSCALL for set_thread_area syscall.
+
+2002-09-28  Roland McGrath  <roland@redhat.com>
+
+	* pthread.c (__pthread_reset_main_thread) [FLOATING_STACKS]:
+	Don't call setrlimit, since we did no prior bogon we need to undo.
+
+2002-09-27  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/x86_64/tls.h [__ASSEMBLER__]: Don't include <pt-machine.h>.
+
+2002-09-24  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/x86_64/tls.h: New file.
+
+2002-09-23  Roland McGrath  <roland@redhat.com>
+
+	* Examples/ex13.c (dump_mut): int -> size_t for counter.
+
+2002-09-18  Bruno Haible  <bruno@clisp.org>
+
+	* Examples/ex10.c (thread): Fail if pthread_mutex_timedlock() returns
+	an unexpected error code.
+
+	* internals.h (__pthread_message): Add const to first parameter type.
+	* pthread.c (__pthread_message): Likewise.
+
+	* sysdeps/unix/sysv/linux/configure: Moved to ../sysdeps/pthread.
+
+2002-09-17  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT, TLS_DO_SET_THREAD_AREA):
+	Set the descriptor limit to the full 4GB, so %gs:OFFSET works for any
+	offset (positive or negative) relative to the thread struct.
+	* sysdeps/i386/useldt.h (DO_MODIFY_LDT, DO_SET_THREAD_AREA): Likewise.
+
+2002-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: Move...
+	* sysdeps/unix/sysv/linux/sparc/Makefile: ...here.
+	Replace /usr/lib/crt[in].o with crt[in].o too.
+
+2002-09-11  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/pt-machine.h: New file.
+
+2002-09-04  Bruno Haible  <bruno@clisp.org>
+
+	* pthread.c: Include <sys/time.h>.
+	(is_smp_system): Move to sysdeps/unix/sysv/linux/smp.h.
+	* sysdeps/unix/sysv/linux/smp.h: New file, extracted from pthread.c.
+	* Makefile (distribute): Add smp.h to the list.
+
+2002-09-04  Bruno Haible  <bruno@clisp.org>
+
+	* sysdeps/alpha/pt-machine.h: Choose different include file location
+	on non-Linux platforms.
+
+	* wrapsyscall.c (PROMOTE_INTEGRAL_TYPE): New macro.
+	(open, open64): Change va_arg argument type to the integral type to
+	which mode_t promotes.
+
+	* sysdeps/pthread/tst-timer.c (main): Don't assume anything about
+	the structure of 'struct sigevent'.
+
+	* errno.c (__errno_location, __h_errno_location, __res_state):
+	Use prototype function definitions.
+
+2002-07-29  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* shlib-versions: Set libpthread version to 2.3 for powerpc64.
+	* sysdeps/powerpc/pt-machine.h: moved to...
+	* sysdeps/powerpc/powerpc32/pt-machine.h: ...here
+	* sysdeps/powerpc/powerpc64/pt-machine.h: New file.
+
+2002-09-02  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/powerpc/Makefile (CFLAGS-pt-initfini.s): New variable.
+
+2002-09-01  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/bits/libc-tsd.h (enum __libc_tsd_key_t): Add new keys
+	CTYPE_B, CTYPE_TOLOWER, CTYPE_TOUPPER.
+
+	* sysdeps/pthread/bits/libc-tsd.h (__libc_tsd_address): New macro.
+	(__libc_internal_tsd_address): Declare it.
+	* Versions (libc, ld, libpthread: GLIBC_PRIVATE): Add
+	__libc_internal_tsd_address.
+	* specific.c (libc_internal_tsd_address): New function.
+	(__libc_internal_tsd_address): New variable.
+	* no-tsd.c (__libc_internal_tsd_address): New variable.
+
+2002-08-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: Don't use rule for crt%.o, spell it out as rules for
+	crti.o and crtn.o.
+
+2002-08-30  Roland McGrath  <roland@redhat.com>
+
+	* Makefile (extra-objs, omit-deps): Add crtn.
+	($(objpfx)libpthread.so): Depend on $(objpfx)crtn.o.
+	($(objpfx)libpthread.so: +postinit): Append $(objpfx)crtn.o.
+	($(objpfx)crtn.S): New target.
+	($(objpfx)crt%.o): Pattern rule replaces crti.o target.
+	(generated): Add crtn.S.
+
+	* sysdeps/unix/sysv/linux/x86_64/Makefile ($(objpfx)specs): Massage
+	crtn.o pathname too.
+
+2002-08-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (__pthread_initialize_minimal): Call __uselocale even
+	if [! SHARED].
+
+2002-08-30  Roland McGrath  <roland@redhat.com>
+
+	* tst-static-locale.c: New file.
+	* Makefile (tests, tests-static): Add it.
+
+2002-04-24  Steven Munroe  <sjmunroe@us.ibm.com>
+
+	* spinlock.c (__pthread_lock): Fix spurious wakeup
+	handling.  Don't clear lowest bit of list pointer as sign the thread
+	is still on the wait list.  Don't restart after spurious wakeup
+	with spinning to get the lock.
+	(__pthread_unlock): Take set lowest bit into account when handling
+	pointer to list elements.
+	Patch by Steve Munroe <sjmunroe@us.ibm.com>.
+
+2002-08-28  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/timer_routines.c (thread_func): Fix type in cast.
+
+2002-08-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/hppa/aio_cancel.c: New file.
+	* sysdeps/unix/sysv/linux/sparc/aio_cancel.c: New file.
+	* sysdeps/unix/sysv/linux/alpha/aio_cancel.c: New file.
+
+2002-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_routines.c (thread_func): Change return
+	type to void and add casts in use to avoid warnings with all gcc
+	versions.
+
+2002-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h (PTHREAD_THREADS_MAX):
+	Bump to 16384.
+	* manager.c (__pthread_handles): Remove.
+	* pthandles.c: New file.
+	* pthread.c (__pthread_initialize_minimal): Initialize
+	__pthread_handles[0] and __pthread_handles[1].
+	* Makefile (libpthread-routines): Add pthandles (must be last).
+
+2002-08-26  Brian Youmans  <3diff@gnu.org>
+
+	* Examples/ex10.c: Corrected version number in Lesser GPL copying
+	permission notice from 2 to 2.1.
+	* Examples/ex11.c: Likewise.
+	* Examples/ex13.c: Likewise.
+	* Examples/ex8.c: Likewise.
+	* Examples/ex9.c: Likewise.
+	* barrier.c: Likewise.
+	* events.c: Likewise.
+	* lockfile.c: Likewise.
+	* no-tsd.c: Likewise.
+	* pt-machine.c: Likewise.
+	* ptclock_gettime.c: Likewise.
+	* ptclock_settime.c: Likewise.
+	* rwlock.c: Likewise.
+	* sysdeps/alpha/pspinlock.c: Likewise.
+	* sysdeps/alpha/pt-machine.h: Likewise.
+	* sysdeps/arm/pspinlock.c: Likewise.
+	* sysdeps/arm/pt-machine.h: Likewise.
+	* sysdeps/cris/pspinlock.c: Likewise.
+	* sysdeps/cris/pt-machine.h: Likewise.
+	* sysdeps/hppa/pspinlock.c: Likewise.
+	* sysdeps/hppa/pt-machine.h: Likewise.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	* sysdeps/i386/pspinlock.c: Likewise.
+	* sysdeps/i386/pt-machine.h: Likewise.
+	* sysdeps/i386/useldt.h: Likewise.
+	* sysdeps/ia64/pspinlock.c: Likewise.
+	* sysdeps/ia64/pt-machine.h: Likewise.
+	* sysdeps/m68k/pspinlock.c: Likewise.
+	* sysdeps/m68k/pt-machine.h: Likewise.
+	* sysdeps/mips/pspinlock.c: Likewise.
+	* sysdeps/mips/pt-machine.h: Likewise.
+	* sysdeps/powerpc/pspinlock.c: Likewise.
+	* sysdeps/powerpc/pt-machine.h: Likewise.
+	* sysdeps/pthread/bits/initspin.h: Likewise.
+	* sysdeps/pthread/bits/libc-lock.h: Likewise.
+	* sysdeps/pthread/bits/libc-tsd.h: Likewise.
+	* sysdeps/pthread/getcpuclockid.c: Likewise.
+	* sysdeps/pthread/posix-timer.h: Likewise.
+	* sysdeps/pthread/timer_create.c: Likewise.
+	* sysdeps/pthread/timer_delete.c: Likewise.
+	* sysdeps/pthread/timer_getoverr.c: Likewise.
+	* sysdeps/pthread/timer_gettime.c: Likewise.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+	* sysdeps/pthread/timer_settime.c: Likewise.
+	* sysdeps/pthread/tst-timer.c: Likewise.
+	* sysdeps/s390/pspinlock.c: Likewise.
+	* sysdeps/s390/s390-32/pt-machine.h: Likewise.
+	* sysdeps/s390/s390-64/pt-machine.h: Likewise.
+	* sysdeps/sh/pspinlock.c: Likewise.
+	* sysdeps/sh/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc32/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc32/sparcv9/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc64/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Likewise.
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise.
+	* sysdeps/unix/sysv/linux/bits/sigthread.h: Likewise.
+	* sysdeps/unix/sysv/linux/hppa/bits/initspin.h: Likewise.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+	* tststack.c: Likewise.
+	* unload.c: Likewise.
+	* weaks.c: Likewise.
+	* wrapsyscall.c: Likewise.
+
+	* sysdeps/pthread/pt-initfini.c: Changed copying
+	permission notice to Lesser GPL from Library GPL, including the
+	references in the special exception.
+	* sysdeps/unix/sysv/linux/hppa/pt-initfini.c: Likewise.
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c:
+	Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c:
+	Likewise.
+	* sysdeps/unix/sysv/linux/sh/pt-initfini.c: Likewise.
+
+2002-08-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* Examples/ex10.c (thread): tv_nsec == 1000000000 is already
+	overflow [PR libc/4244].
+
+2002-08-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_routines.c (thread_func): Make the
+	compiler happy by adding a return statement which will never be
+	reached.
+
+	* tst-context.c (main): Cast to long before casting to pointer.
+
+	* Examples/ex17.c (main): Use correct format string.
+
+	* Examples/ex9.c (thread): Remove incorrect return statement.
+
+2002-08-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__linuxthreads_version): New global constant.
+
+2002-08-23  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/pt-machine.h: Use %fs instead of %gs
+	as thread specific register.
+	(testandset): Fix inline asm.
+	(THREAD_GETMEM): Fix inline asm.
+
+2002-08-22  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/useldt.h (INIT_THREAD_SELF): Remove [HAVE_TLS_SUPPORT]
+	conditional.
+	(INIT_THREAD_SELF): Pass second arg to DO_SET_THREAD_AREA.
+	(DO_SET_THREAD_AREA): Take second arg, pass to DO_SET_THREAD_AREA_REUSE
+	macro.  That chooses whether to reuse %gs value or let kernel set it.
+	[USE_TLS] (DO_SET_THREAD_AREA_REUSE): New macro, always 1.
+	[!USE_TLS] (DO_SET_THREAD_AREA_REUSE): New macro, true if arg is
+	not constant 0.
+
+2002-08-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_SETUP_GS_SEGMENT): Add new parameter
+	also to the third definition of this macro.
+
+2002-06-17  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/x86_64/Makefile (CFLAGS-pt-initfini.s):
+	Set it.
+
+2002-08-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/useldt.h: Go back to using 16-bit instructions when
+	loading/reading segment registers.  Some old hardware doesn't
+	handle the 32-bit instructions as expected.
+	* sysdeps/i386/tls.h: Likewise.
+
+	* sysdeps/i386/tls.h (TLS_DO_SET_THREAD_AREA): Second parameter is
+	renamed to secondcall and use is negated.
+	(TLS_SETUP_GS_SEGMENT): Likewise.
+	(TLS_INIT_TP): Likewise.
+	* sysdeps/sh/tls.h (TLS_INIT_TP): Second parameter is renamed to
+	secondcall.
+
+	* sysdeps/i386/tls.h: Use 32-bit operations when handling segment
+	registers.  No need to mask upper 16 bits in this case.
+	* sysdeps/i386/useldt.h: Likewise.
+	(DO_SET_THREAD_AREA): We have to load %gs again even if the value
+	is the same since the GDT content changed.
+
+	* sysdeps/i386/tls.h (TLS_INIT_TP): Add new parameter and pass it on
+	to TLS_SETUP_GS_SEGMENT.
+	(TLS_SETUP_GS_SEGMENT): Add new parameter and pass it on to
+	TLS_DO_SET_THREAD_AREA.
+	(TLS_DO_SET_THREAD_AREA): If new parameter is zero determine
+	entry number from %gs value.
+	* sysdeps/sh/tls.h (TLS_INIT_TP): Add new parameter and simply
+	ignore it.
+
+	* manager.c (pthread_handle_create): Pass NULL to _dl_allocate_tls.
+	Pass true to _dl_deallocate_tls.
+	(pthread_free): Likewise.
+	* pthread.c (__pthread_initialize_manager): Likewise.
+
+2002-08-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/useldt.h (DO_SET_THREAD_AREA): Use correct shift when
+	computing index from %gs value.
+
+2002-08-16  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_SET_THREAD_AREA): Calculate segment
+	register value from entry number properly.
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): Rewrite asm to use %ebx
+	optimally conditional on [__PIC__].
+	(TLS_DO_SET_THREAD_AREA): New macro, implement inline syscall
+	without touching errno, and use latest modify_ldt-like interface.
+	(TLS_SETUP_GS_SEGMENT): Use that instead of INLINE_SYSCALL.
+	* sysdeps/i386/useldt.h (DO_MODIFY_LDT): Set %gs in this macro.
+	(DO_SET_THREAD_AREA): New macro, uses current syscall interface with
+	existing %gs value as the segment to set.
+	(INIT_THREAD_SELF): Rewritten using those.  Use set_thread_area only
+	under [HAVE_TLS_SUPPORT] so we can rely on the initialization done
+	by the first thread's early TLS setup.
+
+2002-08-15  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_INIT_TP): Use statement expression and
+	return a value as callers now expect.
+
+2002-08-11  Roland McGrath  <roland@redhat.com>
+
+	* pthread.c (__pthread_initialize_manager): Initialize
+	p_header.data.tcb field of manager thread's descriptor.
+	(__pthread_initialize_minimal): Don't initialize p_header.data.self
+	field, already done by TLS_INIT_TP.
+
+	* manager.c (pthread_handle_create): Move p_header field initializers
+	together.
+
+2002-08-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_SET_THREAD_AREA): Removed.
+
+2002-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__linuxthreads_initial_report_events): New variable.
+	(__pthread_initialize_manager): Use it to initialize p_report_events
+	of initial thread.
+	[TLS]: Store pointer to descriptor of manager in __pthread_handles.
+
+2002-08-07  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): Add an extra argument with
+	an "m" constraint to the asm so the compiler knows LDT_ENTRY was used.
+
+2002-08-02  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/bits/libc-tsd.h (enum __libc_tsd_key_t):
+	Add _LIBC_TSD_KEY_LOCALE.
+	* manager.c (pthread_start_thread) [!(USE_TLS && HAVE___THREAD)]:
+	Call __uselocale to initialize our per-thread locale pointer to
+	the global one.
+	* pthread.c (__pthread_initialize_minimal): Likewise.
+
+	* sysdeps/i386/tls.h (TLS_DO_SET_THREAD_AREA): Add missing \s.
+
+2002-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c: Declare _errno, _h_errno, and _res unless we use TLS
+	internally.
+
+	* cancel.c (__pthread_perform_cleanup) [USE_TLS && HAVE___THREAD]:
+	Don't use p_libc_specific element in thread descriptor.
+
+2002-07-30  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/bits/libc-tsd.h: Include <tls.h>.
+	[USE_TLS && HAVE___THREAD]: Just include the sysdeps/generic file,
+	which does the right thing when __thread support is available.
+	* descr.h (struct _pthread_descr_struct) [USE_TLS && HAVE___THREAD]:
+	Omit `p_libc_specific', `p_errnop', `p_errno', `p_h_errnop',
+	`p_h_errno', `p_resp', and `p_res' members.
+	* pthread.c (__pthread_initialize_minimal) [USE_TLS && HAVE___THREAD]:
+	Don't initialize `p_errnop' and `p_h_errnop' members.
+	(__pthread_reset_main_thread): Likewise.
+	(__pthread_initialize_manager): Likewise.
+	* manager.c (__pthread_manager, pthread_handle_create): Likewise.
+	* pthread.c (pthread_initialize) [USE_TLS && HAVE___THREAD]:
+	Don't initialize `p_resp' member.
+	(__pthread_reset_main_thread): Likewise.
+	* manager.c (pthread_handle_create): Likewise.
+	* specific.c (libc_internal_tsd_set, libc_internal_tsd_get):
+	Conditionalize these on [!(USE_TLS && HAVE___THREAD)].
+	* no-tsd.c: Conditionalize contents on [!(USE_TLS && HAVE___THREAD)].
+	* errno.c [USE_TLS && HAVE___THREAD]
+	(__h_errno_location, __res_state): Don't define these at all.
+
+	* sysdeps/i386/tls.h (INSTALL_DTV): Add parens around arguments!
+	(INSTALL_NEW_DTV, GET_DTV): Likewise.
+	* sysdeps/sh/tls.h (INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV): Likewise.
+
+	* weaks.c: Don't include <errno.h> here.
+
+2002-08-01  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): New macro, broken out of
+	TLS_INIT_TP.
+	(TLS_DO_SET_THREAD_AREA): New macro, uses thread_set_area syscall.
+	(TLS_SETUP_GS_SEGMENT): New macro, try one or the other or both.
+	(TLS_INIT_TP): Use that.
+
+2002-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/useldt.h (DO_MODIFY_LDT): Move from INIT_THREAD_SELF.
+	(INIT_THREAD_SELF): Use sys_thread_area syscall instead if available.
+	(FREE_THREAD): Avoid modify_ldt if using GDT.
+	* sysdeps/i386/pspinlock.c (__have_no_set_thread_area): New variable.
+
+2002-07-25  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/tls.h: Use __ASSEMBLER__ test macro not ASSEMBLER.
+	* sysdeps/i386/pt-machine.h: Likewise.
+	* sysdeps/i386/useldt.h: Likewise.
+
+2002-07-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__pthread_initialize_minimal): If !SHARED and TLS
+	call __libc_setup_tls first.
+	* Makefile: Actually create tst-signal.out file when running the test.
+	(tests): Add tststatic.
+	* Examples/tststatic.c: New file.
+
+2002-07-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* errno.c (__errno_location): Don't define unless !USE_TLS
+	|| !HAVE___THREAD.
+	* sysdeps/i386/pt-machine.c: Protect C code with #ifndef ASSEMBLER.
+	* sysdeps/i386/tls.h: Likewise.
+	* sysdeps/i386/useldt.h: Likewise.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+
+2002-07-02  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/mips/pspinlock.c: Don't include <sgidefs.h>.  Always
+	use ll/sc.
+	* sysdeps/mips/pt-machine.h: Likewise.
+
+2002-07-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* manager.c (pthread_handle_create): Initialize self-reference in
+	descriptor.
+
+2002-07-01  Jakub Jelinek  <jakub@redhat.com>
+
+	* Examples/ex9.c (main): Remove unused th variable.
+
+2002-07-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* wrapsyscall.c: Add __nanosleep alias.
+	* Versions (GLIBC_2.2.6): Add __nanosleep.
+	* bug-sleep.c: New file.
+	* Makefile (tests): Add bug-sleep.
+
+2002-06-19  Steven Munroe  <sjmunroe@vnet.ibm.com>
+
+	* Examples/ex9.c (main):  Use list of children and join them.
+	(thread): Do not call exit.
+
+2002-06-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c (wait_node_alloc): We cannot use compare-and-exchange.
+	Unconditionally use the code using spinlock.  Use __pthread_release
+	to free a spinlock.
+	(wait_node_free): Likewise.
+	(__pthread_acquire, __pthread_release): Unconditionally define.
+
+2002-06-07  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/ia64/pt-machine.h (MEMORY_BARRIER): Fix typo.
+
+2002-05-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/ia64/pt-machine.h (MEMORY_BARRIER): Use __sync_synchronize.
+
+2002-05-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h (pthread_create): Rename first
+	parameter.
+	(pthread_cancel): Likewise.
+	* internals.h (__pthread_create_2_1): Likewise.
+	* sysdeps/unix/sysv/linux/bits/sigthread.h (pthread_kill): Likewise.
+
+2002-05-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/alpha/pt-machine.c (THREAD_SELF): Remove clobber.
+	Patch by Glen Nakamura <gen@flex.com>.
+
+2002-05-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* signals.c: Move sighandler functions to...
+	* sighandler.c: ...here.  New file.
+	* signals.c: Move signal handler related type definitions to...
+	* internals.h: ...here.  Add prototypes for signal handlers.
+	* Makefile (libpthread-routines): Add sighandler.
+	(CFLAGS-sighandler.c): Add $(exceptions).
+
+2002-04-30  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/x86_64/Makefile: New file.
+
+2002-04-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_getoverr.c: Return real overrun.
+	* sysdeps/pthread/posix-timer.h (struct timer_node): Add overrun_count.
+	* sysdeps/pthread/timer_routines.c (thread_func): Schedule next timeout
+	based on previous one and not on current time.  Count overruns.
+	Patch by Eric F. Sorton <eric@cctcorp.com>.
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Add DELAYTIMER_MAX.
+
+2002-04-08  kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/pt-machine.h: Define _PT_MACHINE_H
+	if it isn't defined yet.
+	(FLOATING_STACKS, ARCH_STACK_MAX_SIZE): Defined.
+	(THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, THREAD_SETMEM_NC):
+	Likewise.
+	* sysdeps/sh/tls.h: New file.
+
+2002-04-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* manager.c (__pthread_manager_event): Use self instead of arg
+	for INIT_THREAD_SELF.
+	* sysdeps/i386/useldt.h (INIT_THREAD_SELF): Use sizeof (struct
+	_pthread_descr_struct) instead of sizeof (*descr).
+
+2002-04-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/ia64/pt-machine.h: Protect against multiple inclusion.
+	* sysdeps/alpha/pt-machine.h: Likewise.
+	* sysdeps/arm/pt-machine.h: Likewise.
+	* sysdeps/cris/pt-machine.h: Likewise.
+	* sysdeps/hppa/pt-machine.h: Likewise.
+	* sysdeps/m68k/pt-machine.h: Likewise.
+	* sysdeps/mips/pt-machine.h: Likewise.
+	* sysdeps/powerpc/pt-machine.h: Likewise.
+	* sysdeps/s390/s390-32/pt-machine.h: Likewise.
+	* sysdeps/s390/s390-64/pt-machine.h: Likewise.
+	* sysdeps/sh/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+	* sysdeps/x86_64/pt-machine.h: Likewise.
+
+2002-04-05  Jakub Jelinek  <jakub@redhat.com>
+
+	* man/pthread_mutexattr_init.man (pthread_mutexattr_settype): Document
+	instead of pthread_mutexattr_setkind_np.
+	(pthread_mutexattr_gettype): Similarly.
+	* man/pthread_mutexattr_setkind_np.man: New.
+	* man/Makefile (SOURCES): Add pthread_mutexattr_setkind_np.man.
+
+2002-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/ia64/pt-machine.h (MEMORY_BARRIER): Define.
+
+2002-03-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/mips/pt-machine.h (MEMORY_BARRIER): Remove.
+
+2002-03-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h (MEMORY_BARRIER): Define as asm with memory as clobber.
+
+2002-03-17  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/i386/pt-machine.h: Add testandset and __compare_and_swap
+	prototpyes.
+	* sysdeps/alpha/pt-machine.h: Likewise.
+	* sysdeps/arm/pt-machine.h: Likewise.
+	* sysdeps/cris/pt-machine.h: Likewise.
+	* sysdeps/hppa/pt-machine.h: Likewise.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	* sysdeps/ia64/pt-machine.h: Likewise.
+	* sysdeps/m68k/pt-machine.h: Likewise.
+	* sysdeps/mips/pt-machine.h: Likewise.
+	* sysdeps/powerpc/pt-machine.h: Likewise.
+	* sysdeps/s390/s390-32/pt-machine.h: Likewise.
+	* sysdeps/s390/s390-64/pt-machine.h: Likewise.
+	* sysdeps/sh/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+	* sysdeps/x86_64/pt-machine.h: Likewise.
+
+	* internals.h: Move testandset and __compare_and_swap prototypes
+	to pt-machine.h.
+
+2002-03-03  Andreas Jaeger  <aj@suse.de>
+
+	* errno.c: Include resolv.h to avoid warning.
+
+2002-02-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c [USE_TLS] (thread_self_stack): Correct check for upper
+	stack limit.
+
+2002-02-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (pthread_getattr_np): Don't take thread descriptor size
+	into account if USE_TLS.
+	* manager.c (pthread_handle_create): Free TLS data structures if call
+	failed.  Pass correct stack to clone if USE_TLS.
+	* sysdeps/i386/pt-machine.h: Handle multiple inclusion.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	* sysdeps/i386/tls.h: Unconditionally include <pt-machine.h>.
+
+	* descr.h (struct _pthread_descr_struct): Update p_header for TLS.
+	Add p_stackaddr element #if USE_TLS.
+	* internals.c: Include <tls.h>.
+	* manager.c: Integrate creating and handling of thread descriptor
+	for TLS.
+	* pthread.c: Likewise.
+	* sysdeps/i386/tls.h (tcbhead_t): Add self pointer.
+	Include <linuxthreads/descr.h> only if TLS is really used.
+	(GET_DTV): New macro.
+	(TLS_INIT_TP): Initialize self pointer.
+
+2002-02-17  Andreas Schwab  <schwab@suse.de>
+
+	* signals.c (sigwait): Check for old sighandler being SIG_ERR,
+	not NULL.
+
+2002-02-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.c (INSTALL_NEW_DTV): Define.
+	(INSTALL_DTV): Adjust for being passed pointer to element with length.
+
+2002-02-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_INIT_TP): Also initialize %gs.
+
+2002-02-08  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/alpha/elf/pt-initfini.c: Use \n\ for multiline string.
+
+2002-02-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h: TLS cannot be supported with FLOATING_STACKS
+	after all.
+
+2002-02-07  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Silence the
+	gcc warning.
+	(__pthread_spin_lock): Remove ".set noreorder".
+	* sysdeps/mips/pt-machine.h (__compare_and_swap): Liekwise.
+
+2002-02-05  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Not use
+	branch likely.
+	* sysdeps/mips/pt-machine.h (testandset): Likewise.
+	(__compare_and_swap): Likewise.
+
+2002-02-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h: Move declarations/definitions of
+	__pthread_initial_thread_bos, __pthread_initial_thread,
+	__pthread_manager_thread_bos, __pthread_manager_thread_tos,
+	__pthread_manager_thread, __pthread_nonstandard_stacks, STACK_SIZE,
+	CURRENT_STACK_FRAME, __pthread_find_self, and thread_self...
+	* descr.h: ...here.
+	* sysdeps/i386/tls.h: Add TLS definitions also for !FLOATING_STACKS.
+	Define THREAD_GETMEM accordingly.
+
+2002-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/tls.h: Include <stddef.h> for size_t.
+
+	* sysdeps/i386/tls.h: Define THREAD_DTV.
+
+2002-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h: Move thread descriptor definition...
+	* descr.h.: ...here.  New file.
+	* sysdeps/i386/tls.h: New file.
+
+2002-02-01  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Use a
+	different register in the delayed slot.  Use branch likely.
+
+	* sysdeps/mips/pt-machine.h (testandset): Call _test_and_set.
+	(__compare_and_swap): Return 0 only when failed to compare. Use
+	branch likely.
+
+2002-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+	* Versions (__libc_internal_tsd_get, __libc_internal_tsd_set,
+	__pthread_kill_other_threads_np): Move to GLIBC_PRIVATE.
+	* sysdeps/i386/i586/Versions: Move all symbols to GLIBC_PRIVATE.
+	* sysdeps/i386/i686/Versions: Move all symbols to GLIBC_PRIVATE.
+	* sysdeps/sparc/sparc32/sparcv9/Versions: New file.
+	* sysdeps/sparc/sparc64/Versions: New file.
+	* sysdeps/ia64/Versions: Move all symbols to GLIBC_PRIVATE.
+
+2002-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c: _dl_cpuclock_offset is not any longer a global variable
+	in SHARED code, use GL(dl_cpuclock_offset).
+
+2002-01-28  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_init): Clear *LOCK to
+	0. Patch by Machida Hiroyuki <machida@sm.sony.co.jp>.
+
+2002-01-16  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/s390/s390-32/pt-machine.h (MEMORY_BARRIER): Define.
+	(CURRENT_STACK_FRAME): Remove duplicate definition.
+	* sysdeps/s390/s390-64/pt-machine.h: Likewise.
+
+2002-01-14  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* Makefile (CFLAGS-tst-cancel.c): Add -fno-inline-functions to prevent
+	automatic inline.
+
+2002-01-12  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile (test-srcs): Add tst-signal.
+	(tests): Run tst-signal.
+	(distribute): Add tst-signal.sh.
+	* tst-signal.c, tst-signal.sh: New files.
+
+2002-01-14  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/pt-machine.h (INIT_THREAD_SELF): Avoid warning.
+
+2002-01-11  Andreas Schwab  <schwab@suse.de>
+
+	* signals.c (sighandler): Initialize all elements to SIG_ERR.
+	(__sigaction): Don't use value from sighandler if it is SIG_ERR.
+
+2002-01-06  Richard Henderson  <rth@redhat.com>
+
+	* sysdeps/alpha/elf/pt-initfini.c: New file.
+
+2001-12-29  Andreas Jaeger  <aj@suse.de>
+
+	* Examples/ex9.c: Add noreturn attribute for thread.
+	* Examples/ex10.c: Likewise.
+	* Examples/ex13.c (thread_start): Likewise.
+	* Examples/ex15.c (worker): Likewise.
+
+	* Examples/ex18.c: Include unistd.h for prototype of sleep.
+
+2001-12-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* man/pthread_atfork.man: Adjust description of mutex handling
+	after fork for current implementation.
+	* linuxthreads.texi: Likewise [PR libc/2519].
+
+2001-12-13  Andreas Schwab  <schwab@suse.de>
+
+	* specific.c (pthread_key_delete): Don't contact the thread
+	manager if no threads have been created yet.
+
+2001-12-12  NIIBE Yutaka  <gniibe@m17n.org>
+
+	* sysdeps/sh/pt-machine.h (INIT_THREAD_SELF): Added __volatile__
+	qualifier to be safe.
+
+2001-11-30  Andreas Schwab  <schwab@suse.de>
+
+	* pthread.c (pthread_handle_sigcancel) [THREAD_SELF]: Double check
+	that self is the manager thread, and initialize the thread
+	register if not.
+	(thread_self_stack) [THREAD_SELF]: New function to find self via
+	stack pointer.
+	* manager.c (pthread_handle_create): Don't block cancel signal any
+	more.
+
+2001-11-29  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/pt-machine.h: Use %gs as thread specific register.
+	(THREAD_SELF): New.
+	(INIT_THREAD_SELF): New.
+	(THREAD_GETMEM): New.
+	(THREAD_GETMEM_NC):
+	(THREAD_SETMEM): New.
+	(THREAD_SETMEM_NC): New.
+	(FLOATING_STACKS): Define.
+	(ARCH_STACK_MAX_SIZE): Define.
+
+2001-11-28  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Bugfix to pthread_key_delete. It was iterating over the thread
+	manager's linked list of threads, behind the thread manager's
+	back causing a race. The fix is to have the manager iterate over
+	the threads instead, using a new request type for doing so.
+	* internals.h (struct pthread_request): New manager request type
+	REQ_FOR_EACH_THREAD.
+	* manager.c (pthread_for_each_thread): New function.
+	(__pthread_manager): Handle new REQ_FOR_EACH_THREAD request.
+	* specific.c (struct pthread_key_delete_helper_args): New type.
+	(pthread_key_delete_helper): New static function.
+	(pthread_key_delete): Use the new thread manager
+	REQ_FOR_EACH_THREAD function to iterate over the threads and set
+	the delete key slot to a null value in each thread.
+	* Examples/ex18.c: New test.
+	* Makefile (tests): Add ex18.
+
+2001-11-22  Wolfram Gloger  <wg@malloc.de>
+
+	* pthread.c (pthread_onexit_process): Don't call free
+	after threads have been asynchronously terminated.
+
+	* manager.c (pthread_handle_exit): Surround cancellation
+	of threads with __flockfilelist()/__funlockfilelist().
+
+2001-11-26  Andreas Schwab  <schwab@suse.de>
+
+	* manager.c (pthread_handle_create): Start the child thread with
+	the cancel signal blocked, so that it does not handle it before
+	the thread register is set up.  Save errno from failed clone call.
+
+2001-11-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/i686/Implies: Removed.
+	* sysdeps/i386/i686/Versions: New file.
+
+2001-10-31  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/Makefile: Remove, we do not need it anymore.
+
+2001-10-05  Kevin Buettner  <kevinb@cygnus.com>
+
+	* pthread.c (__linuxthread_pthread_sizeof_descr): Change name
+	to __linuxthreads_pthread_sizeof_descr to match name used by
+	symbol_list_arr[LINUXTHREADS_PTHREAD_SIZEOF_DESCR] in
+	linuxthreads_db/td_symbol_list.c.
+
+2001-09-22  Andreas Jaeger  <aj@suse.de>
+
+	* linuxthreads/tst-context.c: Avoid compile warning.
+
+2001-09-20  Andreas Jaeger  <aj@suse.de>
+
+	* shlib-versions: Add x86-64.
+
+2001-09-19  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/x86_64/Makefile: New file.
+	* sysdeps/x86_64/pspinlock.c: New file.
+	* sysdeps/x86_64/pt-machine.h: New file.
+
+2001-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/timer_delete.c (timer_delete): Thread may be NULL
+	for SIGEV_NONE.
+	* sysdeps/pthread/timer_settime.c (timer_settime): Likewise.
+
+2001-09-11  Ulrich Drepper  <drepper@redhat.com>
+	    Wolfram Gloger <wg@malloc.de>
+
+	* join.c: Protect all communications from and to manager with
+	TEMP_FAILURE_RETRY.
+	* manager.c: Likewise.
+	* pthread.c: Likewise.
+	* smeaphore.c: Likewise.
+
+2001-08-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c (__pthread_lock): Top max_count value with
+	MAX_ADAPTIVE_SPIN_COUNT.
+	* internals.h (MAX_ADAPTIVE_SPIN_COUNT): Define if not already done.
+
+	* sysdeps/i386/i686/pt-machine.h (BUSY_WAIT_NOP): New macro to
+	help P4.
+
+2001-08-27  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_rwlock_t): Only define to
+	non-opaque type if __USE_UNIX98.
+
+2001-08-26  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_t): Define
+	non-opaque lock types also if _IO_MTSAFE_IO is defined.
+
+2001-08-23  Roland McGrath  <roland@frob.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): Take
+	new first argument, skip the cleanup handler if it's zero.
+	(_LIBC_LOCK_RECURSIVE_INITIALIZER): New macro.
+	(__libc_lock_define_initialized_recursive): Use it.
+	* sysdeps/pthread/bits/stdio-lock.h: File removed.
+	The sysdeps/generic file from the main tree now suffices.
+
+2001-08-22  Roland McGrath  <roland@frob.com>
+
+	* sysdeps/pthread/bits/stdio-lock.h: Include <bits/libc-lock.h>
+	instead of <pthread.h>.
+	(_IO_lock_t): Define this typedef using __libc_lock_define_recursive.
+	(_IO_lock_initializer): Add braces.
+	(_IO_lock_lock): Use __libc_lock_lock_recursive.
+	(_IO_lock_unlock): Use __libc_lock_unlock_recursive.
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_recursive_t): New type.
+	(__libc_lock_define_initialized_recursive): Use it.
+	(__libc_lock_init_recursive): Likewise.
+	(__libc_lock_fini_recursive): Likewise.
+	(__libc_lock_lock_recursive): Likewise.
+	(__libc_lock_trylock_recursive): Likewise.
+	(__libc_lock_unlock_recursive): Likewise.
+	(__libc_lock_define_recursive): New macro.
+
+2001-08-14  Jakub Jelinek  <jakub@redhat.com>
+
+	* lockfile.c (__pthread_provide_lockfile): New variable.
+	* pthread.c (__pthread_require_lockfile): New variable.
+	* cancel.c (__pthread_require_lockfile): New variable.
+
+2001-07-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-context.c (threadfct): Initialize context before calling
+	makecontext.
+
+	* Examples/ex17.c: Make sure test thread is around long enough.
+
+2001-07-26  kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF): Defined.
+
+2001-07-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-context.c (main): Print explanation before bailing out
+	because context handling is not supported.
+
+2001-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add tst-context.
+	* tst-context.c: New file.
+
+	* sysdeps/pthread/bits/stdio-lock.h: Define
+	_IO_cleanup_region_start_noarg.
+
+2001-07-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/alpha/pt-machine.h (FLOATING_STACKS): Define.
+	(ARCH_STACK_MAX_SIZE): Define.
+	* sysdeps/sparc/sparc32/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+2001-07-19  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/i386/useldt.h: Fix typo in ARCH_STACK_MAX_SIZE comment.
+
+	* sysdeps/ia64/pt-machine.h (FLOATING_STACKS): Define.
+	(ARCH_STACK_MAX_SIZE): Define.
+	* manager.c (pthread_allocate_stack): Handle FLOATING_STACKS with
+	NEED_SEPARATE_REGISTER_STACK.
+
+2001-07-16  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile (before-compile): Don't add $(objpfx)crti.o.
+	(omit-deps): Add crti.
+	($(objpfx)libpthread.so): Depend on $(objpfx)crti.o, but make sure
+	it is filtered out of the link command.
+
+2001-07-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (pthread_initialize): For FLOATING_STACKS don't bother
+	to find the right value for __pthread_initial_thread_bos, it's not
+	used.  If not FLOATING_STACKS first run
+	__pthread_init_max_stacksize.
+
+2001-06-16  H.J. Lu  <hjl@gnu.org>
+
+	* internals.h: Include <stackinfo.h>.
+
+	* attr.c: Don't include <stackinfo.h> here.
+	* cancel.c: Likewise.
+	* manager.c: Likewise.
+	* pthread.c: Likewise.
+	* ptlongjmp.c: Likewise.
+
+2001-03-23  Matthew Wilcox  <willy@ldl.fc.hp.com>
+
+	* attr.c: Make _STACK_GROWS_UP work.
+	* internals.h: Likewise.
+	* manager.c: Likewise.
+	* pthread.c: Likewise.
+
+2001-06-15  H.J. Lu  <hjl@gnu.org>
+
+	* pthread.c (__pthread_reset_main_thread): Fix a typo.
+
+2001-02-02  John S. Marvin  <jsm@udlkern.fc.hp.com>
+
+	* semaphore.h: Use struct _pthread_fastlock as an element of
+	sem_t instead of an identical struct.
+	* rwlock.c: Remove casts.
+	* semaphore.c: Likewise.
+
+2001-04-30  Alan Modra  <amodra@one.net.au>
+
+	* sysdeps/unix/sysv/linux/hppa/pt-initfini.c: New.
+
+2001-05-25  Bruce Mitchener  <bruce@cubik.org>
+
+	* linuxthreads.texi: Spelling corrections.
+
+2001-05-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* oldsemaphore.c (__old_sem_wait): Clear p_nextwaiting before
+	returning successfully.
+	Patch by Gene Cooperman <gene@ccs.neu.edu>.
+
+2001-05-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c (__pthread_lock) [HAS_COMPARE_AND_SWAP]: Before doing any
+	serious work try once whether the lock is uncontested.
+	Remove duplicate reading of __status before loop.
+	Change suggested by Hans Boehm <hans_boehm@hp.com>.
+
+	* spinlock.h (__pthread_trylock): Remove need for oldstatus variable.
+	(__pthread_alt_trylock): Likewise.
+
+2001-05-01  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Memory barrier overhaul following line by line inspection.
+	* mutex.c (pthread_once): Missing memory barriers added.
+	* pthread.c (__pthread_wait_for_restart_signal,
+	__pthread_timedsuspend_new, __pthread_restart_new): Added
+	memory barriers ``just in case'' and for documentary value.
+	* spinlock.c (__pthread_release): New inline function for releasing
+	spinlock, to complement __pthread_acquire.  Includes memory
+	barrier prior to assignment to spinlock, and __asm __volatile
+	dance to prevent reordering or optimization of the spinlock access.
+	* spinlock.c (__pthread_unlock, __pthread_alt_lock,
+	__pthread_alt_timedlock, __pthread_alt_unlock,
+	__pthread_compare_and_swap): Updated to use new __pthread_release
+	instead of updating spinlock directly.
+	* spinlock.c (__pthread_lock, __pthread_unlock, wait_node_alloc,
+	wait_node_free, wait_node_dequeue, __pthread_alt_lock,
+	__pthread_alt_timedlock, __pthread_alt_unlock, __pthread_acquire):
+	Memory barrier overhaul.  Lots of missing memory barriers added,
+	a couple needless ones removed.
+	* spinlock.c (__pthread_compare_and_swap): testandset optimization
+	removed, just calls __pthread_acquire, which has the new read
+	barrier in it before its testandset.
+
+2001-05-20  Roland McGrath  <roland@frob.com>
+
+	* Makeconfig: New file, variables used to be in main libc Makeconfig.
+
+2001-05-09  Geoff Keating  <geoffk@redhat.com>
+
+	* sysdeps/powerpc/pt-machine.h
+	(HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS): Define.
+	(__compare_and_swap): Remove memory barriers.
+	(__compare_and_swap_with_release_semantics): New function.
+
+2001-04-24  Andreas Jaeger  <aj@suse.de>
+
+	* wrapsyscall.c: send* and recv* return ssize_t.
+
+	* sysdeps/pthread/timer_getoverr.c (timer_getoverrun): Unlock the
+	mutex instead of double locking it.
+	Reported by Pierre Artaud <partaud@sodatec.com>.
+
+2001-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/getcpuclockid.c: Make function generic, test
+	using #ifdef whether the clock is available.
+	* sysdeps/unix/sysv/linux/i386/getcpuclockid.c: Removed.
+
+	* sysdeps/ia64/Versions: New file.
+
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c (_init): We don't
+	have to call __gmon_start__ in the libpthread DSO.
+	* sysdeps/pthread/pt-initfini.c (_init): Likewise.
+
+	* Makefile (libpthread-routines): Add ptclock_gettime and
+	ptclock_settime.
+	* internals.h: Don't use cpuclock-init.h definitions, use
+	hp-timing.h definitions.
+	* pthread.c: Likewise.
+	* manager.c: Likewise.
+	* ptclock_gettime.c: New file.
+	* ptclock_settime.c: New file.
+	* internals.h: Fix parameter type for __pthread_clock_gettime and
+	__pthread_clock_settime.
+
+	* sysdeps/i386/i586/ptclock_gettime.c: Removed.
+	* sysdeps/i386/i586/ptclock_settime.c: Removed.
+	* sysdeps/i386/i586/Makefile: Removed.
+
+2001-04-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _POSIX_ASYNCH_IO.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+2001-04-21  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/timer_routines.c (thread_func): Add noreturn
+	attribute, remove statements that will never be executed.
+	(thread_func): Remove mutex_unlock call since it's never executed.
+	(thread_func): Fix comment as suggested by Jakub Jelinek.
+
+	* manager.c (__pthread_manager): Add noreturn
+	attribute.
+	(pthread_start_thread): Likewise, remove return statement.
+	(pthread_start_thread_event): Likewise.
+	Add noreturn attribute for pthread_handle_exit.
+	* weaks.c: Add noreturn attribute for pthread_exit.
+
+	* internals.h: Add __pthread_clock_gettime and
+	__pthread_clock_settime prototypes.
+
+2001-04-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h: Include <cpuclock-init.h>.
+	(struct _pthread_descr_struct): Add p_cpuclock_offset field if
+	CPUCLOCK_VARDEF is defined.
+	* pthread.c (__pthread_initialize_minimal): Initialize
+	p_cpuclock_offset field for main thread if CPUCLOCK_INIT is defined.
+	* manager.c (pthread_start_thread): Set p_cpuclock_offset field
+	for new thread to current CPU clock value.
+
+	* sysdeps/i386/useldt.h: Extend all the macros to handle 8-byte values.
+
+	* sysdeps/i386/i586/Makefile: New file.
+	* sysdeps/i386/i586/Versions: New file.
+	* sysdeps/i386/i586/ptclock_gettime.c: New file.
+	* sysdeps/i386/i586/ptclock_settime.c: New file.
+	* sysdeps/i386/i686/Implies: New file.
+
+2001-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: Put specs into
+	$generated, not $postclean-generated.
+
+2001-04-18  Andreas Jaeger  <aj@suse.de>
+
+	* Makefile (otherlibs): Added.
+
+2001-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: New file.
+
+2001-04-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* signals.c (sigwait): NSIG is no signal number.  Block all
+	signals while in signal handler for signals in SET.
+	Patch by Manfred Spraul <manfred@colorfullife.com>.
+
+2001-04-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* tst-cancel.c: Disable most tests.  Add new test where all
+	cleanup handlers must run.
+	* Makefile (tests): Add tst-cancel again.
+
+	* cancel.c (__pthread_perform_cleanup): Correct condition for
+	leaving cleanup loop early.
+
+	* sysdeps/i386/Makefile: Make sure gcc uses a frame pointer for
+	all the files which use CURRENT_STACK_FRAME.
+	* sysdeps/i386/pt-machine.h (CURRENT_STACK_FRAME): Define using
+	__builtin_frame_address.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+
+2001-04-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Comment out tst-cancel for now.
+
+	* tst-cancel.c (main): Cleanup 4 is supposed to run.  Create
+	temporary file in object directory.
+	* Makefile: Don't allow inlining when compiling tst-cancel.c.
+	Pass $(objpfx) to tst-cancel.
+
+2001-04-11  David S. Miller  <davem@redhat.com>
+
+	* sysdeps/sparc/sparc32/pt-machine.h (stack_pointer): Advance
+	up closer to user local variables so that new cleanup heuristics work.
+	* sysdeps/sparc/sparc64/pt-machine.h (stack_pointer): Likewise.
+
+2001-04-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* cancel.c (_pthread_cleanup_push): Catch invalid __prev buffer
+	and remove it.
+	(_pthread_cleanup_push_defer): Likewise.
+
+	* tst-cancel.c (main): Fix loop printing cleanup output.
+
+2001-04-10  kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/sh/pspinlock.c (__pthread_spin_lock): Fix a reverse
+	test.
+	(__pthread_spin_trylock): Likewise.
+	* sysdeps/sh/pt-machine.h (testandset): Likewise.
+
+2001-04-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* join.c (pthread_exit): Move code to new function __pthread_do_exit
+	which takes an extra parameter with the current frame pointer.
+	Call new function with CURRENT_STACK_FRAME.
+	(__pthread_do_exit): New function.  Call __pthread_perform_cleanup
+	with the new parameter.
+	(pthread_join): Call __pthread_do_exit instead of pthread_exit.
+	* cancel.c (__pthread_perform_cleanup): Takes extra parameter.  Use
+	this parameter as the initial value the cleanup handler records are
+	compared against.  No active cleanup handler record must have an
+	address lower than the previous one and the initial record must be
+	above (below on PA) the frame address passed in.
+	(pthread_setcancelstate): Call __pthread_do_exit instead of
+	pthread_exit.
+	(pthread_setcanceltype): Likewise.
+	(pthread_testcancel): Likewise.
+	(_pthread_cleanup_pop_restore): Likewise.
+	* condvar.c (pthread_cond_wait): Likewise.
+	(pthread_cond_timedwait_relative): Likewise.
+	* manager.c (pthread_start_thread): Likewise.
+	* oldsemaphore.c (__old_sem_wait): Likewise.
+	* pthread.c (pthread_handle_sigcancel): Likewise.
+	* semaphore.c (__new_sem_wait): Likewise.
+	(sem_timedwait): Likewise.
+	* ptlongjmp.c (pthread_cleanup_upto): Also use current stack frame
+	to limit the cleanup handlers which get run.
+	* internals.h: Add prototype for __pthread_do_exit.  Adjust prototype
+	for __pthread_perform_cleanup.
+
+	* Makefile (tests): Add tst-cancel.
+	* tst-cancel.c: New file.
+
+2001-04-08  Hans-Peter Nilsson  <hp@axis.com>
+
+	* sysdeps/cris/pt-machine.h: New file.
+	* sysdeps/cris/pspinlock.c: New file.
+
+2001-04-09  Hans-Peter Nilsson  <hp@axis.com>
+
+	* shlib-versions: Add case for Linux on CRIS.
+
+2001-03-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (pthread_getattr_np): Correct computation of stack size
+	for machiens with register stack.
+
+	* Examples/ex17.c (main): Correct detection of failed mmap call.
+
+2001-03-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (__pthread_initialize_manager): Fix a typo.
+
+2001-03-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* attr.c (__pthread_attr_setstack): Fix alignment check.
+	(pthread_getattr_np): __stackaddr is top of stack, not bottom.
+	* Makefile (tests): Add ex17 test.
+	* Examples/ex17.c: New test.
+
+2001-03-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: Define -D_RPC_THREAD_SAFE_ for cancel.c.
+	* cancel.c (__pthread_perform_cleanup): Call __rpc_thread_destroy.
+	* sysdeps/pthread/bits/libc-tsd.h: Define _LIBC_TSD_KEY_VARS.
+
+2001-03-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: When generating DSO link with libc_nonshared.a.
+
+2001-02-26  Jakub Jelinek  <jakub@redhat.com>
+
+	* signals.c (pthread_sighandler): Use CALL_SIGHANDLER.
+
+2001-02-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (__pthread_init_max_stacksize): New prototype.
+	* attr.c (__pthread_attr_setstacksize): Call
+	__pthread_init_max_stacksize if not yet initialized.
+	* pthread.c (__pthread_init_max_stacksize): New function.
+	(__pthread_initialize_manager): Call it.
+	Patch by <dtc@cmucl.cons.org>.
+
+2001-03-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (pthread_getattr_np): Fix __stacksize computation for IA-64.
+
+2001-03-13  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* shlib-versions: Add rule for Linux on 64 bit S/390.
+	* sysdeps/s390/s390-64/pt-machine.h: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: New file.
+
+2001-03-13  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/s390/pt-machine.h: Move to...
+	* sysdeps/s390/s390-32/pt-machine.h: ...here.
+	Add defines for FLOATING_STACK and ARCH_STACK_MAX_SIZE.
+
+2001-03-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions [libpthread] (GLIBC_2.2.3): Add pthread_getattr_np.
+	* attr.c: Implement pthread_getattr_np.
+	* sysdeps/pthread/pthread.h: Add prototype for pthread_getattr_np.
+	* internals.h (struct _pthread_descr_struct): Add p_inheritsched.
+	* manager.c (pthread_handle_create): Initialize p_inheritsched.
+
+2001-03-09  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/pt-initfini.c: Use 0x07 padding for
+	code alignment.
+
+2001-02-20  Hans Boehm  <hans_boehm@hp.com>
+
+	* manager.c (manager_mask): Removed static vesion.  Now always local
+	to __pthread_manager().
+	(manager_mask_all): Removed completely.
+	(__pthread_manager): Remove manager_mask_all initialization.
+	(pthread_handle_create): Remove code to set and reset signal mask
+	around __clone2() calls.
+
+2001-02-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* spinlock.c (__pthread_lock): Force lock->__status to be read from
+	memory on every spin.
+
+2001-02-10  Andreas Jaeger  <aj@suse.de>
+
+	* Makefile (extra-objs): New.
+
+2001-02-09  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Add
+	__pthread_initialize_minimal prototype.
+
+2001-02-08  kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+	* sysdeps/unix/sysv/linux/sh/pt-initfini.c: New file.
+
+2001-02-06  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/pt-initfini.c: New file.
+
+2001-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: First attempt to fix the
+	broken code.  Patch by Jes Sorensen.
+
+2001-02-06  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/pthread.h: Move __pthread_initialize from here
+	to...
+	* internals.h: ...here.
+
+2001-02-05  Jes Sorensen  <jes@linuxcare.com>
+
+	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: New file.
+
+2001-02-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions: Remove __pthread_initialize_minimal.
+
+2001-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: Add rules to build crti.o and make it being used in
+	building libpthread.so.
+	* sysdeps/i386/Makefile: New file.
+	* sysdeps/pthread/pt-initfini.c: New file.
+
+	* pthread.c: Cleanups.
+
+2001-01-28  Andreas Jaeger  <aj@suse.de>
+
+	* oldsemaphore.c (__old_sem_init): Adjust for last change.
+	* sysdeps/pthread/bits/libc-lock.h: Likewise.
+	* spinlock.c: Likewise.
+
+2001-01-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/initspin.h: Make all names namespace clean.
+	* sysdeps/unix/sysv/linux/hppa/bits/initspin.h: Likewise.
+	* manager.c: Adjust for namespace cleanup in bits/initspin.h.
+	* pthread.c: Likewise.
+	* spinlock.h: Likewise.
+	* sysdeps/pthread/pthread.h: Likewise.
+
+2001-01-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/pthreadtypes.h: Define pthread_attr_t also
+	as struct __pthread_attr_s.
+
+	* semaphore.h (sem_t): Cleanup namespace, rename status and
+	spinlock elements.
+
+2001-01-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (pthread_onexit_process): Clear
+	__pthread_manager_thread_bos after freeing it.
+	* Makefile (tests): Add ex16.
+	* Examples/ex16.c: New file.
+
+2001-01-11  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (CFLAGS-pthread.c): Pass -DHAVE_Z_NODELETE if ld supports
+	-z nodelete.
+	* pthread.c (pthread_exit_process): Rename to...
+	(pthread_onexit_process): ...this.
+	(pthread_atexit_process, pthread_atexit_retcode): New.
+	(pthread_initialize): Call __cxa_atexit instead of __cxa_on_exit
+	and only if HAVE_Z_NODELETE is not defined.
+	(__pthread_initialize_manager): Register pthread_atexit_retcode
+	with __cxa_atexit.
+
+2001-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (pthread_initialize): Use __cxs_on_exit not __cxa_atexit.
+
+2001-01-11  Jakub Jelinek  <jakub@redhat.com>
+
+	* Makefile (tests): Add ex15.
+	* Examples/ex15.c: New test.
+
+2001-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (pthread_exit_process): Free memory allocated for
+	manager stack.
+
+2000-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* manager.c (pthread_alloca_stack): Remove MAP_FIXED from mmap calls.
+	(pthread_free): Always unmap the stack.  It's safe now that we don't
+	use MAP_FIXED to allocate stacks.
+
+2000-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/powerpc/pspinlock.c: Don't include pt-machine.h here.
+
+	* manager.c (pthread_allocate_stack): Prepare for removal of MAP_FIXED.
+
+2000-11-15  Wolfram Gloger  <wg@malloc.de>
+
+	* manager.c (pthread_free): [!FLOATING_STACKS]: Only remap the
+	stack to PROT_NONE, don't unmap it, avoiding collisions with malloc.
+
+2000-12-27  Andreas Jaeger  <aj@suse.de>
+
+	* Examples/ex13.c: Make local functions static.
+	* ecmutex.c: Likewise.
+	* joinrace.c: Likewise.
+	* Examples/ex14.c: Likewise.
+
+	* Examples/ex2.c: Make local functions static; reformat.
+	* Examples/ex1.c: Likewise.
+	* Examples/ex4.c: Likewise.
+	* Examples/ex5.c: Likewise.
+	* Examples/ex7.c: Likewise.
+
+	* oldsemaphore.c: Add prototypes to shut up GCC.
+	* pt-machine.c: Likewise.
+
+	* weaks.c: Add prototype for pthread_exit.
+
+	* internals.h: Add some prototypes, format prototypes and add
+	missing externs.
+	Move __libc_waitpid prototype to include/sys/wait.h.
+
+	* rwlock.c: Include <bits/libc-lock.h> for prototypes.
+	* mutex.c: Likewise.
+	* specific.c: Likewise.
+	* ptfork.c: Likewise.
+
+	* lockfile.c: Include internals.h to get prototypes.
+	* events.c: Likewise.
+	* sysdeps/alpha/pspinlock.c: Likewise.
+	* sysdeps/arm/pspinlock.c: Likewise.
+	* sysdeps/hppa/pspinlock.c: Likewise.
+	* sysdeps/i386/pspinlock.c: Likewise.
+	* sysdeps/ia64/pspinlock.c: Likewise.
+	* sysdeps/m68k/pspinlock.c: Likewise.
+	* sysdeps/mips/pspinlock.c: Likewise.
+	* sysdeps/powerpc/pspinlock.c: Likewise.
+	* sysdeps/s390/pspinlock.c: Likewise.
+	* sysdeps/sh/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc32/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc32/sparcv9/pspinlock.c: Likewise.
+	* sysdeps/sparc/sparc64/pspinlock.c: Likewise.
+
+2000-12-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (__pthread_attr_setstack): Fix setting of __stackaddr element.
+	(__pthread_attr_getstack): Return correct address.
+	Add warnings for using pthread_attr_getstackaddr and
+	pthread_attr_setstackaddr.
+
+2000-12-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* Examples/ex6.c (test_thread): Make static.
+	* Examples/ex12.c (test_thread): Make static and add noreturn
+	attribute.
+
+2000-12-18  Jes Sorensen  <jes@linuxcare.com>
+
+	* linuxthreads/sysdeps/ia64/pt-machine.h: __compare_and_swap
+	and compare_and_swap_with_release_semantics returns int not long.
+
+2000-12-17  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/s390/pt-machine.h (testandset): Use long int as return
+	value.
+	* sysdeps/arm/pt-machine.h (testandset): Likewise.
+	* sysdeps/hppa/pt-machine.h (testandset): Likewise.
+	* sysdeps/m68k/pt-machine.h (testandset): Likewise.
+	* sysdeps/sh/pt-machine.h (testandset): Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h (testandset): Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h (testandset): Likewise.
+
+2000-12-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/pt-machine.h (testandset): Adjust for prototype change.
+	* sysdeps/i386/i686/pt-machine.h (testandset): Likewise.
+
+2000-12-17  Andreas Jaeger  <aj@suse.de>
+
+	* internals.h: Add prototypes for testandset and
+	__compare_and_swap to shut up gcc warnings.
+
+2000-12-06  Wolfram Gloger  <wg@malloc.de>
+
+	* join.c (pthread_detach): Allow case where the thread has already
+	terminated.
+
+2000-12-05  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Don't set mips2.
+	* sysdeps/mips/pt-machine.h (testandset): Likewise.
+	(__compare_and_swap): Likewise.
+	Patches by Maciej W. Rozycki <macro@ds2.pg.gda.pl>.
+
+2000-11-20  Jakub Jelinek  <jakub@redhat.com>
+
+	* Examples/ex3.c (main): Cast int to long before casting to void *.
+	(search): Cast void * to long, not int.
+	* Examples/ex8.c (main, thread): Similarly.
+	* Examples/ex11.c (main): Similarly.
+	* Examples/ex14.c (worker, do_test): Similarly.
+	* ecmutex.c (worker, do_test): Similarly.
+	(nlocks): Cast to int.
+
+2000-11-08  Bruce Mitchener  <bruce@cubik.org>
+
+	* linuxthreads.texi:  Add documentation for pthreads attributes
+	guardsize, stackaddr, stacksize, and stack.  Fix typo in previous
+	patch.  Document pthread_[sg]etconcurrency().  Mark
+	pthread_mutexattr_[sg]ettype() as POSIX rather than GNU.
+
+2000-11-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_MESSAGE_PASSING):
+	Don't define it.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+	Reported by Christopher Yeoh <cyeoh@linuxcare.com.au>.
+
+2000-11-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* cancel.c (pthread_cancel): Always set p_canceled, even if we are
+	not doing it right now.
+	Reported by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-10-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* Examples/ex4.c (main): Don't use exit() to avoid warning with
+	broken compilers.
+
+2000-10-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c (__pthread_attr_setguardsize): Don't round guardsize
+	here.  Reported by Bruce Mitchener <bruce@cubik.org>.
+
+	* linuxthreads.texi: Changes terminology to 'type' from 'kind' when
+	discussing mutexes. (As per the Unix98 name for the API.)
+	Changes documentation for pthread_mutexattr_setkind_np() and
+	pthread_mutexattr_getkind_np() over to the Unix98 APIs for the
+	same: pthread_mutexattr_settype() and pthread_mutexattr_gettype().
+	Changes references to PTHREAD_MUTEXATTR_FAST_NP to
+	PTHREAD_MUTEXATTR_ADAPTIVE_NP.
+	Begins to introduce discussion of the ``timed'' mutex type.  This
+	discussion is currently incomplete.
+	Patch by Bruce Mitchener <bruce@cubik.org>.
+
+2000-10-26  Kazumoto Kojima  <kkojima@rr.iij4u.or.jp>
+	    Yutaka Niibe  <gniibe@chroot.org>
+
+	* sysdeps/sh/pt-machine.h (testandset): Since the operand of TAS.B
+	has restrictions, use register.
+
+2000-10-23  Andreas Schwab  <schwab@suse.de>
+
+	* Examples/ex14.c (TIMEOUT): Override default timeout.
+
+2000-10-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* specific.c: Protect tsd array modification in thread data
+	structures by getting the thread lock in pthread_key_delete and
+	__pthread_destroy_specifics.
+	Patch by Wolfram Gloger <Wolfram.Gloger@dent.med.uni-muenchen.de>.
+
+2000-10-12  Alan Modra <alan@linuxcare.com.au>
+
+	* sysdeps/pthread/bits/initspin.h: New file.
+	* spinlock.h: Move LOCK_INITIALIZER definition to <bits/initspin.h>.
+	(__pthread_init_lock): Initialize lock with LT_SPINLOCK_INIT.
+	(__pthread_alt_init_lock): Likewise.
+	(__pthread_alt_trylock): Release lock with LT_SPINLOCK_INIT.
+
+2000-10-12  David Huggins-Daines  <dhd@linuxcare.com>
+
+	* oldsemaphore.c (__old_sem_init): Release lock with
+	LT_SPINLOCK_INIT, not zero.
+	* spinlock.c (__pthread_unlock): Likewise.
+	(__pthread_alt_lock): Likewise.
+	(__pthread_alt_timedlock): Likewise.
+	(__pthread_alt_unlock): Likewise.
+	* sysdeps/pthread/bits/libc-lock.h: Initialize locks with
+	LT_SPINLOCK_INIT if it is non-zero.  Likewise for init-once flags.
+	* sysdeps/pthread/pthread.h: Include bits/initspin.h.  Use
+	LT_SPINLOCK_INIT do initialize spinlocks not 0.
+
+2000-10-12  David Huggins-Daines <dhd@linuxcare.com>
+
+	* shlib-versions: Add version definitions for hppa-linux.
+
+2000-10-12  Alan Modra <alan@linuxcare.com.au>
+
+	* sysdeps/hppa/pspinlock.c: New file.
+	* sysdeps/hppa/pt-machine.h: New file.
+	* sysdeps/unix/sysv/linux/hppa/bits/initspin.h: New file.
+
+2000-10-05  Jakub Jelinek  <jakub@redhat.com>
+
+	* mutex.c (__pthread_mutex_destroy): Correct test of
+	busy mutex for mutexes using alternate fastlocks.
+	Patch by dtc@cmucl.cons.org.
+
+2000-09-28  Martin Schwidefsksy    <schwidefsky@de.ibm.com>
+
+	* sysdeps/s390/pt-machine.h: Make %a0 the thread register.
+
+2000-09-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* mutex.c (__pthread_mutex_unlock): For PTHREAD_MUTEX_RECURSIVE_NP
+	test for owner first.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+	* cancel.c (pthread_cancel): Don't do anything if cancelation is
+	disabled.
+
+2000-09-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.h (__pthread_set_own_extricate_if): Optimize a bit.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remove
+	_POSIX_MONOTONIC_CLOCK.
+
+	* spinlock.h (__pthread_set_own_extricate_if): Add back locking
+	and explain why.
+
+2000-09-20  Andreas Jaeger  <aj@suse.de>
+
+	* pthread.c [!__ASSUME_REALTIME_SIGNALS]: Make inclusion of
+	"testrtsig.h" conditional.
+
+2000-09-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Declare pthread_attr_getstack and
+	pthread_attr_setstack.
+	* Versions [libpthread] (GLIBC_2.2): Export pthread_attr_getstack and
+	pthread_attr_setstack.
+	* attr.c (pthread_attr_getstack, pthread_attr_setstack): New functions.
+
+2000-09-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Examples/ex14.c: New file.
+	* Makefile (tests): Add ex14.
+
+	* mutex.c (__pthread_mutex_unlock): Correct test for already unlocked
+	mutex.  Patch by dtc@cmucl.cons.org.
+
+	* ecmutex.c: New file.
+	* Makefile (tests): Add ecmutex.
+
+2000-09-04  H.J. Lu  <hjl@gnu.org>
+
+	* attr.c (__pthread_attr_setguardsize): Use page_roundup
+	instead of roundup to round up to the page size.
+
+2000-09-03  Mark Kettenis  <kettenis@gnu.org>
+
+	* manager.c (pthread_exited): Correctly report event as TD_REAP
+	instead of TD_DEATH.  Fix comments.
+
+2000-09-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.h (testandset): Add cast to avoid warning.
+	Patch by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>.
+
+2000-09-02  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/timer_routines.c: Include stdlib.h for abort
+	prototype.
+
+2000-09-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/bits/stdio-lock.h (_IO_cleanup_region_start):
+	Fix typo in last patch (_mode -> _flags).
+
+	* sysdeps/pthread/bits/stdio-lock.h (_IO_cleanup_region_start):
+	Provide definition which respects _IO_USER_LOCK flag.
+
+2000-08-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* manager.c (pthread_allocate_stack): Clear descriptor only if not
+	mmaped.
+
+2000-08-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: Add rules to build and run unload.
+	* unload.c: New file.
+
+	* pthread.c (pthread_exit_process): Move thread_self use inside `if'.
+
+	* sysdeps/pthread/pthread.h
+	(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Defined.
+	(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: Defined.
+
+2000-08-24  Andreas Jaeger  <aj@suse.de>
+
+	* Examples/ex13.c: Include <string.h> for strerror prototype and
+	<stdlib.h> for abort prototype.
+	(pthr_cond_signal_mutex): Rewrite to silence GCC.
+	(thread_start): Remove unused variable err.
+	(main): Silence GCC warnings.
+
+2000-08-22  Andreas Jaeger  <aj@suse.de>
+
+	* Examples/ex13.c: New test by Kurt Garloff <garloff@suse.de>.
+
+	* Makefile (tests): Add ex13.
+
+2000-08-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* semaphore.h: Add restrict where required by AGd4.
+	* sysdeps/pthread/pthread.h: Likewise.
+	* sysdeps/pthread/unix/sysv/linux/bits/sigthread.h: Likewise.
+
+2000-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add ex12.  Add rule to build it.
+	* Examples/ex12.c: New file.
+
+2000-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _POSIX_SEMAPHORES
+	even though the implementation is not quite complete (but it reports
+	it).  Define _POSIX_MESSAGE_PASSING to -1.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+2000-08-12  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/mips/pt-machine.h (testandset): Add .set mips2 for
+	assembler.
+	(__compare_and_swap): Likewise.
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Likewise.
+
+2000-08-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__pthread_initial_thread): Initialize p_errnop and
+	p_h_errnop correctly and not to NULL.
+
+2000-08-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Banner: Bump version number to 0.9.
+
+2000-08-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add tststack.  Add rule to build the program.
+	* tststack.c: New file.
+
+	* internals.h: Declare __pthread_max_stacksize.
+	* pthread.c (__pthread_max_stacksize): New variable.
+	(__pthread_initialize_manager): Determine __pthread_initialize_manager
+	value.
+	* manager.c (thread_segment): Return always NULL if FLOATING_STACKS.
+	(pthread_allocate_stack): Allow kernel to choose stack address if
+	FLOATING_STACKS.  This also handles variable-sized stacks.
+	Always allocate stack and guardpage together.  Use mprotect to
+	change guardpage access.
+	* sysdeps/i386/useldt.h: Define FLOATING_STACKS and
+	ARCH_STACK_MAX_SIZE.
+
+	* attr.c (__pthread_attr_setstacksize): Also test value against
+	upper limit.
+
+	* manager.c (__pthread_nonstandard_stacks): Define only if
+	THREAD_SELF is not defined.
+	(pthread_allocate_stack): Always initialize gardaddr to a correct
+	value.
+	(pthread_handle_create): Unmap thread with one call.
+	(pthread_free): Remove test for initial thread before removing stack.
+	Unmap stack with one call.
+
+	* pthread.c (__pthread_initial_thread): Initialize p_userstack to
+	1 to avoid removing the stack.
+
+2000-07-27  Jes Sorensen  <jes@linuxcare.com>
+
+	* sysdeps/ia64/pspinlock.c (__pthread_spin_lock): Add
+	load of spin lock to prime the cache before the atomic compare and
+	exchange operation (cmpxchg4). This avoids the spinning on the
+	cmpxchg4 instruction and reduces movement of the cache line back
+	and forth between the processors (explanation by Asis K. Mallick
+	from Intel). This basically makes the implementation operate the
+	same as the Linux kernel implementation.
+
+	* shlib-versions: Use GLIBC_2_2 for Linux/ia64.
+	* sysdeps/ia64/pspinlock.c: New file.
+
+2000-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c: Move definition of __pthread_set_own_extricate_if...
+	* spinlock.h: ...here.  Remove locking.
+	* internals.h: Remove __pthread_set_own_extricate_if prototype.
+
+	* rwlock.c: Use THREAD_GETMEM And THREAD_SETMEM.
+	(rwlock_rd_extricate_func): Don't determine self, let
+	__pthread_lock do it.
+	(rwlock_wr_extricate_func): Likewise.
+	(rwlock_have_already): Optimize *pself handling a bit.
+
+	* mutex.c: Use __builtin_expect.
+	* pthread.c: Likewise.
+
+2000-08-02  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/s390/pspinlock.c: New file.
+	* sysdeps/s390/pt-machine.h: New file.
+	Patches by Martin Schwidefsky <schwidefsky@de.ibm.com>.
+
+2000-07-12  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Implement for
+	R3K.
+	* sysdeps/mips/pt-machine.h (testandset): Likewise.
+
+2000-07-26  Andreas Jaeger  <aj@suse.de>
+
+	* pthread.c: Initialize p_sem_avail.
+
+2000-07-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h (struct __pthread_descr_struct): Add p_sem_avail.
+	* semaphore.c: Handle spurious wakeups.
+
+	* sysdeps/pthread/pthread.h: Add back PTHREAD_MUTX_FAST_NP as an alias
+	for PTHREAD_MUTEX_ADAPTIVE_NP for source code compatibility.
+
+	* pthread.c (__pthread_set_own_extricate): Use THREAD_GETMEM.
+	(__pthread_wait_for_restart): Likewise.
+
+	* condvar.c (pthread_cond_wait): Also check whether thread is
+	cancelable before aborting loop.
+	(pthread_cond_timedwait): Likewise.
+
+	* signals.c (pthread_sighandler): Remove special code to restrore
+	%gs on x86.
+	(pthread_sighandler_t): Likewise.
+
+2000-07-25  Mark Kettenis  <kettenis@gnu.org>
+
+	* internals.h (__RES_PTHREAD_INTERNAL): Remove define.
+	* pthread.c: Include <resolv.h>.
+	(_res): Undefine.  Add extern declaration.
+
+2000-07-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__pthread_initial_thread): Update initializer.
+	(__pthread_manager_thread): Likewise.
+	(pthread_initialize): Move setrlimit call to...
+	(__pthread_initialize_manager): ...here.
+	(__pthread_reset_main_thread): Reset also soft limit on stack size.
+
+	* condvar.c: Handle spurious wakeups.  [PR libc/1749].
+	* internals.h (struct _pthread_descr_struct): Add p_condvar_avail.
+
+2000-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.h: If IMPLEMENT_TAS_WITH_CAS is defined use
+	__compare_and_swap to define testandset.
+	* sysdeps/powerpc/pt-machine.h: Add volatile to asms.
+	Define IMPLEMENT_TAS_WITH_CAS.
+
+2000-07-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile: Pass -z nodelete to linker for libpthread.so
+	generation if it understand this option.
+
+2000-07-18  Mark Kettenis  <kettenis@gnu.org>
+
+	* manager.c (pthread_handle_create): Remove initialization of
+	new_thread->p_res._sock.
+
+2000-07-19  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Bugfixes to the variant of the code for machines with no compare
+	and swap.
+
+	* spinlock.c (__pthread_alt_lock, __pthread_alt_timedlock): Wait
+	node was not being properly enqueued, due to failing to update
+	the lock->__status field.
+
+	* spinlock.c (__pthread_alt_timedlock): The oldstatus variable was
+	being set inappropriately, causing the suspend function to be called
+	with a null self pointer and crash.
+
+2000-07-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.h (__pthread_alt_trylock): Fix code used if no
+	compare&swap is available.
+
+	* spinlock.h (__pthread_trylock): Use __compare_and_swap, not
+	compare_and_swap.
+
+	* pthread.c (pthread_initialize): Don't use sysconf to determine
+	whether the machine has more than one processor.
+
+	* spinlock.c (__pthread_alt_timedlock): Add back one of the
+	removed thread_self calls.
+
+2000-07-18  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* spinlock.c (__pthread_alt_lock, __pthread_alt_timedlock): Changed
+	__compare_and_swap to compare_and_swap in code which assumes
+	compare swap is available.
+
+2000-07-18  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* spinlock.c (__pthread_alt_lock, __pthread_alt_timedlock): Fixed
+	bug whereby thr field of waitnode structure would not be correctly
+	set unless a null self pointer is passed to the functions.
+	Eliminated redundant calls to thread_self().
+
+2000-07-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread.c (__pthread_initialize_manager): Lock
+	__pthread_manager_thread.p_lock before calling clone.
+
+2000-05-05  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/ia64/pt-machine.h (__compare_and_swap): Change it to
+	have acquire semantics.
+	(__compare_and_swap_with_release_semantics): New inline
+	function.
+	(HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS): New macro.
+
+2000-01-28  Hans Boehm  <hboehm@exch.hpl.hp.com>
+
+	* manager.c: Fix the problem with signals at startup.
+	Change the way that thread stacks are allocated on IA64.
+	Clean up some of the guard page allocation stuff.
+
+1999-12-19  H.J. Lu  <hjl@gnu.org>
+
+	* internals.h (page_roundup): New.
+	* attr.c (__pthread_attr_setguardsize); Use page_roundup
+	instead of roundup.
+	* manager.c (pthread_allocate_stack): Make sure guardaddr is
+	page aligned with page_roundup if NEED_SEPARATE_REGISTER_STACK
+	is define.
+
+1999-12-17  Hans Boehm  <hboehm@exch.hpl.hp.com>
+
+	* manager.c (pthread_allocate_stack): Unmap the stack top
+	if failed to map the stack bottom.
+	Fix the guard page.
+	(pthread_free): Fix the guard page.
+
+	* pthread.c (pthread_initialize): Set rlimit correctly for
+	NEED_SEPARATE_REGISTER_STACK.
+
+1999-12-16  H.J. Lu  <hjl@gnu.org>
+
+	* pthread.c (__pthread_initialize_manager): Pass
+	__pthread_manager_thread_bos instead of
+	__pthread_manager_thread_tos to __clone2.
+
+1999-12-16  H.J. Lu  <hjl@gnu.org>
+
+	* manager.c (pthread_allocate_stack): Correct the calculation
+	of "new_thread_bottom". Remove MAP_GROWSDOWN from mmap for
+	stack bottom.
+
+1999-12-13  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/ia64/pt-machine.h (__compare_and_swap): Added a stop
+	bit after setting ar.ccv.
+
+1999-12-12  H.J. Lu  <hjl@gnu.org>
+
+	* manager.c (pthread_allocate_stack): Make the starting
+	address of the stack bottom page aligned. FIXME: it may
+	need changes in other places.
+	(pthread_handle_create): Likewise.
+
+1999-12-11  Hans Boehm  <hboehm@exch.hpl.hp.com>
+
+	* manager.c (pthread_allocate_stack): Handle
+	NEED_SEPARATE_REGISTER_STACK.
+	(pthread_handle_create): Likewise.
+	* pthread.c (__pthread_initialize_manager): Likewise.
+
+	* sysdeps/ia64/pt-machine.h: Use r13 for thread pointer.
+
+1999-12-02  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/ia64/pt-machine.h: New.
+
+2000-07-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* wrapsyscall.c: Mark non-__ protected names as weak.
+	PR libc/1466.
+
+2000-07-12  Bruno Haible  <haible@clisp.cons.org>
+
+	* Examples/ex8.c: Include <sys/wait.h>, not <wait.h>.
+
+2000-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c: Fix code for TEST_FOR_COMPARE_AND_SWAP being defined.
+	Add tests also to new alternative spinlock implementation.
+	* spinlock.h: Likewise.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-07-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* Version: Export __sigaction.
+	* signals.c: Define __sigaction alias.  Use __libc_sigaction instead
+	of __sigaction.
+	* pthread.c: Use __libc_sigaction instead of __sigaction.
+
+	* condvar.c: Implement pthread_condattr_getpshared and
+	pthread_condattr_setpshared.
+	* mutex.c: Implement pthread_mutexattr_getpshared and
+	 pthread_mutexattr_setpshared.
+	* Versions: Export new functions.
+	* sysdeps/pthread/pthread.h: Add prototypes for new functions.
+
+	* rwlock.c (pthread_rwlockattr_init): Use PTHREAD_PROCESS_PRIVATE.
+	(pthread_rwlockattr_setpshared): Fail if PTHREAD_PROCESS_PRIVATE
+	is not selected.
+
+2000-07-04  Greg McGary  <greg@mcgary.org>
+
+	* sysdeps/pthread/bits/libc-lock.h: Remove BP_SYM from
+	pragmas.  Include bp-sym.h only if _LIBC.
+
+2000-07-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c (__pthread_unlock): Properly place write barrier.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-07-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c: Replace fast spinlocks by adaptive spinlocks which are
+	faster on SMP systems.  No more emulation of compare&swap for adaptive
+	spinlocks.
+	* spinlock.h: Likewise.
+	* sysdeps/pthread/pthread.h: Shuffle PTHREAD_MUTEX_* values around.
+	Replace fast with adaptive mutex.
+	* mutex.c: Rewrite for replacement of fast by adaptive mutex.
+	* condvar.c: Likewise.
+	* pthread.c: Define and initialize __pthread_smp_kernel variable.
+	* internals.h: Declare __pthread_smp_kernel.
+	* sysdeps/pthread/bits/pthreadtypes.h: Update comment of
+	_pthread_fastlock structure.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+	* pthread.c: Remove initialization to zero from global variables.
+
+2000-06-29  Jakub Jelinek  <jakub@redhat.com>
+
+	* shlib-versions: Make sparc64 GLIBC_2.2+ only.
+
+2000-06-28  Greg McGary  <greg@mcgary.org>
+
+	* weaks.c: Wrap BP_SYM () around weak extern declarations of
+	pthread functions that have pointers in their return+arg signatures.
+
+2000-06-27  Greg McGary  <greg@mcgary.org>
+
+	* sysdeps/pthread/bits/libc-lock.h: Wrap BP_SYM () around weak
+	extern declarations of pthread functions that have pointers in
+	their return+arg signatures.
+
+2000-06-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add ex11.  Add rules to build it.
+	* Examples/ex11.c: New file.
+	* rwlock.c: Fix complete braindamaged previous try to implement
+	timedout functions.
+
+	* spinlock.c: Pretty print.
+
+2000-06-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add ex10.  Add rules to build it.
+	* Versions [GLIBC_2.2] (libpthread): Add pthread_mutex_timedlock,
+	pthread_rwlock_timedrdlock, and pthread_rwlock_timedwrlock.
+	* condvar.c (pthread_cond_wait): Allow mutex of kind
+	PTHREAD_MUTEX_TIMED_NP.
+	(pthread_cond_timedwait_relative): Likewise.
+	* mutex.c (__pthread_mutex_init): Default is PTHREAD_MUTEX_TIMED_NP.
+	(__pthread_mutex_trylock): Use __pthread_alt_trylock for
+	PTHREAD_MUTEX_ERRORCHECK_NP.  Handle PTHREAD_MUTEX_TIMED_NP.
+	(__pthread_mutex_lock): Use __pthread_alt_lock for
+	PTHREAD_MUTEX_ERRORCHECK_NP.  Handle PTHREAD_MUTEX_TIMED_NP.
+	(__pthread_mutex_timedlock): New function.
+	(__pthread_mutex_unlock): Use __pthread_alt_unlock for
+	PTHREAD_MUTEX_ERRORCHECK_NP.  Handle PTHREAD_MUTEX_TIMED_NP.
+	(__pthread_mutexattr_init): Use PTHREAD_MUTEX_TIMED_NP.
+	(__pthread_mutexattr_settype): Allow PTHREAD_MUTEX_TIMED_NP.
+	* spinlock.c: Implement alternate fastlocks.
+	* spinlock.h: Add prototypes.
+	* Examples/ex10.c: New file.
+	* sysdeps/pthread/pthread.h: Add prototypes for new functions.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+	* rwlock.c (__pthread_rwlock_rdlock): Optimize loop a bit.
+	(__pthread_rwlock_timedrdlock): New function.
+	(__pthread_rwlock_timedwrlock): New function.
+	Use laternate fastlock function everywhere.
+
+2000-06-21  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/timer_routines.c: Include <string.h> for memset
+	prototype.
+
+	* join.c: Include <stdlib.h> for exit prototype.
+
+2000-06-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/useldt.h: Include <stdlib.h>.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _POSIX_BARRIERS.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+	* Makefile (libpthread-routines): Add barrier.
+	(tests): Add ex9.  Add rule to build ex9.
+	* Versions: Export barrier functions.
+	* barrier.c: New file.
+	* Examples/ex9.c: New file.
+	* sysdeps/pthread/pthread.h: Add barrier data types and declarations.
+	* sysdeps/pthread/bits/pthreadtypes.h: Likewise.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-06-19  H.J. Lu  <hjl@gnu.org>
+
+	* spinlock.h (HAS_COMPARE_AND_SWAP): Defined if
+	HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS is defined.
+	(compare_and_swap_with_release_semantics): New. Default to
+	compare_and_swap if HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+	is not defined.
+
+	* spinlock.c (__pthread_unlock): Call
+	compare_and_swap_with_release_semantics () instead of
+	compare_and_swap ().
+
+2000-06-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_create.c: Use _set_errno instead of assigning
+	to errno directly.
+	* sysdeps/pthread/timer_delete.c: Likewise.
+	* sysdeps/pthread/timer_getoverr.c: Likewise.
+	* sysdeps/pthread/timer_gettime.c: Likewise.
+	* sysdeps/pthread/timer_settime.c: Likewise.
+
+2000-06-13  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Timer nodes are now reference counted, and can be marked
+	as deleted. This allows for the safe release of the global mutex
+	in the middle without losing the timer being operated on.
+
+	* sysdeps/pthread/posix-timer.h (struct timer_node):  The inuse
+	member is now an enum with three values, so that an intermediate
+	state can be represented (deleted but not free for reuse yet).
+	New refcount member added.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+
+	* sysdeps/pthread/posix-timer.h (timer_addref, timer_delref,
+	timer_valid): New inline functions added.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Function
+	restructured, recursive deadlock bug fixed.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Uses new
+	timer_addref to ensure that timer won't be deleted while mutex is not
+	held. Also uses timer_invalid to perform validation of timer handle.
+	* sysdeps/pthread/timer_settime.c (timer_settime): Likewise.
+	* sysdeps/pthread/timer_getoverr.c (timer_getoverrun): Likewise.
+
+2000-06-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* shlib-versions: Add entry for SH.
+	Patch by Kaz Kojima <kkojima@rr.iij4u.or.jp>.
+
+2000-06-13  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	A few optimizations.  Got rid of unnecessary wakeups of timer threads,
+	tightened up some critical regions and micro-optimized some list
+	manipulation code.
+
+	* sysdeps/pthread/timer_routines.c (__timer_thread_queue_timer):
+	Returns int value now to indicate whether timer was queued at head.
+	* sysdeps/pthread/posix-timer.h: Likewise.
+	* sysdeps/pthread/timer_settime.c (timer_settime): Takes advantage of
+	new return value from __timer_thread_queue_timer to avoid waking
+	up timer thread unnecessarily.
+
+	* sysdeps/pthread/posix-timer.h (timer_id2ptr): No longer checks
+	inuse flag, because this requires mutex to be held.  Callers updated
+	to do the check when they have the mutex.
+	* sysdeps/pthread/timer_getoverr.c: Add check for inuse here.
+
+	* sysdeps/pthread/timer_settime.c (timer_settime): Tighter critical
+	regions: avoids making system calls while holding timer mutex, and
+	a few computations were moved outside of the mutex as well.
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Likewise.
+
+	* sysdeps/pthread/posix-timer.h (list_unlink_ip): Function name changed
+	to list_unlink_ip, meaning idempotent.  Pointer manipulation
+	changed to get better better code out of gcc.
+	* sysdeps/pthread/timer_routines.c (list_unlink): Non-idempotent
+	version of list_unlink added here.
+	* sysdeps/pthread/timer_delete.c: Use appropriate list unlink
+	function in all places: idempotent one for timers, non-idempotent
+	one for thread nodes.
+	* sysdeps/pthread/timer_settime: Likewise.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+
+2000-06-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_TIMERS): Define.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+	* sysdeps/pthread/Makefile: Remove tests definition.
+
+2000-06-12  Kazumoto Kojima  <kkojima@rr.iij4u.or.jp>
+	    Yutaka Niibe  <gniibe@chroot.org>
+
+	* sysdeps/sh/pspinlock.c: New file.
+	* sysdeps/sh/pt-machine.h: New file.
+
+2000-06-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add joinrace.
+
+	* Examples/ex6.c: Test return value of pthread_join.
+
+2000-06-11  Geoff Keating  <geoffk@cygnus.com>
+
+	* sysdeps/powerpc/pspinlock.c (__pthread_spin_lock): Implement.
+	(__pthread_spin_trylock): Implement.
+	(__pthread_spin_unlock): Implement.
+	(__pthread_spin_init): Implement.
+	(__pthread_spin_destroy): Implement.
+
+2000-06-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_routines.c (list_append): Little fix to
+	really append the entry.
+
+2000-06-10  Andreas Jaeger  <aj@suse.de>
+
+	* lockfile.c (__fresetlockfiles): Remove unused variable fp.
+
+2000-06-10  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* sysdeps/pthread/timer_create.c: Thread matching now done on
+	clock type as well as thread attributes.
+	There are individual global signal-delivering threads for
+	different clock types.
+	* sysdeps/pthread/posix-timer.h: Likewise.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+
+	* sysdeps/pthread/timer_routines.c: Thread allocation and
+	deallocation function now remembers to put thread on active
+	list and remove from active list.
+	Thus now the feature of binding multiple timers
+	to a single thread actually works.
+
+2000-06-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (__pthread_create_2_1): Optimize a bit.
+
+	* internals.h (invalid_handle): Also test for p_terminated != 0.
+	(nonexisting_handle): New function.  Same as old invalid_handle.
+	* join.c (pthread_join): Use nonexisting_handle instead of
+	invalid_handle to test for acceptable thread handle.
+	* manager.c (pthread_handle_free): Likewise.
+	* joinrace.c: New file.
+	Reported by Permaine Cheung <pcheung@cygnus.com>.
+
+2000-06-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_routines.c (__timer_thread_queue_timer):
+	Correct handling of matching variable.
+
+	* sysdeps/pthread/tst-timer.c (main): Rewrite initializers to
+	avoid warnings.
+
+	* sysdeps/pthread/timer_routines.c (__timer_thread_queue_timer):
+	Be prepared for empty timer list.
+
+	* sysdeps/pthread/timer_create.c (timer_create): Correct names of
+	CPUTIME clock ID.  Add support for thread clocks.
+
+	* sysdeps/pthread/posix-timer.h (timer_ptr2id): Operands in
+	subtraction were switched.
+
+	* sysdeps/pthread/timer_routines.c (init_module): Use
+	THREAD_MAXNODES threads.
+
+	* sysdeps/pthread/posix-timer.h (struct timer_node): Add creator_pid.
+	* sysdeps/pthread/timer_create.c: Fill in creator_pid.
+	* sysdeps/pthread/timer_routines.c (thread_expire_timer): Send signal
+	with sigqueueinfo is this system call is available.
+
+	* sysdeps/pthread/timer_create.c (timer_create): Allow
+	CLOCK_CPUTIME if _POSIX_CPUTIME is defined.
+
+	* sysdeps/pthread/Makefile: New file.  Add rules to build timer
+	functionality.
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Add TIMER_MAX.
+
+2000-06-04  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* sysdeps/pthread/posix-timer.h: New file.
+	* sysdeps/pthread/timer_create.c: New file.
+	* sysdeps/pthread/timer_delete.c: New file.
+	* sysdeps/pthread/timer_getoverr.c: New file.
+	* sysdeps/pthread/timer_gettime.c: New file.
+	* sysdeps/pthread/timer_routines.c: New file.
+	* sysdeps/pthread/timer_settime.c: New file.
+	* sysdeps/pthread/tst-timer.c: New file.
+
+2000-06-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Remove OPEN_MAX and
+	LINK_MAX definitions if necessary.
+
+2000-06-04  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Added missing fork time handling of global libio lock.
+
+	* lockfile.c (__fresetlockfiles): Now also resets the list lock,
+	not just the individual stream locks. Rewritten to use new
+	iterator interface provided by libio rather than accessing
+	global variable.
+
+	* lockfile.c (__flockfilelist, _funlockfilelist): New functions
+	which lock and unlock the stream list using the new interface
+	provied by libio.
+	* internals.h: Likewise.
+
+	* ptfork.c (__fork): Now calls __flockfilelist before fork,
+	and __funlockfilelist in the parent after the fork.
+	Child still calls __fresetlockfiles as before.
+
+	* linuxthreads.texi: Now explains what happens to streams at
+	fork time. Also whole new section on forking and thread added.
+	Definition of pthread_atfork moved out of Miscellaneous Functions
+	to this new section.
+
+2000-06-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/sparc/sparc32/sparcv9/pspinlock.c (__pthread_spin_lock):
+	Add missing register.
+	* sysdeps/sparc/sparc64/pspinlock.c (__pthread_spin_lock): Likewise.
+
+2000-06-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/sparc/sparc32/pspinlock.c: Implement spinlocks.
+	* sysdeps/sparc/sparc32/sparcv9/pspinlock.c: New.
+	* sysdeps/sparc/sparc64/pspinlock.c: Implement spinlocks.
+
+2000-05-31  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/mips/pspinlock.c: Implement spinlocks.
+
+2000-05-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* spinlock.c (__pthread_lock): Remove ASSERT.
+
+	* Makefile (tests): Add ex8.
+	* Examples/ex8.c: New file.
+
+2000-05-12  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Bugfix: The pthread_atfork mechanism now takes care of its
+	own internal mutex at fork time.
+
+	* ptfork.c (__fork): Revised so that the mutex is held across
+	the fork operation and while the handlers are called, and so that
+	the child resets the mutex.
+
+	* linuxthreads.texi: Updated pthread_atfork documentation to make
+	it clear that fork and pthread_atfork can't be reentered from
+	atfork handlers, that pthread_atfork and fork are mutually atomic,
+	and that the handlers are inherited by the child process.
+
+2000-05-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (libpthread-routines): Add pspinlock.
+	* cancel.c: Rename __pthread_spin_unlock back to __pthread_unlock.
+	Use struct _pthread_fastlock instead of pthread_spinlock_t.
+	* condvar.c: Likewise.
+	* internals.h: Likewise.
+	* join.c: Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* rwlock.c: Likewise.
+	* semaphore.c: Likewise.
+	* signals.c: Likewise.
+	* spinlock.h: Likewise.
+	* spinlock.c: Likewise.  Remove pthread_spin_lock functions.
+	* sysdeps/alpha/pspinlock.c: New file.
+	* sysdeps/arm/pspinlock.c: New file.
+	* sysdeps/i386/pspinlock.c: New file.
+	* sysdeps/m68k/pspinlock.c: New file.
+	* sysdeps/mips/pspinlock.c: New file.
+	* sysdeps/powerpc/pspinlock.c: New file.
+	* sysdeps/sparc/sparc32/pspinlock.c: New file.
+	* sysdeps/sparc/sparc64/pspinlock.c: New file.
+	* sysdeps/pthread/bits/pthreadtypes.h: Remove pthread_spinlock_t
+	back to _pthread_fastlock.  Define new pthread_spinlock_t.
+
+2000-05-24  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/i386/i686/pt-machine.h: Only use LDT on newer kernels.
+
+2000-05-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* manager.c (pthread_handle_create): Initialize p_res._sock to -1.
+
+2000-05-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* internals.h (__RES_PTHREAD_INTERNAL): Define.
+
+2000-05-06  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* mutex.c (pthread_once): IN_PROGRESS state of pthread_once_t
+	object state is represented with additional bits which distinguish
+	whether that state was set up in the current process, or
+	in an ancestor process. If that state was set in an ancestor,
+	it means that a fork happened while thread was executing the init
+	function. In that case, the state is reset to NEVER.
+	* mutex.c (__pthread_once_fork_prepare): New function.
+	(__pthread_once_fork_child): Likewise
+	(__pthread_once_fork_parent): Likewise
+	(__pthread_reset_pthread_once): Removed.
+	* ptfork.c (__fork): Call new handlers in mutex.c.
+	* internals.h: Declarations of new mutex.c functions added.
+	Declaration of removed function deleted.
+	* linuxthreads.texi: Updated documentation about pthread_once
+	to clarify what happens under cancellation and forking.
+
+2000-05-06  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* internals.h: New thread manager request type, REQ_KICK.
+	* join.c (pthread_exit): main thread now calls exit() instead
+	of _exit() in order to proper process cleanup.
+	* manager.c (__pthread_manager): Do not terminate manager
+	after unblocking main thread; wait for main thread's
+	REQ_PROCESS_EXIT request instead.
+	Also, added REQ_KICK case to handle new request; this just does
+	nothing.
+	* manager.c (pthread_exited): Do not terminate manager after
+	unblocking main thread.
+	* manager.c (__pthread_manager_sighandler): If the main thread
+	is waiting for all other threads to die, send a REQ_KICK into
+	the thread manager request pipe to get it to clean out the threads
+	and unblock the main thread as soon as possible. This fixes
+	the 2000 millisecond hang on shutdown bug.
+	* Examples/ex7.c: New file, tests shutdown behavior when all threads
+	including the main one call pthread_exit(), or implicitly do so.
+	* Makefile (tests): Add ex7.
+
+2000-05-05  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/i386/getcpuclockid.c
+	(pthread_getcpuclockid): Correct test for ourselves.
+
+2000-05-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h (struct _pthread_descr_struct): Reorganization.
+	Allocate room for 16 pointers at head of the structure for future
+	thread-local data handling.  Move p_self member in this area.
+	* manager.c (pthread_handle_create): Adjust use of p_self.
+	* sysdeps/i386/useldt.h (THREAD_SELF): Likewise.
+	* pthread.c (__pthread_initial_thread): Adjust initialization.
+	(__pthread_manager_thread): Likewise.
+
+2000-04-29  Bruno Haible  <haible@clisp.cons.org>
+
+	* join.c (pthread_exit): Use THREAD_GETMEM_NC instead of THREAD_GETMEM
+	for eventmask larger than 1 word.
+
+2000-04-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* Versions [libpthread] (GLIBC_2.2): Add __pthread_initialize_minimal.
+	* pthread.c (__pthread_initialize_minimal): New function.  Perform
+	minimal initialization.
+	(pthread_initialize): Remove this code here.
+	* sysdeps/i386/i686/pt-machine.h: Include "../useldt.h" again.  We
+	are working around the problem in glibc.
+
+2000-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/i386/i686/pt-machine.h: Do not use "../useldt.h" for
+	now.  First gcc must be fixed (more concrete: libgcc).
+
+2000-04-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c: Remove special treatement for interrupt handlers on x86.
+	* manager.c (pthread_free): Use FREE_THREAD not FREE_THREAD_SELF.
+	* sysdeps/i386/useldt.h: Use "q" constraint instead of "r" where
+	necessary.
+	* sysdeps/i386/i686/pt-machine.h: Include "../useldt.h".
+
+2000-04-24  Mark Kettenis  <kettenis@gnu.org>
+
+	* join.c (pthread_exit): Set p_terminated after reporting the
+	termination event instead of before.
+
+2000-04-20  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/pthread/bits/libc-lock.h: Only declare __pthread_rwlock_*
+	if __USE_UNIX98.
+
+2000-04-18  Andreas Jaeger  <aj@suse.de>
+
+	* Versions: Use ld instead of ld.so.
+
+2000-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/bits/sigcontext.h (struct sigcontext):
+	Remove the typedef keyword.
+
+2000-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/sparc/sparc64/pt-machine.h (MEMORY_BARRIER): Use membar,
+	not stbar.
+	(READ_MEMORY_BARRIER): Define.
+	* spinlock.c (__pthread_spin_unlock): Use READ_MEMORY_BARRIER, not
+	MEMORY_BARRIER.
+	* internals.h (READ_MEMORY_BARRIER): Define if not defined in sysdep
+	headers.
+
+2000-04-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/getcpuclockid.c
+	(pthread_getcpuclockid): Don't compare thread_id with thread_self,
+	use thread_handle().
+
+2000-04-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_timedwait_relative): Don't test for owner
+	if fast mutex is used.  Don't initialize `already_canceled' twice.
+	Correctly test for return value of timedsuspend.
+
+	* pthread.c: Correct long-time braino.  We never set SA_SIGINFO and
+	therefore don't need the _rt versions of the signal handlers.
+
+2000-04-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (pthread_yield): New function.
+	* sysdeps/pthread/pthread.h (pthread_yield): Add prototype.
+	* Versions [libpthread] (GLIBC_2.2): Add pthread_yield.
+	* internals.h: Declare __pthread_yield.
+
+	* pthread.c (pthread_initialize): Avoid a bit more code if
+	realtime signals are known to exist.
+
+	* pthread.c: Is __ASSUME_REALTIME_SIGNALS then avoid generating code
+	to dynamically detect RT signals and avoid generating compatibility
+	functions with old kernel.
+	* restart.h (restart) [__ASSUME_REALTIME_SIGNALS]: Use
+	__pthread_restart_new directly.
+	(suspend) [__ASSUME_REALTIME_SIGNALS]: Use
+	__pthread_wait_for_restart_signal directly.
+	(timedsuspend) [__ASSUME_REALTIME_SIGNALS]: Use
+	__pthread_timedsuspend_new directly.
+
+2000-04-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c: Remove all the special code to handle cond_timedwait.
+	Use timedsuspend instead.
+	* internals.h: Declare __pthread_timedsuspend_old,
+	__pthread_timedsuspend_new, and __pthread_timedsuspend.
+	Remove declaration of __pthread_init_condvar.
+	* pthread.c: Define __pthread_timedsuspend variable.
+	(__pthread_timedsuspend_old): New function.  Timed suspension
+	implementation for old Linux kernels.
+	(__pthread_timedsuspend_new): New function.  Timed suspension
+	implementation for new Linux kernels.
+	* restart.h (timedsuspend): New function.  Call appropriate
+	suspension function through __pthread_timedsuspend.
+	* semaphore.c (sem_timedwait): Use timedsuspend, don't duplicate
+	the code.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+	* internals.h (WRITE_MEMORY_BARRIER): Define as MEMORY_BARRIER if
+	undefined.
+	* spinlock.c: Use WRITE_MEMORY_BARRIER instead of MEMORY_BARRIER
+	where possible.
+	* sysdeps/alpha/pt-machine.h: Define WRITE_MEMORY_BARRIER.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Add _POSIX_SPAWN.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+2000-04-14  Andreas Jaeger  <aj@suse.de>
+
+	* weaks.c: Fix typo.
+
+	* shlib-versions (mips.*-.*-linux.*): Support only GLIBC 2.0 and
+	2.2 for linuxthreads.
+
+2000-04-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/getcpuclockid.c
+	(pthread_getcpuclockid): Fix typo.
+
+2000-04-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (libpthread-routines): Add getcpuclockid.
+	* Versions [libpthread] (GLIBC_2.2): Add pthread_getcpuclockid.
+	* sysdeps/pthread/getcpuclockid.c: New file.
+	* sysdeps/unix/sysv/linux/i386/getcpuclockid.c: New file.
+	* sysdeps/pthread/pthread.h: Add prototype for pthread_getcpuclockid.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_SPIN_LOCKS):
+	Defined.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
+
+	* sysdeps/pthread/pthread.h: Add prototypes for pthread_spin_init,
+	pthread_spin_destroy, pthread_spin_lock, pthread_spin_trylock,
+	and pthread_spin_unlock.
+	* sysdeps/pthread/bits/pthreadtypes.h: Change struct _pthread_fastlock
+	into pthread_spinlock_t.  Change all uses.
+	* spinlock.c: Implement pthread_spin_lock.
+	Rename __pthread_unlock to __pthread_spin_unlock and define weak
+	alias for real name.
+	Define pthread_spin_trylock, pthread_spin_init, and
+	pthread_spin_destroy.
+	Change all uses of _pthread_fastlock to pthread_spinlock_t.
+	* spinlock.h: Rename __pthread_unlock to __pthread_spin_unlock.
+	Change all uses of _pthread_fastlock to pthread_spinlock_t.
+	* Versions [libpthread] (GLIBC_2.2): Add pthread_spin_init,
+	pthread_spin_destroy, pthread_spin_lock, pthread_spin_trylock,
+	and pthread_spin_unlock.
+	* cancel.c: Use __pthread_spin_unlock instead of __pthread_unlock.
+	Change all uses of _pthread_fastlock to pthread_spinlock_t.
+	* condvar.c: Likewise.
+	* internals.h: Likewise.
+	* join.c: Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* rwlock.c: Likewise.
+	* semaphore.c: Likewise.
+	* signals.c: Likewise.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Add various new POSIX
+	macros.
+	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: New file.
+
+2000-04-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Add
+	_POSIX_SHARED_MEMORY_OBJECTS.
+
+2000-04-11  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/mips/pt-machine.h (MEMORY_BARRIER): Define.
+	(__compare_and_swap): Mark as modifying memory.
+
+2000-04-11  Geoff Keating  <geoffk@cygnus.com>
+
+	* sysdeps/powerpc/pt-machine.h (MEMORY_BARRIER): Don't be
+	__volatile__.
+	(__compare_and_swap): Replace other 'sync' with MEMORY_BARRIER.
+	Don't have the 'asm' __volatile__.
+
+2000-04-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* internals.h: Define MEMORY_BARRIER as empty if not defined already.
+	* spinlock.c (__pthread_lock): Add memory barriers.
+	(__pthread_unlock): Likewise.
+	* sysdeps/alpha/pt-machine.h (MEMORY_BARRIER): Define using mb
+	instruction.
+	(RELEASE): Not needed anymore.
+	(__compare_and_swap): Mark asm as modifying memory.
+	* sysdeps/powerpc/pt-machine.h (sync): Remove.  Replace with definition
+	of MEMORY_BARRIER.
+	(__compare_and_swap): Use MEMORY_BARRIER instead of sync.
+	* sysdeps/sparc/sparc32/pt-machine.h (RELEASE): Not needed anymore.
+	(MEMORY_BARRIER): Define using stbar.
+	* sysdeps/sparc/sparc64/pt-machine.h (MEMORY_BARRIER): Define using
+	stbar.
+	(__compare_and_swap): Use MEMORY_BARRIER to ensure ordering.
+	Patch by Xavier Leroy <Xavier.Leroy@inria.fr> based on comments by
+	Mike Burrows <m3b@pa.dec.com>.
+
+2000-04-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* signals.c (sigaction): Fix return value for the case SIG is one
+	of the signals the implementation uses.
+	Patch by Xavier.Leroy@inria.fr.
+
+2000-04-01  Andreas Jaeger  <aj@suse.de>
+
+	* attr.c: Use shlib-compat macros.
+	* oldsemaphore.c: Likewise.
+	* pthread.c: Likewise.
+	* weaks.c: Likewise.
+
+2000-03-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* semaphore.c (sem_timedwait): New function.
+	Patch by Carl Mailloux <carlm@oricom.ca>.
+	* semaphore.h: Declare sem_timedwait.
+	* Versions [libpthread] (GLIBC_2.2): Add sem_timedwait.
+
+2000-03-26  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* sysdeps/pthread/Makefile: File removed.
+
+2000-03-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* mutex.c (__pthread_reset_pthread_once): Reset once_masterlock.
+	* internals.h (__pthread_reset_pthread_once): Add prototype.
+	* ptfork.c (__fork): Call __pthread_reset_pthread_once.
+
+	* manager.c (pthread_handle_create): Store ID of new thread before
+	clone call.
+
+2000-03-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* attr.c: Use new macros from shlib-compat.h to define versions.
+	* oldsemaphore.c: Likewise.
+	* semaphore.c: Likewise.
+	* weaks.c: Likewise.
+
+	* pthread.c: Update for new SHLIB_COMPAT definition.
+
+	* manager.c (__pthread_manager): Unmask debug signal.
+
+	* pthread.c (pthread_initialize): Test for address of __dso_handle
+	being NULL, not value.  Use __on_exit, not on_exit.
+	Patch by Andreas Jaeger <aj@suse.de>.
+
+	* pthread.c: Use new macros from shlib-compat.h to define versions.
+
+2000-03-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread.c (pthread_initialize): Instead of on_exit use
+	__cxa_atexit if __dso_label is available to allow unloading the
+	libpthread shared library.
+
+2000-03-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c: Make tests for ownership of mutex less strict.
+
+2000-03-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_wait): Check whether mutex is owned by
+	current thread and return error if not.
+	(pthread_cond_timedwait_relative_old): Likewise.
+	(pthread_cond_timedwait_relative_new): Likewise.
+
+	* mutex.c (__pthread_once): Handle cancelled init function correctly.
+	(pthread_once_cancelhandler): New function.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-03-14  Andreas Jaeger  <aj@suse.de>
+
+	* pthread.c (pthread_handle_sigcancel_rt): GS has been renamed to
+	REG_GS.
+	(pthread_handle_sigrestart_rt): Likewise.
+	* signals.c (pthread_sighandler_rt): Likewise.
+
+2000-03-02  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/bits/libc-lock.h: Fix typo.
+	Reported by Sean Chen <sean.chen@turbolinux.com>.
+
+2000-02-28  Andreas Jaeger  <aj@suse.de>
+
+	* rwlock.c: Fix typo.
+
+2000-02-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* rwlock.c: Define __* variants of the functions and make old names
+	aliases.
+	* Versions [GLIBC_2.2]: Export the __pthread_rwlock_* functions.
+	* sysdeps/pthread/bits/libc-lock.h: Define __libc_rwlock_* macros.
+
+2000-02-25  Andreas Jaeger  <aj@suse.de>
+
+	* Versions: Export pread, __pread64, pread64, pwrite, __pwrite64,
+	pwrite64, lseek64, open64, and __open64 with version 2.2.
+
+2000-02-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* semaphore.h (SEM_FAILED): Use 0 not NULL.
+
+2000-02-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_timedwait_relative_old): Tight loop with
+	nanosleep does not work either.  Get absolute time inside the
+	loop.
+	(pthread_cond_timedwait_relative_new): Likewise.
+	Patch by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-02-13  Andreas Jaeger  <aj@suse.de>
+
+	* condvar.c (pthread_cond_timedwait_relative_new): Fix last patch.
+	(pthread_cond_timedwait_relative_old): Likewise.
+
+2000-02-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_timedwait_relative_old): Undo last patch
+	but keep the code around.  A bug in the kernel prevent us from
+	using the code.
+	(pthread_cond_timedwait_relative_new): Likewise.
+	(PR libc/1597 and libc/1598).
+
+2000-02-01  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	* condvar.c (pthread_cond_timedwait_relative_old): Do tight
+	loop around nanosleep calls instead of around most of the function
+	(pthread_cond_timedwait_relative_new): Likewise.
+	body.  Got rid of backwards goto and one local.
+
+2000-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_timedwait_relative_old): Recompute time
+	before every nanosleep call to account for time spent in the rest
+	of the function.
+	(pthread_cond_timedwait_relative_new): Likewise.
+	Patch by khendricks@ivey.uwo.ca (PR libc/1564).
+
+2000-01-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* condvar.c (pthread_cond_timedwait_relative_old): Get remaining time
+	from nanosleep call so that in case we restart we only wait for the
+	remaining time.
+	(pthread_cond_timedwait_relative_new): Likewise.
+	Patch by khendricks@ivey.uwo.ca (PR libc/1561).
+
+2000-01-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_allocate_stack): Compute guard page address
+	correctly.  Patch by HJ Lu.
+
+	* sysdeps/pthread/pthread.h: Define
+	PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP.
+
+2000-01-16  Ulrich Drepper  <drepper@cygnus.com>
+
+	* rwlock.c (pthread_rwlock_unlock): Correct one more problem with
+	preference handling.
+	(pthread_rwlockattr_setkind_np): Allow
+	PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP.
+	Patches by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-01-12  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h (pthread_readlock_info): New structure.
+	(_pthread_descr_struct): Add p_readlock_list, p_readlock_free, and
+	p_untracked_readlock_count.
+	* pthread.c (__pthread_initial_thread, pthread_manager_thread):
+	Add initializers for new fields.
+	* manager.c (pthread_free): Free read/write lock lists.
+	* queue.h (queue_is_empty): New function.
+	* rwlock.c: Implement requirements about when readers should get
+	locks assigned.
+	* sysdeps/pthread/pthread.h
+	(PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP): New definition.
+	* sysdeps/pthread/bits/pthreadtypes.h (struct _pthread_rwlock_t):
+	Define this name as well.
+	Patches by Kaz Kylheku <kaz@ashi.footprints.net>.
+
+2000-01-05  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_initial_thread, pthread_manager_thread):
+	Adjust initializers for struct _pthread_descr_struct change.
+	* internals.h (struct _pthread_descr_struct): Move new elements to
+	the end.
+
+2000-01-03  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Redesigned how cancellation unblocks a thread from internal
+	cancellation points (sem_wait, pthread_join,
+	pthread_cond_{wait,timedwait}).
+	Cancellation won't eat a signal in any of these functions
+	(*required* by POSIX and Single Unix Spec!).
+	* condvar.c: Spontaneous wakeup on pthread_cond_timedwait won't eat a
+	simultaneous condition variable signal (not required by POSIX
+	or Single Unix Spec, but nice).
+	* spinlock.c: __pthread_lock queues back any received restarts
+	that don't belong to it instead of assuming ownership of lock
+	upon any restart; fastlock can no longer be acquired by two threads
+	simultaneously.
+	* restart.h: Restarts queue even on kernels that don't have
+	queued real time signals (2.0, early 2.1), thanks to atomic counter,
+	avoiding a rare race condition in pthread_cond_timedwait.
+
+1999-12-31  Andreas Jaeger  <aj@suse.de>
+
+	* internals.h: Remove duplicate prototype declarations.
+
+	* weaks.c: Remove __THROW from prototypes since the file is not
+	compiled by a C++ compiler.
+	* internals.h: Likewise.
+
+1999-12-30  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/pthread.h: Move internal functions to...
+	* sysdeps/pthread/bits/libc-lock.h: ...here.
+
+1999-12-29  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/pthread/pthread.h: Fix typos, reformat comments.
+
+1999-12-28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/alpha/pt-machine.h: Move stack_pointer definition to the
+	beginning.
+
+	* manager.c (__pthread_start): Add one more cast to prevent
+	warning on 64bit machines.
+
+1999-12-21  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_handle_create): Set p_pid of new thread
+	before calling the callback function to report a new thread.
+
+1999-12-20  Andreas Jaeger  <aj@suse.de>
+
+	* pthread.c (pthread_initialize): Move getrlimit call after
+	setting of errno.
+
+1999-12-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Versions: Export pread, __pread64, pread64, pwrite, __pwrite64,
+	pwrite64, lseek64, open64, and __open64.
+	* wrapsyscall.c: Define pread, __pread64, pread64, pwrite, __pwrite64,
+	pwrite64, lseek64, open64, and __open64.
+
+	* manager.c (pthread_allocate_stack): Correct computation of
+	new_thread_bottom.  Correct handling of stack size and when the
+	rlimit method to guard for stack growth is used.
+	* pthread.c (pthread_initialize): Stack limit must be STACK_SIZE
+	minus one pagesize (not two).
+
+1999-12-03  Andreas Jaeger  <aj@suse.de>
+
+	* Versions: Add __res_state with version GLIBC_2.2.
+
+	* errno.c (__res_state): New function to return thread specific
+	resolver state.
+
+	* pthread.c (pthread_initialize): Initialize p_resp.
+	(__pthread_reset_main_thread): Also set p_resp.
+
+	* manager.c (pthread_handle_create): Initialize p_resp.
+
+	* internals.h: Add thread specific resolver state.
+	Based on patches by Adam D. Bradley <artdodge@cs.bu.edu>.
+
+1999-12-01  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/i386/pt-machine.h: Move stack_pointer definition to the
+	beginning.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	Patches by Alan Modra <alan@SPRI.Levels.UniSA.Edu.Au>.
+
+1999-11-23  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_start_thread_event): Initialize p_pid already
+	here.
+
+1999-11-22  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h: Add prototype for __pthread_manager_event.
+	* manager.c (__pthread_manager_event): New function.
+	(pthread_start_thread_event): Correct computation of self.
+	Use INIT_THREAD_SELF.
+	* pthread.c (__pthread_manager_thread): Initialize p_lock.
+	(__pthread_initialize_manager): Respect event flags also for creation
+	of the manager thread.
+
+1999-11-08  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_initialize_manager): Initialize
+	__pthread_manager_thread.p_tid.
+
+1999-11-02  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h: Declare __pthread_last_event.
+	* manager.c: Define __pthread_last_event.
+	(pthread_handle_create): Set __pthread_last_event.
+	(pthread_exited): Likewise.
+	* join.c (pthread_exit): Likewise.
+
+	* Makefile (libpthread-routines): Add events.
+	* events.c: New file.
+	* internals.h: Protect against multiple inclusion.
+	Include thread_dbP.h header.
+	(struct _pthread_descr_struct): Add new fields p_report_events and
+	p_eventbuf.
+	Declare event reporting functions.
+	* join.c (pthread_exit): Signal event if this is wanted.
+	* manager.c (__pthread_threads_events): New variable.
+	(pthread_handle_create): Take new parameters with event information.
+	Signal TD_CREATE event if wanted.
+	(__pthread_manager): Adjust pthread_handle_create call.
+	(pthread_start_thread_event): New function.  Block until manager is
+	finished and then call pthread_start_thread.
+	(pthread_exited): Signal TD_REAP event if wanted.
+
+1999-10-26  Ulrich Drepper  <drepper@cygnus.com>
+
+	* restart.h (suspend_with_cancellation): Rewrite as a macro.
+
+	* condvar.c (pthread_cond_timedwait_relative): Don't mark as inline.
+
+1999-10-25  Andreas Jaeger  <aj@suse.de>
+
+	* internals.h: Remove K&R compatibility.
+	* no-tsd.c: Likewise.
+	* semaphore.h: Likewise.
+	* signals.c: Likewise.
+	* sysdeps/pthread/bits/libc-tsd.h: Likewise.
+	* sysdeps/unix/sysv/linux/bits/sigthread.h: Likewise.
+	* weaks.c: Likewise.
+
+1999-10-21  Xavier Leroy  <Xavier.Leroy@inria.fr>
+
+	* pthread.c: For i386, wrap pthread_handle_sigrestart and
+	pthread_handle_sigcancel with functions that restore %gs from the
+	signal context.  For each signal handling function, two wrappers
+	are required, one for a non-RT signal and one for a RT signal.
+	* signal.c: For i386, add code to restore %gs from the signal
+	context in pthread_sighandler and pthread_sighandler_rt.
+
+1999-10-17  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h (PTHREAD_START_ARGS_INITIALIZER): Add cast.
+
+1999-10-14  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_initial_thread): Pass argument to
+	PTHREAD_START_ARGS_INITIALIZER.
+	(__pthread_manager_thread): Likewise.
+
+	* internals.h (PTHREAD_START_ARGS_INITIALIZER): Add parameter to
+	initialize function.
+
+	* manager.c (pthread_handle_create): Remove p_startfct initialization.
+
+	* internals.h (_pthread_descr_struct): We don't need p_startfct field.
+
+1999-10-12  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h: Correct return types for __libc_read and __libc_write.
+
+1999-10-09  Andreas Jaeger  <aj@suse.de>
+
+	* internals.h: Add __new_sem_post to get prototype in
+	manager.c; include semaphore.h for needed types.
+
+1999-10-08  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (__pthread_manager) [REQ_POST]: Use __new_sem_post
+	directly instead of calling sem_post which should not be necessary
+	but is faster and might help in some case to work around problems.
+	Patch by khendricks@ivey.uwo.ca [libc/1382].
+
+1999-10-08  Andreas Schwab  <schwab@suse.de>
+
+	* sysdeps/pthread/Subdirs: New file.
+	* Implies: Removed.
+
+1999-10-07  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Implies: New file.
+	* internals.h (struct _pthread_descr_struct): Add p_startfct.
+	* manager.c (pthread_handle_create): Initialize p_startfct.
+	* pthread.c: Define __linuxthread_pthread_sizeof_descr variable.
+
+1999-09-25  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (__linuxthreads_pthread_threads_max): New variable.
+	* specific.c (__linuxthreads_pthread_keys_max): New variable.
+	(__linuxthreads_pthread_key_2ndlevel_size): New variable.
+
+	* condvar.c (pthread_cond_timedwait_relative): Never return with
+	EINTR.  Patch by Andreas Schwab.
+
+1999-09-19  Ulrich Drepper  <drepper@cygnus.com>
+
+	* signals.c (sigaction): Correct last patch.  Don't select
+	pthread_sighandler_rt based on the signal number but instead of
+	the SA_SIGINFO flag.
+
+1999-09-23  Ulrich Drepper  <drepper@cygnus.com>
+
+	* specific.c: Move definitions of struct pthread_key_struct and
+	destr_function to ...
+	* internals.h: ...here.
+
+1999-09-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (pthread_handle_sigrestart_rt): New function.  Use
+	this instead of pthread_handle_sigrestart if the signal is an RT
+	signal.
+
+	* signals.c: Handle passing through of sighandler arguments also
+	for real-time signals.
+
+1999-09-03  Andreas Schwab  <schwab@suse.de>
+
+	* ptfork.c (__fork): Renamed from fork and use __libc_fork.  Add
+	fork as weak alias.
+	(__vfork): New function, alias vfork.
+	* Versions: Export __fork, vfork, and __vfork in libpthread.
+
+1999-08-23  Andreas Schwab  <schwab@suse.de>
+
+	* signals.c (pthread_sighandler): Add SIGCONTEXT_EXTRA_ARGS to
+	call to signal handler.
+
+1999-08-20  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_reset_main_thread): Undo last change.
+	(__pthread_kill_other_threads_np): Reset signal handlers for the
+	signals we used in the thread implementation here.
+
+1999-08-19  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_reset_main_thread): Reset signal handlers
+	for the signals we used in the thread implementation [PR libc/1234].
+
+	* Versions: Export __pthread_kill_other_threads_np from libpthread
+	for GLIBC_2.1.2.
+
+	* signals.c: Pass sigcontext through wrapper to the user function.
+
+1999-08-01  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Versions [ld.so] (GLIBC_2.0): Export __libc_internal_tsd_get and
+	__libc_internal_tsd_set.
+
+1999-07-29  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* manager.c: Remove inclusion of <linux/tasks.h> since it's not
+	needed anymore.
+
+1999-07-16  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* internals.h: Align _pthread_descr_struct to 32 bytes.
+	Reported by Tim Hockin <thockin@cobaltnet.com>, close PR
+	libc/1206.
+
+1999-07-09  Ulrich Drepper  <drepper@cygnus.com>
+
+	* oldsemaphore.c (sem_compare_and_swap): Fix use of compare and
+	swap function.
+
+1999-07-09  Cristian Gafton  <gafton@redhat.com>
+
+	* Makefile (libpthread-routines): Add oldsemaphore routine.
+	* Versions: Add sem_destroy, sem_getvalue, sem_init, sem_post,
+	sem_trywait, and sem_wait to GLIBC_2.1.
+	* oldsemaphore.c: New file.
+	* semaphore.c: Add default_symbol_versions for the changed functions.
+	(__new_sem_init): Rename from sem_init.
+	(__new_sem_post): Rename from sem_post.
+	(__new_sem_wait): Rename from sem_wait.
+	(__new_sem_trywait): Rename from sem_trywait.
+	(__new_sem_getvalue): Rename from sem_getvalue.
+	(__new_sem_destroy): Rename from sem_destroy.
+
+1999-06-23  Robey Pointer  <robey@netscape.com>
+
+	* internals.h: Added p_nextlock entry to separate queueing for a
+	lock from queueing for a CV (sometimes a thread queues on a lock
+	to serialize removing itself from a CV queue).
+	* pthread.c: Added p_nextlock to initializers.
+	* spinlock.c: Changed to use p_nextlock instead of p_nextwaiting.
+
+1999-07-09  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_handle_create): Free mmap region after stack
+	if clone failed.  Patch by Kaz Kylheku <kaz@ashi.FootPrints.net>.
+
+1999-05-23  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* man/pthread_cond_init.man: Correct example.
+	Reported by Tomas Berndtsson <tomas@nocrew.org>.
+
+	* linuxthreads.texi (Condition Variables): Likewise.
+
+1999-05-18  Jakub Jelinek  <jj@ultra.linux.cz>
+
+	* sysdeps/sparc/sparc64/pt-machine.h (__compare_and_swap): Use
+	casx not cas, also successful casx returns the old value in rd
+	and not the new value.
+
+1999-05-16  Xavier Leroy  <Xavier.Leroy@inria.fr>
+
+	* manager.c: If pthread_create() is given a NULL attribute
+	and the thread manager runs with a realtime policy, set the
+	scheduling policy of the newly created thread back to SCHED_OTHER.
+	* manager.c: If the PTHREAD_INHERIT_SCHED attribute is given,
+	initialize the schedpolicy field of new_thread->p_start_args
+	to that of the calling thread.
+
+1999-04-29  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/sparc/sparc64/pt-machine.h (__compare_and_swap): cas
+	instruction does not allow memory element to use offset.
+
+1999-04-28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_allocate_stack): Optimize initialization of new
+	thread descriptor.
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_define_initialized):
+	Don't use initializer since it is all zeroes.
+	(__libc_once_define): Likewise.
+
+1999-04-16  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* sysdeps/arm/Implies: Removed since cmpxchg/no-cmpxchg
+	doesn't exist anymore.
+	* sysdeps/i386/Implies: Likewise.
+	* sysdeps/m68k/Implies: Likewise.
+	* sysdeps/mips/Implies: Likewise.
+	* sysdeps/powerpc/Implies: Likewise.
+	* sysdeps/sparc/sparc32/Implies: Likewise.
+	* sysdeps/sparc/sparc64/Implies: Likewise.
+
+1999-04-15  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/alpha/bits/semaphore.h: Removed.
+	* sysdeps/powerpc/bits/semaphore.h: Removed.
+	* sysdeps/pthread/cmpxchg/bits/semaphore.h: Removed.
+	* sysdeps/pthread/no-cmpxchg/bits/semaphore.h: Removed.
+	* Makefile (headers): Remove bits/semaphore.h.
+
+	* semaphore.h: Define _pthread_descr if necessary.
+	Don't include limits.h.  Define SEM_VALUE_MAX directly.
+	Define SEM_FAILED.
+	(sem_t): Protect element names with leading __.
+	Add declarations for sem_close, sem_open, and sem_unlink.
+	* semaphore.c: Adjust all functions for new element names.
+	Define sem_close, sem_open, and sem_unlink.
+	* Versions (libthread): Add sem_close, sem_open, and sem_unlink for
+	GLIBC_2.1.1.
+	* sysdeps/pthread/bits/pthreadtypes.h: Define _pthread_descr only if
+	necessary.
+
+1999-03-16  H.J. Lu  <hjl@gnu.org>
+
+	* specific.c (pthread_key_delete): Check th->p_terminated to see
+	if the thread is running.
+
+	* Versions (__libc_internal_tsd_get, __libc_internal_tsd_set):
+	Added to GLIBC_2.0 for libc.so.
+
+1999-02-12  H.J. Lu  <hjl@gnu.org>
+
+	* Versions (__libc_current_sigrtmin, __libc_current_sigrtmax,
+	__libc_allocate_rtsig): Added to GLIBC_2.1.
+
+	* internals.h (DEFAULT_SIG_RESTART): Removed.
+	(DEFAULT_SIG_CANCEL): Removed.
+
+	* pthread.c (init_rtsigs, __libc_current_sigrtmin,
+	__libc_current_sigrtmax, __libc_allocate_rtsig): New functions.
+	(__pthread_sig_restart, __pthread_sig_cancel,
+	__pthread_sig_debug): Initialized.
+	(pthread_initialize): Call init_rtsigs () to initialize
+	real-time signals.
+
+1999-02-03  H.J. Lu  <hjl@gnu.org>
+
+	* manager.c (__pthread_manager): Do block __pthread_sig_debug.
+	Don't restart the thread which sent REQ_DEBUG.
+	(pthread_start_thread): Check if __pthread_sig_debug > 0
+	before debugging.
+
+	* pthread.c (__pthread_initialize_manager): Suspend ourself
+	after sending __pthread_sig_debug to gdb instead of
+	__pthread_sig_cancel.
+
+1999-01-24  H.J. Lu  <hjl@gnu.org>
+
+	* manager.c (__pthread_manager): Delete __pthread_sig_debug
+	from mask if __pthread_sig_debug > 0.
+	(pthread_handle_create): Increment __pthread_handles_num.
+
+	* manager.c (pthread_handle_create): Don't pass CLONE_PTRACE to clone.
+	* pthread.c (__pthread_initialize_manager): Likewise.
+
+	* pthread.c (pthread_initialize): Use __libc_allocate_rtsig (1)
+	instead of __libc_allocate_rtsig (2).
+	(__pthread_initialize_manager): Send __pthread_sig_debug to gdb
+	instead of __pthread_sig_cancel.
+	(pthread_handle_sigdebug): Fix comments.
+
+1999-01-21  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_allocate_stack): Set
+	__pthread_nonstandard_stacks if user-specified stack is used.
+
+1999-01-16  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Add _LFS_ASYNCHRONOUS_IO,
+	_LFS_LARGEFILE, _LFS64_LARGEFILE, and _LFS64_STDIO from Unix98.
+
+1999-01-07  Xavier Leroy  <Xavier.Leroy@inria.fr>
+
+	* pthread.c: Use a third signal __pthread_sig_debug distinct
+	from __pthread_sig_cancel to notify gdb when a thread is
+	created
+	* manager.c: Likewise.
+	* internals.h: Likewise.
+	* signals.c: The implementation of sigwait(s) assumed that
+	all signals in s have signal handlers already attached.
+	This is not required by the standard, so make it work
+	also if some of the signals have no handlers.
+
+1999-01-05  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+	* linuxthreads.texi: Remove pointers from first @node.  Move old
+	@node spec inside comment.
+
+1998-12-31  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/bits/stdio-lock.h: Define _IO_lock_lock and
+	_IO_lock_unlock.
+
+1998-12-29  Ulrich Drepper  <drepper@cygnus.com>
+
+	* semaphore.c (sem_trywait): Don't forget to unlock the semaphore
+	lock.  Patch by Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>.
+
+1998-12-21  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c: Threads now send __pthread_sig_cancel on termination.
+	Change clone call and signal masks.
+	* thread.c (pthread_handle_sigrestart): Remove special code for
+	manager.
+	(pthread_handle_sigcancel): In manager thread call
+	__pthread_manager_sighandler.
+	* sysdeps/i386/pt-machine.h (__compare_and_swap): Add memory clobber.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	Patches by Xavier Leroy.
+
+1998-12-14  Ulrich Drepper  <drepper@cygnus.com>
+
+	* spinlock.c (__pthread_unlock): Don't crash if called for an
+	untaken mutex.  Reported by Ruslan V. Brushkoff <rus@Snif.Te.Net.UA>.
+
+	* Examples/ex6.c: Unbuffer stdout and reduce sleep time to reduce
+	overall runtime.
+
+1998-12-13  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Examples/ex3.c: Wait until all threads are started before
+	searching for the number to avoid race condition on very fast
+	systems.
+
+1998-12-08  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* sysdeps/pthread/pthread.h: Remove __pthread_setcanceltype
+	declaration since it's not needed.
+
+	* sysdeps/pthread/pthread.h: Move internal functions to ...
+	* internals.h: ...here.
+
+1998-12-02  H.J. Lu  <hjl@gnu.org>
+
+	* pthread.c (__pthread_sig_restart): Initiliaze to 0 if
+	SIGRTMIN is defined.
+	(__pthread_sig_cancel): Likewise.
+
+1998-12-01  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* wrapsyscall.c: Include <sys/mman.h> for msync,
+	<stdlib.h> for system and <termios.h> for tcdrain prototype.
+	Correct msync declaration.
+
+1998-11-29  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* sysdeps/pthread/bits/libc-tsd.h (__libc_tsd_define, __libc_tsd_get,
+	__libc_tsd_set): New macros for new interface.
+	* no-tsd.c: New file, provide uninitialized defns of
+	__libc_internal_tsd_get and __libc_internal_tsd_set.
+	* Makefile (routines): Add no-tsd.
+
+1998-10-12  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* internals.h: Include <bits/libc-tsd.h>, not <bits/libc-lock.h>.
+	* sysdeps/pthread/bits/libc-lock.h (__libc_internal_tsd_get,
+	__libc_internal_tsd_set): Move decls to ...
+	* sysdeps/pthread/bits/libc-tsd.h: New file for __libc_internal_tsd_*
+	declarations.
+
+	* sysdeps/pthread/bits/libc-lock.h (__libc_internal_tsd_get,
+	__libc_internal_tsd_set): Make these pointers to functions, not
+	functions; remove #pragma weak decls for them.
+	* specific.c (__libc_internal_tsd_get, __libc_internal_tsd_set):
+	Define static functions and initialized pointers to them.
+
+1998-11-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Makefile (CFLAGS-mutex.c): Define as -D__NO_WEAK_PTHREAD_ALIASES.
+	(CFLAGS-specific.c): Likewise.
+	(CFLAGS-pthread.c): Likewise.
+	(CFLAGS-ptfork.c): Likewise.
+	(CFLAGS-cancel.c): Likewise.
+	* sysdeps/pthread/bits/libc-lock.h: Don't mark __pthread_* functions
+	as weak references if __NO_WEAK_PTHREAD_ALIASES is defined.
+
+	* mutex.c (pthread_mutex_init): Define as strong symbol.
+	(pthread_mutex_destroy): Likewise.
+	(pthread_mutex_trylock): Likewise.
+	(pthread_mutex_lock): Likewise.
+	(pthread_mutex_unlock): Likewise.
+	(pthread_mutexattr_init): Likewise.
+	(pthread_mutexattr_destroy): Likewise.
+	(pthread_once): Likewise.
+	* ptfork.c (pthread_atfork): Likewise.
+	* specific.c (pthread_key_create): Likewise.
+	(pthread_setspecific): Likewise.
+	(pthread_getspecific): Likewise.
+
+1998-11-15  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+	* linuxthreads.texi: Fix punctuation after xref.
+
+1998-11-10  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine NR_OPEN
+	if it is defined in <linux/limits.h>.
+
+1998-10-29 14:28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* spinlock.h (__pthread_trylock): Define inline.
+	(__pthread_lock): Add extra parameter to declaration.  Declare
+	using internal_function.
+	(__pthread_unlock): Declare using internal_function.
+	* spinlock.c (__pthread_lock): Add new parameter.  Use it instead
+	of local variable self.  Avoid recomputing self.  Define using
+	internal_function.
+	(__pthread_trylock): Remove.
+	(__pthread_unlock): Define using internal_function.
+	* cancel.c: Adjust for __pthread_lock interface change.  Use already
+	computed self value is possible.
+	* condvar.c: Likewise.
+	* join.c: Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* rwlock.c: Likewise.
+	* semaphore.c: Likewise.
+	* signals.c: Likewise.
+
+1998-10-27 13:46  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/pthread.h (struct _pthread_cleanup_buffer): Prepend
+	__ to field names of the struct.
+	* sysdeps/pthread/bits/pthreadtypes.h (struct _pthread_fastlock):
+	Likewise.
+	(pthread_attr_t): Likewise.
+	(pthread_cond_t): Likewise.
+	(pthread_condattr_t): Likewise.
+	(pthread_mutex_t): Likewise.
+	(pthread_mutexattr_t): Likewise.
+	(pthread_rwlock_t): Likewise.
+	(pthread_rwlockattr_t): Likewise.
+	* attr.c: Adjust for pthread.h and pthreadtypes.h change.
+	* cancel.c: Likewise.
+	* condvar.c: Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* ptlongjmp.c: Likewise.
+	* rwlock.c: Likewise.
+	* spinlock.c: Likewise.
+
+1998-10-09  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/i386/pt-machine.h (get_eflags, set_eflags): Mark these
+	also with PT_EI.
+
+	* sysdeps/i386/i686/pt-machine.h: Remove unused inline
+	definitions.
+
+	* Makefile (libpthread-routines): Add pt-machine.
+	* pt-machine.c: New file.
+	* sysdeps/alpha/pt-machine.h: Define PT_EI as extern inline is not
+	yet defined.  Use PT_EI in extern inline definitions.
+	* sysdeps/arm/pt-machine.h: Likewise.
+	* sysdeps/i386/pt-machine.h: Likewise.
+	* sysdeps/i386/i686/pt-machine.h: Likewise.
+	* sysdeps/m68k/pt-machine.h: Likewise.
+	* sysdeps/mips/pt-machine.h: Likewise.
+	* sysdeps/powerpc/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc32/pt-machine.h: Likewise.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+1998-10-02  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* semaphore.h: Include <sys/types.h> so that _pthread_descr
+	is declared.
+
+1998-09-15  David S. Miller  <davem@pierdol.cobaltmicro.com>
+
+	* sysdeps/sparc/sparc32/pt-machine.h (INIT_THREAD_SELF): Add nr
+	argument.
+	* sysdeps/sparc/sparc64/pt-machine.h (INIT_THREAD_SELF): Likewise.
+
+1998-09-12 14:24 -0400  Zack Weinberg  <zack@rabi.phys.columbia.edu>
+
+	* sysdeps/unix/sysv/linux/bits/sigthread.h: Add multiple inclusion
+	guard.
+
+1998-09-02 11:08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* signals.c (sigaction): Check that sig is less than NSIG to avoid
+	array index overflow.
+
+1998-09-06 10:56  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/semaphore.h: New file.
+
+1998-09-06 09:08  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/bits/libc-lock.h (enum __libc_tsd_key_t): Add
+	_LIBC_TSD_KEY_DL_ERROR.
+
+1998-08-31  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/i386/i686/pt-machine.h (testandset): Add memory clobber.
+	* sysdeps/i386/pt-machine.h: Likewise.
+	Suggested by Roland McGrath.
+
+1998-08-28 13:58  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h: Also define THREAD_GETMEM_NC and THREAD_SETMEM_NC to
+	access thread data with non-constant offsets.
+	* specific.c: Use THREAD_GETMEM_NC and THREAD_SETMEM_NC where
+	necessary.
+
+	* sysdeps/i386/useldt.h: Fix typo.  Add THREAD_GETMEM_NC and
+	THREAD_SETMEM_NC definitions.
+
+	* sysdeps/sparc/sparc32/pt-machine.h: Define THREAD_GETMEM_NC and
+	THREAD_SETMEM_NC.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+1998-08-26 15:46  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h: Define THREAD_GETMEM and THREAD_SETMEM to default if
+	not already defined.
+	(struct _pthread_descr_struct): Add p_self and p_nr field.
+	* manager.c (__pthread_handles): Define second element to point
+	to manager thread.
+	(__pthread_handles_num): Initialize to 2.
+	(__pthread_manager): Use INIT_THREAD_SELF with two arguments.
+	(pthread_start_thread): Likewise.
+	(pthread_handle_create): Start search for free slot at entry 2.
+	Initialize new fields p_self and p_nr.
+	Call __clone with CLONE_PTRACE if available.
+	(pthread_free): Call FREE_THREAD_SELF if available.
+	* pthread.c (__pthread_initial_thread): Initialize new fields.
+	(__pthread_manager_thread): Likewise.
+	(__pthread_initialize_manager): Call __clone with CLONE_PTRACE.
+
+	* cancel.c: Use THREAD_GETMEM and THREAD_SETMEM to access the
+	elements of the thread descriptor.
+	* condvar.c: Likewise.
+	* errno.c: Likewise.
+	* join.c: Likewise.
+	* manager.c: Likewise.
+	* pthread.c: Likewise.
+	* ptlongjmp.c: Likewise.
+	* semaphore.c: Likewise.
+	* signals.c: Likewise.
+	* specific.c: Likewise.
+	* spinlock.c: Likewise.
+
+	* sysdeps/alpha/pt-machine.h (INIT_THREAD_SELF): Add extra parameter.
+
+	* sysdeps/i386/useldt.h: New file.
+	* sysdeps/i386/i686/pt-machine.h: Show how to use this file.
+
+	* sysdeps/sparc/sparc32/pt-machine.h: Define THREAD_GETMEM and
+	THREAD_SETMEM using __thread_self.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+1998-08-24  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* spinlock.c (__pthread_lock): Reset p_nextwaiting to NULL if it
+	turned out that we didn't need to queue after all.
+
+1998-08-22  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* sysdeps/powerpc/pt-machine.h: Remove testandset, it's not used
+	and wastes space; correct types.
+
+1998-08-08 11:18  H.J. Lu  <hjl@gnu.org>
+
+	* signals.c (sigaction): Handle NULL argument.
+
+1998-08-04  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/bits/sigthread.h: Use __sigset_t instead
+	of sigset_t.
+
+1998-08-02  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* Makefile (linuxthreads-version): Extract correct number from
+	Banner.
+
+1998-07-29  Xavier Leroy  <Xavier.Leroy@inria.fr>
+
+	* Banner: Bump version number to 0.8
+	* FAQ.html: Many updates, in particular w.r.t. debugging.
+	* manager.c: Support for non-default stacksize for
+	LinuxThreads-allocated stacks;
+	don't use guard pages for stacks with default size, rely on
+	rlimit(RLIMIT_STACK) instead (it's cheaper).
+	* attr.c: Likewise.
+	* cancel.c: Use __pthread_sig_cancel and __pthread_sig_restart
+	everywhere instead of PTHREAD_SIG_CANCEL and PTHREAD_SIG_RESTART.
+	* condvar.c: Likewise.
+	* internals.h: Likewise.
+	* restart.h: Likewise.
+	* signals.c: Likewise.
+	* pthread.c: Likewise; set rlimit(RLIMIT_STACK) as we need it.
+
+1998-07-23  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* weaks.c: Define pthread_mutexattr_[sg]ettype instead of
+	__pthread_mutexattr_[sg]ettype.  Add more weak aliases.
+	* Versions: Put __pthread_mutexattr_settype under version
+	GLIBC_2.0.  Don't export __pthread_mutexattr_setkind_np and
+	__pthread_mutexattr_gettype.
+
+1998-07-23  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* sysdeps/pthread/bits/libc-lock.h: Make
+	__pthread_mutexattr_settype weak.  Don't make
+	__pthread_mutexattr_setkind_np weak.
+
+1998-07-16 10:52  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_handle_create): Check whether sched_setscheduler
+	call can succeed here.
+
+	* mutex.c: Define __pthread_mutexattr_settype and make
+	__pthread_mutexattr_setkind_np an alias.
+	Likewise for __pthread_mutexattr_gettype.
+
+1998-07-15 11:00 -0400  Zack Weinberg  <zack@rabi.phys.columbia.edu>
+
+	* attr.c (pthread_attr_setschedpolicy): Don't check whether caller
+	is root.
+
+1998-07-14 19:38  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/bits/libc-lock.h: Define __libc_cleanup_end.
+
+1998-07-11  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* Examples/ex6.c: Include <unistd.h> for usleep.
+
+1998-06-13 11:04  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* Examples/ex4.c (main): Use exit, not pthread_exit.
+
+1998-07-09 13:39  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Versions: Add __pthread_mutexattr_gettype and
+	__pthread_mutexattr_settype.
+	* lockfile.c: Use __pthread_mutexattr_settype instead of
+	__pthread_mutexattr_setkind_np.
+	* mutex.c: Define __pthread_mutexattr_gettype and
+	__pthread_mutexattr_settype.
+	* weak.c: Likewise.
+	* sysdeps/pthread/pthread.h: Declare __pthread_mutexattr_gettype and
+	__pthread_mutexattr_settype.
+	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_init_recursive):
+	Use __pthread_mutexattr_settype.
+
+1998-07-08 22:26  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Versions: Add pthread_mutexattr_gettype, pthread_mutexattr_settype.
+	* mutex.c: Define weak alias pthread_mutexattr_gettype and
+	pthread_mutexattr_settype.
+	* sysdeps/pthread/pthread.h: Declare these functions.
+	Move pthread_sigmask and pthread_kill declaration in separate header.
+	* sysdeps/unix/sysv/linux/bits/sigthread.h: New file.
+
+1998-07-07 15:20  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Makefile: Add rules to compile and run tests.
+	* Examples/ex1.c: Little changes to fix warnings.
+	* Examples/ex2.c: Likewise.
+	* Examples/ex3.c: Likewise.
+	* Examples/ex4.c: Likewise.
+	* Examples/ex5.c: Likewise.
+	* Examples/ex6.c: New file.
+
+1998-07-05 11:54  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Versions: Add pthread_attr_init to GLIBC_2.1 version in libc.
+
+1998-07-01  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* attr.c: Include <string.h>.
+
+1998-06-30 11:47  Ulrich Drepper  <drepper@cygnus.com>
+
+	* attr.c: Include errno.h.  Use memcpy to copy sched_param.
+	* internals.h: Include limits.h.
+	* manager.c: Use memcpy to copy sched_param.
+	* ptfork.c: Include errno.h.
+	* pthread.c: Likewise.
+	* semaphore.c: Likewise.
+	* specific.c: Likewise.
+	* spinlock.h: Likewise.
+	* sysdeps/pthread/pthread.h: Include only allowed headers.  Move
+	type definition to ...
+	* sysdeps/pthread/bits/pthreadtypes.h: ...here.  New file.
+
+1998-06-29 12:34  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/pthread.h: Use __PMT not __P for function pointers.
+
+	* sysdeps/pthread/pthread.h: Define various PTHREAD_* symbols also
+	as macros as demanded in POSIX.1, Annex C.
+
+1998-06-29 12:29  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h (struct pthread_request): For free use pthread_t
+	instead of pthread_descr.
+	* join.c (pthread_join): Pass thread_id, not th to manager.
+	(pthread_detach): Likewise.
+	* manager.c (__pthread_manager): Except thread ID in FREE_REQ case.
+	(pthread_exited): Remove detached queue code.
+	(pthread_handle_free): Expect thread ID parameter and use it to
+	validate the thread decsriptor.  Don't use detached queue.
+	Patches by Xavier Leroy.
+
+1998-06-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* libpthread.map: Export accept, longjmp, sigaction, siglongjmp,
+	_IO_flockfile, _IO_ftrylockfile, _IO_funlockfile,
+	__pthread_atfork, __pthread_key_create, __pthread_once.
+	* internals.h: Doc fix.
+	* pthread.c (__pthread_initialize): Define again.
+
+1998-06-26  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_exited): If thread is not detached put it on
+	special list.
+	(pthread_handle_free): If thread is not on list with living threads
+	search on list with detached threads.
+
+	* sysdeps/pthread/pthread.h (PTHREAD_RWLOCK_INITIALIZER): Correct
+	for new definition of pthread_rwlock_t.
+
+	* spinlock.c: Correct test whether to compile
+	__pthread_compare_and_swap or not.
+
+1998-06-25 19:27  Ulrich Drepper  <drepper@cygnus.com>
+
+	* attr.c: Finish user stack support.  Change locking code to be safe
+	in situations with different priorities.
+	* cancel.c: Likewise.
+	* condvar.c: Likewise.
+	* internals.h: Likewise.
+	* join.c: Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* ptlongjmp.c: Likewise.
+	* queue.h: Likewise.
+	* rwlock.c: Likewise.
+	* semaphore.c: Likewise.
+	* semaphore.h: Likewise.
+	* signals.c: Likewise.
+	* spinlock.c: Likewise.
+	* spinlock.h: Likewise.
+	* sysdeps/pthread/pthread.h: Likewise.
+	Patches by Xavier Leroy.
+
+	* sysdeps/i386/i686/pt-machine.h: New file.
+
+1998-06-25  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/pthread.h: Make [sg]et_stacksize and
+	[sg]et_stackaddr prototypes always available.
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
+	_POSIX_THREAD_ATTR_STACKSIZE and _POSIX_THREAD_ATTR_STACKADDR.
+
+1998-06-24  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_free): Undo patch from 980430.
+	Reported by David Wragg <dpw@doc.ic.ac.uk>.
+
+1998-06-09 15:07  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c: Define __pthread_manager_adjust_prio and use it to
+	increase priority when needed.
+	* internals.h: Add prototype for __pthread_manager_adjust_prio.
+	* mutex.c: Optimize mutexes to wake up only one thread.
+	* pthread.c: Move PID of manager for global variable in structure
+	element.
+	Patches by Xavier Leroy.
+
+1998-06-07 13:47  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/pthread/bits/libc-lock.h: Optimize cleanup handlers a bit.
+
+1998-06-03  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* attr.c: Correct typo.
+
+1998-05-01  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_free): Unmap guard before the stack.
+	Patch by Matthias Urlichs.
+
+1998-04-30  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_free): Detect already free child.
+	Patch by Xavier Leroy, reported by Matthias Urlichs.
+
+1998-04-23  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* Makefile (linuxthreads-version): Renamed back from
+	libpthread-version.
+
+1998-04-21  Ulrich Drepper  <drepper@cygnus.com>
+
+	* ptlongjmp.c: Add prototypes for __libc_siglongjmp and
+	__libc_longjmp.
+
+1998-04-20 14:55  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Makefile (libpthread-routines): Add ptlongjmp and spinlock.
+	* internals.h: Add definitions for new spinlock implementation.
+	* ptlongjmp.c: New file.
+	* spinlock.c: New file.
+	* spinlock.h (acquire): Don't reschedule using __sched_yield, use
+	new function __pthread_acquire to prevent deadlocks with thread
+	with different priorities.
+	Patches by Xavier Leroy <Xavier.Leroy@inria.fr>.
+
+1998-03-16  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* manager.c (__pthread_manager): Reduce first argument to select
+	to include just the needed file descriptor.
+
+1998-03-17 00:06  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c: Fix last patch which caused core dumps.
+
+	* pthread.c: Correctly handle missing SIGRTMIN.
+
+1998-03-15  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* libpthread.map: Add __libc_internal_tsd_get and
+	__libc_internal_tsd_set.  Add missing cancelable functions. Export
+	libc internal versions of the cancelable functions.
+
+1998-03-13 16:51  Ulrich Drepper  <drepper@cygnus.com>
+
+	* weaks.c: Define pthread_attr_init as GLIBC_2.0 and GLIBC_2.1.
+
+1998-03-13 00:46  Ulrich Drepper  <drepper@cygnus.com>
+
+	* attr.c: Implement pthread_attr_[gs]etguardsize,
+	pthread_attr_[gs]setstackaddr, pthread_attr_[gs]etstacksize.
+	Change pthread_attr_init to have two interfaces.
+	* internals.h (struct _pthread_descr_struct): Add new fields for
+	above functions.
+	* libpthread.map: Add names in GLIBC_2.1 section.
+	* manager.c (pthread_handle_create): Implement guardsize and
+	user stack.
+	(pthread_free): Likewise.
+	* pthread.c (pthread_create): Add new interface for changed
+	pthread_attr_t.
+	* sysdeps/pthread/pthread.h: Add prototypes for new functions.
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Add definition of
+	PTHREAD_STACK_MIN.
+
+1998-03-11 00:42  Wolfram Gloger  <wmglo@dent.med.uni-muenchen.de>
+
+	* manager.c: Enable resetting of the thread scheduling policy
+	to SCHED_OTHER when the parent thread has a different one.
+
+1998-02-01 13:51  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
+	_POSIX_ASYNCHRONOUS_IO.
+
+	* sysdeps/pthread/pthread.h: Define bits for Unix98 variants of
+	mutexes.
+	* mutex.c: Implement new mutex types.
+
+	* internals.h: Include <signal.h>.
+
+	* libpthread.map: Add __erno_location and __h_errno_location.
+
+	* errno.c: Return pointer to variable actually in use.  This might
+	not be the one in the thread structure.
+	* internals.h (struct _pthread_descr_struct): Add new fields p_errnop
+	and p_h_errnop.
+	* manager.c (__pthread_manager): Set p_errnop and p_h_errnop member
+	of manager thread structure.
+	(pthread_handle_create): Set p_errnop and p_h_errnop members for new
+	thread.
+	* pthread.c: Adapt initializer for thread structures.
+	(__pthread_initial_thread): Set p_errnop and p_h_errnop member.
+	(__pthread_reset_main_thread): Reset p_errnop and p_h_errnop of
+	current thread to global variables.
+
+1998-01-31 17:27  Ulrich Drepper  <drepper@cygnus.com>
+
+	* rwlock.c: New file.
+	* Makefile (libpthread-routines): Add rwlock.
+	* sysdeps/pthread/pthread.h: Define data structures and declare
+	functions.
+	* libpthread.map: Add new functions.
+
+1997-12-18 13:50  Philip Blundell  <pb@nexus.co.uk>
+
+	* sysdeps/arm/pt-machine.h: New file; add ARM support.
+	* sysdeps/arm/Implies: likewise.
+	* README: Document it.
+
+1997-12-13  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* signals.c: Remove unneeded initializer for sigwaited, saving a
+	warning.
+
+1997-04-11 01:18  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* semaphore.c (sem_init): Set sem_spinlock only if available.
+
+1997-12-04 01:48  Ulrich Drepper  <drepper@cygnus.com>
+
+	* mutex.c: Implement PTHREAD_MUTEX_CHECKERROR.
+	* sysdeps/pthread/pthread.h: Define PTHREAD_MUTEX_CHECKERROR.
+
+	* Makefile: Update from LinuxThreads 0.7.
+	* internals.h. Likewise.
+	* manager.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* signals.c: Likewise.
+	* specific.c: Likewise.
+	* Examples/ex3.c: Likewise.
+
+1997-11-20 18:13  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_reset_main_thread): Close pipe only if still
+	open.
+
+1997-10-29 05:38  Ulrich Drepper  <drepper@cygnus.com>
+
+	* wrapsyscall.c: Add socket functions which are also cancelation
+	points.
+
+1997-10-19 21:40  Wolfram Gloger  <wg@wolfram.dent.med.uni-muenchen.de>
+
+	* specific.c (__libc_internal_tsd_set, __libc_internal_tsd_get):
+	New functions for fast thread specific data within libc.
+
+	* internals.h: Add new array p_libc_specific to struct
+	_pthread_descr_struct.
+
+	* sysdeps/pthread/bits/libc-lock.h: Declare new functions.
+
+1997-10-13 05:39  Ulrich Drepper  <drepper@cygnus.com>
+
+	* semaphore.h: Add __BEGIN_DECLS/__END_DECLS.
+	Reported by Ralf Corsepius <corsepiu@faw.uni-ulm.de>.
+
+1997-08-29 03:05  Ulrich Drepper  <drepper@cygnus.com>
+
+	* internals.h (struct _pthread_descr_struct): Add definitions for
+	two-level specific key handling.
+	* manager.c (pthread_handle_create): Initialize specific memory array.
+	* specific.c: Implement two-level key handling.
+	* weaks.c: Don't provide dummy key handling.
+	* sysdeps/pthread/bits/libc-lock.h: Typedef __libc_lock_t (no #define).
+	Add definition of __libc_key_t.
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Define PTHREAD_KEYS_MAX
+	as 1024.
+	Add definition of _POSIX_THREAD_DESTRUCTOR_ITERATIONS and
+	PTHREAD_DESTRUCTOR_ITERATIONS.
+
+	* manager.c (pthread_handle_create): Compare mmap result with
+	MAP_FAILED.
+
+	* ptfork.c: Rename to __pthread_atfork and make old name a weak alias.
+	* sysdeps/pthread/bits/pthread.h: Add prototype for __pthread_atfork.
+
+1997-08-22 19:04  Richard Henderson  <rth@cygnus.com>
+
+	sysdeps/sparc -> sysdeps/sparc/sparc32
+	sysdeps/sparc64 -> sysdeps/sparc/sparc64
+
+	* internals.h: Change definition of THREAD_SELF to be an expression,
+	not a statement that did a return.
+	* sysdeps/alpha/pt-machine.h (THREAD_SELF): Update accordingly.
+	* sysdeps/sparc/sparc32/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
+	Follow Solaris and use a "system reserved" register (%g6) to hold
+	the thread descriptor.
+	* sysdeps/sparc/sparc64/pt-machine.h: Likewise.
+
+1997-08-03 00:09  Ulrich Drepper  <drepper@cygnus.com>
+
+	* mutex.c: Correct pthread_once.  Patch by Xavier Leroy.
+	* sysdeps/pthread/pthread.h: Add prototype for __pthread_once.
+	* sysdeps/pthread/bits/pthread.h: Add macros for __libc_once.
+
+	* semaphore.c: Include spinlock.h only when needed.
+
+	* specific.c (__pthread_setsepcific, __pthread_getspecific): Reject
+	keys for entries not in use.
+
+	* weaks.c: Implement key handling functions for real.
+
+1997-06-29  01:04  Richard Henderson  <richard@gnu.ai.mit.edu>
+
+	Initial sparc64-linux support:
+	* sysdeps/sparc64/Implies: New file.
+	* sysdeps/sparc64/pt-machine.h: Likewise.
+
+1997-06-29 00:48  Ulrich Drepper  <drepper@cygnus.com>
+
+	* semaphore.c: Include spinlock.h at correct place.
+	Patch by HJ Lu.
+
+1997-06-13 10:06  Richard Henderson  <rth@tamu.edu>
+
+	The Great Bit File Move:
+	* sysdeps/alpha/semaphorebits.h: -> .../bits/semaphore.h.
+	* sysdeps/powerpc/semaphorebits.h: Likewise.
+	* sysdeps/pthread/cmpxchg/semaphorebits.h: Likewise.
+	* sysdeps/pthread/no-cmpxchg/semaphorebits.h: Likewise.
+	* sysdeps/pthread/libc-lock.h: -> bits/
+	* sysdeps/pthread/stdio-lock.h: Likewise.
+	* sysdeps/unix/sysv/linux/local_lim.h: Likewise.
+	* sysdeps/unix/sysv/linux/posix_opt.h: Likewise.
+	* semaphore.h: Likewise.
+	* sysdeps/pthread/pthread.h: Likewise.
+
+	* lockfile.c: <foo.h> -> <bits/foo.h>.
+	* semaphore.h: Likewise.
+
+	* Makefile: (headers): foo.h -> bits/foo.h.
+	* sysdeps/pthread/Makefile: Likewise.
+
+1997-04-11 01:18  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* semaphore.c (sem_init): Set sem_spinlock only if available.
+
+	* sysdeps/m68k/pt-machine.h (testandset, __compare_and_swap): Fix
+	asm constraints.
+
+1997-04-09 03:00  Ulrich Drepper  <drepper@cygnus.com>
+
+	Update from LinuxThreads 0.6.
+
+	* attr.c (pthread_attr_getdetachstate): Use __sched_get_priority_max
+	and __sched_get_priority_min instead of names without `__'.
+
+	* manager.c: Rewrite large parts to implement opaque pthread_t.
+
+	* cancel.c: Adapt for opaque pthread_t type.
+	* condvar.c: Likewise.
+	* errno.c: Likewise.
+	* join.c: Likewise.
+	* mutex.c: Likewise.
+	* pthread.c: Likewise.
+	* signals.c: Likewise.
+	* specific.c: Likewise.
+	* restart.h: Likewise.
+	* queue.h: Likewise.
+	* Examples/ex3.c: Likewise.
+	* Examples/ex4.c: Likewise.
+	* sysdeps/pthread/pthread.h: Likewise.
+
+	* pthread.c: Accumulate time for all threads in thread manager.
+
+	* semaphore.c: Implement fallback implementation for architectures
+	sometimes missing compare-exchange operations.
+
+	* cancel.c (pthread_cancel): Validate handle argument.
+	* join.c (pthread_join): Likewise.
+	(pthread_detach): Likewise.
+	* signals.c (pthread_kill): Likewise.
+
+	* spinlock.h (acquire): Use __sched_yield not sched_yield.
+
+	* queue.h (enqueue): Enqueue thread according to priority.
+
+	* internals.c (struct pthread_start_args): New struct for passing
+	args to cloning function.
+	(struct _pthread): Rename to _pthread_descr_struct and adapt for
+	opaque pthread_t.
+
+	* Examples/Makefile (clean): Pass -f option to rm.
+
+	* sysdeps/i386/pt-machine.h: Add check for compare-exchange instruction
+	and define TEST_FOR_COMPARE_AND_SWAP.
+	* sysdeps/i386/i486/pt-machine.h: Removed.
+
+	* sysdeps/unix/sysv/linux/local_lim.h (PTHREAD_THREADS_MAX): Increase
+	to 1024.
+
+1997-04-04 16:38  Ulrich Drepper  <drepper@cygnus.com>
+
+	* restart.h (suspend): Clear p_signal before suspending.
+	(suspend_with_cancellation): Likewise.
+	Patch by Xavier Leroy <Xavier.Leroy@inria.fr>.
+
+	* weaks.c: Make __pthread_key_create return 1.
+	* sysdeps/pthread/libc-lock.h: Define __libc_key_create,
+	__libc_getspecific, __libc_setspecific, and __libc_key_t.
+	* sysdeps/pthread/stdio-lock.h: Don't care for implementation not
+	using libio.
+
+1997-03-19 15:13  Miguel de Icaza  <miguel@nuclecu.unam.mx>
+
+	* sysdeps/sparc/pt-machine (RELEASE): Fix.
+
+1997-03-01 07:55  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* sysdeps/powerpc/Implies: Added.
+	* sysdeps/powerpc/pt-machine.h: Added.
+	* sysdeps/powerpc/semaphorebits.h: Added.
+
+1997-01-22 01:22  Ulrich Drepper  <drepper@cygnus.com>
+
+	* pthread.c (__pthread_initial_thread): Correct
+	initializer.
+	(__pthread_manager_thread): Likewise.
+	Reported by Andreas Jaeger.
+
+1997-01-18 22:15  Richard Henderson  <rth@tamu.edu>
+
+	Since sigset_t no longer fits in a register, we can't pass in the
+	thread's initial mask so easily.  Take this opportunity to simplify
+	the clone implementation by only accepting a single void* argument.
+
+	* manager.c (__pthread_manager): Put thread vitals in the thread
+	struct instead of as arguments through clone.
+	(pthread_start_thread): Look for them there.
+	* internals.h (struct _pthread): Add p_initial_fn,
+	p_initial_fn_arg, p_initial_mask.  Fix __pthread_manager proto.
+	* pthread.c (pthread_initialize_manager): Revise clone invocation.
diff --git a/linuxthreads/Changes b/linuxthreads/Changes
new file mode 100644
index 0000000000..b213f36c57
--- /dev/null
+++ b/linuxthreads/Changes
@@ -0,0 +1,85 @@
+Release 0.9:
+- more ports (SH, IA-64, s390)
+- many bug fixes
+- timed sync object wait functions
+- barrier implementation
+- spinlocks implementation
+- thread register on x86
+- variable stack size and position on some platforms
+
+Release 0.8:
+(ehmm, forgot to update, don't know anymore)
+
+Release 0.7:
+- Destructors for thread-specific data now conform to the POSIX semantics
+  (call destructors again if non-NULL TSD remains after a round of
+   destruction).
+- Implemented thread-specific data as a sparse array, allows more TSD keys
+  and smaller thread descriptors (Ulrich Drepper).
+- Added "error checking" mutexes.
+- Protect against multiple sigwait() on the same signals.
+- Simplified implementation of semaphores when compare_and_swap is
+  not available.
+- Fixed bug in fork() where stdin was closed if fork() was called before
+  the first pthread_create().
+- Fixed bug in the gethostby*_r functions (bad result if null bytes
+  in addresses).
+- Typos in manual pages corrected.
+- First cut at a PowerPC port (not working yet, runs into problems
+  with gcc and with the C library).
+
+Release 0.6:
+- Validation of thread identifiers: no more crashes when operating on
+  a thread that has exited (based on Pavel Krauz's ideas).
+- Added fallback implementation of semaphores for the 386 and the
+  Sparc.
+- Fixed a bug in signal handling causing false restarts of suspended
+  threads.
+- Fixed a bug in realtime scheduling causing all threads to have
+  default scheduling on Ix86 with libc5.
+- With realtime scheduling, unlocking a mutex now restarts the
+  highest priority thread waiting on the mutex, not the
+  first-suspended thread (Richard Neitzel).
+- Timing a process now returns cumulative times for all threads, not
+  just times for the initial thread (suggested by Wolfram Gloger).
+- Cleaned up name space (internal defs prefixed by __, weak aliases
+  for non-portable extensions).
+- MIPS port (contributed by Ralf Baechle).
+
+Release 0.5:
+- Signal-safe semaphores a la POSIX 1003.1b added.
+- Locking bug in pthread_mutex_trylock over recursive mutexes fixed.
+- Race conditions in thread cancellation fixed.
+- Sparc port (contributed by Miguel de Icaza).
+- Support for getpwnam_r and getpwuid_r.
+- Added pthread_kill_other_threads_np to be used in conjunction with
+  exec*().
+
+Release 0.4:
+- Manual pages for all functions.
+- Synchronization bug causing accumulation of zombie processes fixed.
+- Race condition in pthread_cond_timedwait fixed.
+- Recursive mutexes are back by popular demand.
+- Partial support for realtime scheduling (initiated by Richard Neitzel).
+- pthread.h cleaned up a lot: now C++ compatible, added missing "const"
+  qualifiers, added short documentation, put to GNU libc standards
+  for name space pollution (Ulrich Drepper).
+- Motorola 68k port (contributed by Andreas Schwab).
+- Interaction with fork(2) cleaned up a lot.
+
+Release 0.3:
+- Thread creation and reclaimation now performed by a centralized
+  "thread manager" thread.
+- Removed recursive mutexes to make regular mutexes more efficient.
+- Now available as a shared library (contributed by Richard Henderson).
+- Alpha port (contributed by Richard Henderson).
+- Fixed many small discrepancies with Posix 1003.1c.
+- Put under the LGPL instead of the GPL.
+
+Release 0.2:
+- Reentrant libc functions (adapted from libc 5.3.9 by Peeter Joot)
+- pthread_cond_wait did not reacquire the mutex correctly on return
+- More efficient pthread_cond_broadcast
+
+Release 0.1:
+- First public release
diff --git a/linuxthreads/Examples/Makefile b/linuxthreads/Examples/Makefile
new file mode 100644
index 0000000000..c68b3676a4
--- /dev/null
+++ b/linuxthreads/Examples/Makefile
@@ -0,0 +1,15 @@
+CC=gcc
+CFLAGS=-g -O -Wall -I.. -D_REENTRANT
+LIBPTHREAD=../libpthread.a
+
+PROGS=ex1 ex2 ex3 ex4 ex5 proxy
+
+all: $(PROGS)
+
+.c:
+	$(CC) $(CFLAGS) -o $* $*.c $(LIBPTHREAD)
+
+$(PROGS):
+
+clean:
+	rm -f $(PROGS)
diff --git a/linuxthreads/Examples/ex1.c b/linuxthreads/Examples/ex1.c
new file mode 100644
index 0000000000..29138cf761
--- /dev/null
+++ b/linuxthreads/Examples/ex1.c
@@ -0,0 +1,42 @@
+/* Creates two threads, one printing 10000 "a"s, the other printing
+   10000 "b"s.
+   Illustrates: thread creation, thread joining. */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "pthread.h"
+
+static void *
+process (void *arg)
+{
+  int i;
+  fprintf (stderr, "Starting process %s\n", (char *) arg);
+  for (i = 0; i < 10000; i++)
+    {
+      write (1, (char *) arg, 1);
+    }
+  return NULL;
+}
+
+int
+main (void)
+{
+  int retcode;
+  pthread_t th_a, th_b;
+  void *retval;
+
+  retcode = pthread_create (&th_a, NULL, process, (void *) "a");
+  if (retcode != 0)
+    fprintf (stderr, "create a failed %d\n", retcode);
+  retcode = pthread_create (&th_b, NULL, process, (void *) "b");
+  if (retcode != 0)
+    fprintf (stderr, "create b failed %d\n", retcode);
+  retcode = pthread_join (th_a, &retval);
+  if (retcode != 0)
+    fprintf (stderr, "join a failed %d\n", retcode);
+  retcode = pthread_join (th_b, &retval);
+  if (retcode != 0)
+    fprintf (stderr, "join b failed %d\n", retcode);
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex10.c b/linuxthreads/Examples/ex10.c
new file mode 100644
index 0000000000..f3ad517283
--- /dev/null
+++ b/linuxthreads/Examples/ex10.c
@@ -0,0 +1,108 @@
+/* Tests for pthread_mutex_timedlock function.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
+
+   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 <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#define NUM_THREADS 10
+#define NUM_ITERS   50
+#define TIMEOUT_NS  100000000L
+
+static void *thread (void *)  __attribute__ ((__noreturn__));
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int
+main (void)
+{
+  pthread_t th;
+  int i;
+
+  for (i = 0; i < NUM_THREADS; i++)
+    {
+      if (pthread_create (&th, NULL, thread, NULL) != 0)
+	error (EXIT_FAILURE, 0, "cannot create thread");
+    }
+
+  (void) thread (NULL);
+  /* notreached */
+  return 0;
+}
+
+
+static void *
+thread (void *arg)
+{
+  int i;
+  pthread_t self = pthread_self ();
+  static int linecount; /* protected by flockfile(stdout) */
+
+  for (i = 0; i < NUM_ITERS; i++)
+    {
+      struct timespec ts;
+
+      for (;;)
+	{
+	  int err;
+
+	  clock_gettime (CLOCK_REALTIME, &ts);
+
+	  ts.tv_nsec += TIMEOUT_NS;
+
+	  if (ts.tv_nsec >= 1000000000L) {
+	     ts.tv_sec++;
+	     ts.tv_nsec -= 1000000000L;
+	  }
+
+	  switch ((err = pthread_mutex_timedlock (&mutex, &ts)))
+	    {
+	    case 0:
+	      flockfile (stdout);
+	      printf ("%04d: thread %lu got mutex\n", ++linecount,
+		      (unsigned long) self);
+	      funlockfile (stdout);
+	      break;
+	    case ETIMEDOUT:
+	      flockfile (stdout);
+	      printf ("%04d: thread %lu timed out on mutex\n", ++linecount,
+		      (unsigned long) self);
+	      funlockfile (stdout);
+	      continue;
+	    default:
+	      error (EXIT_FAILURE, err, "pthread_mutex_timedlock failure");
+	    }
+	  break;
+	}
+
+      ts.tv_sec = 0;
+      ts.tv_nsec = TIMEOUT_NS;
+      nanosleep (&ts, NULL);
+
+      flockfile (stdout);
+      printf ("%04d: thread %lu releasing mutex\n", ++linecount,
+	      (unsigned long) self);
+      funlockfile (stdout);
+      pthread_mutex_unlock (&mutex);
+    }
+
+  pthread_exit (NULL);
+}
diff --git a/linuxthreads/Examples/ex11.c b/linuxthreads/Examples/ex11.c
new file mode 100644
index 0000000000..abb5b5385a
--- /dev/null
+++ b/linuxthreads/Examples/ex11.c
@@ -0,0 +1,154 @@
+/* Test program for timedout read/write lock functions.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   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 <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define TIMEOUT 1000000
+#define DELAY   1000000
+
+static pthread_rwlock_t lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
+
+
+static void *
+writer_thread (void *nr)
+{
+  struct timespec ts;
+  struct timespec delay;
+  int n;
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = TIMEOUT;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < WRITETRIES; ++n)
+    {
+      do
+	{
+	  clock_gettime (CLOCK_REALTIME, &ts);
+
+	  ts.tv_nsec += 2 * TIMEOUT;
+
+	  printf ("writer thread %ld tries again\n", (long int) nr);
+	}
+      //while (pthread_rwlock_wrlock (&lock), 0);
+      while (pthread_rwlock_timedwrlock (&lock, &ts) == ETIMEDOUT);
+
+      printf ("writer thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      pthread_rwlock_unlock (&lock);
+
+      printf ("writer thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+  struct timespec ts;
+  struct timespec delay;
+  int n;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < READTRIES; ++n)
+    {
+      do
+	{
+	  clock_gettime (CLOCK_REALTIME, &ts);
+
+	  ts.tv_nsec += TIMEOUT;
+
+	  printf ("reader thread %ld tries again\n", (long int) nr);
+	}
+      //while (pthread_rwlock_rdlock (&lock), 0);
+      while (pthread_rwlock_timedrdlock (&lock, &ts) == ETIMEDOUT);
+
+      printf ("reader thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      pthread_rwlock_unlock (&lock);
+
+      printf ("reader thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+int
+main (void)
+{
+  pthread_t thwr[NWRITERS];
+  pthread_t thrd[NREADERS];
+  int n;
+  void *res;
+
+  /* Make standard error the same as standard output.  */
+  dup2 (1, 2);
+
+  /* Make sure we see all message, even those on stdout.  */
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (n = 0; n < NWRITERS; ++n)
+    {
+      int err = pthread_create (&thwr[n], NULL, writer_thread,
+				(void *) (long int) n);
+
+      if (err != 0)
+	error (EXIT_FAILURE, err, "cannot create writer thread");
+    }
+
+  for (n = 0; n < NREADERS; ++n)
+    {
+      int err = pthread_create (&thrd[n], NULL, reader_thread,
+				(void *) (long int) n);
+
+      if (err != 0)
+	error (EXIT_FAILURE, err, "cannot create reader thread");
+    }
+
+  /* Wait for all the threads.  */
+  for (n = 0; n < NWRITERS; ++n)
+    pthread_join (thwr[n], &res);
+  for (n = 0; n < NREADERS; ++n)
+    pthread_join (thrd[n], &res);
+
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex12.c b/linuxthreads/Examples/ex12.c
new file mode 100644
index 0000000000..e986fec97f
--- /dev/null
+++ b/linuxthreads/Examples/ex12.c
@@ -0,0 +1,47 @@
+/* Variant of ex6, but this time we use pthread_exit ().  */
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *
+__attribute__ ((noreturn))
+test_thread (void *v_param)
+{
+  pthread_exit (NULL);
+}
+
+int
+main (void)
+{
+  unsigned long count;
+
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (count = 0; count < 2000; ++count)
+    {
+      pthread_t thread;
+      int status;
+
+      status = pthread_create (&thread, NULL, test_thread, NULL);
+      if (status != 0)
+	{
+	  printf ("status = %d, count = %lu: %s\n", status, count,
+		  strerror (errno));
+	  return 1;
+	}
+      else
+	{
+	  printf ("count = %lu\n", count);
+	}
+      /* pthread_detach (thread); */
+      if (pthread_join (thread, NULL) != 0)
+	{
+	  printf ("join failed, count %lu\n", count);
+	  return 2;
+	}
+      usleep (10);
+    }
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex13.c b/linuxthreads/Examples/ex13.c
new file mode 100644
index 0000000000..14add6c773
--- /dev/null
+++ b/linuxthreads/Examples/ex13.c
@@ -0,0 +1,112 @@
+/* Test for Pthreads/mutexes.
+   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kurt Garloff <garloff@suse.de>, 2000.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *thread_start (void *ptr) __attribute__ ((__noreturn__));
+
+
+struct thr_ctrl
+{
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  int retval;
+};
+
+static void
+dump_mut (pthread_mutex_t * mut)
+{
+  size_t i;
+  for (i = 0; i < sizeof (*mut); i++)
+    printf (" %02x", *((unsigned char *) mut + i));
+  printf ("\n");
+};
+
+/* Helper, the opposite of pthread_cond_wait (cond, mut).  */
+static void
+pthr_cond_signal_mutex (pthread_cond_t * cond, pthread_mutex_t * mut)
+{
+  int err;
+  err = pthread_mutex_lock (mut);
+  if (err)
+    printf ("mutex_lock  : %s\n", strerror (err));
+  err = pthread_cond_signal (cond);
+  if (err)
+    printf ("cond_signal : %s\n", strerror (err));
+  err = pthread_mutex_unlock (mut);
+  if (err)
+    printf ("mutex_unlock: %s\n", strerror (err));
+}
+
+static void *
+thread_start (void *ptr)
+{
+  struct thr_ctrl *tc = ptr;
+  /* Do initialization.  */
+  /* ... */
+  /* Signal that we are ready.  */
+  pthr_cond_signal_mutex (&tc->cond, &tc->mutex);
+  sleep (2);
+  pthr_cond_signal_mutex (&tc->cond, &tc->mutex);
+  tc->retval = 0;
+  pthread_exit (&tc->retval);
+}
+
+int
+main (void)
+{
+  struct thr_ctrl threadctrl;
+  pthread_t thread;
+  int err;
+  void *res = &threadctrl.retval;
+  pthread_mutexattr_t mutattr;
+  pthread_mutexattr_init (&mutattr);
+  pthread_mutex_init (&threadctrl.mutex, &mutattr);
+  pthread_cond_init (&threadctrl.cond, NULL);
+  err = pthread_mutex_lock (&threadctrl.mutex);
+  if (err)
+    printf ("mutex_lock : %s\n", strerror (err));
+  dump_mut (&threadctrl.mutex);
+  pthread_create (&thread, NULL, thread_start, &threadctrl);
+  /* Wait until it's ready.  */
+  err = pthread_cond_wait (&threadctrl.cond, &threadctrl.mutex);
+  if (err)
+    printf ("cond_wait  : %s\n", strerror (err));
+  /* Now, we should have acquired the mutex again!  */
+  dump_mut (&threadctrl.mutex);
+  sleep (1);
+  dump_mut (&threadctrl.mutex);
+  err = pthread_cond_wait (&threadctrl.cond, &threadctrl.mutex);
+  if (err)
+    {
+      printf ("cond_wait  : %s\n", strerror (err));
+      printf ("ERROR\n");
+      abort ();
+    };
+  dump_mut (&threadctrl.mutex);
+  pthread_join (thread, &res);
+  printf ("OK\n");
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex14.c b/linuxthreads/Examples/ex14.c
new file mode 100644
index 0000000000..406e03f346
--- /dev/null
+++ b/linuxthreads/Examples/ex14.c
@@ -0,0 +1,133 @@
+/* Test of POSIX barriers.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NTHREADS 20
+
+#define ROUNDS 20
+
+static pthread_barrier_t barriers[NTHREADS];
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int counters[NTHREADS];
+static int serial[NTHREADS];
+
+static void *
+worker (void *arg)
+{
+  void *result = NULL;
+  int nr = (long int) arg;
+  int i;
+
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      int j;
+      int retval;
+
+      if (nr == 0)
+	{
+	  memset (counters, '\0', sizeof (counters));
+	  memset (serial, '\0', sizeof (serial));
+	}
+
+      retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
+      if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("thread %d failed to wait for all the others\n", nr);
+	  result = (void *) 1;
+	}
+
+      for (j = nr; j < NTHREADS; ++j)
+	{
+	  /* Increment the counter for this round.  */
+	  pthread_mutex_lock (&lock);
+	  ++counters[j];
+	  pthread_mutex_unlock (&lock);
+
+	  /* Wait for the rest.  */
+	  retval = pthread_barrier_wait (&barriers[j]);
+
+	  /* Test the result.  */
+	  if (nr == 0 && counters[j] != j + 1)
+	    {
+	      printf ("barrier in round %d released but count is %d\n",
+		      j, counters[j]);
+	      result = (void *) 1;
+	    }
+
+	  if (retval != 0)
+	    {
+	      if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
+		{
+		  printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
+			  nr, j);
+		  result = (void *) 1;
+		}
+	      else
+		{
+		  pthread_mutex_lock (&lock);
+		  ++serial[j];
+		  pthread_mutex_unlock (&lock);
+		}
+	    }
+
+	  /* Wait for the rest again.  */
+	  retval = pthread_barrier_wait (&barriers[j]);
+
+	  /* Now we can check whether exactly one thread was serializing.  */
+	  if (nr == 0 && serial[j] != 1)
+	    {
+	      printf ("not exactly one serial thread in round %d\n", j);
+	      result = (void *) 1;
+	    }
+	}
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 60
+static int
+do_test (void)
+{
+  pthread_t threads[NTHREADS];
+  int i;
+  void *res;
+  int result = 0;
+
+  /* Initialized the barrier variables.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
+      {
+	printf ("Failed to initialize barrier %d\n", i);
+	exit (1);
+      }
+
+  /* Start the threads.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
+      {
+	printf ("Failed to start thread %d\n", i);
+	exit (1);
+      }
+
+  /* And wait for them.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_join (threads[i], &res) != 0 || res != NULL)
+      {
+	printf ("thread %d returned a failure\n", i);
+	result = 1;
+      }
+
+  if (result == 0)
+    puts ("all OK");
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/linuxthreads/Examples/ex15.c b/linuxthreads/Examples/ex15.c
new file mode 100644
index 0000000000..e953b231d7
--- /dev/null
+++ b/linuxthreads/Examples/ex15.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *worker (void *dummy) __attribute__ ((__noreturn__));
+
+static void *
+worker (void *dummy)
+{
+  exit (26);
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 10
+static int
+do_test (void)
+{
+  pthread_t th;
+  pid_t pid;
+  int status;
+
+  switch ((pid = fork ()))
+    {
+    case -1:
+      puts ("Could not fork");
+      exit (1);
+    case 0:
+      if (pthread_create(&th, NULL, worker, NULL) != 0)
+	{
+	  puts ("Failed to start thread");
+	  exit (1);
+	}
+      for (;;);
+      exit (1);
+    default:
+      break;
+    }
+
+  if (waitpid (pid, &status, 0) != pid)
+    {
+      puts ("waitpid failed");
+      exit (1);
+    }
+
+  if (!WIFEXITED (status) || WEXITSTATUS (status) != 26)
+    {
+      printf ("Wrong exit code %d\n", status);
+      exit (1);
+    }
+
+  puts ("All OK");
+  return 0;
+}
+
+#include "../../test-skeleton.c"
diff --git a/linuxthreads/Examples/ex16.c b/linuxthreads/Examples/ex16.c
new file mode 100644
index 0000000000..6509ae4515
--- /dev/null
+++ b/linuxthreads/Examples/ex16.c
@@ -0,0 +1,26 @@
+/* Tst case by Jakub Jelinek <jakub@redhat.com>.  */
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+static void *
+task (void *p)
+{
+  sleep (30);
+  return NULL;
+}
+
+int
+main (void)
+{
+  pthread_t t;
+  int status;
+
+  status = pthread_create (&t, NULL, task, NULL);
+  if (status)
+    exit (status);
+
+  status = pthread_detach (t);
+  pthread_kill_other_threads_np ();
+  return status;
+}
diff --git a/linuxthreads/Examples/ex17.c b/linuxthreads/Examples/ex17.c
new file mode 100644
index 0000000000..1bc09a5bda
--- /dev/null
+++ b/linuxthreads/Examples/ex17.c
@@ -0,0 +1,112 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/mman.h>
+
+static pthread_mutex_t synch = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+test_thread (void *v_param)
+{
+  pthread_mutex_lock (&synch);
+  return NULL;
+}
+
+#define STACKSIZE 0x100000
+
+int
+main (void)
+{
+  pthread_t thread;
+  pthread_attr_t attr;
+  int status;
+  void *stack, *stack2;
+  size_t stacksize;
+
+  pthread_attr_init (&attr);
+  stack = mmap (NULL, STACKSIZE,
+		PROT_READ | PROT_WRITE | PROT_EXEC,
+		MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+  if (stack == MAP_FAILED)
+    {
+      perror ("mmap failed");
+      return 1;
+    }
+
+  status = pthread_attr_setstack (&attr, stack, STACKSIZE);
+  if (status != 0)
+    {
+      printf ("pthread_attr_setstack failed: %s\n", strerror (status));
+      return 1;
+    }
+
+  status = pthread_attr_getstack (&attr, &stack2, &stacksize);
+  if (status != 0)
+    {
+      printf ("pthread_attr_getstack failed: %s\n", strerror (status));
+      return 1;
+    }
+
+  if (stack2 != stack || stacksize != STACKSIZE)
+    {
+      printf ("first pthread_attr_getstack returned different stack (%p,%zx)\n"
+	      "than was set by setstack (%p,%x)\n",
+	      stack2, stacksize, stack, STACKSIZE);
+      return 2;
+    }
+
+  status = pthread_mutex_lock (&synch);
+  if (status != 0)
+    {
+      printf ("cannot get lock: %s\n", strerror (status));
+      return 1;
+    }
+
+  status = pthread_create (&thread, &attr, test_thread, NULL);
+  if (status != 0)
+    {
+      printf ("pthread_create failed: %s\n", strerror (status));
+      return 1;
+    }
+
+  status = pthread_getattr_np (thread, &attr);
+  if (status != 0)
+    {
+      printf ("pthread_getattr_np failed: %s\n", strerror (status));
+      return 1;
+    }
+
+  status = pthread_attr_getstack (&attr, &stack2, &stacksize);
+  if (status != 0)
+    {
+      printf ("pthread_attr_getstack failed: %s\n", strerror (status));
+      return 1;
+    }
+
+  if (stack2 != stack || stacksize != STACKSIZE)
+    {
+      printf ("second pthread_attr_getstack returned different stack (%p,%zx)\n"
+	      "than was set by setstack (%p,%x)\n",
+	      stack2, stacksize, stack, STACKSIZE);
+      return 3;
+    }
+
+  status = pthread_mutex_unlock (&synch);
+  if (status != 0)
+    {
+      printf ("cannot release lock: %s\n", strerror (status));
+      return 1;
+    }
+
+  /* pthread_detach (thread); */
+  if (pthread_join (thread, NULL) != 0)
+    {
+      printf ("join failed\n");
+      return 1;
+    }
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex18.c b/linuxthreads/Examples/ex18.c
new file mode 100644
index 0000000000..283396bede
--- /dev/null
+++ b/linuxthreads/Examples/ex18.c
@@ -0,0 +1,113 @@
+/*
+ * Beat up the pthread_key_create and pthread_key_delete
+ * functions.
+ */
+
+#if 0
+#define CHATTY
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+const int beatup_iterations = 10000;
+const int num_threads = 30;
+const int max_keys = 500;
+
+struct key_list {
+  struct key_list *next;
+  pthread_key_t key;	
+};
+
+struct key_list *key_list;
+pthread_mutex_t key_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Create a new key and put it at the tail of a linked list.
+ * If the linked list grows to a certain length, delete a key from the
+ * head of * the list. 
+ */
+
+static void 
+beat_up(void)
+{
+  struct key_list *new = malloc(sizeof *new);
+  struct key_list **iter, *old_key = 0;
+  int key_count = 0;
+
+  if (new == 0) {
+    fprintf(stderr, "malloc failed\n");
+    abort();
+  }
+
+  new->next = 0;
+
+  if (pthread_key_create(&new->key, 0) != 0) {
+    fprintf(stderr, "pthread_key_create failed\n");
+    abort();
+  }
+
+  if (pthread_getspecific(new->key) != 0) {
+    fprintf(stderr, "new pthread_key_t resolves to non-null value\n");
+    abort();
+  }
+
+  pthread_setspecific(new->key, (void *) 1);
+
+#ifdef CHATTY
+  printf("created key\n");
+#endif
+
+  pthread_mutex_lock(&key_lock);
+
+  for (iter = &key_list; *iter != 0; iter = &(*iter)->next)
+    key_count++;
+
+  *iter = new;
+
+  if (key_count > max_keys) {
+    old_key = key_list;
+    key_list = key_list->next;
+  }
+
+  pthread_mutex_unlock(&key_lock);
+
+  if (old_key != 0) {
+#ifdef CHATTY
+    printf("deleting key\n");
+#endif
+    pthread_key_delete(old_key->key);
+  }
+}
+
+static void *
+thread(void *arg)
+{
+  int i;
+  for (i = 0; i < beatup_iterations; i++) 
+    beat_up();
+  return 0;
+}
+
+int
+main(void)
+{
+  int i;
+  pthread_attr_t detached_thread;
+
+  pthread_attr_init(&detached_thread);
+  pthread_attr_setdetachstate(&detached_thread, PTHREAD_CREATE_DETACHED);
+
+  for (i = 0; i < num_threads; i++) {
+    pthread_t thread_id;
+    while (pthread_create(&thread_id, &detached_thread, thread, 0) == EAGAIN) {
+      /* let some threads die, so system can breathe. :) */
+      sleep(1);
+    }
+  }
+
+  pthread_exit(0);
+}
diff --git a/linuxthreads/Examples/ex2.c b/linuxthreads/Examples/ex2.c
new file mode 100644
index 0000000000..f2556a4206
--- /dev/null
+++ b/linuxthreads/Examples/ex2.c
@@ -0,0 +1,124 @@
+/* The classic producer-consumer example.
+   Illustrates mutexes and conditions.
+   All integers between 0 and 9999 should be printed exactly twice,
+   once to the right of the arrow and once to the left. */
+
+#include <stdio.h>
+#include "pthread.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons
+{
+  int buffer[BUFFER_SIZE];	/* the actual data */
+  pthread_mutex_t lock;		/* mutex ensuring exclusive access to buffer */
+  int readpos, writepos;	/* positions for reading and writing */
+  pthread_cond_t notempty;	/* signaled when buffer is not empty */
+  pthread_cond_t notfull;	/* signaled when buffer is not full */
+};
+
+/* Initialize a buffer */
+static void
+init (struct prodcons *b)
+{
+  pthread_mutex_init (&b->lock, NULL);
+  pthread_cond_init (&b->notempty, NULL);
+  pthread_cond_init (&b->notfull, NULL);
+  b->readpos = 0;
+  b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+static void
+put (struct prodcons *b, int data)
+{
+  pthread_mutex_lock (&b->lock);
+  /* Wait until buffer is not full */
+  while ((b->writepos + 1) % BUFFER_SIZE == b->readpos)
+    {
+      pthread_cond_wait (&b->notfull, &b->lock);
+      /* pthread_cond_wait reacquired b->lock before returning */
+    }
+  /* Write the data and advance write pointer */
+  b->buffer[b->writepos] = data;
+  b->writepos++;
+  if (b->writepos >= BUFFER_SIZE)
+    b->writepos = 0;
+  /* Signal that the buffer is now not empty */
+  pthread_cond_signal (&b->notempty);
+  pthread_mutex_unlock (&b->lock);
+}
+
+/* Read and remove an integer from the buffer */
+static int
+get (struct prodcons *b)
+{
+  int data;
+  pthread_mutex_lock (&b->lock);
+  /* Wait until buffer is not empty */
+  while (b->writepos == b->readpos)
+    {
+      pthread_cond_wait (&b->notempty, &b->lock);
+    }
+  /* Read the data and advance read pointer */
+  data = b->buffer[b->readpos];
+  b->readpos++;
+  if (b->readpos >= BUFFER_SIZE)
+    b->readpos = 0;
+  /* Signal that the buffer is now not full */
+  pthread_cond_signal (&b->notfull);
+  pthread_mutex_unlock (&b->lock);
+  return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+   the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void *
+producer (void *data)
+{
+  int n;
+  for (n = 0; n < 10000; n++)
+    {
+      printf ("%d --->\n", n);
+      put (&buffer, n);
+    }
+  put (&buffer, OVER);
+  return NULL;
+}
+
+static void *
+consumer (void *data)
+{
+  int d;
+  while (1)
+    {
+      d = get (&buffer);
+      if (d == OVER)
+	break;
+      printf ("---> %d\n", d);
+    }
+  return NULL;
+}
+
+int
+main (void)
+{
+  pthread_t th_a, th_b;
+  void *retval;
+
+  init (&buffer);
+  /* Create the threads */
+  pthread_create (&th_a, NULL, producer, 0);
+  pthread_create (&th_b, NULL, consumer, 0);
+  /* Wait until producer and consumer finish. */
+  pthread_join (th_a, &retval);
+  pthread_join (th_b, &retval);
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex3.c b/linuxthreads/Examples/ex3.c
new file mode 100644
index 0000000000..b80b323a33
--- /dev/null
+++ b/linuxthreads/Examples/ex3.c
@@ -0,0 +1,152 @@
+/* Multi-thread searching.
+   Illustrates: thread cancellation, cleanup handlers. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+/* Defines the number of searching threads */
+#define NUM_THREADS 5
+
+/* Function prototypes */
+void *search(void *);
+void print_it(void *);
+
+/* Global variables */
+pthread_t threads[NUM_THREADS];
+pthread_mutex_t lock;
+int tries;
+volatile int started;
+
+int main(int argc, char ** argv)
+{
+  int i;
+  int pid;
+
+  /* create a number to search for */
+  pid = getpid();
+  printf("Searching for the number = %d...\n", pid);
+
+  /* Initialize the mutex lock */
+  pthread_mutex_init(&lock, NULL);
+
+  /* Create the searching threads */
+  for (started=0; started<NUM_THREADS; started++)
+    pthread_create(&threads[started], NULL, search, (void *) (long int) pid);
+
+  /* Wait for (join) all the searching threads */
+  for (i=0; i<NUM_THREADS; i++)
+    pthread_join(threads[i], NULL);
+
+  printf("It took %d tries to find the number.\n", tries);
+
+  /* Exit the program */
+  return 0;
+}
+
+/* This is the cleanup function that is called
+   when the threads are cancelled */
+
+void print_it(void *arg)
+{
+  int *try = (int *) arg;
+  pthread_t tid;
+
+  /* Get the calling thread's ID */
+  tid = pthread_self();
+
+  /* Print where the thread was in its search when it was cancelled */
+  printf("Thread %lx was canceled on its %d try.\n", tid, *try);
+}
+
+/* This is the search routine that is executed in each thread */
+
+void *search(void *arg)
+{
+  int num = (long int) arg;
+  int i, j, ntries;
+  pthread_t tid;
+
+  /* get the calling thread ID */
+  tid = pthread_self();
+
+  /* use the thread ID to set the seed for the random number generator */
+  /* Since srand and rand are not thread-safe, serialize with lock */
+
+  /* Try to lock the mutex lock --
+     if locked, check to see if the thread has been cancelled
+     if not locked then continue */
+  while (pthread_mutex_trylock(&lock) == EBUSY)
+    pthread_testcancel();
+
+  srand((int)tid);
+  i = rand() & 0xFFFFFF;
+  pthread_mutex_unlock(&lock);
+  ntries = 0;
+
+  /* Set the cancellation parameters --
+     - Enable thread cancellation
+     - Defer the action of the cancellation */
+
+  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+
+  while (started < NUM_THREADS)
+    sched_yield ();
+
+  /* Push the cleanup routine (print_it) onto the thread
+     cleanup stack.  This routine will be called when the
+     thread is cancelled.  Also note that the pthread_cleanup_push
+     call must have a matching pthread_cleanup_pop call.  The
+     push and pop calls MUST be at the same lexical level
+     within the code */
+
+  /* Pass address of `ntries' since the current value of `ntries' is not
+     the one we want to use in the cleanup function */
+
+  pthread_cleanup_push(print_it, (void *)&ntries);
+
+  /* Loop forever */
+  while (1) {
+    i = (i + 1) & 0xFFFFFF;
+    ntries++;
+
+    /* Does the random number match the target number? */
+    if (num == i) {
+      /* Try to lock the mutex lock --
+         if locked, check to see if the thread has been cancelled
+         if not locked then continue */
+      while (pthread_mutex_trylock(&lock) == EBUSY)
+        pthread_testcancel();
+
+      /* Set the global variable for the number of tries */
+      tries = ntries;
+      printf("Thread %lx found the number!\n", tid);
+
+      /* Cancel all the other threads */
+      for (j=0; j<NUM_THREADS; j++)
+        if (threads[j] != tid) pthread_cancel(threads[j]);
+
+      /* Break out of the while loop */
+      break;
+    }
+
+    /* Every 100 tries check to see if the thread has been cancelled. */
+    if (ntries % 100 == 0) {
+      pthread_testcancel();
+    }
+  }
+
+  /* The only way we can get here is when the thread breaks out
+     of the while loop.  In this case the thread that makes it here
+     has found the number we are looking for and does not need to run
+     the thread cleanup function.  This is why the pthread_cleanup_pop
+     function is called with a 0 argument; this will pop the cleanup
+     function off the stack without executing it */
+
+  pthread_cleanup_pop(0);
+  return((void *)0);
+}
diff --git a/linuxthreads/Examples/ex4.c b/linuxthreads/Examples/ex4.c
new file mode 100644
index 0000000000..5c8b929e22
--- /dev/null
+++ b/linuxthreads/Examples/ex4.c
@@ -0,0 +1,115 @@
+/* Making a library function that uses static variables thread-safe.
+   Illustrates: thread-specific data, pthread_once(). */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+/* This is a typical example of a library function that uses
+   static variables to accumulate results between calls.
+   Here, it just returns the concatenation of all string arguments
+   that were given to it. */
+
+#if 0
+
+char *
+str_accumulate (char *s)
+{
+  static char accu[1024] = { 0 };
+  strcat (accu, s);
+  return accu;
+}
+
+#endif
+
+/* Of course, this cannot be used in a multi-threaded program
+   because all threads store "accu" at the same location.
+   So, we'll use thread-specific data to have a different "accu"
+   for each thread. */
+
+/* Key identifying the thread-specific data */
+static pthread_key_t str_key;
+/* "Once" variable ensuring that the key for str_alloc will be allocated
+   exactly once. */
+static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
+
+/* Forward functions */
+static void str_alloc_key (void);
+static void str_alloc_destroy_accu (void *accu);
+
+/* Thread-safe version of str_accumulate */
+
+static char *
+str_accumulate (const char *s)
+{
+  char *accu;
+
+  /* Make sure the key is allocated */
+  pthread_once (&str_alloc_key_once, str_alloc_key);
+  /* Get the thread-specific data associated with the key */
+  accu = (char *) pthread_getspecific (str_key);
+  /* It's initially NULL, meaning that we must allocate the buffer first. */
+  if (accu == NULL)
+    {
+      accu = malloc (1024);
+      if (accu == NULL)
+	return NULL;
+      accu[0] = 0;
+      /* Store the buffer pointer in the thread-specific data. */
+      pthread_setspecific (str_key, (void *) accu);
+      printf ("Thread %lx: allocating buffer at %p\n", pthread_self (), accu);
+    }
+  /* Now we can use accu just as in the non thread-safe code. */
+  strcat (accu, s);
+  return accu;
+}
+
+/* Function to allocate the key for str_alloc thread-specific data. */
+
+static void
+str_alloc_key (void)
+{
+  pthread_key_create (&str_key, str_alloc_destroy_accu);
+  printf ("Thread %lx: allocated key %d\n", pthread_self (), str_key);
+}
+
+/* Function to free the buffer when the thread exits. */
+/* Called only when the thread-specific data is not NULL. */
+
+static void
+str_alloc_destroy_accu (void *accu)
+{
+  printf ("Thread %lx: freeing buffer at %p\n", pthread_self (), accu);
+  free (accu);
+}
+
+/* Test program */
+
+static void *
+process (void *arg)
+{
+  char *res;
+  res = str_accumulate ("Result of ");
+  res = str_accumulate ((char *) arg);
+  res = str_accumulate (" thread");
+  printf ("Thread %lx: \"%s\"\n", pthread_self (), res);
+  return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+  char *res;
+  pthread_t th1, th2;
+
+  res = str_accumulate ("Result of ");
+  pthread_create (&th1, NULL, process, (void *) "first");
+  pthread_create (&th2, NULL, process, (void *) "second");
+  res = str_accumulate ("initial thread");
+  printf ("Thread %lx: \"%s\"\n", pthread_self (), res);
+  pthread_join (th1, NULL);
+  pthread_join (th2, NULL);
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex5.c b/linuxthreads/Examples/ex5.c
new file mode 100644
index 0000000000..d39d487603
--- /dev/null
+++ b/linuxthreads/Examples/ex5.c
@@ -0,0 +1,114 @@
+/* The classic producer-consumer example, implemented with semaphores.
+   All integers between 0 and 9999 should be printed exactly twice,
+   once to the right of the arrow and once to the left. */
+
+#include <stdio.h>
+#include "pthread.h"
+#include "semaphore.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons
+{
+  int buffer[BUFFER_SIZE];	/* the actual data */
+  int readpos, writepos;	/* positions for reading and writing */
+  sem_t sem_read;		/* number of elements available for reading */
+  sem_t sem_write;		/* number of locations available for writing */
+};
+
+/* Initialize a buffer */
+
+static void
+init (struct prodcons *b)
+{
+  sem_init (&b->sem_write, 0, BUFFER_SIZE - 1);
+  sem_init (&b->sem_read, 0, 0);
+  b->readpos = 0;
+  b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+
+static void
+put (struct prodcons *b, int data)
+{
+  /* Wait until buffer is not full */
+  sem_wait (&b->sem_write);
+  /* Write the data and advance write pointer */
+  b->buffer[b->writepos] = data;
+  b->writepos++;
+  if (b->writepos >= BUFFER_SIZE)
+    b->writepos = 0;
+  /* Signal that the buffer contains one more element for reading */
+  sem_post (&b->sem_read);
+}
+
+/* Read and remove an integer from the buffer */
+
+static int
+get (struct prodcons *b)
+{
+  int data;
+  /* Wait until buffer is not empty */
+  sem_wait (&b->sem_read);
+  /* Read the data and advance read pointer */
+  data = b->buffer[b->readpos];
+  b->readpos++;
+  if (b->readpos >= BUFFER_SIZE)
+    b->readpos = 0;
+  /* Signal that the buffer has now one more location for writing */
+  sem_post (&b->sem_write);
+  return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+   the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void *
+producer (void *data)
+{
+  int n;
+  for (n = 0; n < 10000; n++)
+    {
+      printf ("%d --->\n", n);
+      put (&buffer, n);
+    }
+  put (&buffer, OVER);
+  return NULL;
+}
+
+static void *
+consumer (void *data)
+{
+  int d;
+  while (1)
+    {
+      d = get (&buffer);
+      if (d == OVER)
+	break;
+      printf ("---> %d\n", d);
+    }
+  return NULL;
+}
+
+int
+main (void)
+{
+  pthread_t th_a, th_b;
+  void *retval;
+
+  init (&buffer);
+  /* Create the threads */
+  pthread_create (&th_a, NULL, producer, 0);
+  pthread_create (&th_b, NULL, consumer, 0);
+  /* Wait until producer and consumer finish. */
+  pthread_join (th_a, &retval);
+  pthread_join (th_b, &retval);
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex6.c b/linuxthreads/Examples/ex6.c
new file mode 100644
index 0000000000..9a0266828b
--- /dev/null
+++ b/linuxthreads/Examples/ex6.c
@@ -0,0 +1,46 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *
+test_thread (void *v_param)
+{
+  return NULL;
+}
+
+int
+main (void)
+{
+  unsigned long count;
+
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (count = 0; count < 2000; ++count)
+    {
+      pthread_t thread;
+      int status;
+
+      status = pthread_create (&thread, NULL, test_thread, NULL);
+      if (status != 0)
+	{
+	  printf ("status = %d, count = %lu: %s\n", status, count,
+		  strerror (errno));
+	  return 1;
+	}
+      else
+	{
+	  printf ("count = %lu\n", count);
+	}
+      /* pthread_detach (thread); */
+      int err = pthread_join (thread, NULL);
+      if (err != 0)
+	{
+	  printf ("join failed (%s), count %lu\n", strerror (err), count);
+	  return 2;
+	}
+      usleep (10);
+    }
+  return 0;
+}
diff --git a/linuxthreads/Examples/ex7.c b/linuxthreads/Examples/ex7.c
new file mode 100644
index 0000000000..d9db33c5cd
--- /dev/null
+++ b/linuxthreads/Examples/ex7.c
@@ -0,0 +1,45 @@
+/* This is a test of the special shutdown that occurs
+   when all threads, including the main one, call
+   pthread_exit(). It demonstrates that atexit
+   handlers are properly called, and that the
+   output is properly flushed even when stdout is
+   redirected to a file, and therefore fully buffered. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NTHREADS 20		/* number of threads */
+
+static void *
+thread (void *arg)
+{
+  printf ("thread terminating\n");
+  return 0;
+}
+
+static void
+cleanup (void)
+{
+  printf ("atexit handler called\n");
+}
+
+int
+main (void)
+{
+  int i;
+
+  atexit (cleanup);
+
+  for (i = 0; i < NTHREADS; i++)
+    {
+      pthread_t id;
+      if (pthread_create (&id, 0, thread, 0) != 0)
+	{
+	  fprintf (stderr, "pthread_create failed\n");
+	  abort ();
+	}
+    }
+
+  pthread_exit (0);
+}
diff --git a/linuxthreads/Examples/ex8.c b/linuxthreads/Examples/ex8.c
new file mode 100644
index 0000000000..bda81b9c61
--- /dev/null
+++ b/linuxthreads/Examples/ex8.c
@@ -0,0 +1,101 @@
+/* Tests for fork in multi-threaded environment.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   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 <error.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+enum
+{
+  PREPARE_BIT = 1,
+  PARENT_BIT = 2,
+  CHILD_BIT = 4
+};
+
+static int var;
+
+static void
+prepare (void)
+{
+  var |= PREPARE_BIT;
+}
+
+static void
+parent (void)
+{
+  var |= PARENT_BIT;
+}
+
+static void
+child (void)
+{
+  var |= CHILD_BIT;
+}
+
+
+static void *thread (void *arg);
+
+
+int
+main (void)
+{
+  pthread_t th;
+  void *res;
+
+  pthread_atfork (prepare, parent, child);
+
+  if (pthread_create (&th, NULL, thread, NULL) != 0)
+    error (EXIT_FAILURE, 0, "cannot create thread");
+
+  pthread_join (th, &res);
+
+  return (int) (long int) res;
+}
+
+
+static void *
+thread (void *arg)
+{
+  int status;
+  pid_t pid;
+
+  pid = fork ();
+  if (pid == 0)
+    {
+      /* We check whether the `prepare' and `child' function ran.  */
+      exit (var != (PREPARE_BIT | CHILD_BIT));
+    }
+  else if (pid == (pid_t) -1)
+    error (EXIT_FAILURE, errno, "cannot fork");
+
+  if (waitpid (pid, &status, 0) != pid)
+    error (EXIT_FAILURE, errno, "wrong child");
+
+  if (WTERMSIG (status) != 0)
+    error (EXIT_FAILURE, 0, "Child terminated incorrectly");
+  status = WEXITSTATUS (status);
+
+  if (status == 0)
+    status = var != (PREPARE_BIT | PARENT_BIT);
+
+  return (void *) (long int) status;
+}
diff --git a/linuxthreads/Examples/ex9.c b/linuxthreads/Examples/ex9.c
new file mode 100644
index 0000000000..3c8b8142e1
--- /dev/null
+++ b/linuxthreads/Examples/ex9.c
@@ -0,0 +1,98 @@
+/* Tests for pthread_barrier_* functions.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
+
+   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 <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM_THREADS 10
+#define NUM_ITERS   500
+
+static void *thread (void *)  __attribute__ ((__noreturn__));
+static pthread_barrier_t barrier;
+
+int
+main (void)
+{
+  pthread_t thread_list[NUM_THREADS];
+  int i;
+
+  if (pthread_barrier_init (&barrier, NULL, NUM_THREADS + 1) != 0)
+    error (EXIT_FAILURE, 0, "cannot initialize barrier");
+
+  for (i = 0; i < NUM_THREADS; i++)
+    {
+      if (pthread_create (&thread_list[i], NULL, thread, NULL) != 0)
+	error (EXIT_FAILURE, 0, "cannot create thread");
+    }
+
+  (void) thread (NULL);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    {
+      pthread_join(thread_list[i], NULL);
+    }
+
+  return 0;
+}
+
+
+static void *
+thread (void *arg)
+{
+  int i;
+  pthread_t self = pthread_self ();
+  static pthread_t last_serial_thread;
+  static int linecount; /* protected by flockfile(stdout) */
+
+  for (i = 0; i < NUM_ITERS; i++)
+    {
+      switch (pthread_barrier_wait (&barrier))
+	{
+	case 0:
+	  flockfile (stdout);
+	  printf ("%04d: non-serial thread %lu\n", ++linecount,
+		  (unsigned long) self);
+	  funlockfile (stdout);
+	  break;
+	case PTHREAD_BARRIER_SERIAL_THREAD:
+	  flockfile (stdout);
+	  printf ("%04d: serial thread %lu\n", ++linecount,
+		  (unsigned long) self);
+	  funlockfile (stdout);
+	  last_serial_thread = self;
+	  break;
+	default:
+	  /* Huh? */
+	  error (EXIT_FAILURE, 0, "unexpected return value from barrier wait");
+	}
+    }
+
+  if (pthread_equal (self, last_serial_thread))
+  {
+    flockfile (stdout);
+    printf ("%04d: last serial thread %lu terminating process\n",
+	    ++linecount, (unsigned long) self);
+    funlockfile (stdout);
+  }
+
+  pthread_exit(NULL);
+}
diff --git a/linuxthreads/Examples/tststatic.c b/linuxthreads/Examples/tststatic.c
new file mode 100644
index 0000000000..421011a3c4
--- /dev/null
+++ b/linuxthreads/Examples/tststatic.c
@@ -0,0 +1 @@
+#include "ex1.c"
diff --git a/linuxthreads/FAQ.html b/linuxthreads/FAQ.html
new file mode 100644
index 0000000000..21be33ec4c
--- /dev/null
+++ b/linuxthreads/FAQ.html
@@ -0,0 +1,1039 @@
+<HTML>
+<HEAD>
+<TITLE>LinuxThreads Frequently Asked Questions</TITLE>
+</HEAD>
+<BODY>
+<H1 ALIGN=center>LinuxThreads Frequently Asked Questions <BR>
+                 (with answers)</H1>
+<H2 ALIGN=center>[For LinuxThreads version 0.8]</H2>
+
+<HR><P>
+
+<A HREF="#A">A. The big picture</A><BR>
+<A HREF="#B">B. Getting more information</A><BR>
+<A HREF="#C">C. Issues related to the C library</A><BR>
+<A HREF="#D">D. Problems, weird behaviors, potential bugs</A><BR>
+<A HREF="#E">E. Missing functions, wrong types, etc</A><BR>
+<A HREF="#F">F. C++ issues</A><BR>
+<A HREF="#G">G. Debugging LinuxThreads programs</A><BR>
+<A HREF="#H">H. Compiling multithreaded code; errno madness</A><BR>
+<A HREF="#I">I. X-Windows and other libraries</A><BR>
+<A HREF="#J">J. Signals and threads</A><BR>
+<A HREF="#K">K. Internals of LinuxThreads</A><P>
+
+<HR>
+<P>
+
+<H2><A NAME="A">A. The big picture</A></H2>
+
+<H4><A NAME="A.1">A.1: What is LinuxThreads?</A></H4>
+
+LinuxThreads is a Linux library for multi-threaded programming.
+It implements the Posix 1003.1c API (Application Programming
+Interface) for threads.  It runs on any Linux system with kernel 2.0.0
+or more recent, and a suitable C library (see section <A HREF="C">C</A>).
+<P>
+
+<H4><A NAME="A.2">A.2: What are threads?</A></H4>
+
+A thread is a sequential flow of control through a program.
+Multi-threaded programming is, thus, a form of parallel programming
+where several threads of control are executing concurrently in the
+program.  All threads execute in the same memory space, and can
+therefore work concurrently on shared data.<P>
+
+Multi-threaded programming differs from Unix-style multi-processing in
+that all threads share the same memory space (and a few other system
+resources, such as file descriptors), instead of running in their own
+memory space as is the case with Unix processes.<P>
+
+Threads are useful for two reasons.  First, they allow a program to
+exploit multi-processor machines: the threads can run in parallel on
+several processors, allowing a single program to divide its work
+between several processors, thus running faster than a single-threaded
+program, which runs on only one processor at a time.  Second, some
+programs are best expressed as several threads of control that
+communicate together, rather than as one big monolithic sequential
+program.  Examples include server programs, overlapping asynchronous
+I/O, and graphical user interfaces.<P>
+
+<H4><A NAME="A.3">A.3: What is POSIX 1003.1c?</A></H4>
+
+It's an API for multi-threaded programming standardized by IEEE as
+part of the POSIX standards.  Most Unix vendors have endorsed the
+POSIX 1003.1c standard.  Implementations of the 1003.1c API are
+already available under Sun Solaris 2.5, Digital Unix 4.0,
+Silicon Graphics IRIX 6, and should soon be available from other
+vendors such as IBM and HP.  More generally, the 1003.1c API is
+replacing relatively quickly the proprietary threads library that were
+developed previously under Unix, such as Mach cthreads, Solaris
+threads, and IRIX sprocs.  Thus, multithreaded programs using the
+1003.1c API are likely to run unchanged on a wide variety of Unix
+platforms.<P>
+
+<H4><A NAME="A.4">A.4: What is the status of LinuxThreads?</A></H4>
+
+LinuxThreads implements almost all of Posix 1003.1c, as well as a few
+extensions.  The only part of LinuxThreads that does not conform yet
+to Posix is signal handling (see section <A HREF="#J">J</A>).  Apart
+from the signal stuff, all the Posix 1003.1c base functionality,
+as well as a number of optional extensions, are provided and conform
+to the standard (to the best of my knowledge).
+The signal stuff is hard to get right, at least without special kernel
+support, and while I'm definitely looking at ways to implement the
+Posix behavior for signals, this might take a long time before it's
+completed.<P>
+
+<H4><A NAME="A.5">A.5: How stable is LinuxThreads?</A></H4>
+
+The basic functionality (thread creation and termination, mutexes,
+conditions, semaphores) is very stable.  Several industrial-strength
+programs, such as the AOL multithreaded Web server, use LinuxThreads
+and seem quite happy about it.  There used to be some rough edges in
+the LinuxThreads / C library interface with libc 5, but glibc 2
+fixes all of those problems and is now the standard C library on major
+Linux distributions (see section <A HREF="#C">C</A>). <P>
+
+<HR>
+<P>
+
+<H2><A NAME="B">B.  Getting more information</A></H2>
+
+<H4><A NAME="B.1">B.1: What are good books and other sources of
+information on POSIX threads?</A></H4>
+
+The FAQ for comp.programming.threads lists several books:
+<A HREF="http://www.serpentine.com/~bos/threads-faq/">http://www.serpentine.com/~bos/threads-faq/</A>.<P>
+
+There are also some online tutorials. Follow the links from the
+LinuxThreads web page:
+<A HREF="http://pauillac.inria.fr/~xleroy/linuxthreads">http://pauillac.inria.fr/~xleroy/linuxthreads</A>.<P>
+
+<H4><A NAME="B.2">B.2: I'd like to be informed of future developments on
+LinuxThreads. Is there a mailing list for this purpose?</A></H4>
+
+I post LinuxThreads-related announcements on the newsgroup
+<A HREF="news:comp.os.linux.announce">comp.os.linux.announce</A>,
+and also on the mailing list
+<code>linux-threads@magenet.com</code>.
+You can subscribe to the latter by writing
+<A HREF="mailto:majordomo@magenet.com">majordomo@magenet.com</A>.<P>
+
+<H4><A NAME="B.3">B.3: What are good places for discussing
+LinuxThreads?</A></H4>
+
+For questions about programming with POSIX threads in general, use
+the newsgroup
+<A HREF="news:comp.programming.threads">comp.programming.threads</A>.
+Be sure you read the
+<A HREF="http://www.serpentine.com/~bos/threads-faq/">FAQ</A>
+for this group before you post.<P>
+
+For Linux-specific questions, use
+<A
+HREF="news:comp.os.linux.development.apps">comp.os.linux.development.apps</A>
+and <A
+HREF="news:comp.os.linux.development.kernel">comp.os.linux.development.kernel</A>.
+The latter is especially appropriate for questions relative to the
+interface between the kernel and LinuxThreads.<P>
+
+<H4><A NAME="B.4">B.4: How should I report a possible bug in
+LinuxThreads?</A></H4>
+
+If you're using glibc 2, the best way by far is to use the
+<code>glibcbug</code> script to mail a bug report to the glibc
+maintainers. <P>
+
+If you're using an older libc, or don't have the <code>glibcbug</code>
+script on your machine, then e-mail me directly
+(<code>Xavier.Leroy@inria.fr</code>).  <P>
+
+In both cases, before sending the bug report, make sure that it is not 
+addressed already in this FAQ.  Also, try to send a short program that
+reproduces the weird behavior you observed. <P>
+
+<H4><A NAME="B.5">B.5: I'd like to read the POSIX 1003.1c standard. Is
+it available online?</A></H4>
+
+Unfortunately, no.  POSIX standards are copyrighted by IEEE, and
+IEEE does not distribute them freely.  You can buy paper copies from
+IEEE, but the price is fairly high ($120 or so). If you disagree with
+this policy and you're an IEEE member, be sure to let them know.<P>
+
+On the other hand, you probably don't want to read the standard.  It's
+very hard to read, written in standard-ese, and targeted to
+implementors who already know threads inside-out.  A good book on
+POSIX threads provides the same information in a much more readable form.
+I can personally recommend Dave Butenhof's book, <CITE>Programming
+with POSIX threads</CITE> (Addison-Wesley). Butenhof was part of the
+POSIX committee and also designed the Digital Unix implementations of
+POSIX threads, and it shows.<P>
+
+Another good source of information is the X/Open Group Single Unix
+specification which is available both
+<A HREF="http://www.rdg.opengroup.org/onlinepubs/7908799/index.html">on-line</A>
+and as a
+<A HREF="http://www.UNIX-systems.org/gosolo2/">book and CD/ROM</A>.
+That specification includes pretty much all the POSIX standards,
+including 1003.1c, with some extensions and clarifications.<P>
+
+<HR>
+<P>
+
+<H2><A NAME="C">C.  Issues related to the C library</A></H2>
+
+<H4><A NAME="C.1">C.1: Which version of the C library should I use
+with LinuxThreads?</A></H4>
+
+The best choice by far is glibc 2, a.k.a. libc 6.  It offers very good
+support for multi-threading, and LinuxThreads has been closely
+integrated with glibc 2.  The glibc 2 distribution contains the
+sources of a specially adapted version of LinuxThreads.<P>
+
+glibc 2 comes preinstalled as the default C library on several Linux
+distributions, such as RedHat 5 and up, and Debian 2.
+Those distributions include the version of LinuxThreads matching
+glibc 2.<P>
+
+<H4><A NAME="C.2">C.2: My system has libc 5 preinstalled, not glibc
+2.  Can I still use LinuxThreads?</H4>
+
+Yes, but you're likely to run into some problems, as libc 5 only
+offers minimal support for threads and contains some bugs that affect
+multithreaded programs. <P>
+
+The versions of libc 5 that work best with LinuxThreads are
+libc 5.2.18 on the one hand, and libc 5.4.12 or later on the other hand.
+Avoid 5.3.12 and 5.4.7: these have problems with the per-thread errno
+variable. <P>
+
+<H4><A NAME="C.3">C.3: So, should I switch to glibc 2, or stay with a
+recent libc 5?</A></H4>
+
+I'd recommend you switch to glibc 2.  Even for single-threaded
+programs, glibc 2 is more solid and more standard-conformant than libc
+5.  And the shortcomings of libc 5 almost preclude any serious
+multi-threaded programming.<P>
+
+Switching an already installed
+system from libc 5 to glibc 2 is not completely straightforward.
+See the <A HREF="http://sunsite.unc.edu/LDP/HOWTO/Glibc2-HOWTO.html">Glibc2
+HOWTO</A> for more information.  Much easier is (re-)installing a
+Linux distribution based on glibc 2, such as RedHat 6.<P>
+
+<H4><A NAME="C.4">C.4: Where can I find glibc 2 and the version of
+LinuxThreads that goes with it?</A></H4>
+
+On <code>prep.ai.mit.edu</code> and its many, many mirrors around the world.
+See <A
+HREF="http://www.gnu.org/order/ftp.html">http://www.gnu.org/order/ftp.html</A>
+for a list of mirrors.<P>
+
+<H4><A NAME="C.5">C.5: Where can I find libc 5 and the version of
+LinuxThreads that goes with it?</A></H4>
+
+For libc 5, see <A HREF="ftp://sunsite.unc.edu/pub/Linux/devel/GCC/"><code>ftp://sunsite.unc.edu/pub/Linux/devel/GCC/</code></A>.<P>
+
+For the libc 5 version of LinuxThreads, see
+<A HREF="ftp://ftp.inria.fr/INRIA/Projects/cristal/Xavier.Leroy/linuxthreads/">ftp://ftp.inria.fr/INRIA/Projects/cristal/Xavier.Leroy/linuxthreads/</A>.<P>
+
+<H4><A NAME="C.6">C.6: How can I recompile the glibc 2 version of the
+LinuxThreads sources?</A></H4>
+
+You must transfer the whole glibc sources, then drop the LinuxThreads
+sources in the <code>linuxthreads/</code> subdirectory, then recompile
+glibc as a whole.  There are now too many inter-dependencies between
+LinuxThreads and glibc 2 to allow separate re-compilation of LinuxThreads.
+<P>
+
+<H4><A NAME="C.7">C.7: What is the correspondence between LinuxThreads 
+version numbers, libc version numbers, and RedHat version
+numbers?</A></H4>
+
+Here is a summary. (Information on Linux distributions other than
+RedHat are welcome.)<P>
+
+<TABLE>
+<TR><TD>LinuxThreads </TD> <TD>C library</TD> <TD>RedHat</TD></TR>
+<TR><TD>0.7, 0.71 (for libc 5)</TD> <TD>libc 5.x</TD> <TD>RH 4.2</TD></TR>
+<TR><TD>0.7, 0.71 (for glibc 2)</TD> <TD>glibc 2.0.x</TD> <TD>RH 5.x</TD></TR>
+<TR><TD>0.8</TD> <TD>glibc 2.1.1</TD> <TD>RH 6.0</TD></TR>
+<TR><TD>0.8</TD> <TD>glibc 2.1.2</TD> <TD>not yet released</TD></TR>
+</TABLE>
+<P>
+
+<HR>
+<P>
+
+<H2><A NAME="D">D. Problems, weird behaviors, potential bugs</A></H2>
+
+<H4><A NAME="D.1">D.1: When I compile LinuxThreads, I run into problems in
+file <code>libc_r/dirent.c</code></A></H4>
+
+You probably mean:
+<PRE>
+        libc_r/dirent.c:94: structure has no member named `dd_lock'
+</PRE>
+I haven't actually seen this problem, but several users reported it.
+My understanding is that something is wrong in the include files of
+your Linux installation (<code>/usr/include/*</code>). Make sure
+you're using a supported version of the libc 5 library. (See question <A
+HREF="#C.2">C.2</A>).<P>
+
+<H4><A NAME="D.2">D.2: When I compile LinuxThreads, I run into problems with
+<CODE>/usr/include/sched.h</CODE>: there are several occurrences of
+<CODE>_p</CODE> that the C compiler does not understand</A></H4>
+
+Yes, <CODE>/usr/include/sched.h</CODE> that comes with libc 5.3.12 is broken.
+Replace it with the <code>sched.h</code> file contained in the
+LinuxThreads distribution.  But really you should not be using libc
+5.3.12 with LinuxThreads! (See question <A HREF="#C.2">C.1</A>.)<P>
+
+<H4><A NAME="D.3">D.3: My program does <CODE>fdopen()</CODE> on a file
+descriptor opened on a pipe.  When I link it with LinuxThreads,
+<CODE>fdopen()</CODE> always returns NULL!</A></H4>
+
+You're using one of the buggy versions of libc (5.3.12, 5.4.7., etc).
+See question <A HREF="#C.1">C.1</A> above.<P>
+
+<H4><A NAME="D.4">D.4: My program creates a lot of threads, and after
+a while <CODE>pthread_create()</CODE> no longer returns!</A></H4>
+
+This is known bug in the version of LinuxThreads that comes with glibc
+2.1.1.  An upgrade to 2.1.2 is recommended. <P>
+
+<H4><A NAME="D.5">D.5: When I'm running a program that creates N
+threads, <code>top</code> or <code>ps</code>
+display N+2 processes that are running my program. What do all these
+processes correspond to?</A></H4>
+
+Due to the general "one process per thread" model, there's one process
+for the initial thread and N processes for the threads it created
+using <CODE>pthread_create</CODE>.  That leaves one process
+unaccounted for.  That extra process corresponds to the "thread
+manager" thread, a thread created internally by LinuxThreads to handle
+thread creation and thread termination.  This extra thread is asleep
+most of the time.
+
+<H4><A NAME="D.6">D.6: Scheduling seems to be very unfair when there
+is strong contention on a mutex: instead of giving the mutex to each
+thread in turn, it seems that it's almost always the same thread that
+gets the mutex. Isn't this completely broken behavior?</A></H4>
+
+That behavior has mostly disappeared in recent releases of
+LinuxThreads (version 0.8 and up).  It was fairly common in older
+releases, though.
+
+What happens in LinuxThreads 0.7 and before is the following: when a
+thread unlocks a mutex, all other threads that were waiting on the
+mutex are sent a signal which makes them runnable.  However, the
+kernel scheduler may or may not restart them immediately.  If the
+thread that unlocked the mutex tries to lock it again immediately
+afterwards, it is likely that it will succeed, because the threads
+haven't yet restarted.  This results in an apparently very unfair
+behavior, when the same thread repeatedly locks and unlocks the mutex,
+while other threads can't lock the mutex.<P>
+
+In LinuxThreads 0.8 and up, <code>pthread_unlock</code> restarts only
+one waiting thread, and pre-assign the mutex to that thread.  Hence,
+if the thread that unlocked the mutex tries to lock it again
+immediately, it will block until other waiting threads have had a
+chance to lock and unlock the mutex.  This results in much fairer
+scheduling.<P>
+
+Notice however that even the old "unfair" behavior is perfectly
+acceptable with respect to the POSIX standard: for the default
+scheduling policy, POSIX makes no guarantees of fairness, such as "the
+thread waiting for the mutex for the longest time always acquires it
+first".  Properly written multithreaded code avoids that kind of heavy
+contention on mutexes, and does not run into fairness problems.  If
+you need scheduling guarantees, you should consider using the
+real-time scheduling policies <code>SCHED_RR</code> and
+<code>SCHED_FIFO</code>, which have precisely defined scheduling
+behaviors. <P>
+
+<H4><A NAME="D.7">D.7: I have a simple test program with two threads
+that do nothing but <CODE>printf()</CODE> in tight loops, and from the
+printout it seems that only one thread is running, the other doesn't
+print anything!</A></H4>
+
+Again, this behavior is characteristic of old releases of LinuxThreads
+(0.7 and before); more recent versions (0.8 and up) should not exhibit
+this behavior.<P>
+
+The reason for this behavior is explained in
+question <A HREF="#D.6">D.6</A> above: <CODE>printf()</CODE> performs
+locking on <CODE>stdout</CODE>, and thus your two threads contend very
+heavily for the mutex associated with <CODE>stdout</CODE>.  But if you
+do some real work between two calls to <CODE>printf()</CODE>, you'll
+see that scheduling becomes much smoother.<P>
+
+<H4><A NAME="D.8">D.8: I've looked at <code>&lt;pthread.h&gt;</code>
+and there seems to be a gross error in the <code>pthread_cleanup_push</code>
+macro: it opens a block with <code>{</code> but does not close it!
+Surely you forgot a <code>}</code> at the end of the macro, right?
+</A></H4>
+
+Nope.  That's the way it should be.  The closing brace is provided by
+the <code>pthread_cleanup_pop</code> macro.  The POSIX standard
+requires <code>pthread_cleanup_push</code> and
+<code>pthread_cleanup_pop</code> to be used in matching pairs, at the
+same level of brace nesting.  This allows
+<code>pthread_cleanup_push</code> to open a block in order to
+stack-allocate some data structure, and
+<code>pthread_cleanup_pop</code> to close that block.  It's ugly, but
+it's the standard way of implementing cleanup handlers.<P>
+
+<H4><A NAME="D.9">D.9: I tried to use real-time threads and my program
+loops like crazy and freezes the whole machine!</A></H4>
+
+Versions of LinuxThreads prior to 0.8 are susceptible to ``livelocks''
+(one thread loops, consuming 100% of the CPU time) in conjunction with
+real-time scheduling.  Since real-time threads and processes have
+higher priority than normal Linux processes, all other processes on
+the machine, including the shell, the X server, etc, cannot run and
+the machine appears frozen.<P>
+
+The problem is fixed in LinuxThreads 0.8.<P>
+
+<H4><A NAME="D.10">D.10: My application needs to create thousands of
+threads, or maybe even more.  Can I do this with
+LinuxThreads?</A></H4>
+
+No.  You're going to run into several hard limits:
+<UL>
+<LI>Each thread, from the kernel's standpoint, is one process.  Stock
+Linux kernels are limited to at most 512 processes for the super-user,
+and half this number for regular users.  This can be changed by
+changing <code>NR_TASKS</code> in <code>include/linux/tasks.h</code>
+and recompiling the kernel.  On the x86 processors at least,
+architectural constraints seem to limit <code>NR_TASKS</code> to 4090
+at most.
+<LI>LinuxThreads contains a table of all active threads.  This table
+has room for 1024 threads at most.  To increase this limit, you must
+change <code>PTHREAD_THREADS_MAX</code> in the LinuxThreads sources
+and recompile.
+<LI>By default, each thread reserves 2M of virtual memory space for
+its stack.  This space is just reserved; actual memory is allocated
+for the stack on demand.  But still, on a 32-bit processor, the total
+virtual memory space available for the stacks is on the order of 1G,
+meaning that more than 500 threads will have a hard time fitting in.
+You can overcome this limitation by moving to a 64-bit platform, or by
+allocating smaller stacks yourself using the <code>setstackaddr</code>
+attribute.
+<LI>Finally, the Linux kernel contains many algorithms that run in
+time proportional to the number of process table entries.  Increasing
+this number drastically will slow down the kernel operations
+noticeably.
+</UL>
+(Other POSIX threads libraries have similar limitations, by the way.)
+For all those reasons, you'd better restructure your application so
+that it doesn't need more than, say, 100 threads.  For instance,
+in the case of a multithreaded server, instead of creating a new
+thread for each connection, maintain a fixed-size pool of worker
+threads that pick incoming connection requests from a queue.<P>
+
+<HR>
+<P>
+
+<H2><A NAME="E">E. Missing functions, wrong types, etc</A></H2>
+
+<H4><A NAME="E.1">E.1: Where is <CODE>pthread_yield()</CODE> ? How
+comes LinuxThreads does not implement it?</A></H4>
+
+Because it's not part of the (final) POSIX 1003.1c standard.
+Several drafts of the standard contained <CODE>pthread_yield()</CODE>,
+but then the POSIX guys discovered it was redundant with
+<CODE>sched_yield()</CODE> and dropped it.  So, just use
+<CODE>sched_yield()</CODE> instead.
+
+<H4><A NAME="E.2">E.2: I've found some type errors in
+<code>&lt;pthread.h&gt;</code>.
+For instance, the second argument to <CODE>pthread_create()</CODE>
+should be a <CODE>pthread_attr_t</CODE>, not a
+<CODE>pthread_attr_t *</CODE>. Also, didn't you forget to declare
+<CODE>pthread_attr_default</CODE>?</A></H4>
+
+No, I didn't.  What you're describing is draft 4 of the POSIX
+standard, which is used in OSF DCE threads.  LinuxThreads conforms to the
+final standard.  Even though the functions have the same names as in
+draft 4 and DCE, their calling conventions are slightly different.  In
+particular, attributes are passed by reference, not by value, and
+default attributes are denoted by the NULL pointer.  Since draft 4/DCE
+will eventually disappear, you'd better port your program to use the
+standard interface.<P>
+
+<H4><A NAME="E.3">E.3: I'm porting an application from Solaris and I
+have to rename all thread functions from <code>thr_blah</code> to
+<CODE>pthread_blah</CODE>.  This is very annoying.  Why did you change
+all the function names?</A></H4>
+
+POSIX did it.  The <code>thr_*</code> functions correspond to Solaris
+threads, an older thread interface that you'll find only under
+Solaris.  The <CODE>pthread_*</CODE> functions correspond to POSIX
+threads, an international standard available for many, many platforms.
+Even Solaris 2.5 and later support the POSIX threads interface.  So,
+do yourself a favor and rewrite your code to use POSIX threads: this
+way, it will run unchanged under Linux, Solaris, and quite a lot of
+other platforms.<P>
+
+<H4><A NAME="E.4">E.4: How can I suspend and resume a thread from
+another thread? Solaris has the <CODE>thr_suspend()</CODE> and
+<CODE>thr_resume()</CODE> functions to do that; why don't you?</A></H4>
+
+The POSIX standard provides <B>no</B> mechanism by which a thread A can
+suspend the execution of another thread B, without cooperation from B.
+The only way to implement a suspend/restart mechanism is to have B
+check periodically some global variable for a suspend request
+and then suspend itself on a condition variable, which another thread
+can signal later to restart B.<P>
+
+Notice that <CODE>thr_suspend()</CODE> is inherently dangerous and
+prone to race conditions.  For one thing, there is no control on where
+the target thread stops: it can very well be stopped in the middle of
+a critical section, while holding mutexes.  Also, there is no
+guarantee on when the target thread will actually stop.  For these
+reasons, you'd be much better off using mutexes and conditions
+instead.  The only situations that really require the ability to
+suspend a thread are debuggers and some kind of garbage collectors.<P>
+
+If you really must suspend a thread in LinuxThreads, you can send it a
+<CODE>SIGSTOP</CODE> signal with <CODE>pthread_kill</CODE>. Send
+<CODE>SIGCONT</CODE> for restarting it.
+Beware, this is specific to LinuxThreads and entirely non-portable.
+Indeed, a truly conforming POSIX threads implementation will stop all
+threads when one thread receives the <CODE>SIGSTOP</CODE> signal!
+One day, LinuxThreads will implement that behavior, and the
+non-portable hack with <CODE>SIGSTOP</CODE> won't work anymore.<P>
+
+<H4><A NAME="E.5">E.5: Does LinuxThreads implement
+<CODE>pthread_attr_setstacksize()</CODE> and
+<CODE>pthread_attr_setstackaddr()</CODE>?</A></H4>
+
+These optional functions are provided in recent versions of
+LinuxThreads (0.8 and up).  Earlier releases did not provide these
+optional components of the POSIX standard.<P>
+
+Even if <CODE>pthread_attr_setstacksize()</CODE> and
+<CODE>pthread_attr_setstackaddr()</CODE> are now provided, we still
+recommend that you do not use them unless you really have strong
+reasons for doing so.  The default stack allocation strategy for
+LinuxThreads is nearly optimal: stacks start small (4k) and
+automatically grow on demand to a fairly large limit (2M).
+Moreover, there is no portable way to estimate the stack requirements
+of a thread, so setting the stack size yourself makes your program
+less reliable and non-portable.<P>
+
+<H4><A NAME="E.6">E.6: LinuxThreads does not support the
+<CODE>PTHREAD_SCOPE_PROCESS</CODE> value of the "contentionscope"
+attribute.  Why? </A></H4>
+
+With a "one-to-one" model, as in LinuxThreads (one kernel execution
+context per thread), there is only one scheduler for all processes and
+all threads on the system.  So, there is no way to obtain the behavior of
+<CODE>PTHREAD_SCOPE_PROCESS</CODE>.
+
+<H4><A NAME="E.7">E.7: LinuxThreads does not implement process-shared
+mutexes, conditions, and semaphores. Why?</A></H4>
+
+This is another optional component of the POSIX standard.  Portable
+applications should test <CODE>_POSIX_THREAD_PROCESS_SHARED</CODE>
+before using this facility.
+<P>
+The goal of this extension is to allow different processes (with
+different address spaces) to synchronize through mutexes, conditions
+or semaphores allocated in shared memory (either SVR4 shared memory
+segments or <CODE>mmap()</CODE>ed files).
+<P>
+The reason why this does not work in LinuxThreads is that mutexes,
+conditions, and semaphores are not self-contained: their waiting
+queues contain pointers to linked lists of thread descriptors, and
+these pointers are meaningful only in one address space.
+<P>
+Matt Messier and I spent a significant amount of time trying to design a
+suitable mechanism for sharing waiting queues between processes.  We
+came up with several solutions that combined two of the following
+three desirable features, but none that combines all three:
+<UL>
+<LI>allow sharing between processes having different UIDs
+<LI>supports cancellation
+<LI>supports <CODE>pthread_cond_timedwait</CODE>
+</UL>
+We concluded that kernel support is required to share mutexes,
+conditions and semaphores between processes.  That's one place where
+Linus Torvalds's intuition that "all we need in the kernel is
+<CODE>clone()</CODE>" fails.
+<P>
+Until suitable kernel support is available, you'd better use
+traditional interprocess communications to synchronize different
+processes: System V semaphores and message queues, or pipes, or sockets.
+<P>
+
+<HR>
+<P>
+
+<H2><A NAME="F">F. C++ issues</A></H2>
+
+<H4><A NAME="F.1">F.1: Are there C++ wrappers for LinuxThreads?</A></H4>
+
+Douglas Schmidt's ACE library contains, among a lot of other
+things, C++ wrappers for LinuxThreads and quite a number of other
+thread libraries.  Check out
+<A HREF="http://www.cs.wustl.edu/~schmidt/ACE.html">http://www.cs.wustl.edu/~schmidt/ACE.html</A><P>
+
+<H4><A NAME="F.2">F.2: I'm trying to use LinuxThreads from a C++
+program, and the compiler complains about the third argument to
+<CODE>pthread_create()</CODE> !</A></H4>
+
+You're probably trying to pass a class member function or some
+other C++ thing as third argument to <CODE>pthread_create()</CODE>.
+Recall that <CODE>pthread_create()</CODE> is a C function, and it must
+be passed a C function as third argument.<P>
+
+<H4><A NAME="F.3">F.3: I'm trying to use LinuxThreads in conjunction
+with libg++, and I'm having all sorts of trouble.</A></H4>
+
+>From what I understand, thread support in libg++ is completely broken,
+especially with respect to locking of iostreams.  H.J.Lu wrote:
+<BLOCKQUOTE>
+If you want to use thread, I can only suggest egcs and glibc. You
+can find egcs at
+<A HREF="http://www.cygnus.com/egcs">http://www.cygnus.com/egcs</A>.
+egcs has libsdtc++, which is MT safe under glibc 2. If you really
+want to use the libg++, I have a libg++ add-on for egcs.
+</BLOCKQUOTE>
+<HR>
+<P>
+
+<H2><A NAME="G">G. Debugging LinuxThreads programs</A></H2>
+
+<H4><A NAME="G.1">G.1: Can I debug LinuxThreads program using gdb?</A></H4>
+
+Yes, but not with the stock gdb 4.17.  You need a specially patched
+version of gdb 4.17 developed by Eric Paire and colleages at The Open
+Group, Grenoble.  The patches against gdb 4.17 are available at
+<A HREF="http://www.gr.opengroup.org/java/jdk/linux/debug.htm"><code>http://www.gr.opengroup.org/java/jdk/linux/debug.htm</code></A>.
+Precompiled binaries of the patched gdb are available in RedHat's RPM
+format at <A
+HREF="http://odin.appliedtheory.com/"><code>http://odin.appliedtheory.com/</code></A>.<P>
+
+Some Linux distributions provide an already-patched version of gdb;
+others don't.  For instance, the gdb in RedHat 5.2 is thread-aware,
+but apparently not the one in RedHat 6.0.  Just ask (politely) the
+makers of your Linux distributions to please make sure that they apply
+the correct patches to gdb.<P>
+
+<H4><A NAME="G.2">G.2: Does it work with post-mortem debugging?</A></H4>
+
+Not very well.  Generally, the core file does not correspond to the
+thread that crashed.  The reason is that the kernel will not dump core
+for a process that shares its memory with other processes, such as the
+other threads of your program.  So, the thread that crashes silently
+disappears without generating a core file.  Then, all other threads of
+your program die on the same signal that killed the crashing thread.
+(This is required behavior according to the POSIX standard.)  The last
+one that dies is no longer sharing its memory with anyone else, so the
+kernel generates a core file for that thread.  Unfortunately, that's
+not the thread you are interested in.
+
+<H4><A NAME="G.3">G.3: Any other ways to debug multithreaded programs, then?</A></H4>
+
+Assertions and <CODE>printf()</CODE> are your best friends.  Try to debug
+sequential parts in a single-threaded program first.  Then, put
+<CODE>printf()</CODE> statements all over the place to get execution traces.
+Also, check invariants often with the <CODE>assert()</CODE> macro.  In truth,
+there is no other effective way (save for a full formal proof of your
+program) to track down concurrency bugs.  Debuggers are not really
+effective for subtle concurrency problems, because they disrupt
+program execution too much.<P>
+
+<HR>
+<P>
+
+<H2><A NAME="H">H. Compiling multithreaded code; errno madness</A></H2>
+
+<H4><A NAME="H.1">H.1: You say all multithreaded code must be compiled
+with <CODE>_REENTRANT</CODE> defined. What difference does it make?</A></H4>
+
+It affects include files in three ways:
+<UL>
+<LI> The include files define prototypes for the reentrant variants of
+some of the standard library functions,
+e.g. <CODE>gethostbyname_r()</CODE> as a reentrant equivalent to
+<CODE>gethostbyname()</CODE>.<P>
+
+<LI> If <CODE>_REENTRANT</CODE> is defined, some
+<code>&lt;stdio.h&gt;</code> functions are no longer defined as macros,
+e.g. <CODE>getc()</CODE> and <CODE>putc()</CODE>. In a multithreaded
+program, stdio functions require additional locking, which the macros
+don't perform, so we must call functions instead.<P>
+
+<LI> More importantly, <code>&lt;errno.h&gt;</code> redefines errno when
+<CODE>_REENTRANT</CODE> is
+defined, so that errno refers to the thread-specific errno location
+rather than the global errno variable.  This is achieved by the
+following <code>#define</code> in <code>&lt;errno.h&gt;</code>:
+<PRE>
+        #define errno (*(__errno_location()))
+</PRE>
+which causes each reference to errno to call the
+<CODE>__errno_location()</CODE> function for obtaining the location
+where error codes are stored.  libc provides a default definition of
+<CODE>__errno_location()</CODE> that always returns
+<code>&errno</code> (the address of the global errno variable). Thus,
+for programs not linked with LinuxThreads, defining
+<CODE>_REENTRANT</CODE> makes no difference w.r.t. errno processing.
+But LinuxThreads redefines <CODE>__errno_location()</CODE> to return a
+location in the thread descriptor reserved for holding the current
+value of errno for the calling thread.  Thus, each thread operates on
+a different errno location.
+</UL>
+<P>
+
+<H4><A NAME="H.2">H.2: Why is it so important that each thread has its
+own errno variable? </A></H4>
+
+If all threads were to store error codes in the same, global errno
+variable, then the value of errno after a system call or library
+function returns would be unpredictable:  between the time a system
+call stores its error code in the global errno and your code inspects
+errno to see which error occurred, another thread might have stored
+another error code in the same errno location. <P>
+
+<H4><A NAME="H.3">H.3: What happens if I link LinuxThreads with code
+not compiled with <CODE>-D_REENTRANT</CODE>?</A></H4>
+
+Lots of trouble.  If the code uses <CODE>getc()</CODE> or
+<CODE>putc()</CODE>, it will perform I/O without proper interlocking
+of the stdio buffers; this can cause lost output, duplicate output, or
+just crash other stdio functions.  If the code consults errno, it will
+get back the wrong error code.  The following code fragment is a
+typical example:
+<PRE>
+        do {
+          r = read(fd, buf, n);
+          if (r == -1) {
+            if (errno == EINTR)   /* an error we can handle */
+              continue;
+            else {                /* other errors are fatal */
+              perror("read failed");
+              exit(100);
+            }
+          }
+        } while (...);
+</PRE>
+Assume this code is not compiled with <CODE>-D_REENTRANT</CODE>, and
+linked with LinuxThreads.  At run-time, <CODE>read()</CODE> is
+interrupted.  Since the C library was compiled with
+<CODE>-D_REENTRANT</CODE>, <CODE>read()</CODE> stores its error code
+in the location pointed to by <CODE>__errno_location()</CODE>, which
+is the thread-local errno variable.  Then, the code above sees that
+<CODE>read()</CODE> returns -1 and looks up errno.  Since
+<CODE>_REENTRANT</CODE> is not defined, the reference to errno
+accesses the global errno variable, which is most likely 0.  Hence the
+code concludes that it cannot handle the error and stops.<P>
+
+<H4><A NAME="H.4">H.4: With LinuxThreads, I can no longer use the signals
+<code>SIGUSR1</code> and <code>SIGUSR2</code> in my programs! Why? </A></H4>
+
+The short answer is: because the Linux kernel you're using does not
+support realtime signals.  <P>
+
+LinuxThreads needs two signals for its internal operation.
+One is used to suspend and restart threads blocked on mutex, condition
+or semaphore operations.  The other is used for thread
+cancellation.<P>
+
+On ``old'' kernels (2.0 and early 2.1 kernels), there are only 32
+signals available and the kernel reserves all of them but two:
+<code>SIGUSR1</code> and <code>SIGUSR2</code>.  So, LinuxThreads has
+no choice but use those two signals.<P>
+
+On recent kernels (2.2 and up), more than 32 signals are provided in
+the form of realtime signals. When run on one of those kernels,
+LinuxThreads uses two reserved realtime signals for its internal
+operation, thus leaving <code>SIGUSR1</code> and <code>SIGUSR2</code>
+free for user code.  (This works only with glibc, not with libc 5.) <P>
+
+<H4><A NAME="H.5">H.5: Is the stack of one thread visible from the
+other threads?  Can I pass a pointer into my stack to other threads?
+</A></H4>
+
+Yes, you can -- if you're very careful.  The stacks are indeed visible
+from all threads in the system.  Some non-POSIX thread libraries seem
+to map the stacks for all threads at the same virtual addresses and
+change the memory mapping when they switch from one thread to
+another.  But this is not the case for LinuxThreads, as it would make
+context switching between threads more expensive, and at any rate
+might not conform to the POSIX standard.<P>
+
+So, you can take the address of an "auto" variable and pass it to
+other threads via shared data structures.  However, you need to make
+absolutely sure that the function doing this will not return as long
+as other threads need to access this address.  It's the usual mistake
+of returning the address of an "auto" variable, only made much worse
+because of concurrency.  It's much, much safer to systematically
+heap-allocate all shared data structures. <P>
+
+<HR>
+<P>
+
+<H2><A NAME="I">I.  X-Windows and other libraries</A></H2>
+
+<H4><A NAME="I.1">I.1: My program uses both Xlib and LinuxThreads.
+It stops very early with an "Xlib: unknown 0 error" message.  What
+does this mean? </A></H4>
+
+That's a prime example of the errno problem described in question <A
+HREF="#H.2">H.2</A>.  The binaries for Xlib you're using have not been
+compiled with <CODE>-D_REENTRANT</CODE>.  It happens Xlib contains a
+piece of code very much like the one in question <A
+HREF="#H.2">H.2</A>.  So, your Xlib fetches the error code from the
+wrong errno location and concludes that an error it cannot handle
+occurred.<P>
+
+<H4><A NAME="I.2">I.2: So, what can I do to build a multithreaded X
+Windows client? </A></H4>
+
+The best solution is to use X libraries that have been compiled with
+multithreading options set.  Linux distributions that come with glibc
+2 as the main C library generally provide thread-safe X libraries.
+At least, that seems to be the case for RedHat 5 and later.<P>
+
+You can try to recompile yourself the X libraries with multithreading
+options set.  They contain optional support for multithreading; it's
+just that the binaries provided by your Linux distribution were built
+without this support.  See the file <code>README.Xfree3.3</code> in
+the LinuxThreads distribution for patches and info on how to compile
+thread-safe X libraries from the Xfree3.3 distribution.  The Xfree3.3
+sources are readily available in most Linux distributions, e.g. as a
+source RPM for RedHat.  Be warned, however, that X Windows is a huge
+system, and recompiling even just the libraries takes a lot of time
+and disk space.<P>
+
+Another, less involving solution is to call X functions only from the
+main thread of your program.  Even if all threads have their own errno
+location, the main thread uses the global errno variable for its errno
+location.  Thus, code not compiled with <code>-D_REENTRANT</code>
+still "sees" the right error values if it executes in the main thread
+only. <P>
+
+<H4><A NAME="I.2">This is a lot of work. Don't you have precompiled
+thread-safe X libraries that you could distribute?</A></H4>
+
+No, I don't.  Sorry.  But consider installing a Linux distribution
+that comes with thread-safe X libraries, such as RedHat 6.<P>
+
+<H4><A NAME="I.3">I.3: Can I use library FOO in a multithreaded
+program?</A></H4>
+
+Most libraries cannot be used "as is" in a multithreaded program.
+For one thing, they are not necessarily thread-safe: calling
+simultaneously two functions of the library from two threads might not
+work, due to internal use of global variables and the like.  Second,
+the libraries must have been compiled with <CODE>-D_REENTRANT</CODE> to avoid
+the errno problems explained in question <A HREF="#H.2">H.2</A>.
+<P>
+
+<H4><A NAME="I.4">I.4: What if I make sure that only one thread calls
+functions in these libraries?</A></H4>
+
+This avoids problems with the library not being thread-safe.  But
+you're still vulnerable to errno problems.  At the very least, a
+recompile of the library with <CODE>-D_REENTRANT</CODE> is needed.
+<P>
+
+<H4><A NAME="I.5">I.5: What if I make sure that only the main thread
+calls functions in these libraries?</A></H4>
+
+That might actually work.  As explained in question <A HREF="#I.1">I.1</A>,
+the main thread uses the global errno variable, and can therefore
+execute code not compiled with <CODE>-D_REENTRANT</CODE>.<P>
+
+<H4><A NAME="I.6">I.6: SVGAlib doesn't work with LinuxThreads.  Why?
+</A></H4>
+
+Because both LinuxThreads and SVGAlib use the signals
+<code>SIGUSR1</code> and <code>SIGUSR2</code>.  See question <A
+HREF="#H.4">H.4</A>.
+<P>
+
+
+<HR>
+<P>
+
+<H2><A NAME="J">J.  Signals and threads</A></H2>
+
+<H4><A NAME="J.1">J.1: When it comes to signals, what is shared
+between threads and what isn't?</A></H4>
+
+Signal handlers are shared between all threads: when a thread calls
+<CODE>sigaction()</CODE>, it sets how the signal is handled not only
+for itself, but for all other threads in the program as well.<P>
+
+On the other hand, signal masks are per-thread: each thread chooses
+which signals it blocks independently of others.  At thread creation
+time, the newly created thread inherits the signal mask of the thread
+calling <CODE>pthread_create()</CODE>.  But afterwards, the new thread
+can modify its signal mask independently of its creator thread.<P>
+
+<H4><A NAME="J.2">J.2: When I send a <CODE>SIGKILL</CODE> to a
+particular thread using <CODE>pthread_kill</CODE>, all my threads are
+killed!</A></H4>
+
+That's how it should be.  The POSIX standard mandates that all threads
+should terminate when the process (i.e. the collection of all threads
+running the program) receives a signal whose effect is to
+terminate the process (such as <CODE>SIGKILL</CODE> or <CODE>SIGINT</CODE>
+when no handler is installed on that signal).  This behavior makes a
+lot of sense: when you type "ctrl-C" at the keyboard, or when a thread
+crashes on a division by zero or a segmentation fault, you really want
+all threads to stop immediately, not just the one that caused the
+segmentation violation or that got the <CODE>SIGINT</CODE> signal.
+(This assumes default behavior for those signals; see question
+<A HREF="#J.3">J.3</A> if you install handlers for those signals.)<P>
+
+If you're trying to terminate a thread without bringing the whole
+process down, use <code>pthread_cancel()</code>.<P>
+
+<H4><A NAME="J.3">J.3: I've installed a handler on a signal.  Which
+thread executes the handler when the signal is received?</A></H4>
+
+If the signal is generated by a thread during its execution (e.g. a
+thread executes a division by zero and thus generates a
+<CODE>SIGFPE</CODE> signal), then the handler is executed by that
+thread.  This also applies to signals generated by
+<CODE>raise()</CODE>.<P>
+
+If the signal is sent to a particular thread using
+<CODE>pthread_kill()</CODE>, then that thread executes the handler.<P>
+
+If the signal is sent via <CODE>kill()</CODE> or the tty interface
+(e.g. by pressing ctrl-C), then the POSIX specs say that the handler
+is executed by any thread in the process that does not currently block
+the signal.  In other terms, POSIX considers that the signal is sent
+to the process (the collection of all threads) as a whole, and any
+thread that is not blocking this signal can then handle it.<P>
+
+The latter case is where LinuxThreads departs from the POSIX specs.
+In LinuxThreads, there is no real notion of ``the process as a whole'':
+in the kernel, each thread is really a distinct process with a
+distinct PID, and signals sent to the PID of a thread can only be
+handled by that thread.  As long as no thread is blocking the signal,
+the behavior conforms to the standard: one (unspecified) thread of the
+program handles the signal.  But if the thread to which PID the signal
+is sent blocks the signal, and some other thread does not block the
+signal, then LinuxThreads will simply queue in
+that thread and execute the handler only when that thread unblocks
+the signal, instead of executing the handler immediately in the other
+thread that does not block the signal.<P>
+
+This is to be viewed as a LinuxThreads bug, but I currently don't see
+any way to implement the POSIX behavior without kernel support.<P>
+
+<H4><A NAME="J.3">J.3: How shall I go about mixing signals and threads
+in my program? </A></H4>
+
+The less you mix them, the better.  Notice that all
+<CODE>pthread_*</CODE> functions are not async-signal safe, meaning
+that you should not call them from signal handlers.  This
+recommendation is not to be taken lightly: your program can deadlock
+if you call a <CODE>pthread_*</CODE> function from a signal handler!
+<P>
+
+The only sensible things you can do from a signal handler is set a
+global flag, or call <CODE>sem_post</CODE> on a semaphore, to record
+the delivery of the signal.  The remainder of the program can then
+either poll the global flag, or use <CODE>sem_wait()</CODE> and
+<CODE>sem_trywait()</CODE> on the semaphore.<P>
+
+Another option is to do nothing in the signal handler, and dedicate
+one thread (preferably the initial thread) to wait synchronously for
+signals, using <CODE>sigwait()</CODE>, and send messages to the other
+threads accordingly.
+
+<H4><A NAME="J.4">J.4: When one thread is blocked in
+<CODE>sigwait()</CODE>, other threads no longer receive the signals
+<CODE>sigwait()</CODE> is waiting for!  What happens? </A></H4>
+
+It's an unfortunate consequence of how LinuxThreads implements
+<CODE>sigwait()</CODE>.  Basically, it installs signal handlers on all
+signals waited for, in order to record which signal was received.
+Since signal handlers are shared with the other threads, this
+temporarily deactivates any signal handlers you might have previously
+installed on these signals.<P>
+
+Though surprising, this behavior actually seems to conform to the
+POSIX standard.  According to POSIX, <CODE>sigwait()</CODE> is
+guaranteed to work as expected only if all other threads in the
+program block the signals waited for (otherwise, the signals could be
+delivered to other threads than the one doing <CODE>sigwait()</CODE>,
+which would make <CODE>sigwait()</CODE> useless).  In this particular
+case, the problem described in this question does not appear.<P>
+
+One day, <CODE>sigwait()</CODE> will be implemented in the kernel,
+along with others POSIX 1003.1b extensions, and <CODE>sigwait()</CODE>
+will have a more natural behavior (as well as better performances).<P>
+
+<HR>
+<P>
+
+<H2><A NAME="K">K.  Internals of LinuxThreads</A></H2>
+
+<H4><A NAME="K.1">K.1: What is the implementation model for
+LinuxThreads?</A></H4>
+
+LinuxThreads follows the so-called "one-to-one" model: each thread is
+actually a separate process in the kernel.  The kernel scheduler takes
+care of scheduling the threads, just like it schedules regular
+processes.  The threads are created with the Linux
+<code>clone()</code> system call, which is a generalization of
+<code>fork()</code> allowing the new process to share the memory
+space, file descriptors, and signal handlers of the parent.<P>
+
+Advantages of the "one-to-one" model include:
+<UL>
+<LI> minimal overhead on CPU-intensive multiprocessing (with
+about one thread per processor);
+<LI> minimal overhead on I/O operations;
+<LI> a simple and robust implementation (the kernel scheduler does
+most of the hard work for us).
+</UL>
+The main disadvantage is more expensive context switches on mutex and
+condition operations, which must go through the kernel.  This is
+mitigated by the fact that context switches in the Linux kernel are
+pretty efficient.<P>
+
+<H4><A NAME="K.2">K.2: Have you considered other implementation
+models?</A></H4>
+
+There are basically two other models.  The "many-to-one" model
+relies on a user-level scheduler that context-switches between the
+threads entirely in user code; viewed from the kernel, there is only
+one process running.  This model is completely out of the question for
+me, since it does not take advantage of multiprocessors, and require
+unholy magic to handle blocking I/O operations properly.  There are
+several user-level thread libraries available for Linux, but I found
+all of them deficient in functionality, performance, and/or robustness.
+<P>
+
+The "many-to-many" model combines both kernel-level and user-level
+scheduling: several kernel-level threads run concurrently, each
+executing a user-level scheduler that selects between user threads.
+Most commercial Unix systems (Solaris, Digital Unix, IRIX) implement
+POSIX threads this way.  This model combines the advantages of both
+the "many-to-one" and the "one-to-one" model, and is attractive
+because it avoids the worst-case behaviors of both models --
+especially on kernels where context switches are expensive, such as
+Digital Unix.  Unfortunately, it is pretty complex to implement, and
+requires kernel support which Linux does not provide.  Linus Torvalds
+and other Linux kernel developers have always been pushing the
+"one-to-one" model in the name of overall simplicity, and are doing a
+pretty good job of making kernel-level context switches between
+threads efficient.  LinuxThreads is just following the general
+direction they set.<P>
+
+<HR>
+<ADDRESS>Xavier.Leroy@inria.fr</ADDRESS>
+</BODY>
+</HTML>
diff --git a/linuxthreads/LICENSE b/linuxthreads/LICENSE
new file mode 100644
index 0000000000..7bcca60504
--- /dev/null
+++ b/linuxthreads/LICENSE
@@ -0,0 +1,501 @@
+GNU LIBRARY GENERAL PUBLIC LICENSE
+**********************************
+
+                         Version 2, June 1991
+
+     Copyright (C) 1991 Free Software Foundation, Inc.
+     59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA
+     
+     Everyone is permitted to copy and distribute verbatim copies
+     of this license document, but changing it is not allowed.
+     
+     [This is the first released version of the library GPL.  It is
+      numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+Preamble
+========
+
+   The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+   This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+   When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it in
+new free programs; and that you know you can do these things.
+
+   To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the library, or if you modify it.
+
+   For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+   Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+   Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+   Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+   Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License, which was designed for utility
+programs.  This license, the GNU Library General Public License,
+applies to certain designated libraries.  This license is quite
+different from the ordinary one; be sure to read it in full, and don't
+assume that anything in it is the same as in the ordinary license.
+
+   The reason we have a separate public license for some libraries is
+that they blur the distinction we usually make between modifying or
+adding to a program and simply using it.  Linking a program with a
+library, without changing the library, is in some sense simply using
+the library, and is analogous to running a utility program or
+application program.  However, in a textual and legal sense, the linked
+executable is a combined work, a derivative of the original library,
+and the ordinary General Public License treats it as such.
+
+   Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+   However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended
+to permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to
+achieve this as regards changes in header files, but we have achieved
+it as regards changes in the actual functions of the Library.)  The
+hope is that this will lead to faster development of free libraries.
+
+   The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+   Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+     contains a notice placed by the copyright holder or other
+     authorized party saying it may be distributed under the terms of
+     this Library General Public License (also called "this License").
+     Each licensee is addressed as "you".
+
+     A "library" means a collection of software functions and/or data
+     prepared so as to be conveniently linked with application programs
+     (which use some of those functions and data) to form executables.
+
+     The "Library", below, refers to any such software library or work
+     which has been distributed under these terms.  A "work based on the
+     Library" means either the Library or any derivative work under
+     copyright law: that is to say, a work containing the Library or a
+     portion of it, either verbatim or with modifications and/or
+     translated straightforwardly into another language.  (Hereinafter,
+     translation is included without limitation in the term
+     "modification".)
+
+     "Source code" for a work means the preferred form of the work for
+     making modifications to it.  For a library, complete source code
+     means all the source code for all modules it contains, plus any
+     associated interface definition files, plus the scripts used to
+     control compilation and installation of the library.
+
+     Activities other than copying, distribution and modification are
+     not covered by this License; they are outside its scope.  The act
+     of running a program using the Library is not restricted, and
+     output from such a program is covered only if its contents
+     constitute a work based on the Library (independent of the use of
+     the Library in a tool for writing it).  Whether that is true
+     depends on what the Library does and what the program that uses
+     the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+     complete source code as you receive it, in any medium, provided
+     that you conspicuously and appropriately publish on each copy an
+     appropriate copyright notice and disclaimer of warranty; keep
+     intact all the notices that refer to this License and to the
+     absence of any warranty; and distribute a copy of this License
+     along with the Library.
+
+     You may charge a fee for the physical act of transferring a copy,
+     and you may at your option offer warranty protection in exchange
+     for a fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+     of it, thus forming a work based on the Library, and copy and
+     distribute such modifications or work under the terms of Section 1
+     above, provided that you also meet all of these conditions:
+
+       a. The modified work must itself be a software library.
+
+       b. You must cause the files modified to carry prominent notices
+          stating that you changed the files and the date of any change.
+
+       c. You must cause the whole of the work to be licensed at no
+          charge to all third parties under the terms of this License.
+
+       d. If a facility in the modified Library refers to a function or
+          a table of data to be supplied by an application program that
+          uses the facility, other than as an argument passed when the
+          facility is invoked, then you must make a good faith effort
+          to ensure that, in the event an application does not supply
+          such function or table, the facility still operates, and
+          performs whatever part of its purpose remains meaningful.
+
+          (For example, a function in a library to compute square roots
+          has a purpose that is entirely well-defined independent of the
+          application.  Therefore, Subsection 2d requires that any
+          application-supplied function or table used by this function
+          must be optional: if the application does not supply it, the
+          square root function must still compute square roots.)
+
+     These requirements apply to the modified work as a whole.  If
+     identifiable sections of that work are not derived from the
+     Library, and can be reasonably considered independent and separate
+     works in themselves, then this License, and its terms, do not
+     apply to those sections when you distribute them as separate
+     works.  But when you distribute the same sections as part of a
+     whole which is a work based on the Library, the distribution of
+     the whole must be on the terms of this License, whose permissions
+     for other licensees extend to the entire whole, and thus to each
+     and every part regardless of who wrote it.
+
+     Thus, it is not the intent of this section to claim rights or
+     contest your rights to work written entirely by you; rather, the
+     intent is to exercise the right to control the distribution of
+     derivative or collective works based on the Library.
+
+     In addition, mere aggregation of another work not based on the
+     Library with the Library (or with a work based on the Library) on
+     a volume of a storage or distribution medium does not bring the
+     other work under the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+     License instead of this License to a given copy of the Library.
+     To do this, you must alter all the notices that refer to this
+     License, so that they refer to the ordinary GNU General Public
+     License, version 2, instead of to this License.  (If a newer
+     version than version 2 of the ordinary GNU General Public License
+     has appeared, then you can specify that version instead if you
+     wish.)  Do not make any other change in these notices.
+
+     Once this change is made in a given copy, it is irreversible for
+     that copy, so the ordinary GNU General Public License applies to
+     all subsequent copies and derivative works made from that copy.
+
+     This option is useful when you wish to copy part of the code of
+     the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+     derivative of it, under Section 2) in object code or executable
+     form under the terms of Sections 1 and 2 above provided that you
+     accompany it with the complete corresponding machine-readable
+     source code, which must be distributed under the terms of Sections
+     1 and 2 above on a medium customarily used for software
+     interchange.
+
+     If distribution of object code is made by offering access to copy
+     from a designated place, then offering equivalent access to copy
+     the source code from the same place satisfies the requirement to
+     distribute the source code, even though third parties are not
+     compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+     Library, but is designed to work with the Library by being
+     compiled or linked with it, is called a "work that uses the
+     Library".  Such a work, in isolation, is not a derivative work of
+     the Library, and therefore falls outside the scope of this License.
+
+     However, linking a "work that uses the Library" with the Library
+     creates an executable that is a derivative of the Library (because
+     it contains portions of the Library), rather than a "work that
+     uses the library".  The executable is therefore covered by this
+     License.  Section 6 states terms for distribution of such
+     executables.
+
+     When a "work that uses the Library" uses material from a header
+     file that is part of the Library, the object code for the work may
+     be a derivative work of the Library even though the source code is
+     not.  Whether this is true is especially significant if the work
+     can be linked without the Library, or if the work is itself a
+     library.  The threshold for this to be true is not precisely
+     defined by law.
+
+     If such an object file uses only numerical parameters, data
+     structure layouts and accessors, and small macros and small inline
+     functions (ten lines or less in length), then the use of the object
+     file is unrestricted, regardless of whether it is legally a
+     derivative work.  (Executables containing this object code plus
+     portions of the Library will still fall under Section 6.)
+
+     Otherwise, if the work is a derivative of the Library, you may
+     distribute the object code for the work under the terms of Section
+     6.  Any executables containing that work also fall under Section 6,
+     whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+     link a "work that uses the Library" with the Library to produce a
+     work containing portions of the Library, and distribute that work
+     under terms of your choice, provided that the terms permit
+     modification of the work for the customer's own use and reverse
+     engineering for debugging such modifications.
+
+     You must give prominent notice with each copy of the work that the
+     Library is used in it and that the Library and its use are covered
+     by this License.  You must supply a copy of this License.  If the
+     work during execution displays copyright notices, you must include
+     the copyright notice for the Library among them, as well as a
+     reference directing the user to the copy of this License.  Also,
+     you must do one of these things:
+
+       a. Accompany the work with the complete corresponding
+          machine-readable source code for the Library including
+          whatever changes were used in the work (which must be
+          distributed under Sections 1 and 2 above); and, if the work
+          is an executable linked with the Library, with the complete
+          machine-readable "work that uses the Library", as object code
+          and/or source code, so that the user can modify the Library
+          and then relink to produce a modified executable containing
+          the modified Library.  (It is understood that the user who
+          changes the contents of definitions files in the Library will
+          not necessarily be able to recompile the application to use
+          the modified definitions.)
+
+       b. Accompany the work with a written offer, valid for at least
+          three years, to give the same user the materials specified in
+          Subsection 6a, above, for a charge no more than the cost of
+          performing this distribution.
+
+       c. If distribution of the work is made by offering access to copy
+          from a designated place, offer equivalent access to copy the
+          above specified materials from the same place.
+
+       d. Verify that the user has already received a copy of these
+          materials or that you have already sent this user a copy.
+
+     For an executable, the required form of the "work that uses the
+     Library" must include any data and utility programs needed for
+     reproducing the executable from it.  However, as a special
+     exception, the source code distributed need not include anything
+     that is normally distributed (in either source or binary form)
+     with the major components (compiler, kernel, and so on) of the
+     operating system on which the executable runs, unless that
+     component itself accompanies the executable.
+
+     It may happen that this requirement contradicts the license
+     restrictions of other proprietary libraries that do not normally
+     accompany the operating system.  Such a contradiction means you
+     cannot use both them and the Library together in an executable
+     that you distribute.
+
+  7. You may place library facilities that are a work based on the
+     Library side-by-side in a single library together with other
+     library facilities not covered by this License, and distribute
+     such a combined library, provided that the separate distribution
+     of the work based on the Library and of the other library
+     facilities is otherwise permitted, and provided that you do these
+     two things:
+
+       a. Accompany the combined library with a copy of the same work
+          based on the Library, uncombined with any other library
+          facilities.  This must be distributed under the terms of the
+          Sections above.
+
+       b. Give prominent notice with the combined library of the fact
+          that part of it is a work based on the Library, and explaining
+          where to find the accompanying uncombined form of the same
+          work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute the
+     Library except as expressly provided under this License.  Any
+     attempt otherwise to copy, modify, sublicense, link with, or
+     distribute the Library is void, and will automatically terminate
+     your rights under this License.  However, parties who have
+     received copies, or rights, from you under this License will not
+     have their licenses terminated so long as such parties remain in
+     full compliance.
+
+  9. You are not required to accept this License, since you have not
+     signed it.  However, nothing else grants you permission to modify
+     or distribute the Library or its derivative works.  These actions
+     are prohibited by law if you do not accept this License.
+     Therefore, by modifying or distributing the Library (or any work
+     based on the Library), you indicate your acceptance of this
+     License to do so, and all its terms and conditions for copying,
+     distributing or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+     Library), the recipient automatically receives a license from the
+     original licensor to copy, distribute, link with or modify the
+     Library subject to these terms and conditions.  You may not impose
+     any further restrictions on the recipients' exercise of the rights
+     granted herein.  You are not responsible for enforcing compliance
+     by third parties to this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+     infringement or for any other reason (not limited to patent
+     issues), conditions are imposed on you (whether by court order,
+     agreement or otherwise) that contradict the conditions of this
+     License, they do not excuse you from the conditions of this
+     License.  If you cannot distribute so as to satisfy simultaneously
+     your obligations under this License and any other pertinent
+     obligations, then as a consequence you may not distribute the
+     Library at all.  For example, if a patent license would not permit
+     royalty-free redistribution of the Library by all those who
+     receive copies directly or indirectly through you, then the only
+     way you could satisfy both it and this License would be to refrain
+     entirely from distribution of the Library.
+
+     If any portion of this section is held invalid or unenforceable
+     under any particular circumstance, the balance of the section is
+     intended to apply, and the section as a whole is intended to apply
+     in other circumstances.
+
+     It is not the purpose of this section to induce you to infringe any
+     patents or other property right claims or to contest validity of
+     any such claims; this section has the sole purpose of protecting
+     the integrity of the free software distribution system which is
+     implemented by public license practices.  Many people have made
+     generous contributions to the wide range of software distributed
+     through that system in reliance on consistent application of that
+     system; it is up to the author/donor to decide if he or she is
+     willing to distribute software through any other system and a
+     licensee cannot impose that choice.
+
+     This section is intended to make thoroughly clear what is believed
+     to be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+     certain countries either by patents or by copyrighted interfaces,
+     the original copyright holder who places the Library under this
+     License may add an explicit geographical distribution limitation
+     excluding those countries, so that distribution is permitted only
+     in or among countries not thus excluded.  In such case, this
+     License incorporates the limitation as if written in the body of
+     this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+     versions of the Library General Public License from time to time.
+     Such new versions will be similar in spirit to the present version,
+     but may differ in detail to address new problems or concerns.
+
+     Each version is given a distinguishing version number.  If the
+     Library specifies a version number of this License which applies
+     to it and "any later version", you have the option of following
+     the terms and conditions either of that version or of any later
+     version published by the Free Software Foundation.  If the Library
+     does not specify a license version number, you may choose any
+     version ever published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+     programs whose distribution conditions are incompatible with these,
+     write to the author to ask for permission.  For software which is
+     copyrighted by the Free Software Foundation, write to the Free
+     Software Foundation; we sometimes make exceptions for this.  Our
+     decision will be guided by the two goals of preserving the free
+     status of all derivatives of our free software and of promoting
+     the sharing and reuse of software generally.
+
+                                NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+     WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE
+     LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+     HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT
+     WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
+     NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+     FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE
+     QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU.  SHOULD THE
+     LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
+     SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
+     MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+     LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
+     INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+     INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
+     DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
+     OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY
+     OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+     ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+                      END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Libraries
+==============================================
+
+   If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of
+the ordinary General Public License).
+
+   To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should have
+at least the "copyright" line and a pointer to where the full notice is
+found.
+
+     ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES.
+     Copyright (C) YEAR  NAME OF AUTHOR
+     
+     This 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.
+     
+     This 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 General Public License along
+     with this program; if not, write to the Free Software Foundation, Inc.,
+     59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+   Also add information on how to contact you by electronic and paper
+mail.
+
+   You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary.  Here is a sample; alter the names:
+
+     Yoyodyne, Inc., hereby disclaims all copyright interest in the library
+     `Frob' (a library for tweaking knobs) written by James Random Hacker.
+     
+     SIGNATURE OF TY COON, 1 April 1990
+     Ty Coon, President of Vice
+
+   That's all there is to it!
+
diff --git a/linuxthreads/Makeconfig b/linuxthreads/Makeconfig
new file mode 100644
index 0000000000..5470c22b97
--- /dev/null
+++ b/linuxthreads/Makeconfig
@@ -0,0 +1,11 @@
+# Makeconfig fragment for linuxthreads add-on.
+# This gets included at the end of the main glibc Makeconfig.
+
+have-thread-library = yes
+
+shared-thread-library = $(common-objpfx)linuxthreads/libpthread_nonshared.a \
+			$(common-objpfx)linuxthreads/libpthread.so
+static-thread-library = $(common-objpfx)linuxthreads/libpthread.a
+bounded-thread-library = $(common-objpfx)linuxthreads/libpthread_b.a
+
+rpath-dirs += linuxthreads
diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile
new file mode 100644
index 0000000000..3f06c41276
--- /dev/null
+++ b/linuxthreads/Makefile
@@ -0,0 +1,345 @@
+# Copyright (C) 1996-2003, 2004 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.
+
+#
+#	Sub-makefile for linuxthreads portion of the library.
+#
+subdir	:= linuxthreads
+
+all: # Make this the default target; it will be defined in Rules.
+
+linuxthreads-version := $(shell sed -n 's/^.*$(subdir)-\([0-9.]*\).*$$/\1/p' \
+				    Banner)
+libpthread-abi-frozen := GLIBC_2.3.2
+
+headers := pthread.h semaphore.h
+distribute := internals.h queue.h restart.h spinlock.h smp.h tst-signal.sh \
+	      tst-cancel-wrappers.sh libc-tsd.c
+
+routines := forward alloca_cutoff libc-cancellation libc_pthread_init
+shared-only-routines = forward
+
+extra-libs := libpthread
+extra-libs-others := $(extra-libs)
+install-lib-ldscripts := libpthread.so
+
+libpthread-routines := attr cancel condvar join manager mutex ptfork \
+		       ptlongjmp pthread pt-sigsuspend signals specific errno \
+		       lockfile semaphore spinlock rwlock pt-machine \
+		       oldsemaphore events getcpuclockid pspinlock barrier \
+		       ptclock_gettime ptclock_settime sighandler \
+		       pthandles libc-tls-loc pt-allocrtsig \
+		       ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \
+		       ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg \
+		       ptw-send ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek \
+		       ptw-lseek64 ptw-llseek ptw-msync ptw-nanosleep \
+		       ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \
+		       ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \
+		       ptw-waitpid pt-system old_pthread_atfork pthread_atfork \
+		       ptcleanup
+#		       pthread_setuid pthread_seteuid pthread_setreuid \
+#		       pthread_setresuid \
+#		       pthread_setgid pthread_setegid pthread_setregid \
+#		       pthread_setresgid
+
+# Don't generate deps for calls with no sources.  See sysdeps/unix/Makefile.
+omit-deps = $(unix-syscalls:%=ptw-%)
+
+libpthread-shared-only-routines = pt-allocrtsig
+libpthread-static-only-routines = pthread_atfork
+
+linuxthreads-CPPFLAGS = -DIS_IN_linuxthreads=1
+
+CFLAGS-pthread_atfork.c = -DNOT_IN_libc
+
+nodelete-yes = -Wl,--enable-new-dtags,-z,nodelete
+initfirst-yes = -Wl,--enable-new-dtags,-z,initfirst
+LDFLAGS-pthread.so = $(nodelete-$(have-z-nodelete)) \
+		     $(initfirst-$(have-z-initfirst))
+
+vpath %.c Examples
+
+tst-cancel-ARGS = "$(objpfx)"
+CFLAGS-tst-cancel.c = -fno-inline -fno-inline-functions
+
+include ../Makeconfig
+
+ifeq ($(build-shared),yes)
+
+# Set the `multidir' variable by grabbing the variable from the compiler.
+# We do it once and save the result in a generated makefile.
+-include $(objpfx)multidir.mk
+$(objpfx)multidir.mk: $(common-objpfx)config.make
+	$(make-target-directory)
+	dir=`$(CC) $(CFLAGS) $(CPPFLAGS) -print-multi-directory`; \
+	echo "multidir := $$dir" > $@T
+	mv -f $@T $@
+generated += multidir.mk
+
+crti-objs := crti.o
+crtn-objs := crtn.o
+ifneq (,$(patsubst .,,$(multidir)))
+generated-dirs := $(firstword $(subst /, , $(multidir)))
+crti-objs += $(multidir)/crti.o
+crtn-objs += $(multidir)/crtn.o
+omit-deps += $(multidir)/crti $(multidir)/crtn
+endif
+extra-objs += $(crti-objs) $(crtn-objs)
+omit-deps += crti crtn
+
+CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions $(fno-unit-at-a-time)
+endif
+
+librt-tests = ex10 ex11 tst-clock1
+tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 $(librt-tests) ex12 ex13 joinrace \
+	tststack $(tests-nodelete-$(have-z-nodelete)) ecmutex ex14 ex15 ex16 \
+	ex17 ex18 tst-cancel tst-context bug-sleep \
+	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
+	tst-cancel6 tst-cancel7 tst-cancel8 tst-popen tst-popen2 tst-attr1 \
+	tst-stack1
+test-srcs = tst-signal
+# These tests are linked with libc before libpthread
+tests-reverse += tst-cancel5
+
+ifeq ($(build-static),yes)
+tests += tststatic tst-static-locale tst-cancel-static
+tests-static += tststatic tst-static-locale tst-cancel-static
+endif
+
+ifeq (yes,$(build-shared))
+tests-nodelete-yes = unload
+tests += tst-tls1 tst-_res1
+endif
+
+modules-names = tst-_res1mod1 tst-_res1mod2 \
+		tst-tls1mod tst-tls1moda tst-tls1modb tst-tls1modc \
+		tst-tls1modd tst-tls1mode tst-tls1modf
+extra-objs += $(addsuffix .os,$(strip $(modules-names)))
+generated += $(addsuffix .so,$(strip $(modules-names)))
+test-extras += $(modules-names)
+test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
+
+tst-tls1mod.so-no-z-defs = yes
+tst-tls1moda.so-no-z-defs = yes
+tst-tls1modb.so-no-z-defs = yes
+tst-tls1modc.so-no-z-defs = yes
+tst-tls1modd.so-no-z-defs = yes
+tst-tls1mode.so-no-z-defs = yes
+tst-tls1modf.so-no-z-defs = yes
+
+$(test-modules): $(objpfx)%.so: $(objpfx)%.os $(common-objpfx)shlib.lds
+	$(build-module)
+
+ifeq ($(build-shared),yes)
+# Build all the modules even when not actually running test programs.
+tests: $(test-modules)
+endif
+
+# What we install as libpthread.so for programs to link against is in fact a
+# link script.  It contains references for the various libraries we need.
+# The libpthread.so object is not complete since some functions are only defined
+# in libpthread_nonshared.a.
+# We need to use absolute paths since otherwise local copies (if they exist)
+# of the files are taken by the linker.
+install: $(inst_libdir)/libpthread.so
+$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
+			      $(objpfx)libpthread.so$(libpthread.so-version) \
+			      $(inst_libdir)/$(patsubst %,$(libtype.oS),\
+							$(libprefix)pthread) \
+			      $(+force)
+	(echo '/* GNU ld script';\
+	 echo '   Use the shared library, but some functions are only in';\
+	 echo '   the static library, so try that secondarily.  */';\
+	 cat $<; \
+	 echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \
+	      '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\
+	      ')' \
+	) > $@.new
+	mv -f $@.new $@
+
+
+extra-B-pthread.so = -B$(common-objpfx)linuxthreads/
+$(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs))
+$(objpfx)libpthread.so: +preinit += $(addprefix $(objpfx),$(crti-objs))
+$(objpfx)libpthread.so: +postinit += $(addprefix $(objpfx),$(crtn-objs))
+
+znodelete-yes = -DHAVE_Z_NODELETE
+CFLAGS-mutex.c += -D__NO_WEAK_PTHREAD_ALIASES
+CFLAGS-specific.c += -D__NO_WEAK_PTHREAD_ALIASES
+CFLAGS-pthread.c += -D__NO_WEAK_PTHREAD_ALIASES $(znodelete-$(have-z-nodelete))
+CFLAGS-ptfork.c += -D__NO_WEAK_PTHREAD_ALIASES
+CFLAGS-cancel.c += -D__NO_WEAK_PTHREAD_ALIASES -D_RPC_THREAD_SAFE_
+CFLAGS-unload.c += -DPREFIX=\"$(objpfx)\"
+CFLAGS-mutex.c += $(uses-callbacks)
+CFLAGS-sighandler.c += $(uses-callbacks)
+
+ifeq (yes,$(versioning))
+-include $(common-objpfx)tls.make
+libc-ok-for-link = $(use-thread)
+else
+libc-ok-for-link = yes
+endif
+
+ifeq (no,$(libc-ok-for-link))
+# These hacks are necessary to let us link against a libc.so that exports
+# the symbols _errno, _h_errno, and _res.  Those symbols are accessible
+# in libc at runtime (dynamic linkable), but are not exported at link time
+# so that applications cannot link against them.  However, libpthread.so
+# needs to link against them for its __errno_location et al functions to
+# find the locations that libc's symbols resolve to.  We cannot do this
+# with aliases in libc.so(GLIBC_PRIVATE), because we need to refer to an
+# executable's symbols when it defines them with copy relocs.
+libc-link.so = $(objpfx)libc.so
+
+$(objpfx)libc_pic_lite.a: $(common-objpfx)libc_pic.a
+	cp $< $@T
+	$(AR) d $@T errno.os herrno.os res_libc.os
+	mv -f $@T $@
+
+extra-objs += libc-tsd.os
+$(objpfx)libc_pic_lite.os: $(objpfx)libc_pic_lite.a $(objpfx)libc-tsd.os
+	$(LINK.o) -nostdlib -nostartfiles -r -o $@ \
+		  $(LDFLAGS-c_pic.os) -Wl,-d -Wl,--whole-archive $^
+
+# This trick leaves errno and h_errno undefined.
+libc.so-no-z-defs = yes
+
+$(objpfx)libc.so: $(elfobjdir)/soinit.os \
+		  $(objpfx)libc_pic_lite.os \
+		  $(elfobjdir)/sofini.os \
+		  $(elfobjdir)/interp.os $(elfobjdir)/ld.so
+	$(build-shlib)
+
+generated += libc_pic_lite.a libc_pic_lite.os libc.so libc-tsd.os
+else
+libc-link.so = $(common-objpfx)libc.so
+endif
+
+include ../Rules
+
+# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
+# This ensures they will load libc.so for needed symbols if loaded by
+# a statically-linked program that hasn't already loaded it.
+# Depend on ld.so too to get proper versions of ld.so symbols.
+$(objpfx)libpthread.so: $(libc-link.so) $(common-objpfx)libc_nonshared.a \
+			$(if $(filter yes,$(elf)), $(elfobjdir)/ld.so)
+
+# Make sure we link with the thread library.
+ifeq ($(build-shared),yes)
+$(addprefix $(objpfx), \
+  $(filter-out $(tests-static) $(tests-reverse) unload, \
+    $(tests) $(test-srcs))): $(objpfx)libpthread.so \
+			     $(objpfx)libpthread_nonshared.a
+# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# since otherwise libpthread.so comes before libc.so when linking.
+$(addprefix $(objpfx), $(tests-reverse)): \
+  $(objpfx)../libc.so $(objpfx)libpthread.so \
+  $(objpfx)libpthread_nonshared.a
+$(objpfx)../libc.so: $(common-objpfx)libc.so ;
+$(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.so
+$(objpfx)unload: $(common-objpfx)dlfcn/libdl.so
+$(objpfx)unload.out: $(objpfx)libpthread.so $(objpfx)libpthread_nonshared.a
+else
+$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
+$(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.a
+endif
+ifeq ($(build-bounded),yes)
+$(tests:%=$(objpfx)%-bp): $(objpfx)libpthread_b.a
+$(librt-tests:%=$(objpfx)%-bp): $(common-objpfx)rt/librt_b.a
+endif
+
+ifeq ($(build-static),yes)
+$(addprefix $(objpfx), $(tests-static)): $(objpfx)libpthread.a
+endif
+
+ifeq ($(build-shared),yes)
+vpath pt-initfini.c $(full_config_sysdirs)
+
+$(objpfx)pt-initfini.s: pt-initfini.c
+	$(compile.c) -S $(CFLAGS-pt-initfini.s) -finhibit-size-directive \
+		$(patsubst -f%,-fno-%,$(exceptions)) -o $@
+
+# We only have one kind of startup code files.  Static binaries and
+# shared libraries are build using the PIC version.
+$(objpfx)crti.S: $(objpfx)pt-initfini.s
+	sed -n -e '1,/@HEADER_ENDS/p' \
+	       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
+	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
+$(objpfx)crtn.S: $(objpfx)pt-initfini.s
+	sed -n -e '1,/@HEADER_ENDS/p' \
+	       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
+	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
+
+$(objpfx)defs.h: $(objpfx)pt-initfini.s
+	sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \
+		$(AWK) -f ../csu/defs.awk > $@
+
+$(objpfx)crti.o: $(objpfx)crti.S $(objpfx)defs.h
+	$(compile.S) -g0 $(ASFLAGS-.os) -o $@
+
+$(objpfx)crtn.o: $(objpfx)crtn.S $(objpfx)defs.h
+	$(compile.S) -g0 $(ASFLAGS-.os) -o $@
+
+ifneq ($(multidir),.)
+$(objpfx)$(multidir):
+	@mkdir -p $(objpfx)$(multidir)
+
+$(objpfx)$(multidir)/crti.o: $(objpfx)crti.o $(objpfx)$(multidir)
+	ln -f $< $@
+
+$(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)
+	ln -f $< $@
+endif
+
+generated += crti.S crtn.S defs.h pt-initfini.s libpthread_nonshared.a
+endif
+
+ifeq (yes,$(build-static-nss))
+otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \
+             $(resolvobjdir)/libresolv.a
+endif
+
+ifeq (yes,$(build-shared))
+$(objpfx)tst-_res1mod2.so: $(objpfx)tst-_res1mod1.so
+$(objpfx)tst-_res1: $(objpfx)tst-_res1mod2.so $(shared-thread-library)
+
+$(objpfx)tst-tls1: $(objpfx)tst-tls1mod.so $(shared-thread-library)
+
+tests: $(objpfx)tst-tls2.out
+$(objpfx)tst-tls2.out: tst-tls2.sh $(objpfx)tst-tls1 \
+		       $(objpfx)tst-tls1moda.so $(objpfx)tst-tls1modb.so \
+		       $(objpfx)tst-tls1modc.so $(objpfx)tst-tls1modd.so \
+		       $(objpfx)tst-tls1mode.so $(objpfx)tst-tls1modf.so
+	$(SHELL) -e tst-tls2.sh $(common-objpfx) $(elf-objpfx) \
+		    $(rtld-installed-name)
+generated += tst-tls2.out
+endif
+
+ifeq (no,$(cross-compiling))
+ifeq (yes,$(build-shared))
+tests: $(objpfx)tst-signal.out $(objpfx)tst-cancel-wrappers.out
+$(objpfx)tst-signal.out: tst-signal.sh $(objpfx)tst-signal
+	$(SHELL) -e $< $(common-objpfx) > $@
+$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
+	$(SHELL) $< $(common-objpfx)/libc_pic.a \
+		    $(common-objpfx)/libc.a \
+		    $(objpfx)/libpthread_pic.a \
+		    $(objpfx)/libpthread.a > $@
+generated += tst-signal.out tst-cancel-wrappers.out
+endif
+endif
diff --git a/linuxthreads/README b/linuxthreads/README
new file mode 100644
index 0000000000..955bd59e7a
--- /dev/null
+++ b/linuxthreads/README
@@ -0,0 +1,166 @@
+        Linuxthreads - POSIX 1003.1c kernel threads for Linux
+
+      Copyright 1996, 1997 Xavier Leroy (Xavier.Leroy@inria.fr)
+
+
+DESCRIPTION:
+
+This is release 0.7 (late beta) of LinuxThreads, a BiCapitalized
+implementation of the Posix 1003.1c "pthread" interface for Linux.
+
+LinuxThreads provides kernel-level threads: each thread is a separate
+Unix process, sharing its address space with the other threads through
+the new system call clone(). Scheduling between threads is handled by
+the kernel scheduler, just like scheduling between Unix processes.
+
+
+REQUIREMENTS:
+
+- Linux version 2.0 and up (requires the new clone() system call
+  and the new realtime scheduler).
+
+- For Intel platforms: libc 5.2.18 or later is required.
+  5.2.18 or 5.4.12 or later are recommended;
+  5.3.12 and 5.4.7 have problems (see the FAQ.html file for more info).
+
+- Also supports glibc 2 (a.k.a. libc 6), which actually comes with
+  a specially-adapted version of this library.
+
+- Currently supports Intel, Alpha, Sparc, Motorola 68k, ARM and MIPS
+  platforms.
+
+- Multiprocessors are supported.
+
+
+INSTALLATION:
+
+- Edit the Makefile, set the variables in the "Configuration" section.
+
+- Do "make".
+
+- Do "make install".
+
+
+USING LINUXTHREADS:
+
+        gcc -D_REENTRANT ... -lpthread
+
+A complete set of manual pages is included. Also see the subdirectory
+Examples/ for some sample programs.
+
+
+STATUS:
+
+- All functions in the Posix 1003.1c base interface implemented.
+  Also supports priority scheduling.
+
+- For users of libc 5 (H.J.Lu's libc), a number of C library functions
+  are reimplemented or wrapped to make them thread-safe, including:
+  * malloc functions
+  * stdio functions (define _REENTRANT before including <stdio.h>)
+  * per-thread errno variable (define _REENTRANT before including <errno.h>)
+  * directory reading functions (opendir(), etc)
+  * sleep()
+  * gmtime(), localtime()
+
+  New library functions provided:
+  * flockfile(), funlockfile(), ftrylockfile()
+  * reentrant versions of network database functions (gethostbyname_r(), etc)
+    and password functions (getpwnam_r(), etc).
+
+- libc 6 (glibc 2) provides much better thread support than libc 5,
+  and comes with a specially-adapted version of LinuxThreads.
+  For serious multithreaded programming, you should consider switching
+  to glibc 2. It is available from ftp.gnu.org:/pub/gnu and its mirrors.
+
+
+WARNING:
+
+Many existing libraries are not compatible with LinuxThreads,
+either because they are not inherently thread-safe, or because they
+have not been compiled with the -D_REENTRANT.  For more info, see the
+FAQ.html file in this directory.
+
+A prime example of the latter is Xlib. If you link it with
+LinuxThreads, you'll probably get an "unknown 0 error" very
+early. This is just a consequence of the Xlib binaries using the
+global variable "errno" to fetch error codes, while LinuxThreads and
+the C library use the per-thread "errno" location.
+
+See the file README.Xfree3.3 for info on how to compile the Xfree 3.3
+libraries to make them compatible with LinuxThreads.
+
+
+KNOWN BUGS AND LIMITATIONS:
+
+- Threads share pretty much everything they should share according
+  to the standard: memory space, file descriptors, signal handlers,
+  current working directory, etc. One thing that they do not share
+  is their pid's and parent pid's. According to the standard, they
+  should have the same, but that's one thing we cannot achieve
+  in this implementation (until the CLONE_PID flag to clone() becomes
+  usable).
+
+- The current implementation uses the two signals SIGUSR1 and SIGUSR2,
+  so user-level code cannot employ them. Ideally, there should be two
+  signals reserved for this library. One signal is used for restarting
+  threads blocked on mutexes or conditions; the other is for thread
+  cancellation.
+
+  *** This is not anymore true when the application runs on a kernel
+      newer than approximately 2.1.60.
+
+- The stacks for the threads are allocated high in the memory space,
+  below the stack of the initial process, and spaced 2M apart.
+  Stacks are allocated with the "grow on demand" flag, so they don't
+  use much virtual space initially (4k, currently), but can grow
+  up to 2M if needed.
+
+  Reserving such a large address space for each thread means that,
+  on a 32-bit architecture, no more than about 1000 threads can
+  coexist (assuming a 2Gb address space for user processes),
+  but this is reasonable, since each thread uses up one entry in the
+  kernel's process table, which is usually limited to 512 processes.
+
+  Another potential problem of the "grow on demand" scheme is that
+  nothing prevents the user from mmap'ing something in the 2M address
+  window reserved for a thread stack, possibly causing later extensions of
+  that stack to fail. Mapping at fixed addresses should be avoided
+  when using this library.
+
+- Signal handling does not fully conform to the Posix standard,
+  due to the fact that threads are here distinct processes that can be
+  sent signals individually, so there's no notion of sending a signal
+  to "the" process (the collection of all threads).
+  More precisely, here is a summary of the standard requirements
+  and how they are met by the implementation:
+
+  1- Synchronous signals (generated by the thread execution, e.g. SIGFPE)
+     are delivered to the thread that raised them.
+     (OK.)
+
+  2- A fatal asynchronous signal terminates all threads in the process.
+     (OK. The thread manager notices when a thread dies on a signal
+      and kills all other threads with the same signal.)
+
+  3- An asynchronous signal will be delivered to one of the threads
+     of the program which does not block the signal (it is unspecified
+     which).
+     (No, the signal is delivered to the thread it's been sent to,
+      based on the pid of the thread. If that thread is currently
+      blocking the signal, the signal remains pending.)
+
+  4- The signal will be delivered to at most one thread.
+     (OK, except for signals generated from the terminal or sent to
+      the process group, which will be delivered to all threads.)
+
+- The current implementation of the MIPS support assumes a MIPS ISA II
+  processor or better.  These processors support atomic operations by
+  ll/sc instructions.  Older R2000/R3000 series processors are not
+  supported yet; support for these will have higher overhead.
+
+- The current implementation of the ARM support assumes that the SWP
+  (atomic swap register with memory) instruction is available.  This is
+  the case for all processors except for the ARM1 and ARM2.  On StrongARM,
+  the SWP instruction does not bypass the cache, so multi-processor support
+  will be more troublesome.
diff --git a/linuxthreads/README.Xfree3.2 b/linuxthreads/README.Xfree3.2
new file mode 100644
index 0000000000..ac08e15832
--- /dev/null
+++ b/linuxthreads/README.Xfree3.2
@@ -0,0 +1,352 @@
+This file describes how to make a threaded X11R6.
+
+You need the source-code of XFree-3.2. I used the sources of X11R6.1
+(files: xc-1.tar.gz xc-2.tar.gz xc-3.tar.gz) and the patches to
+XFree-3.2 (files: README.X11.patch R6.1pl1-3.2.diff.gz cfont32.tgz).
+
+Untar the xc-?.tar.gz files in a directory called XF3.2 and apply
+the XFree-3.2 patches as described in README.X11.patch or use the
+whole XFree86 source.
+
+Now apply the thread patch with
+
+patch -p0 < XF3.2.xc.diff
+
+Go to the XF3.2/xc directory and make the whole thing:
+nice make World >& world.log &
+tail -f world.log
+
+Wait a few hours or interrupt the process after the shared libs
+are made. The shared libs are:
+
+XF3.2/xc/lib/ICE/libICE.so.6.0*
+XF3.2/xc/lib/PEX5/libPEX5.so.6.0*
+XF3.2/xc/lib/SM/libSM.so.6.0*
+XF3.2/xc/lib/X11/libX11.so.6.1*
+XF3.2/xc/lib/XIE/libXIE.so.6.0*
+XF3.2/xc/lib/XThrStub/libXThrStub.so.6.0*
+XF3.2/xc/lib/Xaw/libXaw.so.6.1*
+XF3.2/xc/lib/Xext/libXext.so.6.1*
+XF3.2/xc/lib/Xi/libXi.so.6.0*
+XF3.2/xc/lib/Xmu/libXmu.so.6.0*
+XF3.2/xc/lib/Xt/libXt.so.6.0*
+XF3.2/xc/lib/Xtst/libXtst.so.6.1*
+
+(The Program dga didn't compile, but I have not check out why.)
+
+Now you can copy the resulting libs   
+
+cp XF3.2/xc/lib/*/*.so.?.? /usr/X11R6/lib/
+
+and create some links
+
+cd /usr/X11R6/lib/
+ln -s libXThrStub.so.6.0 libXThrStub.so.6
+ln -s libXThrStub.so.6 libXThrStub.so
+
+or use make install (not tested, and needs new configuration).
+
+It is possible with the libXThrSub to compile X11 programs without linking
+libpthread to them and not necessary to recompile already installed
+unthreaded X11 programs, because libXThrSub keeps the dynamic linker quit.
+On the other hand you can link libpthread to a X11 program to use threads.
+
+I used linux 2.0.23 and libc 5.4.7 .
+
+Hans-Helmut Bühmann     hans@expmech.ing.tu-bs.de
+
+----------------------------------------------------------------------------
+
+XF3.2.xc.diff:
+-----------------------------------------------------------------------------
+diff -u --recursive XF3.2.orig/xc/config/cf/linux.cf XF3.2/xc/config/cf/linux.cf
+--- XF3.2.orig/xc/config/cf/linux.cf	Sun Nov 10 17:05:30 1996
++++ XF3.2/xc/config/cf/linux.cf	Sun Nov 10 16:30:55 1996
+@@ -61,6 +61,14 @@
+ #define HasSnprintf		YES
+ #endif
+ 
++#define HasPosixThreads         YES
++#define ThreadedX               YES
++#define BuildThreadStubLibrary	YES
++#define NeedUIThrStubs		YES
++#define HasThreadSafeAPI        NO
++#define SystemMTDefines         -D_REENTRANT
++#define ThreadsLibraries        -lpthread
++
+ #define AvoidNullMakeCommand	YES
+ #define StripInstalledPrograms	YES
+ #define CompressAllFonts	YES
+@@ -158,7 +166,7 @@
+ #define LdPostLib		/* Never needed */
+ 
+ #ifdef i386Architecture
+-#define OptimizedCDebugFlags	DefaultGcc2i386Opt -m486
++#define OptimizedCDebugFlags	DefaultGcc2i386Opt -m486 -pipe
+ #define StandardDefines		-Dlinux -D__i386__ -D_POSIX_SOURCE \
+ 				-D_BSD_SOURCE -D_SVID_SOURCE -DX_LOCALE
+ #define XawI18nDefines		-DUSE_XWCHAR_STRING -DUSE_XMBTOWC
+diff -u --recursive XF3.2.orig/xc/config/cf/lnxLib.tmpl XF3.2/xc/config/cf/lnxLib.tmpl
+--- XF3.2.orig/xc/config/cf/lnxLib.tmpl	Sun Nov 10 17:05:30 1996
++++ XF3.2/xc/config/cf/lnxLib.tmpl	Sat Nov  9 14:52:39 1996
+@@ -19,7 +19,7 @@
+ 
+ #define CplusplusLibC
+ 
+-#define SharedX11Reqs
++#define SharedX11Reqs  	-L$(BUILDLIBDIR) -lXThrStub 
+ #define SharedOldXReqs	$(LDPRELIB) $(XLIBONLY)
+ #define SharedXtReqs	$(LDPRELIB) $(XLIBONLY) $(SMLIB) $(ICELIB)
+ #define SharedXawReqs	$(LDPRELIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
+diff -u --recursive XF3.2.orig/xc/include/Xthreads.h XF3.2/xc/include/Xthreads.h
+--- XF3.2.orig/xc/include/Xthreads.h	Thu Dec  7 02:19:09 1995
++++ XF3.2/xc/include/Xthreads.h	Sat Nov  9 01:04:55 1996
+@@ -229,12 +229,12 @@
+ #define xcondition_wait(c,m) pthread_cond_wait(c,m)
+ #define xcondition_signal(c) pthread_cond_signal(c)
+ #define xcondition_broadcast(c) pthread_cond_broadcast(c)
+-#ifdef _DECTHREADS_
++#if defined(_DECTHREADS_) || defined(linux)
+ static xthread_t _X_no_thread_id;
+ #define xthread_have_id(id) !pthread_equal(id, _X_no_thread_id)
+ #define xthread_clear_id(id) id = _X_no_thread_id
+ #define xthread_equal(id1,id2) pthread_equal(id1, id2)
+-#endif /* _DECTHREADS_ */
++#endif /* _DECTHREADS_ || linux */
+ #if _CMA_VENDOR_ == _CMA__IBM
+ #ifdef DEBUG			/* too much of a hack to enable normally */
+ /* see also cma__obj_set_name() */
+diff -u --recursive XF3.2.orig/xc/lib/X11/util/makekeys.c XF3.2/xc/lib/X11/util/makekeys.c
+--- XF3.2.orig/xc/lib/X11/util/makekeys.c	Mon Apr 18 02:22:22 1994
++++ XF3.2/xc/lib/X11/util/makekeys.c	Sat Nov  9 00:44:14 1996
+@@ -73,7 +73,7 @@
+     register char c;
+     int first;
+     int best_max_rehash;
+-    int best_z;
++    int best_z = 0;
+     int num_found;
+     KeySym val;
+ 
+diff -u --recursive XF3.2.orig/xc/lib/XThrStub/Imakefile XF3.2/xc/lib/XThrStub/Imakefile
+--- XF3.2.orig/xc/lib/XThrStub/Imakefile	Sun Nov 10 17:08:12 1996
++++ XF3.2/xc/lib/XThrStub/Imakefile	Sat Nov  9 19:04:51 1996
+@@ -25,7 +25,7 @@
+       DEFINES = $(ALLOC_DEFINES)
+      INCLUDES = 
+          SRCS = $(STUBSRCS)
+-         OBJS = $(STUBOBJS
++         OBJS = $(STUBOBJS)
+      LINTLIBS = $(LINTXLIB)
+ 
+ #include <Library.tmpl>
+diff -u --recursive XF3.2.orig/xc/lib/XThrStub/UIThrStubs.c XF3.2/xc/lib/XThrStub/UIThrStubs.c
+--- XF3.2.orig/xc/lib/XThrStub/UIThrStubs.c	Sun Nov 10 17:08:12 1996
++++ XF3.2/xc/lib/XThrStub/UIThrStubs.c	Sun Nov 10 15:14:55 1996
+@@ -37,16 +37,43 @@
+  * specificies the thread library on the link line.
+  */
+ 
++#if defined(linux)
++#include <pthread.h>
++#else
+ #include <thread.h>
+ #include <synch.h>
++#endif
+ 
++#if defined(linux)
++static pthread_t no_thread_id;
++#endif /* defined(linux) */
++
++#if defined(linux)
++#pragma weak pthread_self = _Xthr_self_stub_
++pthread_t 
++_Xthr_self_stub_()
++{
++    return(no_thread_id);
++}
++#else /* defined(linux) */
+ #pragma weak thr_self = _Xthr_self_stub_
+ thread_t 
+ _Xthr_self_stub_()
+ {
+     return((thread_t)0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_mutex_init = _Xmutex_init_stub_
++int 
++_Xmutex_init_stub_(m, a)
++    pthread_mutex_t *m;
++    __const pthread_mutexattr_t *a;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak mutex_init = _Xmutex_init_stub_
+ int 
+ _Xmutex_init_stub_(m, t, a)
+@@ -56,7 +83,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_mutex_destroy = _Xmutex_destroy_stub_
++int
++_Xmutex_destroy_stub_(m)
++    pthread_mutex_t *m;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak mutex_destroy = _Xmutex_destroy_stub_
+ int
+ _Xmutex_destroy_stub_(m)
+@@ -64,7 +101,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_mutex_lock = _Xmutex_lock_stub_
++int
++_Xmutex_lock_stub_(m)
++    pthread_mutex_t *m;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak mutex_lock = _Xmutex_lock_stub_
+ int
+ _Xmutex_lock_stub_(m)
+@@ -72,7 +119,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_mutex_unlock = _Xmutex_unlock_stub_
++int
++_Xmutex_unlock_stub_(m)
++    pthread_mutex_t *m;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak mutex_unlock = _Xmutex_unlock_stub_
+ int
+ _Xmutex_unlock_stub_(m)
+@@ -80,7 +137,18 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak  pthread_cond_init = _Xcond_init_stub_
++int 
++_Xcond_init_stub_(c, a)
++    pthread_cond_t *c;
++    __const pthread_condattr_t *a;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak cond_init = _Xcond_init_stub_
+ int 
+ _Xcond_init_stub_(c, t, a)
+@@ -90,7 +158,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_cond_destroy = _Xcond_destroy_stub_
++int
++_Xcond_destroy_stub_(c)
++    pthread_cond_t *c;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak cond_destroy = _Xcond_destroy_stub_
+ int
+ _Xcond_destroy_stub_(c)
+@@ -98,7 +176,18 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_cond_wait = _Xcond_wait_stub_
++int
++_Xcond_wait_stub_(c,m)
++    pthread_cond_t *c;
++    pthread_mutex_t *m;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak cond_wait = _Xcond_wait_stub_
+ int
+ _Xcond_wait_stub_(c,m)
+@@ -107,7 +196,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_cond_signal = _Xcond_signal_stub_
++int
++_Xcond_signal_stub_(c)
++    pthread_cond_t *c;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak cond_signal = _Xcond_signal_stub_
+ int
+ _Xcond_signal_stub_(c)
+@@ -115,7 +214,17 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
+ 
++#if defined(linux)
++#pragma weak pthread_cond_broadcast = _Xcond_broadcast_stub_
++int
++_Xcond_broadcast_stub_(c)
++    pthread_cond_t *c;
++{
++    return(0);
++}
++#else /* defined(linux) */
+ #pragma weak cond_broadcast = _Xcond_broadcast_stub_
+ int
+ _Xcond_broadcast_stub_(c)
+@@ -123,3 +232,15 @@
+ {
+     return(0);
+ }
++#endif /* defined(linux) */
++
++#if defined(linux)
++#pragma weak pthread_equal = _Xthr_equal_stub_
++int
++_Xthr_equal_stub_(t1, t2)
++    pthread_t t1;
++    pthread_t t2;
++{
++    return(1);
++}
++#endif /* defined(linux) */
+-------------------------------------------------------------------------
diff --git a/linuxthreads/Versions b/linuxthreads/Versions
new file mode 100644
index 0000000000..615a132e54
--- /dev/null
+++ b/linuxthreads/Versions
@@ -0,0 +1,188 @@
+libc {
+  GLIBC_2.0 {
+    pthread_attr_destroy; pthread_attr_getdetachstate;
+    pthread_attr_getinheritsched; pthread_attr_getschedparam;
+    pthread_attr_getschedpolicy; pthread_attr_getscope; pthread_attr_init;
+    pthread_attr_setdetachstate; pthread_attr_setinheritsched;
+    pthread_attr_setschedparam; pthread_attr_setschedpolicy;
+    pthread_attr_setscope; pthread_cond_broadcast; pthread_cond_destroy;
+    pthread_cond_init; pthread_cond_signal; pthread_cond_wait;
+    pthread_cond_timedwait;
+    pthread_condattr_destroy; pthread_condattr_init; pthread_equal;
+    pthread_exit; pthread_getschedparam; pthread_mutex_destroy;
+    pthread_mutex_init; pthread_mutex_lock; pthread_mutex_unlock;
+    pthread_self; pthread_setcancelstate; pthread_setcanceltype;
+    pthread_setschedparam;
+  }
+  GLIBC_2.1 {
+    pthread_attr_init;
+  }
+  GLIBC_2.3.2 {
+    # Changed pthread_cond_t.
+    pthread_cond_init; pthread_cond_destroy;
+    pthread_cond_wait; pthread_cond_signal;
+    pthread_cond_broadcast; pthread_cond_timedwait;
+  }
+  GLIBC_PRIVATE {
+    # Internal libc interface to libpthread
+    __libc_dl_error_tsd;
+
+    __libc_pthread_init; __libc_current_sigrtmin_private;
+    __libc_current_sigrtmax_private; __libc_allocate_rtsig_private;
+
+    __libc_creat; __libc_poll; __libc_pselect; __libc_select;
+    __libc_sigpause; __libc_sigsuspend; __libc_sigwait; __libc_sigwaitinfo;
+    __libc_waitid; __libc___xpg_sigpause; __librt_enable_asynccancel;
+    __librt_disable_asynccancel; __librt_multiple_threads;
+
+    __libc_sigaction; __on_exit;
+  }
+}
+
+libpthread {
+  GLIBC_2.0 {
+    # Hidden entry point (through macros).
+    _pthread_cleanup_pop; _pthread_cleanup_pop_restore; _pthread_cleanup_push;
+    _pthread_cleanup_push_defer;
+
+    # Overwritten libc functions.
+    accept; close; connect; fcntl; fork; fsync; longjmp; lseek; msync;
+    nanosleep; open; pause; raise; read; recv; recvfrom; recvmsg; send;
+    sendmsg; sendto; sigaction; siglongjmp; system; tcdrain; wait;
+    waitpid; write;
+    __close; __connect; __fcntl; __lseek; __open; __read; __send; __wait;
+    __write;
+    _IO_flockfile; _IO_ftrylockfile; _IO_funlockfile;
+    vfork; __fork;
+
+    # POSIX.1c extensions to libc.
+    flockfile; funlockfile; ftrylockfile;
+
+    # Non-standard POSIX1.x functions.
+    pthread_kill_other_threads_np; pthread_mutexattr_getkind_np;
+    pthread_mutexattr_setkind_np;
+
+    # Real POSIX.1c functions.
+    pthread_atfork; pthread_attr_destroy; pthread_attr_getdetachstate;
+    pthread_attr_getinheritsched; pthread_attr_getschedparam;
+    pthread_attr_getschedpolicy; pthread_attr_getscope; pthread_attr_init;
+    pthread_attr_setdetachstate; pthread_attr_setinheritsched;
+    pthread_attr_setschedparam; pthread_attr_setschedpolicy;
+    pthread_attr_setscope; pthread_cancel; pthread_cond_broadcast;
+    pthread_cond_destroy; pthread_cond_init; pthread_cond_signal;
+    pthread_cond_timedwait; pthread_cond_wait; pthread_condattr_destroy;
+    pthread_condattr_init; pthread_create; pthread_detach; pthread_equal;
+    pthread_exit; pthread_getschedparam; pthread_getspecific; pthread_join;
+    pthread_key_create; pthread_key_delete; pthread_kill;
+    pthread_mutex_destroy; pthread_mutex_init; pthread_mutex_lock;
+    pthread_mutex_trylock; pthread_mutex_unlock; pthread_mutexattr_destroy;
+    pthread_mutexattr_init; pthread_once; pthread_self; pthread_setcancelstate;
+    pthread_setcanceltype; pthread_setschedparam; pthread_setspecific;
+    pthread_sigmask; pthread_testcancel;
+
+    sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait;
+    sigwait;
+
+    # Protected names for functions used in other shared objects.
+    __pthread_atfork; __pthread_getspecific;
+    __pthread_key_create; __pthread_mutex_destroy; __pthread_mutex_init;
+    __pthread_mutex_lock; __pthread_mutex_trylock; __pthread_mutex_unlock;
+    __pthread_mutexattr_destroy; __pthread_mutexattr_init;
+    __pthread_mutexattr_settype; __pthread_once; __pthread_setspecific;
+
+    # The error functions.
+    __errno_location; __h_errno_location;
+
+    # Must be preemptible
+    __sigaction;
+  }
+  GLIBC_2.1 {
+    # Functions with changed interface.
+    pthread_attr_init; pthread_create;
+
+    # Unix98 extensions.
+    pthread_rwlock_init; pthread_rwlock_destroy; pthread_rwlock_rdlock;
+    pthread_rwlock_tryrdlock; pthread_rwlock_wrlock; pthread_rwlock_trywrlock;
+    pthread_rwlock_unlock; pthread_rwlockattr_init; pthread_rwlockattr_destroy;
+    pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared;
+    pthread_rwlockattr_getkind_np; pthread_rwlockattr_setkind_np;
+
+    pthread_attr_getguardsize; pthread_attr_setguardsize;
+    pthread_attr_getstackaddr; pthread_attr_setstackaddr;
+    pthread_attr_getstacksize; pthread_attr_setstacksize;
+
+    pthread_getconcurrency; pthread_setconcurrency;
+
+    pthread_mutexattr_gettype; pthread_mutexattr_settype;
+
+    sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait;
+
+    # helper functions
+    __libc_current_sigrtmin; __libc_current_sigrtmax;
+    __libc_allocate_rtsig;
+  }
+  GLIBC_2.1.1 {
+    sem_close; sem_open; sem_unlink;
+  }
+  GLIBC_2.1.2 {
+    __vfork;
+  }
+  GLIBC_2.2 {
+    # For the cancelation wrappers.
+    pread; __pread64; pread64; pwrite; __pwrite64; pwrite64; lseek64;
+    open64; __open64;
+
+    __res_state;
+
+    # Names used internally.
+    __pthread_rwlock_init; __pthread_rwlock_destroy; __pthread_rwlock_rdlock;
+    __pthread_rwlock_tryrdlock; __pthread_rwlock_wrlock;
+    __pthread_rwlock_trywrlock; __pthread_rwlock_unlock;
+
+    # No really implemented.
+    pthread_condattr_getpshared; pthread_condattr_setpshared;
+    pthread_mutexattr_getpshared; pthread_mutexattr_setpshared;
+
+    # New functions from IEEE Std. 1003.1-200x.
+    sem_timedwait;
+    pthread_attr_getstack; pthread_attr_setstack;
+    pthread_spin_destroy; pthread_spin_init; pthread_spin_lock;
+    pthread_spin_trylock; pthread_spin_unlock;
+    pthread_getcpuclockid;
+    pthread_barrier_destroy; pthread_barrier_init; pthread_barrier_wait;
+    pthread_barrierattr_destroy; pthread_barrierattr_init;
+    pthread_barrierattr_setpshared;
+    pthread_mutex_timedlock;
+    pthread_rwlock_timedrdlock; pthread_rwlock_timedwrlock;
+
+    # Extensions.
+    pthread_yield;
+  }
+  GLIBC_2.2.3 {
+    # Extensions.
+    pthread_getattr_np;
+  }
+  GLIBC_2.2.6 {
+    # Cancellation wrapper
+    __nanosleep;
+  }
+  GLIBC_2.3.2 {
+    # Changed pthread_cond_t.
+    pthread_cond_init; pthread_cond_destroy;
+    pthread_cond_wait; pthread_cond_timedwait;
+    pthread_cond_signal; pthread_cond_broadcast;
+  }
+
+  # Hey you!!  Yes, YOU!  Do not add new symbols here!
+  # The linuxthreads libpthread ABI froze at GLIBC_2.3.2 and lacks
+  # numerous additions that NPTL's libpthread has.  We can't go adding
+  # any new symbols here unless we support all the new symbols in NPTL,
+  # and we don't want to do that.  Linuxthreads is only alive for
+  # compatibility with old binaries using old interfaces.
+
+  GLIBC_PRIVATE {
+    # Internal libc interface to libpthread
+    __pthread_initialize;
+    __pthread_kill_other_threads_np;
+  }
+}
diff --git a/linuxthreads/alloca_cutoff.c b/linuxthreads/alloca_cutoff.c
new file mode 100644
index 0000000000..ca064b3bb6
--- /dev/null
+++ b/linuxthreads/alloca_cutoff.c
@@ -0,0 +1,36 @@
+/* Determine whether block of given size can be allocated on the stack or not.
+   Copyright (C) 2002, 2003 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 <alloca.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "internals.h"
+#include <sysdep-cancel.h>
+
+int
+__libc_alloca_cutoff (size_t size)
+{
+  if (! SINGLE_THREAD_P)
+    {
+      pthread_descr self = thread_self ();
+      return size <= LIBC_THREAD_GETMEM (self, p_alloca_cutoff);
+    }
+
+  return size <= __MAX_ALLOCA_CUTOFF;
+}
diff --git a/linuxthreads/attr.c b/linuxthreads/attr.c
new file mode 100644
index 0000000000..2adc7ccd7a
--- /dev/null
+++ b/linuxthreads/attr.c
@@ -0,0 +1,485 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Handling of thread attributes */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/resource.h>
+#include "pthread.h"
+#include "internals.h"
+#include <shlib-compat.h>
+#include <ldsodefs.h>
+
+
+int __pthread_attr_init_2_1(pthread_attr_t *attr)
+{
+  size_t ps = __getpagesize ();
+
+  attr->__detachstate = PTHREAD_CREATE_JOINABLE;
+  attr->__schedpolicy = SCHED_OTHER;
+  attr->__schedparam.sched_priority = 0;
+  attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
+  attr->__scope = PTHREAD_SCOPE_SYSTEM;
+#ifdef NEED_SEPARATE_REGISTER_STACK
+  attr->__guardsize = ps + ps;
+#else
+  attr->__guardsize = ps;
+#endif
+  attr->__stackaddr = NULL;
+  attr->__stackaddr_set = 0;
+  attr->__stacksize = STACK_SIZE - ps;
+  return 0;
+}
+
+versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
+		  GLIBC_2_1);
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+int __pthread_attr_init_2_0(pthread_attr_t *attr)
+{
+  attr->__detachstate = PTHREAD_CREATE_JOINABLE;
+  attr->__schedpolicy = SCHED_OTHER;
+  attr->__schedparam.sched_priority = 0;
+  attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
+  attr->__scope = PTHREAD_SCOPE_SYSTEM;
+  return 0;
+}
+compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
+	       GLIBC_2_0);
+#endif
+
+int __pthread_attr_destroy(pthread_attr_t *attr)
+{
+  return 0;
+}
+strong_alias (__pthread_attr_destroy, pthread_attr_destroy);
+
+int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+  if (detachstate < PTHREAD_CREATE_JOINABLE ||
+      detachstate > PTHREAD_CREATE_DETACHED)
+    return EINVAL;
+  attr->__detachstate = detachstate;
+  return 0;
+}
+strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate);
+
+int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
+{
+  *detachstate = attr->__detachstate;
+  return 0;
+}
+strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate);
+
+int __pthread_attr_setschedparam(pthread_attr_t *attr,
+                                 const struct sched_param *param)
+{
+  int max_prio = __sched_get_priority_max(attr->__schedpolicy);
+  int min_prio = __sched_get_priority_min(attr->__schedpolicy);
+
+  if (param->sched_priority < min_prio || param->sched_priority > max_prio)
+    return EINVAL;
+  memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
+  return 0;
+}
+strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam);
+
+int __pthread_attr_getschedparam(const pthread_attr_t *attr,
+                                 struct sched_param *param)
+{
+  memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
+  return 0;
+}
+strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam);
+
+int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
+{
+  if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
+    return EINVAL;
+  attr->__schedpolicy = policy;
+  return 0;
+}
+strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
+
+int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
+{
+  *policy = attr->__schedpolicy;
+  return 0;
+}
+strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
+
+int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
+{
+  if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
+    return EINVAL;
+  attr->__inheritsched = inherit;
+  return 0;
+}
+strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched);
+
+int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
+{
+  *inherit = attr->__inheritsched;
+  return 0;
+}
+strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched);
+
+int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
+{
+  switch (scope) {
+  case PTHREAD_SCOPE_SYSTEM:
+    attr->__scope = scope;
+    return 0;
+  case PTHREAD_SCOPE_PROCESS:
+    return ENOTSUP;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_attr_setscope, pthread_attr_setscope);
+
+int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
+{
+  *scope = attr->__scope;
+  return 0;
+}
+strong_alias (__pthread_attr_getscope, pthread_attr_getscope);
+
+int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
+{
+  /* The guard size must not be larger than the stack itself */
+  if (guardsize >= attr->__stacksize) return EINVAL;
+
+  attr->__guardsize = guardsize;
+
+  return 0;
+}
+weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
+
+int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
+{
+  *guardsize = attr->__guardsize;
+  return 0;
+}
+weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
+
+int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
+{
+  attr->__stackaddr = stackaddr;
+  attr->__stackaddr_set = 1;
+  return 0;
+}
+weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
+
+link_warning (pthread_attr_setstackaddr,
+	      "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
+
+int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
+{
+  /* XXX This function has a stupid definition.  The standard specifies
+     no error value but what is if no stack address was set?  We simply
+     return the value we have in the member.  */
+  *stackaddr = attr->__stackaddr;
+  return 0;
+}
+weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
+
+link_warning (pthread_attr_getstackaddr,
+	      "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
+
+
+int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+#ifdef FLOATING_STACKS
+  /* We have to check against the maximum allowed stack size.  This is no
+     problem if the manager is already started and we determined it.  If
+     this hasn't happened, we have to find the limit outself.  */
+  if (__pthread_max_stacksize == 0)
+    __pthread_init_max_stacksize ();
+
+  if (stacksize > __pthread_max_stacksize)
+    return EINVAL;
+#else
+  /* We have a fixed size limit.  */
+  if (stacksize > STACK_SIZE)
+    return EINVAL;
+#endif
+
+  /* We don't accept value smaller than PTHREAD_STACK_MIN.  */
+  if (stacksize < PTHREAD_STACK_MIN)
+    return EINVAL;
+
+  attr->__stacksize = stacksize;
+  return 0;
+}
+
+#if PTHREAD_STACK_MIN == 16384
+weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
+#else
+versioned_symbol (libpthread, __pthread_attr_setstacksize,
+                  pthread_attr_setstacksize, GLIBC_2_3_3);
+
+# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
+
+int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+#  ifdef FLOATING_STACKS
+  /* We have to check against the maximum allowed stack size.  This is no
+     problem if the manager is already started and we determined it.  If
+     this hasn't happened, we have to find the limit outself.  */
+  if (__pthread_max_stacksize == 0)
+    __pthread_init_max_stacksize ();
+
+  if (stacksize > __pthread_max_stacksize)
+    return EINVAL;
+#  else
+  /* We have a fixed size limit.  */
+  if (stacksize > STACK_SIZE)
+    return EINVAL;
+#  endif
+
+  /* We don't accept value smaller than old PTHREAD_STACK_MIN.  */
+  if (stacksize < 16384)
+    return EINVAL;
+
+  attr->__stacksize = stacksize;
+  return 0;
+}
+compat_symbol (libpthread, __old_pthread_attr_setstacksize,
+	       pthread_attr_setstacksize, GLIBC_2_1);
+# endif
+#endif
+
+
+int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
+{
+  *stacksize = attr->__stacksize;
+  return 0;
+}
+weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
+
+int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
+			     size_t stacksize)
+{
+  int err;
+
+  if ((((uintptr_t) stackaddr)
+       & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
+    err = EINVAL;
+  else
+    err = __pthread_attr_setstacksize (attr, stacksize);
+  if (err == 0)
+    {
+#ifndef _STACK_GROWS_UP
+      attr->__stackaddr = (char *) stackaddr + stacksize;
+#else
+      attr->__stackaddr = stackaddr;
+#endif
+      attr->__stackaddr_set = 1;
+    }
+
+  return err;
+}
+
+#if PTHREAD_STACK_MIN == 16384
+weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
+#else
+versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
+                  GLIBC_2_3_3);
+# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
+int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
+				 size_t stacksize)
+{
+  int err;
+
+  if ((((uintptr_t) stackaddr)
+       & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
+    err = EINVAL;
+  else
+    err = __old_pthread_attr_setstacksize (attr, stacksize);
+  if (err == 0)
+    {
+#  ifndef _STACK_GROWS_UP
+      attr->__stackaddr = (char *) stackaddr + stacksize;
+#  else
+      attr->__stackaddr = stackaddr;
+#  endif
+      attr->__stackaddr_set = 1;
+    }
+
+  return err;
+}
+
+compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
+               GLIBC_2_2);
+
+# endif
+#endif
+
+int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
+			     size_t *stacksize)
+{
+  /* XXX This function has a stupid definition.  The standard specifies
+     no error value but what is if no stack address was set?  We simply
+     return the value we have in the member.  */
+#ifndef _STACK_GROWS_UP
+  *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
+#else
+  *stackaddr = attr->__stackaddr;
+#endif
+  *stacksize = attr->__stacksize;
+  return 0;
+}
+weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
+
+int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
+{
+  pthread_handle handle = thread_handle (thread);
+  pthread_descr descr;
+  int ret = 0;
+
+  if (handle == NULL)
+    return ENOENT;
+
+  descr = handle->h_descr;
+
+  attr->__detachstate = (descr->p_detached
+			 ? PTHREAD_CREATE_DETACHED
+			 : PTHREAD_CREATE_JOINABLE);
+
+  attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
+  if (attr->__schedpolicy == -1)
+    return errno;
+
+  if (__sched_getparam (descr->p_pid,
+			(struct sched_param *) &attr->__schedparam) != 0)
+    return errno;
+
+  attr->__inheritsched = descr->p_inheritsched;
+  attr->__scope = PTHREAD_SCOPE_SYSTEM;
+
+#ifdef _STACK_GROWS_DOWN
+# ifdef USE_TLS
+  attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
+		      - descr->p_guardsize;
+# else
+  attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
+		      - descr->p_guardsize;
+# endif
+#else
+# ifdef USE_TLS
+  attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
+# else
+  attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
+# endif
+#endif
+  attr->__guardsize = descr->p_guardsize;
+  attr->__stackaddr_set = descr->p_userstack;
+#ifdef NEED_SEPARATE_REGISTER_STACK
+  if (descr->p_userstack == 0)
+    attr->__stacksize *= 2;
+  /* XXX This is awkward.  The guard pages are in the middle of the
+     two stacks.  We must count the guard size in the stack size since
+     otherwise the range of the stack area cannot be computed.  */
+  attr->__stacksize += attr->__guardsize;
+#endif
+#ifdef USE_TLS
+  attr->__stackaddr = descr->p_stackaddr;
+#else
+# ifndef _STACK_GROWS_UP
+  attr->__stackaddr = (char *)(descr + 1);
+# else
+  attr->__stackaddr = (char *)descr;
+# endif
+#endif
+
+#ifdef USE_TLS
+  if (attr->__stackaddr == NULL)
+#else
+  if (descr == &__pthread_initial_thread)
+#endif
+    {
+      /* Stack size limit.  */
+      struct rlimit rl;
+
+      /* The safest way to get the top of the stack is to read
+	 /proc/self/maps and locate the line into which
+	 __libc_stack_end falls.  */
+      FILE *fp = fopen ("/proc/self/maps", "rc");
+      if (fp == NULL)
+	ret = errno;
+      /* We need the limit of the stack in any case.  */
+      else if (getrlimit (RLIMIT_STACK, &rl) != 0)
+	ret = errno;
+      else
+	{
+	  /* We need no locking.  */
+	  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+	  /* Until we found an entry (which should always be the case)
+	     mark the result as a failure.  */
+	  ret = ENOENT;
+
+	  char *line = NULL;
+	  size_t linelen = 0;
+	  uintptr_t last_to = 0;
+
+	  while (! feof_unlocked (fp))
+	    {
+	      if (__getdelim (&line, &linelen, '\n', fp) <= 0)
+		break;
+
+	      uintptr_t from;
+	      uintptr_t to;
+	      if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
+		continue;
+	      if (from <= (uintptr_t) __libc_stack_end
+		  && (uintptr_t) __libc_stack_end < to)
+		{
+		  /* Found the entry.  Now we have the info we need.  */
+		  attr->__stacksize = rl.rlim_cur;
+#ifdef _STACK_GROWS_UP
+		  /* Don't check to enforce a limit on the __stacksize */
+		  attr->__stackaddr = (void *) from;
+#else
+		  attr->__stackaddr = (void *) to;
+
+		  /* The limit might be too high.  */
+		  if ((size_t) attr->__stacksize
+		      > (size_t) attr->__stackaddr - last_to)
+		    attr->__stacksize = (size_t) attr->__stackaddr - last_to;
+#endif
+
+		  /* We succeed and no need to look further.  */
+		  ret = 0;
+		  break;
+		}
+	      last_to = to;
+	    }
+
+	  fclose (fp);
+	  free (line);
+	}
+    }
+
+  return 0;
+
+}
diff --git a/linuxthreads/barrier.c b/linuxthreads/barrier.c
new file mode 100644
index 0000000000..37d997cfc1
--- /dev/null
+++ b/linuxthreads/barrier.c
@@ -0,0 +1,128 @@
+/* POSIX barrier implementation for LinuxThreads.
+   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
+
+   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 "internals.h"
+#include "spinlock.h"
+#include "queue.h"
+#include "restart.h"
+
+int
+pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+  pthread_descr self = thread_self();
+  pthread_descr temp_wake_queue, th;
+  int result = 0;
+
+  __pthread_lock(&barrier->__ba_lock, self);
+
+  /* If the required number of threads have achieved rendezvous... */
+  if (barrier->__ba_present >= barrier->__ba_required - 1)
+    {
+      /* ... then this last caller shall be the serial thread */
+      result = PTHREAD_BARRIER_SERIAL_THREAD;
+      /* Copy and clear wait queue and reset barrier. */
+      temp_wake_queue = barrier->__ba_waiting;
+      barrier->__ba_waiting = NULL;
+      barrier->__ba_present = 0;
+    }
+  else
+    {
+      result = 0;
+      barrier->__ba_present++;
+      enqueue(&barrier->__ba_waiting, self);
+    }
+
+  __pthread_unlock(&barrier->__ba_lock);
+
+  if (result == 0)
+    {
+      /* Non-serial threads have to suspend */
+      suspend(self);
+      /* We don't bother dealing with cancellation because the POSIX
+         spec for barriers doesn't mention that pthread_barrier_wait
+         is a cancellation point. */
+    }
+  else
+    {
+      /* Serial thread wakes up all others. */
+      while ((th = dequeue(&temp_wake_queue)) != NULL)
+	restart(th);
+    }
+
+  return result;
+}
+
+int
+pthread_barrier_init(pthread_barrier_t *barrier,
+				const pthread_barrierattr_t *attr,
+				unsigned int count)
+{
+  if (count == 0)
+     return EINVAL;
+
+  __pthread_init_lock(&barrier->__ba_lock);
+  barrier->__ba_required = count;
+  barrier->__ba_present = 0;
+  barrier->__ba_waiting = NULL;
+  return 0;
+}
+
+int
+pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+  if (barrier->__ba_waiting != NULL) return EBUSY;
+  return 0;
+}
+
+int
+pthread_barrierattr_init(pthread_barrierattr_t *attr)
+{
+  attr->__pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+
+int
+pthread_barrierattr_destroy(pthread_barrierattr_t *attr)
+{
+  return 0;
+}
+
+int
+__pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr,
+				 int *pshared)
+{
+  *pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+
+int
+pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  return 0;
+}
diff --git a/linuxthreads/bug-sleep.c b/linuxthreads/bug-sleep.c
new file mode 100644
index 0000000000..f29a6b73c0
--- /dev/null
+++ b/linuxthreads/bug-sleep.c
@@ -0,0 +1,34 @@
+/* PR libc/4005 */
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+void *
+run_thread (void *a)
+{
+  while (1)
+    {
+      sleep (10);
+    }
+  return 0;
+}
+
+int
+main (void)
+{
+  pthread_t thr;
+  void *result;
+  alarm (4);
+  printf ("Starting thread.\n");
+  pthread_create (&thr, 0, run_thread, 0);
+  sleep (2);
+  printf ("Canceling thread.\n");
+  pthread_cancel (thr);
+  pthread_join (thr, &result);
+  if (result == PTHREAD_CANCELED)
+    printf ("Thread canceled.\n");
+  else
+    printf ("Thread exited.\n");
+  return 0;
+}
diff --git a/linuxthreads/cancel.c b/linuxthreads/cancel.c
new file mode 100644
index 0000000000..d8053ca899
--- /dev/null
+++ b/linuxthreads/cancel.c
@@ -0,0 +1,234 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Thread cancellation */
+
+#include <errno.h>
+#include <libc-internal.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+
+#ifdef _STACK_GROWS_DOWN
+# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other)
+#elif _STACK_GROWS_UP
+# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other)
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+
+
+int __pthread_setcancelstate(int state, int * oldstate)
+{
+  pthread_descr self = thread_self();
+  if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE)
+    return EINVAL;
+  if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate);
+  THREAD_SETMEM(self, p_cancelstate, state);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  return 0;
+}
+strong_alias (__pthread_setcancelstate, pthread_setcancelstate);
+
+int __pthread_setcanceltype(int type, int * oldtype)
+{
+  pthread_descr self = thread_self();
+  if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
+    return EINVAL;
+  if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype);
+  THREAD_SETMEM(self, p_canceltype, type);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  return 0;
+}
+strong_alias (__pthread_setcanceltype, pthread_setcanceltype);
+
+
+/* The next two functions are similar to pthread_setcanceltype() but
+   more specialized for the use in the cancelable functions like write().
+   They do not need to check parameters etc.  */
+int
+attribute_hidden
+__pthread_enable_asynccancel (void)
+{
+  pthread_descr self = thread_self();
+  int oldtype = THREAD_GETMEM(self, p_canceltype);
+  THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
+  if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  return oldtype;
+}
+
+void
+internal_function attribute_hidden
+__pthread_disable_asynccancel (int oldtype)
+{
+  pthread_descr self = thread_self();
+  THREAD_SETMEM(self, p_canceltype, oldtype);
+}
+
+
+int pthread_cancel(pthread_t thread)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid;
+  int dorestart = 0;
+  pthread_descr th;
+  pthread_extricate_if *pextricate;
+  int already_canceled;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+
+  th = handle->h_descr;
+
+  already_canceled = th->p_canceled;
+  th->p_canceled = 1;
+
+  if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) {
+    __pthread_unlock(&handle->h_lock);
+    return 0;
+  }
+
+  pextricate = th->p_extricate;
+  pid = th->p_pid;
+
+  /* If the thread has registered an extrication interface, then
+     invoke the interface. If it returns 1, then we succeeded in
+     dequeuing the thread from whatever waiting object it was enqueued
+     with. In that case, it is our responsibility to wake it up.
+     And also to set the p_woken_by_cancel flag so the woken thread
+     can tell that it was woken by cancellation. */
+
+  if (pextricate != NULL) {
+    dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th);
+    th->p_woken_by_cancel = dorestart;
+  }
+
+  __pthread_unlock(&handle->h_lock);
+
+  /* If the thread has suspended or is about to, then we unblock it by
+     issuing a restart, instead of a cancel signal. Otherwise we send
+     the cancel signal to unblock the thread from a cancellation point,
+     or to initiate asynchronous cancellation. The restart is needed so
+     we have proper accounting of restarts; suspend decrements the thread's
+     resume count, and restart() increments it.  This also means that suspend's
+     handling of the cancel signal is obsolete. */
+
+  if (dorestart)
+    restart(th);
+  else
+    kill(pid, __pthread_sig_cancel);
+
+  return 0;
+}
+
+void pthread_testcancel(void)
+{
+  pthread_descr self = thread_self();
+  if (THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+}
+
+void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
+			   void (*routine)(void *), void * arg)
+{
+  pthread_descr self = thread_self();
+  buffer->__routine = routine;
+  buffer->__arg = arg;
+  buffer->__prev = THREAD_GETMEM(self, p_cleanup);
+  if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev))
+    buffer->__prev = NULL;
+  THREAD_SETMEM(self, p_cleanup, buffer);
+}
+
+void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
+			  int execute)
+{
+  pthread_descr self = thread_self();
+  if (execute) buffer->__routine(buffer->__arg);
+  THREAD_SETMEM(self, p_cleanup, buffer->__prev);
+}
+
+void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
+				 void (*routine)(void *), void * arg)
+{
+  pthread_descr self = thread_self();
+  buffer->__routine = routine;
+  buffer->__arg = arg;
+  buffer->__canceltype = THREAD_GETMEM(self, p_canceltype);
+  buffer->__prev = THREAD_GETMEM(self, p_cleanup);
+  if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev))
+    buffer->__prev = NULL;
+  THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
+  THREAD_SETMEM(self, p_cleanup, buffer);
+}
+
+void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
+				  int execute)
+{
+  pthread_descr self = thread_self();
+  if (execute) buffer->__routine(buffer->__arg);
+  THREAD_SETMEM(self, p_cleanup, buffer->__prev);
+  THREAD_SETMEM(self, p_canceltype, buffer->__canceltype);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+}
+
+void __pthread_perform_cleanup(char *currentframe)
+{
+  pthread_descr self = thread_self();
+  struct _pthread_cleanup_buffer *c = THREAD_GETMEM(self, p_cleanup);
+  struct _pthread_cleanup_buffer *last;
+
+  if (c != NULL)
+    while (FRAME_LEFT (currentframe, c))
+      {
+	last = c;
+	c = c->__prev;
+
+	if (c == NULL || FRAME_LEFT (last, c))
+	  {
+	    c = NULL;
+	    break;
+	  }
+      }
+
+  while (c != NULL)
+    {
+      c->__routine(c->__arg);
+
+      last = c;
+      c = c->__prev;
+
+      if (FRAME_LEFT (last, c))
+	break;
+    }
+
+  /* And the TSD which needs special help.  */
+  __libc_thread_freeres ();
+}
diff --git a/linuxthreads/condvar.c b/linuxthreads/condvar.c
new file mode 100644
index 0000000000..6ab95b88ae
--- /dev/null
+++ b/linuxthreads/condvar.c
@@ -0,0 +1,341 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/* and Pavel Krauz (krauz@fsid.cvut.cz).                                */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Condition variables */
+
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "queue.h"
+#include "restart.h"
+#include <shlib-compat.h>
+
+int __pthread_cond_init(pthread_cond_t *cond,
+                        const pthread_condattr_t *cond_attr)
+{
+  __pthread_init_lock(&cond->__c_lock);
+  cond->__c_waiting = NULL;
+  return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_init, pthread_cond_init,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_init, __old_pthread_cond_init)
+compat_symbol (libpthread, __old_pthread_cond_init, pthread_cond_init,
+	       GLIBC_2_0);
+#endif
+
+int __pthread_cond_destroy(pthread_cond_t *cond)
+{
+  if (cond->__c_waiting != NULL) return EBUSY;
+  return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_destroy, pthread_cond_destroy,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_destroy, __old_pthread_cond_destroy)
+compat_symbol (libpthread, __old_pthread_cond_destroy, pthread_cond_destroy,
+	       GLIBC_2_0);
+#endif
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting on a condition variable queue. */
+
+static int cond_extricate_func(void *obj, pthread_descr th)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_cond_t *cond = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&cond->__c_lock, self);
+  did_remove = remove_from_queue(&cond->__c_waiting, th);
+  __pthread_unlock(&cond->__c_lock);
+
+  return did_remove;
+}
+
+int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  /* Check whether the mutex is locked and owned by this thread.  */
+  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && mutex->__m_owner != self)
+    return EINVAL;
+
+  /* Set up extrication interface */
+  extr.pu_object = cond;
+  extr.pu_extricate_func = cond_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_condvar_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+
+  /* Atomically enqueue thread for waiting, but only if it is not
+     canceled. If the thread is canceled, then it will fall through the
+     suspend call below, and then call pthread_exit without
+     having to worry about whether it is still on the condition variable queue.
+     This depends on pthread_cancel setting p_canceled before calling the
+     extricate function. */
+
+  __pthread_lock(&cond->__c_lock, self);
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&cond->__c_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&cond->__c_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  pthread_mutex_unlock(mutex);
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      suspend(self);
+      if (THREAD_GETMEM(self, p_condvar_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* Check for cancellation again, to provide correct cancellation
+     point behavior */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    pthread_mutex_lock(mutex);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  pthread_mutex_lock(mutex);
+  return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_wait, __old_pthread_cond_wait)
+compat_symbol (libpthread, __old_pthread_cond_wait, pthread_cond_wait,
+	       GLIBC_2_0);
+#endif
+
+static int
+pthread_cond_timedwait_relative(pthread_cond_t *cond,
+				pthread_mutex_t *mutex,
+				const struct timespec * abstime)
+{
+  volatile pthread_descr self = thread_self();
+  int already_canceled = 0;
+  pthread_extricate_if extr;
+  int spurious_wakeup_count;
+
+  /* Check whether the mutex is locked and owned by this thread.  */
+  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && mutex->__m_owner != self)
+    return EINVAL;
+
+  /* Set up extrication interface */
+  extr.pu_object = cond;
+  extr.pu_extricate_func = cond_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_condvar_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+
+  /* Enqueue to wait on the condition and check for cancellation. */
+  __pthread_lock(&cond->__c_lock, self);
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&cond->__c_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&cond->__c_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  pthread_mutex_unlock(mutex);
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      if (!timedsuspend(self, abstime)) {
+	int was_on_queue;
+
+	/* __pthread_lock will queue back any spurious restarts that
+	   may happen to it. */
+
+	__pthread_lock(&cond->__c_lock, self);
+	was_on_queue = remove_from_queue(&cond->__c_waiting, self);
+	__pthread_unlock(&cond->__c_lock);
+
+	if (was_on_queue) {
+	  __pthread_set_own_extricate_if(self, 0);
+	  pthread_mutex_lock(mutex);
+	  return ETIMEDOUT;
+	}
+
+	/* Eat the outstanding restart() from the signaller */
+	suspend(self);
+      }
+
+      if (THREAD_GETMEM(self, p_condvar_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* The remaining logic is the same as in other cancellable waits,
+     such as pthread_join sem_wait or pthread_cond wait. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    pthread_mutex_lock(mutex);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  pthread_mutex_lock(mutex);
+  return 0;
+}
+
+int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+			     const struct timespec * abstime)
+{
+  /* Indirect call through pointer! */
+  return pthread_cond_timedwait_relative(cond, mutex, abstime);
+}
+versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_timedwait, __old_pthread_cond_timedwait)
+compat_symbol (libpthread, __old_pthread_cond_timedwait,
+	       pthread_cond_timedwait, GLIBC_2_0);
+#endif
+
+int __pthread_cond_signal(pthread_cond_t *cond)
+{
+  pthread_descr th;
+
+  __pthread_lock(&cond->__c_lock, NULL);
+  th = dequeue(&cond->__c_waiting);
+  __pthread_unlock(&cond->__c_lock);
+  if (th != NULL) {
+    th->p_condvar_avail = 1;
+    WRITE_MEMORY_BARRIER();
+    restart(th);
+  }
+  return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_signal, __old_pthread_cond_signal)
+compat_symbol (libpthread, __old_pthread_cond_signal, pthread_cond_signal,
+	       GLIBC_2_0);
+#endif
+
+int __pthread_cond_broadcast(pthread_cond_t *cond)
+{
+  pthread_descr tosignal, th;
+
+  __pthread_lock(&cond->__c_lock, NULL);
+  /* Copy the current state of the waiting queue and empty it */
+  tosignal = cond->__c_waiting;
+  cond->__c_waiting = NULL;
+  __pthread_unlock(&cond->__c_lock);
+  /* Now signal each process in the queue */
+  while ((th = dequeue(&tosignal)) != NULL) {
+    th->p_condvar_avail = 1;
+    WRITE_MEMORY_BARRIER();
+    restart(th);
+  }
+  return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
+		  GLIBC_2_3_2);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_broadcast, __old_pthread_cond_broadcast)
+compat_symbol (libpthread, __old_pthread_cond_broadcast,
+	       pthread_cond_broadcast, GLIBC_2_0);
+#endif
+
+int __pthread_condattr_init(pthread_condattr_t *attr)
+{
+  return 0;
+}
+strong_alias (__pthread_condattr_init, pthread_condattr_init)
+
+int __pthread_condattr_destroy(pthread_condattr_t *attr)
+{
+  return 0;
+}
+strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy)
+
+int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
+{
+  *pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+
+int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  return 0;
+}
diff --git a/linuxthreads/configure b/linuxthreads/configure
new file mode 100755
index 0000000000..2624f9ec5a
--- /dev/null
+++ b/linuxthreads/configure
@@ -0,0 +1,17 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+
+# LinuxThreads fragment for GNU C library configure mechanism.
+# This is a shell script fragment sourced by the main configure script.
+
+for other in $add_ons; do
+  test $other = nptl || continue
+  if test $add_ons_automatic = yes; then
+    echo "$as_me:$LINENO: result: $libc_add_on disabled because $other add-on is also in use" >&5
+echo "${ECHO_T}$libc_add_on disabled because $other add-on is also in use" >&6
+    libc_add_on=
+  else
+    { { echo "$as_me:$LINENO: error: cannot use both $libc_add_on and $other add-ons in one build" >&5
+echo "$as_me: error: cannot use both $libc_add_on and $other add-ons in one build" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+done
diff --git a/linuxthreads/configure.in b/linuxthreads/configure.in
new file mode 100644
index 0000000000..3f9904a411
--- /dev/null
+++ b/linuxthreads/configure.in
@@ -0,0 +1,14 @@
+GLIBC_PROVIDES dnl See top-level configure.in.
+
+# LinuxThreads fragment for GNU C library configure mechanism.
+# This is a shell script fragment sourced by the main configure script.
+
+for other in $add_ons; do
+  test $other = nptl || continue
+  if test $add_ons_automatic = yes; then
+    AC_MSG_RESULT($libc_add_on disabled because $other add-on is also in use)
+    libc_add_on=
+  else
+    AC_MSG_ERROR(cannot use both $libc_add_on and $other add-ons in one build)
+  fi
+done
diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h
new file mode 100644
index 0000000000..bea8b912f7
--- /dev/null
+++ b/linuxthreads/descr.h
@@ -0,0 +1,267 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#ifndef _DESCR_H
+#define _DESCR_H	1
+
+#define __need_res_state
+#include <resolv.h>
+#include <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <hp-timing.h>
+#include <tls.h>
+
+/* Fast thread-specific data internal to libc.  */
+enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
+			_LIBC_TSD_KEY_DL_ERROR,
+			_LIBC_TSD_KEY_RPC_VARS,
+			_LIBC_TSD_KEY_LOCALE,
+			_LIBC_TSD_KEY_CTYPE_B,
+			_LIBC_TSD_KEY_CTYPE_TOLOWER,
+			_LIBC_TSD_KEY_CTYPE_TOUPPER,
+			_LIBC_TSD_KEY_N };
+
+/* The type of thread descriptors */
+typedef struct _pthread_descr_struct *pthread_descr;
+
+
+/* Some more includes.  */
+#include <pt-machine.h>
+#include <linuxthreads_db/thread_dbP.h>
+
+
+/* Arguments passed to thread creation routine */
+struct pthread_start_args {
+  void *(*start_routine)(void *); /* function to run */
+  void *arg;                      /* its argument */
+  sigset_t mask;                  /* initial signal mask for thread */
+  int schedpolicy;                /* initial scheduling policy (if any) */
+  struct sched_param schedparam;  /* initial scheduling parameters (if any) */
+};
+
+
+/* Callback interface for removing the thread from waiting on an
+   object if it is cancelled while waiting or about to wait.
+   This hold a pointer to the object, and a pointer to a function
+   which ``extricates'' the thread from its enqueued state.
+   The function takes two arguments: pointer to the wait object,
+   and a pointer to the thread. It returns 1 if an extrication
+   actually occured, and hence the thread must also be signalled.
+   It returns 0 if the thread had already been extricated. */
+typedef struct _pthread_extricate_struct {
+    void *pu_object;
+    int (*pu_extricate_func)(void *, pthread_descr);
+} pthread_extricate_if;
+
+
+/* Atomic counter made possible by compare_and_swap */
+struct pthread_atomic {
+  long p_count;
+  int p_spinlock;
+};
+
+
+/* Context info for read write locks. The pthread_rwlock_info structure
+   is information about a lock that has been read-locked by the thread
+   in whose list this structure appears. The pthread_rwlock_context
+   is embedded in the thread context and contains a pointer to the
+   head of the list of lock info structures, as well as a count of
+   read locks that are untracked, because no info structure could be
+   allocated for them. */
+struct _pthread_rwlock_t;
+typedef struct _pthread_rwlock_info {
+  struct _pthread_rwlock_info *pr_next;
+  struct _pthread_rwlock_t *pr_lock;
+  int pr_lock_count;
+} pthread_readlock_info;
+
+
+/* We keep thread specific data in a special data structure, a two-level
+   array.  The top-level array contains pointers to dynamically allocated
+   arrays of a certain number of data pointers.  So we can implement a
+   sparse array.  Each dynamic second-level array has
+	PTHREAD_KEY_2NDLEVEL_SIZE
+   entries.  This value shouldn't be too large.  */
+#define PTHREAD_KEY_2NDLEVEL_SIZE	32
+
+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
+   keys in each subarray.  */
+#define PTHREAD_KEY_1STLEVEL_SIZE \
+  ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
+   / PTHREAD_KEY_2NDLEVEL_SIZE)
+
+
+union dtv;
+
+struct _pthread_descr_struct
+{
+#if !defined USE_TLS || !TLS_DTV_AT_TP
+  /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads.  */
+  union
+  {
+    struct
+    {
+      void *tcb;		/* Pointer to the TCB.  This is not always
+				   the address of this thread descriptor.  */
+      union dtv *dtvp;
+      pthread_descr self;	/* Pointer to this structure */
+      int multiple_threads;
+# ifdef NEED_DL_SYSINFO
+      uintptr_t sysinfo;
+# endif
+    } data;
+    void *__padding[16];
+  } p_header;
+# define p_multiple_threads p_header.data.multiple_threads
+#elif TLS_MULTIPLE_THREADS_IN_TCB
+  int p_multiple_threads;
+#endif
+
+  pthread_descr p_nextlive, p_prevlive;
+                                /* Double chaining of active threads */
+  pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
+  pthread_descr p_nextlock;	/* can be on a queue and waiting on a lock */
+  pthread_t p_tid;              /* Thread identifier */
+  int p_pid;                    /* PID of Unix process */
+  int p_priority;               /* Thread priority (== 0 if not realtime) */
+  struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
+  int p_signal;                 /* last signal received */
+  sigjmp_buf * p_signal_jmp;    /* where to siglongjmp on a signal or NULL */
+  sigjmp_buf * p_cancel_jmp;    /* where to siglongjmp on a cancel or NULL */
+  char p_terminated;            /* true if terminated e.g. by pthread_exit */
+  char p_detached;              /* true if detached */
+  char p_exited;                /* true if the assoc. process terminated */
+  void * p_retval;              /* placeholder for return value */
+  int p_retcode;                /* placeholder for return code */
+  pthread_descr p_joining;      /* thread joining on that thread or NULL */
+  struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
+  char p_cancelstate;           /* cancellation state */
+  char p_canceltype;            /* cancellation type (deferred/async) */
+  char p_canceled;              /* cancellation request pending */
+  char * p_in_sighandler;       /* stack address of sighandler, or NULL */
+  char p_sigwaiting;            /* true if a sigwait() is in progress */
+  struct pthread_start_args p_start_args; /* arguments for thread creation */
+  void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
+#if !(USE_TLS && HAVE___THREAD)
+  void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
+  int * p_errnop;               /* pointer to used errno variable */
+  int p_errno;                  /* error returned by last system call */
+  int * p_h_errnop;             /* pointer to used h_errno variable */
+  int p_h_errno;                /* error returned by last netdb function */
+  struct __res_state *p_resp;	/* Pointer to resolver state */
+#endif
+  struct __res_state p_res;	/* per-thread resolver state */
+  int p_userstack;		/* nonzero if the user provided the stack */
+  void *p_guardaddr;		/* address of guard area or NULL */
+  size_t p_guardsize;		/* size of guard area */
+  int p_nr;                     /* Index of descriptor in __pthread_handles */
+  int p_report_events;		/* Nonzero if events must be reported.  */
+  td_eventbuf_t p_eventbuf;     /* Data for event.  */
+  struct pthread_atomic p_resume_count; /* number of times restart() was
+					   called on thread */
+  char p_woken_by_cancel;       /* cancellation performed wakeup */
+  char p_condvar_avail;		/* flag if conditional variable became avail */
+  char p_sem_avail;             /* flag if semaphore became available */
+  pthread_extricate_if *p_extricate; /* See above */
+  pthread_readlock_info *p_readlock_list;  /* List of readlock info structs */
+  pthread_readlock_info *p_readlock_free;  /* Free list of structs */
+  int p_untracked_readlock_count;	/* Readlocks not tracked by list */
+  int p_inheritsched;           /* copied from the thread attribute */
+#if HP_TIMING_AVAIL
+  hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread.  */
+#endif
+#ifdef USE_TLS
+  char *p_stackaddr;		/* Stack address.  */
+#endif
+  size_t p_alloca_cutoff;	/* Maximum size which should be allocated
+				   using alloca() instead of malloc().  */
+  /* New elements must be added at the end.  */
+} __attribute__ ((aligned(32))); /* We need to align the structure so that
+				    doubles are aligned properly.  This is 8
+				    bytes on MIPS and 16 bytes on MIPS64.
+				    32 bytes might give better cache
+				    utilization.  */
+
+
+
+/* Limit between the stack of the initial thread (above) and the
+   stacks of other threads (below). Aligned on a STACK_SIZE boundary.
+   Initially 0, meaning that the current thread is (by definition)
+   the initial thread. */
+
+extern char *__pthread_initial_thread_bos;
+
+/* Descriptor of the initial thread */
+
+extern struct _pthread_descr_struct __pthread_initial_thread;
+
+/* Limits of the thread manager stack. */
+
+extern char *__pthread_manager_thread_bos;
+extern char *__pthread_manager_thread_tos;
+
+/* Descriptor of the manager thread */
+
+extern struct _pthread_descr_struct __pthread_manager_thread;
+extern pthread_descr __pthread_manager_threadp attribute_hidden;
+
+/* Indicate whether at least one thread has a user-defined stack (if 1),
+   or all threads have stacks supplied by LinuxThreads (if 0). */
+
+extern int __pthread_nonstandard_stacks;
+
+/* The max size of the thread stack segments.  If the default
+   THREAD_SELF implementation is used, this must be a power of two and
+   a multiple of PAGE_SIZE.  */
+#ifndef STACK_SIZE
+#define STACK_SIZE  (2 * 1024 * 1024)
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#ifndef CURRENT_STACK_FRAME
+#define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
+#endif
+
+/* Recover thread descriptor for the current thread */
+
+extern pthread_descr __pthread_find_self (void) __attribute__ ((const));
+
+static inline pthread_descr thread_self (void) __attribute__ ((const));
+static inline pthread_descr thread_self (void)
+{
+#ifdef THREAD_SELF
+  return THREAD_SELF;
+#else
+  char *sp = CURRENT_STACK_FRAME;
+  if (sp >= __pthread_initial_thread_bos)
+    return &__pthread_initial_thread;
+  else if (sp >= __pthread_manager_thread_bos
+	   && sp < __pthread_manager_thread_tos)
+    return &__pthread_manager_thread;
+  else if (__pthread_nonstandard_stacks)
+    return __pthread_find_self();
+  else
+#ifdef _STACK_GROWS_DOWN
+    return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;
+#else
+    return (pthread_descr)((unsigned long)sp &~ (STACK_SIZE-1));
+#endif
+#endif
+}
+
+#endif	/* descr.h */
diff --git a/linuxthreads/ecmutex.c b/linuxthreads/ecmutex.c
new file mode 100644
index 0000000000..ce54ddf331
--- /dev/null
+++ b/linuxthreads/ecmutex.c
@@ -0,0 +1,157 @@
+/* Test of the error checking mutex and incidently also barriers.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t locks[] =
+{
+  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
+  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
+  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
+  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
+  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+};
+#define nlocks ((int) (sizeof (locks) / sizeof (locks[0])))
+
+static pthread_barrier_t barrier;
+#define SYNC pthread_barrier_wait (&barrier)
+
+#define NTHREADS nlocks
+
+#define ROUNDS 20
+
+
+static void *
+worker (void *arg)
+{
+  /* We are locking the and unlocked the locks and check the errors.
+     Since we are using the error-checking variant the implementation
+     should report them.  */
+  int nr = (long int) arg;
+  int i;
+  void *result = NULL;
+  int retval;
+
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      /* Skip the rounds which would make other == own.  */
+      if (i % nlocks == 0)
+	continue;
+
+      /* Get the "own" mutex.  */
+      if (pthread_mutex_trylock (&locks[nr]) != 0)
+	{
+	  printf ("thread %d failed getting own mutex\n", nr);
+	  result = (void *) 1;
+	}
+
+      /* Try locking "own" mutex again.  */
+      retval = pthread_mutex_lock (&locks[nr]);
+      if (retval != EDEADLK)
+	{
+	  printf ("thread %d failed getting own mutex\n", nr);
+	  result = (void *) 1;
+	}
+
+      /* Try to get a different semaphore.  */
+      SYNC;
+      retval = pthread_mutex_trylock (&locks[(nr + i) % nlocks]);
+      if (retval != EBUSY)
+	{
+	  printf ("thread %d didn't deadlock on getting %d's lock\n",
+		  nr, (nr + i) % nlocks);
+	  result = (void *) 1;
+	}
+
+      /* Try unlocking other's lock.  */
+      retval = pthread_mutex_unlock (&locks[(nr + i) % nlocks]);
+      if (retval != EPERM)
+	{
+	  printf ("thread %d managed releasing mutex %d\n",
+		  nr, (nr + i) % nlocks);
+	  result = (void *) 1;
+	}
+
+      /* All lock one mutex now.  */
+      SYNC;
+      retval = pthread_mutex_lock (&locks[i % nlocks]);
+      if (nr == (i % nlocks))
+	{
+	  if (retval != EDEADLK)
+	    {
+	      printf ("thread %d didn't deadlock on getting %d's lock\n",
+		      nr, (nr + i) % nlocks);
+	      result = (void *) 1;
+	    }
+	  if (pthread_mutex_unlock (&locks[i % nlocks]) != 0)
+	    {
+	      printf ("thread %d failed releasing own mutex\n", nr);
+	      result = (void *) 1;
+	    }
+	}
+      else
+	{
+	  if (retval != 0)
+	    {
+	      printf ("thread %d failed acquiring mutex %d\n",
+		      nr, i % nlocks);
+	      result = (void *) 1;
+	    }
+	  else if (pthread_mutex_unlock (&locks[i % nlocks]) != 0)
+	    {
+	      printf ("thread %d failed releasing mutex %d\n",
+		      nr, i % nlocks);
+	      result = (void *) 1;
+	    }
+	}
+
+      /* Unlock the own lock.  */
+      SYNC;
+      if (nr != (i % nlocks) && pthread_mutex_unlock (&locks[nr]) != 0)
+	{
+	  printf ("thread %d failed releasing own mutex\n", nr);
+	  result = (void *) 1;
+	}
+
+      /* Try unlocking again.  */
+      retval = pthread_mutex_unlock (&locks[nr]);
+      if (retval == 0)
+	{
+	  printf ("thread %d managed releasing own mutex twice\n", nr);
+	  result = (void *) 1;
+	}
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  pthread_t threads[NTHREADS];
+  int i;
+  void *res;
+  int result = 0;
+
+  pthread_barrier_init (&barrier, NULL, NTHREADS);
+
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
+      {
+	printf ("failed to create thread %d: %m\n", i);
+	exit (1);
+      }
+
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_join (threads[i], &res) != 0 || res != NULL)
+      result = 1;
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/linuxthreads/errno.c b/linuxthreads/errno.c
new file mode 100644
index 0000000000..5c0e8767a1
--- /dev/null
+++ b/linuxthreads/errno.c
@@ -0,0 +1,47 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Define the location of errno for the remainder of the C library */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <tls.h>
+#include "pthread.h"
+#include "internals.h"
+
+#if !USE_TLS || !HAVE___THREAD
+/* The definition in libc is sufficient if we use TLS.  */
+int *
+__errno_location (void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM (self, p_errnop);
+}
+
+int *
+__h_errno_location (void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM (self, p_h_errnop);
+}
+
+/* Return thread specific resolver state.  */
+struct __res_state *
+__res_state (void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM (self, p_resp);
+}
+#endif
diff --git a/linuxthreads/events.c b/linuxthreads/events.c
new file mode 100644
index 0000000000..b4ca3846e8
--- /dev/null
+++ b/linuxthreads/events.c
@@ -0,0 +1,37 @@
+/* Event functions used while debugging.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The functions contained here do nothing, they just return.  */
+
+#include "internals.h"
+
+void
+__linuxthreads_create_event (void)
+{
+}
+
+void
+__linuxthreads_death_event (void)
+{
+}
+
+void
+__linuxthreads_reap_event (void)
+{
+}
diff --git a/linuxthreads/forward.c b/linuxthreads/forward.c
new file mode 100644
index 0000000000..b2a36d7d60
--- /dev/null
+++ b/linuxthreads/forward.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002, 2003 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 <dlfcn.h>
+#include "internals.h"
+#include <stdlib.h>
+
+#include <shlib-compat.h>
+
+
+/* Pointers to the libc functions.  */
+struct pthread_functions __libc_pthread_functions attribute_hidden;
+
+
+# define FORWARD2(name, rettype, decl, params, defaction) \
+rettype									      \
+name decl								      \
+{									      \
+  if (__libc_pthread_functions.ptr_##name == NULL)			      \
+    defaction;								      \
+									      \
+  return __libc_pthread_functions.ptr_##name params;			      \
+}
+
+# define FORWARD(name, decl, params, defretval) \
+  FORWARD2 (name, int, decl, params, return defretval)
+
+FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0)
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1)
+FORWARD (__pthread_attr_init_2_0, (pthread_attr_t *attr), (attr), 0)
+compat_symbol (libc, __pthread_attr_init_2_0, pthread_attr_init, GLIBC_2_0);
+#endif
+
+FORWARD (__pthread_attr_init_2_1, (pthread_attr_t *attr), (attr), 0)
+versioned_symbol (libc, __pthread_attr_init_2_1, pthread_attr_init, GLIBC_2_1);
+
+FORWARD (pthread_attr_getdetachstate,
+	 (const pthread_attr_t *attr, int *detachstate), (attr, detachstate),
+	 0)
+FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate),
+	 (attr, detachstate), 0)
+
+FORWARD (pthread_attr_getinheritsched,
+	 (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0)
+FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit),
+	 (attr, inherit), 0)
+
+FORWARD (pthread_attr_getschedparam,
+	 (const pthread_attr_t *attr, struct sched_param *param),
+	 (attr, param), 0)
+FORWARD (pthread_attr_setschedparam,
+	 (pthread_attr_t *attr, const struct sched_param *param),
+	 (attr, param), 0)
+
+FORWARD (pthread_attr_getschedpolicy,
+	 (const pthread_attr_t *attr, int *policy), (attr, policy), 0)
+FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy),
+	 (attr, policy), 0)
+
+FORWARD (pthread_attr_getscope,
+	 (const pthread_attr_t *attr, int *scope), (attr, scope), 0)
+FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope),
+	 (attr, scope), 0)
+
+
+FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0)
+FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0)
+
+
+FORWARD (__pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_broadcast, __pthread_cond_broadcast_2_0)
+compat_symbol (libc, __pthread_cond_broadcast_2_0, pthread_cond_broadcast,
+	       GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_broadcast, pthread_cond_broadcast,
+		  GLIBC_2_3_2);
+
+FORWARD (__pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_destroy, __pthread_cond_destroy_2_0)
+compat_symbol (libc, __pthread_cond_destroy_2_0, pthread_cond_destroy,
+	       GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_destroy, pthread_cond_destroy,
+		  GLIBC_2_3_2);
+
+FORWARD (__pthread_cond_init,
+	 (pthread_cond_t *cond, const pthread_condattr_t *cond_attr),
+	 (cond, cond_attr), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_init, __pthread_cond_init_2_0)
+compat_symbol (libc, __pthread_cond_init_2_0, pthread_cond_init, GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_init, pthread_cond_init, GLIBC_2_3_2);
+
+FORWARD (__pthread_cond_signal, (pthread_cond_t *cond), (cond), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_signal, __pthread_cond_signal_2_0)
+compat_symbol (libc, __pthread_cond_signal_2_0, pthread_cond_signal,
+	       GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_signal, pthread_cond_signal,
+		  GLIBC_2_3_2);
+
+FORWARD (__pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex),
+	 (cond, mutex), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_wait, __pthread_cond_wait_2_0)
+compat_symbol (libc, __pthread_cond_wait_2_0, pthread_cond_wait, GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_wait, pthread_cond_wait, GLIBC_2_3_2);
+
+FORWARD (__pthread_cond_timedwait,
+	 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+	  const struct timespec *abstime), (cond, mutex, abstime), 0)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+strong_alias (__pthread_cond_timedwait, __pthread_cond_timedwait_2_0)
+compat_symbol (libc, __pthread_cond_timedwait_2_0, pthread_cond_timedwait, GLIBC_2_0);
+#endif
+versioned_symbol (libc, __pthread_cond_timedwait, pthread_cond_timedwait, GLIBC_2_3_2);
+
+
+FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
+	 (thread1, thread2), 1)
+
+
+/* Use an alias to avoid warning, as pthread_exit is declared noreturn.  */
+FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS))
+strong_alias (__pthread_exit, pthread_exit);
+
+
+FORWARD (pthread_getschedparam,
+	 (pthread_t target_thread, int *policy, struct sched_param *param),
+	 (target_thread, policy, param), 0)
+FORWARD (pthread_setschedparam,
+	 (pthread_t target_thread, int policy,
+	  const struct sched_param *param), (target_thread, policy, param), 0)
+
+
+FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
+
+FORWARD (pthread_mutex_init,
+	 (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
+	 (mutex, mutexattr), 0)
+
+FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
+
+FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
+
+
+FORWARD2 (pthread_self, pthread_t, (void), (), return 0)
+
+
+FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate),
+	 0)
+
+FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
+
+FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return)
+
+FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return)
diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h
new file mode 100644
index 0000000000..605021766c
--- /dev/null
+++ b/linuxthreads/internals.h
@@ -0,0 +1,550 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#ifndef _INTERNALS_H
+#define _INTERNALS_H	1
+
+/* Internal data structures */
+
+/* Includes */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stackinfo.h>
+#include <sigcontextinfo.h>
+
+#include <tls.h>
+#include "descr.h"
+
+#include "semaphore.h"
+#include <pthread-functions.h>
+
+#ifndef THREAD_GETMEM
+# define THREAD_GETMEM(descr, member) descr->member
+#endif
+#ifndef THREAD_GETMEM_NC
+# define THREAD_GETMEM_NC(descr, member) descr->member
+#endif
+#ifndef THREAD_SETMEM
+# define THREAD_SETMEM(descr, member, value) descr->member = (value)
+#endif
+#ifndef THREAD_SETMEM_NC
+# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value)
+#endif
+
+#if !defined NOT_IN_libc && defined FLOATING_STACKS
+# define LIBC_THREAD_GETMEM(descr, member) THREAD_GETMEM (descr, member)
+# define LIBC_THREAD_SETMEM(descr, member, value) \
+  THREAD_SETMEM (descr, member, value)
+#else
+# define LIBC_THREAD_GETMEM(descr, member) descr->member
+# define LIBC_THREAD_SETMEM(descr, member, value) descr->member = (value)
+#endif
+
+typedef void (*destr_function)(void *);
+
+struct pthread_key_struct {
+  int in_use;                   /* already allocated? */
+  destr_function destr;         /* destruction routine */
+};
+
+
+#define PTHREAD_START_ARGS_INITIALIZER(fct) \
+  { (void *(*) (void *)) fct, NULL, {{0, }}, 0, { 0 } }
+
+
+/* The type of thread handles. */
+
+typedef struct pthread_handle_struct * pthread_handle;
+
+struct pthread_handle_struct {
+  struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */
+  pthread_descr h_descr;        /* Thread descriptor or NULL if invalid */
+  char * h_bottom;              /* Lowest address in the stack thread */
+};
+
+/* The type of messages sent to the thread manager thread */
+
+struct pthread_request {
+  pthread_descr req_thread;     /* Thread doing the request */
+  enum {                        /* Request kind */
+    REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT,
+    REQ_POST, REQ_DEBUG, REQ_KICK, REQ_FOR_EACH_THREAD
+  } req_kind;
+  union {                       /* Arguments for request */
+    struct {                    /* For REQ_CREATE: */
+      const pthread_attr_t * attr; /* thread attributes */
+      void * (*fn)(void *);     /*   start function */
+      void * arg;               /*   argument to start function */
+      sigset_t mask;            /*   signal mask */
+    } create;
+    struct {                    /* For REQ_FREE: */
+      pthread_t thread_id;      /*   identifier of thread to free */
+    } free;
+    struct {                    /* For REQ_PROCESS_EXIT: */
+      int code;                 /*   exit status */
+    } exit;
+    void * post;                /* For REQ_POST: the semaphore */
+    struct {			/* For REQ_FOR_EACH_THREAD: callback */
+      void (*fn)(void *, pthread_descr);
+      void *arg;
+    } for_each;
+  } req_args;
+};
+
+
+
+typedef void (*arch_sighandler_t) (int, SIGCONTEXT);
+union sighandler
+{
+  arch_sighandler_t old;
+  void (*rt) (int, struct siginfo *, struct ucontext *);
+};
+extern union sighandler __sighandler[NSIG];
+
+
+/* Signals used for suspend/restart and for cancellation notification.  */
+
+extern int __pthread_sig_restart;
+extern int __pthread_sig_cancel;
+
+/* Signal used for interfacing with gdb */
+
+extern int __pthread_sig_debug;
+
+/* Global array of thread handles, used for validating a thread id
+   and retrieving the corresponding thread descriptor. Also used for
+   mapping the available stack segments. */
+
+extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];
+
+/* Descriptor of the main thread */
+
+extern pthread_descr __pthread_main_thread;
+
+/* File descriptor for sending requests to the thread manager.
+   Initially -1, meaning that __pthread_initialize_manager must be called. */
+
+extern int __pthread_manager_request;
+
+/* Other end of the pipe for sending requests to the thread manager. */
+
+extern int __pthread_manager_reader;
+
+#ifdef FLOATING_STACKS
+/* Maximum stack size.  */
+extern size_t __pthread_max_stacksize;
+#endif
+
+/* Pending request for a process-wide exit */
+
+extern int __pthread_exit_requested, __pthread_exit_code;
+
+/* Set to 1 by gdb if we're debugging */
+
+extern volatile int __pthread_threads_debug;
+
+/* Globally enabled events.  */
+extern volatile td_thr_events_t __pthread_threads_events;
+
+/* Pointer to descriptor of thread with last event.  */
+extern volatile pthread_descr __pthread_last_event;
+
+/* Flag which tells whether we are executing on SMP kernel. */
+extern int __pthread_smp_kernel;
+
+/* Return the handle corresponding to a thread id */
+
+static inline pthread_handle thread_handle(pthread_t id)
+{
+  return &__pthread_handles[id % PTHREAD_THREADS_MAX];
+}
+
+/* Validate a thread handle. Must have acquired h->h_spinlock before. */
+
+static inline int invalid_handle(pthread_handle h, pthread_t id)
+{
+  return h->h_descr == NULL || h->h_descr->p_tid != id || h->h_descr->p_terminated;
+}
+
+static inline int nonexisting_handle(pthread_handle h, pthread_t id)
+{
+  return h->h_descr == NULL || h->h_descr->p_tid != id;
+}
+
+/* Fill in defaults left unspecified by pt-machine.h.  */
+
+/* We round up a value with page size. */
+#ifndef page_roundup
+#define page_roundup(v,p) ((((size_t) (v)) + (p) - 1) & ~((p) - 1))
+#endif
+
+/* The page size we can get from the system.  This should likely not be
+   changed by the machine file but, you never know.  */
+#ifndef PAGE_SIZE
+#define PAGE_SIZE  (sysconf (_SC_PAGE_SIZE))
+#endif
+
+/* The initial size of the thread stack.  Must be a multiple of PAGE_SIZE.  */
+#ifndef INITIAL_STACK_SIZE
+#define INITIAL_STACK_SIZE  (4 * PAGE_SIZE)
+#endif
+
+/* Size of the thread manager stack. The "- 32" avoids wasting space
+   with some malloc() implementations. */
+#ifndef THREAD_MANAGER_STACK_SIZE
+#define THREAD_MANAGER_STACK_SIZE  (2 * PAGE_SIZE - 32)
+#endif
+
+/* The base of the "array" of thread stacks.  The array will grow down from
+   here.  Defaults to the calculated bottom of the initial application
+   stack.  */
+#ifndef THREAD_STACK_START_ADDRESS
+#define THREAD_STACK_START_ADDRESS  __pthread_initial_thread_bos
+#endif
+
+/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the
+   architecture doesn't need a memory barrier instruction (e.g. Intel
+   x86).  Still we need the compiler to respect the barrier and emit
+   all outstanding operations which modify memory.  Some architectures
+   distinguish between full, read and write barriers.  */
+
+#ifndef MEMORY_BARRIER
+#define MEMORY_BARRIER() asm ("" : : : "memory")
+#endif
+#ifndef READ_MEMORY_BARRIER
+#define READ_MEMORY_BARRIER() MEMORY_BARRIER()
+#endif
+#ifndef WRITE_MEMORY_BARRIER
+#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER()
+#endif
+
+/* Max number of times we must spin on a spinlock calling sched_yield().
+   After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */
+
+#ifndef MAX_SPIN_COUNT
+#define MAX_SPIN_COUNT 50
+#endif
+
+/* Max number of times the spinlock in the adaptive mutex implementation
+   spins actively on SMP systems.  */
+
+#ifndef MAX_ADAPTIVE_SPIN_COUNT
+#define MAX_ADAPTIVE_SPIN_COUNT 100
+#endif
+
+/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock
+   after MAX_SPIN_COUNT iterations of sched_yield().
+   With the 2.0 and 2.1 kernels, this MUST BE > 2ms.
+   (Otherwise the kernel does busy-waiting for realtime threads,
+    giving other threads no chance to run.) */
+
+#ifndef SPIN_SLEEP_DURATION
+#define SPIN_SLEEP_DURATION 2000001
+#endif
+
+/* Defined and used in libc.so.  */
+extern int __libc_multiple_threads attribute_hidden;
+extern int __librt_multiple_threads;
+
+/* Debugging */
+
+#ifdef DEBUG
+#include <assert.h>
+#define ASSERT assert
+#define MSG __pthread_message
+#else
+#define ASSERT(x)
+#define MSG(msg,arg...)
+#endif
+
+/* Internal global functions */
+
+extern void __pthread_do_exit (void *retval, char *currentframe)
+     __attribute__ ((__noreturn__));
+extern void __pthread_destroy_specifics (void);
+extern void __pthread_perform_cleanup (char *currentframe);
+extern void __pthread_init_max_stacksize (void);
+extern int __pthread_initialize_manager (void);
+extern void __pthread_message (const char * fmt, ...);
+extern int __pthread_manager (void *reqfd);
+extern int __pthread_manager_event (void *reqfd);
+extern void __pthread_manager_sighandler (int sig);
+extern void __pthread_reset_main_thread (void);
+extern void __pthread_once_fork_prepare (void);
+extern void __pthread_once_fork_parent (void);
+extern void __pthread_once_fork_child (void);
+extern void __flockfilelist (void);
+extern void __funlockfilelist (void);
+extern void __fresetlockfiles (void);
+extern void __pthread_manager_adjust_prio (int thread_prio);
+extern void __pthread_initialize_minimal (void);
+
+extern int __pthread_attr_setguardsize (pthread_attr_t *__attr,
+					size_t __guardsize);
+extern int __pthread_attr_getguardsize (const pthread_attr_t *__attr,
+					size_t *__guardsize);
+extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr,
+					void *__stackaddr);
+extern int __pthread_attr_getstackaddr (const pthread_attr_t *__attr,
+					void **__stackaddr);
+extern int __pthread_attr_setstacksize (pthread_attr_t *__attr,
+					size_t __stacksize);
+extern int __pthread_attr_getstacksize (const pthread_attr_t *__attr,
+					size_t *__stacksize);
+extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
+				    size_t __stacksize);
+extern int __pthread_attr_getstack (const pthread_attr_t *__attr, void **__stackaddr,
+				    size_t *__stacksize);
+extern int __pthread_attr_destroy (pthread_attr_t *attr);
+extern int __pthread_attr_setdetachstate (pthread_attr_t *attr,
+					  int detachstate);
+extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr,
+					  int *detachstate);
+extern int __pthread_attr_setschedparam (pthread_attr_t *attr,
+					 const struct sched_param *param);
+extern int __pthread_attr_getschedparam (const pthread_attr_t *attr,
+					 struct sched_param *param);
+extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy);
+extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr,
+					  int *policy);
+extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit);
+extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr,
+					   int *inherit);
+extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope);
+extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope);
+
+extern int __pthread_getconcurrency (void);
+extern int __pthread_setconcurrency (int __level);
+extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex,
+				      const struct timespec *__abstime);
+extern int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *__attr,
+					   int *__pshared);
+extern int __pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
+					   int __pshared);
+extern int __pthread_mutexattr_gettype (const pthread_mutexattr_t *__attr,
+					int *__kind);
+extern void __pthread_kill_other_threads_np (void);
+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_lock (pthread_mutex_t *__mutex);
+extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
+extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+#if defined NOT_IN_libc && defined IS_IN_libpthread
+hidden_proto (__pthread_mutex_init)
+hidden_proto (__pthread_mutex_destroy)
+hidden_proto (__pthread_mutex_lock)
+hidden_proto (__pthread_mutex_trylock)
+hidden_proto (__pthread_mutex_unlock)
+#endif
+extern int __pthread_cond_init (pthread_cond_t *cond,
+				const pthread_condattr_t *cond_attr);
+extern int __pthread_cond_destroy (pthread_cond_t *cond);
+extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
+extern int __pthread_cond_timedwait (pthread_cond_t *cond,
+				     pthread_mutex_t *mutex,
+				     const struct timespec *abstime);
+extern int __pthread_cond_signal (pthread_cond_t *cond);
+extern int __pthread_cond_broadcast (pthread_cond_t *cond);
+extern int __pthread_condattr_init (pthread_condattr_t *attr);
+extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
+extern pthread_t __pthread_self (void);
+extern pthread_descr __pthread_thread_self (void);
+extern pthread_descr __pthread_self_stack (void) attribute_hidden;
+extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
+extern void __pthread_exit (void *retval);
+extern int __pthread_getschedparam (pthread_t thread, int *policy,
+				    struct sched_param *param);
+extern int __pthread_setschedparam (pthread_t thread, int policy,
+				    const struct sched_param *param);
+extern int __pthread_setcancelstate (int state, int * oldstate);
+extern int __pthread_setcanceltype (int type, int * oldtype);
+
+extern void __pthread_restart_old(pthread_descr th);
+extern void __pthread_suspend_old(pthread_descr self);
+extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abs);
+
+extern void __pthread_restart_new(pthread_descr th);
+extern void __pthread_suspend_new(pthread_descr self);
+extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abs);
+
+extern void __pthread_wait_for_restart_signal(pthread_descr self);
+
+extern void __pthread_sigsuspend (const sigset_t *mask) attribute_hidden;
+
+extern int __pthread_yield (void);
+
+extern int __pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
+					 __const struct timespec *__restrict
+					 __abstime);
+extern int __pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
+					 __const struct timespec *__restrict
+					 __abstime);
+extern int __pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr);
+
+extern int __pthread_barrierattr_getpshared (__const pthread_barrierattr_t *
+					     __restrict __attr,
+					     int *__restrict __pshared);
+
+extern int __pthread_spin_lock (pthread_spinlock_t *__lock);
+extern int __pthread_spin_trylock (pthread_spinlock_t *__lock);
+extern int __pthread_spin_unlock (pthread_spinlock_t *__lock);
+extern int __pthread_spin_init (pthread_spinlock_t *__lock, int __pshared);
+extern int __pthread_spin_destroy (pthread_spinlock_t *__lock);
+
+/* Global pointers to old or new suspend functions */
+
+extern void (*__pthread_restart)(pthread_descr);
+extern void (*__pthread_suspend)(pthread_descr);
+extern int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *);
+
+/* Prototypes for the function without cancelation support when the
+   normal version has it.  */
+extern int __libc_close (int fd);
+extern int __libc_nanosleep (const struct timespec *requested_time,
+			     struct timespec *remaining);
+/* Prototypes for some of the new semaphore functions.  */
+extern int __new_sem_post (sem_t * sem);
+extern int __new_sem_init (sem_t *__sem, int __pshared, unsigned int __value);
+extern int __new_sem_wait (sem_t *__sem);
+extern int __new_sem_trywait (sem_t *__sem);
+extern int __new_sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval);
+extern int __new_sem_destroy (sem_t *__sem);
+
+/* Prototypes for compatibility functions.  */
+extern int __pthread_attr_init_2_1 (pthread_attr_t *__attr);
+extern int __pthread_attr_init_2_0 (pthread_attr_t *__attr);
+extern int __pthread_create_2_1 (pthread_t *__restrict __threadp,
+				 const pthread_attr_t *__attr,
+				 void *(*__start_routine) (void *),
+				 void *__restrict __arg);
+extern int __pthread_create_2_0 (pthread_t *__restrict thread,
+				 const pthread_attr_t *__attr,
+				 void *(*__start_routine) (void *),
+				 void *__restrict arg);
+
+/* The functions called the signal events.  */
+extern void __linuxthreads_create_event (void);
+extern void __linuxthreads_death_event (void);
+extern void __linuxthreads_reap_event (void);
+
+/* This function is called to initialize the pthread library.  */
+extern void __pthread_initialize (void);
+
+/* TSD.  */
+extern int __pthread_internal_tsd_set (int key, const void * pointer);
+extern void * __pthread_internal_tsd_get (int key);
+extern void ** __attribute__ ((__const__))
+  __pthread_internal_tsd_address (int key);
+
+/* Sighandler wrappers.  */
+extern void __pthread_sighandler(int signo, SIGCONTEXT ctx);
+extern void __pthread_sighandler_rt(int signo, struct siginfo *si,
+				    struct ucontext *uc);
+extern void __pthread_null_sighandler(int sig);
+extern int __pthread_sigaction (int sig, const struct sigaction *act,
+				struct sigaction *oact);
+extern int __pthread_sigwait (const sigset_t *set, int *sig);
+extern int __pthread_raise (int sig);
+
+/* Cancellation.  */
+extern int __pthread_enable_asynccancel (void) attribute_hidden;
+extern void __pthread_disable_asynccancel (int oldtype)
+  internal_function attribute_hidden;
+
+/* The two functions are in libc.so and not exported.  */
+extern int __libc_enable_asynccancel (void) attribute_hidden;
+extern void __libc_disable_asynccancel (int oldtype)
+  internal_function attribute_hidden;
+
+/* The two functions are in libc.so and are exported.  */
+extern int __librt_enable_asynccancel (void);
+extern void __librt_disable_asynccancel (int oldtype) internal_function;
+
+extern void __pthread_cleanup_upto (__jmp_buf target,
+				    char *targetframe) attribute_hidden;
+extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden;
+
+#if !defined NOT_IN_libc
+# define LIBC_CANCEL_ASYNC() \
+  __libc_enable_asynccancel ()
+# define LIBC_CANCEL_RESET(oldtype) \
+  __libc_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
+#elif defined IS_IN_libpthread
+# define LIBC_CANCEL_ASYNC() \
+  __pthread_enable_asynccancel ()
+# define LIBC_CANCEL_RESET(oldtype) \
+  __pthread_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
+#elif defined IS_IN_librt
+# define LIBC_CANCEL_ASYNC() \
+  __librt_enable_asynccancel ()
+# define LIBC_CANCEL_RESET(oldtype) \
+  __librt_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__librt_disable_asynccancel")
+#else
+# define LIBC_CANCEL_ASYNC()    0 /* Just a dummy value.  */
+# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it.  */
+# define LIBC_CANCEL_HANDLED()	/* Nothing.  */
+#endif
+
+extern int * __libc_pthread_init (const struct pthread_functions *functions);
+
+#if !defined NOT_IN_libc && !defined FLOATING_STACKS
+# ifdef SHARED
+#  define thread_self() \
+  (*__libc_pthread_functions.ptr_pthread_thread_self) ()
+# else
+weak_extern (__pthread_thread_self)
+#  define thread_self() __pthread_thread_self ()
+# endif
+#endif
+
+#ifndef USE_TLS
+# define __manager_thread (&__pthread_manager_thread)
+#else
+# define __manager_thread __pthread_manager_threadp
+#endif
+
+extern inline __attribute__((always_inline)) pthread_descr
+check_thread_self (void)
+{
+  pthread_descr self = thread_self ();
+#if defined THREAD_SELF && defined INIT_THREAD_SELF
+  if (self == __manager_thread)
+    {
+      /* A new thread might get a cancel signal before it is fully
+	 initialized, so that the thread register might still point to the
+	 manager thread.  Double check that this is really the manager
+	 thread.  */
+      self = __pthread_self_stack();
+      if (self != __manager_thread)
+	/* Oops, thread_self() isn't working yet..  */
+	INIT_THREAD_SELF(self, self->p_nr);
+    }
+#endif
+  return self;
+}
+
+#endif /* internals.h */
diff --git a/linuxthreads/join.c b/linuxthreads/join.c
new file mode 100644
index 0000000000..148f222319
--- /dev/null
+++ b/linuxthreads/join.c
@@ -0,0 +1,220 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Thread termination and joining */
+
+#include <errno.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include <not-cancel.h>
+
+void __pthread_exit(void * retval)
+{
+  __pthread_do_exit (retval, CURRENT_STACK_FRAME);
+}
+strong_alias (__pthread_exit, pthread_exit);
+
+void __pthread_do_exit(void *retval, char *currentframe)
+{
+  pthread_descr self = thread_self();
+  pthread_descr joining;
+  struct pthread_request request;
+
+  /* Reset the cancellation flag to avoid looping if the cleanup handlers
+     contain cancellation points */
+  THREAD_SETMEM(self, p_canceled, 0);
+  /* Call cleanup functions and destroy the thread-specific data */
+  __pthread_perform_cleanup(currentframe);
+  __pthread_destroy_specifics();
+  /* Store return value */
+  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
+  THREAD_SETMEM(self, p_retval, retval);
+  /* See whether we have to signal the death.  */
+  if (THREAD_GETMEM(self, p_report_events))
+    {
+      /* See whether TD_DEATH is in any of the mask.  */
+      int idx = __td_eventword (TD_DEATH);
+      uint32_t mask = __td_eventmask (TD_DEATH);
+
+      if ((mask & (__pthread_threads_events.event_bits[idx]
+		   | THREAD_GETMEM_NC(self,
+				      p_eventbuf.eventmask.event_bits[idx])))
+	  != 0)
+	{
+	  /* Yep, we have to signal the death.  */
+	  THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
+	  THREAD_SETMEM(self, p_eventbuf.eventdata, self);
+	  __pthread_last_event = self;
+
+	  /* Now call the function to signal the event.  */
+	  __linuxthreads_death_event();
+	}
+    }
+  /* Say that we've terminated */
+  THREAD_SETMEM(self, p_terminated, 1);
+  /* See if someone is joining on us */
+  joining = THREAD_GETMEM(self, p_joining);
+  __pthread_unlock(THREAD_GETMEM(self, p_lock));
+  /* Restart joining thread if any */
+  if (joining != NULL) restart(joining);
+  /* If this is the initial thread, block until all threads have terminated.
+     If another thread calls exit, we'll be terminated from our signal
+     handler. */
+  if (self == __pthread_main_thread && __pthread_manager_request >= 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_MAIN_THREAD_EXIT;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *)&request, sizeof(request)));
+    suspend(self);
+    /* Main thread flushes stdio streams and runs atexit functions.
+       It also calls a handler within LinuxThreads which sends a process exit
+       request to the thread manager. */
+    exit(0);
+  }
+  /* Threads other than the main one  terminate without flushing stdio streams
+     or running atexit functions. */
+  _exit(0);
+}
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting on a condition variable queue. */
+
+static int join_extricate_func(void *obj, pthread_descr th)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_handle handle = obj;
+  pthread_descr jo;
+  int did_remove = 0;
+
+  __pthread_lock(&handle->h_lock, self);
+  jo = handle->h_descr;
+  did_remove = jo->p_joining != NULL;
+  jo->p_joining = NULL;
+  __pthread_unlock(&handle->h_lock);
+
+  return did_remove;
+}
+
+int pthread_join(pthread_t thread_id, void ** thread_return)
+{
+  volatile pthread_descr self = thread_self();
+  struct pthread_request request;
+  pthread_handle handle = thread_handle(thread_id);
+  pthread_descr th;
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+
+  /* Set up extrication interface */
+  extr.pu_object = handle;
+  extr.pu_extricate_func = join_extricate_func;
+
+  __pthread_lock(&handle->h_lock, self);
+  if (nonexisting_handle(handle, thread_id)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  if (th == self) {
+    __pthread_unlock(&handle->h_lock);
+    return EDEADLK;
+  }
+  /* If detached or already joined, error */
+  if (th->p_detached || th->p_joining != NULL) {
+    __pthread_unlock(&handle->h_lock);
+    return EINVAL;
+  }
+  /* If not terminated yet, suspend ourselves. */
+  if (! th->p_terminated) {
+    /* Register extrication interface */
+    __pthread_set_own_extricate_if(self, &extr);
+    if (!(THREAD_GETMEM(self, p_canceled)
+	&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+      th->p_joining = self;
+    else
+      already_canceled = 1;
+    __pthread_unlock(&handle->h_lock);
+
+    if (already_canceled) {
+      __pthread_set_own_extricate_if(self, 0);
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    }
+
+    suspend(self);
+    /* Deregister extrication interface */
+    __pthread_set_own_extricate_if(self, 0);
+
+    /* This is a cancellation point */
+    if (THREAD_GETMEM(self, p_woken_by_cancel)
+	&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+      THREAD_SETMEM(self, p_woken_by_cancel, 0);
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    }
+    __pthread_lock(&handle->h_lock, self);
+  }
+  /* Get return value */
+  if (thread_return != NULL) *thread_return = th->p_retval;
+  __pthread_unlock(&handle->h_lock);
+  /* Send notification to thread manager */
+  if (__pthread_manager_request >= 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_FREE;
+    request.req_args.free.thread_id = thread_id;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+  }
+  return 0;
+}
+
+int pthread_detach(pthread_t thread_id)
+{
+  int terminated;
+  struct pthread_request request;
+  pthread_handle handle = thread_handle(thread_id);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (nonexisting_handle(handle, thread_id)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  /* If already detached, error */
+  if (th->p_detached) {
+    __pthread_unlock(&handle->h_lock);
+    return EINVAL;
+  }
+  /* If already joining, don't do anything. */
+  if (th->p_joining != NULL) {
+    __pthread_unlock(&handle->h_lock);
+    return 0;
+  }
+  /* Mark as detached */
+  th->p_detached = 1;
+  terminated = th->p_terminated;
+  __pthread_unlock(&handle->h_lock);
+  /* If already terminated, notify thread manager to reclaim resources */
+  if (terminated && __pthread_manager_request >= 0) {
+    request.req_thread = thread_self();
+    request.req_kind = REQ_FREE;
+    request.req_args.free.thread_id = thread_id;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+  }
+  return 0;
+}
diff --git a/linuxthreads/joinrace.c b/linuxthreads/joinrace.c
new file mode 100644
index 0000000000..8e1064c984
--- /dev/null
+++ b/linuxthreads/joinrace.c
@@ -0,0 +1,48 @@
+/* Test case by Permaine Cheung <pcheung@cygnus.com>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void *
+sub1 (void *arg)
+{
+  /* Nothing.  */
+  return NULL;
+}
+
+int
+main (void)
+{
+  int istatus;
+  int policy;
+  int cnt;
+  pthread_t thread1;
+  struct sched_param spresult1, sp1;
+
+  for (cnt = 0; cnt < 100; ++cnt)
+    {
+      printf ("Round %d\n", cnt);
+
+      pthread_create (&thread1, NULL, &sub1, NULL);
+      pthread_join (thread1, NULL);
+
+      istatus = pthread_getschedparam (thread1, &policy, &spresult1);
+      if (istatus != ESRCH)
+	{
+	  printf ("pthread_getschedparam returns: %d\n", istatus);
+	  return 1;
+	}
+
+      sp1.sched_priority = 0;
+      istatus = pthread_setschedparam (thread1, SCHED_OTHER, &sp1);
+      if (istatus != ESRCH)
+	{
+	  printf ("pthread_setschedparam returns: %d\n", istatus);
+	  return 2;
+	}
+    }
+
+  return 0;
+}
diff --git a/linuxthreads/libc-cancellation.c b/linuxthreads/libc-cancellation.c
new file mode 100644
index 0000000000..c28920feb3
--- /dev/null
+++ b/linuxthreads/libc-cancellation.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <rpc/rpc.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include <bits/libc-lock.h>
+
+#if !defined NOT_IN_libc
+
+# ifndef SHARED
+weak_extern (__pthread_do_exit)
+# endif
+
+int __libc_multiple_threads attribute_hidden __attribute__((nocommon));
+strong_alias (__libc_multiple_threads, __librt_multiple_threads);
+
+/* The next two functions are similar to pthread_setcanceltype() but
+   more specialized for the use in the cancelable functions like write().
+   They do not need to check parameters etc.  */
+int
+attribute_hidden
+__libc_enable_asynccancel (void)
+{
+  pthread_descr self = thread_self();
+  int oldtype = LIBC_THREAD_GETMEM(self, p_canceltype);
+  LIBC_THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
+  if (__builtin_expect (LIBC_THREAD_GETMEM(self, p_canceled), 0) &&
+      LIBC_THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    __libc_maybe_call2 (pthread_do_exit,
+			(PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0);
+  return oldtype;
+}
+strong_alias (__libc_enable_asynccancel, __librt_enable_asynccancel)
+
+void
+internal_function attribute_hidden
+__libc_disable_asynccancel (int oldtype)
+{
+  pthread_descr self = thread_self();
+  LIBC_THREAD_SETMEM(self, p_canceltype, oldtype);
+}
+strong_alias (__libc_disable_asynccancel, __librt_disable_asynccancel)
+
+#endif
diff --git a/linuxthreads/libc-tls-loc.c b/linuxthreads/libc-tls-loc.c
new file mode 100644
index 0000000000..a0a4b1b07d
--- /dev/null
+++ b/linuxthreads/libc-tls-loc.c
@@ -0,0 +1,49 @@
+/* Special definitions for libc's own exposed thread-specific variables.
+   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; 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 <tls.h>
+
+#if USE___THREAD
+# include <errno.h>
+# include <netdb.h>
+# include <resolv.h>
+
+/* These functions have identical definitions in libc.  But the versioned
+   dependencies in executables bind them to libpthread.so definitions,
+   so we must have some here.  */
+
+int *
+__errno_location (void)
+{
+  return &errno;
+}
+
+int *
+__h_errno_location (void)
+{
+  return &h_errno;
+}
+
+struct __res_state *
+__res_state (void)
+{
+  return __resp;
+}
+
+#endif
diff --git a/linuxthreads/libc-tsd.c b/linuxthreads/libc-tsd.c
new file mode 100644
index 0000000000..353ffb380a
--- /dev/null
+++ b/linuxthreads/libc-tsd.c
@@ -0,0 +1,41 @@
+/* Special hack used to build link-time libc.so object for linking libpthread.
+   Copyright (C) 2002, 2004 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 <tls.h>
+#include <resolv.h>
+
+#if ! USE___THREAD
+
+/* Special hack used to build link-time libc.so object for linking libpthread.
+   See Makefile comments near libc_pic_lite.os rule for what this is for.  */
+
+# undef _res
+
+int _errno;
+int _h_errno;
+struct __res_state _res;
+
+#endif
+
+int
+__res_maybe_init (res_state resp, int preinit)
+{
+  return -1;
+}
+libc_hidden_def (__res_maybe_init)
diff --git a/linuxthreads/libc_pthread_init.c b/linuxthreads/libc_pthread_init.c
new file mode 100644
index 0000000000..99213a2ff0
--- /dev/null
+++ b/linuxthreads/libc_pthread_init.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tls.h>
+#include "internals.h"
+#include <sysdep-cancel.h>
+
+int *
+__libc_pthread_init (functions)
+     const struct pthread_functions *functions;
+{
+#ifdef SHARED
+  /* We copy the content of the variable pointed to by the FUNCTIONS
+     parameter to one in libc.so since this means access to the array
+     can be done with one memory access instead of two.  */
+  memcpy (&__libc_pthread_functions, functions,
+	  sizeof (__libc_pthread_functions));
+#endif
+
+#if !(USE_TLS && HAVE___THREAD)
+  /* Initialize thread-locale current locale to point to the global one.
+     With __thread support, the variable's initializer takes care of this.  */
+  __uselocale (LC_GLOBAL_LOCALE);
+#endif
+
+  return &__libc_multiple_threads;
+}
diff --git a/linuxthreads/linuxthreads.texi b/linuxthreads/linuxthreads.texi
new file mode 100644
index 0000000000..795fb70977
--- /dev/null
+++ b/linuxthreads/linuxthreads.texi
@@ -0,0 +1,1627 @@
+@node POSIX Threads
+@c @node POSIX Threads, , Top, Top
+@chapter POSIX Threads
+@c %MENU% The standard threads library
+
+@c This chapter needs more work bigtime. -zw
+
+This chapter describes the pthreads (POSIX threads) library.  This
+library provides support functions for multithreaded programs: thread
+primitives, synchronization objects, and so forth.  It also implements
+POSIX 1003.1b semaphores (not to be confused with System V semaphores).
+
+The threads operations (@samp{pthread_*}) do not use @var{errno}.
+Instead they return an error code directly.  The semaphore operations do
+use @var{errno}.
+
+@menu
+* Basic Thread Operations::     Creating, terminating, and waiting for threads.
+* Thread Attributes::           Tuning thread scheduling.
+* Cancellation::                Stopping a thread before it's done.
+* Cleanup Handlers::            Deallocating resources when a thread is
+                                  canceled.
+* Mutexes::                     One way to synchronize threads.
+* Condition Variables::         Another way.
+* POSIX Semaphores::            And a third way.
+* Thread-Specific Data::        Variables with different values in
+                                  different threads.
+* Threads and Signal Handling:: Why you should avoid mixing the two, and
+                                  how to do it if you must.
+* Threads and Fork::            Interactions between threads and the
+                                  @code{fork} function.
+* Streams and Fork::            Interactions between stdio streams and
+                                  @code{fork}.
+* Miscellaneous Thread Functions:: A grab bag of utility routines.
+@end menu
+
+@node Basic Thread Operations
+@section Basic Thread Operations
+
+These functions are the thread equivalents of @code{fork}, @code{exit},
+and @code{wait}.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_create (pthread_t * @var{thread}, pthread_attr_t * @var{attr}, void * (*@var{start_routine})(void *), void * @var{arg})
+@code{pthread_create} creates a new thread of control that executes
+concurrently with the calling thread. The new thread calls the
+function @var{start_routine}, passing it @var{arg} as first argument. The
+new thread terminates either explicitly, by calling @code{pthread_exit},
+or implicitly, by returning from the @var{start_routine} function. The
+latter case is equivalent to calling @code{pthread_exit} with the result
+returned by @var{start_routine} as exit code.
+
+The @var{attr} argument specifies thread attributes to be applied to the
+new thread. @xref{Thread Attributes}, for details. The @var{attr}
+argument can also be @code{NULL}, in which case default attributes are
+used: the created thread is joinable (not detached) and has an ordinary
+(not realtime) scheduling policy.
+
+On success, the identifier of the newly created thread is stored in the
+location pointed by the @var{thread} argument, and a 0 is returned. On
+error, a non-zero error code is returned.
+
+This function may return the following errors:
+@table @code
+@item EAGAIN
+Not enough system resources to create a process for the new thread,
+or more than @code{PTHREAD_THREADS_MAX} threads are already active.
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun void pthread_exit (void *@var{retval})
+@code{pthread_exit} terminates the execution of the calling thread.  All
+cleanup handlers (@pxref{Cleanup Handlers}) that have been set for the
+calling thread with @code{pthread_cleanup_push} are executed in reverse
+order (the most recently pushed handler is executed first). Finalization
+functions for thread-specific data are then called for all keys that
+have non-@code{NULL} values associated with them in the calling thread
+(@pxref{Thread-Specific Data}).  Finally, execution of the calling
+thread is stopped.
+
+The @var{retval} argument is the return value of the thread. It can be
+retrieved from another thread using @code{pthread_join}.
+
+The @code{pthread_exit} function never returns.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cancel (pthread_t @var{thread})
+
+@code{pthread_cancel} sends a cancellation request to the thread denoted
+by the @var{thread} argument.  If there is no such thread,
+@code{pthread_cancel} fails and returns @code{ESRCH}.  Otherwise it
+returns 0. @xref{Cancellation}, for details.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return})
+@code{pthread_join} suspends the execution of the calling thread until
+the thread identified by @var{th} terminates, either by calling
+@code{pthread_exit} or by being canceled.
+
+If @var{thread_return} is not @code{NULL}, the return value of @var{th}
+is stored in the location pointed to by @var{thread_return}.  The return
+value of @var{th} is either the argument it gave to @code{pthread_exit},
+or @code{PTHREAD_CANCELED} if @var{th} was canceled.
+
+The joined thread @code{th} must be in the joinable state: it must not
+have been detached using @code{pthread_detach} or the
+@code{PTHREAD_CREATE_DETACHED} attribute to @code{pthread_create}.
+
+When a joinable thread terminates, its memory resources (thread
+descriptor and stack) are not deallocated until another thread performs
+@code{pthread_join} on it. Therefore, @code{pthread_join} must be called
+once for each joinable thread created to avoid memory leaks.
+
+At most one thread can wait for the termination of a given
+thread. Calling @code{pthread_join} on a thread @var{th} on which
+another thread is already waiting for termination returns an error.
+
+@code{pthread_join} is a cancellation point. If a thread is canceled
+while suspended in @code{pthread_join}, the thread execution resumes
+immediately and the cancellation is executed without waiting for the
+@var{th} thread to terminate. If cancellation occurs during
+@code{pthread_join}, the @var{th} thread remains not joined.
+
+On success, the return value of @var{th} is stored in the location
+pointed to by @var{thread_return}, and 0 is returned. On error, one of
+the following values is returned:
+@table @code
+@item ESRCH
+No thread could be found corresponding to that specified by @var{th}.
+@item EINVAL
+The @var{th} thread has been detached, or another thread is already
+waiting on termination of @var{th}.
+@item EDEADLK
+The @var{th} argument refers to the calling thread.
+@end table
+@end deftypefun
+
+@node Thread Attributes
+@section Thread Attributes
+
+@comment pthread.h
+@comment POSIX
+
+Threads have a number of attributes that may be set at creation time.
+This is done by filling a thread attribute object @var{attr} of type
+@code{pthread_attr_t}, then passing it as second argument to
+@code{pthread_create}. Passing @code{NULL} is equivalent to passing a
+thread attribute object with all attributes set to their default values.
+
+Attribute objects are consulted only when creating a new thread.  The
+same attribute object can be used for creating several threads.
+Modifying an attribute object after a call to @code{pthread_create} does
+not change the attributes of the thread previously created.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_attr_init (pthread_attr_t *@var{attr})
+@code{pthread_attr_init} initializes the thread attribute object
+@var{attr} and fills it with default values for the attributes. (The
+default values are listed below for each attribute.)
+
+Each attribute @var{attrname} (see below for a list of all attributes)
+can be individually set using the function
+@code{pthread_attr_set@var{attrname}} and retrieved using the function
+@code{pthread_attr_get@var{attrname}}.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_attr_destroy (pthread_attr_t *@var{attr})
+@code{pthread_attr_destroy} destroys the attribute object pointed to by
+@var{attr} releasing any resources associated with it.  @var{attr} is
+left in an undefined state, and you must not use it again in a call to
+any pthreads function until it has been reinitialized.
+@end deftypefun
+
+@findex pthread_attr_setdetachstate
+@findex pthread_attr_setguardsize
+@findex pthread_attr_setinheritsched
+@findex pthread_attr_setschedparam
+@findex pthread_attr_setschedpolicy
+@findex pthread_attr_setscope
+@findex pthread_attr_setstack
+@findex pthread_attr_setstackaddr
+@findex pthread_attr_setstacksize
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value})
+Set attribute @var{attr} to @var{value} in the attribute object pointed
+to by @var{obj}.  See below for a list of possible attributes and the
+values they can take.
+
+On success, these functions return 0.  If @var{value} is not meaningful
+for the @var{attr} being modified, they will return the error code
+@code{EINVAL}.  Some of the functions have other failure modes; see
+below.
+@end deftypefun
+
+@findex pthread_attr_getdetachstate
+@findex pthread_attr_getguardsize
+@findex pthread_attr_getinheritsched
+@findex pthread_attr_getschedparam
+@findex pthread_attr_getschedpolicy
+@findex pthread_attr_getscope
+@findex pthread_attr_getstack
+@findex pthread_attr_getstackaddr
+@findex pthread_attr_getstacksize
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value})
+Store the current setting of @var{attr} in @var{obj} into the variable
+pointed to by @var{value}.
+
+These functions always return 0.
+@end deftypefun
+
+The following thread attributes are supported:
+@table @samp
+@item detachstate
+Choose whether the thread is created in the joinable state (value
+@code{PTHREAD_CREATE_JOINABLE}) or in the detached state
+(@code{PTHREAD_CREATE_DETACHED}).  The default is
+@code{PTHREAD_CREATE_JOINABLE}.
+
+In the joinable state, another thread can synchronize on the thread
+termination and recover its termination code using @code{pthread_join},
+but some of the thread resources are kept allocated after the thread
+terminates, and reclaimed only when another thread performs
+@code{pthread_join} on that thread.
+
+In the detached state, the thread resources are immediately freed when
+it terminates, but @code{pthread_join} cannot be used to synchronize on
+the thread termination.
+
+A thread created in the joinable state can later be put in the detached
+thread using @code{pthread_detach}.
+
+@item schedpolicy
+Select the scheduling policy for the thread: one of @code{SCHED_OTHER}
+(regular, non-realtime scheduling), @code{SCHED_RR} (realtime,
+round-robin) or @code{SCHED_FIFO} (realtime, first-in first-out).
+The default is @code{SCHED_OTHER}.
+@c Not doc'd in our manual: FIXME.
+@c See @code{sched_setpolicy} for more information on scheduling policies.
+
+The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO}
+are available only to processes with superuser privileges.
+@code{pthread_attr_setschedparam} will fail and return @code{ENOTSUP} if
+you try to set a realtime policy when you are unprivileged.
+
+The scheduling policy of a thread can be changed after creation with
+@code{pthread_setschedparam}.
+
+@item schedparam
+Change the scheduling parameter (the scheduling priority)
+for the thread.  The default is 0.
+
+This attribute is not significant if the scheduling policy is
+@code{SCHED_OTHER}; it only matters for the realtime policies
+@code{SCHED_RR} and @code{SCHED_FIFO}.
+
+The scheduling priority of a thread can be changed after creation with
+@code{pthread_setschedparam}.
+
+@item inheritsched
+Choose whether the scheduling policy and scheduling parameter for the
+newly created thread are determined by the values of the
+@var{schedpolicy} and @var{schedparam} attributes (value
+@code{PTHREAD_EXPLICIT_SCHED}) or are inherited from the parent thread
+(value @code{PTHREAD_INHERIT_SCHED}).  The default is
+@code{PTHREAD_EXPLICIT_SCHED}.
+
+@item scope
+Choose the scheduling contention scope for the created thread.  The
+default is @code{PTHREAD_SCOPE_SYSTEM}, meaning that the threads contend
+for CPU time with all processes running on the machine. In particular,
+thread priorities are interpreted relative to the priorities of all
+other processes on the machine. The other possibility,
+@code{PTHREAD_SCOPE_PROCESS}, means that scheduling contention occurs
+only between the threads of the running process: thread priorities are
+interpreted relative to the priorities of the other threads of the
+process, regardless of the priorities of other processes.
+
+@code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads.  If you
+try to set the scope to this value, @code{pthread_attr_setscope} will
+fail and return @code{ENOTSUP}.
+
+@item stackaddr
+Provide an address for an application managed stack.  The size of the
+stack must be at least @code{PTHREAD_STACK_MIN}.
+
+@item stacksize
+Change the size of the stack created for the thread.  The value defines
+the minimum stack size, in bytes.
+
+If the value exceeds the system's maximum stack size, or is smaller
+than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will
+fail and return @code{EINVAL}.
+
+@item stack
+Provide both the address and size of an application managed stack to
+use for the new thread.  The base of the memory area is @var{stackaddr}
+with the size of the memory area, @var{stacksize}, measured in bytes.
+
+If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN},
+or greater than the system's maximum stack size, or if the value of
+@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack}
+will fail and return @code{EINVAL}.
+
+@item guardsize
+Change the minimum size in bytes of the guard area for the thread's
+stack.  The default size is a single page.  If this value is set, it
+will be rounded up to the nearest page size.  If the value is set to 0,
+a guard area will not be created for this thread.  The space allocated
+for the guard area is used to catch stack overflow.  Therefore, when
+allocating large structures on the stack, a larger guard area may be
+required to catch a stack overflow.
+
+If the caller is managing their own stacks (if the @code{stackaddr}
+attribute has been set), then the @code{guardsize} attribute is ignored.
+
+If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize}
+will fail and return @code{EINVAL}.
+@end table
+
+@node Cancellation
+@section Cancellation
+
+Cancellation is the mechanism by which a thread can terminate the
+execution of another thread. More precisely, a thread can send a
+cancellation request to another thread. Depending on its settings, the
+target thread can then either ignore the request, honor it immediately,
+or defer it till it reaches a cancellation point.  When threads are
+first created by @code{pthread_create}, they always defer cancellation
+requests.
+
+When a thread eventually honors a cancellation request, it behaves as if
+@code{pthread_exit(PTHREAD_CANCELED)} was called.  All cleanup handlers
+are executed in reverse order, finalization functions for
+thread-specific data are called, and finally the thread stops executing.
+If the canceled thread was joinable, the return value
+@code{PTHREAD_CANCELED} is provided to whichever thread calls
+@var{pthread_join} on it. See @code{pthread_exit} for more information.
+
+Cancellation points are the points where the thread checks for pending
+cancellation requests and performs them.  The POSIX threads functions
+@code{pthread_join}, @code{pthread_cond_wait},
+@code{pthread_cond_timedwait}, @code{pthread_testcancel},
+@code{sem_wait}, and @code{sigwait} are cancellation points.  In
+addition, these system calls are cancellation points:
+
+@multitable @columnfractions .33 .33 .33
+@item @t{accept}	@tab @t{open}		@tab @t{sendmsg}
+@item @t{close}		@tab @t{pause}		@tab @t{sendto}
+@item @t{connect}	@tab @t{read}		@tab @t{system}
+@item @t{fcntl}		@tab @t{recv}		@tab @t{tcdrain}
+@item @t{fsync}		@tab @t{recvfrom}	@tab @t{wait}
+@item @t{lseek}		@tab @t{recvmsg}	@tab @t{waitpid}
+@item @t{msync}		@tab @t{send}		@tab @t{write}
+@item @t{nanosleep}
+@end multitable
+
+@noindent
+All library functions that call these functions (such as
+@code{printf}) are also cancellation points.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setcancelstate (int @var{state}, int *@var{oldstate})
+@code{pthread_setcancelstate} changes the cancellation state for the
+calling thread -- that is, whether cancellation requests are ignored or
+not. The @var{state} argument is the new cancellation state: either
+@code{PTHREAD_CANCEL_ENABLE} to enable cancellation, or
+@code{PTHREAD_CANCEL_DISABLE} to disable cancellation (cancellation
+requests are ignored).
+
+If @var{oldstate} is not @code{NULL}, the previous cancellation state is
+stored in the location pointed to by @var{oldstate}, and can thus be
+restored later by another call to @code{pthread_setcancelstate}.
+
+If the @var{state} argument is not @code{PTHREAD_CANCEL_ENABLE} or
+@code{PTHREAD_CANCEL_DISABLE}, @code{pthread_setcancelstate} fails and
+returns @code{EINVAL}.  Otherwise it returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setcanceltype (int @var{type}, int *@var{oldtype})
+@code{pthread_setcanceltype} changes the type of responses to
+cancellation requests for the calling thread: asynchronous (immediate)
+or deferred.  The @var{type} argument is the new cancellation type:
+either @code{PTHREAD_CANCEL_ASYNCHRONOUS} to cancel the calling thread
+as soon as the cancellation request is received, or
+@code{PTHREAD_CANCEL_DEFERRED} to keep the cancellation request pending
+until the next cancellation point. If @var{oldtype} is not @code{NULL},
+the previous cancellation state is stored in the location pointed to by
+@var{oldtype}, and can thus be restored later by another call to
+@code{pthread_setcanceltype}.
+
+If the @var{type} argument is not @code{PTHREAD_CANCEL_DEFERRED} or
+@code{PTHREAD_CANCEL_ASYNCHRONOUS}, @code{pthread_setcanceltype} fails
+and returns @code{EINVAL}.  Otherwise it returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun void pthread_testcancel (@var{void})
+@code{pthread_testcancel} does nothing except testing for pending
+cancellation and executing it. Its purpose is to introduce explicit
+checks for cancellation in long sequences of code that do not call
+cancellation point functions otherwise.
+@end deftypefun
+
+@node Cleanup Handlers
+@section Cleanup Handlers
+
+Cleanup handlers are functions that get called when a thread terminates,
+either by calling @code{pthread_exit} or because of
+cancellation. Cleanup handlers are installed and removed following a
+stack-like discipline.
+
+The purpose of cleanup handlers is to free the resources that a thread
+may hold at the time it terminates. In particular, if a thread exits or
+is canceled while it owns a locked mutex, the mutex will remain locked
+forever and prevent other threads from executing normally. The best way
+to avoid this is, just before locking the mutex, to install a cleanup
+handler whose effect is to unlock the mutex. Cleanup handlers can be
+used similarly to free blocks allocated with @code{malloc} or close file
+descriptors on thread termination.
+
+Here is how to lock a mutex @var{mut} in such a way that it will be
+unlocked if the thread is canceled while @var{mut} is locked:
+
+@smallexample
+pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_mutex_unlock(&mut);
+pthread_cleanup_pop(0);
+@end smallexample
+
+Equivalently, the last two lines can be replaced by
+
+@smallexample
+pthread_cleanup_pop(1);
+@end smallexample
+
+Notice that the code above is safe only in deferred cancellation mode
+(see @code{pthread_setcanceltype}). In asynchronous cancellation mode, a
+cancellation can occur between @code{pthread_cleanup_push} and
+@code{pthread_mutex_lock}, or between @code{pthread_mutex_unlock} and
+@code{pthread_cleanup_pop}, resulting in both cases in the thread trying
+to unlock a mutex not locked by the current thread. This is the main
+reason why asynchronous cancellation is difficult to use.
+
+If the code above must also work in asynchronous cancellation mode,
+then it must switch to deferred mode for locking and unlocking the
+mutex:
+
+@smallexample
+pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
+pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_cleanup_pop(1);
+pthread_setcanceltype(oldtype, NULL);
+@end smallexample
+
+The code above can be rewritten in a more compact and efficient way,
+using the non-portable functions @code{pthread_cleanup_push_defer_np}
+and @code{pthread_cleanup_pop_restore_np}:
+
+@smallexample
+pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_cleanup_pop_restore_np(1);
+@end smallexample
+
+@comment pthread.h
+@comment POSIX
+@deftypefun void pthread_cleanup_push (void (*@var{routine}) (void *), void *@var{arg})
+
+@code{pthread_cleanup_push} installs the @var{routine} function with
+argument @var{arg} as a cleanup handler. From this point on to the
+matching @code{pthread_cleanup_pop}, the function @var{routine} will be
+called with arguments @var{arg} when the thread terminates, either
+through @code{pthread_exit} or by cancellation. If several cleanup
+handlers are active at that point, they are called in LIFO order: the
+most recently installed handler is called first.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun void pthread_cleanup_pop (int @var{execute})
+@code{pthread_cleanup_pop} removes the most recently installed cleanup
+handler. If the @var{execute} argument is not 0, it also executes the
+handler, by calling the @var{routine} function with arguments
+@var{arg}. If the @var{execute} argument is 0, the handler is only
+removed but not executed.
+@end deftypefun
+
+Matching pairs of @code{pthread_cleanup_push} and
+@code{pthread_cleanup_pop} must occur in the same function, at the same
+level of block nesting.  Actually, @code{pthread_cleanup_push} and
+@code{pthread_cleanup_pop} are macros, and the expansion of
+@code{pthread_cleanup_push} introduces an open brace @code{@{} with the
+matching closing brace @code{@}} being introduced by the expansion of the
+matching @code{pthread_cleanup_pop}.
+
+@comment pthread.h
+@comment GNU
+@deftypefun void pthread_cleanup_push_defer_np (void (*@var{routine}) (void *), void *@var{arg})
+@code{pthread_cleanup_push_defer_np} is a non-portable extension that
+combines @code{pthread_cleanup_push} and @code{pthread_setcanceltype}.
+It pushes a cleanup handler just as @code{pthread_cleanup_push} does,
+but also saves the current cancellation type and sets it to deferred
+cancellation. This ensures that the cleanup mechanism is effective even
+if the thread was initially in asynchronous cancellation mode.
+@end deftypefun
+
+@comment pthread.h
+@comment GNU
+@deftypefun void pthread_cleanup_pop_restore_np (int @var{execute})
+@code{pthread_cleanup_pop_restore_np} pops a cleanup handler introduced
+by @code{pthread_cleanup_push_defer_np}, and restores the cancellation
+type to its value at the time @code{pthread_cleanup_push_defer_np} was
+called.
+@end deftypefun
+
+@code{pthread_cleanup_push_defer_np} and
+@code{pthread_cleanup_pop_restore_np} must occur in matching pairs, at
+the same level of block nesting.
+
+The sequence
+
+@smallexample
+pthread_cleanup_push_defer_np(routine, arg);
+...
+pthread_cleanup_pop_restore_np(execute);
+@end smallexample
+
+@noindent
+is functionally equivalent to (but more compact and efficient than)
+
+@smallexample
+@{
+  int oldtype;
+  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
+  pthread_cleanup_push(routine, arg);
+  ...
+  pthread_cleanup_pop(execute);
+  pthread_setcanceltype(oldtype, NULL);
+@}
+@end smallexample
+
+
+@node Mutexes
+@section Mutexes
+
+A mutex is a MUTual EXclusion device, and is useful for protecting
+shared data structures from concurrent modifications, and implementing
+critical sections and monitors.
+
+A mutex has two possible states: unlocked (not owned by any thread),
+and locked (owned by one thread). A mutex can never be owned by two
+different threads simultaneously. A thread attempting to lock a mutex
+that is already locked by another thread is suspended until the owning
+thread unlocks the mutex first.
+
+None of the mutex functions is a cancellation point, not even
+@code{pthread_mutex_lock}, in spite of the fact that it can suspend a
+thread for arbitrary durations. This way, the status of mutexes at
+cancellation points is predictable, allowing cancellation handlers to
+unlock precisely those mutexes that need to be unlocked before the
+thread stops executing. Consequently, threads using deferred
+cancellation should never hold a mutex for extended periods of time.
+
+It is not safe to call mutex functions from a signal handler.  In
+particular, calling @code{pthread_mutex_lock} or
+@code{pthread_mutex_unlock} from a signal handler may deadlock the
+calling thread.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_init (pthread_mutex_t *@var{mutex}, const pthread_mutexattr_t *@var{mutexattr})
+
+@code{pthread_mutex_init} initializes the mutex object pointed to by
+@var{mutex} according to the mutex attributes specified in @var{mutexattr}.
+If @var{mutexattr} is @code{NULL}, default attributes are used instead.
+
+The LinuxThreads implementation supports only one mutex attribute,
+the @var{mutex type}, which is either ``fast'', ``recursive'', or
+``error checking''. The type of a mutex determines whether
+it can be locked again by a thread that already owns it.
+The default type is ``fast''.
+
+Variables of type @code{pthread_mutex_t} can also be initialized
+statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for
+timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for
+recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}
+(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP}
+(for error checking mutexes).
+
+@code{pthread_mutex_init} always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_lock (pthread_mutex_t *mutex))
+@code{pthread_mutex_lock} locks the given mutex. If the mutex is
+currently unlocked, it becomes locked and owned by the calling thread,
+and @code{pthread_mutex_lock} returns immediately. If the mutex is
+already locked by another thread, @code{pthread_mutex_lock} suspends the
+calling thread until the mutex is unlocked.
+
+If the mutex is already locked by the calling thread, the behavior of
+@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex
+is of the ``fast'' type, the calling thread is suspended.  It will
+remain suspended forever, because no other thread can unlock the mutex.
+If  the mutex is of the ``error checking'' type, @code{pthread_mutex_lock}
+returns immediately with the error code @code{EDEADLK}.  If the mutex is
+of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and
+returns immediately, recording the number of times the calling thread
+has locked the mutex. An equal number of @code{pthread_mutex_unlock}
+operations must be performed before the mutex returns to the unlocked
+state.
+@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_trylock (pthread_mutex_t *@var{mutex})
+@code{pthread_mutex_trylock} behaves identically to
+@code{pthread_mutex_lock}, except that it does not block the calling
+thread if the mutex is already locked by another thread (or by the
+calling thread in the case of a ``fast'' mutex). Instead,
+@code{pthread_mutex_trylock} returns immediately with the error code
+@code{EBUSY}.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime})
+The @code{pthread_mutex_timedlock} is similar to the
+@code{pthread_mutex_lock} function but instead of blocking for in
+indefinite time if the mutex is locked by another thread, it returns
+when the time specified in @var{abstime} is reached.
+
+This function can only be used on standard (``timed'') and ``error
+checking'' mutexes.  It behaves just like @code{pthread_mutex_lock} for
+all other types.
+
+If the mutex is successfully locked, the function returns zero.  If the
+time specified in @var{abstime} is reached without the mutex being locked,
+@code{ETIMEDOUT} is returned.
+
+This function was introduced in the POSIX.1d revision of the POSIX standard.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex})
+@code{pthread_mutex_unlock} unlocks the given mutex. The mutex is
+assumed to be locked and owned by the calling thread on entrance to
+@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type,
+@code{pthread_mutex_unlock} always returns it to the unlocked state. If
+it is of the ``recursive'' type, it decrements the locking count of the
+mutex (number of @code{pthread_mutex_lock} operations performed on it by
+the calling thread), and only when this count reaches zero is the mutex
+actually unlocked.
+
+On ``error checking'' mutexes, @code{pthread_mutex_unlock} actually
+checks at run-time that the mutex is locked on entrance, and that it was
+locked by the same thread that is now calling
+@code{pthread_mutex_unlock}.  If these conditions are not met,
+@code{pthread_mutex_unlock} returns @code{EPERM}, and the mutex remains
+unchanged.  ``Fast'' and ``recursive'' mutexes perform no such checks,
+thus allowing a locked mutex to be unlocked by a thread other than its
+owner. This is non-portable behavior and must not be relied upon.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_destroy (pthread_mutex_t *@var{mutex})
+@code{pthread_mutex_destroy} destroys a mutex object, freeing the
+resources it might hold. The mutex must be unlocked on entrance. In the
+LinuxThreads implementation, no resources are associated with mutex
+objects, thus @code{pthread_mutex_destroy} actually does nothing except
+checking that the mutex is unlocked.
+
+If the mutex is locked by some thread, @code{pthread_mutex_destroy}
+returns @code{EBUSY}.  Otherwise it returns 0.
+@end deftypefun
+
+If any of the above functions (except @code{pthread_mutex_init})
+is applied to an uninitialized mutex, they will simply return
+@code{EINVAL} and do nothing.
+
+A shared global variable @var{x} can be protected by a mutex as follows:
+
+@smallexample
+int x;
+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+@end smallexample
+
+All accesses and modifications to @var{x} should be bracketed by calls to
+@code{pthread_mutex_lock} and @code{pthread_mutex_unlock} as follows:
+
+@smallexample
+pthread_mutex_lock(&mut);
+/* operate on x */
+pthread_mutex_unlock(&mut);
+@end smallexample
+
+Mutex attributes can be specified at mutex creation time, by passing a
+mutex attribute object as second argument to @code{pthread_mutex_init}.
+Passing @code{NULL} is equivalent to passing a mutex attribute object
+with all attributes set to their default values.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutexattr_init (pthread_mutexattr_t *@var{attr})
+@code{pthread_mutexattr_init} initializes the mutex attribute object
+@var{attr} and fills it with default values for the attributes.
+
+This function always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutexattr_destroy (pthread_mutexattr_t *@var{attr})
+@code{pthread_mutexattr_destroy} destroys a mutex attribute object,
+which must not be reused until it is
+reinitialized. @code{pthread_mutexattr_destroy} does nothing in the
+LinuxThreads implementation.
+
+This function always returns 0.
+@end deftypefun
+
+LinuxThreads supports only one mutex attribute: the mutex type, which is
+either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes,
+@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes,
+@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or
+@code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes.  As
+the @code{NP} suffix indicates, this is a non-portable extension to the
+POSIX standard and should not be employed in portable programs.
+
+The mutex type determines what happens if a thread attempts to lock a
+mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of
+the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling
+thread forever.  If the mutex is of the ``error checking'' type,
+@code{pthread_mutex_lock} returns immediately with the error code
+@code{EDEADLK}.  If the mutex is of the ``recursive'' type, the call to
+@code{pthread_mutex_lock} returns immediately with a success return
+code. The number of times the thread owning the mutex has locked it is
+recorded in the mutex. The owning thread must call
+@code{pthread_mutex_unlock} the same number of times before the mutex
+returns to the unlocked state.
+
+The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}.
+@c This doesn't describe how a ``timed'' mutex behaves. FIXME
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type})
+@code{pthread_mutexattr_settype} sets the mutex type attribute in
+@var{attr} to the value specified by @var{type}.
+
+If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP},
+@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or
+@code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return
+@code{EINVAL} and leave @var{attr} unchanged.
+
+The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT},
+@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE},
+and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted.
+
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type})
+@code{pthread_mutexattr_gettype} retrieves the current value of the
+mutex type attribute in @var{attr} and stores it in the location pointed
+to by @var{type}.
+
+This function always returns 0.
+@end deftypefun
+
+@node Condition Variables
+@section Condition Variables
+
+A condition (short for ``condition variable'') is a synchronization
+device that allows threads to suspend execution until some predicate on
+shared data is satisfied. The basic operations on conditions are: signal
+the condition (when the predicate becomes true), and wait for the
+condition, suspending the thread execution until another thread signals
+the condition.
+
+A condition variable must always be associated with a mutex, to avoid
+the race condition where a thread prepares to wait on a condition
+variable and another thread signals the condition just before the first
+thread actually waits on it.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_init (pthread_cond_t *@var{cond}, pthread_condattr_t *cond_@var{attr})
+
+@code{pthread_cond_init} initializes the condition variable @var{cond},
+using the condition attributes specified in @var{cond_attr}, or default
+attributes if @var{cond_attr} is @code{NULL}. The LinuxThreads
+implementation supports no attributes for conditions, hence the
+@var{cond_attr} parameter is actually ignored.
+
+Variables of type @code{pthread_cond_t} can also be initialized
+statically, using the constant @code{PTHREAD_COND_INITIALIZER}.
+
+This function always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_signal (pthread_cond_t *@var{cond})
+@code{pthread_cond_signal} restarts one of the threads that are waiting
+on the condition variable @var{cond}. If no threads are waiting on
+@var{cond}, nothing happens. If several threads are waiting on
+@var{cond}, exactly one is restarted, but it is not specified which.
+
+This function always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_broadcast (pthread_cond_t *@var{cond})
+@code{pthread_cond_broadcast} restarts all the threads that are waiting
+on the condition variable @var{cond}. Nothing happens if no threads are
+waiting on @var{cond}.
+
+This function always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_wait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex})
+@code{pthread_cond_wait} atomically unlocks the @var{mutex} (as per
+@code{pthread_unlock_mutex}) and waits for the condition variable
+@var{cond} to be signaled. The thread execution is suspended and does
+not consume any CPU time until the condition variable is signaled. The
+@var{mutex} must be locked by the calling thread on entrance to
+@code{pthread_cond_wait}. Before returning to the calling thread,
+@code{pthread_cond_wait} re-acquires @var{mutex} (as per
+@code{pthread_lock_mutex}).
+
+Unlocking the mutex and suspending on the condition variable is done
+atomically. Thus, if all threads always acquire the mutex before
+signaling the condition, this guarantees that the condition cannot be
+signaled (and thus ignored) between the time a thread locks the mutex
+and the time it waits on the condition variable.
+
+This function always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_timedwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime})
+@code{pthread_cond_timedwait} atomically unlocks @var{mutex} and waits
+on @var{cond}, as @code{pthread_cond_wait} does, but it also bounds the
+duration of the wait. If @var{cond} has not been signaled before time
+@var{abstime}, the mutex @var{mutex} is re-acquired and
+@code{pthread_cond_timedwait} returns the error code @code{ETIMEDOUT}.
+The wait can also be interrupted by a signal; in that case
+@code{pthread_cond_timedwait} returns @code{EINTR}.
+
+The @var{abstime} parameter specifies an absolute time, with the same
+origin as @code{time} and @code{gettimeofday}: an @var{abstime} of 0
+corresponds to 00:00:00 GMT, January 1, 1970.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_cond_destroy (pthread_cond_t *@var{cond})
+@code{pthread_cond_destroy} destroys the condition variable @var{cond},
+freeing the resources it might hold.  If any threads are waiting on the
+condition variable, @code{pthread_cond_destroy} leaves @var{cond}
+untouched and returns @code{EBUSY}.  Otherwise it returns 0, and
+@var{cond} must not be used again until it is reinitialized.
+
+In the LinuxThreads implementation, no resources are associated with
+condition variables, so @code{pthread_cond_destroy} actually does
+nothing.
+@end deftypefun
+
+@code{pthread_cond_wait} and @code{pthread_cond_timedwait} are
+cancellation points. If a thread is canceled while suspended in one of
+these functions, the thread immediately resumes execution, relocks the
+mutex specified by  @var{mutex}, and finally executes the cancellation.
+Consequently, cleanup handlers are assured that @var{mutex} is locked
+when they are called.
+
+It is not safe to call the condition variable functions from a signal
+handler. In particular, calling @code{pthread_cond_signal} or
+@code{pthread_cond_broadcast} from a signal handler may deadlock the
+calling thread.
+
+Consider two shared variables @var{x} and @var{y}, protected by the
+mutex @var{mut}, and a condition variable @var{cond} that is to be
+signaled whenever @var{x} becomes greater than @var{y}.
+
+@smallexample
+int x,y;
+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+@end smallexample
+
+Waiting until @var{x} is greater than @var{y} is performed as follows:
+
+@smallexample
+pthread_mutex_lock(&mut);
+while (x <= y) @{
+        pthread_cond_wait(&cond, &mut);
+@}
+/* operate on x and y */
+pthread_mutex_unlock(&mut);
+@end smallexample
+
+Modifications on @var{x} and @var{y} that may cause @var{x} to become greater than
+@var{y} should signal the condition if needed:
+
+@smallexample
+pthread_mutex_lock(&mut);
+/* modify x and y */
+if (x > y) pthread_cond_broadcast(&cond);
+pthread_mutex_unlock(&mut);
+@end smallexample
+
+If it can be proved that at most one waiting thread needs to be waken
+up (for instance, if there are only two threads communicating through
+@var{x} and @var{y}), @code{pthread_cond_signal} can be used as a slightly more
+efficient alternative to @code{pthread_cond_broadcast}. In doubt, use
+@code{pthread_cond_broadcast}.
+
+To wait for @var{x} to becomes greater than @var{y} with a timeout of 5
+seconds, do:
+
+@smallexample
+struct timeval now;
+struct timespec timeout;
+int retcode;
+
+pthread_mutex_lock(&mut);
+gettimeofday(&now);
+timeout.tv_sec = now.tv_sec + 5;
+timeout.tv_nsec = now.tv_usec * 1000;
+retcode = 0;
+while (x <= y && retcode != ETIMEDOUT) @{
+        retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
+@}
+if (retcode == ETIMEDOUT) @{
+        /* timeout occurred */
+@} else @{
+        /* operate on x and y */
+@}
+pthread_mutex_unlock(&mut);
+@end smallexample
+
+Condition attributes can be specified at condition creation time, by
+passing a condition attribute object as second argument to
+@code{pthread_cond_init}.  Passing @code{NULL} is equivalent to passing
+a condition attribute object with all attributes set to their default
+values.
+
+The LinuxThreads implementation supports no attributes for
+conditions. The functions on condition attributes are included only for
+compliance with the POSIX standard.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_condattr_init (pthread_condattr_t *@var{attr})
+@deftypefunx int pthread_condattr_destroy (pthread_condattr_t *@var{attr})
+@code{pthread_condattr_init} initializes the condition attribute object
+@var{attr} and fills it with default values for the attributes.
+@code{pthread_condattr_destroy} destroys the condition attribute object
+@var{attr}.
+
+Both functions do nothing in the LinuxThreads implementation.
+
+@code{pthread_condattr_init} and @code{pthread_condattr_destroy} always
+return 0.
+@end deftypefun
+
+@node POSIX Semaphores
+@section POSIX Semaphores
+
+@vindex SEM_VALUE_MAX
+Semaphores are counters for resources shared between threads. The
+basic operations on semaphores are: increment the counter atomically,
+and wait until the counter is non-null and decrement it atomically.
+
+Semaphores have a maximum value past which they cannot be incremented.
+The macro @code{SEM_VALUE_MAX} is defined to be this maximum value.  In
+the GNU C library, @code{SEM_VALUE_MAX} is equal to @code{INT_MAX}
+(@pxref{Range of Type}), but it may be much smaller on other systems.
+
+The pthreads library implements POSIX 1003.1b semaphores.  These should
+not be confused with System V semaphores (@code{ipc}, @code{semctl} and
+@code{semop}).
+@c !!! SysV IPC is not doc'd at all in our manual
+
+All the semaphore functions and macros are defined in @file{semaphore.h}.
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
+@code{sem_init} initializes the semaphore object pointed to by
+@var{sem}. The count associated with the semaphore is set initially to
+@var{value}. The @var{pshared} argument indicates whether the semaphore
+is local to the current process (@var{pshared} is zero) or is to be
+shared between several processes (@var{pshared} is not zero).
+
+On success @code{sem_init} returns 0.  On failure it returns -1 and sets
+@var{errno} to one of the following values:
+
+@table @code
+@item EINVAL
+@var{value} exceeds the maximal counter value @code{SEM_VALUE_MAX}
+
+@item ENOSYS
+@var{pshared} is not zero.  LinuxThreads currently does not support
+process-shared semaphores.  (This will eventually change.)
+@end table
+@end deftypefun
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_destroy (sem_t * @var{sem})
+@code{sem_destroy} destroys a semaphore object, freeing the resources it
+might hold.  If any threads are waiting on the semaphore when
+@code{sem_destroy} is called, it fails and sets @var{errno} to
+@code{EBUSY}.
+
+In the LinuxThreads implementation, no resources are associated with
+semaphore objects, thus @code{sem_destroy} actually does nothing except
+checking that no thread is waiting on the semaphore.  This will change
+when process-shared semaphores are implemented.
+@end deftypefun
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_wait (sem_t * @var{sem})
+@code{sem_wait} suspends the calling thread until the semaphore pointed
+to by @var{sem} has non-zero count. It then atomically decreases the
+semaphore count.
+
+@code{sem_wait} is a cancellation point.  It always returns 0.
+@end deftypefun
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_trywait (sem_t * @var{sem})
+@code{sem_trywait} is a non-blocking variant of @code{sem_wait}. If the
+semaphore pointed to by @var{sem} has non-zero count, the count is
+atomically decreased and @code{sem_trywait} immediately returns 0.  If
+the semaphore count is zero, @code{sem_trywait} immediately returns -1
+and sets errno to @code{EAGAIN}.
+@end deftypefun
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_post (sem_t * @var{sem})
+@code{sem_post} atomically increases the count of the semaphore pointed to
+by @var{sem}. This function never blocks.
+
+@c !!! This para appears not to agree with the code.
+On processors supporting atomic compare-and-swap (Intel 486, Pentium and
+later, Alpha, PowerPC, MIPS II, Motorola 68k, Ultrasparc), the
+@code{sem_post} function is can safely be called from signal handlers.
+This is the only thread synchronization function provided by POSIX
+threads that is async-signal safe.  On the Intel 386 and earlier Sparc
+chips, the current LinuxThreads implementation of @code{sem_post} is not
+async-signal safe, because the hardware does not support the required
+atomic operations.
+
+@code{sem_post} always succeeds and returns 0, unless the semaphore
+count would exceed @code{SEM_VALUE_MAX} after being incremented.  In
+that case @code{sem_post} returns -1 and sets @var{errno} to
+@code{EINVAL}.  The semaphore count is left unchanged.
+@end deftypefun
+
+@comment semaphore.h
+@comment POSIX
+@deftypefun int sem_getvalue (sem_t * @var{sem}, int * @var{sval})
+@code{sem_getvalue} stores in the location pointed to by @var{sval} the
+current count of the semaphore @var{sem}.  It always returns 0.
+@end deftypefun
+
+@node Thread-Specific Data
+@section Thread-Specific Data
+
+Programs often need global or static variables that have different
+values in different threads. Since threads share one memory space, this
+cannot be achieved with regular variables. Thread-specific data is the
+POSIX threads answer to this need.
+
+Each thread possesses a private memory block, the thread-specific data
+area, or TSD area for short. This area is indexed by TSD keys. The TSD
+area associates values of type @code{void *} to TSD keys. TSD keys are
+common to all threads, but the value associated with a given TSD key can
+be different in each thread.
+
+For concreteness, the TSD areas can be viewed as arrays of @code{void *}
+pointers, TSD keys as integer indices into these arrays, and the value
+of a TSD key as the value of the corresponding array element in the
+calling thread.
+
+When a thread is created, its TSD area initially associates @code{NULL}
+with all keys.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*destr_function) (void *))
+@code{pthread_key_create} allocates a new TSD key. The key is stored in
+the location pointed to by @var{key}. There is a limit of
+@code{PTHREAD_KEYS_MAX} on the number of keys allocated at a given
+time. The value initially associated with the returned key is
+@code{NULL} in all currently executing threads.
+
+The @var{destr_function} argument, if not @code{NULL}, specifies a
+destructor function associated with the key. When a thread terminates
+via @code{pthread_exit} or by cancellation, @var{destr_function} is
+called on the value associated with the key in that thread. The
+@var{destr_function} is not called if a key is deleted with
+@code{pthread_key_delete} or a value is changed with
+@code{pthread_setspecific}.  The order in which destructor functions are
+called at thread termination time is unspecified.
+
+Before the destructor function is called, the @code{NULL} value is
+associated with the key in the current thread.  A destructor function
+might, however, re-associate non-@code{NULL} values to that key or some
+other key.  To deal with this, if after all the destructors have been
+called for all non-@code{NULL} values, there are still some
+non-@code{NULL} values with associated destructors, then the process is
+repeated.  The LinuxThreads implementation stops the process after
+@code{PTHREAD_DESTRUCTOR_ITERATIONS} iterations, even if some
+non-@code{NULL} values with associated descriptors remain.  Other
+implementations may loop indefinitely.
+
+@code{pthread_key_create} returns 0 unless @code{PTHREAD_KEYS_MAX} keys
+have already been allocated, in which case it fails and returns
+@code{EAGAIN}.
+@end deftypefun
+
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_key_delete (pthread_key_t @var{key})
+@code{pthread_key_delete} deallocates a TSD key. It does not check
+whether non-@code{NULL} values are associated with that key in the
+currently executing threads, nor call the destructor function associated
+with the key.
+
+If there is no such key @var{key}, it returns @code{EINVAL}.  Otherwise
+it returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{pointer})
+@code{pthread_setspecific} changes the value associated with @var{key}
+in the calling thread, storing the given @var{pointer} instead.
+
+If there is no such key @var{key}, it returns @code{EINVAL}.  Otherwise
+it returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun {void *} pthread_getspecific (pthread_key_t @var{key})
+@code{pthread_getspecific} returns the value currently associated with
+@var{key} in the calling thread.
+
+If there is no such key @var{key}, it returns @code{NULL}.
+@end deftypefun
+
+The following code fragment allocates a thread-specific array of 100
+characters, with automatic reclaimation at thread exit:
+
+@smallexample
+/* Key for the thread-specific buffer */
+static pthread_key_t buffer_key;
+
+/* Once-only initialisation of the key */
+static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
+
+/* Allocate the thread-specific buffer */
+void buffer_alloc(void)
+@{
+  pthread_once(&buffer_key_once, buffer_key_alloc);
+  pthread_setspecific(buffer_key, malloc(100));
+@}
+
+/* Return the thread-specific buffer */
+char * get_buffer(void)
+@{
+  return (char *) pthread_getspecific(buffer_key);
+@}
+
+/* Allocate the key */
+static void buffer_key_alloc()
+@{
+  pthread_key_create(&buffer_key, buffer_destroy);
+@}
+
+/* Free the thread-specific buffer */
+static void buffer_destroy(void * buf)
+@{
+  free(buf);
+@}
+@end smallexample
+
+@node Threads and Signal Handling
+@section Threads and Signal Handling
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_sigmask (int @var{how}, const sigset_t *@var{newmask}, sigset_t *@var{oldmask})
+@code{pthread_sigmask} changes the signal mask for the calling thread as
+described by the @var{how} and @var{newmask} arguments. If @var{oldmask}
+is not @code{NULL}, the previous signal mask is stored in the location
+pointed to by @var{oldmask}.
+
+The meaning of the @var{how} and @var{newmask} arguments is the same as
+for @code{sigprocmask}. If @var{how} is @code{SIG_SETMASK}, the signal
+mask is set to @var{newmask}. If @var{how} is @code{SIG_BLOCK}, the
+signals specified to @var{newmask} are added to the current signal mask.
+If @var{how} is @code{SIG_UNBLOCK}, the signals specified to
+@var{newmask} are removed from the current signal mask.
+
+Recall that signal masks are set on a per-thread basis, but signal
+actions and signal handlers, as set with @code{sigaction}, are shared
+between all threads.
+
+The @code{pthread_sigmask} function returns 0 on success, and one of the
+following error codes on error:
+@table @code
+@item EINVAL
+@var{how} is not one of @code{SIG_SETMASK}, @code{SIG_BLOCK}, or @code{SIG_UNBLOCK}
+
+@item EFAULT
+@var{newmask} or @var{oldmask} point to invalid addresses
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_kill (pthread_t @var{thread}, int @var{signo})
+@code{pthread_kill} sends signal number @var{signo} to the thread
+@var{thread}.  The signal is delivered and handled as described in
+@ref{Signal Handling}.
+
+@code{pthread_kill} returns 0 on success, one of the following error codes
+on error:
+@table @code
+@item EINVAL
+@var{signo} is not a valid signal number
+
+@item ESRCH
+The thread @var{thread} does not exist (e.g. it has already terminated)
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int sigwait (const sigset_t *@var{set}, int *@var{sig})
+@code{sigwait} suspends the calling thread until one of the signals in
+@var{set} is delivered to the calling thread. It then stores the number
+of the signal received in the location pointed to by @var{sig} and
+returns. The signals in @var{set} must be blocked and not ignored on
+entrance to @code{sigwait}. If the delivered signal has a signal handler
+function attached, that function is @emph{not} called.
+
+@code{sigwait} is a cancellation point.  It always returns 0.
+@end deftypefun
+
+For @code{sigwait} to work reliably, the signals being waited for must be
+blocked in all threads, not only in the calling thread, since
+otherwise the POSIX semantics for signal delivery do not guarantee
+that it's the thread doing the @code{sigwait} that will receive the signal.
+The best way to achieve this is block those signals before any threads
+are created, and never unblock them in the program other than by
+calling @code{sigwait}.
+
+Signal handling in LinuxThreads departs significantly from the POSIX
+standard. According to the standard, ``asynchronous'' (external) signals
+are addressed to the whole process (the collection of all threads),
+which then delivers them to one particular thread. The thread that
+actually receives the signal is any thread that does not currently block
+the signal.
+
+In LinuxThreads, each thread is actually a kernel process with its own
+PID, so external signals are always directed to one particular thread.
+If, for instance, another thread is blocked in @code{sigwait} on that
+signal, it will not be restarted.
+
+The LinuxThreads implementation of @code{sigwait} installs dummy signal
+handlers for the signals in @var{set} for the duration of the
+wait. Since signal handlers are shared between all threads, other
+threads must not attach their own signal handlers to these signals, or
+alternatively they should all block these signals (which is recommended
+anyway).
+
+@node Threads and Fork
+@section Threads and Fork
+
+It's not intuitively obvious what should happen when a multi-threaded POSIX
+process calls @code{fork}. Not only are the semantics tricky, but you may
+need to write code that does the right thing at fork time even if that code
+doesn't use the @code{fork} function. Moreover, you need to be aware of
+interaction between @code{fork} and some library features like
+@code{pthread_once} and stdio streams.
+
+When @code{fork} is called by one of the threads of a process, it creates a new
+process which is copy of the  calling process. Effectively, in addition to
+copying certain system objects, the function takes a snapshot of the memory
+areas of the parent process, and creates identical areas in the child.
+To make matters more complicated, with threads it's possible for two or more
+threads to concurrently call fork to create two or more child processes.
+
+The child process has a copy of the address space of the parent, but it does
+not inherit any of its threads. Execution of the child process is carried out
+by a new thread which returns from @code{fork} function with a return value of
+zero; it is the only thread in the child process.  Because threads are not
+inherited across fork, issues arise. At the time of the call to @code{fork},
+threads in the parent process other than the one calling @code{fork} may have
+been executing critical regions of code.  As a result, the child process may
+get a copy of objects that are not in a well-defined state.  This potential
+problem affects all components of the program.
+
+Any program component which will continue being used in a child process must
+correctly handle its state during @code{fork}. For this purpose, the POSIX
+interface provides the special function @code{pthread_atfork} for installing
+pointers to handler functions which are called from within @code{fork}.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void))
+
+@code{pthread_atfork} registers handler functions to be called just
+before and just after a new process is created with @code{fork}. The
+@var{prepare} handler will be called from the parent process, just
+before the new process is created. The @var{parent} handler will be
+called from the parent process, just before @code{fork} returns. The
+@var{child} handler will be called from the child process, just before
+@code{fork} returns.
+
+@code{pthread_atfork} returns 0 on success and a non-zero error code on
+error.
+
+One or more of the three handlers @var{prepare}, @var{parent} and
+@var{child} can be given as @code{NULL}, meaning that no handler needs
+to be called at the corresponding point.
+
+@code{pthread_atfork} can be called several times to install several
+sets of handlers. At @code{fork} time, the @var{prepare} handlers are
+called in LIFO order (last added with @code{pthread_atfork}, first
+called before @code{fork}), while the @var{parent} and @var{child}
+handlers are called in FIFO order (first added, first called).
+
+If there is insufficient memory available to register the handlers,
+@code{pthread_atfork} fails and returns @code{ENOMEM}.  Otherwise it
+returns 0.
+
+The functions @code{fork} and @code{pthread_atfork} must not be regarded as
+reentrant from the context of the handlers.  That is to say, if a
+@code{pthread_atfork} handler invoked from within @code{fork} calls
+@code{pthread_atfork} or @code{fork}, the behavior is undefined.
+
+Registering a triplet of handlers is an atomic operation with respect to fork.
+If new handlers are registered at about the same time as a fork occurs, either
+all three handlers will be called, or none of them will be called.
+
+The handlers are inherited by the child process, and there is no
+way to remove them, short of using @code{exec} to load a new
+pocess image.
+
+@end deftypefun
+
+To understand the purpose of @code{pthread_atfork}, recall that
+@code{fork} duplicates the whole memory space, including mutexes in
+their current locking state, but only the calling thread: other threads
+are not running in the child process.  The mutexes are not usable after
+the @code{fork} and must be initialized with @code{pthread_mutex_init}
+in the child process.  This is a limitation of the current
+implementation and might or might not be present in future versions.
+
+To avoid this, install handlers with @code{pthread_atfork} as follows: have the
+@var{prepare} handler lock the mutexes (in locking order), and the
+@var{parent} handler unlock the mutexes. The @var{child} handler should reset
+the mutexes using @code{pthread_mutex_init}, as well as any other
+synchronization objects such as condition variables.
+
+Locking the global mutexes before the fork ensures that all other threads are
+locked out of the critical regions of code protected by those mutexes.  Thus
+when @code{fork} takes a snapshot of the parent's address space, that snapshot
+will copy valid, stable data.  Resetting the synchronization objects in the
+child process will ensure they are properly cleansed of any artifacts from the
+threading subsystem of the parent process. For example, a mutex may inherit
+a wait queue of threads waiting for the lock; this wait queue makes no sense
+in the child process. Initializing the mutex takes care of this.
+
+@node Streams and Fork
+@section Streams and Fork
+
+The GNU standard I/O library has an internal mutex which guards the internal
+linked list of all standard C FILE objects. This mutex is properly taken care
+of during @code{fork} so that the child receives an intact copy of the list.
+This allows the @code{fopen} function, and related stream-creating functions,
+to work correctly in the child process, since these functions need to insert
+into the list.
+
+However, the individual stream locks are not completely taken care of.  Thus
+unless the multithreaded application takes special precautions in its use of
+@code{fork}, the child process might not be able to safely use the streams that
+it inherited from the parent.   In general, for any given open stream in the
+parent that is to be used by the child process, the application must ensure
+that that stream is not in use by another thread when @code{fork} is called.
+Otherwise an inconsistent copy of the stream object be produced. An easy way to
+ensure this is to use @code{flockfile} to lock the stream prior to calling
+@code{fork} and then unlock it with @code{funlockfile} inside the parent
+process, provided that the parent's threads properly honor these locks.
+Nothing special needs to be done in the child process, since the library
+internally resets all stream locks.
+
+Note that the stream locks are not shared between the parent and child.
+For example, even if you ensure that, say, the stream @code{stdout} is properly
+treated and can be safely used in the child, the stream locks do not provide
+an exclusion mechanism between the parent and child. If both processes write
+to @code{stdout}, strangely interleaved output may result regardless of
+the explicit use of @code{flockfile} or implicit locks.
+
+Also note that these provisions are a GNU extension; other systems might not
+provide any way for streams to be used in the child of a multithreaded process.
+POSIX requires that such a child process confines itself to calling only
+asynchronous safe functions, which excludes much of the library, including
+standard I/O.
+
+@node Miscellaneous Thread Functions
+@section Miscellaneous Thread Functions
+
+@comment pthread.h
+@comment POSIX
+@deftypefun {pthread_t} pthread_self (@var{void})
+@code{pthread_self} returns the thread identifier for the calling thread.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2)
+@code{pthread_equal} determines if two thread identifiers refer to the same
+thread.
+
+A non-zero value is returned if @var{thread1} and @var{thread2} refer to
+the same thread. Otherwise, 0 is returned.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_detach (pthread_t @var{th})
+@code{pthread_detach} puts the thread @var{th} in the detached
+state. This guarantees that the memory resources consumed by @var{th}
+will be freed immediately when @var{th} terminates. However, this
+prevents other threads from synchronizing on the termination of @var{th}
+using @code{pthread_join}.
+
+A thread can be created initially in the detached state, using the
+@code{detachstate} attribute to @code{pthread_create}. In contrast,
+@code{pthread_detach} applies to threads created in the joinable state,
+and which need to be put in the detached state later.
+
+After @code{pthread_detach} completes, subsequent attempts to perform
+@code{pthread_join} on @var{th} will fail. If another thread is already
+joining the thread @var{th} at the time @code{pthread_detach} is called,
+@code{pthread_detach} does nothing and leaves @var{th} in the joinable
+state.
+
+On success, 0 is returned. On error, one of the following codes is
+returned:
+@table @code
+@item ESRCH
+No thread could be found corresponding to that specified by @var{th}
+@item EINVAL
+The thread @var{th} is already in the detached state
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment GNU
+@deftypefun void pthread_kill_other_threads_np (@var{void})
+@code{pthread_kill_other_threads_np} is a non-portable LinuxThreads extension.
+It causes all threads in the program to terminate immediately, except
+the calling thread which proceeds normally. It is intended to be
+called just before a thread calls one of the @code{exec} functions,
+e.g. @code{execve}.
+
+Termination of the other threads is not performed through
+@code{pthread_cancel} and completely bypasses the cancellation
+mechanism. Hence, the current settings for cancellation state and
+cancellation type are ignored, and the cleanup handlers are not
+executed in the terminated threads.
+
+According to POSIX 1003.1c, a successful @code{exec*} in one of the
+threads should automatically terminate all other threads in the program.
+This behavior is not yet implemented in LinuxThreads.  Calling
+@code{pthread_kill_other_threads_np} before @code{exec*} achieves much
+of the same behavior, except that if @code{exec*} ultimately fails, then
+all other threads are already killed.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_once (pthread_once_t *once_@var{control}, void (*@var{init_routine}) (void))
+
+The purpose of @code{pthread_once} is to ensure that a piece of
+initialization code is executed at most once. The @var{once_control}
+argument points to a static or extern variable statically initialized
+to @code{PTHREAD_ONCE_INIT}.
+
+The first time @code{pthread_once} is called with a given
+@var{once_control} argument, it calls @var{init_routine} with no
+argument and changes the value of the @var{once_control} variable to
+record that initialization has been performed. Subsequent calls to
+@code{pthread_once} with the same @code{once_control} argument do
+nothing.
+
+If a thread is cancelled while executing @var{init_routine}
+the state of the @var{once_control} variable is reset so that
+a future call to @code{pthread_once} will call the routine again.
+
+If the process forks while one or more threads are executing
+@code{pthread_once} initialization routines, the states of their respective
+@var{once_control} variables will appear to be reset in the child process so
+that if the child calls @code{pthread_once}, the routines will be executed.
+
+@code{pthread_once} always returns 0.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setschedparam (pthread_t target_@var{thread}, int @var{policy}, const struct sched_param *@var{param})
+
+@code{pthread_setschedparam} sets the scheduling parameters for the
+thread @var{target_thread} as indicated by @var{policy} and
+@var{param}. @var{policy} can be either @code{SCHED_OTHER} (regular,
+non-realtime scheduling), @code{SCHED_RR} (realtime, round-robin) or
+@code{SCHED_FIFO} (realtime, first-in first-out). @var{param} specifies
+the scheduling priority for the two realtime policies.  See
+@code{sched_setpolicy} for more information on scheduling policies.
+
+The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO}
+are available only to processes with superuser privileges.
+
+On success, @code{pthread_setschedparam} returns 0.  On error it returns
+one of the following codes:
+@table @code
+@item EINVAL
+@var{policy} is not one of @code{SCHED_OTHER}, @code{SCHED_RR},
+@code{SCHED_FIFO}, or the priority value specified by @var{param} is not
+valid for the specified policy
+
+@item EPERM
+Realtime scheduling was requested but the calling process does not have
+sufficient privileges.
+
+@item ESRCH
+The @var{target_thread} is invalid or has already terminated
+
+@item EFAULT
+@var{param} points outside the process memory space
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_getschedparam (pthread_t target_@var{thread}, int *@var{policy}, struct sched_param *@var{param})
+
+@code{pthread_getschedparam} retrieves the scheduling policy and
+scheduling parameters for the thread @var{target_thread} and stores them
+in the locations pointed to by @var{policy} and @var{param},
+respectively.
+
+@code{pthread_getschedparam} returns 0 on success, or one of the
+following error codes on failure:
+@table @code
+@item ESRCH
+The @var{target_thread} is invalid or has already terminated.
+
+@item EFAULT
+@var{policy} or @var{param} point outside the process memory space.
+
+@end table
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setconcurrency (int @var{level})
+@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack
+of a mapping of user threads to kernel threads.  It exists for source
+compatibility.  It does store the value @var{level} so that it can be
+returned by a subsequent call to @code{pthread_getconcurrency}.  It takes
+no other action however.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_getconcurrency ()
+@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack
+of a mapping of user threads to kernel threads.  It exists for source
+compatibility.  However, it will return the value that was set by the
+last call to @code{pthread_setconcurrency}.
+@end deftypefun
diff --git a/linuxthreads/lockfile.c b/linuxthreads/lockfile.c
new file mode 100644
index 0000000000..34055e4115
--- /dev/null
+++ b/linuxthreads/lockfile.c
@@ -0,0 +1,82 @@
+/* lockfile - Handle locking and unlocking of stream.
+   Copyright (C) 1996, 1998, 2000 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 <bits/libc-lock.h>
+#include <stdio.h>
+#include <pthread.h>
+#include "internals.h"
+#include "../libio/libioP.h"
+
+void
+__flockfile (FILE *stream)
+{
+  __pthread_mutex_lock (stream->_lock);
+}
+#undef _IO_flockfile
+strong_alias (__flockfile, _IO_flockfile)
+weak_alias (__flockfile, flockfile);
+
+
+void
+__funlockfile (FILE *stream)
+{
+  __pthread_mutex_unlock (stream->_lock);
+}
+#undef _IO_funlockfile
+strong_alias (__funlockfile, _IO_funlockfile)
+weak_alias (__funlockfile, funlockfile);
+
+
+int
+__ftrylockfile (FILE *stream)
+{
+  return __pthread_mutex_trylock (stream->_lock);
+}
+strong_alias (__ftrylockfile, _IO_ftrylockfile)
+weak_alias (__ftrylockfile, ftrylockfile);
+
+void
+__flockfilelist(void)
+{
+  _IO_list_lock();
+}
+
+void
+__funlockfilelist(void)
+{
+  _IO_list_unlock();
+}
+
+void
+__fresetlockfiles (void)
+{
+  _IO_ITER i;
+
+  pthread_mutexattr_t attr;
+
+  __pthread_mutexattr_init (&attr);
+  __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+
+  for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
+    __pthread_mutex_init (_IO_iter_file(i)->_lock, &attr);
+
+  __pthread_mutexattr_destroy (&attr);
+
+  _IO_list_resetlock();
+}
diff --git a/linuxthreads/man/Makefile b/linuxthreads/man/Makefile
new file mode 100644
index 0000000000..4afd2ee15d
--- /dev/null
+++ b/linuxthreads/man/Makefile
@@ -0,0 +1,31 @@
+SOURCES=pthread_atfork.man pthread_attr_init.man pthread_cancel.man \
+  pthread_cleanup_push.man pthread_cond_init.man \
+  pthread_condattr_init.man pthread_create.man pthread_detach.man \
+  pthread_equal.man pthread_exit.man pthread_join.man \
+  pthread_key_create.man pthread_mutex_init.man \
+  pthread_mutexattr_init.man pthread_once.man pthread_self.man \
+  pthread_setschedparam.man pthread_sigmask.man sem_init.man \
+  pthread_kill_other_threads_np.man pthread_mutexattr_setkind_np.man
+
+MANPAGES=$(SOURCES:.man=.3thr)
+
+PREPRO=perl troffprepro
+
+MANDIR=/usr/man/man3
+
+all: $(MANPAGES)
+
+.SUFFIXES: .man .3thr
+
+.man.3thr:
+	$(PREPRO) $*.man $*.3thr
+
+$(MANPAGES): troffprepro
+
+clean:
+	rm -f *.3thr
+	rm -f *~
+
+install:
+	install *.3thr $(MANDIR)
+	@echo "*** Remember to run /usr/sbin/makewhatis `dirname $(MANDIR)` at some point"
diff --git a/linuxthreads/man/pthread_atfork.man b/linuxthreads/man/pthread_atfork.man
new file mode 100644
index 0000000000..b682bed3ac
--- /dev/null
+++ b/linuxthreads/man/pthread_atfork.man
@@ -0,0 +1,53 @@
+.TH PTHREAD_ATFORK 3 LinuxThreads
+
+.SH NAME
+pthread_atfork \- register handlers to be called at fork(2) time
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
+
+.SH DESCRIPTION
+
+!pthread_atfork! registers handler functions to be called just before
+and just after a new process is created with !fork!(2). The |prepare|
+handler will be called from the parent process, just before the new
+process is created. The |parent| handler will be called from the parent
+process, just before !fork!(2) returns. The |child| handler will be
+called from the child process, just before !fork!(2) returns.
+
+One or several of the three handlers |prepare|, |parent| and |child|
+can be given as !NULL!, meaning that no handler needs to be called at
+the corresponding point.
+
+!pthread_atfork! can be called several times to install several sets
+of handlers. At !fork!(2) time, the |prepare| handlers are called in
+LIFO order (last added with !pthread_atfork!, first called before !fork!),
+while the |parent| and |child| handlers are called in FIFO order
+(first added, first called).
+
+To understand the purpose of !pthread_atfork!, recall that !fork!(2)
+duplicates the whole memory space, including mutexes in their current
+locking state, but only the calling thread: other threads are not
+running in the child process.  The mutexes are not usable after the
+!fork! and must be initialized with |pthread_mutex_init| in the child
+process.  This is a limitation of the current implementation and might
+or might not be present in future versions.
+
+.SH "RETURN VALUE"
+
+!pthread_atfork! returns 0 on success and a non-zero error code on error.
+
+.SH ERRORS
+.TP
+!ENOMEM!
+insufficient memory available to register the handlers.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!fork!(2),
+!pthread_mutex_lock!(3),
+!pthread_mutex_unlock!(3).
diff --git a/linuxthreads/man/pthread_attr_init.man b/linuxthreads/man/pthread_attr_init.man
new file mode 100644
index 0000000000..bd5a169242
--- /dev/null
+++ b/linuxthreads/man/pthread_attr_init.man
@@ -0,0 +1,221 @@
+.TH PTHREAD_ATTR_INIT 3 LinuxThreads
+
+.XREF pthread_attr_destroy
+.XREF pthread_attr_setdetachstate
+.XREF pthread_attr_getdetachstate
+.XREF pthread_attr_setschedparam
+.XREF pthread_attr_getschedparam
+.XREF pthread_attr_setschedpolicy
+.XREF pthread_attr_getschedpolicy
+.XREF pthread_attr_setinheritsched
+.XREF pthread_attr_getinheritsched
+.XREF pthread_attr_setscope
+.XREF pthread_attr_getscope
+
+.SH NAME
+pthread_attr_init, pthread_attr_destroy, pthread_attr_setdetachstate, pthread_attr_getdetachstate, pthread_attr_setschedparam, pthread_attr_getschedparam, pthread_attr_setschedpolicy, pthread_attr_getschedpolicy, pthread_attr_setinheritsched, pthread_attr_getinheritsched, pthread_attr_setscope, pthread_attr_getscope \- thread creation attributes
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_attr_init(pthread_attr_t *attr);
+
+int pthread_attr_destroy(pthread_attr_t *attr);
+
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
+
+int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
+
+int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
+
+int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
+
+int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
+
+int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
+
+int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);
+
+int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit);
+
+int pthread_attr_setscope(pthread_attr_t *attr, int scope);
+
+int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
+
+.SH DESCRIPTION
+
+Setting attributes for threads is achieved by filling a
+thread attribute object |attr| of type !pthread_attr_t!, then passing it as
+second argument to !pthread_create!(3). Passing !NULL! is equivalent to
+passing a thread attribute object with all attributes set to their
+default values.
+
+!pthread_attr_init! initializes the thread attribute object |attr| and
+fills it with default values for the attributes. (The default values
+are listed below for each attribute.)
+
+Each attribute |attrname| (see below for a list of all attributes) can
+be individually set using the function !pthread_attr_set!|attrname|
+and retrieved using the function !pthread_attr_get!|attrname|.
+
+!pthread_attr_destroy! destroys a thread attribute object, which
+must not be reused until it is reinitialized. !pthread_attr_destroy!
+does nothing in the LinuxThreads implementation. 
+
+Attribute objects are consulted only when creating a new thread. The
+same attribute object can be used for creating several
+threads. Modifying an attribute object after a call to
+!pthread_create! does not change the attributes of the thread
+previously created.
+
+The following thread attributes are supported:
+
+.SS detachstate
+
+Control whether the thread is created in the joinable state (value
+!PTHREAD_CREATE_JOINABLE!) or in the detached state
+(!PTHREAD_CREATE_DETACHED!). 
+
+Default value: !PTHREAD_CREATE_JOINABLE!.
+
+In the joinable state, another thread can synchronize on the thread
+termination and recover its termination code using !pthread_join!(3),
+but some of the thread resources are kept allocated after the thread
+terminates, and reclaimed only when another thread performs
+!pthread_join!(3) on that thread.
+
+In the detached state, the thread resources are immediately freed when
+it terminates, but !pthread_join!(3) cannot be used to synchronize on
+the thread termination.
+
+A thread created in the joinable state can later be put in the
+detached thread using !pthread_detach!(3).
+
+.SS schedpolicy
+
+Select the scheduling policy for the thread: one of
+!SCHED_OTHER! (regular, non-realtime scheduling),
+!SCHED_RR! (realtime, round-robin) or
+!SCHED_FIFO! (realtime, first-in first-out). See
+!sched_setpolicy!(2) for more information on scheduling policies.
+
+Default value: !SCHED_OTHER!.
+
+The realtime scheduling policies !SCHED_RR! and !SCHED_FIFO! are
+available only to processes with superuser privileges.
+
+The scheduling policy of a thread can be changed after creation with
+!pthread_setschedparam!(3).
+
+.SS schedparam
+
+Contain the scheduling parameters (essentially, the scheduling
+priority) for the thread. See !sched_setparam!(2) for more information
+on scheduling parameters. 
+
+Default value: priority is 0.
+
+This attribute is not significant if the scheduling policy is !SCHED_OTHER!;
+it only matters for the realtime policies !SCHED_RR! and !SCHED_FIFO!.
+
+The scheduling priority of a thread can be changed after creation with
+!pthread_setschedparam!(3).
+
+.SS inheritsched
+
+Indicate whether the scheduling policy and scheduling parameters for
+the newly created thread are determined by the values of the
+|schedpolicy| and |schedparam| attributes (value
+!PTHREAD_EXPLICIT_SCHED!) or are inherited from the parent thread
+(value !PTHREAD_INHERIT_SCHED!).
+
+Default value: !PTHREAD_EXPLICIT_SCHED!.
+
+.SS scope
+
+Define the scheduling contention scope for the created thread.  The
+only value supported in the LinuxThreads implementation is
+!PTHREAD_SCOPE_SYSTEM!, meaning that the threads contend for CPU time
+with all processes running on the machine. In particular, thread
+priorities are interpreted relative to the priorities of all other
+processes on the machine. The other value specified by the standard,
+!PTHREAD_SCOPE_PROCESS!, means that scheduling contention occurs only
+between the threads of the running process: thread priorities are
+interpreted relative to the priorities of the other threads of the
+process, regardless of the priorities of other processes.
+!PTHREAD_SCOPE_PROCESS! is not supported in LinuxThreads.
+
+Default value: !PTHREAD_SCOPE_SYSTEM!.
+
+.SH "RETURN VALUE"
+
+All functions return 0 on success and a non-zero error code on error.
+On success, the !pthread_attr_get!|attrname| functions also store the
+current value of the attribute |attrname| in the location pointed to
+by their second argument.
+
+.SH ERRORS
+
+The !pthread_attr_setdetachstate! function returns the following error
+codes on error:
+.RS
+.TP
+!EINVAL!
+the specified |detachstate| is not one of !PTHREAD_CREATE_JOINABLE! or
+!PTHREAD_CREATE_DETACHED!.
+.RE
+
+The !pthread_attr_setschedparam! function returns the following error
+codes on error:
+.RS
+.TP
+!EINVAL!
+the priority specified in |param| is outside the range of allowed
+priorities for the scheduling policy currently in |attr|
+(1 to 99 for !SCHED_FIFO! and !SCHED_RR!; 0 for !SCHED_OTHER!).
+.RE
+
+The !pthread_attr_setschedpolicy! function returns the following error
+codes on error:
+.RS
+.TP
+!EINVAL!
+the specified |policy| is not one of !SCHED_OTHER!, !SCHED_FIFO!, or
+!SCHED_RR!.
+
+.TP
+!ENOTSUP!
+|policy| is !SCHED_FIFO! or !SCHED_RR!, and the effective user of the
+calling process is not super-user.
+.RE
+
+The !pthread_attr_setinheritsched! function returns the following error
+codes on error:
+.RS
+.TP
+!EINVAL!
+the specified |inherit| is not one of !PTHREAD_INHERIT_SCHED! or
+!PTHREAD_EXPLICIT_SCHED!.
+.RE
+
+The !pthread_attr_setscope! function returns the following error
+codes on error:
+.RS
+.TP
+!EINVAL!
+the specified |scope| is not one of !PTHREAD_SCOPE_SYSTEM! or
+!PTHREAD_SCOPE_PROCESS!.
+
+.TP
+!ENOTSUP!
+the specified |scope| is !PTHREAD_SCOPE_PROCESS! (not supported).
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_create!(3),
+!pthread_join!(3),
+!pthread_detach!(3),
+!pthread_setschedparam!(3).
diff --git a/linuxthreads/man/pthread_cancel.man b/linuxthreads/man/pthread_cancel.man
new file mode 100644
index 0000000000..202d5c9b26
--- /dev/null
+++ b/linuxthreads/man/pthread_cancel.man
@@ -0,0 +1,155 @@
+.TH PTHREAD_CANCEL 3 LinuxThreads
+
+.XREF pthread_setcancelstate
+.XREF pthread_setcanceltype
+.XREF pthread_testcancel
+
+.SH NAME
+pthread_cancel, pthread_setcancelstate, pthread_setcanceltype, pthread_testcancel \- thread cancellation
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_cancel(pthread_t thread);
+
+int pthread_setcancelstate(int state, int *oldstate);
+
+int pthread_setcanceltype(int type, int *oldtype);
+
+void pthread_testcancel(void);
+
+.SH DESCRIPTION
+
+Cancellation is the mechanism by which a thread can terminate the
+execution of another thread. More precisely, a thread can send a
+cancellation request to another thread. Depending on its settings, the
+target thread can then either ignore the request, honor it
+immediately, or defer it till it reaches a cancellation point.
+
+When a thread eventually honors a cancellation request, it performs as
+if !pthread_exit(PTHREAD_CANCELED)! has been called at that point:
+all cleanup handlers are executed in reverse order, finalization
+functions for thread-specific data are called, and finally the thread
+stops executing with the return value !PTHREAD_CANCELED!. See
+!pthread_exit!(3) for more information.
+
+!pthread_cancel! sends a cancellation request to the thread denoted
+by the |thread| argument.
+
+!pthread_setcancelstate! changes the cancellation state for the
+calling thread -- that is, whether cancellation requests are ignored
+or not. The |state| argument is the new cancellation state: either
+!PTHREAD_CANCEL_ENABLE! to enable cancellation, or
+!PTHREAD_CANCEL_DISABLE! to disable cancellation (cancellation
+requests are ignored). If |oldstate| is not !NULL!, the previous
+cancellation state is stored in the location pointed to by |oldstate|,
+and can thus be restored later by another call to
+!pthread_setcancelstate!.
+
+!pthread_setcanceltype! changes the type of responses to cancellation
+requests for the calling thread: asynchronous (immediate) or deferred.
+The |type| argument is the new cancellation type: either
+!PTHREAD_CANCEL_ASYNCHRONOUS! to cancel the calling thread as soon as
+the cancellation request is received, or !PTHREAD_CANCEL_DEFERRED! to
+keep the cancellation request pending until the next cancellation
+point. If |oldtype| is not !NULL!, the previous
+cancellation state is stored in the location pointed to by |oldtype|,
+and can thus be restored later by another call to
+!pthread_setcanceltype!.
+
+Threads are always created by !pthread_create!(3) with cancellation
+enabled and deferred. That is, the initial cancellation state is
+!PTHREAD_CANCEL_ENABLE! and the initial type is
+!PTHREAD_CANCEL_DEFERRED!.
+
+Cancellation points are those points in the program execution where a
+test for pending cancellation requests is performed and cancellation
+is executed if positive. The following POSIX threads functions
+are cancellation points:
+
+!pthread_join!(3)
+.br
+!pthread_cond_wait!(3)
+.br
+!pthread_cond_timedwait!(3)
+.br
+!pthread_testcancel!(3)
+.br
+!sem_wait!(3)
+.br
+!sigwait!(3)
+
+All other POSIX threads functions are guaranteed not to be
+cancellation points. That is, they never perform cancellation in
+deferred cancellation mode.
+
+!pthread_testcancel! does nothing except testing for pending
+cancellation and executing it. Its purpose is to introduce explicit
+checks for cancellation in long sequences of code that do not call
+cancellation point functions otherwise.
+
+.SH "RETURN VALUE"
+
+!pthread_cancel!, !pthread_setcancelstate! and
+!pthread_setcanceltype! return 0 on success and a non-zero error code
+on error.
+
+.SH ERRORS
+!pthread_cancel! returns the following error code on error:
+.RS
+.TP
+!ESRCH!
+no thread could be found corresponding to that specified by the |thread| ID.
+.RE
+
+!pthread_setcancelstate! returns the following error code on error:
+.RS
+.TP
+!EINVAL!
+the |state| argument is not !PTHREAD_CANCEL_ENABLE! nor
+!PTHREAD_CANCEL_DISABLE!
+.RE
+
+!pthread_setcanceltype! returns the following error code on error:
+.RS
+.TP
+!EINVAL!
+the |type| argument is not !PTHREAD_CANCEL_DEFERRED! nor
+!PTHREAD_CANCEL_ASYNCHRONOUS!
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_exit!(3),
+!pthread_cleanup_push!(3),
+!pthread_cleanup_pop!(3).
+
+.SH BUGS
+
+POSIX specifies that a number of system calls (basically, all
+system calls that may block, such as !read!(2), !write!(2), !wait!(2),
+etc.) and library functions that may call these system calls (e.g.
+!fprintf!(3)) are cancellation points.  LinuxThreads is not yet
+integrated enough with the C library to implement this, and thus none
+of the C library functions is a cancellation point.
+
+For system calls at least, there is a workaround. Cancellation
+requests are transmitted to the target thread by sending it a
+signal. That signal will interrupt all blocking system calls, causing
+them to return immediately with the !EINTR! error. So, checking for
+cancellation during a !read! system call, for instance, can be
+achieved as follows:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_testcancel();
+retcode = read(fd, buffer, length);
+pthread_testcancel();
+.ft
+.LP
+.RE
+.fi
diff --git a/linuxthreads/man/pthread_cleanup_push.man b/linuxthreads/man/pthread_cleanup_push.man
new file mode 100644
index 0000000000..1591431c9c
--- /dev/null
+++ b/linuxthreads/man/pthread_cleanup_push.man
@@ -0,0 +1,194 @@
+.TH PTHREAD_CLEANUP 3 LinuxThreads
+
+.XREF pthread_cleanup_pop
+.XREF pthread_cleanup_push_defer_np
+.XREF pthread_cleanup_pop_restore_np
+
+.SH NAME
+pthread_cleanup_push, pthread_cleanup_pop, pthread_cleanup_push_defer_np, pthread_cleanup_pop_restore_np \- install and remove cleanup handlers
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+void pthread_cleanup_push(void (*routine) (void *), void *arg);
+
+void pthread_cleanup_pop(int execute);
+
+void pthread_cleanup_push_defer_np(void (*routine) (void *), void *arg);
+
+void pthread_cleanup_pop_restore_np(int execute);
+
+.SH DESCRIPTION
+
+Cleanup handlers are functions that get called when a thread
+terminates, either by calling !pthread_exit!(3) or because of
+cancellation. Cleanup handlers are installed and removed following a
+stack-like discipline.
+
+The purpose of cleanup handlers is to free the resources that a thread
+may hold at the time it terminates. In particular, if a thread
+exits or is cancelled while it owns a locked mutex, the mutex will
+remain locked forever and prevent other threads from executing
+normally. The best way to avoid this is, just before locking the
+mutex, to install a cleanup handler whose effect is to unlock the
+mutex. Cleanup handlers can be used similarly to free blocks allocated
+with !malloc!(3) or close file descriptors on thread termination.
+
+!pthread_cleanup_push! installs the |routine| function with argument
+|arg| as a cleanup handler. From this point on to the matching
+!pthread_cleanup_pop!, the function |routine| will be called with
+arguments |arg| when the thread terminates, either through !pthread_exit!(3)
+or by cancellation. If several cleanup handlers are active at that
+point, they are called in LIFO order: the most recently installed
+handler is called first.
+
+!pthread_cleanup_pop! removes the most recently installed cleanup
+handler. If the |execute| argument is not 0, it also executes the
+handler, by calling the |routine| function with arguments |arg|. If
+the |execute| argument is 0, the handler is only removed but not
+executed.
+
+Matching pairs of !pthread_cleanup_push! and !pthread_cleanup_pop!
+must occur in the same function, at the same level of block nesting.
+Actually, !pthread_cleanup_push! and !pthread_cleanup_pop! are macros,
+and the expansion of !pthread_cleanup_push! introduces an open brace !{!
+with the matching closing brace !}! being introduced by the expansion
+of the matching !pthread_cleanup_pop!.
+
+!pthread_cleanup_push_defer_np! is a non-portable extension that
+combines !pthread_cleanup_push! and !pthread_setcanceltype!(3).
+It pushes a cleanup handler just as !pthread_cleanup_push! does, but
+also saves the current cancellation type and sets it to deferred
+cancellation. This ensures that the cleanup mechanism is effective
+even if the thread was initially in asynchronous cancellation mode.
+
+!pthread_cleanup_pop_restore_np! pops a cleanup handler introduced by
+!pthread_cleanup_push_defer_np!, and restores the cancellation type to
+its value at the time !pthread_cleanup_push_defer_np! was called.
+
+!pthread_cleanup_push_defer_np! and !pthread_cleanup_pop_restore_np!
+must occur in matching pairs, at the same level of block nesting.
+
+The following sequence
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_cleanup_push_defer_np(routine, arg);
+...
+pthread_cleanup_pop_defer_np(execute);
+.ft
+.LP
+.RE
+.fi
+
+is functionally equivalent to (but more compact and more efficient than)
+
+.RS
+.ft 3
+.nf
+.sp
+{ int oldtype;
+  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
+  pthread_cleanup_push(routine, arg);
+  ...
+  pthread_cleanup_pop(execute);
+  pthread_setcanceltype(oldtype, NULL);
+}
+.ft
+.LP
+.RE
+.fi
+
+.SH "RETURN VALUE"
+
+None.
+
+.SH ERRORS
+
+None.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_exit!(3),
+!pthread_cancel!(3),
+!pthread_setcanceltype!(3).
+
+.SH EXAMPLE
+
+Here is how to lock a mutex |mut| in such a way that it will be
+unlocked if the thread is canceled while |mut| is locked:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_mutex_unlock(&mut);
+pthread_cleanup_pop(0);
+.ft
+.LP
+.RE
+.fi
+
+Equivalently, the last two lines can be replaced by
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_cleanup_pop(1);
+.ft
+.LP
+.RE
+.fi
+
+Notice that the code above is safe only in deferred cancellation mode
+(see !pthread_setcanceltype!(3)). In asynchronous cancellation mode,
+a cancellation can occur between !pthread_cleanup_push! and
+!pthread_mutex_lock!, or between !pthread_mutex_unlock! and
+!pthread_cleanup_pop!, resulting in both cases in the thread trying to
+unlock a mutex not locked by the current thread. This is the main
+reason why asynchronous cancellation is difficult to use.
+
+If the code above must also work in asynchronous cancellation mode,
+then it must switch to deferred mode for locking and unlocking the
+mutex:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
+pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_cleanup_pop(1);
+pthread_setcanceltype(oldtype, NULL);
+.ft
+.LP
+.RE
+.fi
+
+The code above can be rewritten in a more compact and more
+efficient way, using the non-portable functions
+!pthread_cleanup_push_defer_np! and !pthread_cleanup_pop_restore_np!:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_cleanup_push_restore_np(pthread_mutex_unlock, (void *) &mut);
+pthread_mutex_lock(&mut);
+/* do some work */
+pthread_cleanup_pop_restore_np(1);
+.ft
+.LP
+.RE
+.fi
+
diff --git a/linuxthreads/man/pthread_cond_init.man b/linuxthreads/man/pthread_cond_init.man
new file mode 100644
index 0000000000..4913062fd2
--- /dev/null
+++ b/linuxthreads/man/pthread_cond_init.man
@@ -0,0 +1,234 @@
+.TH PTHREAD_COND 3 LinuxThreads
+
+.XREF pthread_cond_signal
+.XREF pthread_cond_broadcast
+.XREF pthread_cond_wait
+.XREF pthread_cond_timedwait
+.XREF pthread_cond_destroy
+
+.SH NAME
+pthread_cond_init, pthread_cond_destroy, pthread_cond_signal, pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait \- operations on conditions
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
+
+int pthread_cond_signal(pthread_cond_t *cond);
+
+int pthread_cond_broadcast(pthread_cond_t *cond);
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
+
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
+
+int pthread_cond_destroy(pthread_cond_t *cond);
+
+.SH DESCRIPTION
+
+A condition (short for ``condition variable'') is a synchronization
+device that allows threads to suspend execution and relinquish the
+processors until some predicate on shared data is satisfied. The basic
+operations on conditions are: signal the condition (when the
+predicate becomes true), and wait for the condition, suspending the
+thread execution until another thread signals the condition.
+
+A condition variable must always be associated with a mutex, to avoid
+the race condition where a thread prepares to wait on a condition
+variable and another thread signals the condition just before the
+first thread actually waits on it.
+
+!pthread_cond_init! initializes the condition variable |cond|, using the
+condition attributes specified in |cond_attr|, or default attributes
+if |cond_attr| is !NULL!. The LinuxThreads implementation supports no
+attributes for conditions, hence the |cond_attr| parameter is actually
+ignored.
+
+Variables of type !pthread_cond_t! can also be initialized
+statically, using the constant !PTHREAD_COND_INITIALIZER!.
+
+!pthread_cond_signal! restarts one of the threads that are waiting on
+the condition variable |cond|. If no threads are waiting on |cond|,
+nothing happens. If several threads are waiting on |cond|, exactly one
+is restarted, but it is not specified which.
+
+!pthread_cond_broadcast! restarts all the threads that are waiting on
+the condition variable |cond|. Nothing happens if no threads are
+waiting on |cond|.
+
+!pthread_cond_wait! atomically unlocks the |mutex| (as per
+!pthread_unlock_mutex!) and waits for the condition variable |cond| to
+be signaled. The thread execution is suspended and does not consume
+any CPU time until the condition variable is signaled. The |mutex|
+must be locked by the calling thread on entrance to
+!pthread_cond_wait!. Before returning to the calling thread,
+!pthread_cond_wait! re-acquires |mutex| (as per !pthread_lock_mutex!).
+
+Unlocking the mutex and suspending on the condition variable is done
+atomically. Thus, if all threads always acquire the mutex before
+signaling the condition, this guarantees that the condition cannot be
+signaled (and thus ignored) between the time a thread locks the mutex
+and the time it waits on the condition variable.
+
+!pthread_cond_timedwait! atomically unlocks |mutex| and waits on
+|cond|, as !pthread_cond_wait! does, but it also bounds the duration
+of the wait. If |cond| has not been signaled within the amount of time
+specified by |abstime|, the mutex |mutex| is re-acquired and
+!pthread_cond_timedwait! returns the error !ETIMEDOUT!.
+The |abstime| parameter specifies an absolute time, with the same
+origin as !time!(2) and !gettimeofday!(2): an |abstime| of 0
+corresponds to 00:00:00 GMT, January 1, 1970.
+
+!pthread_cond_destroy! destroys a condition variable, freeing the
+resources it might hold. No threads must be waiting on the condition
+variable on entrance to !pthread_cond_destroy!. In the LinuxThreads
+implementation, no resources are associated with condition variables,
+thus !pthread_cond_destroy! actually does nothing except checking that
+the condition has no waiting threads.
+
+.SH CANCELLATION
+
+!pthread_cond_wait! and !pthread_cond_timedwait! are cancellation
+points. If a thread is cancelled while suspended in one of these
+functions, the thread immediately resumes execution, then locks again
+the |mutex| argument to !pthread_cond_wait! and
+!pthread_cond_timedwait!, and finally executes the cancellation.
+Consequently, cleanup handlers are assured that |mutex| is locked when
+they are called.
+
+.SH "ASYNC-SIGNAL SAFETY"
+
+The condition functions are not async-signal safe, and should not be
+called from a signal handler. In particular, calling
+!pthread_cond_signal! or !pthread_cond_broadcast! from a signal
+handler may deadlock the calling thread.
+
+.SH "RETURN VALUE"
+
+All condition variable functions return 0 on success and a non-zero
+error code on error.
+
+.SH ERRORS
+
+!pthread_cond_init!, !pthread_cond_signal!, !pthread_cond_broadcast!,
+and !pthread_cond_wait! never return an error code.
+
+The !pthread_cond_timedwait! function returns the following error codes
+on error:
+.RS
+.TP
+!ETIMEDOUT!
+the condition variable was not signaled until the timeout specified by
+|abstime|
+
+.TP
+!EINTR!
+!pthread_cond_timedwait! was interrupted by a signal
+.RE
+
+The !pthread_cond_destroy! function returns the following error code
+on error:
+.RS
+.TP
+!EBUSY!
+some threads are currently waiting on |cond|.
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_condattr_init!(3),
+!pthread_mutex_lock!(3),
+!pthread_mutex_unlock!(3),
+!gettimeofday!(2),
+!nanosleep!(2).
+
+.SH EXAMPLE
+
+Consider two shared variables |x| and |y|, protected by the mutex |mut|,
+and a condition variable |cond| that is to be signaled whenever |x|
+becomes greater than |y|.
+
+.RS
+.ft 3
+.nf
+.sp
+int x,y;
+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+.ft
+.LP
+.RE
+.fi
+
+Waiting until |x| is greater than |y| is performed as follows:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_mutex_lock(&mut);
+while (x <= y) {
+        pthread_cond_wait(&cond, &mut);
+}
+/* operate on x and y */
+pthread_mutex_unlock(&mut);
+.ft
+.LP
+.RE
+.fi
+
+Modifications on |x| and |y| that may cause |x| to become greater than
+|y| should signal the condition if needed:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_mutex_lock(&mut);
+/* modify x and y */
+if (x > y) pthread_cond_broadcast(&cond);
+pthread_mutex_unlock(&mut);
+.ft
+.LP
+.RE
+.fi
+
+If it can be proved that at most one waiting thread needs to be waken
+up (for instance, if there are only two threads communicating through
+|x| and |y|), !pthread_cond_signal! can be used as a slightly more
+efficient alternative to !pthread_cond_broadcast!. In doubt, use
+!pthread_cond_broadcast!.
+
+To wait for |x| to becomes greater than |y| with a timeout of 5
+seconds, do:
+
+.RS
+.ft 3
+.nf
+.sp
+struct timeval now;
+struct timespec timeout;
+int retcode;
+
+pthread_mutex_lock(&mut);
+gettimeofday(&now);
+timeout.tv_sec = now.tv_sec + 5;
+timeout.tv_nsec = now.tv_usec * 1000;
+retcode = 0;
+while (x <= y && retcode != ETIMEDOUT) {
+        retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
+}
+if (retcode == ETIMEDOUT) {
+        /* timeout occurred */
+} else {
+        /* operate on x and y */
+}
+pthread_mutex_unlock(&mut);
+.ft
+.LP
+.RE
+.fi
diff --git a/linuxthreads/man/pthread_condattr_init.man b/linuxthreads/man/pthread_condattr_init.man
new file mode 100644
index 0000000000..f491cbedbe
--- /dev/null
+++ b/linuxthreads/man/pthread_condattr_init.man
@@ -0,0 +1,39 @@
+.TH PTHREAD_CONDATTR 3 LinuxThreads
+
+.XREF pthread_condattr_destroy
+
+.SH NAME
+pthread_condattr_init, pthread_condattr_destroy \- condition creation attributes
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_condattr_init(pthread_condattr_t *attr);
+
+int pthread_condattr_destroy(pthread_condattr_t *attr);
+
+.SH DESCRIPTION
+
+Condition attributes can be specified at condition creation time, by passing a
+condition attribute object as second argument to !pthread_cond_init!(3).
+Passing !NULL! is equivalent to passing a condition attribute object with
+all attributes set to their default values.
+
+The LinuxThreads implementation supports no attributes for
+conditions. The functions on condition attributes are included only
+for compliance with the POSIX standard.
+
+!pthread_condattr_init! initializes the condition attribute object
+|attr| and fills it with default values for the attributes.
+!pthread_condattr_destroy! destroys a condition attribute object,
+which must not be reused until it is reinitialized. Both functions do
+nothing in the LinuxThreads implementation.
+
+.SH "RETURN VALUE"
+!pthread_condattr_init! and !pthread_condattr_destroy! always return 0.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_cond_init!(3).
diff --git a/linuxthreads/man/pthread_create.man b/linuxthreads/man/pthread_create.man
new file mode 100644
index 0000000000..a94004767a
--- /dev/null
+++ b/linuxthreads/man/pthread_create.man
@@ -0,0 +1,46 @@
+.TH PTHREAD_CREATE 3 LinuxThreads
+
+.SH NAME
+pthread_create \- create a new thread
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
+
+.SH DESCRIPTION
+!pthread_create! creates a new thread of control that executes
+concurrently with the calling thread. The new thread applies the
+function |start_routine| passing it |arg| as first argument. The new
+thread terminates either explicitly, by calling !pthread_exit!(3),
+or implicitly, by returning from the |start_routine| function. The
+latter case is equivalent to calling !pthread_exit!(3) with the result
+returned by |start_routine| as exit code.
+
+The |attr| argument specifies thread attributes to be applied to the
+new thread. See !pthread_attr_init!(3) for a complete list of thread
+attributes. The |attr| argument can also be !NULL!, in which case
+default attributes are used: the created thread is joinable (not
+detached) and has default (non real-time) scheduling policy.
+
+.SH "RETURN VALUE"
+On success, the identifier of the newly created thread is stored in
+the location pointed by the |thread| argument, and a 0 is returned. On
+error, a non-zero error code is returned.
+
+.SH ERRORS
+.TP
+!EAGAIN!
+not enough system resources to create a process for the new thread.
+.TP
+!EAGAIN!
+more than !PTHREAD_THREADS_MAX! threads are already active.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_exit!(3),
+!pthread_join!(3),
+!pthread_detach!(3),
+!pthread_attr_init!(3).
diff --git a/linuxthreads/man/pthread_detach.man b/linuxthreads/man/pthread_detach.man
new file mode 100644
index 0000000000..7b43f45faa
--- /dev/null
+++ b/linuxthreads/man/pthread_detach.man
@@ -0,0 +1,44 @@
+.TH PTHREAD_DETACH 3 LinuxThreads
+
+.SH NAME
+pthread_detach \- put a running thread in the detached state
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_detach(pthread_t th);
+
+.SH DESCRIPTION
+!pthread_detach! put the thread |th| in the detached state. This
+guarantees that the memory resources consumed by |th| will be freed
+immediately when |th| terminates. However, this prevents other threads
+from synchronizing on the termination of |th| using !pthread_join!.
+
+A thread can be created initially in the detached state, using the
+!detachstate! attribute to !pthread_create!(3). In contrast,
+!pthread_detach! applies to threads created in the joinable state, and
+which need to be put in the detached state later.
+
+After !pthread_detach! completes, subsequent attempts to perform
+!pthread_join! on |th| will fail. If another thread is already joining
+the thread |th| at the time !pthread_detach! is called,
+!pthread_detach! does nothing and leaves |th| in the joinable state.
+
+.SH "RETURN VALUE"
+On success, 0 is returned. On error, a non-zero error code is returned.
+
+.SH ERRORS
+.TP
+!ESRCH!
+No thread could be found corresponding to that specified by |th|
+.TP
+!EINVAL!
+the thread |th| is already in the detached state
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_create!(3),
+!pthread_join!(3),
+!pthread_attr_setdetachstate!(3).
\ No newline at end of file
diff --git a/linuxthreads/man/pthread_equal.man b/linuxthreads/man/pthread_equal.man
new file mode 100644
index 0000000000..1a0396515a
--- /dev/null
+++ b/linuxthreads/man/pthread_equal.man
@@ -0,0 +1,23 @@
+.TH PTHREAD_EQUAL 3 LinuxThreads
+
+.SH NAME
+pthread_equal \- compare two thread identifiers
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_equal(pthread_t thread1, pthread_t thread2);
+
+.SH DESCRIPTION
+!pthread_equal! determines if two thread identifiers refer to the same
+thread.
+
+.SH "RETURN VALUE"
+A non-zero value is returned if |thread1| and |thread2| refer to the
+same thread. Otherwise, 0 is returned.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_self!(3).
diff --git a/linuxthreads/man/pthread_exit.man b/linuxthreads/man/pthread_exit.man
new file mode 100644
index 0000000000..54751e9d05
--- /dev/null
+++ b/linuxthreads/man/pthread_exit.man
@@ -0,0 +1,32 @@
+.TH PTHREAD_EXIT 3 LinuxThreads
+
+.SH NAME
+pthread_exit \- terminate the calling thread
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+void pthread_exit(void *retval);
+
+.SH DESCRIPTION
+!pthread_exit! terminates the execution of the calling thread.
+All cleanup handlers that have been set for the calling thread with
+!pthread_cleanup_push!(3) are executed in reverse order (the most
+recently pushed handler is executed first). Finalization functions for
+thread-specific data are then called for all keys that have non-!NULL!
+values associated with them in the calling thread (see
+!pthread_key_create!(3)). Finally, execution of the calling thread is
+stopped.
+
+The |retval| argument is the return value of the thread. It can be
+consulted from another thread using !pthread_join!(3).
+
+.SH "RETURN VALUE"
+The !pthread_exit! function never returns.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_create!(3),
+!pthread_join!(3).
diff --git a/linuxthreads/man/pthread_join.man b/linuxthreads/man/pthread_join.man
new file mode 100644
index 0000000000..d587093841
--- /dev/null
+++ b/linuxthreads/man/pthread_join.man
@@ -0,0 +1,70 @@
+.TH PTHREAD_JOIN 3 LinuxThreads
+
+.SH NAME
+pthread_join \- wait for termination of another thread
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_join(pthread_t th, void **thread_return);
+
+.SH DESCRIPTION
+!pthread_join! suspends the execution of the calling thread until the
+thread identified by |th| terminates, either by calling !pthread_exit!(3)
+or by being cancelled.
+
+If |thread_return| is not !NULL!, the return value of |th| is stored
+in the location pointed to by |thread_return|.  The return value of
+|th| is either the argument it gave to !pthread_exit!(3), or
+!PTHREAD_CANCELED! if |th| was cancelled.
+
+The joined thread !th! must be in the joinable state: it must not have
+been detached using !pthread_detach!(3) or the
+!PTHREAD_CREATE_DETACHED! attribute to !pthread_create!(3).
+
+When a joinable thread terminates, its memory resources (thread
+descriptor and stack) are not deallocated until another thread
+performs !pthread_join! on it. Therefore, !pthread_join! must be
+called once for each joinable thread created to avoid memory leaks.
+
+At most one thread can wait for the termination of a given
+thread. Calling !pthread_join! on a thread |th| on which another
+thread is already waiting for termination returns an error.
+
+.SH CANCELLATION
+
+!pthread_join! is a cancellation point. If a thread is canceled while
+suspended in !pthread_join!, the thread execution resumes immediately
+and the cancellation is executed without waiting for the |th| thread
+to terminate. If cancellation occurs during !pthread_join!, the |th|
+thread remains not joined.
+
+.SH "RETURN VALUE"
+On success, the return value of |th| is stored in the location pointed
+to by |thread_return|, and 0 is returned. On error, a non-zero error
+code is returned.
+
+.SH ERRORS
+.TP
+!ESRCH!
+No thread could be found corresponding to that specified by |th|.
+.TP
+!EINVAL!
+The |th| thread has been detached.
+.TP
+!EINVAL!
+Another thread is already waiting on termination of |th|.
+.TP
+!EDEADLK!
+The |th| argument refers to the calling thread.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_exit!(3),
+!pthread_detach!(3),
+!pthread_create!(3),
+!pthread_attr_setdetachstate!(3),
+!pthread_cleanup_push!(3),
+!pthread_key_create!(3).
diff --git a/linuxthreads/man/pthread_key_create.man b/linuxthreads/man/pthread_key_create.man
new file mode 100644
index 0000000000..6823e304c9
--- /dev/null
+++ b/linuxthreads/man/pthread_key_create.man
@@ -0,0 +1,151 @@
+.TH PTHREAD_SPECIFIC 3 LinuxThreads
+
+.SH NAME
+pthread_key_create, pthread_key_delete, pthread_setspecific, pthread_getspecific \- management of thread-specific data
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));
+
+int pthread_key_delete(pthread_key_t key);
+
+int pthread_setspecific(pthread_key_t key, const void *pointer);
+
+void * pthread_getspecific(pthread_key_t key);
+
+.SH DESCRIPTION
+
+Programs often need global or static variables that have different
+values in different threads. Since threads share one memory space,
+this cannot be achieved with regular variables. Thread-specific data
+is the POSIX threads answer to this need.
+
+Each thread possesses a private memory block, the thread-specific data
+area, or TSD area for short. This area is indexed by TSD keys. The TSD
+area associates values of type !void *! to TSD keys. TSD keys are
+common to all threads, but the value associated with a given TSD key
+can be different in each thread.
+
+For concreteness, the TSD areas can be viewed as arrays of !void *!
+pointers, TSD keys as integer indices into these arrays, and the value
+of a TSD key as the value of the corresponding array element in the
+calling thread.
+
+When a thread is created, its TSD area initially associates !NULL!
+with all keys.
+
+!pthread_key_create! allocates a new TSD key. The key is stored in the
+location pointed to by |key|. There is a limit of !PTHREAD_KEYS_MAX!
+on the number of keys allocated at a given time. The value initially
+associated with the returned key is !NULL! in all currently executing
+threads.
+
+The |destr_function| argument, if not !NULL!, specifies a destructor
+function associated with the key. When a thread terminates via
+!pthread_exit! or by cancellation, |destr_function| is called with
+arguments the value associated with the key in that thread. The
+|destr_function| is not called if that value is !NULL!. The order in
+which destructor functions are called at thread termination time is
+unspecified.
+
+Before the destructor function is called, the !NULL! value is
+associated with the key in the current thread.  A destructor function
+might, however, re-associate non-!NULL! values to that key or some
+other key.  To deal with this, if after all the destructors have been
+called for all non-!NULL! values, there are still some non-!NULL!
+values with associated destructors, then the process is repeated.  The
+LinuxThreads implementation stops the process after
+!PTHREAD_DESTRUCTOR_ITERATIONS! iterations, even if some non-!NULL!
+values with associated descriptors remain.  Other implementations may
+loop indefinitely.
+
+!pthread_key_delete! deallocates a TSD key. It does not check whether
+non-!NULL! values are associated with that key in the currently
+executing threads, nor call the destructor function associated with
+the key.
+
+!pthread_setspecific! changes the value associated with |key| in the
+calling thread, storing the given |pointer| instead.
+
+!pthread_getspecific! returns the value currently associated with
+|key| in the calling thread.
+
+.SH "RETURN VALUE"
+
+!pthread_key_create!, !pthread_key_delete!, and !pthread_setspecific!
+return 0 on success and a non-zero error code on failure. If
+successful, !pthread_key_create! stores the newly allocated key in the
+location pointed to by its |key| argument.
+
+!pthread_getspecific! returns the value associated with |key| on
+success, and !NULL! on error.
+
+.SH ERRORS
+!pthread_key_create! returns the following error code on error:
+.RS
+.TP
+!EAGAIN!
+!PTHREAD_KEYS_MAX! keys are already allocated
+.RE
+
+!pthread_key_delete! and !pthread_setspecific! return the following
+error code on error:
+.RS
+.TP
+!EINVAL!
+|key| is not a valid, allocated TSD key
+.RE
+
+!pthread_getspecific! returns !NULL! if |key| is not a valid,
+allocated TSD key.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+pthread_create(3), pthread_exit(3), pthread_testcancel(3).
+
+.SH EXAMPLE
+
+The following code fragment allocates a thread-specific array of 100
+characters, with automatic reclaimation at thread exit:
+
+.RS
+.ft 3
+.nf
+.sp
+/* Key for the thread-specific buffer */
+static pthread_key_t buffer_key;
+
+/* Once-only initialisation of the key */
+static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
+
+/* Allocate the thread-specific buffer */
+void buffer_alloc(void)
+{
+  pthread_once(&buffer_key_once, buffer_key_alloc);
+  pthread_setspecific(buffer_key, malloc(100));
+}
+
+/* Return the thread-specific buffer */
+char * get_buffer(void)
+{
+  return (char *) pthread_getspecific(buffer_key);
+}
+
+/* Allocate the key */
+static void buffer_key_alloc()
+{
+  pthread_key_create(&buffer_key, buffer_destroy);
+}
+
+/* Free the thread-specific buffer */
+static void buffer_destroy(void * buf)
+{
+  free(buf);
+}
+.ft
+.LP
+.RE
+.fi
diff --git a/linuxthreads/man/pthread_kill_other_threads_np.man b/linuxthreads/man/pthread_kill_other_threads_np.man
new file mode 100644
index 0000000000..0de42d52d5
--- /dev/null
+++ b/linuxthreads/man/pthread_kill_other_threads_np.man
@@ -0,0 +1,40 @@
+.TH PTHREAD_KILL_OTHER_THREADS_NP 3 LinuxThreads
+
+.SH NAME
+pthread_kill_other_threads_np \- terminate all threads in program except calling thread
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+void pthread_kill_other_threads_np(void);
+
+.SH DESCRIPTION
+!pthread_kill_other_threads_np! is a non-portable LinuxThreads extension.
+It causes all threads in the program to terminate immediately, except
+the calling thread which proceeds normally. It is intended to be
+called just before a thread calls one of the !exec! functions,
+e.g. !execve!(2).
+
+Termination of the other threads is not performed through
+!pthread_cancel!(3) and completely bypasses the cancellation
+mechanism. Hence, the current settings for cancellation state and
+cancellation type are ignored, and the cleanup handlers are not
+executed in the terminated threads.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!execve!(2),
+!pthread_setcancelstate!(3),
+!pthread_setcanceltype!(3),
+!pthread_cancel!(3).
+
+.SH BUGS
+
+According to POSIX 1003.1c, a successful !exec*! in one of the threads
+should terminate automatically all other threads in the program.
+This behavior is not yet implemented in LinuxThreads.
+Calling !pthread_kill_other_threads_np! before !exec*! achieves much
+of the same behavior, except that if !exec*! ultimately fails, then
+all other threads are already killed.
diff --git a/linuxthreads/man/pthread_mutex_init.man b/linuxthreads/man/pthread_mutex_init.man
new file mode 100644
index 0000000000..643b007aec
--- /dev/null
+++ b/linuxthreads/man/pthread_mutex_init.man
@@ -0,0 +1,213 @@
+.TH PTHREAD_MUTEX 3 LinuxThreads
+
+.XREF pthread_mutex_lock
+.XREF pthread_mutex_unlock
+.XREF pthread_mutex_trylock
+.XREF pthread_mutex_destroy
+
+.SH NAME
+pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock, pthread_mutex_destroy \- operations on mutexes
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
+
+pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
+
+int pthread_mutex_lock(pthread_mutex_t *mutex);
+
+int pthread_mutex_trylock(pthread_mutex_t *mutex);
+
+int pthread_mutex_unlock(pthread_mutex_t *mutex);
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex);
+
+.SH DESCRIPTION
+A mutex is a MUTual EXclusion device, and is useful for protecting
+shared data structures from concurrent modifications, and implementing
+critical sections and monitors.
+
+A mutex has two possible states: unlocked (not owned by any thread),
+and locked (owned by one thread). A mutex can never be owned by two
+different threads simultaneously. A thread attempting to lock a mutex
+that is already locked by another thread is suspended until the owning
+thread unlocks the mutex first.
+
+!pthread_mutex_init! initializes the mutex object pointed to by
+|mutex| according to the mutex attributes specified in |mutexattr|.
+If |mutexattr| is !NULL!, default attributes are used instead.
+
+The LinuxThreads implementation supports only one mutex attributes,
+the |mutex kind|, which is either ``fast'', ``recursive'', or
+``error checking''. The kind of a mutex determines whether
+it can be locked again by a thread that already owns it.
+The default kind is ``fast''. See !pthread_mutexattr_init!(3) for more
+information on mutex attributes.
+
+Variables of type !pthread_mutex_t! can also be initialized
+statically, using the constants !PTHREAD_MUTEX_INITIALIZER! (for fast
+mutexes), !PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP! (for recursive
+mutexes), and !PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP! (for error checking
+mutexes).
+
+!pthread_mutex_lock! locks the given mutex. If the mutex is currently
+unlocked, it becomes locked and owned by the calling thread, and
+!pthread_mutex_lock! returns immediately. If the mutex is already
+locked by another thread, !pthread_mutex_lock! suspends the calling
+thread until the mutex is unlocked.
+
+If the mutex is already locked by the calling thread, the behavior of
+!pthread_mutex_lock! depends on the kind of the mutex. If the mutex is
+of the ``fast'' kind, the calling thread is suspended until the mutex
+is unlocked, thus effectively causing the calling thread to
+deadlock. If the mutex is of the ``error checking'' kind,
+!pthread_mutex_lock! returns immediately with the error code !EDEADLK!.
+If the mutex is of the ``recursive'' kind, !pthread_mutex_lock!
+succeeds and returns immediately, recording the number of times the
+calling thread has locked the mutex. An equal number of
+!pthread_mutex_unlock! operations must be performed before the mutex
+returns to the unlocked state.
+
+!pthread_mutex_trylock! behaves identically to !pthread_mutex_lock!,
+except that it does not block the calling thread if the mutex is
+already locked by another thread (or by the calling thread in the case
+of a ``fast'' mutex). Instead, !pthread_mutex_trylock! returns
+immediately with the error code !EBUSY!.
+
+!pthread_mutex_unlock! unlocks the given mutex. The mutex is assumed
+to be locked and owned by the calling thread on entrance to
+!pthread_mutex_unlock!. If the mutex is of the ``fast'' kind,
+!pthread_mutex_unlock! always returns it to the unlocked state. If it
+is of the ``recursive'' kind, it decrements the locking count of the
+mutex (number of !pthread_mutex_lock! operations performed on it by
+the calling thread), and only when this count reaches zero is the
+mutex actually unlocked.
+
+On ``error checking'' mutexes, !pthread_mutex_unlock! actually checks
+at run-time that the mutex is locked on entrance, and that it was
+locked by the same thread that is now calling !pthread_mutex_unlock!.
+If these conditions are not met, an error code is returned and the
+mutex remains unchanged.  ``Fast'' and ``recursive'' mutexes perform
+no such checks, thus allowing a locked mutex to be unlocked by a
+thread other than its owner. This is non-portable behavior and must
+not be relied upon.
+
+!pthread_mutex_destroy! destroys a mutex object, freeing the resources
+it might hold. The mutex must be unlocked on entrance. In the
+LinuxThreads implementation, no resources are associated with mutex
+objects, thus !pthread_mutex_destroy! actually does nothing except
+checking that the mutex is unlocked.
+
+.SH CANCELLATION
+
+None of the mutex functions is a cancellation point, not even
+!pthread_mutex_lock!, in spite of the fact that it can suspend a
+thread for arbitrary durations. This way, the status of mutexes at
+cancellation points is predictable, allowing cancellation handlers to
+unlock precisely those mutexes that need to be unlocked before the
+thread stops executing. Consequently, threads using deferred
+cancellation should never hold a mutex for extended periods of time.
+
+.SH "ASYNC-SIGNAL SAFETY"
+
+The mutex functions are not async-signal safe. What this means is that
+they should not be called from a signal handler. In particular,
+calling !pthread_mutex_lock! or !pthread_mutex_unlock! from a signal
+handler may deadlock the calling thread.
+
+.SH "RETURN VALUE"
+
+!pthread_mutex_init! always returns 0. The other mutex functions
+return 0 on success and a non-zero error code on error.
+
+.SH ERRORS
+
+The !pthread_mutex_lock! function returns the following error code
+on error:
+.RS
+.TP
+!EINVAL!
+the mutex has not been properly initialized.
+
+.TP
+!EDEADLK!
+the mutex is already locked by the calling thread
+(``error checking'' mutexes only).
+.RE
+
+The !pthread_mutex_trylock! function returns the following error codes
+on error:
+.RS
+.TP
+!EBUSY!
+the mutex could not be acquired because it was currently locked.
+
+.TP
+!EINVAL!
+the mutex has not been properly initialized.
+.RE
+
+The !pthread_mutex_unlock! function returns the following error code
+on error:
+.RS
+.TP
+!EINVAL!
+the mutex has not been properly initialized.
+
+.TP
+!EPERM!
+the calling thread does not own the mutex (``error checking'' mutexes only).
+.RE
+
+The !pthread_mutex_destroy! function returns the following error code
+on error:
+.RS
+.TP
+!EBUSY!
+the mutex is currently locked.
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_mutexattr_init!(3),
+!pthread_mutexattr_setkind_np!(3),
+!pthread_cancel!(3).
+
+.SH EXAMPLE
+
+A shared global variable |x| can be protected by a mutex as follows:
+
+.RS
+.ft 3
+.nf
+.sp
+int x;
+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+.ft
+.LP
+.RE
+.fi
+
+All accesses and modifications to |x| should be bracketed by calls to
+!pthread_mutex_lock! and !pthread_mutex_unlock! as follows:
+
+.RS
+.ft 3
+.nf
+.sp
+pthread_mutex_lock(&mut);
+/* operate on x */
+pthread_mutex_unlock(&mut);
+.ft
+.LP
+.RE
+.fi
+
+
diff --git a/linuxthreads/man/pthread_mutexattr_init.man b/linuxthreads/man/pthread_mutexattr_init.man
new file mode 100644
index 0000000000..b838948904
--- /dev/null
+++ b/linuxthreads/man/pthread_mutexattr_init.man
@@ -0,0 +1,84 @@
+.TH PTHREAD_MUTEXATTR 3 LinuxThreads
+
+.XREF pthread_mutexattr_destroy
+.XREF pthread_mutexattr_settype
+.XREF pthread_mutexattr_gettype
+
+.SH NAME
+pthread_mutexattr_init, pthread_mutexattr_destroy, pthread_mutexattr_settype, pthread_mutexattr_gettype \- mutex creation attributes
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_mutexattr_init(pthread_mutexattr_t *attr);
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
+
+int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
+
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);
+
+.SH DESCRIPTION
+
+Mutex attributes can be specified at mutex creation time, by passing a
+mutex attribute object as second argument to !pthread_mutex_init!(3).
+Passing !NULL! is equivalent to passing a mutex attribute object with
+all attributes set to their default values.
+
+!pthread_mutexattr_init! initializes the mutex attribute object |attr|
+and fills it with default values for the attributes.
+
+!pthread_mutexattr_destroy! destroys a mutex attribute object, which
+must not be reused until it is reinitialized. !pthread_mutexattr_destroy!
+does nothing in the LinuxThreads implementation. 
+
+LinuxThreads supports only one mutex attribute: the mutex kind, which
+is either !PTHREAD_MUTEX_FAST_NP! for ``fast'' mutexes,
+!PTHREAD_MUTEX_RECURSIVE_NP! for ``recursive'' mutexes,
+or !PTHREAD_MUTEX_ERRORCHECK_NP! for ``error checking'' mutexes.
+As the !NP! suffix indicates, this is a non-portable extension to the
+POSIX standard and should not be employed in portable programs.
+
+The mutex kind determines what happens if a thread attempts to lock a
+mutex it already owns with !pthread_mutex_lock!(3). If the mutex is of
+the ``fast'' kind, !pthread_mutex_lock!(3) simply suspends the calling
+thread forever.  If the mutex is of the ``error checking'' kind,
+!pthread_mutex_lock!(3) returns immediately with the error code
+!EDEADLK!.  If the mutex is of the ``recursive'' kind, the call to
+!pthread_mutex_lock!(3) returns immediately with a success return
+code. The number of times the thread owning the mutex has locked it is
+recorded in the mutex. The owning thread must call
+!pthread_mutex_unlock!(3) the same number of times before the mutex
+returns to the unlocked state.
+
+The default mutex kind is ``fast'', that is, !PTHREAD_MUTEX_FAST_NP!.
+
+!pthread_mutexattr_settype! sets the mutex kind attribute in |attr|
+to the value specified by |kind|.
+
+!pthread_mutexattr_gettype! retrieves the current value of the
+mutex kind attribute in |attr| and stores it in the location pointed
+to by |kind|.
+
+.SH "RETURN VALUE"
+!pthread_mutexattr_init!, !pthread_mutexattr_destroy! and
+!pthread_mutexattr_gettype! always return 0.
+
+!pthread_mutexattr_settype! returns 0 on success and a non-zero
+error code on error.
+
+.SH ERRORS
+
+On error, !pthread_mutexattr_settype! returns the following error code:
+.TP
+!EINVAL!
+|kind| is neither !PTHREAD_MUTEX_FAST_NP! nor !PTHREAD_MUTEX_RECURSIVE_NP!
+nor !PTHREAD_MUTEX_ERRORCHECK_NP!
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_mutex_init!(3),
+!pthread_mutex_lock!(3),
+!pthread_mutex_unlock!(3).
diff --git a/linuxthreads/man/pthread_mutexattr_setkind_np.man b/linuxthreads/man/pthread_mutexattr_setkind_np.man
new file mode 100644
index 0000000000..e10f47d0e5
--- /dev/null
+++ b/linuxthreads/man/pthread_mutexattr_setkind_np.man
@@ -0,0 +1,39 @@
+.TH PTHREAD_MUTEXATTR_SETKIND_NP 3 LinuxThreads
+
+.XREF pthread_mutexattr_getkind_np
+
+.SH NAME
+pthread_mutexattr_setkind_np, pthread_mutexattr_getkind_np \- deprecated mutex creation attributes
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
+
+int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind);
+
+.SH DESCRIPTION
+
+These functions are deprecated, use !pthread_mutexattr_settype!(3)
+and !pthread_mutexattr_gettype!(3) instead.
+
+.SH "RETURN VALUE"
+!pthread_mutexattr_getkind_np! always returns 0.
+
+!pthread_mutexattr_setkind_np! returns 0 on success and a non-zero
+error code on error.
+
+.SH ERRORS
+
+On error, !pthread_mutexattr_setkind_np! returns the following error code:
+.TP
+!EINVAL!
+|kind| is neither !PTHREAD_MUTEX_FAST_NP! nor !PTHREAD_MUTEX_RECURSIVE_NP!
+nor !PTHREAD_MUTEX_ERRORCHECK_NP!
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_mutexattr_settype!(3),
+!pthread_mutexattr_gettype!(3).
diff --git a/linuxthreads/man/pthread_once.man b/linuxthreads/man/pthread_once.man
new file mode 100644
index 0000000000..e9d117b656
--- /dev/null
+++ b/linuxthreads/man/pthread_once.man
@@ -0,0 +1,34 @@
+.TH PTHREAD_ONCE 3 LinuxThreads
+
+.SH NAME
+pthread_once \- once-only initialization
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));
+
+.SH DESCRIPTION
+
+The purpose of !pthread_once! is to ensure that a piece of
+initialization code is executed at most once. The |once_control|
+argument points to a static or extern variable statically initialized
+to !PTHREAD_ONCE_INIT!.
+
+The first time !pthread_once! is called with a given |once_control|
+argument, it calls |init_routine| with no argument and changes the
+value of the |once_control| variable to record that initialization has
+been performed. Subsequent calls to !pthread_once! with the same
+!once_control! argument do nothing. 
+
+.SH "RETURN VALUE"
+!pthread_once! always returns 0.
+
+.SH ERRORS
+None.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
diff --git a/linuxthreads/man/pthread_self.man b/linuxthreads/man/pthread_self.man
new file mode 100644
index 0000000000..3aa4a0021e
--- /dev/null
+++ b/linuxthreads/man/pthread_self.man
@@ -0,0 +1,23 @@
+.TH PTHREAD_SELF 3 LinuxThreads
+
+.SH NAME
+pthread_self \- return identifier of current thread
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+pthread_t pthread_self(void);
+
+.SH DESCRIPTION
+!pthread_self! return the thread identifier for the calling thread.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_equal!(3),
+!pthread_join!(3),
+!pthread_detach!(3),
+!pthread_setschedparam!(3),
+!pthread_getschedparam!(3).
+
diff --git a/linuxthreads/man/pthread_setschedparam.man b/linuxthreads/man/pthread_setschedparam.man
new file mode 100644
index 0000000000..3992927837
--- /dev/null
+++ b/linuxthreads/man/pthread_setschedparam.man
@@ -0,0 +1,79 @@
+.TH PTHREAD_SETSCHEDPARAM 3 LinuxThreads
+
+.XREF pthread_getschedparam
+
+.SH NAME
+pthread_setschedparam, pthread_getschedparam \- control thread scheduling parameters
+
+.SH SYNOPSIS
+#include <pthread.h>
+
+int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param);
+
+int pthread_getschedparam(pthread_t target_thread, int *policy, struct sched_param *param);
+
+.SH DESCRIPTION
+
+!pthread_setschedparam! sets the scheduling parameters for the thread
+|target_thread| as indicated by |policy| and |param|. |policy| can be
+either !SCHED_OTHER! (regular, non-realtime scheduling), !SCHED_RR!
+(realtime, round-robin) or !SCHED_FIFO! (realtime, first-in
+first-out). |param| specifies the scheduling priority for the two
+realtime policies.  See !sched_setpolicy!(2) for more information on
+scheduling policies.
+
+The realtime scheduling policies !SCHED_RR! and !SCHED_FIFO! are
+available only to processes with superuser privileges.
+
+!pthread_getschedparam! retrieves the scheduling policy and scheduling
+parameters for the thread |target_thread| and store them in the
+locations pointed to by |policy| and |param|, respectively.
+
+.SH "RETURN VALUE"
+!pthread_setschedparam! and !pthread_getschedparam! return 0 on
+success and a non-zero error code on error.
+
+.SH ERRORS
+On error, !pthread_setschedparam! returns the following error codes:
+.RS
+.TP
+!EINVAL!
+|policy| is not one of !SCHED_OTHER!, !SCHED_RR!, !SCHED_FIFO!
+
+.TP
+!EINVAL!
+the priority value specified by |param| is not valid for the specified policy
+
+.TP
+!EPERM!
+the calling process does not have superuser permissions
+
+.TP
+!ESRCH!
+the |target_thread| is invalid or has already terminated
+
+.TP
+!EFAULT!
+|param| points outside the process memory space
+.RE
+
+On error, !pthread_getschedparam! returns the following error codes:
+.RS
+.TP
+!ESRCH!
+the |target_thread| is invalid or has already terminated
+
+.TP
+!EFAULT!
+|policy| or |param| point outside the process memory space
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!sched_setscheduler!(2),
+!sched_getscheduler!(2),
+!sched_getparam!(2),
+!pthread_attr_setschedpolicy!(3),
+!pthread_attr_setschedparam!(3).
diff --git a/linuxthreads/man/pthread_sigmask.man b/linuxthreads/man/pthread_sigmask.man
new file mode 100644
index 0000000000..784161da2b
--- /dev/null
+++ b/linuxthreads/man/pthread_sigmask.man
@@ -0,0 +1,123 @@
+.TH PTHREAD_SIGNAL 3 LinuxThreads
+
+.XREF pthread_kill
+.XREF sigwait
+
+.SH NAME
+pthread_sigmask, pthread_kill, sigwait \- handling of signals in threads
+
+.SH SYNOPSIS
+#include <pthread.h>
+.br
+#include <signal.h>
+
+int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);
+
+int pthread_kill(pthread_t thread, int signo);
+
+int sigwait(const sigset_t *set, int *sig);
+
+.SH DESCRIPTION
+
+!pthread_sigmask! changes the signal mask for the calling thread as
+described by the |how| and |newmask| arguments. If |oldmask| is not
+!NULL!, the previous signal mask is stored in the location pointed to
+by |oldmask|. 
+
+The meaning of the |how| and |newmask| arguments is the same as for
+!sigprocmask!(2). If |how| is !SIG_SETMASK!, the signal mask is set to
+|newmask|. If |how| is !SIG_BLOCK!, the signals specified to |newmask|
+are added to the current signal mask.  If |how| is !SIG_UNBLOCK!, the
+signals specified to |newmask| are removed from the current signal
+mask.
+
+Recall that signal masks are set on a per-thread basis, but signal
+actions and signal handlers, as set with !sigaction!(2), are shared
+between all threads.
+
+!pthread_kill! send signal number |signo| to the thread
+|thread|. The signal is delivered and handled as described in
+!kill!(2).
+
+!sigwait! suspends the calling thread until one of the signals
+in |set| is delivered to the calling thread. It then stores the number
+of the signal received in the location pointed to by |sig| and
+returns. The signals in |set| must be blocked and not ignored on
+entrance to !sigwait!. If the delivered signal has a signal handler
+function attached, that function is |not| called.
+
+.SH CANCELLATION
+
+!sigwait! is a cancellation point.
+
+.SH "RETURN VALUE"
+
+On success, 0 is returned. On failure, a non-zero error code is returned.
+
+.SH ERRORS
+
+The !pthread_sigmask! function returns the following error codes
+on error:
+.RS
+.TP
+!EINVAL!
+|how| is not one of !SIG_SETMASK!, !SIG_BLOCK!, or !SIG_UNBLOCK!
+
+.TP
+!EFAULT!
+|newmask| or |oldmask| point to invalid addresses
+.RE
+
+The !pthread_kill! function returns the following error codes
+on error:
+.RS
+.TP
+!EINVAL!
+|signo| is not a valid signal number
+
+.TP
+!ESRCH!
+the thread |thread| does not exist (e.g. it has already terminated)
+.RE
+
+The !sigwait! function never returns an error.
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!sigprocmask!(2),
+!kill!(2),
+!sigaction!(2),
+!sigsuspend!(2).
+
+.SH NOTES
+
+For !sigwait! to work reliably, the signals being waited for must be
+blocked in all threads, not only in the calling thread, since
+otherwise the POSIX semantics for signal delivery do not guarantee
+that it's the thread doing the !sigwait! that will receive the signal.
+The best way to achieve this is block those signals before any threads
+are created, and never unblock them in the program other than by
+calling !sigwait!.
+
+.SH BUGS
+
+Signal handling in LinuxThreads departs significantly from the POSIX
+standard. According to the standard, ``asynchronous'' (external)
+signals are addressed to the whole process (the collection of all
+threads), which then delivers them to one particular thread. The
+thread that actually receives the signal is any thread that does
+not currently block the signal.
+
+In LinuxThreads, each thread is actually a kernel process with its own
+PID, so external signals are always directed to one particular thread.
+If, for instance, another thread is blocked in !sigwait! on that
+signal, it will not be restarted.
+
+The LinuxThreads implementation of !sigwait! installs dummy signal
+handlers for the signals in |set| for the duration of the wait. Since
+signal handlers are shared between all threads, other threads must not
+attach their own signal handlers to these signals, or alternatively
+they should all block these signals (which is recommended anyway --
+see the Notes section).
diff --git a/linuxthreads/man/sem_init.man b/linuxthreads/man/sem_init.man
new file mode 100644
index 0000000000..e3a1a63e36
--- /dev/null
+++ b/linuxthreads/man/sem_init.man
@@ -0,0 +1,132 @@
+.TH SEMAPHORES 3 LinuxThreads
+
+.XREF sem_wait
+.XREF sem_trywait
+.XREF sem_post
+.XREF sem_getvalue
+.XREF sem_destroy
+
+.SH NAME
+sem_init, sem_wait, sem_trywait, sem_post, sem_getvalue, sem_destroy \- operations on semaphores
+
+.SH SYNOPSIS
+#include <semaphore.h>
+
+int sem_init(sem_t *sem, int pshared, unsigned int value);
+
+int sem_wait(sem_t * sem);
+
+int sem_trywait(sem_t * sem);
+
+int sem_post(sem_t * sem);
+
+int sem_getvalue(sem_t * sem, int * sval);
+
+int sem_destroy(sem_t * sem);
+
+.SH DESCRIPTION
+This manual page documents POSIX 1003.1b semaphores, not to be
+confused with SystemV semaphores as described in !ipc!(5), !semctl!(2)
+and !semop!(2).
+
+Semaphores are counters for resources shared between threads. The
+basic operations on semaphores are: increment the counter atomically,
+and wait until the counter is non-null and decrement it atomically.
+
+!sem_init! initializes the semaphore object pointed to by |sem|. The
+count associated with the semaphore is set initially to |value|. The
+|pshared| argument indicates whether the semaphore is local to the
+current process (|pshared| is zero) or is to be shared between several
+processes (|pshared| is not zero). LinuxThreads currently does not
+support process-shared semaphores, thus !sem_init! always returns with
+error !ENOSYS! if |pshared| is not zero.
+
+!sem_wait! suspends the calling thread until the semaphore pointed to
+by |sem| has non-zero count. It then atomically decreases the
+semaphore count.
+
+!sem_trywait! is a non-blocking variant of !sem_wait!. If the
+semaphore pointed to by |sem| has non-zero count, the count is
+atomically decreased and !sem_trywait! immediately returns 0.
+If the semaphore count is zero, !sem_trywait! immediately returns with
+error !EAGAIN!.
+
+!sem_post! atomically increases the count of the semaphore pointed to
+by |sem|. This function never blocks and can safely be used in
+asynchronous signal handlers.
+
+!sem_getvalue! stores in the location pointed to by |sval| the current
+count of the semaphore |sem|.
+
+!sem_destroy! destroys a semaphore object, freeing the resources it
+might hold. No threads should be waiting on the semaphore at the time
+!sem_destroy! is called. In the LinuxThreads implementation, no
+resources are associated with semaphore objects, thus !sem_destroy!
+actually does nothing except checking that no thread is waiting on the
+semaphore.
+
+.SH CANCELLATION
+
+!sem_wait! is a cancellation point.
+
+.SH "ASYNC-SIGNAL SAFETY"
+
+On processors supporting atomic compare-and-swap (Intel 486, Pentium
+and later, Alpha, PowerPC, MIPS II, Motorola 68k), the !sem_post!
+function is async-signal safe and can therefore be
+called from signal handlers. This is the only thread synchronization
+function provided by POSIX threads that is async-signal safe.
+
+On the Intel 386 and the Sparc, the current LinuxThreads
+implementation of !sem_post! is not async-signal safe by lack of the
+required atomic operations.
+
+.SH "RETURN VALUE"
+
+The !sem_wait! and !sem_getvalue! functions always return 0.
+All other semaphore functions return 0 on success and -1 on error, in
+addition to writing an error code in !errno!.
+
+.SH ERRORS
+
+The !sem_init! function sets !errno! to the following codes on error:
+.RS
+.TP
+!EINVAL!
+|value| exceeds the maximal counter value !SEM_VALUE_MAX!
+.TP
+!ENOSYS!
+|pshared| is not zero
+.RE
+
+The !sem_trywait! function sets !errno! to the following error code on error:
+.RS
+.TP
+!EAGAIN!
+the semaphore count is currently 0
+.RE
+
+The !sem_post! function sets !errno! to the following error code on error:
+.RS
+.TP
+!ERANGE!
+after incrementation, the semaphore value would exceed !SEM_VALUE_MAX!
+(the semaphore count is left unchanged in this case)
+.RE
+
+The !sem_destroy! function sets !errno! to the following error code on error:
+.RS
+.TP
+!EBUSY!
+some threads are currently blocked waiting on the semaphore.
+.RE
+
+.SH AUTHOR
+Xavier Leroy <Xavier.Leroy@inria.fr>
+
+.SH "SEE ALSO"
+!pthread_mutex_init!(3),
+!pthread_cond_init!(3),
+!pthread_cancel!(3),
+!ipc!(5).
+
diff --git a/linuxthreads/man/troffprepro b/linuxthreads/man/troffprepro
new file mode 100755
index 0000000000..ba564fefbe
--- /dev/null
+++ b/linuxthreads/man/troffprepro
@@ -0,0 +1,68 @@
+#!/usr/local/bin/perl
+
+$insynopsis = 0;
+
+open(INPUT, $ARGV[0]) || die("cannot open $ARGV[0]");
+open(OUTPUT, "> $ARGV[1]") || die("cannot create $ARGV[1]");
+
+select(OUTPUT);
+
+line:
+while(<INPUT>) {
+  if (/^\.XREF (.*)$/) {
+    $xref = $1;
+    $_ = $ARGV[1];
+    m/^.*\.(([1-8]).*)$/;
+    $suffix = $1;
+    $extension = $2;
+    open(XREF, "> $xref.$suffix");
+    print XREF ".so man$extension/$ARGV[1]\n";
+    close(XREF);
+    next line;
+  }
+  if (/^\.SH/) {
+    $insynopsis = /SYNOPSIS/;
+    print $_;
+    next;
+  }
+  if ($insynopsis) {
+    if (/^#/) {
+      print ".B ", $_;
+    }
+    elsif (/^[a-z]/) {    
+      chop;
+#      if (m/^([a-zA-Z][a-zA-Z0-9_]*\s+[a-zA-Z][a-zA-Z0-9_]*)\(/) {
+#          print ".B \"", $1, "\"\n";
+#          $_ = '(' . $';
+#      }
+#      s/([a-zA-Z][a-zA-Z0-9_]*)(\s*[,()=])/" \1 "\2/g;
+      s/([ *])([a-zA-Z][a-zA-Z0-9_]*)(\s*[,)=])/\1" \2 "\3/g;
+      print ".BI \"", $_, "\"\n";
+    }
+    else {
+      print $_;
+    }
+    next;
+  }
+  chop;
+  s/!([^!]+)!\|([^|]+)\|([^\s]*)\s*/\n.BI "\1" "\2\3"\n/g;
+  s/([!|])([^!|]+)\1([^\s]*)\s*/do subst($1,$2,$3)/eg;
+  s/^\n+//;
+  s/\n+$//;
+  s/\n\n+/\n/g;
+  print $_, "\n";
+}
+
+close(INPUT);
+close(OUTPUT);
+
+sub subst {
+  local ($a, $b, $c) = @_;
+  if ($c) {
+    "\n" . ($a eq "!" ? ".BR " : ".IR ") . "\"$b\" $c\n"
+  } else {
+    "\n" . ($a eq "!" ? ".B " : ".I ") . "\"$b\"\n"
+  }
+}
+
+  
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c
new file mode 100644
index 0000000000..f21a6def6f
--- /dev/null
+++ b/linuxthreads/manager.c
@@ -0,0 +1,1112 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* The "thread manager" thread: manages creation and termination of threads */
+
+#include <assert.h>
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>		/* for poll */
+#include <sys/mman.h>           /* for mmap */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/wait.h>           /* for waitpid macros */
+#include <locale.h>		/* for __uselocale */
+#include <resolv.h>		/* for __resp */
+
+#include <ldsodefs.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "semaphore.h"
+#include <not-cancel.h>
+
+/* For debugging purposes put the maximum number of threads in a variable.  */
+const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX;
+
+#ifndef THREAD_SELF
+/* Indicate whether at least one thread has a user-defined stack (if 1),
+   or if all threads have stacks supplied by LinuxThreads (if 0). */
+int __pthread_nonstandard_stacks;
+#endif
+
+/* Number of active entries in __pthread_handles (used by gdb) */
+volatile int __pthread_handles_num = 2;
+
+/* Whether to use debugger additional actions for thread creation
+   (set to 1 by gdb) */
+volatile int __pthread_threads_debug;
+
+/* Globally enabled events.  */
+volatile td_thr_events_t __pthread_threads_events;
+
+/* Pointer to thread descriptor with last event.  */
+volatile pthread_descr __pthread_last_event;
+
+static pthread_descr manager_thread;
+
+/* Mapping from stack segment to thread descriptor. */
+/* Stack segment numbers are also indices into the __pthread_handles array. */
+/* Stack segment number 0 is reserved for the initial thread. */
+
+#if FLOATING_STACKS
+# define thread_segment(seq) NULL
+#else
+static inline pthread_descr thread_segment(int seg)
+{
+# ifdef _STACK_GROWS_UP
+  return (pthread_descr)(THREAD_STACK_START_ADDRESS + (seg - 1) * STACK_SIZE)
+         + 1;
+# else
+  return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
+         - 1;
+# endif
+}
+#endif
+
+/* Flag set in signal handler to record child termination */
+
+static volatile int terminated_children;
+
+/* Flag set when the initial thread is blocked on pthread_exit waiting
+   for all other threads to terminate */
+
+static int main_thread_exiting;
+
+/* Counter used to generate unique thread identifier.
+   Thread identifier is pthread_threads_counter + segment. */
+
+static pthread_t pthread_threads_counter;
+
+/* Forward declarations */
+
+static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
+                                 void * (*start_routine)(void *), void *arg,
+                                 sigset_t *mask, int father_pid,
+				 int report_events,
+				 td_thr_events_t *event_maskp);
+static void pthread_handle_free(pthread_t th_id);
+static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
+     __attribute__ ((noreturn));
+static void pthread_reap_children(void);
+static void pthread_kill_all_threads(int sig, int main_thread_also);
+static void pthread_for_each_thread(void *arg,
+    void (*fn)(void *, pthread_descr));
+
+/* The server thread managing requests for thread creation and termination */
+
+int
+__attribute__ ((noreturn))
+__pthread_manager(void *arg)
+{
+  pthread_descr self = manager_thread = arg;
+  int reqfd = __pthread_manager_reader;
+  struct pollfd ufd;
+  sigset_t manager_mask;
+  int n;
+  struct pthread_request request;
+
+  /* If we have special thread_self processing, initialize it.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, 1);
+#endif
+#if !(USE_TLS && HAVE___THREAD)
+  /* Set the error variable.  */
+  self->p_errnop = &self->p_errno;
+  self->p_h_errnop = &self->p_h_errno;
+#endif
+  /* Block all signals except __pthread_sig_cancel and SIGTRAP */
+  sigfillset(&manager_mask);
+  sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
+  sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
+  if (__pthread_threads_debug && __pthread_sig_debug > 0)
+    sigdelset(&manager_mask, __pthread_sig_debug);
+  sigprocmask(SIG_SETMASK, &manager_mask, NULL);
+  /* Raise our priority to match that of main thread */
+  __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
+  /* Synchronize debugging of the thread manager */
+  n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request,
+					 sizeof(request)));
+  ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
+  ufd.fd = reqfd;
+  ufd.events = POLLIN;
+  /* Enter server loop */
+  while(1) {
+    n = __poll(&ufd, 1, 2000);
+
+    /* Check for termination of the main thread */
+    if (getppid() == 1) {
+      pthread_kill_all_threads(SIGKILL, 0);
+      _exit(0);
+    }
+    /* Check for dead children */
+    if (terminated_children) {
+      terminated_children = 0;
+      pthread_reap_children();
+    }
+    /* Read and execute request */
+    if (n == 1 && (ufd.revents & POLLIN)) {
+      n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request,
+					     sizeof(request)));
+#ifdef DEBUG
+      if (n < 0) {
+	char d[64];
+	write(STDERR_FILENO, d, snprintf(d, sizeof(d), "*** read err %m\n"));
+      } else if (n != sizeof(request)) {
+	write(STDERR_FILENO, "*** short read in manager\n", 26);
+      }
+#endif
+
+      switch(request.req_kind) {
+      case REQ_CREATE:
+        request.req_thread->p_retcode =
+          pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
+                                request.req_args.create.attr,
+                                request.req_args.create.fn,
+                                request.req_args.create.arg,
+                                &request.req_args.create.mask,
+                                request.req_thread->p_pid,
+				request.req_thread->p_report_events,
+				&request.req_thread->p_eventbuf.eventmask);
+        restart(request.req_thread);
+        break;
+      case REQ_FREE:
+	pthread_handle_free(request.req_args.free.thread_id);
+        break;
+      case REQ_PROCESS_EXIT:
+        pthread_handle_exit(request.req_thread,
+                            request.req_args.exit.code);
+	/* NOTREACHED */
+        break;
+      case REQ_MAIN_THREAD_EXIT:
+        main_thread_exiting = 1;
+	/* Reap children in case all other threads died and the signal handler
+	   went off before we set main_thread_exiting to 1, and therefore did
+	   not do REQ_KICK. */
+	pthread_reap_children();
+
+        if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
+          restart(__pthread_main_thread);
+	  /* The main thread will now call exit() which will trigger an
+	     __on_exit handler, which in turn will send REQ_PROCESS_EXIT
+	     to the thread manager. In case you are wondering how the
+	     manager terminates from its loop here. */
+	}
+        break;
+      case REQ_POST:
+        __new_sem_post(request.req_args.post);
+        break;
+      case REQ_DEBUG:
+	/* Make gdb aware of new thread and gdb will restart the
+	   new thread when it is ready to handle the new thread. */
+	if (__pthread_threads_debug && __pthread_sig_debug > 0)
+	  raise(__pthread_sig_debug);
+        break;
+      case REQ_KICK:
+	/* This is just a prod to get the manager to reap some
+	   threads right away, avoiding a potential delay at shutdown. */
+	break;
+      case REQ_FOR_EACH_THREAD:
+	pthread_for_each_thread(request.req_args.for_each.arg,
+	                        request.req_args.for_each.fn);
+	restart(request.req_thread);
+	break;
+      }
+    }
+  }
+}
+
+int __pthread_manager_event(void *arg)
+{
+  pthread_descr self = arg;
+  /* If we have special thread_self processing, initialize it.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, 1);
+#endif
+
+  /* Get the lock the manager will free once all is correctly set up.  */
+  __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
+  /* Free it immediately.  */
+  __pthread_unlock (THREAD_GETMEM(self, p_lock));
+
+  return __pthread_manager(arg);
+}
+
+/* Process creation */
+
+static int
+__attribute__ ((noreturn))
+pthread_start_thread(void *arg)
+{
+  pthread_descr self = (pthread_descr) arg;
+  struct pthread_request request;
+  void * outcome;
+#if HP_TIMING_AVAIL
+  hp_timing_t tmpclock;
+#endif
+  /* Initialize special thread_self processing, if any.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, self->p_nr);
+#endif
+#if HP_TIMING_AVAIL
+  HP_TIMING_NOW (tmpclock);
+  THREAD_SETMEM (self, p_cpuclock_offset, tmpclock);
+#endif
+  /* Make sure our pid field is initialized, just in case we get there
+     before our father has initialized it. */
+  THREAD_SETMEM(self, p_pid, __getpid());
+  /* Initial signal mask is that of the creating thread. (Otherwise,
+     we'd just inherit the mask of the thread manager.) */
+  sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
+  /* Set the scheduling policy and priority for the new thread, if needed */
+  if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0)
+    /* Explicit scheduling attributes were provided: apply them */
+    __sched_setscheduler(THREAD_GETMEM(self, p_pid),
+			 THREAD_GETMEM(self, p_start_args.schedpolicy),
+                         &self->p_start_args.schedparam);
+  else if (manager_thread->p_priority > 0)
+    /* Default scheduling required, but thread manager runs in realtime
+       scheduling: switch new thread to SCHED_OTHER policy */
+    {
+      struct sched_param default_params;
+      default_params.sched_priority = 0;
+      __sched_setscheduler(THREAD_GETMEM(self, p_pid),
+                           SCHED_OTHER, &default_params);
+    }
+#if !(USE_TLS && HAVE___THREAD)
+  /* Initialize thread-locale current locale to point to the global one.
+     With __thread support, the variable's initializer takes care of this.  */
+  __uselocale (LC_GLOBAL_LOCALE);
+#else
+  /* Initialize __resp.  */
+  __resp = &self->p_res;
+#endif
+  /* Make gdb aware of new thread */
+  if (__pthread_threads_debug && __pthread_sig_debug > 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_DEBUG;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+    suspend(self);
+  }
+  /* Run the thread code */
+  outcome = self->p_start_args.start_routine(THREAD_GETMEM(self,
+							   p_start_args.arg));
+  /* Exit with the given return value */
+  __pthread_do_exit(outcome, CURRENT_STACK_FRAME);
+}
+
+static int
+__attribute__ ((noreturn))
+pthread_start_thread_event(void *arg)
+{
+  pthread_descr self = (pthread_descr) arg;
+
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, self->p_nr);
+#endif
+  /* Make sure our pid field is initialized, just in case we get there
+     before our father has initialized it. */
+  THREAD_SETMEM(self, p_pid, __getpid());
+  /* Get the lock the manager will free once all is correctly set up.  */
+  __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
+  /* Free it immediately.  */
+  __pthread_unlock (THREAD_GETMEM(self, p_lock));
+
+  /* Continue with the real function.  */
+  pthread_start_thread (arg);
+}
+
+#if defined USE_TLS && !FLOATING_STACKS
+# error "TLS can only work with floating stacks"
+#endif
+
+static int pthread_allocate_stack(const pthread_attr_t *attr,
+                                  pthread_descr default_new_thread,
+                                  int pagesize,
+                                  char ** out_new_thread,
+                                  char ** out_new_thread_bottom,
+                                  char ** out_guardaddr,
+                                  size_t * out_guardsize,
+                                  size_t * out_stacksize)
+{
+  pthread_descr new_thread;
+  char * new_thread_bottom;
+  char * guardaddr;
+  size_t stacksize, guardsize;
+
+#ifdef USE_TLS
+  /* TLS cannot work with fixed thread descriptor addresses.  */
+  assert (default_new_thread == NULL);
+#endif
+
+  if (attr != NULL && attr->__stackaddr_set)
+    {
+#ifdef _STACK_GROWS_UP
+      /* The user provided a stack. */
+# ifdef USE_TLS
+      /* This value is not needed.  */
+      new_thread = (pthread_descr) attr->__stackaddr;
+      new_thread_bottom = (char *) new_thread;
+# else
+      new_thread = (pthread_descr) attr->__stackaddr;
+      new_thread_bottom = (char *) (new_thread + 1);
+# endif
+      guardaddr = attr->__stackaddr + attr->__stacksize;
+      guardsize = 0;
+#else
+      /* The user provided a stack.  For now we interpret the supplied
+	 address as 1 + the highest addr. in the stack segment.  If a
+	 separate register stack is needed, we place it at the low end
+	 of the segment, relying on the associated stacksize to
+	 determine the low end of the segment.  This differs from many
+	 (but not all) other pthreads implementations.  The intent is
+	 that on machines with a single stack growing toward higher
+	 addresses, stackaddr would be the lowest address in the stack
+	 segment, so that it is consistently close to the initial sp
+	 value. */
+# ifdef USE_TLS
+      new_thread = (pthread_descr) attr->__stackaddr;
+# else
+      new_thread =
+        (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
+# endif
+      new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
+      guardaddr = new_thread_bottom;
+      guardsize = 0;
+#endif
+#ifndef THREAD_SELF
+      __pthread_nonstandard_stacks = 1;
+#endif
+#ifndef USE_TLS
+      /* Clear the thread data structure.  */
+      memset (new_thread, '\0', sizeof (*new_thread));
+#endif
+      stacksize = attr->__stacksize;
+    }
+  else
+    {
+#ifdef NEED_SEPARATE_REGISTER_STACK
+      const size_t granularity = 2 * pagesize;
+      /* Try to make stacksize/2 a multiple of pagesize */
+#else
+      const size_t granularity = pagesize;
+#endif
+      void *map_addr;
+
+      /* Allocate space for stack and thread descriptor at default address */
+#if FLOATING_STACKS
+      if (attr != NULL)
+	{
+	  guardsize = page_roundup (attr->__guardsize, granularity);
+	  stacksize = __pthread_max_stacksize - guardsize;
+	  stacksize = MIN (stacksize,
+			   page_roundup (attr->__stacksize, granularity));
+	}
+      else
+	{
+	  guardsize = granularity;
+	  stacksize = __pthread_max_stacksize - guardsize;
+	}
+
+      map_addr = mmap(NULL, stacksize + guardsize,
+		      PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (map_addr == MAP_FAILED)
+        /* No more memory available.  */
+        return -1;
+
+# ifdef NEED_SEPARATE_REGISTER_STACK
+      guardaddr = map_addr + stacksize / 2;
+      if (guardsize > 0)
+	mprotect (guardaddr, guardsize, PROT_NONE);
+
+      new_thread_bottom = (char *) map_addr;
+#  ifdef USE_TLS
+      new_thread = ((pthread_descr) (new_thread_bottom + stacksize
+				     + guardsize));
+#  else
+      new_thread = ((pthread_descr) (new_thread_bottom + stacksize
+				     + guardsize)) - 1;
+#  endif
+# elif _STACK_GROWS_DOWN
+      guardaddr = map_addr;
+      if (guardsize > 0)
+	mprotect (guardaddr, guardsize, PROT_NONE);
+
+      new_thread_bottom = (char *) map_addr + guardsize;
+#  ifdef USE_TLS
+      new_thread = ((pthread_descr) (new_thread_bottom + stacksize));
+#  else
+      new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;
+#  endif
+# elif _STACK_GROWS_UP
+      guardaddr = map_addr + stacksize;
+      if (guardsize > 0)
+	mprotect (guardaddr, guardsize, PROT_NONE);
+
+      new_thread = (pthread_descr) map_addr;
+#  ifdef USE_TLS
+      new_thread_bottom = (char *) new_thread;
+#  else
+      new_thread_bottom = (char *) (new_thread + 1);
+#  endif
+# else
+#  error You must define a stack direction
+# endif /* Stack direction */
+#else /* !FLOATING_STACKS */
+      void *res_addr;
+
+      if (attr != NULL)
+	{
+	  guardsize = page_roundup (attr->__guardsize, granularity);
+	  stacksize = STACK_SIZE - guardsize;
+	  stacksize = MIN (stacksize,
+			   page_roundup (attr->__stacksize, granularity));
+	}
+      else
+	{
+	  guardsize = granularity;
+	  stacksize = STACK_SIZE - granularity;
+	}
+
+# ifdef NEED_SEPARATE_REGISTER_STACK
+      new_thread = default_new_thread;
+      new_thread_bottom = (char *) (new_thread + 1) - stacksize - guardsize;
+      /* Includes guard area, unlike the normal case.  Use the bottom
+       end of the segment as backing store for the register stack.
+       Needed on IA64.  In this case, we also map the entire stack at
+       once.  According to David Mosberger, that's cheaper.  It also
+       avoids the risk of intermittent failures due to other mappings
+       in the same region.  The cost is that we might be able to map
+       slightly fewer stacks.  */
+
+      /* First the main stack: */
+      map_addr = (caddr_t)((char *)(new_thread + 1) - stacksize / 2);
+      res_addr = mmap(map_addr, stacksize / 2,
+		      PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (res_addr != map_addr)
+	{
+	  /* Bad luck, this segment is already mapped. */
+	  if (res_addr != MAP_FAILED)
+	    munmap(res_addr, stacksize / 2);
+	  return -1;
+	}
+      /* Then the register stack:	*/
+      map_addr = (caddr_t)new_thread_bottom;
+      res_addr = mmap(map_addr, stacksize/2,
+		      PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (res_addr != map_addr)
+	{
+	  if (res_addr != MAP_FAILED)
+	    munmap(res_addr, stacksize / 2);
+	  munmap((caddr_t)((char *)(new_thread + 1) - stacksize/2),
+		 stacksize/2);
+	  return -1;
+	}
+
+      guardaddr = new_thread_bottom + stacksize/2;
+      /* We leave the guard area in the middle unmapped.	*/
+# else  /* !NEED_SEPARATE_REGISTER_STACK */
+#  ifdef _STACK_GROWS_DOWN
+      new_thread = default_new_thread;
+      new_thread_bottom = (char *) (new_thread + 1) - stacksize;
+      map_addr = new_thread_bottom - guardsize;
+      res_addr = mmap(map_addr, stacksize + guardsize,
+		      PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (res_addr != map_addr)
+	{
+	  /* Bad luck, this segment is already mapped. */
+	  if (res_addr != MAP_FAILED)
+	    munmap (res_addr, stacksize + guardsize);
+	  return -1;
+	}
+
+      /* We manage to get a stack.  Protect the guard area pages if
+	 necessary.  */
+      guardaddr = map_addr;
+      if (guardsize > 0)
+	mprotect (guardaddr, guardsize, PROT_NONE);
+#  else
+      /* The thread description goes at the bottom of this area, and
+       * the stack starts directly above it.
+       */
+      new_thread = (pthread_descr)((unsigned long)default_new_thread &~ (STACK_SIZE - 1));
+      map_addr = mmap(new_thread, stacksize + guardsize,
+		      PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (map_addr == MAP_FAILED)
+	  return -1;
+
+      new_thread_bottom = map_addr + sizeof(*new_thread);
+      guardaddr = map_addr + stacksize;
+      if (guardsize > 0)
+	  mprotect (guardaddr, guardsize, PROT_NONE);
+
+#  endif /* stack direction */
+# endif  /* !NEED_SEPARATE_REGISTER_STACK */
+#endif   /* !FLOATING_STACKS */
+    }
+  *out_new_thread = (char *) new_thread;
+  *out_new_thread_bottom = new_thread_bottom;
+  *out_guardaddr = guardaddr;
+  *out_guardsize = guardsize;
+#ifdef NEED_SEPARATE_REGISTER_STACK
+  *out_stacksize = stacksize / 2;
+#else
+  *out_stacksize = stacksize;
+#endif
+  return 0;
+}
+
+static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
+				 void * (*start_routine)(void *), void *arg,
+				 sigset_t * mask, int father_pid,
+				 int report_events,
+				 td_thr_events_t *event_maskp)
+{
+  size_t sseg;
+  int pid;
+  pthread_descr new_thread;
+  char *stack_addr;
+  char * new_thread_bottom;
+  pthread_t new_thread_id;
+  char *guardaddr = NULL;
+  size_t guardsize = 0, stksize = 0;
+  int pagesize = __getpagesize();
+  int saved_errno = 0;
+
+#ifdef USE_TLS
+  new_thread = _dl_allocate_tls (NULL);
+  if (new_thread == NULL)
+    return EAGAIN;
+# if TLS_DTV_AT_TP
+  /* pthread_descr is below TP.  */
+  new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE);
+# endif
+#else
+  /* Prevent warnings.  */
+  new_thread = NULL;
+#endif
+
+  /* First check whether we have to change the policy and if yes, whether
+     we can  do this.  Normally this should be done by examining the
+     return value of the __sched_setscheduler call in pthread_start_thread
+     but this is hard to implement.  FIXME  */
+  if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
+    return EPERM;
+  /* Find a free segment for the thread, and allocate a stack if needed */
+  for (sseg = 2; ; sseg++)
+    {
+      if (sseg >= PTHREAD_THREADS_MAX)
+	{
+#ifdef USE_TLS
+# if TLS_DTV_AT_TP
+	  new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
+# endif
+	  _dl_deallocate_tls (new_thread, true);
+#endif
+	  return EAGAIN;
+	}
+      if (__pthread_handles[sseg].h_descr != NULL)
+	continue;
+      if (pthread_allocate_stack(attr, thread_segment(sseg),
+				 pagesize, &stack_addr, &new_thread_bottom,
+                                 &guardaddr, &guardsize, &stksize) == 0)
+	{
+#ifdef USE_TLS
+	  new_thread->p_stackaddr = stack_addr;
+#else
+	  new_thread = (pthread_descr) stack_addr;
+#endif
+	  break;
+	}
+    }
+  __pthread_handles_num++;
+  /* Allocate new thread identifier */
+  pthread_threads_counter += PTHREAD_THREADS_MAX;
+  new_thread_id = sseg + pthread_threads_counter;
+  /* Initialize the thread descriptor.  Elements which have to be
+     initialized to zero already have this value.  */
+#if !defined USE_TLS || !TLS_DTV_AT_TP
+  new_thread->p_header.data.tcb = new_thread;
+  new_thread->p_header.data.self = new_thread;
+#endif
+#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
+  new_thread->p_multiple_threads = 1;
+#endif
+  new_thread->p_tid = new_thread_id;
+  new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
+  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
+  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
+#if !(USE_TLS && HAVE___THREAD)
+  new_thread->p_errnop = &new_thread->p_errno;
+  new_thread->p_h_errnop = &new_thread->p_h_errno;
+  new_thread->p_resp = &new_thread->p_res;
+#endif
+  new_thread->p_guardaddr = guardaddr;
+  new_thread->p_guardsize = guardsize;
+  new_thread->p_nr = sseg;
+  new_thread->p_inheritsched = attr ? attr->__inheritsched : 0;
+  new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF
+				 ? __MAX_ALLOCA_CUTOFF : stksize / 4;
+  /* Initialize the thread handle */
+  __pthread_init_lock(&__pthread_handles[sseg].h_lock);
+  __pthread_handles[sseg].h_descr = new_thread;
+  __pthread_handles[sseg].h_bottom = new_thread_bottom;
+  /* Determine scheduling parameters for the thread */
+  new_thread->p_start_args.schedpolicy = -1;
+  if (attr != NULL) {
+    new_thread->p_detached = attr->__detachstate;
+    new_thread->p_userstack = attr->__stackaddr_set;
+
+    switch(attr->__inheritsched) {
+    case PTHREAD_EXPLICIT_SCHED:
+      new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
+      memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
+	      sizeof (struct sched_param));
+      break;
+    case PTHREAD_INHERIT_SCHED:
+      new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
+      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
+      break;
+    }
+    new_thread->p_priority =
+      new_thread->p_start_args.schedparam.sched_priority;
+  }
+  /* Finish setting up arguments to pthread_start_thread */
+  new_thread->p_start_args.start_routine = start_routine;
+  new_thread->p_start_args.arg = arg;
+  new_thread->p_start_args.mask = *mask;
+  /* Make the new thread ID available already now.  If any of the later
+     functions fail we return an error value and the caller must not use
+     the stored thread ID.  */
+  *thread = new_thread_id;
+  /* Raise priority of thread manager if needed */
+  __pthread_manager_adjust_prio(new_thread->p_priority);
+  /* Do the cloning.  We have to use two different functions depending
+     on whether we are debugging or not.  */
+  pid = 0;	/* Note that the thread never can have PID zero.  */
+  if (report_events)
+    {
+      /* See whether the TD_CREATE event bit is set in any of the
+         masks.  */
+      int idx = __td_eventword (TD_CREATE);
+      uint32_t mask = __td_eventmask (TD_CREATE);
+
+      if ((mask & (__pthread_threads_events.event_bits[idx]
+		   | event_maskp->event_bits[idx])) != 0)
+	{
+	  /* Lock the mutex the child will use now so that it will stop.  */
+	  __pthread_lock(new_thread->p_lock, NULL);
+
+	  /* We have to report this event.  */
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	  /* Perhaps this version should be used on all platforms. But
+	   this requires that __clone2 be uniformly supported
+	   everywhere.
+
+	   And there is some argument for changing the __clone2
+	   interface to pass sp and bsp instead, making it more IA64
+	   specific, but allowing stacks to grow outward from each
+	   other, to get less paging and fewer mmaps.  */
+	  pid = __clone2(pthread_start_thread_event,
+  		 (void **)new_thread_bottom,
+			 (char *)stack_addr - new_thread_bottom,
+			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			 __pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			__pthread_sig_cancel, new_thread);
+#else
+	  pid = __clone(pthread_start_thread_event, stack_addr,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			__pthread_sig_cancel, new_thread);
+#endif
+	  saved_errno = errno;
+	  if (pid != -1)
+	    {
+	      /* 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.  */
+	      new_thread->p_eventbuf.eventdata = new_thread;
+	      new_thread->p_eventbuf.eventnum = TD_CREATE;
+	      __pthread_last_event = new_thread;
+
+	      /* We have to set the PID here since the callback function
+		 in the debug library will need it and we cannot guarantee
+		 the child got scheduled before the debugger.  */
+	      new_thread->p_pid = pid;
+
+	      /* Now call the function which signals the event.  */
+	      __linuxthreads_create_event ();
+
+	      /* Now restart the thread.  */
+	      __pthread_unlock(new_thread->p_lock);
+	    }
+	}
+    }
+  if (pid == 0)
+    {
+#ifdef NEED_SEPARATE_REGISTER_STACK
+      pid = __clone2(pthread_start_thread,
+		     (void **)new_thread_bottom,
+                     (char *)stack_addr - new_thread_bottom,
+		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		     __pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+      pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    __pthread_sig_cancel, new_thread);
+#else
+      pid = __clone(pthread_start_thread, stack_addr,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    __pthread_sig_cancel, new_thread);
+#endif /* !NEED_SEPARATE_REGISTER_STACK */
+      saved_errno = errno;
+    }
+  /* Check if cloning succeeded */
+  if (pid == -1) {
+    /* Free the stack if we allocated it */
+    if (attr == NULL || !attr->__stackaddr_set)
+      {
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	size_t stacksize = ((char *)(new_thread->p_guardaddr)
+			    - new_thread_bottom);
+	munmap((caddr_t)new_thread_bottom,
+	       2 * stacksize + new_thread->p_guardsize);
+#elif _STACK_GROWS_UP
+# ifdef USE_TLS
+	size_t stacksize = guardaddr - stack_addr;
+	munmap(stack_addr, stacksize + guardsize);
+# else
+	size_t stacksize = guardaddr - (char *)new_thread;
+	munmap(new_thread, stacksize + guardsize);
+# endif
+#else
+# ifdef USE_TLS
+	size_t stacksize = stack_addr - new_thread_bottom;
+# else
+	size_t stacksize = (char *)(new_thread+1) - new_thread_bottom;
+# endif
+	munmap(new_thread_bottom - guardsize, guardsize + stacksize);
+#endif
+      }
+#ifdef USE_TLS
+# if TLS_DTV_AT_TP
+    new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
+# endif
+    _dl_deallocate_tls (new_thread, true);
+#endif
+    __pthread_handles[sseg].h_descr = NULL;
+    __pthread_handles[sseg].h_bottom = NULL;
+    __pthread_handles_num--;
+    return saved_errno;
+  }
+  /* Insert new thread in doubly linked list of active threads */
+  new_thread->p_prevlive = __pthread_main_thread;
+  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
+  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
+  __pthread_main_thread->p_nextlive = new_thread;
+  /* Set pid field of the new thread, in case we get there before the
+     child starts. */
+  new_thread->p_pid = pid;
+  return 0;
+}
+
+
+/* Try to free the resources of a thread when requested by pthread_join
+   or pthread_detach on a terminated thread. */
+
+static void pthread_free(pthread_descr th)
+{
+  pthread_handle handle;
+  pthread_readlock_info *iter, *next;
+
+  ASSERT(th->p_exited);
+  /* Make the handle invalid */
+  handle =  thread_handle(th->p_tid);
+  __pthread_lock(&handle->h_lock, NULL);
+  handle->h_descr = NULL;
+  handle->h_bottom = (char *)(-1L);
+  __pthread_unlock(&handle->h_lock);
+#ifdef FREE_THREAD
+  FREE_THREAD(th, th->p_nr);
+#endif
+  /* One fewer threads in __pthread_handles */
+  __pthread_handles_num--;
+
+  /* Destroy read lock list, and list of free read lock structures.
+     If the former is not empty, it means the thread exited while
+     holding read locks! */
+
+  for (iter = th->p_readlock_list; iter != NULL; iter = next)
+    {
+      next = iter->pr_next;
+      free(iter);
+    }
+
+  for (iter = th->p_readlock_free; iter != NULL; iter = next)
+    {
+      next = iter->pr_next;
+      free(iter);
+    }
+
+  /* If initial thread, nothing to free */
+  if (!th->p_userstack)
+    {
+      size_t guardsize = th->p_guardsize;
+      /* Free the stack and thread descriptor area */
+      char *guardaddr = th->p_guardaddr;
+#ifdef _STACK_GROWS_UP
+# ifdef USE_TLS
+      size_t stacksize = guardaddr - th->p_stackaddr;
+# else
+      size_t stacksize = guardaddr - (char *)th;
+# endif
+      guardaddr = (char *)th;
+#else
+      /* Guardaddr is always set, even if guardsize is 0.  This allows
+	 us to compute everything else.  */
+# ifdef USE_TLS
+      size_t stacksize = th->p_stackaddr - guardaddr - guardsize;
+# else
+      size_t stacksize = (char *)(th+1) - guardaddr - guardsize;
+# endif
+# ifdef NEED_SEPARATE_REGISTER_STACK
+      /* Take account of the register stack, which is below guardaddr.  */
+      guardaddr -= stacksize;
+      stacksize *= 2;
+# endif
+#endif
+      /* Unmap the stack.  */
+      munmap(guardaddr, stacksize + guardsize);
+
+    }
+
+#ifdef USE_TLS
+# if TLS_DTV_AT_TP
+  th = (pthread_descr) ((char *) th + TLS_PRE_TCB_SIZE);
+# endif
+  _dl_deallocate_tls (th, true);
+#endif
+}
+
+/* Handle threads that have exited */
+
+static void pthread_exited(pid_t pid)
+{
+  pthread_descr th;
+  int detached;
+  /* Find thread with that pid */
+  for (th = __pthread_main_thread->p_nextlive;
+       th != __pthread_main_thread;
+       th = th->p_nextlive) {
+    if (th->p_pid == pid) {
+      /* Remove thread from list of active threads */
+      th->p_nextlive->p_prevlive = th->p_prevlive;
+      th->p_prevlive->p_nextlive = th->p_nextlive;
+      /* Mark thread as exited, and if detached, free its resources */
+      __pthread_lock(th->p_lock, NULL);
+      th->p_exited = 1;
+      /* If we have to signal this event do it now.  */
+      if (th->p_report_events)
+	{
+	  /* See whether TD_REAP is in any of the mask.  */
+	  int idx = __td_eventword (TD_REAP);
+	  uint32_t mask = __td_eventmask (TD_REAP);
+
+	  if ((mask & (__pthread_threads_events.event_bits[idx]
+		       | th->p_eventbuf.eventmask.event_bits[idx])) != 0)
+	    {
+	      /* Yep, we have to signal the reapage.  */
+	      th->p_eventbuf.eventnum = TD_REAP;
+	      th->p_eventbuf.eventdata = th;
+	      __pthread_last_event = th;
+
+	      /* Now call the function to signal the event.  */
+	      __linuxthreads_reap_event();
+	    }
+	}
+      detached = th->p_detached;
+      __pthread_unlock(th->p_lock);
+      if (detached)
+	pthread_free(th);
+      break;
+    }
+  }
+  /* If all threads have exited and the main thread is pending on a
+     pthread_exit, wake up the main thread and terminate ourselves. */
+  if (main_thread_exiting &&
+      __pthread_main_thread->p_nextlive == __pthread_main_thread) {
+    restart(__pthread_main_thread);
+    /* Same logic as REQ_MAIN_THREAD_EXIT. */
+  }
+}
+
+static void pthread_reap_children(void)
+{
+  pid_t pid;
+  int status;
+
+  while ((pid = waitpid_not_cancel(-1, &status, WNOHANG | __WCLONE)) > 0) {
+    pthread_exited(pid);
+    if (WIFSIGNALED(status)) {
+      /* If a thread died due to a signal, send the same signal to
+         all other threads, including the main thread. */
+      pthread_kill_all_threads(WTERMSIG(status), 1);
+      _exit(0);
+    }
+  }
+}
+
+/* Try to free the resources of a thread when requested by pthread_join
+   or pthread_detach on a terminated thread. */
+
+static void pthread_handle_free(pthread_t th_id)
+{
+  pthread_handle handle = thread_handle(th_id);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (nonexisting_handle(handle, th_id)) {
+    /* pthread_reap_children has deallocated the thread already,
+       nothing needs to be done */
+    __pthread_unlock(&handle->h_lock);
+    return;
+  }
+  th = handle->h_descr;
+  if (th->p_exited) {
+    __pthread_unlock(&handle->h_lock);
+    pthread_free(th);
+  } else {
+    /* The Unix process of the thread is still running.
+       Mark the thread as detached so that the thread manager will
+       deallocate its resources when the Unix process exits. */
+    th->p_detached = 1;
+    __pthread_unlock(&handle->h_lock);
+  }
+}
+
+/* Send a signal to all running threads */
+
+static void pthread_kill_all_threads(int sig, int main_thread_also)
+{
+  pthread_descr th;
+  for (th = __pthread_main_thread->p_nextlive;
+       th != __pthread_main_thread;
+       th = th->p_nextlive) {
+    kill(th->p_pid, sig);
+  }
+  if (main_thread_also) {
+    kill(__pthread_main_thread->p_pid, sig);
+  }
+}
+
+static void pthread_for_each_thread(void *arg,
+    void (*fn)(void *, pthread_descr))
+{
+  pthread_descr th;
+
+  for (th = __pthread_main_thread->p_nextlive;
+       th != __pthread_main_thread;
+       th = th->p_nextlive) {
+    fn(arg, th);
+  }
+
+  fn(arg, __pthread_main_thread);
+}
+
+/* Process-wide exit() */
+
+static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
+{
+  pthread_descr th;
+  __pthread_exit_requested = 1;
+  __pthread_exit_code = exitcode;
+  /* A forced asynchronous cancellation follows.  Make sure we won't
+     get stuck later in the main thread with a system lock being held
+     by one of the cancelled threads.  Ideally one would use the same
+     code as in pthread_atfork(), but we can't distinguish system and
+     user handlers there.  */
+  __flockfilelist();
+  /* Send the CANCEL signal to all running threads, including the main
+     thread, but excluding the thread from which the exit request originated
+     (that thread must complete the exit, e.g. calling atexit functions
+     and flushing stdio buffers). */
+  for (th = issuing_thread->p_nextlive;
+       th != issuing_thread;
+       th = th->p_nextlive) {
+    kill(th->p_pid, __pthread_sig_cancel);
+  }
+  /* Now, wait for all these threads, so that they don't become zombies
+     and their times are properly added to the thread manager's times. */
+  for (th = issuing_thread->p_nextlive;
+       th != issuing_thread;
+       th = th->p_nextlive) {
+    waitpid(th->p_pid, NULL, __WCLONE);
+  }
+  __fresetlockfiles();
+  restart(issuing_thread);
+  _exit(0);
+}
+
+/* Handler for __pthread_sig_cancel in thread manager thread */
+
+void __pthread_manager_sighandler(int sig)
+{
+  int kick_manager = terminated_children == 0 && main_thread_exiting;
+  terminated_children = 1;
+
+  /* If the main thread is terminating, kick the thread manager loop
+     each time some threads terminate. This eliminates a two second
+     shutdown delay caused by the thread manager sleeping in the
+     call to __poll(). Instead, the thread manager is kicked into
+     action, reaps the outstanding threads and resumes the main thread
+     so that it can complete the shutdown. */
+
+  if (kick_manager) {
+    struct pthread_request request;
+    request.req_thread = 0;
+    request.req_kind = REQ_KICK;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+  }
+}
+
+/* Adjust priority of thread manager so that it always run at a priority
+   higher than all threads */
+
+void __pthread_manager_adjust_prio(int thread_prio)
+{
+  struct sched_param param;
+
+  if (thread_prio <= manager_thread->p_priority) return;
+  param.sched_priority =
+    thread_prio < __sched_get_priority_max(SCHED_FIFO)
+    ? thread_prio + 1 : thread_prio;
+  __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
+  manager_thread->p_priority = thread_prio;
+}
diff --git a/linuxthreads/mutex.c b/linuxthreads/mutex.c
new file mode 100644
index 0000000000..d5f7a335cc
--- /dev/null
+++ b/linuxthreads/mutex.c
@@ -0,0 +1,362 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Mutexes */
+
+#include <bits/libc-lock.h>
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <limits.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "queue.h"
+#include "restart.h"
+
+int __pthread_mutex_init(pthread_mutex_t * mutex,
+                       const pthread_mutexattr_t * mutex_attr)
+{
+  __pthread_init_lock(&mutex->__m_lock);
+  mutex->__m_kind =
+    mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind;
+  mutex->__m_count = 0;
+  mutex->__m_owner = NULL;
+  return 0;
+}
+strong_alias (__pthread_mutex_init, pthread_mutex_init)
+hidden_def (__pthread_mutex_init)
+
+int __pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+  switch (mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    if ((mutex->__m_lock.__status & 1) != 0)
+      return EBUSY;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+  case PTHREAD_MUTEX_TIMED_NP:
+    if (mutex->__m_lock.__status != 0)
+      return EBUSY;
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
+hidden_def (__pthread_mutex_destroy)
+
+int __pthread_mutex_trylock(pthread_mutex_t * mutex)
+{
+  pthread_descr self;
+  int retcode;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    retcode = __pthread_trylock(&mutex->__m_lock);
+    return retcode;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    retcode = __pthread_trylock(&mutex->__m_lock);
+    if (retcode == 0) {
+      mutex->__m_owner = self;
+      mutex->__m_count = 0;
+    }
+    return retcode;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    retcode = __pthread_alt_trylock(&mutex->__m_lock);
+    if (retcode == 0) {
+      mutex->__m_owner = thread_self();
+    }
+    return retcode;
+  case PTHREAD_MUTEX_TIMED_NP:
+    retcode = __pthread_alt_trylock(&mutex->__m_lock);
+    return retcode;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
+hidden_def (__pthread_mutex_trylock)
+
+int __pthread_mutex_lock(pthread_mutex_t * mutex)
+{
+  pthread_descr self;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_lock(&mutex->__m_lock, NULL);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    __pthread_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    mutex->__m_count = 0;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) return EDEADLK;
+    __pthread_alt_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    return 0;
+  case PTHREAD_MUTEX_TIMED_NP:
+    __pthread_alt_lock(&mutex->__m_lock, NULL);
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
+hidden_def (__pthread_mutex_lock)
+
+int __pthread_mutex_timedlock (pthread_mutex_t *mutex,
+			       const struct timespec *abstime)
+{
+  pthread_descr self;
+  int res;
+
+  if (__builtin_expect (abstime->tv_nsec, 0) < 0
+      || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000)
+    return EINVAL;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_lock(&mutex->__m_lock, NULL);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    __pthread_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    mutex->__m_count = 0;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) return EDEADLK;
+    res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime);
+    if (res != 0)
+      {
+	mutex->__m_owner = self;
+	return 0;
+      }
+    return ETIMEDOUT;
+  case PTHREAD_MUTEX_TIMED_NP:
+    /* Only this type supports timed out lock. */
+    return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime)
+	    ? 0 : ETIMEDOUT);
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
+
+int __pthread_mutex_unlock(pthread_mutex_t * mutex)
+{
+  switch (mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    if (mutex->__m_owner != thread_self())
+      return EPERM;
+    if (mutex->__m_count > 0) {
+      mutex->__m_count--;
+      return 0;
+    }
+    mutex->__m_owner = NULL;
+    __pthread_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0)
+      return EPERM;
+    mutex->__m_owner = NULL;
+    __pthread_alt_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_TIMED_NP:
+    __pthread_alt_unlock(&mutex->__m_lock);
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
+hidden_def (__pthread_mutex_unlock)
+
+int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+  attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP;
+  return 0;
+}
+strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init)
+
+int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+{
+  return 0;
+}
+strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
+
+int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
+{
+  if (kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && kind != PTHREAD_MUTEX_RECURSIVE_NP
+      && kind != PTHREAD_MUTEX_ERRORCHECK_NP
+      && kind != PTHREAD_MUTEX_TIMED_NP)
+    return EINVAL;
+  attr->__mutexkind = kind;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype)
+strong_alias ( __pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
+weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
+
+int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
+{
+  *kind = attr->__mutexkind;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype)
+strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np)
+weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
+
+int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
+				   int *pshared)
+{
+  *pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared)
+
+int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  return 0;
+}
+weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared)
+
+/* Once-only execution */
+
+static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER;
+static int fork_generation = 0;	/* Child process increments this after fork. */
+
+enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };
+
+/* If a thread is canceled while calling the init_routine out of
+   pthread once, this handler will reset the once_control variable
+   to the NEVER state. */
+
+static void pthread_once_cancelhandler(void *arg)
+{
+    pthread_once_t *once_control = arg;
+
+    pthread_mutex_lock(&once_masterlock);
+    *once_control = NEVER;
+    pthread_mutex_unlock(&once_masterlock);
+    pthread_cond_broadcast(&once_finished);
+}
+
+int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
+{
+  /* flag for doing the condition broadcast outside of mutex */
+  int state_changed;
+
+  /* Test without locking first for speed */
+  if (*once_control == DONE) {
+    READ_MEMORY_BARRIER();
+    return 0;
+  }
+  /* Lock and test again */
+
+  state_changed = 0;
+
+  pthread_mutex_lock(&once_masterlock);
+
+  /* If this object was left in an IN_PROGRESS state in a parent
+     process (indicated by stale generation field), reset it to NEVER. */
+  if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
+    *once_control = NEVER;
+
+  /* If init_routine is being called from another routine, wait until
+     it completes. */
+  while ((*once_control & 3) == IN_PROGRESS) {
+    pthread_cond_wait(&once_finished, &once_masterlock);
+  }
+  /* Here *once_control is stable and either NEVER or DONE. */
+  if (*once_control == NEVER) {
+    *once_control = IN_PROGRESS | fork_generation;
+    pthread_mutex_unlock(&once_masterlock);
+    pthread_cleanup_push(pthread_once_cancelhandler, once_control);
+    init_routine();
+    pthread_cleanup_pop(0);
+    pthread_mutex_lock(&once_masterlock);
+    WRITE_MEMORY_BARRIER();
+    *once_control = DONE;
+    state_changed = 1;
+  }
+  pthread_mutex_unlock(&once_masterlock);
+
+  if (state_changed)
+    pthread_cond_broadcast(&once_finished);
+
+  return 0;
+}
+strong_alias (__pthread_once, pthread_once)
+
+/*
+ * Handle the state of the pthread_once mechanism across forks.  The
+ * once_masterlock is acquired in the parent process prior to a fork to ensure
+ * that no thread is in the critical region protected by the lock.  After the
+ * fork, the lock is released. In the child, the lock and the condition
+ * variable are simply reset.  The child also increments its generation
+ * counter which lets pthread_once calls detect stale IN_PROGRESS states
+ * and reset them back to NEVER.
+ */
+
+void __pthread_once_fork_prepare(void)
+{
+  pthread_mutex_lock(&once_masterlock);
+}
+
+void __pthread_once_fork_parent(void)
+{
+  pthread_mutex_unlock(&once_masterlock);
+}
+
+void __pthread_once_fork_child(void)
+{
+  pthread_mutex_init(&once_masterlock, NULL);
+  pthread_cond_init(&once_finished, NULL);
+  if (fork_generation <= INT_MAX - 4)
+    fork_generation += 4;	/* leave least significant two bits zero */
+  else
+    fork_generation = 0;
+}
diff --git a/linuxthreads/old_pthread_atfork.c b/linuxthreads/old_pthread_atfork.c
new file mode 100644
index 0000000000..768e6876c4
--- /dev/null
+++ b/linuxthreads/old_pthread_atfork.c
@@ -0,0 +1,27 @@
+/* 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 <shlib-compat.h>
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3)
+# define __pthread_atfork __dyn_pthread_atfork
+# include "pthread_atfork.c"
+# undef __pthread_atfork
+compat_symbol (libpthread, __dyn_pthread_atfork, pthread_atfork, GLIBC_2_0);
+#endif
diff --git a/linuxthreads/oldsemaphore.c b/linuxthreads/oldsemaphore.c
new file mode 100644
index 0000000000..d35683b98b
--- /dev/null
+++ b/linuxthreads/oldsemaphore.c
@@ -0,0 +1,241 @@
+/*
+ * This file contains the old semaphore code that we need to
+ * preserve for glibc-2.0 backwards compatibility. Port to glibc 2.1
+ * done by Cristian Gafton.
+ */
+
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Semaphores a la POSIX 1003.1b */
+#include <shlib-compat.h>
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "queue.h"
+
+typedef struct {
+    long int sem_status;
+    int sem_spinlock;
+} old_sem_t;
+
+extern int __old_sem_init (old_sem_t *__sem, int __pshared, unsigned int __value);
+extern int __old_sem_wait (old_sem_t *__sem);
+extern int __old_sem_trywait (old_sem_t *__sem);
+extern int __old_sem_post (old_sem_t *__sem);
+extern int __old_sem_getvalue (old_sem_t *__sem, int *__sval);
+extern int __old_sem_destroy (old_sem_t *__sem);
+
+static inline int sem_compare_and_swap(old_sem_t *sem, long oldval, long newval)
+{
+    return compare_and_swap(&sem->sem_status, oldval, newval, &sem->sem_spinlock);
+}
+
+/* The state of a semaphore is represented by a long int encoding
+   either the semaphore count if >= 0 and no thread is waiting on it,
+   or the head of the list of threads waiting for the semaphore.
+   To distinguish the two cases, we encode the semaphore count N
+   as 2N+1, so that it has the lowest bit set.
+
+   A sequence of sem_wait operations on a semaphore initialized to N
+   result in the following successive states:
+     2N+1, 2N-1, ..., 3, 1, &first_waiting_thread, &second_waiting_thread, ...
+*/
+
+static void sem_restart_list(pthread_descr waiting);
+
+int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value)
+{
+    if (value > SEM_VALUE_MAX) {
+	errno = EINVAL;
+	return -1;
+    }
+    if (pshared) {
+	errno = ENOSYS;
+	return -1;
+    }
+  sem->sem_spinlock = __LT_SPINLOCK_INIT;
+  sem->sem_status = ((long)value << 1) + 1;
+  return 0;
+}
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting inside __old_sem_wait. Here we simply unconditionally
+   indicate that the thread is to be woken, by returning 1. */
+
+static int old_sem_extricate_func(void *obj, pthread_descr th)
+{
+    return 1;
+}
+
+int __old_sem_wait(old_sem_t * sem)
+{
+    long oldstatus, newstatus;
+    volatile pthread_descr self = thread_self();
+    pthread_descr * th;
+    pthread_extricate_if extr;
+
+    /* Set up extrication interface */
+    extr.pu_object = 0;
+    extr.pu_extricate_func = old_sem_extricate_func;
+
+    while (1) {
+	/* Register extrication interface */
+	__pthread_set_own_extricate_if(self, &extr);
+	do {
+            oldstatus = sem->sem_status;
+            if ((oldstatus & 1) && (oldstatus != 1))
+		newstatus = oldstatus - 2;
+            else {
+		newstatus = (long) self;
+		self->p_nextwaiting = (pthread_descr) oldstatus;
+	    }
+	}
+	while (! sem_compare_and_swap(sem, oldstatus, newstatus));
+	if (newstatus & 1) {
+	    /* We got the semaphore. */
+	    __pthread_set_own_extricate_if(self, 0);
+	    self->p_nextwaiting = NULL;
+	    return 0;
+	}
+	/* Wait for sem_post or cancellation */
+	suspend(self);
+	__pthread_set_own_extricate_if(self, 0);
+
+	/* This is a cancellation point */
+	if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
+	    /* Remove ourselves from the waiting list if we're still on it */
+	    /* First check if we're at the head of the list. */
+            do {
+		oldstatus = sem->sem_status;
+		if (oldstatus != (long) self) break;
+		newstatus = (long) self->p_nextwaiting;
+	    }
+            while (! sem_compare_and_swap(sem, oldstatus, newstatus));
+            /* Now, check if we're somewhere in the list.
+	       There's a race condition with sem_post here, but it does not matter:
+	       the net result is that at the time pthread_exit is called,
+	       self is no longer reachable from sem->sem_status. */
+            if (oldstatus != (long) self && (oldstatus & 1) == 0) {
+		for (th = &(((pthread_descr) oldstatus)->p_nextwaiting);
+		     *th != NULL && *th != (pthread_descr) 1;
+		     th = &((*th)->p_nextwaiting)) {
+		    if (*th == self) {
+			*th = self->p_nextwaiting;
+			break;
+		    }
+		}
+	    }
+            __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+	}
+    }
+}
+
+int __old_sem_trywait(old_sem_t * sem)
+{
+  long oldstatus, newstatus;
+
+  do {
+    oldstatus = sem->sem_status;
+    if ((oldstatus & 1) == 0 || (oldstatus == 1)) {
+      errno = EAGAIN;
+      return -1;
+    }
+    newstatus = oldstatus - 2;
+  }
+  while (! sem_compare_and_swap(sem, oldstatus, newstatus));
+  return 0;
+}
+
+int __old_sem_post(old_sem_t * sem)
+{
+  long oldstatus, newstatus;
+
+  do {
+    oldstatus = sem->sem_status;
+    if ((oldstatus & 1) == 0)
+      newstatus = 3;
+    else {
+      if (oldstatus >= SEM_VALUE_MAX) {
+        /* Overflow */
+        errno = ERANGE;
+        return -1;
+      }
+      newstatus = oldstatus + 2;
+    }
+  }
+  while (! sem_compare_and_swap(sem, oldstatus, newstatus));
+  if ((oldstatus & 1) == 0)
+    sem_restart_list((pthread_descr) oldstatus);
+  return 0;
+}
+
+int __old_sem_getvalue(old_sem_t * sem, int * sval)
+{
+  long status = sem->sem_status;
+  if (status & 1)
+    *sval = (int)((unsigned long) status >> 1);
+  else
+    *sval = 0;
+  return 0;
+}
+
+int __old_sem_destroy(old_sem_t * sem)
+{
+  if ((sem->sem_status & 1) == 0) {
+    errno = EBUSY;
+    return -1;
+  }
+  return 0;
+}
+
+/* Auxiliary function for restarting all threads on a waiting list,
+   in priority order. */
+
+static void sem_restart_list(pthread_descr waiting)
+{
+  pthread_descr th, towake, *p;
+
+  /* Sort list of waiting threads by decreasing priority (insertion sort) */
+  towake = NULL;
+  while (waiting != (pthread_descr) 1) {
+    th = waiting;
+    waiting = waiting->p_nextwaiting;
+    p = &towake;
+    while (*p != NULL && th->p_priority < (*p)->p_priority)
+      p = &((*p)->p_nextwaiting);
+    th->p_nextwaiting = *p;
+    *p = th;
+  }
+  /* Wake up threads in priority order */
+  while (towake != NULL) {
+    th = towake;
+    towake = towake->p_nextwaiting;
+    th->p_nextwaiting = NULL;
+    restart(th);
+  }
+}
+
+compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
+compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
+compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
+compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
+compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0);
+compat_symbol (libpthread, __old_sem_destroy, sem_destroy, GLIBC_2_0);
+
+#endif
diff --git a/linuxthreads/pt-allocrtsig.c b/linuxthreads/pt-allocrtsig.c
new file mode 100644
index 0000000000..3598dbb49f
--- /dev/null
+++ b/linuxthreads/pt-allocrtsig.c
@@ -0,0 +1,50 @@
+/* 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>
+
+
+/* These are defined in libc.  We want to have only one definition
+   so we "forward" the calls.  */
+extern int __libc_current_sigrtmin_private (void);
+extern int __libc_current_sigrtmax_private (void);
+extern int __libc_allocate_rtsig_private (int high);
+
+
+/* We reserve __SIGRTMIN for use as the cancelation signal.  This
+   signal is used internally.  */
+int
+__libc_current_sigrtmin (void)
+{
+  return __libc_current_sigrtmin_private ();
+}
+
+
+int
+__libc_current_sigrtmax (void)
+{
+  return __libc_current_sigrtmax_private ();
+}
+
+
+int
+__libc_allocate_rtsig (int high)
+{
+  return __libc_allocate_rtsig_private (high);
+}
diff --git a/linuxthreads/pt-machine.c b/linuxthreads/pt-machine.c
new file mode 100644
index 0000000000..5cd477ce97
--- /dev/null
+++ b/linuxthreads/pt-machine.c
@@ -0,0 +1,25 @@
+/* "Instantiation of machine-dependent pthreads inline functions.
+   Copyright (C) 1998 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.  */
+
+#define PT_EI
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+#include <pt-machine.h>
diff --git a/linuxthreads/pt-system.c b/linuxthreads/pt-system.c
new file mode 100644
index 0000000000..c3ed676f51
--- /dev/null
+++ b/linuxthreads/pt-system.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <sysdep-cancel.h>
+
+
+int
+system (const char *line)
+{
+  return __libc_system (line);
+}
+
+/* __libc_system in libc.so handles cancellation.  */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/ptcleanup.c b/linuxthreads/ptcleanup.c
new file mode 100644
index 0000000000..9fde2555b1
--- /dev/null
+++ b/linuxthreads/ptcleanup.c
@@ -0,0 +1,52 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998, 2004 Xavier Leroy (Xavier.Leroy@inria.fr)        */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Redefine siglongjmp and longjmp so that they interact correctly
+   with cleanup handlers */
+
+#include <setjmp.h>
+#include "pthread.h"
+#include "internals.h"
+
+void __pthread_cleanup_upto (__jmp_buf target, char *targetframe)
+{
+  pthread_descr self = thread_self();
+  struct _pthread_cleanup_buffer * c;
+
+  for (c = THREAD_GETMEM(self, p_cleanup);
+       c != NULL && _JMPBUF_UNWINDS(target, c);
+       c = c->__prev)
+    {
+#if _STACK_GROWS_DOWN
+      if ((char *) c <= targetframe)
+	{
+	  c = NULL;
+	  break;
+	}
+#elif _STACK_GROWS_UP
+      if ((char *) c >= targetframe)
+	{
+	  c = NULL;
+	  break;
+	}
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+      c->__routine(c->__arg);
+    }
+  THREAD_SETMEM(self, p_cleanup, c);
+  if (THREAD_GETMEM(self, p_in_sighandler)
+      && _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler)))
+    THREAD_SETMEM(self, p_in_sighandler, NULL);
+}
diff --git a/linuxthreads/ptclock_gettime.c b/linuxthreads/ptclock_gettime.c
new file mode 100644
index 0000000000..755f83d101
--- /dev/null
+++ b/linuxthreads/ptclock_gettime.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2001, 2004 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 <time.h>
+#include <libc-internal.h>
+#include "internals.h"
+#include "spinlock.h"
+
+
+#if HP_TIMING_AVAIL
+int
+__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
+			 struct timespec *tp)
+{
+  hp_timing_t tsc, cpuclock_offset;
+  pthread_descr self = thread_self ();
+  pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
+  const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE;
+
+  if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread)
+    cpuclock_offset = THREAD_GETMEM (self, p_cpuclock_offset);
+  else
+    {
+      pthread_descr th;
+      pthread_handle handle = thread_handle (thread);
+      __pthread_lock (&handle->h_lock, NULL);
+      th = handle->h_descr;
+      if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated)
+	{
+	  __pthread_unlock (&handle->h_lock);
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      cpuclock_offset = th->p_cpuclock_offset;
+      __pthread_unlock (&handle->h_lock);
+   }
+
+  /* Get the current counter.  */
+  HP_TIMING_NOW (tsc);
+
+  /* Compute the offset since the start time of the process.  */
+  tsc -= cpuclock_offset;
+
+  /* Compute the seconds.  */
+  tp->tv_sec = tsc / freq;
+
+  /* And the nanoseconds.  This computation should be stable until
+     we get machines with about 16GHz frequency.  */
+  tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq;
+
+  return 0;
+}
+#endif
diff --git a/linuxthreads/ptclock_settime.c b/linuxthreads/ptclock_settime.c
new file mode 100644
index 0000000000..a4f218c771
--- /dev/null
+++ b/linuxthreads/ptclock_settime.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2001, 2004 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 <time.h>
+#include <libc-internal.h>
+#include "internals.h"
+#include "spinlock.h"
+
+
+#if HP_TIMING_AVAIL
+int
+__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
+{
+  pthread_descr self = thread_self ();
+  pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
+  const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE;
+
+  if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread)
+    /* Our own clock.  */
+    THREAD_SETMEM (self, p_cpuclock_offset, offset);
+  else
+    {
+      pthread_descr th;
+      pthread_handle handle = thread_handle (thread);
+      __pthread_lock (&handle->h_lock, NULL);
+      th = handle->h_descr;
+      if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated)
+	{
+	  __pthread_unlock (&handle->h_lock);
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      th->p_cpuclock_offset = offset;
+      __pthread_unlock (&handle->h_lock);
+   }
+
+  return 0;
+}
+#endif
diff --git a/linuxthreads/ptfork.c b/linuxthreads/ptfork.c
new file mode 100644
index 0000000000..9cdbb54361
--- /dev/null
+++ b/linuxthreads/ptfork.c
@@ -0,0 +1,93 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* The "atfork" stuff */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pthread.h"
+#include "internals.h"
+#include <bits/libc-lock.h>
+#include "fork.h"
+
+extern int __libc_fork (void);
+
+pid_t __pthread_fork (struct fork_block *b)
+{
+  pid_t pid;
+  list_t *runp;
+
+  __libc_lock_lock (b->lock);
+
+  /* Run all the registered preparation handlers.  In reverse order.  */
+  list_for_each_prev (runp, &b->prepare_list)
+    {
+      struct fork_handler *curp;
+      curp = list_entry (runp, struct fork_handler, list);
+      curp->handler ();
+    }
+
+  __pthread_once_fork_prepare();
+  __flockfilelist();
+
+  pid = ARCH_FORK ();
+
+  if (pid == 0) {
+    __pthread_reset_main_thread();
+
+    __fresetlockfiles();
+    __pthread_once_fork_child();
+
+    /* Run the handlers registered for the child.  */
+    list_for_each (runp, &b->child_list)
+      {
+	struct fork_handler *curp;
+	curp = list_entry (runp, struct fork_handler, list);
+	curp->handler ();
+      }
+
+    __libc_lock_init (b->lock);
+  } else {
+    __funlockfilelist();
+    __pthread_once_fork_parent();
+
+    /* Run the handlers registered for the parent.  */
+    list_for_each (runp, &b->parent_list)
+      {
+	struct fork_handler *curp;
+	curp = list_entry (runp, struct fork_handler, list);
+	curp->handler ();
+      }
+
+    __libc_lock_unlock (b->lock);
+  }
+
+  return pid;
+}
+
+#ifdef SHARED
+pid_t __fork (void)
+{
+  return __libc_fork ();
+}
+weak_alias (__fork, fork);
+
+pid_t __vfork(void)
+{
+  return __libc_fork ();
+}
+weak_alias (__vfork, vfork);
+#endif
diff --git a/linuxthreads/pthandles.c b/linuxthreads/pthandles.c
new file mode 100644
index 0000000000..4d2ac1940d
--- /dev/null
+++ b/linuxthreads/pthandles.c
@@ -0,0 +1,6 @@
+#include <ldsodefs.h>
+#include "pthread.h"
+#include "internals.h"
+
+/* Array of active threads. Entry 0 is reserved for the initial thread. */
+struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];
diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c
new file mode 100644
index 0000000000..24f0eb02b0
--- /dev/null
+++ b/linuxthreads/pthread.c
@@ -0,0 +1,1407 @@
+
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Thread creation, initialization, and basic low-level routines */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <shlib-compat.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "smp.h"
+#include <ldsodefs.h>
+#include <tls.h>
+#include <version.h>
+#include <not-cancel.h>
+
+/* Sanity check.  */
+#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3
+# error "This must not happen"
+#endif
+
+#if !(USE_TLS && HAVE___THREAD)
+/* These variables are used by the setup code.  */
+extern int _errno;
+extern int _h_errno;
+
+/* We need the global/static resolver state here.  */
+# include <resolv.h>
+# undef _res
+
+extern struct __res_state _res;
+#endif
+
+#ifdef USE_TLS
+
+/* We need only a few variables.  */
+#define manager_thread __pthread_manager_threadp
+pthread_descr __pthread_manager_threadp attribute_hidden;
+
+#else
+
+/* Descriptor of the initial thread */
+
+struct _pthread_descr_struct __pthread_initial_thread = {
+  .p_header.data.self = &__pthread_initial_thread,
+  .p_nextlive = &__pthread_initial_thread,
+  .p_prevlive = &__pthread_initial_thread,
+  .p_tid = PTHREAD_THREADS_MAX,
+  .p_lock = &__pthread_handles[0].h_lock,
+  .p_start_args = PTHREAD_START_ARGS_INITIALIZER(NULL),
+#if !(USE_TLS && HAVE___THREAD)
+  .p_errnop = &_errno,
+  .p_h_errnop = &_h_errno,
+  .p_resp = &_res,
+#endif
+  .p_userstack = 1,
+  .p_resume_count = __ATOMIC_INITIALIZER,
+  .p_alloca_cutoff = __MAX_ALLOCA_CUTOFF
+};
+
+/* Descriptor of the manager thread; none of this is used but the error
+   variables, the p_pid and p_priority fields,
+   and the address for identification.  */
+
+#define manager_thread (&__pthread_manager_thread)
+struct _pthread_descr_struct __pthread_manager_thread = {
+  .p_header.data.self = &__pthread_manager_thread,
+  .p_header.data.multiple_threads = 1,
+  .p_lock = &__pthread_handles[1].h_lock,
+  .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager),
+#if !(USE_TLS && HAVE___THREAD)
+  .p_errnop = &__pthread_manager_thread.p_errno,
+#endif
+  .p_nr = 1,
+  .p_resume_count = __ATOMIC_INITIALIZER,
+  .p_alloca_cutoff = PTHREAD_STACK_MIN / 4
+};
+#endif
+
+/* Pointer to the main thread (the father of the thread manager thread) */
+/* Originally, this is the initial thread, but this changes after fork() */
+
+#ifdef USE_TLS
+pthread_descr __pthread_main_thread;
+#else
+pthread_descr __pthread_main_thread = &__pthread_initial_thread;
+#endif
+
+/* Limit between the stack of the initial thread (above) and the
+   stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
+
+char *__pthread_initial_thread_bos;
+
+/* File descriptor for sending requests to the thread manager. */
+/* Initially -1, meaning that the thread manager is not running. */
+
+int __pthread_manager_request = -1;
+
+int __pthread_multiple_threads attribute_hidden;
+
+/* Other end of the pipe for sending requests to the thread manager. */
+
+int __pthread_manager_reader;
+
+/* Limits of the thread manager stack */
+
+char *__pthread_manager_thread_bos;
+char *__pthread_manager_thread_tos;
+
+/* For process-wide exit() */
+
+int __pthread_exit_requested;
+int __pthread_exit_code;
+
+/* Maximum stack size.  */
+size_t __pthread_max_stacksize;
+
+/* Nozero if the machine has more than one processor.  */
+int __pthread_smp_kernel;
+
+
+#if !__ASSUME_REALTIME_SIGNALS
+/* Pointers that select new or old suspend/resume functions
+   based on availability of rt signals. */
+
+void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;
+void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;
+int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old;
+#endif	/* __ASSUME_REALTIME_SIGNALS */
+
+/* Communicate relevant LinuxThreads constants to gdb */
+
+const int __pthread_threads_max = PTHREAD_THREADS_MAX;
+const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
+const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct,
+                                              h_descr);
+const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
+                                            p_pid);
+const int __linuxthreads_pthread_sizeof_descr
+  = sizeof(struct _pthread_descr_struct);
+
+const int __linuxthreads_initial_report_events;
+
+const char __linuxthreads_version[] = VERSION;
+
+/* Forward declarations */
+
+static void pthread_onexit_process(int retcode, void *arg);
+#ifndef HAVE_Z_NODELETE
+static void pthread_atexit_process(void *arg, int retcode);
+static void pthread_atexit_retcode(void *arg, int retcode);
+#endif
+static void pthread_handle_sigcancel(int sig);
+static void pthread_handle_sigrestart(int sig);
+static void pthread_handle_sigdebug(int sig);
+
+/* Signal numbers used for the communication.
+   In these variables we keep track of the used variables.  If the
+   platform does not support any real-time signals we will define the
+   values to some unreasonable value which will signal failing of all
+   the functions below.  */
+int __pthread_sig_restart = __SIGRTMIN;
+int __pthread_sig_cancel = __SIGRTMIN + 1;
+int __pthread_sig_debug = __SIGRTMIN + 2;
+
+extern int __libc_current_sigrtmin_private (void);
+
+#if !__ASSUME_REALTIME_SIGNALS
+static int rtsigs_initialized;
+
+static void
+init_rtsigs (void)
+{
+  if (rtsigs_initialized)
+    return;
+
+  if (__libc_current_sigrtmin_private () == -1)
+    {
+      __pthread_sig_restart = SIGUSR1;
+      __pthread_sig_cancel = SIGUSR2;
+      __pthread_sig_debug = 0;
+    }
+  else
+    {
+      __pthread_restart = __pthread_restart_new;
+      __pthread_suspend = __pthread_wait_for_restart_signal;
+      __pthread_timedsuspend = __pthread_timedsuspend_new;
+    }
+
+  rtsigs_initialized = 1;
+}
+#endif
+
+
+/* Initialize the pthread library.
+   Initialization is split in two functions:
+   - a constructor function that blocks the __pthread_sig_restart signal
+     (must do this very early, since the program could capture the signal
+      mask with e.g. sigsetjmp before creating the first thread);
+   - a regular function called from pthread_create when needed. */
+
+static void pthread_initialize(void) __attribute__((constructor));
+
+#ifndef HAVE_Z_NODELETE
+extern void *__dso_handle __attribute__ ((weak));
+#endif
+
+
+#if defined USE_TLS && !defined SHARED
+extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
+#endif
+
+struct pthread_functions __pthread_functions =
+  {
+#if !(USE_TLS && HAVE___THREAD)
+    .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set,
+    .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get,
+    .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address,
+#endif
+    .ptr_pthread_fork = __pthread_fork,
+    .ptr_pthread_attr_destroy = __pthread_attr_destroy,
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+    .ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0,
+#endif
+    .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1,
+    .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate,
+    .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate,
+    .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched,
+    .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched,
+    .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam,
+    .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam,
+    .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy,
+    .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy,
+    .ptr_pthread_attr_getscope = __pthread_attr_getscope,
+    .ptr_pthread_attr_setscope = __pthread_attr_setscope,
+    .ptr_pthread_condattr_destroy = __pthread_condattr_destroy,
+    .ptr_pthread_condattr_init = __pthread_condattr_init,
+    .ptr___pthread_cond_broadcast = __pthread_cond_broadcast,
+    .ptr___pthread_cond_destroy = __pthread_cond_destroy,
+    .ptr___pthread_cond_init = __pthread_cond_init,
+    .ptr___pthread_cond_signal = __pthread_cond_signal,
+    .ptr___pthread_cond_wait = __pthread_cond_wait,
+    .ptr___pthread_cond_timedwait = __pthread_cond_timedwait,
+    .ptr_pthread_equal = __pthread_equal,
+    .ptr___pthread_exit = __pthread_exit,
+    .ptr_pthread_getschedparam = __pthread_getschedparam,
+    .ptr_pthread_setschedparam = __pthread_setschedparam,
+    .ptr_pthread_mutex_destroy = __pthread_mutex_destroy,
+    .ptr_pthread_mutex_init = __pthread_mutex_init,
+    .ptr_pthread_mutex_lock = __pthread_mutex_lock,
+    .ptr_pthread_mutex_trylock = __pthread_mutex_trylock,
+    .ptr_pthread_mutex_unlock = __pthread_mutex_unlock,
+    .ptr_pthread_self = __pthread_self,
+    .ptr_pthread_setcancelstate = __pthread_setcancelstate,
+    .ptr_pthread_setcanceltype = __pthread_setcanceltype,
+    .ptr_pthread_do_exit = __pthread_do_exit,
+    .ptr_pthread_thread_self = __pthread_thread_self,
+    .ptr_pthread_cleanup_upto = __pthread_cleanup_upto,
+    .ptr_pthread_sigaction = __pthread_sigaction,
+    .ptr_pthread_sigwait = __pthread_sigwait,
+    .ptr_pthread_raise = __pthread_raise,
+    .ptr__pthread_cleanup_push = _pthread_cleanup_push,
+    .ptr__pthread_cleanup_pop = _pthread_cleanup_pop
+  };
+#ifdef SHARED
+# define ptr_pthread_functions &__pthread_functions
+#else
+# define ptr_pthread_functions NULL
+#endif
+
+static int *__libc_multiple_threads_ptr;
+
+/* Do some minimal initialization which has to be done during the
+   startup of the C library.  */
+void
+__pthread_initialize_minimal(void)
+{
+#ifdef USE_TLS
+  pthread_descr self;
+
+  /* First of all init __pthread_handles[0] and [1] if needed.  */
+# if __LT_SPINLOCK_INIT != 0
+  __pthread_handles[0].h_lock = __LOCK_INITIALIZER;
+  __pthread_handles[1].h_lock = __LOCK_INITIALIZER;
+# endif
+# ifndef SHARED
+  /* Unlike in the dynamically linked case the dynamic linker has not
+     taken care of initializing the TLS data structures.  */
+  __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
+# elif !USE___THREAD
+  if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0))
+    {
+      tcbhead_t *tcbp;
+
+      /* There is no actual TLS being used, so the thread register
+	 was not initialized in the dynamic linker.  */
+
+      /* We need to install special hooks so that the malloc and memalign
+	 calls in _dl_tls_setup and _dl_allocate_tls won't cause full
+	 malloc initialization that will try to set up its thread state.  */
+
+      extern void __libc_malloc_pthread_startup (bool first_time);
+      __libc_malloc_pthread_startup (true);
+
+      if (__builtin_expect (_dl_tls_setup (), 0)
+	  || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0))
+	{
+	  static const char msg[] = "\
+cannot allocate TLS data structures for initial thread\n";
+	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
+						msg, sizeof msg - 1));
+	  abort ();
+	}
+      const char *lossage = TLS_INIT_TP (tcbp, 0);
+      if (__builtin_expect (lossage != NULL, 0))
+	{
+	  static const char msg[] = "cannot set up thread-local storage: ";
+	  const char nl = '\n';
+	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
+						msg, sizeof msg - 1));
+	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
+						lossage, strlen (lossage)));
+	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1));
+	}
+
+      /* Though it was allocated with libc's malloc, that was done without
+	 the user's __malloc_hook installed.  A later realloc that uses
+	 the hooks might not work with that block from the plain malloc.
+	 So we record this block as unfreeable just as the dynamic linker
+	 does when it allocates the DTV before the libc malloc exists.  */
+      GL(dl_initial_dtv) = GET_DTV (tcbp);
+
+      __libc_malloc_pthread_startup (false);
+    }
+# endif
+
+  self = THREAD_SELF;
+
+  /* The memory for the thread descriptor was allocated elsewhere as
+     part of the TLS allocation.  We have to initialize the data
+     structure by hand.  This initialization must mirror the struct
+     definition above.  */
+  self->p_nextlive = self->p_prevlive = self;
+  self->p_tid = PTHREAD_THREADS_MAX;
+  self->p_lock = &__pthread_handles[0].h_lock;
+# ifndef HAVE___THREAD
+  self->p_errnop = &_errno;
+  self->p_h_errnop = &_h_errno;
+# endif
+  /* self->p_start_args need not be initialized, it's all zero.  */
+  self->p_userstack = 1;
+# if __LT_SPINLOCK_INIT != 0
+  self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER;
+# endif
+  self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF;
+
+  /* Another variable which points to the thread descriptor.  */
+  __pthread_main_thread = self;
+
+  /* And fill in the pointer the the thread __pthread_handles array.  */
+  __pthread_handles[0].h_descr = self;
+
+#else  /* USE_TLS */
+
+  /* First of all init __pthread_handles[0] and [1].  */
+# if __LT_SPINLOCK_INIT != 0
+  __pthread_handles[0].h_lock = __LOCK_INITIALIZER;
+  __pthread_handles[1].h_lock = __LOCK_INITIALIZER;
+# endif
+  __pthread_handles[0].h_descr = &__pthread_initial_thread;
+  __pthread_handles[1].h_descr = &__pthread_manager_thread;
+
+  /* If we have special thread_self processing, initialize that for the
+     main thread now.  */
+# ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(&__pthread_initial_thread, 0);
+# endif
+#endif
+
+#if HP_TIMING_AVAIL
+# ifdef USE_TLS
+  self->p_cpuclock_offset = GL(dl_cpuclock_offset);
+# else
+  __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset);
+# endif
+#endif
+
+  __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions);
+}
+
+
+void
+__pthread_init_max_stacksize(void)
+{
+  struct rlimit limit;
+  size_t max_stack;
+
+  getrlimit(RLIMIT_STACK, &limit);
+#ifdef FLOATING_STACKS
+  if (limit.rlim_cur == RLIM_INFINITY)
+    limit.rlim_cur = ARCH_STACK_MAX_SIZE;
+# ifdef NEED_SEPARATE_REGISTER_STACK
+  max_stack = limit.rlim_cur / 2;
+# else
+  max_stack = limit.rlim_cur;
+# endif
+#else
+  /* Play with the stack size limit to make sure that no stack ever grows
+     beyond STACK_SIZE minus one page (to act as a guard page). */
+# ifdef NEED_SEPARATE_REGISTER_STACK
+  /* STACK_SIZE bytes hold both the main stack and register backing
+     store. The rlimit value applies to each individually.  */
+  max_stack = STACK_SIZE/2 - __getpagesize ();
+# else
+  max_stack = STACK_SIZE - __getpagesize();
+# endif
+  if (limit.rlim_cur > max_stack) {
+    limit.rlim_cur = max_stack;
+    setrlimit(RLIMIT_STACK, &limit);
+  }
+#endif
+  __pthread_max_stacksize = max_stack;
+  if (max_stack / 4 < __MAX_ALLOCA_CUTOFF)
+    {
+#ifdef USE_TLS
+      pthread_descr self = THREAD_SELF;
+      self->p_alloca_cutoff = max_stack / 4;
+#else
+      __pthread_initial_thread.p_alloca_cutoff = max_stack / 4;
+#endif
+    }
+}
+
+#ifdef SHARED
+# if USE___THREAD
+/* When using __thread for this, we do it in libc so as not
+   to give libpthread its own TLS segment just for this.  */
+extern void **__libc_dl_error_tsd (void) __attribute__ ((const));
+# else
+static void ** __attribute__ ((const))
+__libc_dl_error_tsd (void)
+{
+  return &thread_self ()->p_libc_specific[_LIBC_TSD_KEY_DL_ERROR];
+}
+# endif
+#endif
+
+#ifdef USE_TLS
+static inline void __attribute__((always_inline))
+init_one_static_tls (pthread_descr descr, struct link_map *map)
+{
+# if TLS_TCB_AT_TP
+  dtv_t *dtv = GET_DTV (descr);
+  void *dest = (char *) descr - map->l_tls_offset;
+# elif TLS_DTV_AT_TP
+  dtv_t *dtv = GET_DTV ((pthread_descr) ((char *) descr + TLS_PRE_TCB_SIZE));
+  void *dest = (char *) descr + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+# else
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+  /* Fill in the DTV slot so that a later LD/GD access will find it.  */
+  dtv[map->l_tls_modid].pointer = dest;
+
+  /* Initialize the memory.  */
+  memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+}
+
+static void
+__pthread_init_static_tls (struct link_map *map)
+{
+  size_t i;
+
+  for (i = 0; i < PTHREAD_THREADS_MAX; ++i)
+    if (__pthread_handles[i].h_descr != NULL && i != 1)
+      {
+        __pthread_lock (&__pthread_handles[i].h_lock, NULL);
+	if (__pthread_handles[i].h_descr != NULL)
+	  init_one_static_tls (__pthread_handles[i].h_descr, map);
+        __pthread_unlock (&__pthread_handles[i].h_lock);
+      }
+}
+#endif
+
+static void pthread_initialize(void)
+{
+  struct sigaction sa;
+  sigset_t mask;
+
+  /* If already done (e.g. by a constructor called earlier!), bail out */
+  if (__pthread_initial_thread_bos != NULL) return;
+#ifdef TEST_FOR_COMPARE_AND_SWAP
+  /* Test if compare-and-swap is available */
+  __pthread_has_cas = compare_and_swap_is_available();
+#endif
+#ifdef FLOATING_STACKS
+  /* We don't need to know the bottom of the stack.  Give the pointer some
+     value to signal that initialization happened.  */
+  __pthread_initial_thread_bos = (void *) -1l;
+#else
+  /* Determine stack size limits .  */
+  __pthread_init_max_stacksize ();
+# ifdef _STACK_GROWS_UP
+  /* The initial thread already has all the stack it needs */
+  __pthread_initial_thread_bos = (char *)
+    ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1));
+# else
+  /* For the initial stack, reserve at least STACK_SIZE bytes of stack
+     below the current stack address, and align that on a
+     STACK_SIZE boundary. */
+  __pthread_initial_thread_bos =
+    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
+# endif
+#endif
+#ifdef USE_TLS
+  /* Update the descriptor for the initial thread. */
+  THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid());
+# ifndef HAVE___THREAD
+  /* Likewise for the resolver state _res.  */
+  THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res);
+# endif
+#else
+  /* Update the descriptor for the initial thread. */
+  __pthread_initial_thread.p_pid = __getpid();
+  /* Likewise for the resolver state _res.  */
+  __pthread_initial_thread.p_resp = &_res;
+#endif
+#if !__ASSUME_REALTIME_SIGNALS
+  /* Initialize real-time signals. */
+  init_rtsigs ();
+#endif
+  /* Setup signal handlers for the initial thread.
+     Since signal handlers are shared between threads, these settings
+     will be inherited by all other threads. */
+  sa.sa_handler = pthread_handle_sigrestart;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
+  sa.sa_handler = pthread_handle_sigcancel;
+  sigaddset(&sa.sa_mask, __pthread_sig_restart);
+  // sa.sa_flags = 0;
+  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
+  if (__pthread_sig_debug > 0) {
+    sa.sa_handler = pthread_handle_sigdebug;
+    sigemptyset(&sa.sa_mask);
+    // sa.sa_flags = 0;
+    __libc_sigaction(__pthread_sig_debug, &sa, NULL);
+  }
+  /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
+  sigemptyset(&mask);
+  sigaddset(&mask, __pthread_sig_restart);
+  sigprocmask(SIG_BLOCK, &mask, NULL);
+  /* And unblock __pthread_sig_cancel if it has been blocked. */
+  sigdelset(&mask, __pthread_sig_restart);
+  sigaddset(&mask, __pthread_sig_cancel);
+  sigprocmask(SIG_UNBLOCK, &mask, NULL);
+  /* Register an exit function to kill all other threads. */
+  /* Do it early so that user-registered atexit functions are called
+     before pthread_*exit_process. */
+#ifndef HAVE_Z_NODELETE
+  if (__builtin_expect (&__dso_handle != NULL, 1))
+    __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL,
+		  __dso_handle);
+  else
+#endif
+    __on_exit (pthread_onexit_process, NULL);
+  /* How many processors.  */
+  __pthread_smp_kernel = is_smp_system ();
+
+#ifdef SHARED
+  /* Transfer the old value from the dynamic linker's internal location.  */
+  *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) ();
+  GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;
+
+  /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock,
+     keep the lock count from the ld.so implementation.  */
+  GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock;
+  GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock;
+  unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__m_count;
+  GL(dl_load_lock).mutex.__m_count = 0;
+  while (rtld_lock_count-- > 0)
+    __pthread_mutex_lock (&GL(dl_load_lock).mutex);
+#endif
+
+#ifdef USE_TLS
+  GL(dl_init_static_tls) = &__pthread_init_static_tls;
+#endif
+}
+
+void __pthread_initialize(void)
+{
+  pthread_initialize();
+}
+
+int __pthread_initialize_manager(void)
+{
+  int manager_pipe[2];
+  int pid;
+  struct pthread_request request;
+  int report_events;
+  pthread_descr mgr;
+#ifdef USE_TLS
+  tcbhead_t *tcbp;
+#endif
+
+  __pthread_multiple_threads = 1;
+#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
+  __pthread_main_thread->p_multiple_threads = 1;
+#endif
+  *__libc_multiple_threads_ptr = 1;
+
+#ifndef HAVE_Z_NODELETE
+  if (__builtin_expect (&__dso_handle != NULL, 1))
+    __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,
+		  __dso_handle);
+#endif
+
+  if (__pthread_max_stacksize == 0)
+    __pthread_init_max_stacksize ();
+  /* If basic initialization not done yet (e.g. we're called from a
+     constructor run before our constructor), do it now */
+  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
+  /* Setup stack for thread manager */
+  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
+  if (__pthread_manager_thread_bos == NULL) return -1;
+  __pthread_manager_thread_tos =
+    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
+  /* Setup pipe to communicate with thread manager */
+  if (pipe(manager_pipe) == -1) {
+    free(__pthread_manager_thread_bos);
+    return -1;
+  }
+
+#ifdef USE_TLS
+  /* Allocate memory for the thread descriptor and the dtv.  */
+  tcbp = _dl_allocate_tls (NULL);
+  if (tcbp == NULL) {
+    free(__pthread_manager_thread_bos);
+    close_not_cancel(manager_pipe[0]);
+    close_not_cancel(manager_pipe[1]);
+    return -1;
+  }
+
+# if TLS_TCB_AT_TP
+  mgr = (pthread_descr) tcbp;
+# elif TLS_DTV_AT_TP
+  /* pthread_descr is located right below tcbhead_t which _dl_allocate_tls
+     returns.  */
+  mgr = (pthread_descr) ((char *) tcbp - TLS_PRE_TCB_SIZE);
+# endif
+  __pthread_handles[1].h_descr = manager_thread = mgr;
+
+  /* Initialize the descriptor.  */
+#if !defined USE_TLS || !TLS_DTV_AT_TP
+  mgr->p_header.data.tcb = tcbp;
+  mgr->p_header.data.self = mgr;
+  mgr->p_header.data.multiple_threads = 1;
+#elif TLS_MULTIPLE_THREADS_IN_TCB
+  mgr->p_multiple_threads = 1;
+#endif
+  mgr->p_lock = &__pthread_handles[1].h_lock;
+# ifndef HAVE___THREAD
+  mgr->p_errnop = &mgr->p_errno;
+# endif
+  mgr->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager);
+  mgr->p_nr = 1;
+# if __LT_SPINLOCK_INIT != 0
+  self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER;
+# endif
+  mgr->p_alloca_cutoff = PTHREAD_STACK_MIN / 4;
+#else
+  mgr = &__pthread_manager_thread;
+#endif
+
+  __pthread_manager_request = manager_pipe[1]; /* writing end */
+  __pthread_manager_reader = manager_pipe[0]; /* reading end */
+
+  /* Start the thread manager */
+  pid = 0;
+#ifdef USE_TLS
+  if (__linuxthreads_initial_report_events != 0)
+    THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
+		   __linuxthreads_initial_report_events);
+  report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
+#else
+  if (__linuxthreads_initial_report_events != 0)
+    __pthread_initial_thread.p_report_events
+      = __linuxthreads_initial_report_events;
+  report_events = __pthread_initial_thread.p_report_events;
+#endif
+  if (__builtin_expect (report_events, 0))
+    {
+      /* It's a bit more complicated.  We have to report the creation of
+	 the manager thread.  */
+      int idx = __td_eventword (TD_CREATE);
+      uint32_t mask = __td_eventmask (TD_CREATE);
+      uint32_t event_bits;
+
+#ifdef USE_TLS
+      event_bits = THREAD_GETMEM_NC (((pthread_descr) NULL),
+				     p_eventbuf.eventmask.event_bits[idx]);
+#else
+      event_bits = __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx];
+#endif
+
+      if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits))
+	  != 0)
+	{
+	  __pthread_lock(mgr->p_lock, NULL);
+
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	  pid = __clone2(__pthread_manager_event,
+			 (void **) __pthread_manager_thread_bos,
+			 THREAD_MANAGER_STACK_SIZE,
+			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			 mgr);
+#elif _STACK_GROWS_UP
+	  pid = __clone(__pthread_manager_event,
+			(void **) __pthread_manager_thread_bos,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			mgr);
+#else
+	  pid = __clone(__pthread_manager_event,
+			(void **) __pthread_manager_thread_tos,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			mgr);
+#endif
+
+	  if (pid != -1)
+	    {
+	      /* 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.  */
+	      mgr->p_eventbuf.eventdata = mgr;
+	      mgr->p_eventbuf.eventnum = TD_CREATE;
+	      __pthread_last_event = mgr;
+	      mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1;
+	      mgr->p_pid = pid;
+
+	      /* Now call the function which signals the event.  */
+	      __linuxthreads_create_event ();
+	    }
+
+	  /* Now restart the thread.  */
+	  __pthread_unlock(mgr->p_lock);
+	}
+    }
+
+  if (__builtin_expect (pid, 0) == 0)
+    {
+#ifdef NEED_SEPARATE_REGISTER_STACK
+      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
+		     THREAD_MANAGER_STACK_SIZE,
+		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+#elif _STACK_GROWS_UP
+      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+#else
+      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr);
+#endif
+    }
+  if (__builtin_expect (pid, 0) == -1) {
+#ifdef USE_TLS
+    _dl_deallocate_tls (tcbp, true);
+#endif
+    free(__pthread_manager_thread_bos);
+    close_not_cancel(manager_pipe[0]);
+    close_not_cancel(manager_pipe[1]);
+    return -1;
+  }
+  mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1;
+  mgr->p_pid = pid;
+  /* Make gdb aware of new thread manager */
+  if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
+    {
+      raise(__pthread_sig_debug);
+      /* We suspend ourself and gdb will wake us up when it is
+	 ready to handle us. */
+      __pthread_wait_for_restart_signal(thread_self());
+    }
+  /* Synchronize debugging of the thread manager */
+  request.req_kind = REQ_DEBUG;
+  TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+				      (char *) &request, sizeof(request)));
+  return 0;
+}
+
+/* Thread creation */
+
+int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
+			 void * (*start_routine)(void *), void *arg)
+{
+  pthread_descr self = thread_self();
+  struct pthread_request request;
+  int retval;
+  if (__builtin_expect (__pthread_manager_request, 0) < 0) {
+    if (__pthread_initialize_manager() < 0) return EAGAIN;
+  }
+  request.req_thread = self;
+  request.req_kind = REQ_CREATE;
+  request.req_args.create.attr = attr;
+  request.req_args.create.fn = start_routine;
+  request.req_args.create.arg = arg;
+  sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
+              &request.req_args.create.mask);
+  TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+				      (char *) &request, sizeof(request)));
+  suspend(self);
+  retval = THREAD_GETMEM(self, p_retcode);
+  if (__builtin_expect (retval, 0) == 0)
+    *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
+  return retval;
+}
+
+versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1);
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+
+int __pthread_create_2_0(pthread_t *thread, const pthread_attr_t *attr,
+			 void * (*start_routine)(void *), void *arg)
+{
+  /* The ATTR attribute is not really of type `pthread_attr_t *'.  It has
+     the old size and access to the new members might crash the program.
+     We convert the struct now.  */
+  pthread_attr_t new_attr;
+
+  if (attr != NULL)
+    {
+      size_t ps = __getpagesize ();
+
+      memcpy (&new_attr, attr,
+	      (size_t) &(((pthread_attr_t*)NULL)->__guardsize));
+      new_attr.__guardsize = ps;
+      new_attr.__stackaddr_set = 0;
+      new_attr.__stackaddr = NULL;
+      new_attr.__stacksize = STACK_SIZE - ps;
+      attr = &new_attr;
+    }
+  return __pthread_create_2_1 (thread, attr, start_routine, arg);
+}
+compat_symbol (libpthread, __pthread_create_2_0, pthread_create, GLIBC_2_0);
+#endif
+
+/* Simple operations on thread identifiers */
+
+pthread_descr __pthread_thread_self(void)
+{
+  return thread_self();
+}
+
+pthread_t __pthread_self(void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM(self, p_tid);
+}
+strong_alias (__pthread_self, pthread_self);
+
+int __pthread_equal(pthread_t thread1, pthread_t thread2)
+{
+  return thread1 == thread2;
+}
+strong_alias (__pthread_equal, pthread_equal);
+
+/* Helper function for thread_self in the case of user-provided stacks */
+
+#ifndef THREAD_SELF
+
+pthread_descr __pthread_find_self(void)
+{
+  char * sp = CURRENT_STACK_FRAME;
+  pthread_handle h;
+
+  /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
+     the manager threads handled specially in thread_self(), so start at 2 */
+  h = __pthread_handles + 2;
+# ifdef _STACK_GROWS_UP
+  while (! (sp >= (char *) h->h_descr && sp < h->h_descr->p_guardaddr)) h++;
+# else
+  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
+# endif
+  return h->h_descr;
+}
+
+#else
+
+pthread_descr __pthread_self_stack(void)
+{
+  char *sp = CURRENT_STACK_FRAME;
+  pthread_handle h;
+
+  if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
+    return manager_thread;
+  h = __pthread_handles + 2;
+# ifdef USE_TLS
+#  ifdef _STACK_GROWS_UP
+  while (h->h_descr == NULL
+	 || ! (sp >= h->h_descr->p_stackaddr && sp < h->h_descr->p_guardaddr))
+    h++;
+#  else
+  while (h->h_descr == NULL
+	 || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom))
+    h++;
+#  endif
+# else
+#  ifdef _STACK_GROWS_UP
+  while (! (sp >= (char *) h->h_descr && sp < h->h_descr->p_guardaddr))
+    h++;
+#  else
+  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
+    h++;
+#  endif
+# endif
+  return h->h_descr;
+}
+
+#endif
+
+/* Thread scheduling */
+
+int __pthread_setschedparam(pthread_t thread, int policy,
+                            const struct sched_param *param)
+{
+  pthread_handle handle = thread_handle(thread);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (__builtin_expect (invalid_handle(handle, thread), 0)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1,
+			0)) {
+    __pthread_unlock(&handle->h_lock);
+    return errno;
+  }
+  th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
+  __pthread_unlock(&handle->h_lock);
+  if (__pthread_manager_request >= 0)
+    __pthread_manager_adjust_prio(th->p_priority);
+  return 0;
+}
+strong_alias (__pthread_setschedparam, pthread_setschedparam);
+
+int __pthread_getschedparam(pthread_t thread, int *policy,
+                            struct sched_param *param)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid, pol;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (__builtin_expect (invalid_handle(handle, thread), 0)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  pid = handle->h_descr->p_pid;
+  __pthread_unlock(&handle->h_lock);
+  pol = __sched_getscheduler(pid);
+  if (__builtin_expect (pol, 0) == -1) return errno;
+  if (__sched_getparam(pid, param) == -1) return errno;
+  *policy = pol;
+  return 0;
+}
+strong_alias (__pthread_getschedparam, pthread_getschedparam);
+
+int __pthread_yield (void)
+{
+  /* For now this is equivalent with the POSIX call.  */
+  return sched_yield ();
+}
+weak_alias (__pthread_yield, pthread_yield)
+
+/* Process-wide exit() request */
+
+static void pthread_onexit_process(int retcode, void *arg)
+{
+  if (__builtin_expect (__pthread_manager_request, 0) >= 0) {
+    struct pthread_request request;
+    pthread_descr self = thread_self();
+
+    request.req_thread = self;
+    request.req_kind = REQ_PROCESS_EXIT;
+    request.req_args.exit.code = retcode;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+    suspend(self);
+    /* Main thread should accumulate times for thread manager and its
+       children, so that timings for main thread account for all threads. */
+    if (self == __pthread_main_thread)
+      {
+#ifdef USE_TLS
+	waitpid(manager_thread->p_pid, NULL, __WCLONE);
+#else
+	waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+#endif
+	/* Since all threads have been asynchronously terminated
+           (possibly holding locks), free cannot be used any more.
+           For mtrace, we'd like to print something though.  */
+	/* #ifdef USE_TLS
+	   tcbhead_t *tcbp = (tcbhead_t *) manager_thread;
+	   # if TLS_DTV_AT_TP
+	   tcbp = (tcbhead_t) ((char *) tcbp + TLS_PRE_TCB_SIZE);
+	   # endif
+	   _dl_deallocate_tls (tcbp, true);
+	   #endif
+	   free (__pthread_manager_thread_bos); */
+	__pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
+      }
+  }
+}
+
+#ifndef HAVE_Z_NODELETE
+static int __pthread_atexit_retcode;
+
+static void pthread_atexit_process(void *arg, int retcode)
+{
+  pthread_onexit_process (retcode ?: __pthread_atexit_retcode, arg);
+}
+
+static void pthread_atexit_retcode(void *arg, int retcode)
+{
+  __pthread_atexit_retcode = retcode;
+}
+#endif
+
+/* The handler for the RESTART signal just records the signal received
+   in the thread descriptor, and optionally performs a siglongjmp
+   (for pthread_cond_timedwait). */
+
+static void pthread_handle_sigrestart(int sig)
+{
+  pthread_descr self = check_thread_self();
+  THREAD_SETMEM(self, p_signal, sig);
+  if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
+    siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
+}
+
+/* The handler for the CANCEL signal checks for cancellation
+   (in asynchronous mode), for process-wide exit and exec requests.
+   For the thread manager thread, redirect the signal to
+   __pthread_manager_sighandler. */
+
+static void pthread_handle_sigcancel(int sig)
+{
+  pthread_descr self = check_thread_self();
+  sigjmp_buf * jmpbuf;
+
+  if (self == manager_thread)
+    {
+      __pthread_manager_sighandler(sig);
+      return;
+    }
+  if (__builtin_expect (__pthread_exit_requested, 0)) {
+    /* Main thread should accumulate times for thread manager and its
+       children, so that timings for main thread account for all threads. */
+    if (self == __pthread_main_thread) {
+#ifdef USE_TLS
+      waitpid(manager_thread->p_pid, NULL, __WCLONE);
+#else
+      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+#endif
+    }
+    _exit(__pthread_exit_code);
+  }
+  if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
+    if (jmpbuf != NULL) {
+      THREAD_SETMEM(self, p_cancel_jmp, NULL);
+      siglongjmp(*jmpbuf, 1);
+    }
+  }
+}
+
+/* Handler for the DEBUG signal.
+   The debugging strategy is as follows:
+   On reception of a REQ_DEBUG request (sent by new threads created to
+   the thread manager under debugging mode), the thread manager throws
+   __pthread_sig_debug to itself. The debugger (if active) intercepts
+   this signal, takes into account new threads and continue execution
+   of the thread manager by propagating the signal because it doesn't
+   know what it is specifically done for. In the current implementation,
+   the thread manager simply discards it. */
+
+static void pthread_handle_sigdebug(int sig)
+{
+  /* Nothing */
+}
+
+/* Reset the state of the thread machinery after a fork().
+   Close the pipe used for requests and set the main thread to the forked
+   thread.
+   Notice that we can't free the stack segments, as the forked thread
+   may hold pointers into them. */
+
+void __pthread_reset_main_thread(void)
+{
+  pthread_descr self = thread_self();
+
+  if (__pthread_manager_request != -1) {
+    /* Free the thread manager stack */
+    free(__pthread_manager_thread_bos);
+    __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
+    /* Close the two ends of the pipe */
+    close_not_cancel(__pthread_manager_request);
+    close_not_cancel(__pthread_manager_reader);
+    __pthread_manager_request = __pthread_manager_reader = -1;
+  }
+
+  /* Update the pid of the main thread */
+  THREAD_SETMEM(self, p_pid, __getpid());
+  /* Make the forked thread the main thread */
+  __pthread_main_thread = self;
+  THREAD_SETMEM(self, p_nextlive, self);
+  THREAD_SETMEM(self, p_prevlive, self);
+#if !(USE_TLS && HAVE___THREAD)
+  /* Now this thread modifies the global variables.  */
+  THREAD_SETMEM(self, p_errnop, &_errno);
+  THREAD_SETMEM(self, p_h_errnop, &_h_errno);
+  THREAD_SETMEM(self, p_resp, &_res);
+#endif
+
+#ifndef FLOATING_STACKS
+  /* This is to undo the setrlimit call in __pthread_init_max_stacksize.
+     XXX This can be wrong if the user set the limit during the run.  */
+ {
+   struct rlimit limit;
+   if (getrlimit (RLIMIT_STACK, &limit) == 0
+       && limit.rlim_cur != limit.rlim_max)
+     {
+       limit.rlim_cur = limit.rlim_max;
+       setrlimit(RLIMIT_STACK, &limit);
+     }
+ }
+#endif
+}
+
+/* Process-wide exec() request */
+
+void __pthread_kill_other_threads_np(void)
+{
+  struct sigaction sa;
+  /* Terminate all other threads and thread manager */
+  pthread_onexit_process(0, NULL);
+  /* Make current thread the main thread in case the calling thread
+     changes its mind, does not exec(), and creates new threads instead. */
+  __pthread_reset_main_thread();
+
+  /* Reset the signal handlers behaviour for the signals the
+     implementation uses since this would be passed to the new
+     process.  */
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = SIG_DFL;
+  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
+  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
+  if (__pthread_sig_debug > 0)
+    __libc_sigaction(__pthread_sig_debug, &sa, NULL);
+}
+weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
+
+/* Concurrency symbol level.  */
+static int current_level;
+
+int __pthread_setconcurrency(int level)
+{
+  /* We don't do anything unless we have found a useful interpretation.  */
+  current_level = level;
+  return 0;
+}
+weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
+
+int __pthread_getconcurrency(void)
+{
+  return current_level;
+}
+weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
+
+/* Primitives for controlling thread execution */
+
+void __pthread_wait_for_restart_signal(pthread_descr self)
+{
+  sigset_t mask;
+
+  sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
+  sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
+  THREAD_SETMEM(self, p_signal, 0);
+  do {
+    __pthread_sigsuspend(&mask);	/* Wait for signal.  Must not be a
+					   cancellation point. */
+  } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
+
+  READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
+}
+
+#if !__ASSUME_REALTIME_SIGNALS
+/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT
+   signals.
+   On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.
+   Since the restart signal does not queue, we use an atomic counter to create
+   queuing semantics. This is needed to resolve a rare race condition in
+   pthread_cond_timedwait_relative. */
+
+void __pthread_restart_old(pthread_descr th)
+{
+  if (atomic_increment(&th->p_resume_count) == -1)
+    kill(th->p_pid, __pthread_sig_restart);
+}
+
+void __pthread_suspend_old(pthread_descr self)
+{
+  if (atomic_decrement(&self->p_resume_count) <= 0)
+    __pthread_wait_for_restart_signal(self);
+}
+
+int
+__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
+{
+  sigset_t unblock, initial_mask;
+  int was_signalled = 0;
+  sigjmp_buf jmpbuf;
+
+  if (atomic_decrement(&self->p_resume_count) == 0) {
+    /* Set up a longjmp handler for the restart signal, unblock
+       the signal and sleep. */
+
+    if (sigsetjmp(jmpbuf, 1) == 0) {
+      THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
+      THREAD_SETMEM(self, p_signal, 0);
+      /* Unblock the restart signal */
+      sigemptyset(&unblock);
+      sigaddset(&unblock, __pthread_sig_restart);
+      sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
+
+      while (1) {
+	struct timeval now;
+	struct timespec reltime;
+
+	/* Compute a time offset relative to now.  */
+	__gettimeofday (&now, NULL);
+	reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+	reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+	if (reltime.tv_nsec < 0) {
+	  reltime.tv_nsec += 1000000000;
+	  reltime.tv_sec -= 1;
+	}
+
+	/* Sleep for the required duration. If woken by a signal,
+	   resume waiting as required by Single Unix Specification.  */
+	if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
+	  break;
+      }
+
+      /* Block the restart signal again */
+      sigprocmask(SIG_SETMASK, &initial_mask, NULL);
+      was_signalled = 0;
+    } else {
+      was_signalled = 1;
+    }
+    THREAD_SETMEM(self, p_signal_jmp, NULL);
+  }
+
+  /* Now was_signalled is true if we exited the above code
+     due to the delivery of a restart signal.  In that case,
+     we know we have been dequeued and resumed and that the
+     resume count is balanced.  Otherwise, there are some
+     cases to consider. First, try to bump up the resume count
+     back to zero. If it goes to 1, it means restart() was
+     invoked on this thread. The signal must be consumed
+     and the count bumped down and everything is cool. We
+     can return a 1 to the caller.
+     Otherwise, no restart was delivered yet, so a potential
+     race exists; we return a 0 to the caller which must deal
+     with this race in an appropriate way; for example by
+     atomically removing the thread from consideration for a
+     wakeup---if such a thing fails, it means a restart is
+     being delivered. */
+
+  if (!was_signalled) {
+    if (atomic_increment(&self->p_resume_count) != -1) {
+      __pthread_wait_for_restart_signal(self);
+      atomic_decrement(&self->p_resume_count); /* should be zero now! */
+      /* woke spontaneously and consumed restart signal */
+      return 1;
+    }
+    /* woke spontaneously but did not consume restart---caller must resolve */
+    return 0;
+  }
+  /* woken due to restart signal */
+  return 1;
+}
+#endif /* __ASSUME_REALTIME_SIGNALS */
+
+void __pthread_restart_new(pthread_descr th)
+{
+  /* The barrier is proabably not needed, in which case it still documents
+     our assumptions. The intent is to commit previous writes to shared
+     memory so the woken thread will have a consistent view.  Complementary
+     read barriers are present to the suspend functions. */
+  WRITE_MEMORY_BARRIER();
+  kill(th->p_pid, __pthread_sig_restart);
+}
+
+/* There is no __pthread_suspend_new because it would just
+   be a wasteful wrapper for __pthread_wait_for_restart_signal */
+
+int
+__pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime)
+{
+  sigset_t unblock, initial_mask;
+  int was_signalled = 0;
+  sigjmp_buf jmpbuf;
+
+  if (sigsetjmp(jmpbuf, 1) == 0) {
+    THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
+    THREAD_SETMEM(self, p_signal, 0);
+    /* Unblock the restart signal */
+    sigemptyset(&unblock);
+    sigaddset(&unblock, __pthread_sig_restart);
+    sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
+
+    while (1) {
+      struct timeval now;
+      struct timespec reltime;
+
+      /* Compute a time offset relative to now.  */
+      __gettimeofday (&now, NULL);
+      reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+      reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+      if (reltime.tv_nsec < 0) {
+	reltime.tv_nsec += 1000000000;
+	reltime.tv_sec -= 1;
+      }
+
+      /* Sleep for the required duration. If woken by a signal,
+	 resume waiting as required by Single Unix Specification.  */
+      if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
+	break;
+    }
+
+    /* Block the restart signal again */
+    sigprocmask(SIG_SETMASK, &initial_mask, NULL);
+    was_signalled = 0;
+  } else {
+    was_signalled = 1;
+  }
+  THREAD_SETMEM(self, p_signal_jmp, NULL);
+
+  /* Now was_signalled is true if we exited the above code
+     due to the delivery of a restart signal.  In that case,
+     everything is cool. We have been removed from whatever
+     we were waiting on by the other thread, and consumed its signal.
+
+     Otherwise we this thread woke up spontaneously, or due to a signal other
+     than restart. This is an ambiguous case  that must be resolved by
+     the caller; the thread is still eligible for a restart wakeup
+     so there is a race. */
+
+  READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
+  return was_signalled;
+}
+
+
+/* Debugging aid */
+
+#ifdef DEBUG
+#include <stdarg.h>
+
+void __pthread_message(const char * fmt, ...)
+{
+  char buffer[1024];
+  va_list args;
+  sprintf(buffer, "%05d : ", __getpid());
+  va_start(args, fmt);
+  vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
+  va_end(args);
+  TEMP_FAILURE_RETRY(write_not_cancel(2, buffer, strlen(buffer)));
+}
+
+#endif
diff --git a/linuxthreads/pthread_atfork.c b/linuxthreads/pthread_atfork.c
new file mode 100644
index 0000000000..2464acb6b2
--- /dev/null
+++ b/linuxthreads/pthread_atfork.c
@@ -0,0 +1,63 @@
+/* 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.
+
+   In addition to the permissions in the GNU Lesser 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 GNU Lesser 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.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   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 "internals.h"
+#include <fork.h>
+
+/* This is defined by newer gcc version unique for each module.  */
+extern void *__dso_handle __attribute__ ((__weak__));
+
+
+/* Hide the symbol so that no definition but the one locally in the
+   executable or DSO is used.  */
+int
+#ifndef __pthread_atfork
+/* Don't mark the compatibility function as hidden.  */
+attribute_hidden
+#endif
+__pthread_atfork (prepare, parent, child)
+     void (*prepare) (void);
+     void (*parent) (void);
+     void (*child) (void);
+{
+  return __register_atfork (prepare, parent, child,
+			    &__dso_handle == NULL ? NULL : __dso_handle);
+}
+#ifndef __pthread_atfork
+extern int pthread_atfork (void (*prepare) (void), void (*parent) (void),
+			   void (*child) (void)) attribute_hidden;
+strong_alias (__pthread_atfork, pthread_atfork)
+#endif
diff --git a/linuxthreads/pthread_setegid.c b/linuxthreads/pthread_setegid.c
new file mode 100644
index 0000000000..9e16828fa5
--- /dev/null
+++ b/linuxthreads/pthread_setegid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setegid_np (gid_t gid)
+{
+  return setegid (gid);
+}
diff --git a/linuxthreads/pthread_seteuid.c b/linuxthreads/pthread_seteuid.c
new file mode 100644
index 0000000000..9d29d81118
--- /dev/null
+++ b/linuxthreads/pthread_seteuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_seteuid_np (uid_t uid)
+{
+  return seteuid (uid);
+}
diff --git a/linuxthreads/pthread_setgid.c b/linuxthreads/pthread_setgid.c
new file mode 100644
index 0000000000..db37dd1465
--- /dev/null
+++ b/linuxthreads/pthread_setgid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setgid_np (gid_t gid)
+{
+  return setgid (gid);
+}
diff --git a/linuxthreads/pthread_setregid.c b/linuxthreads/pthread_setregid.c
new file mode 100644
index 0000000000..bd75154c50
--- /dev/null
+++ b/linuxthreads/pthread_setregid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setregid_np (gid_t rgid, gid_t egid)
+{
+  return setregid (rgid, egid);
+}
diff --git a/linuxthreads/pthread_setresgid.c b/linuxthreads/pthread_setresgid.c
new file mode 100644
index 0000000000..b5702804ee
--- /dev/null
+++ b/linuxthreads/pthread_setresgid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid)
+{
+  return setresgid (rgid, egid, sgid);
+}
diff --git a/linuxthreads/pthread_setresuid.c b/linuxthreads/pthread_setresuid.c
new file mode 100644
index 0000000000..ceb724deaf
--- /dev/null
+++ b/linuxthreads/pthread_setresuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid)
+{
+  return setresuid (ruid, euid, suid);
+}
diff --git a/linuxthreads/pthread_setreuid.c b/linuxthreads/pthread_setreuid.c
new file mode 100644
index 0000000000..ae8933ece5
--- /dev/null
+++ b/linuxthreads/pthread_setreuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setreuid_np (uid_t ruid, uid_t euid)
+{
+  return setreuid (ruid, euid);
+}
diff --git a/linuxthreads/pthread_setuid.c b/linuxthreads/pthread_setuid.c
new file mode 100644
index 0000000000..f82ccc1a2f
--- /dev/null
+++ b/linuxthreads/pthread_setuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setuid_np (uid_t uid)
+{
+  return setuid (uid);
+}
diff --git a/linuxthreads/queue.h b/linuxthreads/queue.h
new file mode 100644
index 0000000000..28bd75531c
--- /dev/null
+++ b/linuxthreads/queue.h
@@ -0,0 +1,61 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Waiting queues */
+
+/* Waiting queues are represented by lists of thread descriptors
+   linked through their p_nextwaiting field.  The lists are kept
+   sorted by decreasing priority, and then decreasing waiting time. */
+
+static inline void enqueue(pthread_descr * q, pthread_descr th)
+{
+  int prio = th->p_priority;
+  ASSERT(th->p_nextwaiting == NULL);
+  for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
+    if (prio > (*q)->p_priority) {
+      th->p_nextwaiting = *q;
+      *q = th;
+      return;
+    }
+  }
+  *q = th;
+}
+
+static inline pthread_descr dequeue(pthread_descr * q)
+{
+  pthread_descr th;
+  th = *q;
+  if (th != NULL) {
+    *q = th->p_nextwaiting;
+    th->p_nextwaiting = NULL;
+  }
+  return th;
+}
+
+static inline int remove_from_queue(pthread_descr * q, pthread_descr th)
+{
+  for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
+    if (*q == th) {
+      *q = th->p_nextwaiting;
+      th->p_nextwaiting = NULL;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static inline int queue_is_empty(pthread_descr * q)
+{
+    return *q == NULL;
+}
diff --git a/linuxthreads/restart.h b/linuxthreads/restart.h
new file mode 100644
index 0000000000..24d9fab748
--- /dev/null
+++ b/linuxthreads/restart.h
@@ -0,0 +1,49 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#include <signal.h>
+#include <kernel-features.h>
+
+/* Primitives for controlling thread execution */
+
+static inline void restart(pthread_descr th)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  __pthread_restart_new(th);
+#else
+  __pthread_restart(th);
+#endif
+}
+
+static inline void suspend(pthread_descr self)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  __pthread_wait_for_restart_signal(self);
+#else
+  __pthread_suspend(self);
+#endif
+}
+
+static inline int timedsuspend(pthread_descr self,
+		const struct timespec *abstime)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  return __pthread_timedsuspend_new(self, abstime);
+#else
+  return __pthread_timedsuspend(self, abstime);
+#endif
+}
diff --git a/linuxthreads/rwlock.c b/linuxthreads/rwlock.c
new file mode 100644
index 0000000000..f565f18706
--- /dev/null
+++ b/linuxthreads/rwlock.c
@@ -0,0 +1,658 @@
+/* Read-write lock implementation.
+   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Xavier Leroy <Xavier.Leroy@inria.fr>
+   and Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   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 <bits/libc-lock.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include "internals.h"
+#include "queue.h"
+#include "spinlock.h"
+#include "restart.h"
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting inside pthread_rwlock_timedrdlock or pthread_rwlock_timedwrlock. */
+
+static int rwlock_rd_extricate_func(void *obj, pthread_descr th)
+{
+  pthread_rwlock_t *rwlock = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&rwlock->__rw_lock, NULL);
+  did_remove = remove_from_queue(&rwlock->__rw_read_waiting, th);
+  __pthread_unlock(&rwlock->__rw_lock);
+
+  return did_remove;
+}
+
+static int rwlock_wr_extricate_func(void *obj, pthread_descr th)
+{
+  pthread_rwlock_t *rwlock = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&rwlock->__rw_lock, NULL);
+  did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th);
+  __pthread_unlock(&rwlock->__rw_lock);
+
+  return did_remove;
+}
+
+/*
+ * Check whether the calling thread already owns one or more read locks on the
+ * specified lock. If so, return a pointer to the read lock info structure
+ * corresponding to that lock.
+ */
+
+static pthread_readlock_info *
+rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info *info;
+
+  for (info = THREAD_GETMEM (self, p_readlock_list); info != NULL;
+       info = info->pr_next)
+    {
+      if (info->pr_lock == rwlock)
+	return info;
+    }
+
+  return NULL;
+}
+
+/*
+ * Add a new lock to the thread's list of locks for which it has a read lock.
+ * A new info node must be allocated for this, which is taken from the thread's
+ * free list, or by calling malloc. If malloc fails, a null pointer is
+ * returned. Otherwise the lock info structure is initialized and pushed
+ * onto the thread's list.
+ */
+
+static pthread_readlock_info *
+rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info *info = THREAD_GETMEM (self, p_readlock_free);
+
+  if (info != NULL)
+    THREAD_SETMEM (self, p_readlock_free, info->pr_next);
+  else
+    info = malloc(sizeof *info);
+
+  if (info == NULL)
+    return NULL;
+
+  info->pr_lock_count = 1;
+  info->pr_lock = rwlock;
+  info->pr_next = THREAD_GETMEM (self, p_readlock_list);
+  THREAD_SETMEM (self, p_readlock_list, info);
+
+  return info;
+}
+
+/*
+ * If the thread owns a read lock over the given pthread_rwlock_t,
+ * and this read lock is tracked in the thread's lock list,
+ * this function returns a pointer to the info node in that list.
+ * It also decrements the lock count within that node, and if
+ * it reaches zero, it removes the node from the list.
+ * If nothing is found, it returns a null pointer.
+ */
+
+static pthread_readlock_info *
+rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info **pinfo;
+
+  for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next)
+    {
+      if ((*pinfo)->pr_lock == rwlock)
+	{
+	  pthread_readlock_info *info = *pinfo;
+	  if (--info->pr_lock_count == 0)
+	    *pinfo = info->pr_next;
+	  return info;
+	}
+    }
+
+  return NULL;
+}
+
+/*
+ * This function checks whether the conditions are right to place a read lock.
+ * It returns 1 if so, otherwise zero. The rwlock's internal lock must be
+ * locked upon entry.
+ */
+
+static int
+rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already)
+{
+  /* Can't readlock; it is write locked. */
+  if (rwlock->__rw_writer != NULL)
+    return 0;
+
+  /* Lock prefers readers; get it. */
+  if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
+    return 1;
+
+  /* Lock prefers writers, but none are waiting. */
+  if (queue_is_empty(&rwlock->__rw_write_waiting))
+    return 1;
+
+  /* Writers are waiting, but this thread already has a read lock */
+  if (have_lock_already)
+    return 1;
+
+  /* Writers are waiting, and this is a new lock */
+  return 0;
+}
+
+/*
+ * This function helps support brain-damaged recursive read locking
+ * semantics required by Unix 98, while maintaining write priority.
+ * This basically determines whether this thread already holds a read lock
+ * already. It returns 1 if so, otherwise it returns 0.
+ *
+ * If the thread has any ``untracked read locks'' then it just assumes
+ * that this lock is among them, just to be safe, and returns 1.
+ *
+ * Also, if it finds the thread's lock in the list, it sets the pointer
+ * referenced by pexisting to refer to the list entry.
+ *
+ * If the thread has no untracked locks, and the lock is not found
+ * in its list, then it is added to the list. If this fails,
+ * then *pout_of_mem is set to 1.
+ */
+
+static int
+rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock,
+    pthread_readlock_info **pexisting, int *pout_of_mem)
+{
+  pthread_readlock_info *existing = NULL;
+  int out_of_mem = 0, have_lock_already = 0;
+  pthread_descr self = *pself;
+
+  if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
+    {
+      if (!self)
+	*pself = self = thread_self();
+
+      existing = rwlock_is_in_list(self, rwlock);
+
+      if (existing != NULL
+	  || THREAD_GETMEM (self, p_untracked_readlock_count) > 0)
+	have_lock_already = 1;
+      else
+	{
+	  existing = rwlock_add_to_list(self, rwlock);
+	  if (existing == NULL)
+	    out_of_mem = 1;
+	}
+    }
+
+  *pout_of_mem = out_of_mem;
+  *pexisting = existing;
+
+  return have_lock_already;
+}
+
+int
+__pthread_rwlock_init (pthread_rwlock_t *rwlock,
+		       const pthread_rwlockattr_t *attr)
+{
+  __pthread_init_lock(&rwlock->__rw_lock);
+  rwlock->__rw_readers = 0;
+  rwlock->__rw_writer = NULL;
+  rwlock->__rw_read_waiting = NULL;
+  rwlock->__rw_write_waiting = NULL;
+
+  if (attr == NULL)
+    {
+      rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
+      rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE;
+    }
+  else
+    {
+      rwlock->__rw_kind = attr->__lockkind;
+      rwlock->__rw_pshared = attr->__pshared;
+    }
+
+  return 0;
+}
+strong_alias (__pthread_rwlock_init, pthread_rwlock_init)
+
+
+int
+__pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
+{
+  int readers;
+  _pthread_descr writer;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  readers = rwlock->__rw_readers;
+  writer = rwlock->__rw_writer;
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (readers > 0 || writer != NULL)
+    return EBUSY;
+
+  return 0;
+}
+strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy)
+
+int
+__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = NULL;
+  pthread_readlock_info *existing;
+  int out_of_mem, have_lock_already;
+
+  have_lock_already = rwlock_have_already(&self, rwlock,
+					  &existing, &out_of_mem);
+
+  if (self == NULL)
+    self = thread_self ();
+
+  for (;;)
+    {
+      __pthread_lock (&rwlock->__rw_lock, self);
+
+      if (rwlock_can_rdlock(rwlock, have_lock_already))
+	break;
+
+      enqueue (&rwlock->__rw_read_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      suspend (self); /* This is not a cancellation point */
+    }
+
+  ++rwlock->__rw_readers;
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (have_lock_already || out_of_mem)
+    {
+      if (existing != NULL)
+	++existing->pr_lock_count;
+      else
+	++self->p_untracked_readlock_count;
+    }
+
+  return 0;
+}
+strong_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock)
+
+int
+__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
+			      const struct timespec *abstime)
+{
+  pthread_descr self = NULL;
+  pthread_readlock_info *existing;
+  int out_of_mem, have_lock_already;
+  pthread_extricate_if extr;
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  have_lock_already = rwlock_have_already(&self, rwlock,
+					  &existing, &out_of_mem);
+
+  if (self == NULL)
+    self = thread_self ();
+
+  /* Set up extrication interface */
+  extr.pu_object = rwlock;
+  extr.pu_extricate_func = rwlock_rd_extricate_func;
+
+  /* Register extrication interface */
+  __pthread_set_own_extricate_if (self, &extr);
+
+  for (;;)
+    {
+      __pthread_lock (&rwlock->__rw_lock, self);
+
+      if (rwlock_can_rdlock(rwlock, have_lock_already))
+	break;
+
+      enqueue (&rwlock->__rw_read_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      /* This is not a cancellation point */
+      if (timedsuspend (self, abstime) == 0)
+	{
+	  int was_on_queue;
+
+	  __pthread_lock (&rwlock->__rw_lock, self);
+	  was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self);
+	  __pthread_unlock (&rwlock->__rw_lock);
+
+	  if (was_on_queue)
+	    {
+	      __pthread_set_own_extricate_if (self, 0);
+	      return ETIMEDOUT;
+	    }
+
+	  /* Eat the outstanding restart() from the signaller */
+	  suspend (self);
+	}
+    }
+
+  __pthread_set_own_extricate_if (self, 0);
+
+  ++rwlock->__rw_readers;
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (have_lock_already || out_of_mem)
+    {
+      if (existing != NULL)
+	++existing->pr_lock_count;
+      else
+	++self->p_untracked_readlock_count;
+    }
+
+  return 0;
+}
+strong_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock)
+
+int
+__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = thread_self();
+  pthread_readlock_info *existing;
+  int out_of_mem, have_lock_already;
+  int retval = EBUSY;
+
+  have_lock_already = rwlock_have_already(&self, rwlock,
+      &existing, &out_of_mem);
+
+  __pthread_lock (&rwlock->__rw_lock, self);
+
+  /* 0 is passed to here instead of have_lock_already.
+     This is to meet Single Unix Spec requirements:
+     if writers are waiting, pthread_rwlock_tryrdlock
+     does not acquire a read lock, even if the caller has
+     one or more read locks already. */
+
+  if (rwlock_can_rdlock(rwlock, 0))
+    {
+      ++rwlock->__rw_readers;
+      retval = 0;
+    }
+
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (retval == 0)
+    {
+      if (have_lock_already || out_of_mem)
+	{
+	  if (existing != NULL)
+	    ++existing->pr_lock_count;
+	  else
+	    ++self->p_untracked_readlock_count;
+	}
+    }
+
+  return retval;
+}
+strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock)
+
+
+int
+__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = thread_self ();
+
+  while(1)
+    {
+      __pthread_lock (&rwlock->__rw_lock, self);
+      if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+	{
+	  rwlock->__rw_writer = self;
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return 0;
+	}
+
+      /* Suspend ourselves, then try again */
+      enqueue (&rwlock->__rw_write_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      suspend (self); /* This is not a cancellation point */
+    }
+}
+strong_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock)
+
+
+int
+__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
+			      const struct timespec *abstime)
+{
+  pthread_descr self;
+  pthread_extricate_if extr;
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  self = thread_self ();
+
+  /* Set up extrication interface */
+  extr.pu_object = rwlock;
+  extr.pu_extricate_func =  rwlock_wr_extricate_func;
+
+  /* Register extrication interface */
+  __pthread_set_own_extricate_if (self, &extr);
+
+  while(1)
+    {
+      __pthread_lock (&rwlock->__rw_lock, self);
+
+      if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+	{
+	  rwlock->__rw_writer = self;
+	  __pthread_set_own_extricate_if (self, 0);
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return 0;
+	}
+
+      /* Suspend ourselves, then try again */
+      enqueue (&rwlock->__rw_write_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      /* This is not a cancellation point */
+      if (timedsuspend (self, abstime) == 0)
+	{
+	  int was_on_queue;
+
+	  __pthread_lock (&rwlock->__rw_lock, self);
+	  was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self);
+	  __pthread_unlock (&rwlock->__rw_lock);
+
+	  if (was_on_queue)
+	    {
+	      __pthread_set_own_extricate_if (self, 0);
+	      return ETIMEDOUT;
+	    }
+
+	  /* Eat the outstanding restart() from the signaller */
+	  suspend (self);
+	}
+    }
+}
+strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock)
+
+
+int
+__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
+{
+  int result = EBUSY;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+    {
+      rwlock->__rw_writer = thread_self ();
+      result = 0;
+    }
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  return result;
+}
+strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock)
+
+
+int
+__pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr torestart;
+  pthread_descr th;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  if (rwlock->__rw_writer != NULL)
+    {
+      /* Unlocking a write lock.  */
+      if (rwlock->__rw_writer != thread_self ())
+	{
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return EPERM;
+	}
+      rwlock->__rw_writer = NULL;
+
+      if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+	   && !queue_is_empty(&rwlock->__rw_read_waiting))
+	  || (th = dequeue(&rwlock->__rw_write_waiting)) == NULL)
+	{
+	  /* Restart all waiting readers.  */
+	  torestart = rwlock->__rw_read_waiting;
+	  rwlock->__rw_read_waiting = NULL;
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  while ((th = dequeue (&torestart)) != NULL)
+	    restart (th);
+	}
+      else
+	{
+	  /* Restart one waiting writer.  */
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  restart (th);
+	}
+    }
+  else
+    {
+      /* Unlocking a read lock.  */
+      if (rwlock->__rw_readers == 0)
+	{
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return EPERM;
+	}
+
+      --rwlock->__rw_readers;
+      if (rwlock->__rw_readers == 0)
+	/* Restart one waiting writer, if any.  */
+	th = dequeue (&rwlock->__rw_write_waiting);
+      else
+	th = NULL;
+
+      __pthread_unlock (&rwlock->__rw_lock);
+      if (th != NULL)
+	restart (th);
+
+      /* Recursive lock fixup */
+
+      if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
+	{
+	  pthread_descr self = thread_self();
+	  pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock);
+
+	  if (victim != NULL)
+	    {
+	      if (victim->pr_lock_count == 0)
+		{
+		  victim->pr_next = THREAD_GETMEM (self, p_readlock_free);
+		  THREAD_SETMEM (self, p_readlock_free, victim);
+		}
+	    }
+	  else
+	    {
+	      int val = THREAD_GETMEM (self, p_untracked_readlock_count);
+	      if (val > 0)
+		THREAD_SETMEM (self, p_untracked_readlock_count, val - 1);
+	    }
+	}
+    }
+
+  return 0;
+}
+strong_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock)
+
+
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
+{
+  attr->__lockkind = 0;
+  attr->__pshared = PTHREAD_PROCESS_PRIVATE;
+
+  return 0;
+}
+
+
+int
+__pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
+{
+  return 0;
+}
+strong_alias (__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy)
+
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
+{
+  *pshared = attr->__pshared;
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  attr->__pshared = pshared;
+
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref)
+{
+  *pref = attr->__lockkind;
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref)
+{
+  if (pref != PTHREAD_RWLOCK_PREFER_READER_NP
+      && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP
+      && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
+      && pref != PTHREAD_RWLOCK_DEFAULT_NP)
+    return EINVAL;
+
+  attr->__lockkind = pref;
+
+  return 0;
+}
diff --git a/linuxthreads/semaphore.c b/linuxthreads/semaphore.c
new file mode 100644
index 0000000000..017539e176
--- /dev/null
+++ b/linuxthreads/semaphore.c
@@ -0,0 +1,307 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Semaphores a la POSIX 1003.1b */
+
+#include <errno.h>
+#include "pthread.h"
+#include "semaphore.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "queue.h"
+#include <shlib-compat.h>
+#include <not-cancel.h>
+
+int __new_sem_init(sem_t *sem, int pshared, unsigned int value)
+{
+  if (value > SEM_VALUE_MAX) {
+    errno = EINVAL;
+    return -1;
+  }
+  if (pshared) {
+    errno = ENOSYS;
+    return -1;
+  }
+  __pthread_init_lock(&sem->__sem_lock);
+  sem->__sem_value = value;
+  sem->__sem_waiting = NULL;
+  return 0;
+}
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting inside __new_sem_wait. */
+
+static int new_sem_extricate_func(void *obj, pthread_descr th)
+{
+  volatile pthread_descr self = thread_self();
+  sem_t *sem = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  did_remove = remove_from_queue(&sem->__sem_waiting, th);
+  __pthread_unlock(&sem->__sem_lock);
+
+  return did_remove;
+}
+
+int __new_sem_wait(sem_t * sem)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  /* Set up extrication interface */
+  extr.pu_object = sem;
+  extr.pu_extricate_func = new_sem_extricate_func;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  if (sem->__sem_value > 0) {
+    sem->__sem_value--;
+    __pthread_unlock(&sem->__sem_lock);
+    return 0;
+  }
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+  /* Enqueue only if not already cancelled. */
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&sem->__sem_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&sem->__sem_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Wait for sem_post or cancellation, or fall through if already canceled */
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      suspend(self);
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* Terminate only if the wakeup came from cancellation. */
+  /* Otherwise ignore cancellation because we got the semaphore. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+  /* We got the semaphore */
+  return 0;
+}
+
+int __new_sem_trywait(sem_t * sem)
+{
+  int retval;
+
+  __pthread_lock(&sem->__sem_lock, NULL);
+  if (sem->__sem_value == 0) {
+    errno = EAGAIN;
+    retval = -1;
+  } else {
+    sem->__sem_value--;
+    retval = 0;
+  }
+  __pthread_unlock(&sem->__sem_lock);
+  return retval;
+}
+
+int __new_sem_post(sem_t * sem)
+{
+  pthread_descr self = thread_self();
+  pthread_descr th;
+  struct pthread_request request;
+
+  if (THREAD_GETMEM(self, p_in_sighandler) == NULL) {
+    __pthread_lock(&sem->__sem_lock, self);
+    if (sem->__sem_waiting == NULL) {
+      if (sem->__sem_value >= SEM_VALUE_MAX) {
+        /* Overflow */
+        errno = ERANGE;
+        __pthread_unlock(&sem->__sem_lock);
+        return -1;
+      }
+      sem->__sem_value++;
+      __pthread_unlock(&sem->__sem_lock);
+    } else {
+      th = dequeue(&sem->__sem_waiting);
+      __pthread_unlock(&sem->__sem_lock);
+      th->p_sem_avail = 1;
+      WRITE_MEMORY_BARRIER();
+      restart(th);
+    }
+  } else {
+    /* If we're in signal handler, delegate post operation to
+       the thread manager. */
+    if (__pthread_manager_request < 0) {
+      if (__pthread_initialize_manager() < 0) {
+        errno = EAGAIN;
+        return -1;
+      }
+    }
+    request.req_kind = REQ_POST;
+    request.req_args.post = sem;
+    TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					(char *) &request, sizeof(request)));
+  }
+  return 0;
+}
+
+int __new_sem_getvalue(sem_t * sem, int * sval)
+{
+  *sval = sem->__sem_value;
+  return 0;
+}
+
+int __new_sem_destroy(sem_t * sem)
+{
+  if (sem->__sem_waiting != NULL) {
+    __set_errno (EBUSY);
+    return -1;
+  }
+  return 0;
+}
+
+sem_t *sem_open(const char *name, int oflag, ...)
+{
+  __set_errno (ENOSYS);
+  return SEM_FAILED;
+}
+
+int sem_close(sem_t *sem)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+int sem_unlink(const char *name)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+int sem_timedwait(sem_t *sem, const struct timespec *abstime)
+{
+  pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  if (sem->__sem_value > 0) {
+    --sem->__sem_value;
+    __pthread_unlock(&sem->__sem_lock);
+    return 0;
+  }
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {
+    /* The standard requires that if the function would block and the
+       time value is illegal, the function returns with an error.  */
+    __pthread_unlock(&sem->__sem_lock);
+    __set_errno (EINVAL);
+    return -1;
+  }
+
+  /* Set up extrication interface */
+  extr.pu_object = sem;
+  extr.pu_extricate_func = new_sem_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+  /* Enqueue only if not already cancelled. */
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&sem->__sem_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&sem->__sem_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      if (timedsuspend(self, abstime) == 0) {
+	int was_on_queue;
+
+	/* __pthread_lock will queue back any spurious restarts that
+	   may happen to it. */
+
+	__pthread_lock(&sem->__sem_lock, self);
+	was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
+	__pthread_unlock(&sem->__sem_lock);
+
+	if (was_on_queue) {
+	  __pthread_set_own_extricate_if(self, 0);
+	  __set_errno (ETIMEDOUT);
+	  return -1;
+	}
+
+	/* Eat the outstanding restart() from the signaller */
+	suspend(self);
+      }
+
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+ __pthread_set_own_extricate_if(self, 0);
+
+  /* Terminate only if the wakeup came from cancellation. */
+  /* Otherwise ignore cancellation because we got the semaphore. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+  /* We got the semaphore */
+  return 0;
+}
+
+
+versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
+versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
+versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
+versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1);
+versioned_symbol (libpthread, __new_sem_destroy, sem_destroy, GLIBC_2_1);
diff --git a/linuxthreads/semaphore.h b/linuxthreads/semaphore.h
new file mode 100644
index 0000000000..8407007d0b
--- /dev/null
+++ b/linuxthreads/semaphore.h
@@ -0,0 +1,87 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#ifndef _SEMAPHORE_H
+#define _SEMAPHORE_H    1
+
+#include <features.h>
+#include <sys/types.h>
+#ifdef __USE_XOPEN2K
+# define __need_timespec
+# include <time.h>
+#endif
+
+#ifndef _PTHREAD_DESCR_DEFINED
+/* Thread descriptors.  Needed for `sem_t' definition.  */
+typedef struct _pthread_descr_struct *_pthread_descr;
+# define _PTHREAD_DESCR_DEFINED
+#endif
+
+/* System specific semaphore definition.  */
+typedef struct
+{
+  struct _pthread_fastlock __sem_lock;
+  int __sem_value;
+  _pthread_descr __sem_waiting;
+} sem_t;
+
+
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED	((sem_t *) 0)
+
+/* Maximum value the semaphore can have.  */
+#define SEM_VALUE_MAX 	(2147483647)
+
+
+__BEGIN_DECLS
+
+/* Initialize semaphore object SEM to VALUE.  If PSHARED then share it
+   with other processes.  */
+extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW;
+
+/* Free resources associated with semaphore object SEM.  */
+extern int sem_destroy (sem_t *__sem) __THROW;
+
+/* Open a named semaphore NAME with open flaot OFLAG.  */
+extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW;
+
+/* Close descriptor for named semaphore SEM.  */
+extern int sem_close (sem_t *__sem) __THROW;
+
+/* Remove named semaphore NAME.  */
+extern int sem_unlink (__const char *__name) __THROW;
+
+/* Wait for SEM being posted.  */
+extern int sem_wait (sem_t *__sem);
+
+#ifdef __USE_XOPEN2K
+/* Similar to `sem_wait' but wait only until ABSTIME.  */
+extern int sem_timedwait (sem_t *__restrict __sem,
+			  __const struct timespec *__restrict __abstime);
+#endif
+
+/* Test whether SEM is posted.  */
+extern int sem_trywait (sem_t *__sem) __THROW;
+
+/* Post SEM.  */
+extern int sem_post (sem_t *__sem) __THROW;
+
+/* Get current value of SEM and store it in *SVAL.  */
+extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
+     __THROW;
+
+__END_DECLS
+
+#endif  /* semaphore.h */
diff --git a/linuxthreads/shlib-versions b/linuxthreads/shlib-versions
new file mode 100644
index 0000000000..58488ce65c
--- /dev/null
+++ b/linuxthreads/shlib-versions
@@ -0,0 +1,11 @@
+# Xavier Leroy's Linux clone based thread library.
+mips.*-.*-linux.*	libpthread=0		GLIBC_2.0 GLIBC_2.2
+sparc64-.*-linux.*	libpthread=0		GLIBC_2.2
+sh.*-.*-linux.*		libpthread=0		GLIBC_2.2
+ia64.*-.*-linux.*	libpthread=0		GLIBC_2.2
+hppa.*-.*-linux.*	libpthread=0		GLIBC_2.2
+s390x-.*-linux.*	libpthread=0		GLIBC_2.2
+cris-.*-linux.*		libpthread=0		GLIBC_2.2
+x86_64-.*-linux.*	libpthread=0		GLIBC_2.2.5
+powerpc64-.*-linux.*	libpthread=0		GLIBC_2.3
+.*-.*-linux.*		libpthread=0
diff --git a/linuxthreads/sighandler.c b/linuxthreads/sighandler.c
new file mode 100644
index 0000000000..9dd3e228f6
--- /dev/null
+++ b/linuxthreads/sighandler.c
@@ -0,0 +1,71 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Signal handlers */
+
+#include "internals.h"
+
+
+/* The wrapper around user-provided signal handlers */
+void __pthread_sighandler(int signo, SIGCONTEXT ctx)
+{
+  pthread_descr self;
+  char * in_sighandler;
+  self = check_thread_self();
+
+  /* If we're in a sigwait operation, just record the signal received
+     and return without calling the user's handler */
+  if (THREAD_GETMEM(self, p_sigwaiting)) {
+    THREAD_SETMEM(self, p_sigwaiting, 0);
+    THREAD_SETMEM(self, p_signal, signo);
+    return;
+  }
+  /* Record that we're in a signal handler and call the user's
+     handler function */
+  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
+  CALL_SIGHANDLER(__sighandler[signo].old, signo, ctx);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, NULL);
+}
+
+/* The same, this time for real-time signals.  */
+void __pthread_sighandler_rt(int signo, struct siginfo *si,
+			     struct ucontext *uc)
+{
+  pthread_descr self;
+  char * in_sighandler;
+  self = check_thread_self();
+
+  /* If we're in a sigwait operation, just record the signal received
+     and return without calling the user's handler */
+  if (THREAD_GETMEM(self, p_sigwaiting)) {
+    THREAD_SETMEM(self, p_sigwaiting, 0);
+    THREAD_SETMEM(self, p_signal, signo);
+    return;
+  }
+  /* Record that we're in a signal handler and call the user's
+     handler function */
+  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
+  __sighandler[signo].rt(signo, si, uc);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, NULL);
+}
+
+
+/* A signal handler that does nothing */
+void __pthread_null_sighandler(int sig) { }
diff --git a/linuxthreads/signals.c b/linuxthreads/signals.c
new file mode 100644
index 0000000000..50f55995a3
--- /dev/null
+++ b/linuxthreads/signals.c
@@ -0,0 +1,213 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Handling of signals */
+
+#include <errno.h>
+#include <signal.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include <ucontext.h>
+
+
+int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask)
+{
+  sigset_t mask;
+
+  if (newmask != NULL) {
+    mask = *newmask;
+    /* Don't allow __pthread_sig_restart to be unmasked.
+       Don't allow __pthread_sig_cancel to be masked. */
+    switch(how) {
+    case SIG_SETMASK:
+      sigaddset(&mask, __pthread_sig_restart);
+      sigdelset(&mask, __pthread_sig_cancel);
+      if (__pthread_sig_debug > 0)
+	sigdelset(&mask, __pthread_sig_debug);
+      break;
+    case SIG_BLOCK:
+      sigdelset(&mask, __pthread_sig_cancel);
+      if (__pthread_sig_debug > 0)
+	sigdelset(&mask, __pthread_sig_debug);
+      break;
+    case SIG_UNBLOCK:
+      sigdelset(&mask, __pthread_sig_restart);
+      break;
+    }
+    newmask = &mask;
+  }
+  if (sigprocmask(how, newmask, oldmask) == -1)
+    return errno;
+  else
+    return 0;
+}
+
+int pthread_kill(pthread_t thread, int signo)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  pid = handle->h_descr->p_pid;
+  __pthread_unlock(&handle->h_lock);
+  if (kill(pid, signo) == -1)
+    return errno;
+  else
+    return 0;
+}
+
+union sighandler __sighandler[NSIG] =
+  { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } };
+
+/* The wrapper around sigaction.  Install our own signal handler
+   around the signal. */
+int __pthread_sigaction(int sig, const struct sigaction * act,
+			struct sigaction * oact)
+{
+  struct sigaction newact;
+  struct sigaction *newactp;
+  __sighandler_t old = SIG_DFL;
+
+  if (sig == __pthread_sig_restart ||
+      sig == __pthread_sig_cancel ||
+      (sig == __pthread_sig_debug && __pthread_sig_debug > 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+  if (sig > 0 && sig < NSIG)
+    old = (__sighandler_t) __sighandler[sig].old;
+  if (act)
+    {
+      newact = *act;
+      if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
+	  && sig > 0 && sig < NSIG)
+	{
+	  if (act->sa_flags & SA_SIGINFO)
+	    newact.sa_handler = (__sighandler_t) __pthread_sighandler_rt;
+	  else
+	    newact.sa_handler = (__sighandler_t) __pthread_sighandler;
+	  if (old == SIG_IGN || old == SIG_DFL || old == SIG_ERR)
+	    __sighandler[sig].old = (arch_sighandler_t) act->sa_handler;
+	}
+      newactp = &newact;
+    }
+  else
+    newactp = NULL;
+  if (__libc_sigaction(sig, newactp, oact) == -1)
+    {
+      if (act)
+	__sighandler[sig].old = (arch_sighandler_t) old;
+      return -1;
+    }
+  if (sig > 0 && sig < NSIG)
+    {
+      if (oact != NULL
+	  /* We may have inherited SIG_IGN from the parent, so return the
+	     kernel's idea of the signal handler the first time
+	     through.  */
+	  && old != SIG_ERR)
+	oact->sa_handler = old;
+      if (act)
+	/* For the assignment it does not matter whether it's a normal
+	   or real-time signal.  */
+	__sighandler[sig].old = (arch_sighandler_t) act->sa_handler;
+    }
+  return 0;
+}
+#ifdef SHARED
+strong_alias(__pthread_sigaction, __sigaction)
+strong_alias(__pthread_sigaction, sigaction)
+#endif
+
+/* sigwait -- synchronously wait for a signal */
+int __pthread_sigwait(const sigset_t * set, int * sig)
+{
+  volatile pthread_descr self = thread_self();
+  sigset_t mask;
+  int s;
+  sigjmp_buf jmpbuf;
+  struct sigaction sa;
+
+  /* Get ready to block all signals except those in set
+     and the cancellation signal.
+     Also check that handlers are installed on all signals in set,
+     and if not, install our dummy handler.  This is conformant to
+     POSIX: "The effect of sigwait() on the signal actions for the
+     signals in set is unspecified." */
+  sigfillset(&mask);
+  sigdelset(&mask, __pthread_sig_cancel);
+  for (s = 1; s < NSIG; s++) {
+    if (sigismember(set, s) &&
+        s != __pthread_sig_restart &&
+        s != __pthread_sig_cancel &&
+        s != __pthread_sig_debug) {
+      sigdelset(&mask, s);
+      if (__sighandler[s].old == (arch_sighandler_t) SIG_ERR ||
+          __sighandler[s].old == (arch_sighandler_t) SIG_DFL ||
+          __sighandler[s].old == (arch_sighandler_t) SIG_IGN) {
+        sa.sa_handler = __pthread_null_sighandler;
+        sigfillset(&sa.sa_mask);
+        sa.sa_flags = 0;
+        sigaction(s, &sa, NULL);
+      }
+    }
+  }
+  /* Test for cancellation */
+  if (sigsetjmp(jmpbuf, 1) == 0) {
+    THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf);
+    if (! (THREAD_GETMEM(self, p_canceled)
+	   && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) {
+      /* Reset the signal count */
+      THREAD_SETMEM(self, p_signal, 0);
+      /* Say we're in sigwait */
+      THREAD_SETMEM(self, p_sigwaiting, 1);
+      /* Unblock the signals and wait for them */
+      sigsuspend(&mask);
+    }
+  }
+  THREAD_SETMEM(self, p_cancel_jmp, NULL);
+  /* The signals are now reblocked.  Check for cancellation */
+  pthread_testcancel();
+  /* We should have self->p_signal != 0 and equal to the signal received */
+  *sig = THREAD_GETMEM(self, p_signal);
+  return 0;
+}
+#ifdef SHARED
+strong_alias (__pthread_sigwait, sigwait)
+#endif
+
+/* Redefine raise() to send signal to calling thread only,
+   as per POSIX 1003.1c */
+int __pthread_raise (int sig)
+{
+  int retcode = pthread_kill(pthread_self(), sig);
+  if (retcode == 0)
+    return 0;
+  else {
+    errno = retcode;
+    return -1;
+  }
+}
+#ifdef SHARED
+strong_alias (__pthread_raise, raise)
+#endif
+
+/* This files handles cancellation internally.  */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/specific.c b/linuxthreads/specific.c
new file mode 100644
index 0000000000..f54fabaeb9
--- /dev/null
+++ b/linuxthreads/specific.c
@@ -0,0 +1,235 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Thread-specific data */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include <bits/libc-lock.h>
+#include <not-cancel.h>
+
+/* Table of keys. */
+
+static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] =
+  { { 0, NULL } };
+
+/* For debugging purposes put the maximum number of keys in a variable.  */
+const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX;
+const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE;
+
+/* Mutex to protect access to pthread_keys */
+
+static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Create a new key */
+
+int __pthread_key_create(pthread_key_t * key, destr_function destr)
+{
+  int i;
+
+  pthread_mutex_lock(&pthread_keys_mutex);
+  for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
+    if (! pthread_keys[i].in_use) {
+      /* Mark key in use */
+      pthread_keys[i].in_use = 1;
+      pthread_keys[i].destr = destr;
+      pthread_mutex_unlock(&pthread_keys_mutex);
+      *key = i;
+      return 0;
+    }
+  }
+  pthread_mutex_unlock(&pthread_keys_mutex);
+  return EAGAIN;
+}
+strong_alias (__pthread_key_create, pthread_key_create)
+
+/* Reset deleted key's value to NULL in each live thread.
+ * NOTE: this executes in the context of the thread manager! */
+
+struct pthread_key_delete_helper_args {
+  /* Damn, we need lexical closures in C! ;) */
+  unsigned int idx1st, idx2nd;
+  pthread_descr self;
+};
+
+static void pthread_key_delete_helper(void *arg, pthread_descr th)
+{
+  struct pthread_key_delete_helper_args *args = arg;
+  unsigned int idx1st = args->idx1st;
+  unsigned int idx2nd = args->idx2nd;
+  pthread_descr self = args->self;
+
+  if (self == 0)
+    self = args->self = thread_self();
+
+  if (!th->p_terminated) {
+    /* pthread_exit() may try to free th->p_specific[idx1st] concurrently. */
+    __pthread_lock(th->p_lock, self);
+    if (th->p_specific[idx1st] != NULL)
+      th->p_specific[idx1st][idx2nd] = NULL;
+    __pthread_unlock(th->p_lock);
+  }
+}
+
+/* Delete a key */
+int pthread_key_delete(pthread_key_t key)
+{
+  pthread_descr self = thread_self();
+
+  pthread_mutex_lock(&pthread_keys_mutex);
+  if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) {
+    pthread_mutex_unlock(&pthread_keys_mutex);
+    return EINVAL;
+  }
+  pthread_keys[key].in_use = 0;
+  pthread_keys[key].destr = NULL;
+
+  /* Set the value of the key to NULL in all running threads, so
+     that if the key is reallocated later by pthread_key_create, its
+     associated values will be NULL in all threads.
+
+     Do nothing if no threads have been created yet.  */
+
+  if (__pthread_manager_request != -1)
+    {
+      struct pthread_key_delete_helper_args args;
+      struct pthread_request request;
+
+      args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+      args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+      args.self = 0;
+
+      request.req_thread = self;
+      request.req_kind = REQ_FOR_EACH_THREAD;
+      request.req_args.for_each.arg = &args;
+      request.req_args.for_each.fn = pthread_key_delete_helper;
+
+      TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request,
+					  (char *) &request, sizeof(request)));
+      suspend(self);
+    }
+
+  pthread_mutex_unlock(&pthread_keys_mutex);
+  return 0;
+}
+
+/* Set the value of a key */
+
+int __pthread_setspecific(pthread_key_t key, const void * pointer)
+{
+  pthread_descr self = thread_self();
+  unsigned int idx1st, idx2nd;
+
+  if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use)
+    return EINVAL;
+  idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+  idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+  if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) {
+    void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
+    if (newp == NULL)
+      return ENOMEM;
+    THREAD_SETMEM_NC(self, p_specific[idx1st], newp);
+  }
+  THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer;
+  return 0;
+}
+strong_alias (__pthread_setspecific, pthread_setspecific)
+
+/* Get the value of a key */
+
+void * __pthread_getspecific(pthread_key_t key)
+{
+  pthread_descr self = thread_self();
+  unsigned int idx1st, idx2nd;
+
+  if (key >= PTHREAD_KEYS_MAX)
+    return NULL;
+  idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+  idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+  if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL
+      || !pthread_keys[key].in_use)
+    return NULL;
+  return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd];
+}
+strong_alias (__pthread_getspecific, pthread_getspecific)
+
+/* Call the destruction routines on all keys */
+
+void __pthread_destroy_specifics()
+{
+  pthread_descr self = thread_self();
+  int i, j, round, found_nonzero;
+  destr_function destr;
+  void * data;
+
+  for (round = 0, found_nonzero = 1;
+       found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
+       round++) {
+    found_nonzero = 0;
+    for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
+      if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL)
+        for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) {
+          destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr;
+          data = THREAD_GETMEM_NC(self, p_specific[i])[j];
+          if (destr != NULL && data != NULL) {
+            THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL;
+            destr(data);
+            found_nonzero = 1;
+          }
+        }
+  }
+  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
+  for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
+    if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
+      free(THREAD_GETMEM_NC(self, p_specific[i]));
+      THREAD_SETMEM_NC(self, p_specific[i], NULL);
+    }
+  }
+  __pthread_unlock(THREAD_GETMEM(self, p_lock));
+}
+
+#if !(USE_TLS && HAVE___THREAD)
+
+/* Thread-specific data for libc. */
+
+int
+__pthread_internal_tsd_set (int key, const void * pointer)
+{
+  pthread_descr self = thread_self();
+
+  THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer);
+  return 0;
+}
+
+void *
+__pthread_internal_tsd_get (int key)
+{
+  pthread_descr self = thread_self();
+
+  return THREAD_GETMEM_NC(self, p_libc_specific[key]);
+}
+
+void ** __attribute__ ((__const__))
+__pthread_internal_tsd_address (int key)
+{
+  pthread_descr self = thread_self();
+  return &self->p_libc_specific[key];
+}
+
+#endif
diff --git a/linuxthreads/spinlock.c b/linuxthreads/spinlock.c
new file mode 100644
index 0000000000..08fff082ef
--- /dev/null
+++ b/linuxthreads/spinlock.c
@@ -0,0 +1,720 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Internal locks */
+
+#include <errno.h>
+#include <sched.h>
+#include <time.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+
+static void __pthread_acquire(int * spinlock);
+
+static inline void __pthread_release(int * spinlock)
+{
+  WRITE_MEMORY_BARRIER();
+  *spinlock = __LT_SPINLOCK_INIT;
+  __asm __volatile ("" : "=m" (*spinlock) : "m" (*spinlock));
+}
+
+
+/* The status field of a spinlock is a pointer whose least significant
+   bit is a locked flag.
+
+   Thus the field values have the following meanings:
+
+   status == 0:       spinlock is free
+   status == 1:       spinlock is taken; no thread is waiting on it
+
+   (status & 1) == 1: spinlock is taken and (status & ~1L) is a
+                      pointer to the first waiting thread; other
+		      waiting threads are linked via the p_nextlock
+		      field.
+   (status & 1) == 0: same as above, but spinlock is not taken.
+
+   The waiting list is not sorted by priority order.
+   Actually, we always insert at top of list (sole insertion mode
+   that can be performed without locking).
+   For __pthread_unlock, we perform a linear search in the list
+   to find the highest-priority, oldest waiting thread.
+   This is safe because there are no concurrent __pthread_unlock
+   operations -- only the thread that locked the mutex can unlock it. */
+
+
+void internal_function __pthread_lock(struct _pthread_fastlock * lock,
+				      pthread_descr self)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus, newstatus;
+  int successful_seizure, spurious_wakeup_count;
+  int spin_count;
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+    return;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  /* First try it without preparation.  Maybe it's a completely
+     uncontested lock.  */
+  if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1))
+    return;
+
+  spurious_wakeup_count = 0;
+  spin_count = 0;
+
+  /* On SMP, try spinning to get the lock. */
+
+  if (__pthread_smp_kernel) {
+    int max_count = lock->__spinlock * 2 + 10;
+
+    if (max_count > MAX_ADAPTIVE_SPIN_COUNT)
+      max_count = MAX_ADAPTIVE_SPIN_COUNT;
+
+    for (spin_count = 0; spin_count < max_count; spin_count++) {
+      if (((oldstatus = lock->__status) & 1) == 0) {
+	if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
+	{
+	  if (spin_count)
+	    lock->__spinlock += (spin_count - lock->__spinlock) / 8;
+	  READ_MEMORY_BARRIER();
+	  return;
+	}
+      }
+#ifdef BUSY_WAIT_NOP
+      BUSY_WAIT_NOP;
+#endif
+      __asm __volatile ("" : "=m" (lock->__status) : "m" (lock->__status));
+    }
+
+    lock->__spinlock += (spin_count - lock->__spinlock) / 8;
+  }
+
+again:
+
+  /* No luck, try once more or suspend. */
+
+  do {
+    oldstatus = lock->__status;
+    successful_seizure = 0;
+
+    if ((oldstatus & 1) == 0) {
+      newstatus = oldstatus | 1;
+      successful_seizure = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      newstatus = (long) self | 1;
+    }
+
+    if (self != NULL) {
+      THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus));
+      /* Make sure the store in p_nextlock completes before performing
+         the compare-and-swap */
+      MEMORY_BARRIER();
+    }
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+
+  /* Suspend with guard against spurious wakeup.
+     This can happen in pthread_cond_timedwait_relative, when the thread
+     wakes up due to timeout and is still on the condvar queue, and then
+     locks the queue to remove itself. At that point it may still be on the
+     queue, and may be resumed by a condition signal. */
+
+  if (!successful_seizure) {
+    for (;;) {
+      suspend(self);
+      if (self->p_nextlock != NULL) {
+	/* Count resumes that don't belong to us. */
+	spurious_wakeup_count++;
+	continue;
+      }
+      break;
+    }
+    goto again;
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  READ_MEMORY_BARRIER();
+#endif
+}
+
+int __pthread_unlock(struct _pthread_fastlock * lock)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus;
+  pthread_descr thr, * ptr, * maxptr;
+  int maxprio;
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_release(&lock->__spinlock);
+    return 0;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  WRITE_MEMORY_BARRIER();
+
+again:
+  while ((oldstatus = lock->__status) == 1) {
+    if (__compare_and_swap_with_release_semantics(&lock->__status,
+	oldstatus, 0))
+      return 0;
+  }
+
+  /* Find thread in waiting queue with maximal priority */
+  ptr = (pthread_descr *) &lock->__status;
+  thr = (pthread_descr) (oldstatus & ~1L);
+  maxprio = 0;
+  maxptr = ptr;
+
+  /* Before we iterate over the wait queue, we need to execute
+     a read barrier, otherwise we may read stale contents of nodes that may
+     just have been inserted by other processors. One read barrier is enough to
+     ensure we have a stable list; we don't need one for each pointer chase
+     through the list, because we are the owner of the lock; other threads
+     can only add nodes at the front; if a front node is consistent,
+     the ones behind it must also be. */
+
+  READ_MEMORY_BARRIER();
+
+  while (thr != 0) {
+    if (thr->p_priority >= maxprio) {
+      maxptr = ptr;
+      maxprio = thr->p_priority;
+    }
+    ptr = &(thr->p_nextlock);
+    thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L);
+  }
+
+  /* Remove max prio thread from waiting list. */
+  if (maxptr == (pthread_descr *) &lock->__status) {
+    /* If max prio thread is at head, remove it with compare-and-swap
+       to guard against concurrent lock operation. This removal
+       also has the side effect of marking the lock as released
+       because the new status comes from thr->p_nextlock whose
+       least significant bit is clear. */
+    thr = (pthread_descr) (oldstatus & ~1L);
+    if (! __compare_and_swap_with_release_semantics
+	    (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L))
+      goto again;
+  } else {
+    /* No risk of concurrent access, remove max prio thread normally.
+       But in this case we must also flip the least significant bit
+       of the status to mark the lock as released. */
+    thr = (pthread_descr)((long)*maxptr & ~1L);
+    *maxptr = thr->p_nextlock;
+
+    /* Ensure deletion from linked list completes before we
+       release the lock. */
+    WRITE_MEMORY_BARRIER();
+
+    do {
+      oldstatus = lock->__status;
+    } while (!__compare_and_swap_with_release_semantics(&lock->__status,
+	     oldstatus, oldstatus & ~1L));
+  }
+
+  /* Wake up the selected waiting thread. Woken thread can check
+     its own p_nextlock field for NULL to detect that it has been removed. No
+     barrier is needed here, since restart() and suspend() take
+     care of memory synchronization. */
+
+  thr->p_nextlock = NULL;
+  restart(thr);
+
+  return 0;
+#endif
+}
+
+/*
+ * Alternate fastlocks do not queue threads directly. Instead, they queue
+ * these wait queue node structures. When a timed wait wakes up due to
+ * a timeout, it can leave its wait node in the queue (because there
+ * is no safe way to remove from the quue). Some other thread will
+ * deallocate the abandoned node.
+ */
+
+
+struct wait_node {
+  struct wait_node *next;	/* Next node in null terminated linked list */
+  pthread_descr thr;		/* The thread waiting with this node */
+  int abandoned;		/* Atomic flag */
+};
+
+static long wait_node_free_list;
+static int wait_node_free_list_spinlock;
+
+/* Allocate a new node from the head of the free list using an atomic
+   operation, or else using malloc if that list is empty.  A fundamental
+   assumption here is that we can safely access wait_node_free_list->next.
+   That's because we never free nodes once we allocate them, so a pointer to a
+   node remains valid indefinitely. */
+
+static struct wait_node *wait_node_alloc(void)
+{
+    struct wait_node *new_node = 0;
+
+    __pthread_acquire(&wait_node_free_list_spinlock);
+    if (wait_node_free_list != 0) {
+      new_node = (struct wait_node *) wait_node_free_list;
+      wait_node_free_list = (long) new_node->next;
+    }
+    WRITE_MEMORY_BARRIER();
+    __pthread_release(&wait_node_free_list_spinlock);
+
+    if (new_node == 0)
+      return malloc(sizeof *wait_node_alloc());
+
+    return new_node;
+}
+
+/* Return a node to the head of the free list using an atomic
+   operation. */
+
+static void wait_node_free(struct wait_node *wn)
+{
+    __pthread_acquire(&wait_node_free_list_spinlock);
+    wn->next = (struct wait_node *) wait_node_free_list;
+    wait_node_free_list = (long) wn;
+    WRITE_MEMORY_BARRIER();
+    __pthread_release(&wait_node_free_list_spinlock);
+    return;
+}
+
+#if defined HAS_COMPARE_AND_SWAP
+
+/* Remove a wait node from the specified queue.  It is assumed
+   that the removal takes place concurrently with only atomic insertions at the
+   head of the queue. */
+
+static void wait_node_dequeue(struct wait_node **pp_head,
+			      struct wait_node **pp_node,
+			      struct wait_node *p_node)
+{
+  /* If the node is being deleted from the head of the
+     list, it must be deleted using atomic compare-and-swap.
+     Otherwise it can be deleted in the straightforward way. */
+
+  if (pp_node == pp_head) {
+    /* We don't need a read barrier between these next two loads,
+       because it is assumed that the caller has already ensured
+       the stability of *p_node with respect to p_node. */
+
+    long oldvalue = (long) p_node;
+    long newvalue = (long) p_node->next;
+
+    if (__compare_and_swap((long *) pp_node, oldvalue, newvalue))
+      return;
+
+    /* Oops! Compare and swap failed, which means the node is
+       no longer first. We delete it using the ordinary method.  But we don't
+       know the identity of the node which now holds the pointer to the node
+       being deleted, so we must search from the beginning. */
+
+    for (pp_node = pp_head; p_node != *pp_node; ) {
+      pp_node = &(*pp_node)->next;
+      READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */
+    }
+  }
+
+  *pp_node = p_node->next;
+  return;
+}
+
+#endif
+
+void __pthread_alt_lock(struct _pthread_fastlock * lock,
+		        pthread_descr self)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus, newstatus;
+#endif
+  struct wait_node wait_node;
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    int suspend_needed = 0;
+    __pthread_acquire(&lock->__spinlock);
+
+    if (lock->__status == 0)
+      lock->__status = 1;
+    else {
+      if (self == NULL)
+	self = thread_self();
+
+      wait_node.abandoned = 0;
+      wait_node.next = (struct wait_node *) lock->__status;
+      wait_node.thr = self;
+      lock->__status = (long) &wait_node;
+      suspend_needed = 1;
+    }
+
+    __pthread_release(&lock->__spinlock);
+
+    if (suspend_needed)
+      suspend (self);
+    return;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    oldstatus = lock->__status;
+    if (oldstatus == 0) {
+      newstatus = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      wait_node.thr = self;
+      newstatus = (long) &wait_node;
+    }
+    wait_node.abandoned = 0;
+    wait_node.next = (struct wait_node *) oldstatus;
+    /* Make sure the store in wait_node.next completes before performing
+       the compare-and-swap */
+    MEMORY_BARRIER();
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+
+  /* Suspend. Note that unlike in __pthread_lock, we don't worry
+     here about spurious wakeup. That's because this lock is not
+     used in situations where that can happen; the restart can
+     only come from the previous lock owner. */
+
+  if (oldstatus != 0)
+    suspend(self);
+
+  READ_MEMORY_BARRIER();
+#endif
+}
+
+/* Timed-out lock operation; returns 0 to indicate timeout. */
+
+int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
+			    pthread_descr self, const struct timespec *abstime)
+{
+  long oldstatus = 0;
+#if defined HAS_COMPARE_AND_SWAP
+  long newstatus;
+#endif
+  struct wait_node *p_wait_node = wait_node_alloc();
+
+  /* Out of memory, just give up and do ordinary lock. */
+  if (p_wait_node == 0) {
+    __pthread_alt_lock(lock, self);
+    return 1;
+  }
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+
+    if (lock->__status == 0)
+      lock->__status = 1;
+    else {
+      if (self == NULL)
+	self = thread_self();
+
+      p_wait_node->abandoned = 0;
+      p_wait_node->next = (struct wait_node *) lock->__status;
+      p_wait_node->thr = self;
+      lock->__status = (long) p_wait_node;
+      oldstatus = 1; /* force suspend */
+    }
+
+    __pthread_release(&lock->__spinlock);
+    goto suspend;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    oldstatus = lock->__status;
+    if (oldstatus == 0) {
+      newstatus = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      p_wait_node->thr = self;
+      newstatus = (long) p_wait_node;
+    }
+    p_wait_node->abandoned = 0;
+    p_wait_node->next = (struct wait_node *) oldstatus;
+    /* Make sure the store in wait_node.next completes before performing
+       the compare-and-swap */
+    MEMORY_BARRIER();
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+#endif
+
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  suspend:
+#endif
+
+  /* If we did not get the lock, do a timed suspend. If we wake up due
+     to a timeout, then there is a race; the old lock owner may try
+     to remove us from the queue. This race is resolved by us and the owner
+     doing an atomic testandset() to change the state of the wait node from 0
+     to 1. If we succeed, then it's a timeout and we abandon the node in the
+     queue. If we fail, it means the owner gave us the lock. */
+
+  if (oldstatus != 0) {
+    if (timedsuspend(self, abstime) == 0) {
+      if (!testandset(&p_wait_node->abandoned))
+	return 0; /* Timeout! */
+
+      /* Eat oustanding resume from owner, otherwise wait_node_free() below
+	 will race with owner's wait_node_dequeue(). */
+      suspend(self);
+    }
+  }
+
+  wait_node_free(p_wait_node);
+
+  READ_MEMORY_BARRIER();
+
+  return 1; /* Got the lock! */
+}
+
+void __pthread_alt_unlock(struct _pthread_fastlock *lock)
+{
+  struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio;
+  struct wait_node ** const pp_head = (struct wait_node **) &lock->__status;
+  int maxprio;
+
+  WRITE_MEMORY_BARRIER();
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+  }
+#endif
+
+  while (1) {
+
+  /* If no threads are waiting for this lock, try to just
+     atomically release it. */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+    if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+    {
+      if (lock->__status == 0 || lock->__status == 1) {
+	lock->__status = 0;
+	break;
+      }
+    }
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+    else
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+    {
+      long oldstatus = lock->__status;
+      if (oldstatus == 0 || oldstatus == 1) {
+	if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0))
+	  break;
+	else
+	  continue;
+      }
+    }
+#endif
+
+    /* Process the entire queue of wait nodes. Remove all abandoned
+       wait nodes and put them into the global free queue, and
+       remember the one unabandoned node which refers to the thread
+       having the highest priority. */
+
+    pp_max_prio = pp_node = pp_head;
+    p_max_prio = p_node = *pp_head;
+    maxprio = INT_MIN;
+
+    READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */
+
+    while (p_node != (struct wait_node *) 1) {
+      int prio;
+
+      if (p_node->abandoned) {
+	/* Remove abandoned node. */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+	if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+	  *pp_node = p_node->next;
+#endif
+#if defined TEST_FOR_COMPARE_AND_SWAP
+	else
+#endif
+#if defined HAS_COMPARE_AND_SWAP
+	  wait_node_dequeue(pp_head, pp_node, p_node);
+#endif
+	wait_node_free(p_node);
+	/* Note that the next assignment may take us to the beginning
+	   of the queue, to newly inserted nodes, if pp_node == pp_head.
+	   In that case we need a memory barrier to stabilize the first of
+	   these new nodes. */
+	p_node = *pp_node;
+	if (pp_node == pp_head)
+	  READ_MEMORY_BARRIER(); /* No stale reads through p_node */
+	continue;
+      } else if ((prio = p_node->thr->p_priority) >= maxprio) {
+	/* Otherwise remember it if its thread has a higher or equal priority
+	   compared to that of any node seen thus far. */
+	maxprio = prio;
+	pp_max_prio = pp_node;
+	p_max_prio = p_node;
+      }
+
+      /* This canno6 jump backward in the list, so no further read
+         barrier is needed. */
+      pp_node = &p_node->next;
+      p_node = *pp_node;
+    }
+
+    /* If all threads abandoned, go back to top */
+    if (maxprio == INT_MIN)
+      continue;
+
+    ASSERT (p_max_prio != (struct wait_node *) 1);
+
+    /* Now we want to to remove the max priority thread's wait node from
+       the list. Before we can do this, we must atomically try to change the
+       node's abandon state from zero to nonzero. If we succeed, that means we
+       have the node that we will wake up. If we failed, then it means the
+       thread timed out and abandoned the node in which case we repeat the
+       whole unlock operation. */
+
+    if (!testandset(&p_max_prio->abandoned)) {
+#if defined TEST_FOR_COMPARE_AND_SWAP
+      if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+	*pp_max_prio = p_max_prio->next;
+#endif
+#if defined TEST_FOR_COMPARE_AND_SWAP
+      else
+#endif
+#if defined HAS_COMPARE_AND_SWAP
+	wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
+#endif
+      restart(p_max_prio->thr);
+      break;
+    }
+  }
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_release(&lock->__spinlock);
+  }
+#endif
+}
+
+
+/* Compare-and-swap emulation with a spinlock */
+
+#ifdef TEST_FOR_COMPARE_AND_SWAP
+int __pthread_has_cas = 0;
+#endif
+
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+
+int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
+                               int * spinlock)
+{
+  int res;
+
+  __pthread_acquire(spinlock);
+
+  if (*ptr == oldval) {
+    *ptr = newval; res = 1;
+  } else {
+    res = 0;
+  }
+
+  __pthread_release(spinlock);
+
+  return res;
+}
+
+#endif
+
+/* The retry strategy is as follows:
+   - We test and set the spinlock MAX_SPIN_COUNT times, calling
+     sched_yield() each time.  This gives ample opportunity for other
+     threads with priority >= our priority to make progress and
+     release the spinlock.
+   - If a thread with priority < our priority owns the spinlock,
+     calling sched_yield() repeatedly is useless, since we're preventing
+     the owning thread from making progress and releasing the spinlock.
+     So, after MAX_SPIN_LOCK attemps, we suspend the calling thread
+     using nanosleep().  This again should give time to the owning thread
+     for releasing the spinlock.
+     Notice that the nanosleep() interval must not be too small,
+     since the kernel does busy-waiting for short intervals in a realtime
+     process (!).  The smallest duration that guarantees thread
+     suspension is currently 2ms.
+   - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT
+     sched_yield(), then sleeping again if needed. */
+
+static void __pthread_acquire(int * spinlock)
+{
+  int cnt = 0;
+  struct timespec tm;
+
+  READ_MEMORY_BARRIER();
+
+  while (testandset(spinlock)) {
+    if (cnt < MAX_SPIN_COUNT) {
+      sched_yield();
+      cnt++;
+    } else {
+      tm.tv_sec = 0;
+      tm.tv_nsec = SPIN_SLEEP_DURATION;
+      nanosleep(&tm, NULL);
+      cnt = 0;
+    }
+  }
+}
diff --git a/linuxthreads/spinlock.h b/linuxthreads/spinlock.h
new file mode 100644
index 0000000000..ff96fc3360
--- /dev/null
+++ b/linuxthreads/spinlock.h
@@ -0,0 +1,218 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#include <bits/initspin.h>
+
+
+/* There are 2 compare and swap synchronization primitives with
+   different semantics:
+
+	1. compare_and_swap, which has acquire semantics (i.e. it
+	completes befor subsequent writes.)
+	2. compare_and_swap_with_release_semantics, which has release
+	semantics (it completes after previous writes.)
+
+   For those platforms on which they are the same. HAS_COMPARE_AND_SWAP
+   should be defined. For those platforms on which they are different,
+   HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined.  */
+
+#ifndef HAS_COMPARE_AND_SWAP
+#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define HAS_COMPARE_AND_SWAP
+#endif
+#endif
+
+#if defined(TEST_FOR_COMPARE_AND_SWAP)
+
+extern int __pthread_has_cas;
+extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
+                                      int * spinlock);
+
+static inline int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  if (__builtin_expect (__pthread_has_cas, 1))
+    return __compare_and_swap(ptr, oldval, newval);
+  else
+    return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
+}
+
+#elif defined(HAS_COMPARE_AND_SWAP)
+
+#ifdef IMPLEMENT_TAS_WITH_CAS
+#define testandset(p) !__compare_and_swap((long int *) p, 0, 1)
+#endif
+
+#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+
+static inline int
+compare_and_swap_with_release_semantics (long * ptr, long oldval,
+					 long newval, int * spinlock)
+{
+  return __compare_and_swap_with_release_semantics (ptr, oldval,
+						    newval);
+}
+
+#endif
+
+static inline int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  return __compare_and_swap(ptr, oldval, newval);
+}
+
+#else
+
+extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
+                                      int * spinlock);
+
+static inline int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
+}
+
+#endif
+
+#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define compare_and_swap_with_release_semantics compare_and_swap
+#define __compare_and_swap_with_release_semantics __compare_and_swap
+#endif
+
+/* Internal locks */
+
+extern void internal_function __pthread_lock(struct _pthread_fastlock * lock,
+					     pthread_descr self);
+extern int __pthread_unlock(struct _pthread_fastlock *lock);
+
+static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
+{
+  lock->__status = 0;
+  lock->__spinlock = __LT_SPINLOCK_INIT;
+}
+
+static inline int __pthread_trylock (struct _pthread_fastlock * lock)
+{
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    return (testandset(&lock->__spinlock) ? EBUSY : 0);
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    if (lock->__status != 0) return EBUSY;
+  } while(! __compare_and_swap(&lock->__status, 0, 1));
+  return 0;
+#endif
+}
+
+/* Variation of internal lock used for pthread_mutex_t, supporting
+   timed-out waits.  Warning: do not mix these operations with the above ones
+   over the same lock object! */
+
+extern void __pthread_alt_lock(struct _pthread_fastlock * lock,
+			       pthread_descr self);
+
+extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
+			       pthread_descr self, const struct timespec *abstime);
+
+extern void __pthread_alt_unlock(struct _pthread_fastlock *lock);
+
+static inline void __pthread_alt_init_lock(struct _pthread_fastlock * lock)
+{
+  lock->__status = 0;
+  lock->__spinlock = __LT_SPINLOCK_INIT;
+}
+
+static inline int __pthread_alt_trylock (struct _pthread_fastlock * lock)
+{
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    int res = EBUSY;
+
+    if (testandset(&lock->__spinlock) == 0)
+      {
+	if (lock->__status == 0)
+	  {
+	    lock->__status = 1;
+	    WRITE_MEMORY_BARRIER();
+	    res = 0;
+	  }
+	lock->__spinlock = __LT_SPINLOCK_INIT;
+      }
+    return res;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    if (lock->__status != 0) return EBUSY;
+  } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
+  return 0;
+#endif
+}
+
+/* Operations on pthread_atomic, which is defined in internals.h */
+
+static inline long atomic_increment(struct pthread_atomic *pa)
+{
+    long oldval;
+
+    do {
+	oldval = pa->p_count;
+    } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock));
+
+    return oldval;
+}
+
+
+static inline long atomic_decrement(struct pthread_atomic *pa)
+{
+    long oldval;
+
+    do {
+	oldval = pa->p_count;
+    } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock));
+
+    return oldval;
+}
+
+
+static inline __attribute__((always_inline)) void
+__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif)
+{
+  /* Only store a non-null peif if the thread has cancellation enabled.
+     Otherwise pthread_cancel will unconditionally call the extricate handler,
+     and restart the thread giving rise to forbidden spurious wakeups. */
+  if (peif == NULL
+      || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    {
+      /* If we are removing the extricate interface, we need to synchronize
+	 against pthread_cancel so that it does not continue with a pointer
+         to a deallocated pthread_extricate_if struct! The thread lock
+         is (ab)used for this synchronization purpose. */
+      if (peif == NULL)
+	__pthread_lock (THREAD_GETMEM(self, p_lock), self);
+      THREAD_SETMEM(self, p_extricate, peif);
+      if (peif == NULL)
+	__pthread_unlock (THREAD_GETMEM(self, p_lock));
+    }
+}
diff --git a/linuxthreads/sysdeps/alpha/elf/pt-initfini.c b/linuxthreads/sysdeps/alpha/elf/pt-initfini.c
new file mode 100644
index 0000000000..ee25582101
--- /dev/null
+++ b/linuxthreads/sysdeps/alpha/elf/pt-initfini.c
@@ -0,0 +1,90 @@
+/* Special .init and .fini section support for Alpha.  Linuxthreads version.
+   Copyright (C) 2002, 2003 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.  */
+
+/* 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.
+
+   This differs from what would be generated by the generic code in that
+   we save and restore the GP within the function.  In order for linker
+   relaxation to work, the value in the GP register on exit from a function
+   must be valid for the function entry point.  Normally, a function is
+   contained within one object file and this is not an issue, provided
+   that the function reloads the gp after making any function calls.
+   However, _init and _fini are constructed from pieces of many object
+   files, all of which may have different GP values.  So we must reload
+   the GP value from crti.o in crtn.o.  */
+
+__asm__ ("						\n\
+#include \"defs.h\"					\n\
+							\n\
+/*@HEADER_ENDS*/					\n\
+							\n\
+/*@_init_PROLOG_BEGINS*/				\n\
+	.section .init, \"ax\", @progbits		\n\
+	.globl	_init					\n\
+	.type	_init,@function				\n\
+	.usepv	_init,std				\n\
+_init:							\n\
+	ldgp	$29, 0($27)				\n\
+	subq	$30, 16, $30				\n\
+	stq	$26, 0($30)				\n\
+	stq	$29, 8($30)				\n\
+	jsr	$26, __pthread_initialize_minimal	\n\
+	ldq	$29, 8($30)				\n\
+	.align 3					\n\
+/*@_init_PROLOG_ENDS*/					\n\
+							\n\
+/*@_init_EPILOG_BEGINS*/				\n\
+	.section .init, \"ax\", @progbits		\n\
+	ldq	$26, 0($30)				\n\
+	ldq	$29, 8($30)				\n\
+	addq	$30, 16, $30				\n\
+	ret						\n\
+/*@_init_EPILOG_ENDS*/					\n\
+							\n\
+/*@_fini_PROLOG_BEGINS*/				\n\
+	.section .fini, \"ax\", @progbits		\n\
+	.globl	_fini					\n\
+	.type	_fini,@function				\n\
+	.usepv	_fini,std				\n\
+_fini:							\n\
+	ldgp	$29, 0($27)				\n\
+	subq	$30, 16, $30				\n\
+	stq	$26, 0($30)				\n\
+	stq	$29, 8($30)				\n\
+	.align 3					\n\
+/*@_fini_PROLOG_ENDS*/					\n\
+							\n\
+/*@_fini_EPILOG_BEGINS*/				\n\
+	.section .fini, \"ax\", @progbits		\n\
+	ldq	$26, 0($30)				\n\
+	ldq	$29, 8($30)				\n\
+	addq	$30, 16, $30				\n\
+	ret						\n\
+/*@_fini_EPILOG_ENDS*/					\n\
+							\n\
+/*@TRAILER_BEGINS*/					\n\
+");
diff --git a/linuxthreads/sysdeps/alpha/pspinlock.c b/linuxthreads/sysdeps/alpha/pspinlock.c
new file mode 100644
index 0000000000..79b7836293
--- /dev/null
+++ b/linuxthreads/sysdeps/alpha/pspinlock.c
@@ -0,0 +1,110 @@
+/* POSIX spinlock implementation.  Alpha version.
+   Copyright (C) 2000 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 "internals.h"
+
+
+/* This implementation is similar to the one used in the Linux kernel.
+   But the kernel is byte instructions for the memory access.  This is
+   faster but unusable here.  The problem is that only 128
+   threads/processes could use the spinlock at the same time.  If (by
+   a design error in the program) a thread/process would hold the
+   spinlock for a time long enough to accumulate 128 waiting
+   processes, the next one will find a positive value in the spinlock
+   and assume it is unlocked.  We cannot accept that.  */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int tmp;
+  asm volatile
+    ("1:	ldl_l	%0,%1\n"
+     "		blbs	%0,2f\n"
+     "		or	%0,1,%0\n"
+     "		stl_c	%0,%1\n"
+     "		beq	%0,2f\n"
+     "		mb\n"
+     ".subsection 2\n"
+     "2:	ldl	%0,%1\n"
+     "		blbs	%0,2b\n"
+     "		br	1b\n"
+     ".previous"
+     : "=r" (tmp), "=m" (lock)
+     : "m" (lock));
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  unsigned long int oldval;
+  unsigned long int temp;
+
+  asm volatile
+    ("1:	ldl_l	%0,%1\n"
+     "		and	%0,%3,%2\n"
+     "		bne	%2,2f\n"
+     "		xor	%0,%3,%0\n"
+     "		stl_c	%0,%1\n"
+     "		beq	%0,3f\n"
+     "		mb\n"
+     "2:\n"
+     ".subsection 2\n"
+     "3:	br	1b\n"
+     ".previous"
+     : "=&r" (temp), "=m" (*lock), "=&r" (oldval)
+     : "Ir" (1UL), "m" (*lock));
+
+  return oldval == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile ("mb");
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/alpha/pt-machine.h b/linuxthreads/sysdeps/alpha/pt-machine.h
new file mode 100644
index 0000000000..853ac6f04a
--- /dev/null
+++ b/linuxthreads/sysdeps/alpha/pt-machine.h
@@ -0,0 +1,128 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   Alpha version.
+   Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+#ifdef __linux__
+# include <asm/pal.h>
+#else
+# include <machine/pal.h>
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char *stack_pointer __asm__("$30");
+
+
+/* Memory barrier; default is to do nothing */
+#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory")
+/* Write barrier.  */
+#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory")
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret, temp;
+
+  __asm__ __volatile__(
+	"/* Inline spinlock test & set */\n"
+	"1:\t"
+	"ldl_l %0,%3\n\t"
+	"bne %0,2f\n\t"
+	"or $31,1,%1\n\t"
+	"stl_c %1,%2\n\t"
+	"beq %1,1b\n"
+	"2:\tmb\n"
+	"/* End spinlock test & set */"
+	: "=&r"(ret), "=&r"(temp), "=m"(*spinlock)
+	: "m"(*spinlock)
+        : "memory");
+
+  return ret;
+}
+
+
+/* Begin allocating thread stacks at this address.  Default is to allocate
+   them just below the initial program stack.  */
+#define THREAD_STACK_START_ADDRESS  0x40000000000
+
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF \
+({									      \
+  register pthread_descr __self __asm__("$0");				      \
+  __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq));		      \
+  __self;								      \
+})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) \
+{									      \
+  register pthread_descr __self __asm__("$16") = (descr);		      \
+  __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq));      \
+}
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"/* Inline compare & swap */\n"
+	"1:\t"
+	"ldq_l %0,%4\n\t"
+	"cmpeq %0,%2,%0\n\t"
+	"beq %0,2f\n\t"
+	"mov %3,%0\n\t"
+	"stq_c %0,%1\n\t"
+	"beq %0,1b\n\t"
+	"2:\tmb\n"
+	"/* End compare & swap */"
+	: "=&r"(ret), "=m"(*p)
+	: "r"(oldval), "r"(newval), "m"(*p)
+        : "memory");
+
+  return ret;
+}
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/alpha/tls.h b/linuxthreads/sysdeps/alpha/tls.h
new file mode 100644
index 0000000000..261d333eb4
--- /dev/null
+++ b/linuxthreads/sysdeps/alpha/tls.h
@@ -0,0 +1,129 @@
+/* Definitions for thread-local data handling.  linuxthreads/Alpha version.
+   Copyright (C) 2002, 2003 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  dtv_t *dtv;
+
+  /* Reserved for the thread implementation.  Unused in LinuxThreads.  */
+  void *private;
+} tcbhead_t;
+#endif
+
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.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 (tcbhead_t)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN		__alignof__ (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE	sizeof (struct _pthread_descr_struct)
+
+/* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+#  define TLS_DTV_AT_TP 1
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(TCBP, DTVP) \
+  (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1)
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(DTV) \
+  (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(TCBP) \
+  (((tcbhead_t *) (TCBP))->dtv)
+
+/* 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(TCBP, SECONDCALL) \
+  (__builtin_set_thread_pointer (TCBP), 0)
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *)__builtin_thread_pointer ())->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+  ((pthread_descr)__builtin_thread_pointer () - 1)
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(DESCR, NR) \
+  __builtin_set_thread_pointer ((struct _pthread_descr_struct *)(DESCR) + 1)
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+/* ??? Generic bits of LinuxThreads may call these macros with
+   DESCR set to NULL.  We are expected to be able to reference
+   the "current" value.
+
+   In our case, we'd really prefer to use DESCR, since lots of
+   PAL_code calls would be expensive.  We can only trust that
+   the compiler does its job and unifies the multiple
+   __builtin_thread_pointer instances.  */
+
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+# endif	/* HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/arm/pspinlock.c b/linuxthreads/sysdeps/arm/pspinlock.c
new file mode 100644
index 0000000000..665e270b69
--- /dev/null
+++ b/linuxthreads/sysdeps/arm/pspinlock.c
@@ -0,0 +1,82 @@
+/* POSIX spinlock implementation.  Arm version.
+   Copyright (C) 2000 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 "internals.h"
+
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  do
+    asm volatile ("swp %0, %1, [%2]"
+		  : "=r" (val)
+		  : "0" (1), "r" (lock)
+		  : "memory");
+  while (val != 0);
+
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  asm volatile ("swp %0, %1, [%2]"
+		: "=r" (val)
+		: "0" (1), "r" (lock)
+		: "memory");
+
+  return val ? EBUSY : 0;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/arm/pt-machine.h b/linuxthreads/sysdeps/arm/pt-machine.h
new file mode 100644
index 0000000000..a4c2f314cb
--- /dev/null
+++ b/linuxthreads/sysdeps/arm/pt-machine.h
@@ -0,0 +1,55 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   ARM version.
+   Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Philip Blundell <philb@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; 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 _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* This will not work on ARM1 or ARM2 because SWP is lacking on those
+   machines.  Unfortunately we have no way to detect this at compile
+   time; let's hope nobody tries to use one.  */
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  register unsigned int ret;
+
+  __asm__ __volatile__("swp %0, %1, [%2]"
+		       : "=r"(ret)
+		       : "0"(1), "r"(spinlock));
+
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("sp");
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/cris/pspinlock.c b/linuxthreads/sysdeps/cris/pspinlock.c
new file mode 100644
index 0000000000..402e838c00
--- /dev/null
+++ b/linuxthreads/sysdeps/cris/pspinlock.c
@@ -0,0 +1,72 @@
+/* POSIX spinlock implementation.  CRIS version.
+   Copyright (C) 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 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 "internals.h"
+
+/* FIXME: These are just dummies.  I don't know why or if they're needed;
+   configury should default to these definitions.  We just follow the
+   crowd here.  */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  while (testandset (lock) != 0)
+    ;
+
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return testandset (lock) != 0 ? EBUSY : 0;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/cris/pt-machine.h b/linuxthreads/sysdeps/cris/pt-machine.h
new file mode 100644
index 0000000000..431da7101d
--- /dev/null
+++ b/linuxthreads/sysdeps/cris/pt-machine.h
@@ -0,0 +1,58 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   CRIS version.
+   Copyright (C) 2001, 2002, 2003 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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+PT_EI long int
+testandset (int *spinlock)
+{
+  register unsigned long int ret;
+
+  /* Note the use of a dummy output of *spinlock to expose the write.  The
+     memory barrier is to stop *other* writes being moved past this code.  */
+  __asm__ __volatile__("clearf\n"
+		       "0:\n\t"
+		       "movu.b [%2],%0\n\t"
+		       "ax\n\t"
+		       "move.b %3,[%2]\n\t"
+		       "bwf 0b\n\t"
+		       "clearf"
+		       : "=&r" (ret), "=m" (*spinlock)
+		       : "r" (spinlock), "r" ((int) 1)
+		       : "memory");
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.
+   I don't trust register variables, so let's do this the safe way.  */
+#define CURRENT_STACK_FRAME \
+ ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; })
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/hppa/pspinlock.c b/linuxthreads/sysdeps/hppa/pspinlock.c
new file mode 100644
index 0000000000..7f481fa4b6
--- /dev/null
+++ b/linuxthreads/sysdeps/hppa/pspinlock.c
@@ -0,0 +1,81 @@
+/* POSIX spinlock implementation.  hppa version.
+   Copyright (C) 2000 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 "internals.h"
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  do
+    asm volatile ("ldcw %1,%0"
+		  : "=r" (val), "=m" (*lock)
+		  : "m" (*lock));
+  while (!val);
+
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  asm volatile ("ldcw %1,%0"
+		: "=r" (val), "=m" (*lock)
+		: "m" (*lock));
+
+  return val ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  *lock = 1;
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 1;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/hppa/pt-machine.h b/linuxthreads/sysdeps/hppa/pt-machine.h
new file mode 100644
index 0000000000..abc25c4ca4
--- /dev/null
+++ b/linuxthreads/sysdeps/hppa/pt-machine.h
@@ -0,0 +1,62 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   hppa version.
+   Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <bits/initspin.h>
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("%r30");
+
+
+/* The hppa only has one atomic read and modify memory operation,
+   load and clear, so hppa spinlocks must use zero to signify that
+   someone is holding the lock.  */
+
+#define xstr(s) str(s)
+#define str(s) #s
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__(
+       "ldcw 0(%2),%0"
+       : "=r"(ret), "=m"(*spinlock)
+       : "r"(spinlock));
+
+  return ret == 0;
+}
+#undef str
+#undef xstr
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/i386/Makefile b/linuxthreads/sysdeps/i386/Makefile
new file mode 100644
index 0000000000..418fa5c6ef
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/Makefile
@@ -0,0 +1,23 @@
+ifeq ($(subdir),linuxthreads)
+# On i686 we must avoid generating the trampoline functions generated
+# to get the GOT pointer.
+CFLAGS-pt-initfini.s += -march=i386 -mcpu=i386
+
+# Most files must not be compiled without frame pointer since we need
+# the frame base address which is stored in %ebp unless the frame pointer
+# is optimized out.
+CFLAGS-cancel.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4
+CFLAGS-condvar.c += -fno-omit-frame-pointer
+CFLAGS-join.c += -fno-omit-frame-pointer
+CFLAGS-manager.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4
+CFLAGS-oldsemaphore.c += -fno-omit-frame-pointer
+CFLAGS-pthread.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4
+CFLAGS-ptlongjmp.c += -fno-omit-frame-pointer
+CFLAGS-semaphore.c += -fno-omit-frame-pointer
+CFLAGS-sighandler.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4
+CFLAGS-tst-align.c += -mpreferred-stack-boundary=4
+endif
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/i386/i586/Versions b/linuxthreads/sysdeps/i386/i586/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/i586/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/i386/i686/Versions b/linuxthreads/sysdeps/i386/i686/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/i686/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/i386/i686/pt-machine.h b/linuxthreads/sysdeps/i386/i686/pt-machine.h
new file mode 100644
index 0000000000..1c75bf9807
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/i686/pt-machine.h
@@ -0,0 +1,79 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   i686 version.
+   Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H	1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+#include "kernel-features.h"
+
+#ifndef __ASSEMBLER__
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  __builtin_frame_address (0)
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"xchgl %0, %1"
+	: "=r" (ret), "=m" (*spinlock)
+	: "0" (1), "m" (*spinlock)
+	: "memory");
+
+  return ret;
+}
+
+
+/* Compare-and-swap for semaphores.  It's always available on i686.  */
+#define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+#endif
+
+#if __ASSUME_LDT_WORKS > 0
+#include "../useldt.h"
+#endif
+
+/* The P4 and above really want some help to prevent overheating.  */
+#define BUSY_WAIT_NOP	__asm__ ("rep; nop")
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/i386/pspinlock.c b/linuxthreads/sysdeps/i386/pspinlock.c
new file mode 100644
index 0000000000..6a70093957
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/pspinlock.c
@@ -0,0 +1,103 @@
+/* POSIX spinlock implementation.  x86 version.
+   Copyright (C) 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 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 "internals.h"
+#include "kernel-features.h"
+
+
+/* This implementation is similar to the one used in the Linux kernel.
+   But the kernel is byte instructions for the memory access.  This is
+   faster but unusable here.  The problem is that only 128
+   threads/processes could use the spinlock at the same time.  If (by
+   a design error in the program) a thread/process would hold the
+   spinlock for a time long enough to accumulate 128 waiting
+   processes, the next one will find a positive value in the spinlock
+   and assume it is unlocked.  We cannot accept that.  */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("\n"
+     "1:\n\t"
+     "lock; decl %0\n\t"
+     "js 2f\n\t"
+     ".section .text.spinlock,\"ax\"\n"
+     "2:\n\t"
+     "cmpl $0,%0\n\t"
+     "rep; nop\n\t"
+     "jle 2b\n\t"
+     "jmp 1b\n\t"
+     ".previous"
+     : "=m" (*lock));
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int oldval;
+
+  asm volatile
+    ("xchgl %0,%1"
+     : "=r" (oldval), "=m" (*lock)
+     : "0" (0));
+  return oldval > 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("movl $1,%0"
+     : "=m" (*lock));
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 1;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
+
+#ifndef __ASSUME_SET_THREAD_AREA_SYSCALL
+int __have_no_set_thread_area;
+#endif
diff --git a/linuxthreads/sysdeps/i386/pt-machine.h b/linuxthreads/sysdeps/i386/pt-machine.h
new file mode 100644
index 0000000000..0df096d152
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/pt-machine.h
@@ -0,0 +1,108 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   i386 version.
+   Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H	1
+
+#ifndef __ASSEMBLER__
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  __builtin_frame_address (0)
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__(
+       "xchgl %0, %1"
+       : "=r"(ret), "=m"(*spinlock)
+       : "0"(1), "m"(*spinlock)
+       : "memory");
+
+  return ret;
+}
+
+
+/* Compare-and-swap for semaphores.
+   Available on the 486 and above, but not on the 386.
+   We test dynamically whether it's available or not. */
+
+#define HAS_COMPARE_AND_SWAP
+#define TEST_FOR_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+
+
+PT_EI int
+get_eflags (void)
+{
+  int res;
+  __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : );
+  return res;
+}
+
+
+PT_EI void
+set_eflags (int newflags)
+{
+  __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc");
+}
+
+
+PT_EI int
+compare_and_swap_is_available (void)
+{
+  int oldflags = get_eflags ();
+  int changed;
+  /* Flip AC bit in EFLAGS.  */
+  set_eflags (oldflags ^ 0x40000);
+  /* See if bit changed.  */
+  changed = (get_eflags () ^ oldflags) & 0x40000;
+  /* Restore EFLAGS.  */
+  set_eflags (oldflags);
+  /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
+     Otherwise, it's a 486 or above and it has cmpxchg.  */
+  return changed != 0;
+}
+#endif /* __ASSEMBLER__ */
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/i386/tcb-offsets.sym b/linuxthreads/sysdeps/i386/tcb-offsets.sym
new file mode 100644
index 0000000000..69a5018d88
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/tcb-offsets.sym
@@ -0,0 +1,7 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads)
+#ifdef NEED_DL_SYSINFO
+SYSINFO_OFFSET			offsetof (tcbhead_t, sysinfo)
+#endif
diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h
new file mode 100644
index 0000000000..5306d082bb
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/tls.h
@@ -0,0 +1,225 @@
+/* Definition for thread-local data handling.  linuxthreads/i386 version.
+   Copyright (C) 2002, 2003, 2004 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
+
+# include <dl-sysdep.h>
+# include <pt-machine.h>
+
+#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.  */
+  int multiple_threads;
+#ifdef NEED_DL_SYSINFO
+  uintptr_t sysinfo;
+#endif
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif
+
+/* We can support TLS only if the floating-stack support is available.
+   However, we want to compile in the support and test at runtime whether
+   the running kernel can support it or not.  To avoid bothering with the
+   TLS support code at all, use configure --without-tls.
+
+   We need USE_TLS to be consistently defined, for ldsodefs.h conditionals.
+   But some of the code below can cause problems in building libpthread
+   (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't).  */
+
+#if defined HAVE_TLS_SUPPORT \
+    && (defined FLOATING_STACKS || !defined IS_IN_libpthread)
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/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_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* 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_descr_struct *__descr;				      \
+     THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+#  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
+
+#  if !defined IS_IN_linuxthreads && !defined DO_MODIFY_LDT
+#   include "useldt.h"		/* For the structure.  */
+#  endif
+#  if __ASSUME_LDT_WORKS > 0
+#   define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) (doit) /* Nothing to check.  */
+#  else
+#   define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit)				      \
+  (__builtin_expect (GLRO(dl_osversion) < 131939, 0)			      \
+   ? "kernel too old for thread-local storage support\n"			      \
+   : (doit))
+#  endif
+
+#  define TLS_DO_MODIFY_LDT(descr, nr)					      \
+TLS_DO_MODIFY_LDT_KERNEL_CHECK(						      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  int result;								      \
+  asm volatile (TLS_LOAD_EBX						      \
+		"int $0x80\n\t"						      \
+		TLS_LOAD_EBX						      \
+		: "=a" (result)						      \
+		: "0" (__NR_modify_ldt),				      \
+		/* The extra argument with the "m" constraint is necessary    \
+		   to let the compiler know that we are accessing LDT_ENTRY   \
+		   here.  */						      \
+		"m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry),	      \
+		"d" (sizeof (ldt_entry)));				      \
+  __builtin_expect (result, 0) == 0					      \
+  ? ({ asm ("movw %w0, %%gs" : : "q" ((nr) * 8 + 7)); NULL; })		      \
+  : "cannot set up LDT for thread-local storage\n";			      \
+}))
+
+#  define TLS_DO_SET_THREAD_AREA(descr, secondcall)			      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  int result;								      \
+  if (secondcall)							      \
+    ldt_entry.entry_number = ({ int _gs;				      \
+				asm ("movw %%gs, %w0" : "=q" (_gs));	      \
+				(_gs & 0xffff) >> 3; });		      \
+  asm volatile (TLS_LOAD_EBX						      \
+		"int $0x80\n\t"						      \
+		TLS_LOAD_EBX						      \
+		: "=a" (result), "=m" (ldt_entry.entry_number)		      \
+		: "0" (__NR_set_thread_area),				      \
+		/* The extra argument with the "m" constraint is necessary    \
+		   to let the compiler know that we are accessing LDT_ENTRY   \
+		   here.  */						      \
+		TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry));		      \
+  if (__builtin_expect (result, 0) == 0)				      \
+    asm ("movw %w0, %%gs" : : "q" (ldt_entry.entry_number * 8 + 3));	      \
+  result;								      \
+})
+
+#  ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall)			      \
+  (TLS_DO_SET_THREAD_AREA (descr, secondcall)				      \
+   ? "set_thread_area failed when setting up thread-local storage\n" : NULL)
+#  elif defined __NR_set_thread_area
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
+  (TLS_DO_SET_THREAD_AREA (descr, secondcall)				      \
+   ? TLS_DO_MODIFY_LDT (descr, 0) : NULL)
+#  else
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
+  TLS_DO_MODIFY_LDT ((descr), 0)
+#  endif
+
+#if defined NEED_DL_SYSINFO
+# define INIT_SYSINFO \
+  head->sysinfo = GLRO(dl_sysinfo)
+#else
+# define INIT_SYSINFO
+#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.
+
+   The value of this macro is null if successful, or an error string.  */
+#  define TLS_INIT_TP(descr, secondcall)				      \
+  ({									      \
+    void *_descr = (descr);						      \
+    tcbhead_t *head = _descr;						      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    INIT_SYSINFO;							      \
+    TLS_SETUP_GS_SEGMENT (_descr, secondcall);				      \
+  })
+
+/* Indicate that dynamic linker shouldn't try to initialize TLS even
+   when no PT_TLS segments are found in the program and libraries
+   it is linked against.  */
+#  define TLS_INIT_TP_EXPENSIVE 1
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+
+# endif	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/i386/useldt.h b/linuxthreads/sysdeps/i386/useldt.h
new file mode 100644
index 0000000000..4ac82f1ab0
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/useldt.h
@@ -0,0 +1,314 @@
+/* Special definitions for ix86 machine using segment register based
+   thread descriptor.
+   Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+   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.	*/
+
+#ifndef __ASSEMBLER__
+#include <stddef.h>	/* For offsetof.  */
+#include <stdlib.h>	/* For abort().	 */
+#include <sysdep.h>
+
+
+/* We don't want to include the kernel header.	So duplicate the
+   information.	 */
+
+/* Structure passed on `modify_ldt' call.  */
+struct modify_ldt_ldt_s
+{
+  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;
+};
+
+/* System call to set LDT entry.  */
+extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
+
+
+/* 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 \
+({									      \
+  register pthread_descr __self;					      \
+  __asm__ ("movl %%gs:%c1,%0" : "=r" (__self)				      \
+	   : "i" (offsetof (struct _pthread_descr_struct,		      \
+			    p_header.data.self)));			      \
+  __self;								      \
+})
+
+
+/* Initialize the thread-unique value.	Two possible ways to do it.  */
+
+#define DO_MODIFY_LDT(descr, nr)					      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)		      \
+    abort ();								      \
+  asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7));				      \
+})
+
+#ifdef __PIC__
+# define USETLS_EBX_ARG "r"
+# define USETLS_LOAD_EBX "xchgl %1, %%ebx\n\t"
+#else
+# define USETLS_EBX_ARG "b"
+# define USETLS_LOAD_EBX
+#endif
+
+/* When using the new set_thread_area call, we don't need to change %gs
+   because we inherited the value set up in the main thread by TLS setup.
+   We need to extract that value and set up the same segment in this
+   thread.  */
+#if USE_TLS
+# define DO_SET_THREAD_AREA_REUSE(nr)	1
+#else
+/* Without TLS, we do the initialization of the main thread, where NR == 0.  */
+# define DO_SET_THREAD_AREA_REUSE(nr)	(!__builtin_constant_p (nr) || (nr))
+#endif
+#define DO_SET_THREAD_AREA(descr, nr) \
+({									      \
+  int __gs;								      \
+  if (DO_SET_THREAD_AREA_REUSE (nr))					      \
+    {									      \
+      asm ("movw %%gs, %w0" : "=q" (__gs));				      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ (__gs & 0xffff) >> 3,						      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
+									      \
+      int __result;							      \
+      __asm (USETLS_LOAD_EBX						      \
+	     "movl %2, %%eax\n\t"					      \
+	     "int $0x80\n\t"						      \
+	     USETLS_LOAD_EBX						      \
+	     : "=&a" (__result)						      \
+	     : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area),	      \
+	       "m" (ldt_entry)						      \
+	     : "memory");						      \
+      if (__result == 0)						      \
+	asm ("movw %w0, %%gs" :: "q" (__gs));				      \
+      else								      \
+	__gs = -1;							      \
+    }									      \
+  else									      \
+    {									      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ -1,								      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
+      int __result;							      \
+      __asm (USETLS_LOAD_EBX						      \
+	     "movl %2, %%eax\n\t"					      \
+	     "int $0x80\n\t"						      \
+	     USETLS_LOAD_EBX						      \
+	     : "=&a" (__result)						      \
+	     : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area),	      \
+	       "m" (ldt_entry)						      \
+	     : "memory");						      \
+      if (__result == 0)						      \
+	{								      \
+	  __gs = (ldt_entry.entry_number << 3) + 3;			      \
+	  asm ("movw %w0, %%gs" : : "q" (__gs));			      \
+	}								      \
+      else								      \
+	__gs = -1;							      \
+    }									      \
+  __gs;									      \
+})
+
+#if defined __ASSUME_SET_THREAD_AREA_SYSCALL
+# define INIT_THREAD_SELF(descr, nr)	DO_SET_THREAD_AREA (descr, nr)
+#elif defined __NR_set_thread_area
+# define INIT_THREAD_SELF(descr, nr)					      \
+({									      \
+  if (__builtin_expect (__have_no_set_thread_area, 0)			      \
+      || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1     \
+	  && (__have_no_set_thread_area = 1)))				      \
+    DO_MODIFY_LDT (descr, nr);						      \
+})
+/* Defined in pspinlock.c.  */
+extern int __have_no_set_thread_area;
+#else
+# define INIT_THREAD_SELF(descr, nr)	DO_MODIFY_LDT (descr, nr)
+#endif
+
+/* Free resources associated with thread descriptor.  */
+#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
+#define FREE_THREAD(descr, nr) do { } while (0)
+#elif defined __NR_set_thread_area
+#define FREE_THREAD(descr, nr) \
+{									      \
+  int __gs;								      \
+  __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs));		      \
+  if (__builtin_expect (__gs & 4, 0))					      \
+    {									      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };				      \
+      __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));			      \
+    }									      \
+}
+#else
+#define FREE_THREAD(descr, nr) \
+{									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };					      \
+  __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));			      \
+}
+#endif
+
+/* Read member of the thread descriptor directly.  */
+#define THREAD_GETMEM(descr, member) \
+({									      \
+  __typeof__ (descr->member) __value;					      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %%gs:%P2,%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%gs:%P1,%0"				      \
+			  : "=r" (__value)				      \
+			  : "i" (offsetof (struct _pthread_descr_struct,      \
+					   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 %%gs:%P1,%%eax\n\t"			      \
+			    "movl %%gs:%P2,%%edx"			      \
+			    : "=A" (__value)				      \
+			    : "i" (offsetof (struct _pthread_descr_struct,    \
+					     member)),			      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     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__ __volatile__ ("movb %%gs:(%2),%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%gs:(%1),%0"				      \
+			  : "=r" (__value)				      \
+			  : "r" (offsetof (struct _pthread_descr_struct,      \
+					   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 %%gs:(%1),%%eax\n\t"			      \
+			    "movl %%gs:4(%1),%%edx"			      \
+			    : "=&A" (__value)				      \
+			    : "r" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+  __value;								      \
+})
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+#define THREAD_SETMEM(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%gs:%P1" :				      \
+			  : "q" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %0,%%gs:%P1" :				      \
+			  : "r" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   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_descr_struct,    \
+					     member)),			      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     member) + 4));		      \
+    }									      \
+})
+
+/* Set member of the thread descriptor directly.  */
+#define THREAD_SETMEM_NC(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%gs:(%1)" :				      \
+			  : "q" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %0,%%gs:(%1)" :				      \
+			  : "r" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   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_descr_struct,    \
+					     member)));			      \
+    }									      \
+})
+#endif
+
+#if __ASSUME_LDT_WORKS > 0
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS	1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE	8*1024*1024
+#endif
diff --git a/linuxthreads/sysdeps/ia64/Makefile b/linuxthreads/sysdeps/ia64/Makefile
new file mode 100644
index 0000000000..81bddf688c
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/ia64/Versions b/linuxthreads/sysdeps/ia64/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/ia64/pspinlock.c b/linuxthreads/sysdeps/ia64/pspinlock.c
new file mode 100644
index 0000000000..14c7f3a181
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/pspinlock.c
@@ -0,0 +1,79 @@
+/* POSIX spinlock implementation.  ia64 version.
+   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jes Sorensen <jes@linuxcare.com>
+
+   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 "internals.h"
+#include <ia64intrin.h>
+
+/* This implementation is inspired by the implementation used in the
+   Linux kernel. */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  int *p = (int *) lock;
+  
+  while (__builtin_expect (__sync_val_compare_and_swap_si (p, 0, 1), 0))
+    {
+      /* Spin without using the atomic instruction.  */
+      do
+        __asm __volatile ("" : : : "memory");
+      while (*p);
+    }
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return __sync_val_compare_and_swap_si ((int *) lock, 0, 1) == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/ia64/pt-machine.h b/linuxthreads/sysdeps/ia64/pt-machine.h
new file mode 100644
index 0000000000..6c5dfe93bb
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/pt-machine.h
@@ -0,0 +1,133 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   IA-64 version.
+   Copyright (C) 1999, 2000, 2002, 2003, 2004 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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <ia64intrin.h>
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Make sure gcc doesn't try to be clever and move things around on
+   us. We need to use _exactly_ the address the user gave us, not some
+   alias that contains the same information.  */
+#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
+
+#ifndef ELF_MACHINE_NAME
+
+#define NEED_SEPARATE_REGISTER_STACK
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.
+   r12 (sp) is the stack pointer. */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char *stack_pointer __asm__ ("sp");
+
+
+/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("r13");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+
+/* Memory barrier */
+#define MEMORY_BARRIER() __sync_synchronize ()
+
+
+#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int readval;
+
+  __asm__ __volatile__
+       ("mov ar.ccv=%4;;\n\t"
+	"cmpxchg8.acq %0=%1,%2,ar.ccv"
+	: "=r" (readval), "=m" (__atomic_fool_gcc (p))
+	: "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval)
+	: "memory");
+  return readval == oldval;
+}
+
+PT_EI int
+__compare_and_swap_with_release_semantics (long int *p,
+					   long int oldval,
+					   long int newval)
+{
+  long int readval;
+
+  __asm__ __volatile__
+       ("mov ar.ccv=%4;;\n\t"
+	"cmpxchg8.rel %0=%1,%2,ar.ccv"
+	: "=r" (readval), "=m" (__atomic_fool_gcc (p))
+	: "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval)
+	: "memory");
+  return readval == oldval;
+}
+
+#endif /* ELF_MACHINE_NAME */
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__(
+       "xchg4 %0=%1,%2"
+       : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock))
+       : "r"(1), "m"(__atomic_fool_gcc (spinlock))
+       : "memory");
+
+  return ret;
+}
+
+/* Indicate that we are looping.  */
+#define BUSY_WAIT_NOP	__asm__ ("hint @pause")
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/ia64/tcb-offsets.sym b/linuxthreads/sysdeps/ia64/tcb-offsets.sym
new file mode 100644
index 0000000000..f7793f7665
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/tcb-offsets.sym
@@ -0,0 +1,9 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+#ifdef USE_TLS
+MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - sizeof (struct _pthread_descr_struct)
+#else
+MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+#endif
diff --git a/linuxthreads/sysdeps/ia64/tls.h b/linuxthreads/sysdeps/ia64/tls.h
new file mode 100644
index 0000000000..3ec2eda783
--- /dev/null
+++ b/linuxthreads/sysdeps/ia64/tls.h
@@ -0,0 +1,141 @@
+/* Definitions for thread-local data handling.  linuxthreads/IA-64 version.
+   Copyright (C) 2002, 2003, 2004 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
+
+#ifndef __ASSEMBLER__
+
+# include <dl-sysdep.h>
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS        1
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+/* 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 (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+#  define TLS_DTV_AT_TP 1
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(tcbp, dtvp) \
+  ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(DTV) \
+  (((tcbhead_t *)__thread_self)->dtv = (DTV))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
+
+#if defined NEED_DL_SYSINFO
+# define INIT_SYSINFO \
+  (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo))
+#else
+# define INIT_SYSINFO 0
+#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(tcbp, secondcall) \
+  (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL)
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *)__thread_self)->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF (__thread_self - 1)
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(descr, nr) \
+  (__thread_self = (struct _pthread_descr_struct *)(descr) + 1)
+
+# define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+# endif
+
+#else
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  void *tcb;
+  dtv_t *dtv;
+  void *self;
+  int multiple_threads;
+} tcbhead_t;
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+#  define NONTLS_INIT_TP \
+  do { 									\
+    static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 };	\
+    __thread_self = (__typeof (__thread_self)) &nontls_init_tp;		\
+  } while (0)
+
+#endif
+
+#endif /* USE_TLS */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/m68k/Makefile b/linuxthreads/sysdeps/m68k/Makefile
new file mode 100644
index 0000000000..1cd27d44ca
--- /dev/null
+++ b/linuxthreads/sysdeps/m68k/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(subdir), linuxthreads)
+object-suffixes-left := $(libpthread-nonshared)
+define o-iterator-doit
+$(objpfx)$o.os: pic-ccflag = -fPIC
+endef
+include $(o-iterator)
+endif
diff --git a/linuxthreads/sysdeps/m68k/pspinlock.c b/linuxthreads/sysdeps/m68k/pspinlock.c
new file mode 100644
index 0000000000..30b9b9e8b9
--- /dev/null
+++ b/linuxthreads/sysdeps/m68k/pspinlock.c
@@ -0,0 +1,82 @@
+/* POSIX spinlock implementation.  M68k version.
+   Copyright (C) 2000 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 "internals.h"
+
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  do
+    asm volatile ("tas %1; sne %0"
+		  : "=dm" (val), "=m" (*lock)
+		  : "m" (*lock)
+		  : "cc");
+  while (val);
+
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  asm volatile ("tas %1; sne %0"
+		: "=dm" (val), "=m" (*lock)
+		: "m" (*lock)
+		: "cc");
+
+  return val ? EBUSY : 0;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/m68k/pt-machine.h b/linuxthreads/sysdeps/m68k/pt-machine.h
new file mode 100644
index 0000000000..ad524d6d2e
--- /dev/null
+++ b/linuxthreads/sysdeps/m68k/pt-machine.h
@@ -0,0 +1,69 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   m68k version.
+   Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  char ret;
+
+  __asm__ __volatile__("tas %1; sne %0"
+       : "=dm"(ret), "=m"(*spinlock)
+       : "m"(*spinlock)
+       : "cc");
+
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("%sp");
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("casl %2, %3, %1; seq %0"
+			: "=dm" (ret), "=m" (*p), "=d" (readval)
+			: "d" (newval), "m" (*p), "2" (oldval));
+
+  return ret;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/mips/pspinlock.c b/linuxthreads/sysdeps/mips/pspinlock.c
new file mode 100644
index 0000000000..350aa7553c
--- /dev/null
+++ b/linuxthreads/sysdeps/mips/pspinlock.c
@@ -0,0 +1,98 @@
+/* POSIX spinlock implementation.  MIPS version.
+   Copyright (C) 2000, 2002, 2003, 2004 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 <sgidefs.h>
+#include <sys/tas.h>
+#include "internals.h"
+
+#include <sgidefs.h>
+
+/* This implementation is similar to the one used in the Linux kernel.  */
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int tmp1, tmp2;
+
+  asm volatile
+    ("\t\t\t# spin_lock\n"
+     "1:\n\t"
+     ".set	push\n\t"
+#if _MIPS_SIM == _ABIO32
+     ".set	mips2\n\t"
+#endif
+     "ll	%1,%3\n\t"
+     "li	%2,1\n\t"
+     "bnez	%1,1b\n\t"
+     "sc	%2,%0\n\t"
+     ".set	pop\n\t"
+     "beqz	%2,1b"
+     : "=m" (*lock), "=&r" (tmp1), "=&r" (tmp2)
+     : "m" (*lock)
+     : "memory");
+
+  return 0;
+}
+
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  /* To be done.  */
+  return 0;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("\t\t\t# spin_unlock\n\t"
+     "sw	$0,%0"
+     : "=m" (*lock)
+     :
+     : "memory");
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/mips/pt-machine.h b/linuxthreads/sysdeps/mips/pt-machine.h
new file mode 100644
index 0000000000..96f7a7f8c6
--- /dev/null
+++ b/linuxthreads/sysdeps/mips/pt-machine.h
@@ -0,0 +1,92 @@
+/* Machine-dependent pthreads configuration and inline functions.
+
+   Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ralf Baechle <ralf@gnu.org>.
+   Based on the Alpha version by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <sgidefs.h>
+#include <sys/tas.h>
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+
+/* Spinlock implementation; required.  */
+
+PT_EI long int
+testandset (int *spinlock)
+{
+  return _test_and_set (spinlock, 1);
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("$29");
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int ret, temp;
+
+  __asm__ __volatile__
+    ("/* Inline compare & swap */\n"
+     "1:\n\t"
+     ".set	push\n\t"
+#if _MIPS_SIM == _ABIO32
+     ".set	mips2\n\t"
+#endif
+#if _MIPS_SIM == _ABI64
+     "lld	%1,%5\n\t"
+#else
+     "ll	%1,%5\n\t"
+#endif
+     "move	%0,$0\n\t"
+     "bne	%1,%3,2f\n\t"
+     "move	%0,%4\n\t"
+#if _MIPS_SIM == _ABI64
+     "scd	%0,%2\n\t"
+#else
+     "sc	%0,%2\n\t"
+#endif
+     ".set	pop\n\t"
+     "beqz	%0,1b\n"
+     "2:\n\t"
+     "/* End compare & swap */"
+     : "=&r" (ret), "=&r" (temp), "=m" (*p)
+     : "r" (oldval), "r" (newval), "m" (*p)
+     : "memory");
+
+  return ret;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/powerpc/Makefile b/linuxthreads/sysdeps/powerpc/Makefile
new file mode 100644
index 0000000000..33e4aceb5b
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(subdir):$(elf),linuxthreads:yes)
+# See CFLAGS-initfini.s above; this is the same code.
+CFLAGS-pt-initfini.s = -g0 -fpic -O1
+endif
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c b/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c
new file mode 100644
index 0000000000..15fd545c14
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c
@@ -0,0 +1,70 @@
+/* POSIX spinlock implementation.  PowerPC version.
+   Copyright (C) 2000, 2003 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 "internals.h"
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  while (! __compare_and_swap ((long int *)lock, 0, 1))
+    ;
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return __compare_and_swap ((long int *)lock, 0, 1) ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  MEMORY_BARRIER ();
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h b/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h
new file mode 100644
index 0000000000..8363d16d08
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h
@@ -0,0 +1,120 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   powerpc version.
+   Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003
+   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.  */
+
+/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor
+   User's Manual', by IBM and Motorola.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* For multiprocessor systems, we want to ensure all memory accesses
+   are completed before we reset a lock.  On other systems, we still
+   need to make sure that the compiler has flushed everything to memory.  */
+#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory")
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     8*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("r1");
+
+/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("r2");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) (descr), THREAD_SELF->member = (value))
+
+/* Compare-and-swap for semaphores. */
+/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */
+
+#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define IMPLEMENT_TAS_WITH_CAS
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  int ret;
+
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  /* This version of __compare_and_swap is to be used when acquiring
+     a lock, so we don't need to worry about whether other memory
+     operations have completed, but we do need to be sure that any loads
+     after this point really occur after we have acquired the lock.  */
+  __asm__ __volatile__ ("isync" : : : "memory");
+  return ret == 0;
+}
+
+PT_EI int
+__compare_and_swap_with_release_semantics (long int *p,
+					   long int oldval, long int newval)
+{
+  int ret;
+
+  MEMORY_BARRIER ();
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  return ret == 0;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c b/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c
new file mode 100644
index 0000000000..19161c6e10
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c
@@ -0,0 +1,70 @@
+/* POSIX spinlock implementation.  PowerPC version.
+   Copyright (C) 2000, 2003 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 "internals.h"
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  while (! __compare_and_swap32 ((int *)lock, 0, 1))
+    ;
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return __compare_and_swap32 ((int *)lock, 0, 1) ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  MEMORY_BARRIER ();
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h b/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h
new file mode 100644
index 0000000000..562e69fa18
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h
@@ -0,0 +1,185 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   powerpc version.
+   Copyright (C) 2002, 2003 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.  */
+
+/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor
+   User's Manual', by IBM and Motorola.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+extern int __compare_and_swap32 (int *p, int oldval, int newval);
+
+/* For multiprocessor systems, we want to ensure all memory accesses
+   are completed before we reset a lock.  On other systems, we still
+   need to make sure that the compiler has flushed everything to memory.  */
+#define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory")
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     16*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("r1");
+
+/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("r13");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) (descr), THREAD_SELF->member = (value))
+
+/* Compare-and-swap for semaphores. */
+/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */
+
+#define HAS_COMPARE_AND_SWAP
+#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	   "0:    ldarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stdcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  /* This version of __compare_and_swap is to be used when acquiring
+     a lock, so we don't need to worry about whether other memory
+     operations have completed, but we do need to be sure that any loads
+     after this point really occur after we have acquired the lock.  */
+  __asm__ __volatile__ ("isync" : : : "memory");
+  return (int)(ret == 0);
+}
+
+PT_EI int
+__compare_and_swap_with_release_semantics (long int *p,
+					   long int oldval, long int newval)
+{
+  long int ret;
+
+  MEMORY_BARRIER ();
+  __asm__ __volatile__ (
+	   "0:    ldarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stdcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  return (int)(ret == 0);
+}
+
+PT_EI int
+__compare_and_swap32 (int *p, int oldval, int newval)
+{
+  int ret;
+
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  /* This version of __compare_and_swap is to be used when acquiring
+     a lock, so we don't need to worry about whether other memory
+     operations have completed, but we do need to be sure that any loads
+     after this point really occur after we have acquired the lock.  */
+  __asm__ __volatile__ ("isync" : : : "memory");
+  return (int)(ret == 0);
+}
+
+PT_EI int
+__compare_and_swap32_with_release_semantics (long int *p,
+					   long int oldval, long int newval)
+{
+  long int ret;
+
+  MEMORY_BARRIER ();
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  return (int)(ret == 0);
+}
+
+PT_EI long int
+testandset (int *p)
+{
+  long int ret, val = 1;
+
+  MEMORY_BARRIER ();
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      cmpwi  0,%0,0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r" (val)
+	: "cr0", "memory");
+  MEMORY_BARRIER ();
+  return ret != 0;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/powerpc/tcb-offsets.sym b/linuxthreads/sysdeps/powerpc/tcb-offsets.sym
new file mode 100644
index 0000000000..b526b62336
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/tcb-offsets.sym
@@ -0,0 +1,19 @@
+#include <sysdep.h>
+#include <tls.h>
+
+-- This line separates the #include lines from conditionals.
+
+# ifdef USE_TLS
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#  undef __thread_register
+#  define __thread_register	((void *) 0)
+#  define thread_offsetof(mem)	((void *) &THREAD_SELF->p_##mem - (void *) 0)
+
+# else
+
+#  define thread_offsetof(mem)	offsetof (tcbhead_t, mem)
+
+# endif
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (multiple_threads)
diff --git a/linuxthreads/sysdeps/powerpc/tls.h b/linuxthreads/sysdeps/powerpc/tls.h
new file mode 100644
index 0000000000..f6eb48b434
--- /dev/null
+++ b/linuxthreads/sysdeps/powerpc/tls.h
@@ -0,0 +1,160 @@
+/* Definitions for thread-local data handling.  linuxthreads/PPC version.
+   Copyright (C) 2003 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+
+/* This layout is actually wholly private and not affected by the ABI.
+   Nor does it overlap the pthread data structure, so we need nothing
+   extra here at all.  */
+typedef struct
+{
+  dtv_t *dtv;
+} tcbhead_t;
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE	0
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN	__alignof__ (struct _pthread_descr_struct)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE		0
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN		__alignof__ (struct _pthread_descr_struct)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE \
+  (sizeof (struct _pthread_descr_struct)				      \
+   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* The following assumes that TP (R2 or R13) is points to the end of the
+   TCB + 0x7000 (per the ABI).  This implies that TCB address is
+   TP - 0x7000.  As we define TLS_DTV_AT_TP we can
+   assume that the pthread_descr is allocated immediately ahead of the
+   TCB.  This implies that the pthread_descr address is
+   TP - (TLS_PRE_TCB_SIZE + 0x7000).  */
+#define TLS_TCB_OFFSET		0x7000
+
+/* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+/* This is not really true for powerpc64.  We are following alpha
+   where the DTV pointer is first doubleword in the TCB.  */
+#  define TLS_DTV_AT_TP 1
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(TCBP, DTVP) \
+  (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1)
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(TCBP)	(((tcbhead_t *) (TCBP))[-1].dtv)
+
+/* We still need this define so that tcb-offsets.sym can override it and
+   use THREAD_SELF to generate MULTIPLE_THREADS_OFFSET.  */
+#  define __thread_register ((void *) __thread_self)
+
+/* 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.
+   
+   The global register variable is declared in pt-machine.h with the 
+   wrong type, so we need some extra casts to get the desired result.  
+   This avoids a lvalue cast that gcc-3.4 does not like.  */
+# define TLS_INIT_TP(TCBP, SECONDCALL) \
+    (__thread_self = (struct _pthread_descr_struct *) \
+	((void *) (TCBP) + TLS_TCB_OFFSET), NULL)
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+     (((tcbhead_t *) ((void *) __thread_self - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+    ((pthread_descr) (__thread_register \
+		      - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(DESCR, NR) \
+     (__thread_self = (struct _pthread_descr_struct *)((void *) (DESCR) \
+		           + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE))
+
+/* Make sure we have the p_multiple_threads member in the thread structure.
+   See below.  */
+#  define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
+   different value to mean unset l_tls_offset.  */
+#  define NO_TLS_OFFSET	-1
+
+# endif /* __ASSEMBLER__ */
+
+#elif !defined __ASSEMBLER__
+
+/* This overlaps the start of the pthread_descr.  System calls
+   and such use this to find the multiple_threads flag and need
+   to use the same offset relative to the thread register in both
+   single-threaded and multi-threaded code.  */
+typedef struct
+{
+  void *tcb;			/* Never used.  */
+  dtv_t *dtv;			/* Never used.  */
+  void *self;			/* Used only if multithreaded, and rarely.  */
+  int multiple_threads;		/* Only this member is really used.  */
+} tcbhead_t;
+
+#define NONTLS_INIT_TP							\
+  do {									\
+    static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 };	\
+    __thread_self = (__typeof (__thread_self)) &nontls_init_tp;		\
+  } while (0)
+
+#endif /* HAVE_TLS_SUPPORT */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/pthread/Makefile b/linuxthreads/sysdeps/pthread/Makefile
new file mode 100644
index 0000000000..f73f40e9d9
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/Makefile
@@ -0,0 +1,14 @@
+ifeq ($(subdir),rt)
+librt-sysdep_routines += timer_routines
+CPPFLAGS += -DBROKEN_THREAD_SIGNALS
+
+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
+
+ifeq ($(subdir),posix)
+CFLAGS-confstr.c += -DLIBPTHREAD_VERSION="\"$(shell sed 's/\(.*\) by .*/\1/' ../linuxthreads/Banner)\""
+endif
diff --git a/linuxthreads/sysdeps/pthread/Subdirs b/linuxthreads/sysdeps/pthread/Subdirs
new file mode 100644
index 0000000000..2c56497842
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/Subdirs
@@ -0,0 +1 @@
+linuxthreads_db
diff --git a/linuxthreads/sysdeps/pthread/bits/initspin.h b/linuxthreads/sysdeps/pthread/bits/initspin.h
new file mode 100644
index 0000000000..a19ec077e8
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/bits/initspin.h
@@ -0,0 +1,28 @@
+/* Generic definitions for spinlock initializers.
+   Copyright (C) 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 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.  */
+
+/* Initial value of a spinlock.  Most platforms should use zero,
+   unless they only implement a "test and clear" operation instead of
+   the usual "test and set". */
+#define __LT_SPINLOCK_INIT 0
+
+/* Macros for lock initializers, using the above definition. */
+#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT }
diff --git a/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/linuxthreads/sysdeps/pthread/bits/libc-lock.h
new file mode 100644
index 0000000000..7e22166862
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/bits/libc-lock.h
@@ -0,0 +1,413 @@
+/* libc-internal interface for mutex locks.  LinuxThreads version.
+   Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
+   	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.  */
+
+#ifndef _BITS_LIBC_LOCK_H
+#define _BITS_LIBC_LOCK_H 1
+
+#include <pthread.h>
+
+#if defined _LIBC && !defined NOT_IN_libc
+#include <linuxthreads/internals.h>
+#endif
+
+/* 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
+typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
+#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 __rtld_lock_define_recursive(CLASS,NAME) \
+  CLASS __rtld_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}
+
+#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
+#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
+  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
+
+#if defined _LIBC && defined IS_IN_libpthread
+# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
+#else
+# if defined __PIC__ || (defined _LIBC && defined SHARED)
+#  define __libc_maybe_call(FUNC, ARGS, ELSE) \
+  (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
+                    _fn != NULL ? (*_fn) ARGS : ELSE; }))
+# else
+#  define __libc_maybe_call(FUNC, ARGS, ELSE) \
+  (FUNC != NULL ? FUNC ARGS : ELSE)
+# endif
+#endif
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+# define __libc_maybe_call2(FUNC, ARGS, ELSE) \
+  ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \
+    ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; })
+#else
+# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
+#endif
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+   state.  */
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+#define __libc_lock_init(NAME) \
+  ({									      \
+    (NAME).__m_count = 0;						      \
+    (NAME).__m_owner = NULL;						      \
+    (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP;				      \
+    (NAME).__m_lock.__status = 0;					      \
+    (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;			      \
+    0; })
+#else
+#define __libc_lock_init(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
+#endif
+#define __libc_rwlock_init(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
+
+/* Same as last but this time we initialize a recursive mutex.  */
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+#define __libc_lock_init_recursive(NAME) \
+  ({									      \
+    (NAME).mutex.__m_count = 0;						      \
+    (NAME).mutex.__m_owner = NULL;					      \
+    (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP;			      \
+    (NAME).mutex.__m_lock.__status = 0;					      \
+    (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT;		      \
+    0; })
+#else
+#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);
+#endif
+#define __rtld_lock_init_recursive(NAME) \
+  __libc_lock_init_recursive (NAME)
+
+/* 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) \
+  (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
+#define __libc_rwlock_fini(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
+
+/* Finalize recursive named lock.  */
+#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
+#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
+
+/* Lock the named lock variable.  */
+#define __libc_lock_lock(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
+#define __libc_rwlock_rdlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
+#define __libc_rwlock_wrlock(NAME) \
+  (__libc_maybe_call (__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) \
+  (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
+#define __libc_rwlock_tryrdlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
+#define __libc_rwlock_trywrlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
+
+/* Try to lock the recursive named lock variable.  */
+#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
+#define __rtld_lock_trylock_recursive(NAME) \
+  __libc_lock_trylock_recursive (NAME)
+
+/* Unlock the named lock variable.  */
+#define __libc_lock_unlock(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
+#define __libc_rwlock_unlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
+
+/* Unlock the recursive named lock variable.  */
+#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
+
+#if defined _LIBC && defined SHARED
+# define __rtld_lock_default_lock_recursive(lock) \
+  ++((pthread_mutex_t *)(lock))->__m_count;
+
+# define __rtld_lock_default_unlock_recursive(lock) \
+  --((pthread_mutex_t *)(lock))->__m_count;
+
+# define __rtld_lock_lock_recursive(NAME) \
+  GL(dl_rtld_lock_recursive) (&(NAME).mutex)
+
+# define __rtld_lock_unlock_recursive(NAME) \
+  GL(dl_rtld_unlock_recursive) (&(NAME).mutex)
+#else
+#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME)
+#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME)
+#endif
+
+/* 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) = 2;						      \
+    }									      \
+  } 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));			      \
+    }
+
+#define __libc_cleanup_push(fct, arg) \
+    { struct _pthread_cleanup_buffer _buffer; 				      \
+    __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
+
+#define __libc_cleanup_pop(execute) \
+    __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0);	      \
+    }
+
+/* Create thread-specific key.  */
+#define __libc_key_create(KEY, DESTRUCTOR) \
+  (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
+
+/* Get thread-specific data.  */
+#define __libc_getspecific(KEY) \
+  (__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
+
+/* Set thread-specific data.  */
+#define __libc_setspecific(KEY, VALUE) \
+  (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
+
+
+/* Register handlers to execute before and after `fork'.  */
+#define __libc_atfork(PREPARE, PARENT, CHILD) \
+  (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
+
+/* 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))
+weak_extern (BP_SYM (_pthread_cleanup_pop))
+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
+#  pragma weak _pthread_cleanup_push
+#  pragma weak _pthread_cleanup_pop
+# 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/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/linuxthreads/sysdeps/pthread/bits/libc-tsd.h
new file mode 100644
index 0000000000..fa6eb4be28
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/bits/libc-tsd.h
@@ -0,0 +1,59 @@
+/* libc-internal interface for thread-specific data.  LinuxThreads version.
+   Copyright (C) 1997-2002, 2003 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.  */
+
+#ifndef _BITS_LIBC_TSD_H
+#define _BITS_LIBC_TSD_H 1
+
+#include <linuxthreads/descr.h>
+#include <tls.h>
+
+#if USE_TLS && HAVE___THREAD
+
+/* When __thread works, the generic definition is what we want.  */
+# include <sysdeps/generic/bits/libc-tsd.h>
+
+#else
+
+# include <bits/libc-lock.h>
+
+# ifndef SHARED
+extern void ** __pthread_internal_tsd_address (int);
+extern void *__pthread_internal_tsd_get (int);
+extern int __pthread_internal_tsd_set (int, const void *);
+
+weak_extern (__pthread_internal_tsd_address)
+weak_extern (__pthread_internal_tsd_get)
+weak_extern (__pthread_internal_tsd_set)
+# endif
+
+#define __libc_tsd_define(CLASS, KEY)	CLASS void *__libc_tsd_##KEY##_data;
+#define __libc_tsd_address(KEY) \
+  __libc_maybe_call2 (pthread_internal_tsd_address,			\
+		      (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data)
+#define __libc_tsd_get(KEY) \
+  __libc_maybe_call2 (pthread_internal_tsd_get,				\
+		      (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data)
+#define __libc_tsd_set(KEY, VALUE) \
+  __libc_maybe_call2 (pthread_internal_tsd_set,				\
+		      (_LIBC_TSD_KEY_##KEY, (VALUE)),			\
+		       (__libc_tsd_##KEY##_data = (VALUE), 0))
+
+#endif
+
+#endif	/* bits/libc-tsd.h */
diff --git a/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h
new file mode 100644
index 0000000000..d1daef07aa
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h
@@ -0,0 +1,152 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#if !defined _BITS_TYPES_H && !defined _PTHREAD_H
+# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#define __need_schedparam
+#include <bits/sched.h>
+
+/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
+struct _pthread_fastlock
+{
+  long int __status;   /* "Free" or "taken" or head of waiting list */
+  int __spinlock;      /* Used by compare_and_swap emulation. Also,
+			  adaptive SMP lock stores spin count here. */
+};
+
+#ifndef _PTHREAD_DESCR_DEFINED
+/* Thread descriptors */
+typedef struct _pthread_descr_struct *_pthread_descr;
+# define _PTHREAD_DESCR_DEFINED
+#endif
+
+
+/* Attributes for threads.  */
+typedef struct __pthread_attr_s
+{
+  int __detachstate;
+  int __schedpolicy;
+  struct __sched_param __schedparam;
+  int __inheritsched;
+  int __scope;
+  size_t __guardsize;
+  int __stackaddr_set;
+  void *__stackaddr;
+  size_t __stacksize;
+} pthread_attr_t;
+
+
+/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */
+
+#ifdef __GLIBC_HAVE_LONG_LONG
+__extension__ typedef long long __pthread_cond_align_t;
+#else
+typedef long __pthread_cond_align_t;
+#endif
+
+typedef struct
+{
+  struct _pthread_fastlock __c_lock; /* Protect against concurrent access */
+  _pthread_descr __c_waiting;        /* Threads waiting on this condition */
+  char __padding[48 - sizeof (struct _pthread_fastlock)
+		 - sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)];
+  __pthread_cond_align_t __align;
+} pthread_cond_t;
+
+
+/* Attribute for conditionally variables.  */
+typedef struct
+{
+  int __dummy;
+} pthread_condattr_t;
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER).  */
+/* (The layout is unnatural to maintain binary compatibility
+    with earlier releases of LinuxThreads.) */
+typedef struct
+{
+  int __m_reserved;               /* Reserved for future use */
+  int __m_count;                  /* Depth of recursive locking */
+  _pthread_descr __m_owner;       /* Owner thread (if recursive or errcheck) */
+  int __m_kind;                   /* Mutex kind: fast, recursive or errcheck */
+  struct _pthread_fastlock __m_lock; /* Underlying fast lock */
+} pthread_mutex_t;
+
+
+/* Attribute for mutex.  */
+typedef struct
+{
+  int __mutexkind;
+} pthread_mutexattr_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Read-write locks.  */
+typedef struct _pthread_rwlock_t
+{
+  struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */
+  int __rw_readers;                   /* Number of readers */
+  _pthread_descr __rw_writer;         /* Identity of writer, or NULL if none */
+  _pthread_descr __rw_read_waiting;   /* Threads waiting for reading */
+  _pthread_descr __rw_write_waiting;  /* Threads waiting for writing */
+  int __rw_kind;                      /* Reader/Writer preference selection */
+  int __rw_pshared;                   /* Shared between processes or not */
+} pthread_rwlock_t;
+
+
+/* Attribute for read-write locks.  */
+typedef struct
+{
+  int __lockkind;
+  int __pshared;
+} pthread_rwlockattr_t;
+#endif
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t;
+
+/* POSIX barrier. */
+typedef struct {
+  struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */
+  int __ba_required;                  /* Threads needed for completion */
+  int __ba_present;                   /* Threads waiting */
+  _pthread_descr __ba_waiting;        /* Queue of waiting threads */
+} pthread_barrier_t;
+
+/* barrier attribute */
+typedef struct {
+  int __pshared;
+} pthread_barrierattr_t;
+
+#endif
+
+
+/* Thread identifiers */
+typedef unsigned long int pthread_t;
+
+#endif	/* bits/pthreadtypes.h */
diff --git a/linuxthreads/sysdeps/pthread/bits/typesizes.h b/linuxthreads/sysdeps/pthread/bits/typesizes.h
new file mode 100644
index 0000000000..45264ac9cf
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/bits/typesizes.h
@@ -0,0 +1,66 @@
+/* bits/typesizes.h -- underlying types for *_t.  Generic version.
+   Copyright (C) 2002, 2003 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 _BITS_TYPES_H
+# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TYPESIZES_H
+#define	_BITS_TYPESIZES_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#define __DEV_T_TYPE		__UQUAD_TYPE
+#define __UID_T_TYPE		__U32_TYPE
+#define __GID_T_TYPE		__U32_TYPE
+#define __INO_T_TYPE		__ULONGWORD_TYPE
+#define __INO64_T_TYPE		__UQUAD_TYPE
+#define __MODE_T_TYPE		__U32_TYPE
+#define __NLINK_T_TYPE		__UWORD_TYPE
+#define __OFF_T_TYPE		__SLONGWORD_TYPE
+#define __OFF64_T_TYPE		__SQUAD_TYPE
+#define __PID_T_TYPE		__S32_TYPE
+#define __RLIM_T_TYPE		__ULONGWORD_TYPE
+#define __RLIM64_T_TYPE		__UQUAD_TYPE
+#define	__BLKCNT_T_TYPE		__SLONGWORD_TYPE
+#define	__BLKCNT64_T_TYPE	__SQUAD_TYPE
+#define	__FSBLKCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSBLKCNT64_T_TYPE	__UQUAD_TYPE
+#define	__FSFILCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSFILCNT64_T_TYPE	__UQUAD_TYPE
+#define	__ID_T_TYPE		__U32_TYPE
+#define __CLOCK_T_TYPE		__SLONGWORD_TYPE
+#define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __USECONDS_T_TYPE	__U32_TYPE
+#define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
+#define __DADDR_T_TYPE		__S32_TYPE
+#define __SWBLK_T_TYPE		__SLONGWORD_TYPE
+#define __KEY_T_TYPE		__S32_TYPE
+#define __CLOCKID_T_TYPE	__S32_TYPE
+#define __TIMER_T_TYPE		__S32_TYPE
+#define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE
+#define __FSID_T_TYPE		struct { int __val[2]; }
+#define __SSIZE_T_TYPE		__SWORD_TYPE
+
+/* Number of descriptors that can fit in an `fd_set'.  */
+#define	__FD_SETSIZE		1024
+
+
+#endif /* bits/typesizes.h */
diff --git a/linuxthreads/sysdeps/pthread/errno-loc.c b/linuxthreads/sysdeps/pthread/errno-loc.c
new file mode 100644
index 0000000000..0a8f0f9076
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/errno-loc.c
@@ -0,0 +1,46 @@
+/* MT support function to get address of `errno' variable, linuxthreads
+   version.
+   Copyright (C) 1996, 1998, 2002, 2003, 2004 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 <errno.h>
+#include <tls.h>
+#include <linuxthreads/internals.h>
+#include <sysdep-cancel.h>
+
+#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO
+#undef errno
+extern int errno;
+#endif
+
+int *
+#if ! USE___THREAD
+weak_const_function
+#endif
+__errno_location (void)
+{
+#if ! USE___THREAD && !defined NOT_IN_libc
+  if (! SINGLE_THREAD_P)
+    {
+      pthread_descr self = thread_self();
+      return LIBC_THREAD_GETMEM (self, p_errnop);
+    }
+#endif
+  return &errno;
+}
+libc_hidden_def (__errno_location)
diff --git a/linuxthreads/sysdeps/pthread/flockfile.c b/linuxthreads/sysdeps/pthread/flockfile.c
new file mode 100644
index 0000000000..918cb84f61
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/flockfile.c
@@ -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.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <libio.h>
+#include <bits/stdio-lock.h>
+
+
+void
+__flockfile (stream)
+     FILE *stream;
+{
+  _IO_lock_lock (*stream->_lock);
+}
+strong_alias (__flockfile, _IO_flockfile)
+weak_alias (__flockfile, flockfile)
diff --git a/linuxthreads/sysdeps/pthread/ftrylockfile.c b/linuxthreads/sysdeps/pthread/ftrylockfile.c
new file mode 100644
index 0000000000..21c1ea01ed
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/ftrylockfile.c
@@ -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.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <bits/stdio-lock.h>
+
+
+int
+__ftrylockfile (stream)
+     FILE *stream;
+{
+  return _IO_lock_trylock (*stream->_lock);
+}
+strong_alias (__ftrylockfile, _IO_ftrylockfile)
+weak_alias (__ftrylockfile, ftrylockfile)
diff --git a/linuxthreads/sysdeps/pthread/funlockfile.c b/linuxthreads/sysdeps/pthread/funlockfile.c
new file mode 100644
index 0000000000..f941fc9851
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/funlockfile.c
@@ -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.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <libio.h>
+#include <bits/stdio-lock.h>
+
+
+void
+__funlockfile (stream)
+     FILE *stream;
+{
+  _IO_lock_unlock (*stream->_lock);
+}
+strong_alias (__funlockfile, _IO_funlockfile)
+weak_alias (__funlockfile, funlockfile)
diff --git a/linuxthreads/sysdeps/pthread/getcpuclockid.c b/linuxthreads/sysdeps/pthread/getcpuclockid.c
new file mode 100644
index 0000000000..032caeb081
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/getcpuclockid.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2000, 2001, 2004 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 <time.h>
+#include <internals.h>
+
+int
+pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id)
+{
+#ifdef CLOCK_THREAD_CPUTIME_ID
+  /* We need to store the thread ID in the CLOCKID variable together
+     with a number identifying the clock.  We reserve the low 3 bits
+     for the clock ID and the rest for the thread ID.  This is
+     problematic if the thread ID is too large.  But 29 bits should be
+     fine.
+
+     If some day more clock IDs are needed the ID part can be
+     enlarged.  The IDs are entirely internal.  */
+  if (2 * PTHREAD_THREADS_MAX
+      >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE))
+    return ERANGE;
+
+  /* Store the number.  */
+  *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE);
+
+  return 0;
+#else
+  /* We don't have a timer for that.  */
+  return ENOENT;
+#endif
+}
diff --git a/linuxthreads/sysdeps/pthread/herrno-loc.c b/linuxthreads/sysdeps/pthread/herrno-loc.c
new file mode 100644
index 0000000000..fbc5576166
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/herrno-loc.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1996, 97, 98, 2002, 2003 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 <netdb.h>
+#include <tls.h>
+#include <linuxthreads/internals.h>
+#include <sysdep-cancel.h>
+
+#if ! USE___THREAD
+# undef h_errno
+extern int h_errno;
+#endif
+
+/* When threaded, h_errno may be a per-thread variable.  */
+int *
+weak_const_function
+__h_errno_location (void)
+{
+#if ! USE___THREAD
+  if (! SINGLE_THREAD_P)
+    {
+      pthread_descr self = thread_self();
+      return LIBC_THREAD_GETMEM (self, p_h_errnop);
+    }
+#endif
+  return &h_errno;
+}
+libc_hidden_def (__h_errno_location)
diff --git a/linuxthreads/sysdeps/pthread/list.h b/linuxthreads/sysdeps/pthread/list.h
new file mode 100644
index 0000000000..43186a2d51
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/list.h
@@ -0,0 +1,114 @@
+/* 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
+
+/* 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/linuxthreads/sysdeps/pthread/malloc-machine.h b/linuxthreads/sysdeps/pthread/malloc-machine.h
new file mode 100644
index 0000000000..5191f8c779
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/malloc-machine.h
@@ -0,0 +1,67 @@
+/* Basic platform-independent macro definitions for mutexes,
+   thread-specific data and parameters for malloc.
+   Copyright (C) 2003 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 _MALLOC_MACHINE_H
+#define _MALLOC_MACHINE_H
+
+#undef thread_atfork_static
+
+#include <atomic.h>
+#include <bits/libc-lock.h>
+
+__libc_lock_define (typedef, mutex_t)
+
+#define mutex_init(m)		\
+  __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
+#define mutex_lock(m)		\
+  __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
+#define mutex_trylock(m)	\
+  __libc_maybe_call2 (pthread_mutex_trylock, (m), \
+		      (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
+#define mutex_unlock(m)		\
+  __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0))
+
+/* This is defined by newer gcc version unique for each module.  */
+extern void *__dso_handle __attribute__ ((__weak__));
+
+#include <fork.h>
+
+#ifdef SHARED
+# define thread_atfork(prepare, parent, child) \
+   __register_atfork (prepare, parent, child, __dso_handle)
+#else
+# define thread_atfork(prepare, parent, child) \
+   __register_atfork (prepare, parent, child,				      \
+		      &__dso_handle == NULL ? NULL : __dso_handle)
+#endif
+
+/* thread specific data for glibc */
+
+#include <bits/libc-tsd.h>
+
+typedef int tsd_key_t[1];	/* no key data structure, libc magic does it */
+__libc_tsd_define (static, MALLOC)	/* declaration/common definition */
+#define tsd_key_create(key, destr)	((void) (key))
+#define tsd_setspecific(key, data)	__libc_tsd_set (MALLOC, (data))
+#define tsd_getspecific(key, vptr)	((vptr) = __libc_tsd_get (MALLOC))
+
+#include <sysdeps/generic/malloc-machine.h>
+
+#endif /* !defined(_MALLOC_MACHINE_H) */
diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h
new file mode 100644
index 0000000000..1b0a2b65e4
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/posix-timer.h
@@ -0,0 +1,204 @@
+/* Definitions for POSIX timer implementation on top of LinuxThreads.
+   Copyright (C) 2000, 2002, 2004 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;
+
+
+/* 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/linuxthreads/sysdeps/pthread/pt-initfini.c b/linuxthreads/sysdeps/pthread/pt-initfini.c
new file mode 100644
index 0000000000..1ccac2f6ef
--- /dev/null
+++ b/linuxthreads/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 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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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/linuxthreads/sysdeps/pthread/pthread-functions.h b/linuxthreads/sysdeps/pthread/pthread-functions.h
new file mode 100644
index 0000000000..43a328ae9c
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/pthread-functions.h
@@ -0,0 +1,96 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _PTHREAD_FUNCTIONS_H
+#define _PTHREAD_FUNCTIONS_H	1
+
+#include <pthread.h>
+#include <setjmp.h>
+#include <linuxthreads/descr.h>
+
+struct fork_block;
+
+/* Data type shared with libc.  The libc uses it to pass on calls to
+   the thread functions.  Wine pokes directly into this structure,
+   so if possible avoid breaking it and append new hooks to the end.  */
+struct pthread_functions
+{
+  pid_t (*ptr_pthread_fork) (struct fork_block *);
+  int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
+  int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
+  int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
+  int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *,
+					 struct sched_param *);
+  int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *,
+					 const struct sched_param *);
+  int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
+  int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
+  int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
+  int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
+  int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
+  int (*ptr___pthread_cond_init) (pthread_cond_t *,
+				  const pthread_condattr_t *);
+  int (*ptr___pthread_cond_signal) (pthread_cond_t *);
+  int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
+  int (*ptr_pthread_equal) (pthread_t, pthread_t);
+  void (*ptr___pthread_exit) (void *);
+  int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
+  int (*ptr_pthread_setschedparam) (pthread_t, int,
+				    const struct sched_param *);
+  int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_init) (pthread_mutex_t *,
+				 const pthread_mutexattr_t *);
+  int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
+  pthread_t (*ptr_pthread_self) (void);
+  int (*ptr_pthread_setcancelstate) (int, int *);
+  int (*ptr_pthread_setcanceltype) (int, int *);
+  void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
+  void (*ptr_pthread_cleanup_upto) (__jmp_buf target,
+				    char *targetframe);
+  pthread_descr (*ptr_pthread_thread_self) (void);
+  int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
+  void * (*ptr_pthread_internal_tsd_get) (int key);
+  void ** __attribute__ ((__const__))
+    (*ptr_pthread_internal_tsd_address) (int key);
+  int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act,
+				struct sigaction *oact);
+  int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
+  int (*ptr_pthread_raise) (int sig);
+  int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *,
+				       const struct timespec *);
+  void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer,
+				     void (*routine)(void *), void * arg);
+
+  void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer,
+				    int execute);
+};
+
+/* Variable in libc.so.  */
+extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+
+#endif	/* pthread-functions.h */
diff --git a/linuxthreads/sysdeps/pthread/pthread.h b/linuxthreads/sysdeps/pthread/pthread.h
new file mode 100644
index 0000000000..86c7ff7391
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/pthread.h
@@ -0,0 +1,686 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+#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>
+#include <bits/initspin.h>
+
+
+__BEGIN_DECLS
+
+/* Initializers.  */
+
+#define PTHREAD_MUTEX_INITIALIZER \
+  {0, 0, 0, PTHREAD_MUTEX_TIMED_NP, __LOCK_INITIALIZER}
+#ifdef __USE_GNU
+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER}
+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER}
+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER}
+#endif
+
+#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0, "", 0}
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+# define PTHREAD_RWLOCK_INITIALIZER \
+  { __LOCK_INITIALIZER, 0, NULL, NULL, NULL,				      \
+    PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE }
+#endif
+#ifdef __USE_GNU
+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+  { __LOCK_INITIALIZER, 0, NULL, NULL, NULL,				      \
+    PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE }
+#endif
+
+/* Values for attributes.  */
+
+enum
+{
+  PTHREAD_CREATE_JOINABLE,
+#define PTHREAD_CREATE_JOINABLE	PTHREAD_CREATE_JOINABLE
+  PTHREAD_CREATE_DETACHED
+#define PTHREAD_CREATE_DETACHED	PTHREAD_CREATE_DETACHED
+};
+
+enum
+{
+  PTHREAD_INHERIT_SCHED,
+#define PTHREAD_INHERIT_SCHED	PTHREAD_INHERIT_SCHED
+  PTHREAD_EXPLICIT_SCHED
+#define PTHREAD_EXPLICIT_SCHED	PTHREAD_EXPLICIT_SCHED
+};
+
+enum
+{
+  PTHREAD_SCOPE_SYSTEM,
+#define PTHREAD_SCOPE_SYSTEM	PTHREAD_SCOPE_SYSTEM
+  PTHREAD_SCOPE_PROCESS
+#define PTHREAD_SCOPE_PROCESS	PTHREAD_SCOPE_PROCESS
+};
+
+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_ADAPTIVE_NP
+#endif
+};
+
+enum
+{
+  PTHREAD_PROCESS_PRIVATE,
+#define PTHREAD_PROCESS_PRIVATE	PTHREAD_PROCESS_PRIVATE
+  PTHREAD_PROCESS_SHARED
+#define PTHREAD_PROCESS_SHARED	PTHREAD_PROCESS_SHARED
+};
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+enum
+{
+  PTHREAD_RWLOCK_PREFER_READER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+  PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP
+};
+#endif	/* Unix98 */
+
+#define PTHREAD_ONCE_INIT 0
+
+/* Special constants */
+
+#ifdef __USE_XOPEN2K
+/* -1 is distinct from 0 and all errno constants */
+# define PTHREAD_BARRIER_SERIAL_THREAD -1
+#endif
+
+/* 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)
+
+
+/* Function for handling threads.  */
+
+/* Create a thread with given attributes ATTR (or default attributes
+   if ATTR is NULL), and call function START_ROUTINE with given
+   arguments ARG.  */
+extern int pthread_create (pthread_t *__restrict __threadp,
+			   __const pthread_attr_t *__restrict __attr,
+			   void *(*__start_routine) (void *),
+			   void *__restrict __arg) __THROW;
+
+/* Obtain the identifier of the current thread.  */
+extern pthread_t pthread_self (void) __THROW;
+
+/* Compare two thread identifiers.  */
+extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW;
+
+/* Terminate calling thread.  */
+extern void pthread_exit (void *__retval) __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);
+
+/* 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;
+
+
+/* Functions for handling attributes.  */
+
+/* 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;
+
+/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE.  */
+extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
+					int __detachstate) __THROW;
+
+/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR.  */
+extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr,
+					int *__detachstate) __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 *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 policy in *ATTR according to POLICY.  */
+extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
+     __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 inheritance mode in *ATTR according to INHERIT.  */
+extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
+					 int __inherit) __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 contention scope in *ATTR according to SCOPE.  */
+extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
+     __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;
+
+#ifdef __USE_UNIX98
+/* Set the size of the guard area at the bottom of the thread.  */
+extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
+				      size_t __guardsize) __THROW;
+
+/* Get the size of the guard area at the bottom of the thread.  */
+extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict
+				      __attr, size_t *__restrict __guardsize)
+     __THROW;
+#endif
+
+/* 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_MIN.  */
+extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
+				      void *__stackaddr) __THROW;
+
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict
+				      __attr, void **__restrict __stackaddr)
+     __THROW;
+
+#ifdef __USE_XOPEN2K
+/* 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;
+
+/* 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;
+#endif
+
+/* Add information about the minimum stack size needed for the thread
+   to be started.  This size must never be less than PTHREAD_STACK_MIN
+   and must also not exceed the system limits.  */
+extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
+				      size_t __stacksize) __THROW;
+
+/* Return the currently used minimal stack size.  */
+extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict
+				      __attr, size_t *__restrict __stacksize)
+     __THROW;
+
+#ifdef __USE_GNU
+/* Initialize thread attribute *ATTR with attributes corresponding to the
+   already running thread TH.  It shall be called on unitialized ATTR
+   and destroyed with pthread_attr_destroy when no longer needed.  */
+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 mutex handling.  */
+
+/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the
+   default values if later is NULL.  */
+extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex,
+			       __const pthread_mutexattr_t *__restrict
+			       __mutex_attr) __THROW;
+
+/* Destroy MUTEX.  */
+extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW;
+
+/* Try to lock MUTEX.  */
+extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW;
+
+/* Wait until lock for MUTEX becomes available and lock it.  */
+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 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
+/* 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;
+
+/* Return in *KIND the mutex kind attribute in *ATTR.  */
+extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
+				      __attr, int *__restrict __kind) __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);
+
+/* 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);
+
+/* 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;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* 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 *__attr,
+					  int *__pref) __THROW;
+
+/* Set reader/write preference.  */
+extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
+					  int __pref) __THROW;
+#endif
+
+#ifdef __USE_XOPEN2K
+/* The IEEE Std. 1003.1j-2000 introduces functions to implement
+   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;
+
+
+/* Barriers are a also a new feature in 1003.1j-2000. */
+
+extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
+				 __const pthread_barrierattr_t *__restrict
+				 __attr, unsigned int __count) __THROW;
+
+extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW;
+
+extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW;
+
+extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW;
+
+extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t *
+					   __restrict __attr,
+					   int *__restrict __pshared) __THROW;
+
+extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
+					   int __pshared) __THROW;
+
+extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __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;
+
+/* Store POINTER in the thread-specific data slot identified by KEY. */
+extern int pthread_setspecific (pthread_key_t __key,
+				__const void *__pointer) __THROW;
+
+/* Return current value of the thread-specific data slot identified by KEY.  */
+extern void *pthread_getspecific (pthread_key_t __key) __THROW;
+
+
+/* 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.
+
+   The initialization functions might throw exception which is why
+   this function is not marked with __THROW.  */
+extern int pthread_once (pthread_once_t *__once_control,
+			 void (*__init_routine) (void));
+
+
+/* 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);
+
+/* 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);
+
+/* Cancel THREAD immediately or at the next possibility.  */
+extern int pthread_cancel (pthread_t __cancelthread);
+
+/* 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);
+
+
+/* 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;
+
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and set it to deferred cancellation.  */
+
+#ifdef __USE_GNU
+# 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
+
+
+/* Functions for handling signals.  */
+#include <bits/sigthread.h>
+
+
+/* Functions for handling process creation and process execution.  */
+
+/* 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;
+
+/* Terminate all threads in the program except the calling process.
+   Should be called just before invoking one of the exec*() functions.  */
+
+extern void pthread_kill_other_threads_np (void) __THROW;
+
+__END_DECLS
+
+#endif	/* pthread.h */
diff --git a/linuxthreads/sysdeps/pthread/ptlongjmp.c b/linuxthreads/sysdeps/pthread/ptlongjmp.c
new file mode 100644
index 0000000000..a2a56b8d9c
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/ptlongjmp.c
@@ -0,0 +1,39 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Redefine siglongjmp and longjmp so that they interact correctly
+   with cleanup handlers */
+
+#include <setjmp.h>
+#include "pthread.h"
+#include "internals.h"
+
+/* These functions are not declared anywhere since they shouldn't be
+   used at another place but here.  */
+extern void __libc_siglongjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+extern void __libc_longjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+
+#ifdef SHARED
+void siglongjmp (sigjmp_buf env, int val)
+{
+  __libc_siglongjmp (env, val);
+}
+
+void longjmp (jmp_buf env, int val)
+{
+  __libc_longjmp (env, val);
+}
+#endif
diff --git a/linuxthreads/sysdeps/pthread/res-state.c b/linuxthreads/sysdeps/pthread/res-state.c
new file mode 100644
index 0000000000..016e20b4ef
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/res-state.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1996, 97, 98, 2002, 2003 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 <resolv.h>
+#include <tls.h>
+#include <linuxthreads/internals.h>
+#include <sysdep-cancel.h>
+
+#if ! USE___THREAD
+# undef _res
+extern struct __res_state _res;
+#endif
+
+/* When threaded, _res may be a per-thread variable.  */
+struct __res_state *
+#if ! USE___THREAD
+weak_const_function
+#endif
+__res_state (void)
+{
+#if ! USE___THREAD
+  if (! SINGLE_THREAD_P)
+    {
+      pthread_descr self = thread_self();
+      return LIBC_THREAD_GETMEM (self, p_resp);
+    }
+  return &_res;
+#else
+  return __resp;
+#endif
+}
+libc_hidden_def (__res_state)
diff --git a/linuxthreads/sysdeps/pthread/semaphore.h b/linuxthreads/sysdeps/pthread/semaphore.h
new file mode 100644
index 0000000000..8793768a8e
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/semaphore.h
@@ -0,0 +1 @@
+#include <linuxthreads/semaphore.h>
diff --git a/linuxthreads/sysdeps/pthread/sigaction.c b/linuxthreads/sysdeps/pthread/sigaction.c
new file mode 100644
index 0000000000..f4e20790d9
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/sigaction.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This is tricky.  GCC doesn't like #include_next in the primary
+   source file and even if it did, the first #include_next is this
+   exact file anyway.  */
+#ifndef LIBC_SIGACTION
+
+# include <bits/libc-lock.h>
+
+# define LIBC_SIGACTION	1
+
+# include <linuxthreads/sysdeps/pthread/sigaction.c>
+
+# ifndef NOT_IN_libc
+#  ifndef SHARED
+weak_extern (__pthread_sigaction)
+#  endif
+
+int
+__sigaction (sig, act, oact)
+     int sig;
+     const struct sigaction *act;
+     struct sigaction *oact;
+{
+  return __libc_maybe_call2 (pthread_sigaction, (sig, act, oact),
+			     __libc_sigaction (sig, act, oact));
+}
+# else
+weak_alias (__libc_sigaction, __sigaction)
+# endif
+libc_hidden_weak (__sigaction)
+weak_alias (__sigaction, sigaction)
+
+#else
+
+# include_next <sigaction.c>
+
+#endif /* LIBC_SIGACTION */
diff --git a/linuxthreads/sysdeps/pthread/tcb-offsets.h b/linuxthreads/sysdeps/pthread/tcb-offsets.h
new file mode 100644
index 0000000000..3fe13702ea
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/tcb-offsets.h
@@ -0,0 +1 @@
+/* This is overridden by generated tcb-offsets.h on arches which need it.  */
diff --git a/linuxthreads/sysdeps/pthread/timer_create.c b/linuxthreads/sysdeps/pthread/timer_create.c
new file mode 100644
index 0000000000..7f7e886c83
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/timer_create.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 2000, 2003, 2004 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 (0
+#ifdef _POSIX_CPUTIME
+      || clock_id == CLOCK_PROCESS_CPUTIME_ID
+#endif
+#ifdef _POSIX_THREAD_CPUTIME
+      || clock_id == CLOCK_THREAD_CPUTIME_ID
+#endif
+      )
+    {
+      /* We don't allow timers for CPU clocks.  At least not in the
+	 moment.  */
+      __set_errno (ENOTSUP);
+      return -1;
+    }
+
+  if (clock_id != CLOCK_REALTIME)
+    {
+      __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:
+    case SIGEV_SIGNAL:
+      /* We have a global thread for delivering timed signals.
+	 If it is not running, try to start it up.  */
+      thread = &__timer_signal_thread_rclk;
+      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_delref (newtimer);
+	  __timer_dealloc (newtimer);
+	}
+    }
+
+  pthread_mutex_unlock (&__timer_mutex);
+
+  return retval;
+}
diff --git a/linuxthreads/sysdeps/pthread/timer_delete.c b/linuxthreads/sysdeps/pthread/timer_delete.c
new file mode 100644
index 0000000000..48ba1f2726
--- /dev/null
+++ b/linuxthreads/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/linuxthreads/sysdeps/pthread/timer_getoverr.c b/linuxthreads/sysdeps/pthread/timer_getoverr.c
new file mode 100644
index 0000000000..f3e22215b2
--- /dev/null
+++ b/linuxthreads/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/linuxthreads/sysdeps/pthread/timer_gettime.c b/linuxthreads/sysdeps/pthread/timer_gettime.c
new file mode 100644
index 0000000000..723a61632f
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/timer_gettime.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2000, 2004 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);
+	  if (timespec_compare (&now, &expiry) < 0)
+	    timespec_sub (&value->it_value, &expiry, &now);
+	  else
+	    {
+	      value->it_value.tv_sec = 0;
+	      value->it_value.tv_nsec = 0;
+	    }
+	}
+      else
+	{
+	  value->it_value.tv_sec = 0;
+	  value->it_value.tv_nsec = 0;
+	}
+
+      retval = 0;
+    }
+  else
+    __set_errno (EINVAL);
+
+  return retval;
+}
diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c
new file mode 100644
index 0000000000..3877b86fbb
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/timer_routines.c
@@ -0,0 +1,573 @@
+/* Helper code for POSIX timer implementation on LinuxThreads.
+   Copyright (C) 2000, 2001, 2002, 2004 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"
+
+
+/* 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;
+
+/* 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);
+}
+
+
+/* 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);
+
+      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:
+      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)
+{
+  return (left->__detachstate == right->__detachstate
+	  && left->__schedpolicy == right->__schedpolicy
+	  && left->__guardsize == right->__guardsize
+	  && (left->__schedparam.sched_priority
+	      == right->__schedparam.sched_priority)
+	  && left->__inheritsched == right->__inheritsched
+	  && left->__scope == right->__scope
+	  && left->__stacksize == right->__stacksize
+	  && left->__stackaddr_set == right->__stackaddr_set
+	  && (left->__stackaddr_set
+	      || left->__stackaddr == right->__stackaddr));
+}
+
+
+/* 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)
+	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/linuxthreads/sysdeps/pthread/timer_settime.c b/linuxthreads/sysdeps/pthread/timer_settime.c
new file mode 100644
index 0000000000..592b5271ba
--- /dev/null
+++ b/linuxthreads/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/linuxthreads/sysdeps/pthread/tst-timer.c b/linuxthreads/sysdeps/pthread/tst-timer.c
new file mode 100644
index 0000000000..7417bcd5f0
--- /dev/null
+++ b/linuxthreads/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/linuxthreads/sysdeps/s390/Makefile b/linuxthreads/sysdeps/s390/Makefile
new file mode 100644
index 0000000000..2885c968b3
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/Makefile
@@ -0,0 +1,6 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep
+endif
diff --git a/linuxthreads/sysdeps/s390/pspinlock.c b/linuxthreads/sysdeps/s390/pspinlock.c
new file mode 100644
index 0000000000..f963f35371
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/pspinlock.c
@@ -0,0 +1,91 @@
+/* POSIX spinlock implementation.  S/390 version.
+   Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+   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 "internals.h"
+
+/* This implementation is similar to the one used in the Linux kernel.
+   But the kernel is byte instructions for the memory access.  This is
+   faster but unusable here.  The problem is that only 128
+   threads/processes could use the spinlock at the same time.  If (by
+   a design error in the program) a thread/process would hold the
+   spinlock for a time long enough to accumulate 128 waiting
+   processes, the next one will find a positive value in the spinlock
+   and assume it is unlocked.  We cannot accept that.  */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile("    basr  1,0\n"
+	       "0:  slr   0,0\n"
+	       "    cs    0,1,%1\n"
+	       "    jl    0b\n"
+	       : "=m" (*lock)
+	       : "m" (*lock) : "0", "1", "cc" );
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int oldval;
+
+  asm volatile("    slr   %1,%1\n"
+	       "    basr  1,0\n"
+	       "0:  cs    %1,1,%0"
+	       : "=m" (*lock), "=&d" (oldval)
+	       : "m" (*lock) : "1", "cc" );
+  return oldval == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile("    xc 0(4,%0),0(%0)\n"
+	       "    bcr 15,0"
+	       : : "a" (lock) : "memory" );
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/s390/s390-32/pt-machine.h b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
new file mode 100644
index 0000000000..398332965f
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
@@ -0,0 +1,120 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   S390 version.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* For multiprocessor systems, we want to ensure all memory accesses
+   are completed before we reset a lock.  On other systems, we still
+   need to make sure that the compiler has flushed everything to memory.  */
+#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory")
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__(
+       "    la    1,%1\n"
+       "    lhi   0,1\n"
+       "    l     %0,%1\n"
+       "0:  cs    %0,0,0(1)\n"
+       "    jl    0b"
+       : "=&d" (ret), "+m" (*spinlock)
+       : : "0", "1", "cc");
+
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("15");
+
+#ifdef USE_TLS
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
+#else
+/* Return the thread descriptor for the current thread.
+   S/390 registers uses access register 0 as "thread register".  */
+#define THREAD_SELF  ({                                                       \
+  register pthread_descr __self;                                              \
+  __asm__ ("ear %0,%%a0" : "=d" (__self) );                                   \
+  __self;                                                                     \
+})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  ({                                       \
+  __asm__ ("sar %%a0,%0" : : "d" (descr) );                                   \
+})
+#endif
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     8*1024*1024
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap(long int *p, long int oldval, long int newval)
+{
+        int retval;
+
+        __asm__ __volatile__(
+                "  la   1,%1\n"
+                "  lr   0,%2\n"
+                "  cs   0,%3,0(1)\n"
+                "  ipm  %0\n"
+                "  srl  %0,28\n"
+                "0:"
+                : "=&d" (retval), "+m" (*p)
+                : "d" (oldval) , "d" (newval)
+                : "cc", "0", "1" );
+        return retval == 0;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/s390/s390-64/pt-machine.h b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
new file mode 100644
index 0000000000..49f8ae2b9a
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
@@ -0,0 +1,125 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   64 bit S/390 version.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* For multiprocessor systems, we want to ensure all memory accesses
+   are completed before we reset a lock.  On other systems, we still
+   need to make sure that the compiler has flushed everything to memory.  */
+#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory")
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__(
+       "    la    1,%1\n"
+       "    lhi   0,1\n"
+       "    l     %0,%1\n"
+       "0:  cs    %0,0,0(1)\n"
+       "    jl    0b"
+       : "=&d" (ret), "+m" (*spinlock)
+       : : "0", "1", "cc");
+
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("15");
+
+#ifdef USE_TLS
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
+#else
+/* Return the thread descriptor for the current thread.
+   64 bit S/390 uses access register 0 and 1 as "thread register".  */
+#define THREAD_SELF  ({                                                       \
+  register pthread_descr __self;                                              \
+  __asm__ ("   ear  %0,%%a0\n"                                                \
+           "   sllg %0,%0,32\n"                                               \
+           "   ear  %0,%%a1\n"                                                \
+           : "=d" (__self) );                                                 \
+  __self;                                                                     \
+})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  ({                                       \
+  __asm__ ("   sar  %%a1,%0\n"                                                \
+           "   srlg 0,%0,32\n"                                                \
+           "   sar  %%a0,0\n"                                                 \
+           : : "d" (descr) : "0" );                                           \
+})
+#endif
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     8*1024*1024
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap(long int *p, long int oldval, long int newval)
+{
+        int retval;
+
+        __asm__ __volatile__(
+                "  lgr  0,%2\n"
+                "  csg  0,%3,%1\n"
+                "  ipm  %0\n"
+                "  srl  %0,28\n"
+                "0:"
+                : "=&d" (retval), "+m" (*p)
+                : "d" (oldval) , "d" (newval)
+                : "cc", "0");
+        return retval == 0;
+}
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/s390/tcb-offsets.sym b/linuxthreads/sysdeps/s390/tcb-offsets.sym
new file mode 100644
index 0000000000..aee6be2570
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/tcb-offsets.sym
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads)
diff --git a/linuxthreads/sysdeps/s390/tls.h b/linuxthreads/sysdeps/s390/tls.h
new file mode 100644
index 0000000000..41a83a72fb
--- /dev/null
+++ b/linuxthreads/sysdeps/s390/tls.h
@@ -0,0 +1,140 @@
+/* Definitions for thread-local data handling.  linuxthreads/s390 version.
+   Copyright (C) 2002, 2003 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.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.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+/* TLS is always supported if the tools support it.  There are no
+   kernel dependencies.  To avoid bothering with the TLS support code
+   at all, use configure --without-tls.
+
+   We need USE_TLS to be consistently defined, for ldsodefs.h
+   conditionals.  */
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/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_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* 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) \
+  (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+/* 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.
+
+   The value of this macro is null if successful, or an error string.  */
+#  define TLS_INIT_TP(descr, secondcall)				      \
+  ({									      \
+    void *_descr = (descr);						      \
+    tcbhead_t *head = _descr;						      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    __builtin_set_thread_pointer (_descr);				      \
+    NULL;								      \
+  })
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
+
+# endif /* __ASSEMBLER__ */
+
+#else	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
+
+# ifndef __ASSEMBLER__
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+#  define NONTLS_INIT_TP \
+  do { 								\
+    static const tcbhead_t nontls_init_tp			\
+      = { .multiple_threads = 0 };				\
+    INIT_THREAD_SELF (&nontls_init_tp, 0);			\
+  } while (0)
+
+# endif /* __ASSEMBLER__ */
+
+#endif	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/sh/Makefile b/linuxthreads/sysdeps/sh/Makefile
new file mode 100644
index 0000000000..81bddf688c
--- /dev/null
+++ b/linuxthreads/sysdeps/sh/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/sh/pspinlock.c b/linuxthreads/sysdeps/sh/pspinlock.c
new file mode 100644
index 0000000000..2dec849d3c
--- /dev/null
+++ b/linuxthreads/sysdeps/sh/pspinlock.c
@@ -0,0 +1,80 @@
+/* POSIX spinlock implementation.  SH version.
+   Copyright (C) 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 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 "internals.h"
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  do
+    asm volatile ("tas.b @%1; movt %0"
+		  : "=r" (val)
+		  : "r" (lock)
+		  : "memory");
+  while (val == 0);
+
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  unsigned int val;
+
+  asm volatile ("tas.b @%1; movt %0"
+		: "=r" (val)
+		: "r" (lock)
+		: "memory");
+  return val ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  return *lock = 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/sh/pt-machine.h b/linuxthreads/sysdeps/sh/pt-machine.h
new file mode 100644
index 0000000000..02545e6b45
--- /dev/null
+++ b/linuxthreads/sysdeps/sh/pt-machine.h
@@ -0,0 +1,81 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   SuperH version.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Niibe Yutaka <gniibe@m17n.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; 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 _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef __ASSEMBLER__
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__(
+       "tas.b	@%1\n\t"
+       "movt	%0"
+       : "=r" (ret)
+       : "r" (spinlock)
+       : "memory", "cc");
+
+  return (ret == 0);
+}
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("r15");
+
+/* Return the thread descriptor for the current thread.  */
+struct _pthread_descr_struct;
+#define THREAD_SELF \
+  ({ struct _pthread_descr_struct *self; \
+      __asm__("stc gbr,%0" : "=r" (self)); self;})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) \
+  ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));})
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#endif /* __ASSEMBLER__ */
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/sh/tcb-offsets.sym b/linuxthreads/sysdeps/sh/tcb-offsets.sym
new file mode 100644
index 0000000000..328eb05738
--- /dev/null
+++ b/linuxthreads/sysdeps/sh/tcb-offsets.sym
@@ -0,0 +1,10 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+#ifdef USE_TLS
+MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads)
+TLS_PRE_TCB_SIZE	sizeof (struct _pthread_descr_struct)
+#else
+MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+#endif
diff --git a/linuxthreads/sysdeps/sh/tls.h b/linuxthreads/sysdeps/sh/tls.h
new file mode 100644
index 0000000000..17a247c6b6
--- /dev/null
+++ b/linuxthreads/sysdeps/sh/tls.h
@@ -0,0 +1,148 @@
+/* Definition for thread-local data handling.  linuxthreads/SH version.
+   Copyright (C) 2002, 2003 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
+
+# include <dl-sysdep.h>
+# include <pt-machine.h>
+
+#ifndef __ASSEMBLER__
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+
+/* We can support TLS only if the floating-stack support is available.  */
+#if defined HAVE_TLS_SUPPORT \
+    && (defined FLOATING_STACKS || !defined IS_IN_libpthread)
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+/* 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 (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The TLS blocks start right after the TCB.  */
+#  define TLS_DTV_AT_TP	1
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(tcbp, dtvp) \
+  ((tcbhead_t *) (tcbp))->dtv = dtvp + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(dtv) \
+  ({ tcbhead_t *__tcbp;							      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \
+     __tcbp->dtv = (dtv);})
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
+
+/* 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(tcbp, secondcall) \
+  ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; })
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({ tcbhead_t *__tcbp;							      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \
+     __tcbp->dtv;})
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+  ({ struct _pthread_descr_struct *__self;				      \
+     __asm ("stc gbr,%0" : "=r" (__self));				      \
+     __self - 1;})
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(descr, nr) \
+  ({ struct _pthread_descr_struct *__self = (void *) descr;		      \
+     __asm __volatile ("ldc %0,gbr" : : "r" (__self + 1));		      \
+     0; })
+
+# define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+/* Get the thread descriptor definition.  This must be after the
+   the definition of THREAD_SELF for TLS.  */
+#  include <linuxthreads/descr.h>
+
+# endif /* __ASSEMBLER__ */
+
+#else
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  void *tcb;
+  dtv_t *dtv;
+  void *self;
+  int multiple_threads;
+} tcbhead_t;
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+#  define NONTLS_INIT_TP \
+  do { 									\
+    static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 };	\
+    __asm __volatile ("ldc %0,gbr" : : "r" (&nontls_init_tp));	        \
+  } while (0)
+
+# endif /* __ASSEMBLER__ */
+
+#endif	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/sparc/Makefile b/linuxthreads/sysdeps/sparc/Makefile
new file mode 100644
index 0000000000..81bddf688c
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c
new file mode 100644
index 0000000000..a67dbf901e
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c
@@ -0,0 +1,88 @@
+/* POSIX spinlock implementation.  SPARC32 version.
+   Copyright (C) 2000 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 "internals.h"
+
+/* This implementation is similar to the one used in the Linux kernel.  */
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("1: ldstub [%0], %%g2\n"
+     "   orcc   %%g2, 0x0, %%g0\n"
+     "   bne,a  2f\n"
+     "   ldub   [%0], %%g2\n"
+     ".subsection 2\n"
+     "2: orcc   %%g2, 0x0, %%g0\n"
+     "   bne,a  2b\n"
+     "   ldub   [%0], %%g2\n"
+     "   b,a    1b\n"
+     ".previous"
+     : /* no outputs */
+     : "r" (lock)
+     : "g2", "memory", "cc");
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int result;
+  asm volatile
+    ("ldstub [%1], %0"
+     : "=r" (result)
+     : "r" (lock)
+     : "memory");
+  return result == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h b/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h
new file mode 100644
index 0000000000..322a52051f
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h
@@ -0,0 +1,83 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   sparc version.
+   Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__("ldstub %1,%0"
+	: "=r"(ret), "=m"(*spinlock)
+	: "m"(*spinlock));
+
+  return ret;
+}
+
+
+/* Memory barrier; default is to do nothing */
+#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory")
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  (stack_pointer + (2 * 64))
+register char *stack_pointer __asm__("%sp");
+
+
+/* Registers %g6 and %g7 are reserved by the ABI for "system use".
+   %g7 is specified in the TLS ABI as thread pointer -- we do the same.  */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("%g7");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     8*1024*1024
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c
new file mode 100644
index 0000000000..04f588bed5
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c
@@ -0,0 +1,94 @@
+/* POSIX spinlock implementation.  SPARC v9 version.
+   Copyright (C) 2000 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 "internals.h"
+
+
+/* This implementation is similar to the one used in the Linux kernel.  */
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("1: ldstub  [%0], %%g2\n"
+     "   brnz,pn %%g2, 2f\n"
+     "    membar #StoreLoad | #StoreStore\n"
+     ".subsection 2\n"
+     "2: ldub    [%0], %%g2\n"
+     "   brnz,pt %%g2, 2b\n"
+     "    membar #LoadLoad\n"
+     "   b,a,pt  %%xcc, 1b\n"
+     ".previous"
+     : /* no outputs */
+     : "r" (lock)
+     : "g2", "memory");
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int result;
+  asm volatile
+    ("ldstub [%1], %0\n"
+     "membar #StoreLoad | #StoreStore"
+     : "=r" (result)
+     : "r" (lock)
+     : "memory");
+  return result == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("membar #StoreStore | #LoadStore\n"
+     "stb    %%g0, [%0]"
+     :
+     : "r" (lock)
+     : "memory");
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/sparc/sparc64/Versions b/linuxthreads/sysdeps/sparc/sparc64/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc64/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c
new file mode 100644
index 0000000000..92b84f5108
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c
@@ -0,0 +1,93 @@
+/* POSIX spinlock implementation.  SPARC64 version.
+   Copyright (C) 2000 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 "internals.h"
+
+/* This implementation is similar to the one used in the Linux kernel.  */
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("1: ldstub  [%0], %%g5\n"
+     "   brnz,pn %%g5, 2f\n"
+     "    membar #StoreLoad | #StoreStore\n"
+     ".subsection 2\n"
+     "2: ldub    [%0], %%g5\n"
+     "   brnz,pt %%g5, 2b\n"
+     "    membar #LoadLoad\n"
+     "   b,a,pt  %%xcc, 1b\n"
+     ".previous"
+     : /* no outputs */
+     : "r" (lock)
+     : "g5", "memory");
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int result;
+  asm volatile
+    ("ldstub [%1], %0\n"
+     "membar #StoreLoad | #StoreStore"
+     : "=r" (result)
+     : "r" (lock)
+     : "memory");
+  return result == 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("membar #StoreStore | #LoadStore\n"
+     "stb    %%g0, [%0]"
+     :
+     : "r" (lock)
+     : "memory");
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 0;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h b/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h
new file mode 100644
index 0000000000..f65c13be1b
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h
@@ -0,0 +1,105 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   Sparc v9 version.
+   Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline __attribute__ ((always_inline))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__("ldstub %1,%0"
+	: "=r" (ret), "=m" (*spinlock) : "m" (*spinlock));
+
+  return ret;
+}
+
+
+/* Memory barrier; default is to do nothing */
+#define MEMORY_BARRIER() \
+     __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory")
+/* Read barrier.  */
+#define READ_MEMORY_BARRIER() \
+     __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory")
+/* Write barrier.  */
+#define WRITE_MEMORY_BARRIER() \
+     __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory")
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  (stack_pointer + (2 * 128))
+register char *stack_pointer __asm__ ("%sp");
+
+
+/* Registers %g6 and %g7 are reserved by the ABI for "system use".  The
+   TLS ABI specifies %g7 as the thread pointer.  */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__ ("%g7");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int readval;
+
+  __asm__ __volatile__ ("casx	[%4], %2, %0"
+			: "=r"(readval), "=m"(*p)
+			: "r"(oldval), "m"(*p), "r"(p), "0"(newval));
+  MEMORY_BARRIER();
+  return readval == oldval;
+}
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/sparc/tcb-offsets.sym b/linuxthreads/sysdeps/sparc/tcb-offsets.sym
new file mode 100644
index 0000000000..aee6be2570
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/tcb-offsets.sym
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads)
diff --git a/linuxthreads/sysdeps/sparc/tls.h b/linuxthreads/sysdeps/sparc/tls.h
new file mode 100644
index 0000000000..6b1966fe1c
--- /dev/null
+++ b/linuxthreads/sysdeps/sparc/tls.h
@@ -0,0 +1,110 @@
+/* Definitions for thread-local data handling.  linuxthreads/sparc version.
+   Copyright (C) 2002, 2003 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.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.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/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_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* 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) \
+  (((tcbhead_t *) __thread_self)->dtv = (DTV))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+/* Code to initially initialize the thread pointer.  */
+# define TLS_INIT_TP(descr, secondcall) \
+  (__thread_self = (__typeof (__thread_self)) (descr), NULL)
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *) __thread_self)->dtv)
+
+# endif
+
+#else
+
+# define NONTLS_INIT_TP \
+  do {									      \
+    static const tcbhead_t nontls_init_tp				      \
+      = { .multiple_threads = 0 };					      \
+    __thread_self = (__typeof (__thread_self)) &nontls_init_tp;		      \
+  } while (0)
+
+#endif /* USE_TLS */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Implies b/linuxthreads/sysdeps/unix/sysv/linux/Implies
new file mode 100644
index 0000000000..f1b3e8939c
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/Implies
@@ -0,0 +1 @@
+pthread
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/Makefile
new file mode 100644
index 0000000000..38c6cbc1af
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+sysdep_routines += register-atfork unregister-atfork
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Versions b/linuxthreads/sysdeps/unix/sysv/linux/Versions
new file mode 100644
index 0000000000..6cd3dbe372
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/Versions
@@ -0,0 +1,5 @@
+libc {
+  GLIBC_2.3.2 {
+    __register_atfork;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h b/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h
new file mode 100644
index 0000000000..f62f7d6e9f
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h
@@ -0,0 +1,26 @@
+/* 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 <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/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c
new file mode 100644
index 0000000000..af1581a4c3
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c
@@ -0,0 +1,87 @@
+/* Handle real-time signal allocation.
+   Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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>
+
+/* Sanity check.  */
+#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3
+# error "This must not happen"
+#endif
+
+static int current_rtmin;
+static int current_rtmax;
+
+static int initialized;
+
+#include <testrtsig.h>
+
+static void
+init (void)
+{
+  if (!kernel_has_rtsig ())
+    {
+      current_rtmin = -1;
+      current_rtmax = -1;
+    }
+  else
+    {
+      current_rtmin = __SIGRTMIN + 3;
+      current_rtmax = __SIGRTMAX;
+    }
+  initialized = 1;
+}
+
+/* Return number of available real-time signal with highest priority.  */
+int
+__libc_current_sigrtmin (void)
+{
+  if (!initialized)
+    init ();
+  return current_rtmin;
+}
+strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private);
+libc_hidden_def (__libc_current_sigrtmin)
+
+/* Return number of available real-time signal with lowest priority.  */
+int
+__libc_current_sigrtmax (void)
+{
+  if (!initialized)
+    init ();
+  return current_rtmax;
+}
+strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private);
+libc_hidden_def (__libc_current_sigrtmax)
+
+/* Allocate real-time signal with highest/lowest available
+   priority.  Please note that we don't use a lock since we assume
+   this function to be called at program start.  */
+int
+__libc_allocate_rtsig (int high)
+{
+  if (!initialized)
+    init ();
+  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/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile
new file mode 100644
index 0000000000..e03aee99fc
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions
new file mode 100644
index 0000000000..d102772482
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions
@@ -0,0 +1,6 @@
+libpthread {
+  GLIBC_2.3.3 {
+    # Changed PTHREAD_STACK_MIN.
+    pthread_attr_setstack; pthread_attr_setstacksize;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c
new file mode 100644
index 0000000000..0d6da82919
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c
@@ -0,0 +1,33 @@
+#include <shlib-compat.h>
+
+#define aio_cancel64 XXX
+#include <aio.h>
+#undef aio_cancel64
+#include <errno.h>
+
+extern __typeof (aio_cancel) __new_aio_cancel;
+extern __typeof (aio_cancel) __old_aio_cancel;
+
+#define aio_cancel	__new_aio_cancel
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__new_aio_cancel, __new_aio_cancel64);
+versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3);
+versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3);
+
+#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3)
+
+#undef ECANCELED
+#define aio_cancel	__old_aio_cancel
+#define ECANCELED	125
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__old_aio_cancel, __old_aio_cancel64);
+compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1);
+compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1);
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h
new file mode 100644
index 0000000000..96893c59da
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h
@@ -0,0 +1,92 @@
+/* Minimum guaranteed maximum values for system limits.  Linux/Alpha version.
+   Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* This is the value this implementation supports.  */
+#define PTHREAD_THREADS_MAX	16384
+
+/* 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	24576
+
+/* Maximum number of POSIX timers available.  */
+#define TIMER_MAX	256
+
+/* Maximum number of timer expiration overruns.  */
+#define DELAYTIMER_MAX	2147483647
+
+/* Maximum tty name length.  */
+#define TTY_NAME_MAX		32
+
+/* Maximum login name length.  This is arbitrary.  */
+#define LOGIN_NAME_MAX		256
+
+/* Maximum host name length.  */
+#define HOST_NAME_MAX		64
+
+/* Maximum message queue priority level.  */
+#define MQ_PRIO_MAX		32768
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
new file mode 100644
index 0000000000..a2724885e2
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
@@ -0,0 +1,66 @@
+/* bits/typesizes.h -- underlying types for *_t.  Linux/Alpha version.
+   Copyright (C) 2002, 2003 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 _BITS_TYPES_H
+# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TYPESIZES_H
+#define	_BITS_TYPESIZES_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#define __DEV_T_TYPE		__U64_TYPE
+#define __UID_T_TYPE		__U32_TYPE
+#define __GID_T_TYPE		__U32_TYPE
+#define __INO_T_TYPE		__U32_TYPE
+#define __INO64_T_TYPE		__U64_TYPE
+#define __MODE_T_TYPE		__U32_TYPE
+#define __NLINK_T_TYPE		__U32_TYPE
+#define __OFF_T_TYPE		__SLONGWORD_TYPE
+#define __OFF64_T_TYPE		__S64_TYPE
+#define __PID_T_TYPE		__S32_TYPE
+#define __RLIM_T_TYPE		__ULONGWORD_TYPE
+#define __RLIM64_T_TYPE		__U64_TYPE
+#define	__BLKCNT_T_TYPE		__U32_TYPE
+#define	__BLKCNT64_T_TYPE	__U64_TYPE
+#define	__FSBLKCNT_T_TYPE	__S32_TYPE
+#define	__FSBLKCNT64_T_TYPE	__S64_TYPE
+#define	__FSFILCNT_T_TYPE	__U32_TYPE
+#define	__FSFILCNT64_T_TYPE	__U64_TYPE
+#define	__ID_T_TYPE		__U32_TYPE
+#define __CLOCK_T_TYPE		__SLONGWORD_TYPE
+#define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __USECONDS_T_TYPE	__U32_TYPE
+#define __SUSECONDS_T_TYPE	__S64_TYPE
+#define __DADDR_T_TYPE		__S32_TYPE
+#define __SWBLK_T_TYPE		__SLONGWORD_TYPE
+#define __KEY_T_TYPE		__S32_TYPE
+#define __CLOCKID_T_TYPE	__S32_TYPE
+#define __TIMER_T_TYPE		__S32_TYPE
+#define __BLKSIZE_T_TYPE	__U32_TYPE
+#define __FSID_T_TYPE		struct { int __val[2]; }
+#define __SSIZE_T_TYPE		__SWORD_TYPE
+
+/* Number of descriptors that can fit in an `fd_set'.  */
+#define	__FD_SETSIZE		1024
+
+
+#endif /* bits/typesizes.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S
new file mode 100644
index 0000000000..91e5c86782
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S
@@ -0,0 +1,28 @@
+/* Internal sigsuspend system call for LinuxThreads.  Alpha version.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+#undef PSEUDO_PREPARE_ARGS
+#define PSEUDO_PREPARE_ARGS	ldq	a0, 0(a0);
+
+	.hidden __pthread_sigsuspend
+PSEUDO_NOERRNO(__pthread_sigsuspend, sigsuspend, 1)
+	ret
+PSEUDO_END_NOERRNO(__pthread_sigsuspend)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
new file mode 100644
index 0000000000..9ea779e0d5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
@@ -0,0 +1,146 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# ifdef PROF
+#  define PSEUDO_PROF				\
+	.set noat;				\
+	lda	AT, _mcount;			\
+	jsr	AT, (AT), _mcount;		\
+	.set at
+# else
+#  define PSEUDO_PROF
+# endif
+
+/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END
+   besides "ret".  */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)			\
+	.globl name;						\
+	.align 4;						\
+	.type name, @function;					\
+	.usepv name, std;					\
+	cfi_startproc;						\
+__LABEL(name)							\
+	ldgp	gp, 0(pv);					\
+	PSEUDO_PROF;						\
+	PSEUDO_PREPARE_ARGS					\
+	SINGLE_THREAD_P(t0);					\
+	bne	t0, $pseudo_cancel;				\
+	lda	v0, SYS_ify(syscall_name);			\
+	call_pal PAL_callsys;					\
+	bne	a3, SYSCALL_ERROR_LABEL;			\
+__LABEL($pseudo_ret)						\
+	.subsection 2;						\
+__LABEL($pseudo_cancel)						\
+	subq	sp, 64, sp;					\
+	cfi_def_cfa_offset(64);					\
+	stq	ra, 0(sp);					\
+	cfi_offset(ra, -64);					\
+	SAVE_ARGS_##args;					\
+	CENABLE;						\
+	LOAD_ARGS_##args;					\
+	lda	v0, SYS_ify(syscall_name);			\
+	call_pal PAL_callsys;					\
+	stq	v0, 8(sp);					\
+	bne	a3, $multi_error;				\
+	CDISABLE;						\
+	ldq	ra, 0(sp);					\
+	ldq	v0, 8(sp);					\
+	addq	sp, 64, sp;					\
+	cfi_remember_state;					\
+	cfi_restore(ra);					\
+	cfi_def_cfa_offset(0);					\
+	ret;							\
+	cfi_restore_state;					\
+__LABEL($multi_error)						\
+	CDISABLE;						\
+	ldq	ra, 0(sp);					\
+	ldq	v0, 8(sp);					\
+	addq	sp, 64, sp;					\
+	cfi_restore(ra);					\
+	cfi_def_cfa_offset(0);					\
+__LABEL($syscall_error)						\
+	SYSCALL_ERROR_HANDLER;					\
+	.previous
+
+# undef PSEUDO_END
+# define PSEUDO_END(sym)					\
+	.subsection 2;						\
+	cfi_endproc;						\
+	.size sym, .-sym
+
+# define SAVE_ARGS_0	/* Nothing.  */
+# define SAVE_ARGS_1	SAVE_ARGS_0; stq a0, 8(sp)
+# define SAVE_ARGS_2	SAVE_ARGS_1; stq a1, 16(sp)
+# define SAVE_ARGS_3	SAVE_ARGS_2; stq a2, 24(sp)
+# define SAVE_ARGS_4	SAVE_ARGS_3; stq a3, 32(sp)
+# define SAVE_ARGS_5	SAVE_ARGS_4; stq a4, 40(sp)
+# define SAVE_ARGS_6	SAVE_ARGS_5; stq a5, 48(sp)
+
+# define LOAD_ARGS_0	/* Nothing.  */
+# define LOAD_ARGS_1	LOAD_ARGS_0; ldq a0, 8(sp)
+# define LOAD_ARGS_2	LOAD_ARGS_1; ldq a1, 16(sp)
+# define LOAD_ARGS_3	LOAD_ARGS_2; ldq a2, 24(sp)
+# define LOAD_ARGS_4	LOAD_ARGS_3; ldq a3, 32(sp)
+# define LOAD_ARGS_5	LOAD_ARGS_4; ldq a4, 40(sp)
+# define LOAD_ARGS_6	LOAD_ARGS_5; ldq a5, 48(sp)
+
+# ifdef IS_IN_libpthread
+#  define __local_enable_asynccancel	__pthread_enable_asynccancel
+#  define __local_disable_asynccancel	__pthread_disable_asynccancel
+#  define __local_multiple_threads	__pthread_multiple_threads
+# else
+#  define __local_enable_asynccancel	__libc_enable_asynccancel
+#  define __local_disable_asynccancel	__libc_disable_asynccancel
+#  define __local_multiple_threads	__libc_multiple_threads
+# endif
+
+# ifdef PIC
+#  define CENABLE	bsr ra, __local_enable_asynccancel !samegp
+#  define CDISABLE	bsr ra, __local_disable_asynccancel !samegp
+# else
+#  define CENABLE	jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp)
+#  define CDISABLE	jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp)
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P \
+  __builtin_expect (__local_multiple_threads == 0, 1)
+# elif defined(PIC)
+#  define SINGLE_THREAD_P(reg)  ldl reg, __local_multiple_threads(gp) !gprel
+# else
+#  define SINGLE_THREAD_P(reg)					\
+	ldah	reg, __local_multiple_threads(gp) !gprelhigh;	\
+	ldl	reg, __local_multiple_threads(reg) !gprellow
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S
new file mode 100644
index 0000000000..cfaae10606
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S
@@ -0,0 +1,70 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+
+#include <sysdep-cancel.h>
+
+        .align 4
+	.globl	__vfork
+	.type	__vfork, @function
+	.usepv	__vfork, std
+	cfi_startproc
+__vfork:
+	ldgp	gp, 0(pv)
+	PSEUDO_PROF
+
+#ifdef SHARED
+	ldq	t0, __libc_pthread_functions(gp) !gprel
+	bne	t0, HIDDEN_JUMPTARGET (__fork) !samegp
+#else
+	.weak	pthread_create
+	ldq	t0, pthread_create(gp) !literal
+	bne	t0, $do_fork
+#endif
+
+	lda	v0, SYS_ify(vfork)
+	call_pal PAL_callsys
+	bne	a3, SYSCALL_ERROR_LABEL
+	ret
+
+#ifndef SHARED
+	/* Can't tail-call due to possible mismatch between GP in
+	   fork and vfork object files.  */
+$do_fork:
+	subq	sp, 16, sp
+	cfi_adjust_cfa_offset(16)
+	stq	ra, 0(sp)
+	cfi_offset(ra, -16)
+	jsr	ra, HIDDEN_JUMPTARGET (__fork)
+	ldgp	gp, 0(ra)
+	ldq	ra, 0(sp)
+	addq	sp, 16, sp
+	cfi_restore(ra)
+	cfi_adjust_cfa_offset(-16)
+	ret
+
+$syscall_error:
+	SYSCALL_ERROR_HANDLER
+#endif
+
+	cfi_endproc
+	.size __vfork, .-__vfork
+
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
new file mode 100644
index 0000000000..019bd54913
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
@@ -0,0 +1,145 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+/* We push lr onto the stack, so we have to use ldmib instead of ldmia
+   to find the saved arguments.  */
+# ifdef PIC
+#  undef DOARGS_5
+#  undef DOARGS_6
+#  undef DOARGS_7
+#  define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $8];
+#  define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmib ip, {r4, r5};
+#  define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmib ip, {r4, r5, r6};
+# endif
+
+# undef PSEUDO_RET
+# define PSEUDO_RET						        \
+    ldrcc pc, [sp], $4;						        \
+    ldr	lr, [sp], $4;							\
+    b PLTJMP(SYSCALL_ERROR)
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  .section ".text";							\
+    PSEUDO_PROLOGUE;							\
+  ENTRY (name);								\
+    SINGLE_THREAD_P_INT;						\
+    bne .Lpseudo_cancel;						\
+    DO_CALL (syscall_name, args);					\
+    cmn r0, $4096;							\
+    PSEUDO_RET_MOV;							\
+  .Lpseudo_cancel:							\
+    MAYBE_SAVE_LR;							\
+    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
+    CENABLE;								\
+    mov ip, r0;		/* put mask in safe place.  */			\
+    UNDOCARGS_##args;	/* restore syscall args.  */			\
+    swi SYS_ify (syscall_name);	/* do the call.  */			\
+    str r0, [sp, $-4]!; /* save syscall return value.  */		\
+    mov r0, ip;		/* get mask back.  */				\
+    CDISABLE;								\
+    ldr r0, [sp], $4;	/* retrieve return value.  */			\
+    UNDOC2ARGS_##args;	/* fix register damage.  */			\
+    cmn r0, $4096;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+# define UNDOC2ARGS_0
+
+# define DOCARGS_1	str r0, [sp, #-4]!;
+# define UNDOCARGS_1	ldr r0, [sp], #4;
+# define UNDOC2ARGS_1
+
+# define DOCARGS_2	str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_2	ldr r0, [sp], #4; ldr r1, [sp], #4;
+# define UNDOC2ARGS_2
+
+# define DOCARGS_3	str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_3	ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4
+# define UNDOC2ARGS_3
+
+# define DOCARGS_4	stmfd sp!, {r0-r3}
+# define UNDOCARGS_4	ldmfd sp!, {r0-r3}
+# define UNDOC2ARGS_4
+
+# define DOCARGS_5	stmfd sp!, {r0-r3}
+# define UNDOCARGS_5	ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24]
+# define UNDOC2ARGS_5   ldr r4, [sp], #20
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	bl PLTJMP(__pthread_enable_asynccancel)
+#  define CDISABLE	bl PLTJMP(__pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# else
+#  define CENABLE	bl PLTJMP(__libc_enable_asynccancel)
+#  define CDISABLE	bl PLTJMP(__libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  if !defined PIC
+#   define SINGLE_THREAD_P_INT						\
+  ldr ip, =__local_multiple_threads;					\
+  ldr ip, [ip];								\
+  teq ip, #0;
+#   define SINGLE_THREAD_P SINGLE_THREAD_P_INT
+#   define MAYBE_SAVE_LR						\
+  str lr, [sp, $-4]!;
+#   define PSEUDO_RET_MOV						\
+  RETINSTR(cc, lr);							\
+  b PLTJMP(SYSCALL_ERROR)
+#   define PSEUDO_PROLOGUE
+#  else
+#   define SINGLE_THREAD_P_PIC(reg)					\
+  ldr ip, 1b;								\
+  ldr reg, 2b;								\
+3:									\
+  add ip, pc, ip;							\
+  ldr ip, [ip, reg];							\
+  teq ip, #0;
+#   define SINGLE_THREAD_P_INT						\
+  str lr, [sp, $-4]!;							\
+  SINGLE_THREAD_P_PIC(lr)
+#   define SINGLE_THREAD_P						\
+  SINGLE_THREAD_P_INT;							\
+  ldr lr, [sp], $4
+#   define PSEUDO_PROLOGUE						\
+  1:  .word _GLOBAL_OFFSET_TABLE_ - 3f - 8;				\
+  2:  .word __local_multiple_threads(GOTOFF);
+#   define MAYBE_SAVE_LR	/* lr already saved */
+#   define PSEUDO_RET_MOV PSEUDO_RET
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
new file mode 100644
index 0000000000..2708c701eb
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
@@ -0,0 +1,80 @@
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Philip Blundell <philb@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-cancel.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.  */
+
+	PSEUDO_PROLOGUE
+
+ENTRY (__vfork)
+
+#ifdef __NR_vfork
+
+#ifdef SHARED
+	ldr	ip, 1f
+	ldr	r0, 2f
+3:	add	ip, pc, ip
+	ldr	r0, [ip, r0]
+#else
+	ldr	r0, 1f
+#endif
+	movs	r0, r0
+	bne	HIDDEN_JUMPTARGET (__fork)
+		
+	swi	__NR_vfork
+	cmn	a1, #4096
+	RETINSTR(cc, lr)
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* Check if vfork syscall is known at all.  */
+	cmn	a1, #ENOSYS
+	bne	PLTJMP(C_SYMBOL_NAME(__syscall_error))
+#endif
+
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* If we don't have vfork, fork is close enough.  */
+	swi	__NR_fork
+	cmn	a1, #4096
+	RETINSTR(cc, lr)
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
+#endif
+    	b	PLTJMP(C_SYMBOL_NAME(__syscall_error))
+
+#ifdef SHARED
+1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8
+2:	.word	__libc_pthread_functions(GOTOFF)
+#else
+	.weak	pthread_create
+1:	.word	pthread_create
+#endif
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h
new file mode 100644
index 0000000000..ed6c3c589b
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h
@@ -0,0 +1,92 @@
+/* Minimum guaranteed maximum values for system limits.  Linux version.
+   Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* This is the value this implementation supports.  */
+#define PTHREAD_THREADS_MAX	16384
+
+/* 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
+
+/* Maximum tty name length.  */
+#define TTY_NAME_MAX		32
+
+/* Maximum login name length.  This is arbitrary.  */
+#define LOGIN_NAME_MAX		256
+
+/* Maximum host name length.  */
+#define HOST_NAME_MAX		64
+
+/* Maximum message queue priority level.  */
+#define MQ_PRIO_MAX		32768
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h
new file mode 100644
index 0000000000..71b7e74649
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h
@@ -0,0 +1,181 @@
+/* Define POSIX options for Linux.
+   Copyright (C) 1996-2001, 2002, 2003, 2004 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.  */
+
+#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
+
+/* 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	200112L
+
+/* Real-time signals are supported.  */
+#define _POSIX_REALTIME_SIGNALS	200112L
+
+/* We support asynchronous I/O.  */
+#define _POSIX_ASYNCHRONOUS_IO	200112L
+#define _POSIX_ASYNC_IO		1
+/* Alternative name for Unix98.  */
+#define _LFS_ASYNCHRONOUS_IO	1
+/* Support for prioritization is also available.  */
+#define _POSIX_PRIORITIZED_IO	200112L
+
+/* 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
+
+/* CPU-time clocks support needs to be checked at runtime.  */
+#define _POSIX_CPUTIME	0
+
+/* Clock support in threads must be also checked at runtime.  */
+#define _POSIX_THREAD_CPUTIME	0
+
+/* 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	200112L
+
+/* The barrier functions are available.  */
+#define _POSIX_BARRIERS	200112L
+
+/* POSIX message queues are available.  */
+#define	_POSIX_MESSAGE_PASSING	200112L
+
+/* Thread process-shared synchronization is not supported.  */
+#define _POSIX_THREAD_PROCESS_SHARED	-1
+
+/* The monotonic clock might be available.  */
+#define _POSIX_MONOTONIC_CLOCK	0
+
+/* The clock selection interfaces are not available.  */
+#define _POSIX_CLOCK_SELECTION	-1
+
+/* Advisory information interfaces are available.  */
+#define _POSIX_ADVISORY_INFO	200112L
+
+/* IPv6 support is available.  */
+#define _POSIX_IPV6	200112L
+
+/* Raw socket support is available.  */
+#define _POSIX_RAW_SOCKETS	200112L
+
+/* We have at least one terminal.  */
+#define _POSIX2_CHAR_TERM	200112L
+
+/* Neither process nor thread sporadic server interfaces is available.  */
+#define _POSIX_SPORADIC_SERVER	-1
+#define _POSIX_THREAD_SPORADIC_SERVER	-1
+
+/* trace.h is not available.  */
+#define _POSIX_TRACE	-1
+#define _POSIX_TRACE_EVENT_FILTER	-1
+#define _POSIX_TRACE_INHERIT	-1
+#define _POSIX_TRACE_LOG	-1
+
+/* Typed memory objects are not available.  */
+#define _POSIX_TYPED_MEMORY_OBJECTS	-1
+
+/* No support for priority inheritance or protection.  */
+#define _POSIX_THREAD_PRIO_INHERIT	-1
+#define _POSIX_THREAD_PRIO_PROTECT	-1
+
+#endif /* posix_opt.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h
new file mode 100644
index 0000000000..960bde18a9
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/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 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.  */
+
+#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/linuxthreads/sysdeps/unix/sysv/linux/execve.c b/linuxthreads/sysdeps/unix/sysv/linux/execve.c
new file mode 100644
index 0000000000..9fa912b90d
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/execve.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 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 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 <unistd.h>
+
+#include <sysdep.h>
+#include <alloca.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+extern int __syscall_execve (const char *__unbounded file,
+			     char *__unbounded const *__unbounded argv,
+			     char *__unbounded const *__unbounded envp);
+extern void __pthread_kill_other_threads_np (void);
+weak_extern (__pthread_kill_other_threads_np)
+
+
+int
+__execve (file, argv, envp)
+     const char *file;
+     char *const argv[];
+     char *const envp[];
+{
+  /* If this is a threaded application kill all other threads.  */
+  if (__pthread_kill_other_threads_np)
+    __pthread_kill_other_threads_np ();
+#if __BOUNDED_POINTERS__
+  {
+    char *const *v;
+    int i;
+    char *__unbounded *__unbounded ubp_argv;
+    char *__unbounded *__unbounded ubp_envp;
+    char *__unbounded *__unbounded ubp_v;
+
+    for (v = argv; *v; v++)
+      ;
+    i = v - argv + 1;
+    ubp_argv = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_argv) * i);
+    for (v = argv, ubp_v = ubp_argv; --i; v++, ubp_v++)
+      *ubp_v = CHECK_STRING (*v);
+    *ubp_v = 0;
+
+    for (v = envp; *v; v++)
+      ;
+    i = v - envp + 1;
+    ubp_envp = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_envp) * i);
+    for (v = envp, ubp_v = ubp_envp; --i; v++, ubp_v++)
+      *ubp_v = CHECK_STRING (*v);
+    *ubp_v = 0;
+
+    return INLINE_SYSCALL (execve, 3, CHECK_STRING (file), ubp_argv, ubp_envp);
+  }
+#else
+  return INLINE_SYSCALL (execve, 3, file, argv, envp);
+#endif
+}
+weak_alias (__execve, execve)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/linuxthreads/sysdeps/unix/sysv/linux/fork.c
new file mode 100644
index 0000000000..00eb787093
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/fork.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <fork.h>
+#include <bits/libc-lock.h>
+
+#ifndef SHARED
+weak_extern (__pthread_fork);
+#endif
+
+struct fork_block __fork_block =
+{
+  .lock = PTHREAD_MUTEX_INITIALIZER,
+  .prepare_list = { &__fork_block.prepare_list, &__fork_block.prepare_list },
+  .parent_list = { &__fork_block.parent_list, &__fork_block.parent_list },
+  .child_list = { &__fork_block.child_list, &__fork_block.child_list }
+};
+
+pid_t
+__libc_fork (void)
+{
+  return __libc_maybe_call2 (pthread_fork, (&__fork_block), ARCH_FORK ());
+}
+weak_alias (__libc_fork, __fork)
+libc_hidden_def (__fork)
+weak_alias (__libc_fork, fork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/fork.h
new file mode 100644
index 0000000000..76708e3e39
--- /dev/null
+++ b/linuxthreads/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 <bits/libc-lock.h>
+#include <sysdep.h>
+
+struct fork_block
+{
+  /* Lock to protect handling of fork handlers.  */
+  __libc_lock_define (, lock);
+
+  /* Lists of registered fork handlers.  */
+  list_t prepare_list;
+  list_t parent_list;
+  list_t child_list;
+};
+
+extern struct fork_block __fork_block 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);
+libc_hidden_proto (__register_atfork)
+
+#ifndef ARCH_FORK
+# define ARCH_FORK() INLINE_SYSCALL (fork, 0)
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c
new file mode 100644
index 0000000000..0d6da82919
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c
@@ -0,0 +1,33 @@
+#include <shlib-compat.h>
+
+#define aio_cancel64 XXX
+#include <aio.h>
+#undef aio_cancel64
+#include <errno.h>
+
+extern __typeof (aio_cancel) __new_aio_cancel;
+extern __typeof (aio_cancel) __old_aio_cancel;
+
+#define aio_cancel	__new_aio_cancel
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__new_aio_cancel, __new_aio_cancel64);
+versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3);
+versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3);
+
+#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3)
+
+#undef ECANCELED
+#define aio_cancel	__old_aio_cancel
+#define ECANCELED	125
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__old_aio_cancel, __old_aio_cancel64);
+compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1);
+compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1);
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h
new file mode 100644
index 0000000000..9b13400286
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h
@@ -0,0 +1,27 @@
+/* PA-RISC specific definitions for spinlock initializers.
+   Copyright (C) 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 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.  */
+
+/* Initial value of a spinlock.  PA-RISC only implements atomic load
+   and clear so this must be non-zero. */
+#define __LT_SPINLOCK_INIT 1
+
+/* Macros for lock initializers, using the above definition. */
+#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT }
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h
new file mode 100644
index 0000000000..817cf59222
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h
@@ -0,0 +1,73 @@
+/* HP-PARISC macro definitions for mutexes, thread-specific data 
+   and parameters for malloc.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003.
+   
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _MALLOC_MACHINE_H
+#define _MALLOC_MACHINE_H
+
+#undef thread_atfork_static
+
+#include <atomic.h>
+#include <bits/libc-lock.h>
+
+__libc_lock_define (typedef, mutex_t)
+
+/* Since our lock structure does not tolerate being initialized to zero, we must
+   modify the standard function calls made by malloc */
+#  define mutex_init(m)		\
+	__libc_maybe_call (__pthread_mutex_init, (m, NULL), \
+		(((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT),(*(int *)(m))) )
+#  define mutex_lock(m)		\
+	__libc_maybe_call (__pthread_mutex_lock, (m), \
+			(__load_and_clear(&((m)->__m_lock.__spinlock)), 0))
+#  define mutex_trylock(m)	\
+	__libc_maybe_call (__pthread_mutex_trylock, (m), \
+			(*(int *)(m) ? 1 : (__load_and_clear(&((m)->__m_lock.__spinlock)), 0)))
+#  define mutex_unlock(m)	\
+	__libc_maybe_call (__pthread_mutex_unlock, (m), \
+			(((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT), (*(int *)(m))) )
+	
+/* This is defined by newer gcc version unique for each module.  */
+extern void *__dso_handle __attribute__ ((__weak__));
+
+#include <fork.h>
+
+#ifdef SHARED
+# define thread_atfork(prepare, parent, child) \
+   __register_atfork (prepare, parent, child, __dso_handle)
+#else
+# define thread_atfork(prepare, parent, child) \
+   __register_atfork (prepare, parent, child,				      \
+		      &__dso_handle == NULL ? NULL : __dso_handle)
+#endif
+
+/* thread specific data for glibc */
+
+#include <bits/libc-tsd.h>
+
+typedef int tsd_key_t[1];	/* no key data structure, libc magic does it */
+__libc_tsd_define (static, MALLOC)	/* declaration/common definition */
+#define tsd_key_create(key, destr)	((void) (key))
+#define tsd_setspecific(key, data)	__libc_tsd_set (MALLOC, (data))
+#define tsd_getspecific(key, vptr)	((vptr) = __libc_tsd_get (MALLOC))
+
+#include <sysdeps/generic/malloc-machine.h>
+
+#endif /* !defined(_MALLOC_MACHINE_H) */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c
new file mode 100644
index 0000000000..27f850cf8f
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c
@@ -0,0 +1,109 @@
+/* Special .init and .fini section support for HPPA.  Linuxthreads version.
+   Copyright (C) 2001, 2003 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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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. */
+
+/* If we use the standard C version, the linkage table pointer won't
+   be properly preserved due to the splitting up of function prologues
+   and epilogues.  Therefore we write these in assembly to make sure
+   they do the right thing.  */
+
+__asm__ (
+"#include \"defs.h\"\n"
+"\n"
+"/*@HEADER_ENDS*/\n"
+"\n"
+"/*@_init_PROLOG_BEGINS*/\n"
+"	.section .init\n"
+"	.align 4\n"
+"	.globl _init\n"
+"	.type _init,@function\n"
+"_init:\n"
+"	stw	%rp,-20(%sp)\n"
+"	stwm	%r4,64(%sp)\n"
+"	stw	%r19,-32(%sp)\n"
+"	bl	__pthread_initialize_minimal,%rp\n"
+"	copy	%r19,%r4	/* delay slot */\n"
+"	copy	%r4,%r19\n"
+"/*@_init_PROLOG_ENDS*/\n"
+"\n"
+"/*@_init_EPILOG_BEGINS*/\n"
+"/* Here is the tail end of _init.  */\n"
+"	.section .init\n"
+"	ldw	-84(%sp),%rp\n"
+"	copy	%r4,%r19\n"
+"	bv	%r0(%rp)\n"
+"_end_init:\n"
+"	ldwm	-64(%sp),%r4\n"
+"\n"
+"/* Our very own unwind info, because the assembler can't handle\n"
+"   functions split into two or more pieces.  */\n"
+"	.section .PARISC.unwind,\"a\",@progbits\n"
+"	.extern _init\n"
+"	.word	_init, _end_init\n"
+"	.byte	0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n"
+"\n"
+"/*@_init_EPILOG_ENDS*/\n"
+"\n"
+"/*@_fini_PROLOG_BEGINS*/\n"
+"	.section .fini\n"
+"	.align 4\n"
+"	.globl _fini\n"
+"	.type _fini,@function\n"
+"_fini:\n"
+"	stw	%rp,-20(%sp)\n"
+"	stwm	%r4,64(%sp)\n"
+"	stw	%r19,-32(%sp)\n"
+"	copy	%r19,%r4\n"
+"/*@_fini_PROLOG_ENDS*/\n"
+"\n"
+"/*@_fini_EPILOG_BEGINS*/\n"
+"	.section .fini\n"
+"	ldw	-84(%sp),%rp\n"
+"	copy	%r4,%r19\n"
+"	bv	%r0(%rp)\n"
+"_end_fini:\n"
+"	ldwm	-64(%sp),%r4\n"
+"\n"
+"	.section .PARISC.unwind,\"a\",@progbits\n"
+"	.extern _fini\n"
+"	.word	_fini, _end_fini\n"
+"	.byte	0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n"
+"\n"
+"/*@_fini_EPILOG_ENDS*/\n"
+"\n"
+"/*@TRAILER_BEGINS*/\n"
+);
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h
new file mode 100644
index 0000000000..134977e074
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h
@@ -0,0 +1,189 @@
+/* cancellable system calls for Linux/HPPA.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# ifndef NO_ERROR
+#  define NO_ERROR -0x1000
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  ENTRY (name)								\
+    SINGLE_THREAD_P					ASM_LINE_SEP	\
+    cmpib,<> 0,%ret0,Lpseudo_cancel			ASM_LINE_SEP	\
+    nop							ASM_LINE_SEP	\
+    DO_CALL(syscall_name, args)				ASM_LINE_SEP	\
+    /* DONE! */						ASM_LINE_SEP	\
+    bv 0(2)						ASM_LINE_SEP	\
+    nop							ASM_LINE_SEP	\
+  Lpseudo_cancel:					ASM_LINE_SEP	\
+    /* store return ptr */				ASM_LINE_SEP	\
+    stw %rp, -20(%sr0,%sp)				ASM_LINE_SEP	\
+    /* save syscall args */				ASM_LINE_SEP	\
+    PUSHARGS_##args /* MACRO */				ASM_LINE_SEP	\
+    STW_PIC						ASM_LINE_SEP	\
+    CENABLE /* FUNC CALL */				ASM_LINE_SEP	\
+    ldo 64(%sp), %sp					ASM_LINE_SEP	\
+    ldo -64(%sp), %sp					ASM_LINE_SEP	\
+    LDW_PIC						ASM_LINE_SEP	\
+    /* restore syscall args */				ASM_LINE_SEP	\
+    POPARGS_##args					ASM_LINE_SEP	\
+    /* save r4 in arg0 stack slot */			ASM_LINE_SEP	\
+    stw %r4, -36(%sr0,%sp)				ASM_LINE_SEP	\
+    /* save mask from cenable */			ASM_LINE_SEP	\
+    copy %ret0, %r4					ASM_LINE_SEP	\
+    ble 0x100(%sr2,%r0)					ASM_LINE_SEP    \
+    ldi SYS_ify (syscall_name), %r20			ASM_LINE_SEP	\
+    LDW_PIC						ASM_LINE_SEP	\
+    /* pass mask as arg0 to cdisable */			ASM_LINE_SEP	\
+    copy %r4, %r26					ASM_LINE_SEP	\
+    copy %ret0, %r4					ASM_LINE_SEP	\
+    CDISABLE						ASM_LINE_SEP	\
+    ldo 64(%sp), %sp					ASM_LINE_SEP	\
+    ldo -64(%sp), %sp					ASM_LINE_SEP	\
+    LDW_PIC						ASM_LINE_SEP	\
+    /* compare error */					ASM_LINE_SEP	\
+    ldi NO_ERROR,%r1					ASM_LINE_SEP	\
+    /* branch if no error */				ASM_LINE_SEP	\
+    cmpb,>>=,n %r1,%r4,Lpre_end				ASM_LINE_SEP	\
+    nop							ASM_LINE_SEP	\
+    SYSCALL_ERROR_HANDLER				ASM_LINE_SEP	\
+    ldo 64(%sp), %sp					ASM_LINE_SEP	\
+    ldo -64(%sp), %sp					ASM_LINE_SEP	\
+    /* No need to LDW_PIC */				ASM_LINE_SEP	\
+    /* make syscall res value positive */		ASM_LINE_SEP	\
+    sub %r0, %r4, %r4					ASM_LINE_SEP	\
+    /* store into errno location */			ASM_LINE_SEP	\
+    stw %r4, 0(%sr0,%ret0)				ASM_LINE_SEP	\
+    /* return -1 */					ASM_LINE_SEP	\
+    ldo -1(%r0), %ret0					ASM_LINE_SEP	\
+  Lpre_end:						ASM_LINE_SEP	\
+    ldw -20(%sr0,%sp), %rp             			ASM_LINE_SEP	\
+    /* No need to LDW_PIC */				ASM_LINE_SEP	\
+    ldw -36(%sr0,%sp), %r4				ASM_LINE_SEP
+
+/* Save arguments into our frame */
+# define PUSHARGS_0	/* nothing to do */
+# define PUSHARGS_1	PUSHARGS_0 stw %r26, -36(%sr0,%sp)	ASM_LINE_SEP
+# define PUSHARGS_2	PUSHARGS_1 stw %r25, -40(%sr0,%sp)	ASM_LINE_SEP
+# define PUSHARGS_3	PUSHARGS_2 stw %r24, -44(%sr0,%sp)	ASM_LINE_SEP
+# define PUSHARGS_4	PUSHARGS_3 stw %r23, -48(%sr0,%sp)	ASM_LINE_SEP
+# define PUSHARGS_5	PUSHARGS_4 /* Args are on the stack... */
+# define PUSHARGS_6	PUSHARGS_5
+
+/* Bring them back from the stack */
+# define POPARGS_0	/* nothing to do */
+# define POPARGS_1	POPARGS_0 ldw -36(%sr0,%sp), %r26	ASM_LINE_SEP
+# define POPARGS_2	POPARGS_1 ldw -40(%sr0,%sp), %r25	ASM_LINE_SEP
+# define POPARGS_3	POPARGS_2 ldw -44(%sr0,%sp), %r24	ASM_LINE_SEP
+# define POPARGS_4	POPARGS_3 ldw -48(%sr0,%sp), %r23	ASM_LINE_SEP
+# define POPARGS_5	POPARGS_4 ldw -52(%sr0,%sp), %r22	ASM_LINE_SEP
+# define POPARGS_6	POPARGS_5 ldw -54(%sr0,%sp), %r21	ASM_LINE_SEP
+
+# ifdef IS_IN_libpthread
+#  ifdef PIC
+#   define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
+			bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
+			bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
+#  else
+#   define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
+			bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
+			bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
+#  endif
+# elif !defined NOT_IN_libc
+#  ifdef PIC
+#   define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
+			bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE	.import __libc_disable_asynccancel,code ASM_LINE_SEP \
+			bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
+#  else
+#   define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
+			bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE	.import __libc_disable_asynccancel,code ASM_LINE_SEP \
+			bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
+#  endif
+# else
+#  ifdef PIC
+#   define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
+			bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
+			bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
+#  else
+#   define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
+			bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
+#   define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
+			bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
+#  endif
+# endif
+
+/* p_header.multiple_threads is +12 from the pthread_descr struct start,
+   We could have called __get_cr27() but we really want less overhead */
+# define MULTIPLE_THREADS_OFFSET 0xC
+
+/* cr27 has been initialized to 0x0 by kernel */
+# define NO_THREAD_CR27 0x0
+
+# ifdef IS_IN_libpthread
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define __local_multiple_threads __libc_multiple_threads
+# else
+#  define __local_multiple_threads __librt_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+ extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+/* This ALT version requires newer kernel support */
+#  define SINGLE_THREAD_P_MFCTL						\
+	mfctl %cr27, %ret0					ASM_LINE_SEP	\
+	cmpib,= NO_THREAD_CR27,%ret0,Lstp			ASM_LINE_SEP	\
+	nop							ASM_LINE_SEP	\
+	ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0		ASM_LINE_SEP	\
+ Lstp:								ASM_LINE_SEP
+#  ifdef PIC
+/* Slower version uses GOT to get value of __local_multiple_threads */
+#   define SINGLE_THREAD_P							\
+	addil LT%__local_multiple_threads, %r19			ASM_LINE_SEP	\
+	ldw RT%__local_multiple_threads(%sr0,%r1), %ret0	ASM_LINE_SEP	\
+	ldw 0(%sr0,%ret0), %ret0 				ASM_LINE_SEP
+#  else
+  /* Slow non-pic version using DP */
+#   define SINGLE_THREAD_P								\
+	addil LR%__local_multiple_threads-$global$,%r27  		ASM_LINE_SEP	\
+	ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0	ASM_LINE_SEP
+#  endif
+# endif
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
+/* !defined NOT_IN_libc || defined IS_IN_libpthread */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h
new file mode 100644
index 0000000000..5355310ccd
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h
@@ -0,0 +1,64 @@
+/* System-specific settings for dynamic linker code.  IA-32 version.
+   Copyright (C) 2002, 2003 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 _DL_SYSDEP_H
+#define _DL_SYSDEP_H	1
+
+/* This macro must be defined to either 0 or 1.
+
+   If 1, then an errno global variable hidden in ld.so will work right with
+   all the errno-using libc code compiled for ld.so, and there is never a
+   need to share the errno location with libc.  This is appropriate only if
+   all the libc functions that ld.so uses are called without PLT and always
+   get the versions linked into ld.so rather than the libc ones.  */
+
+#ifdef IS_IN_rtld
+# define RTLD_PRIVATE_ERRNO 1
+#else
+# define RTLD_PRIVATE_ERRNO 0
+#endif
+
+/* Traditionally system calls have been made using int $0x80.  A
+   second method was introduced which, if possible, will use the
+   sysenter/syscall instructions.  To signal the presence and where to
+   find the code the kernel passes an AT_SYSINFO value in the
+   auxiliary vector to the application.
+   sysenter/syscall is not useful on i386 through i586, but the dynamic
+   linker and dl code in libc.a has to be able to load i686 compiled
+   libraries.  */
+#define NEED_DL_SYSINFO	1
+#undef USE_DL_SYSINFO
+
+#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__
+extern void _dl_sysinfo_int80 (void) attribute_hidden;
+# define DL_SYSINFO_DEFAULT (uintptr_t) _dl_sysinfo_int80
+# define DL_SYSINFO_IMPLEMENTATION \
+  asm (".text\n\t"							      \
+       ".type _dl_sysinfo_int80,@function\n\t"				      \
+       ".hidden _dl_sysinfo_int80\n"					      \
+       CFI_STARTPROC "\n"						      \
+       "_dl_sysinfo_int80:\n\t"						      \
+       "int $0x80;\n\t"							      \
+       "ret;\n\t"							      \
+       CFI_ENDPROC "\n"							      \
+       ".size _dl_sysinfo_int80,.-_dl_sysinfo_int80\n\t"		      \
+       ".previous");
+#endif
+
+#endif	/* dl-sysdep.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
new file mode 100644
index 0000000000..7865f7165e
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <tls.h>
+#include <pt-machine.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+    SINGLE_THREAD_P;							      \
+    jne L(pseudo_cancel);						      \
+    DO_CALL (syscall_name, args);					      \
+    cmpl $-4095, %eax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+    ret;								      \
+  L(pseudo_cancel):							      \
+    CENABLE								      \
+    SAVE_OLDTYPE_##args							      \
+    PUSHCARGS_##args							      \
+    DOCARGS_##args							      \
+    movl $SYS_ify (syscall_name), %eax;					      \
+    int $0x80								      \
+    POPCARGS_##args;							      \
+    POPSTATE_##args							      \
+    cmpl $-4095, %eax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+  L(pseudo_end):
+
+# define SAVE_OLDTYPE_0	movl %eax, %ecx;
+# define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0
+# define SAVE_OLDTYPE_2	pushl %eax;
+# define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2
+# define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2
+# define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2
+
+# define PUSHCARGS_0	/* No arguments to push.  */
+# define DOCARGS_0	/* No arguments to frob.  */
+# define POPCARGS_0	/* No arguments to pop.  */
+# define _PUSHCARGS_0	/* No arguments to push.  */
+# define _POPCARGS_0	/* No arguments to pop.  */
+
+# define PUSHCARGS_1	movl %ebx, %edx; PUSHCARGS_0
+# define DOCARGS_1	_DOARGS_1 (4)
+# define POPCARGS_1	POPCARGS_0; movl %edx, %ebx
+# define _PUSHCARGS_1	pushl %ebx; L(PUSHBX2): _PUSHCARGS_0
+# define _POPCARGS_1	_POPCARGS_0; popl %ebx; L(POPBX2):
+
+# define PUSHCARGS_2	PUSHCARGS_1
+# define DOCARGS_2	_DOARGS_2 (12)
+# define POPCARGS_2	POPCARGS_1
+# define _PUSHCARGS_2	_PUSHCARGS_1
+# define _POPCARGS_2	_POPCARGS_1
+
+# define PUSHCARGS_3	_PUSHCARGS_2
+# define DOCARGS_3	_DOARGS_3 (20)
+# define POPCARGS_3	_POPCARGS_3
+# define _PUSHCARGS_3	_PUSHCARGS_2
+# define _POPCARGS_3	_POPCARGS_2
+
+# define PUSHCARGS_4	_PUSHCARGS_4
+# define DOCARGS_4	_DOARGS_4 (28)
+# define POPCARGS_4	_POPCARGS_4
+# define _PUSHCARGS_4	pushl %esi; L(PUSHSI2): _PUSHCARGS_3
+# define _POPCARGS_4	_POPCARGS_3; popl %esi; L(POPSI2):
+
+# define PUSHCARGS_5	_PUSHCARGS_5
+# define DOCARGS_5	_DOARGS_5 (36)
+# define POPCARGS_5	_POPCARGS_5
+# define _PUSHCARGS_5	pushl %edi; L(PUSHDI2): _PUSHCARGS_4
+# define _POPCARGS_5	_POPCARGS_4; popl %edi; L(POPDI2):
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel;
+#  define CDISABLE	call __pthread_disable_asynccancel
+# elif defined IS_IN_librt
+#  ifdef PIC
+#   define CENABLE	pushl %ebx; \
+			call __i686.get_pc_thunk.bx; \
+			addl     $_GLOBAL_OFFSET_TABLE_, %ebx; \
+			call __librt_enable_asynccancel@PLT; \
+			popl %ebx;
+#   define CDISABLE	pushl %ebx; \
+			call __i686.get_pc_thunk.bx; \
+			addl     $_GLOBAL_OFFSET_TABLE_, %ebx; \
+			call __librt_disable_asynccancel@PLT; \
+			popl %ebx;
+#  else
+#   define CENABLE	call __librt_enable_asynccancel;
+#   define CDISABLE	call __librt_disable_asynccancel
+#  endif
+# else
+#  define CENABLE	call __libc_enable_asynccancel;
+#  define CDISABLE	call __libc_disable_asynccancel
+# endif
+# define POPSTATE_0	pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax;
+# define POPSTATE_1	POPSTATE_0
+# define POPSTATE_2	xchgl (%esp), %eax; CDISABLE; popl %eax;
+# define POPSTATE_3	POPSTATE_2
+# define POPSTATE_4	POPSTATE_2
+# define POPSTATE_5	POPSTATE_2
+
+#if !defined NOT_IN_libc
+# define __local_multiple_threads __libc_multiple_threads
+#elif defined IS_IN_libpthread
+# define __local_multiple_threads __pthread_multiple_threads
+#else
+# define __local_multiple_threads __librt_multiple_threads
+#endif
+
+# ifndef __ASSEMBLER__
+#  if defined FLOATING_STACKS && USE___THREAD && defined PIC
+#   define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+#  else
+extern int __local_multiple_threads
+#   if !defined NOT_IN_libc || defined IS_IN_libpthread
+  attribute_hidden;
+#   else
+  ;
+#   endif
+#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+#  endif
+# else
+#  if !defined PIC
+#   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads
+#  elif defined FLOATING_STACKS && USE___THREAD
+#   define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
+#  else
+#   if !defined NOT_IN_libc || defined IS_IN_libpthread
+#    define __SINGLE_THREAD_CMP cmpl $0, __local_multiple_threads@GOTOFF(%ecx)
+#   else
+#    define __SINGLE_THREAD_CMP \
+  movl __local_multiple_threads@GOT(%ecx), %ecx;\
+  cmpl $0, (%ecx)
+#   endif
+#   if !defined HAVE_HIDDEN || !USE___THREAD
+#    define SINGLE_THREAD_P \
+  SETUP_PIC_REG (cx);				\
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;		\
+  __SINGLE_THREAD_CMP
+#   else
+#    define SINGLE_THREAD_P \
+  call __i686.get_pc_thunk.cx;			\
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;		\
+  __SINGLE_THREAD_CMP
+#   endif
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S
new file mode 100644
index 0000000000..c7a120d239
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S
@@ -0,0 +1,95 @@
+/* Copyright (C) 1999, 2002, 2003 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-cancel.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)
+
+#ifdef __NR_vfork
+
+# ifdef SHARED
+#  if !defined HAVE_HIDDEN || !USE___THREAD
+	SETUP_PIC_REG (cx)
+#  else
+	call	__i686.get_pc_thunk.cx
+#  endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
+	cmpl	$0, __libc_pthread_functions@GOTOFF(%ecx)
+# else
+	.weak	pthread_create
+	movl	$pthread_create, %eax
+	testl	%eax, %eax
+# endif
+	jne	HIDDEN_JUMPTARGET (__fork)
+
+	/* 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
+	/* Branch forward if it failed.  */
+# ifdef __ASSUME_VFORK_SYSCALL
+	jae	SYSCALL_ERROR_LABEL
+.Lpseudo_end:
+# else
+	jae	.Lerror
+# endif
+
+	ret
+
+# ifndef __ASSUME_VFORK_SYSCALL
+.Lerror:
+	/* Check if vfork syscall is known at all.  */
+	cmpl	$-ENOSYS, %eax
+	jne	SYSCALL_ERROR_LABEL
+# endif
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* If we don't have vfork, fork is close enough.  */
+
+	movl	$SYS_ify (fork), %eax
+	int	$0x80
+	cmpl	$-4095, %eax
+	jae	SYSCALL_ERROR_LABEL
+.Lpseudo_end:
+	ret
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
+#endif
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile
new file mode 100644
index 0000000000..e03aee99fc
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions
new file mode 100644
index 0000000000..d102772482
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions
@@ -0,0 +1,6 @@
+libpthread {
+  GLIBC_2.3.3 {
+    # Changed PTHREAD_STACK_MIN.
+    pthread_attr_setstack; pthread_attr_setstacksize;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h
new file mode 100644
index 0000000000..629b1f89c1
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h
@@ -0,0 +1,92 @@
+/* Minimum guaranteed maximum values for system limits.  Linux/Alpha version.
+   Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* This is the value this implementation supports.  */
+#define PTHREAD_THREADS_MAX	16384
+
+/* 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	196608
+
+/* Maximum number of POSIX timers available.  */
+#define TIMER_MAX	256
+
+/* Maximum number of timer expiration overruns.  */
+#define DELAYTIMER_MAX	2147483647
+
+/* Maximum tty name length.  */
+#define TTY_NAME_MAX		32
+
+/* Maximum login name length.  This is arbitrary.  */
+#define LOGIN_NAME_MAX		256
+
+/* Maximum host name length.  */
+#define HOST_NAME_MAX		64
+
+/* Maximum message queue priority level.  */
+#define MQ_PRIO_MAX		32768
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
new file mode 100644
index 0000000000..27d5fdfbf5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
@@ -0,0 +1,49 @@
+/* System-specific settings for dynamic linker code.  IA-64 version.
+   Copyright (C) 2003, 2004 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 _DL_SYSDEP_H
+#define _DL_SYSDEP_H	1
+
+#define NEED_DL_SYSINFO	1
+#undef USE_DL_SYSINFO
+
+#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__
+/* Don't declare this as a function---we want it's entry-point, not
+   it's function descriptor... */
+extern int _dl_sysinfo_break attribute_hidden;
+# define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break)
+# define DL_SYSINFO_IMPLEMENTATION		\
+  asm (".text\n\t"				\
+       ".hidden _dl_sysinfo_break\n\t"		\
+       ".proc _dl_sysinfo_break\n\t"		\
+       "_dl_sysinfo_break:\n\t"			\
+       ".prologue\n\t"				\
+       ".altrp b6\n\t"				\
+       ".body\n\t"				\
+       "break 0x100000;\n\t"			\
+       "br.ret.sptk.many b6;\n\t"		\
+       ".endp _dl_sysinfo_break"		\
+       ".previous");
+#endif
+
+/* _dl_argv cannot be attribute_relro, because _dl_start_user
+   might write into it after _dl_start returns.  */
+#define DL_ARGV_NOT_RELRO 1
+
+#endif	/* dl-sysdep.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h
new file mode 100644
index 0000000000..30a0cc1918
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <sysdep.h>
+
+#define ARCH_FORK() INLINE_SYSCALL (clone, 2, SIGCHLD, 0)
+
+#include_next <fork.h>
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
new file mode 100644
index 0000000000..85fd33f4a8
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
@@ -0,0 +1,140 @@
+/* Special .init and .fini section support for ia64. LinuxThreads version.
+   Copyright (C) 2000, 2001, 2002, 2003 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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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 <stddef.h>
+
+#ifdef HAVE_INITFINI_ARRAY
+
+# define INIT_NEW_WAY \
+    ".xdata8 \".init_array\", @fptr(__pthread_initialize_minimal)\n"
+# define INIT_OLD_WAY ""
+#else
+# define INIT_NEW_WAY ""
+# define INIT_OLD_WAY \
+	"\n\
+	st8 [r12] = gp, -16\n\
+	br.call.sptk.many b0 = __pthread_initialize_minimal# ;;\n\
+	;;\n\
+	adds r12 = 16, r12\n\
+	;;\n\
+	ld8 gp = [r12]\n\
+	;;\n"
+#endif
+
+__asm__ ("\n\
+\n\
+#include \"defs.h\"\n\
+\n\
+/*@HEADER_ENDS*/\n\
+\n\
+/*@_init_PROLOG_BEGINS*/\n"
+	INIT_NEW_WAY
+	".section .init\n\
+	.align 16\n\
+	.global _init#\n\
+	.proc _init#\n\
+_init:\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	.vframe r32\n\
+	mov r32 = r12\n\
+	.save rp, r33\n\
+	mov r33 = b0\n\
+	.body\n\
+	adds r12 = -16, r12\n\
+	;;\n"
+	INIT_OLD_WAY
+	".endp _init#\n\
+\n\
+/*@_init_PROLOG_ENDS*/\n\
+\n\
+/*@_init_EPILOG_BEGINS*/\n\
+	.section .init\n\
+	.proc _init#\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	.vframe r32\n\
+	.save rp, r33\n\
+	.body\n\
+	mov r12 = r32\n\
+	mov ar.pfs = r34\n\
+	mov b0 = r33\n\
+	br.ret.sptk.many b0\n\
+	.endp _init#\n\
+/*@_init_EPILOG_ENDS*/\n\
+\n\
+/*@_fini_PROLOG_BEGINS*/\n\
+	.section .fini\n\
+	.align 16\n\
+	.global _fini#\n\
+	.proc _fini#\n\
+_fini:\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	.vframe r32\n\
+	mov r32 = r12\n\
+	.save rp, r33\n\
+	mov r33 = b0\n\
+	.body\n\
+	adds r12 = -16, r12\n\
+	;;\n\
+	.endp _fini#\n\
+\n\
+/*@_fini_PROLOG_ENDS*/\n\
+\n\
+/*@_fini_EPILOG_BEGINS*/\n\
+	.section .fini\n\
+	.proc _fini#\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	.vframe r32\n\
+	.save rp, r33\n\
+	.body\n\
+	mov r12 = r32\n\
+	mov ar.pfs = r34\n\
+	mov b0 = r33\n\
+	br.ret.sptk.many b0\n\
+	.endp _fini#\n\
+\n\
+/*@_fini_EPILOG_ENDS*/\n\
+\n\
+/*@TRAILER_BEGINS*/\n\
+	.weak	__gmon_start__#\n\
+");
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c
new file mode 100644
index 0000000000..0b96e3d5bd
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c
@@ -0,0 +1,33 @@
+/* Internal sigsuspend system call for LinuxThreads.  IA64 version.
+   Copyright (C) 2003 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 <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <linuxthreads/internals.h>
+
+void
+__pthread_sigsuspend (const sigset_t *set)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
new file mode 100644
index 0000000000..dd9637d2b5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
@@ -0,0 +1,144 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# ifdef IS_IN_librt
+#  define PSEUDO_NLOCAL		6
+#  define PSEUDO_SAVE_GP	mov loc5 = gp
+#  define PSEUDO_RESTORE_GP	mov gp = loc5
+#  define PSEUDO_SAVE_GP_1
+#  define PSEUDO_RESTORE_GP_1	mov gp = loc5
+# else
+#  define PSEUDO_NLOCAL		5
+#  define PSEUDO_SAVE_GP
+#  define PSEUDO_RESTORE_GP
+#  define PSEUDO_SAVE_GP_1	mov loc4 = gp;;
+#  define PSEUDO_RESTORE_GP_1	mov gp = loc4
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+.text;									      \
+ENTRY (name)								      \
+     adds r14 = MULTIPLE_THREADS_OFFSET, r13;;				      \
+     ld4 r14 = [r14];							      \
+     mov r15 = SYS_ify(syscall_name);;					      \
+     cmp4.ne p6, p7 = 0, r14;						      \
+(p6) br.cond.spnt .Lpseudo_cancel;;					      \
+     break __BREAK_SYSCALL;;						      \
+     cmp.eq p6,p0=-1,r10;						      \
+(p6) br.cond.spnt.few __syscall_error;					      \
+     ret;;								      \
+     .endp name;							      \
+     .proc __GC_##name;							      \
+     .globl __GC_##name;						      \
+     .hidden __GC_##name;						      \
+__GC_##name:								      \
+.Lpseudo_cancel:							      \
+     .prologue;								      \
+     .regstk args, PSEUDO_NLOCAL, args, 0;				      \
+     .save ar.pfs, loc0;						      \
+     alloc loc0 = ar.pfs, args, PSEUDO_NLOCAL, args, 0;			      \
+     .save rp, loc1;							      \
+     mov loc1 = rp;							      \
+     PSEUDO_SAVE_GP;;							      \
+     .body;								      \
+     CENABLE;;								      \
+     PSEUDO_RESTORE_GP;							      \
+     mov loc2 = r8;							      \
+     COPY_ARGS_##args							      \
+     mov r15 = SYS_ify(syscall_name);					      \
+     break __BREAK_SYSCALL;;						      \
+     mov loc3 = r8;							      \
+     mov loc4 = r10;							      \
+     mov out0 = loc2;							      \
+     CDISABLE;;								      \
+     PSEUDO_RESTORE_GP;							      \
+     cmp.eq p6,p0=-1,loc4;						      \
+(p6) br.cond.spnt.few __syscall_error_##args;				      \
+     mov r8 = loc3;							      \
+     mov rp = loc1;							      \
+     mov ar.pfs = loc0;							      \
+.Lpseudo_end:								      \
+     ret;								      \
+     .endp __GC_##name;							      \
+.section .gnu.linkonce.t.__syscall_error_##args, "ax";			      \
+     .align 32;								      \
+     .proc __syscall_error_##args;					      \
+     .global __syscall_error_##args;					      \
+     .hidden __syscall_error_##args;					      \
+     .size __syscall_error_##args, 64;					      \
+__syscall_error_##args:							      \
+     .prologue;								      \
+     .regstk args, PSEUDO_NLOCAL, args, 0;				      \
+     .save ar.pfs, loc0;						      \
+     .save rp, loc1;							      \
+     .body;								      \
+     PSEUDO_SAVE_GP_1;							      \
+     br.call.sptk.many b0 = __errno_location;;				      \
+     st4 [r8] = loc3;							      \
+     PSEUDO_RESTORE_GP_1;						      \
+     mov rp = loc1;							      \
+     mov r8 = -1;							      \
+     mov ar.pfs = loc0
+
+#undef PSEUDO_END
+#define PSEUDO_END(name) .endp
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	br.call.sptk.many b0 = __pthread_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+#  define CENABLE	br.call.sptk.many b0 = __libc_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __libc_disable_asynccancel
+# else
+#  define CENABLE	br.call.sptk.many b0 = __librt_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __librt_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov out0 = in0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov out1 = in1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov out2 = in2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov out3 = in3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov out4 = in4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov out5 = in5;
+#define COPY_ARGS_7	COPY_ARGS_6 mov out6 = in6;
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P \
+  adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S
new file mode 100644
index 0000000000..54acedad4c
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S
@@ -0,0 +1,54 @@
+/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+
+#include <sysdep-cancel.h>
+#define _SIGNAL_H
+#include <bits/signum.h>
+
+/* The following are defined in linux/sched.h, which unfortunately	*/
+/* is not safe for inclusion in an assembly file.			*/
+#define CLONE_VM        0x00000100      /* set if VM shared between processes */
+#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+
+/* pid_t vfork(void); */
+/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)	*/
+
+ENTRY(__vfork)
+#ifdef SHARED
+	addl r14 = @gprel(__libc_pthread_functions#), gp;;
+#else
+	.weak	pthread_create
+	addl r14 = @ltoff(@fptr(pthread_create#)), gp;;
+#endif
+	ld8 r14 = [r14];;
+	cmp.ne p6, p7 = 0, r14
+(p6)	br.cond.spnt.few HIDDEN_JUMPTARGET (__fork);;
+	alloc r2=ar.pfs,0,0,2,0
+	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
+	mov out1=0		/* Standard sp value.			*/
+	;;
+	DO_CALL (SYS_ify (clone))
+	cmp.eq p6,p0=-1,r10
+	;;
+(p6)	br.cond.spnt.few __syscall_error
+	ret
+PSEUDO_END(__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c
new file mode 100644
index 0000000000..4b90315707
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c
@@ -0,0 +1,34 @@
+/* _longjmp_unwind -- Clean up stack frames unwound by longjmp.
+   Copyright (C) 2002, 2003 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>
+#include <bits/libc-lock.h>
+
+#ifndef SHARED
+weak_extern (__pthread_cleanup_upto);
+#endif
+
+void
+_longjmp_unwind (jmp_buf env, int val)
+{
+  __libc_maybe_call2 (pthread_cleanup_upto,
+		      (env->__jmpbuf, __builtin_frame_address (0)),
+		      (void) 0);
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h
new file mode 100644
index 0000000000..bb798e40d6
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h
@@ -0,0 +1,129 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@suse.de>, 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 __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+    SINGLE_THREAD_P;							      \
+    jne .Lpseudo_cancel;						      \
+    DO_CALL (syscall_name, args);					      \
+    cmp.l &-4095, %d0;							      \
+    jcc SYSCALL_ERROR_LABEL;						      \
+    rts;								      \
+  .Lpseudo_cancel:							      \
+    CENABLE;								      \
+    DOCARGS_##args							      \
+    move.l %d0, -(%sp);							      \
+    move.l &SYS_ify (syscall_name), %d0;				      \
+    trap &0;								      \
+    move.l %d0, %d2;							      \
+    CDISABLE;								      \
+    addq.l &4, %sp;							      \
+    move.l %d2, %d0;							      \
+    UNDOCARGS_##args							      \
+    cmp.l &-4095, %d0;							      \
+    jcc SYSCALL_ERROR_LABEL
+
+# define DOCARGS_0	move.l %d2, -(%sp);
+# define _DOCARGS_0(n)
+# define UNDOCARGS_0	move.l (%sp)+, %d2;
+
+# define DOCARGS_1	_DOCARGS_1 (4); DOCARGS_0
+# define _DOCARGS_1(n)	move.l n(%sp), %d1; _DOARGS_0 (n)
+# define UNDOCARGS_1	UNDOCARGS_0
+
+# define DOCARGS_2	_DOCARGS_2 (8)
+# define _DOCARGS_2(n)	move.l %d2, -(%sp); move.l n+4(%sp), %d2;	\
+			_DOCARGS_1 (n)
+# define UNDOCARGS_2	UNDOCARGS_1
+
+# define DOCARGS_3	_DOCARGS_3 (12)
+# define _DOCARGS_3(n)	move.l %d3, -(%sp); move.l n+4(%sp), %d3;	\
+  	 		_DOCARGS_2 (n)
+# define UNDOCARGS_3	UNDOCARGS_2; move.l (%sp)+, %d3;
+
+# define DOCARGS_4	_DOCARGS_4 (16)
+# define _DOCARGS_4(n)	move.l %d4, -(%sp); move.l n+4(%sp), %d4;	\
+			_DOCARGS_3 (n)
+# define UNDOCARGS_4	UNDOCARGS_3; move.l (%sp)+, %d4;
+
+# define DOCARGS_5	_DOCARGS_5 (20)
+# define _DOCARGS_5(n)	move.l %d5, -(%sp); move.l n+4(%sp), %d5;	\
+			_DOCARGS_4 (n)
+# define UNDOCARGS_5	UNDOCARGS_4; move.l (%sp)+, %d5;
+
+# ifdef IS_IN_libpthread
+#  ifdef PIC
+#   define CENABLE	jbsr __pthread_enable_asynccancel@PLTPC
+#   define CDISABLE	jbsr __pthread_disable_asynccancel@PLTPC
+#  else
+#   define CENABLE	jbsr __pthread_enable_asynccancel
+#   define CDISABLE	jbsr __pthread_disable_asynccancel
+#  endif
+# elif !defined NOT_IN_libc
+#  ifdef PIC
+#   define CENABLE	jbsr __libc_enable_asynccancel@PLTPC
+#   define CDISABLE	jbsr __libc_disable_asynccancel@PLTPC
+#  else
+#   define CENABLE	jbsr __libc_enable_asynccancel
+#   define CDISABLE	jbsr __libc_disable_asynccancel
+#  endif
+# else
+#  ifdef PIC
+#   define CENABLE	jbsr __librt_enable_asynccancel@PLTPC
+#   define CDISABLE	jbsr __librt_disable_asynccancel@PLTPC
+#  else
+#   define CENABLE	jbsr __librt_enable_asynccancel
+#   define CDISABLE	jbsr __librt_disable_asynccancel
+#  endif
+# endif
+
+# if !defined NOT_IN_libc
+#  define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_libpthread
+#  define __local_multiple_threads __pthread_multiple_threads
+# else
+#  define __local_multiple_threads __librt_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  if !defined PIC
+#   define SINGLE_THREAD_P tst.l __local_multiple_threads
+#  else
+#   define SINGLE_THREAD_P tst.l (__local_multiple_threads, %pc)
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S
new file mode 100644
index 0000000000..49b8a3c0ac
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S
@@ -0,0 +1,84 @@
+/* Copyright (C) 1999, 2002, 2003 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-cancel.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)
+
+#ifdef SHARED
+	tstl	(__libc_pthread_functions@GOTPC, %pc)
+#else
+	.weak	pthread_create
+	movel	#pthread_create, %d0
+#endif
+	jbne	HIDDEN_JUMPTARGET (__fork)
+
+#ifdef __NR_vfork
+
+	/* Pop the return PC value into A0.  */
+	movel	%sp@+, %a0
+
+	/* Stuff the syscall number in D0 and trap into the kernel.  */
+	movel	#SYS_ify (vfork), %d0
+	trap	#0
+	tstl	%d0
+	jmi	.Lerror		/* Branch forward if it failed.  */
+
+	/* Jump to the return PC.  */
+	jmp	%a0@
+
+.Lerror:
+	/* Push back the return PC.  */
+	movel	%a0,%sp@-
+
+# ifdef __ASSUME_VFORK_SYSCALL
+#  ifndef PIC
+	jbra	SYSCALL_ERROR_LABEL
+#  endif
+# else
+	/* Check if vfork syscall is known at all.  */
+	movel	#-ENOSYS,%d1
+	cmpl	%d0,%d1
+	jne	SYSCALL_ERROR_LABEL
+
+# endif
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* If we don't have vfork, fork is close enough.  */
+
+	movel	#SYS_ify (fork), %d0
+	trap	#0
+	tstl	%d0
+	jmi	SYSCALL_ERROR_LABEL
+	rts
+#endif
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile
new file mode 100644
index 0000000000..56eeecc789
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile
@@ -0,0 +1,3 @@
+# pull in __syscall_error routine
+libpthread-routines += sysdep
+
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
new file mode 100644
index 0000000000..fc51774252
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
@@ -0,0 +1,144 @@
+/* system call stubs with cancellation handling.  Linux/MIPS version.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Demetriou of Broadcom Corporation,
+   based on work by Guido Guenther <agx@sigxcpu.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>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+#include <sys/asm.h>
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+#ifdef __PIC__
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .align 2;								      \
+  99:									      \
+  PTR_LA t9,__syscall_error;					 	      \
+  /* manual cpreturn.  */						      \
+  REG_L gp, STKOFF_GP(sp);						      \
+  RESTORESTK ;								      \
+  jr t9;								      \
+  ENTRY (name)								      \
+    SAVESTK ;								      \
+    .cpsetup t9, STKOFF_GP, name ;					      \
+    .set reorder;							      \
+    SINGLE_THREAD_P(t0);						      \
+    bne zero, t0, L(pseudo_cancel);					      \
+    .set noreorder;							      \
+    li v0, SYS_ify(syscall_name);					      \
+    syscall;								      \
+    .set reorder;							      \
+    bne a3, zero, SYSCALL_ERROR_LABEL;			       		      \
+    /* manual cpreturn.  */						      \
+    REG_L gp, STKOFF_GP(sp);						      \
+    RESTORESTK ;							      \
+    ret;								      \
+  L(pseudo_cancel):							      \
+    REG_S ra, STKOFF_RA(sp);						      \
+    PUSHARGS_##args;			/* save syscall args */	      	      \
+    CENABLE;								      \
+    REG_S v0, STKOFF_SVMSK(sp);		/* save mask */			      \
+    POPARGS_##args;			/* restore syscall args */	      \
+    .set noreorder;							      \
+    li v0, SYS_ify (syscall_name);				      	      \
+    syscall;								      \
+    .set reorder;							      \
+    REG_S v0, STKOFF_SC_V0(sp);		/* save syscall result */             \
+    REG_S a3, STKOFF_SC_ERR(sp);	/* save syscall error flag */	      \
+    REG_L a0, STKOFF_SVMSK(sp);		/* pass mask as arg1 */		      \
+    CDISABLE;								      \
+    REG_L a3, STKOFF_SC_ERR(sp);	/* restore syscall error flag */      \
+    REG_L ra, STKOFF_RA(sp);		/* restore return address */	      \
+    REG_L v0, STKOFF_SC_V0(sp);		/* restore syscall result */          \
+    bne a3, zero, SYSCALL_ERROR_LABEL;					      \
+    /* manual cpreturn.  */						      \
+    REG_L gp, STKOFF_GP(sp);						      \
+    RESTORESTK ;							      \
+  L(pseudo_end):
+#endif
+
+# define PUSHARGS_0	/* nothing to do */
+# define PUSHARGS_1	PUSHARGS_0 REG_S a0, STKOFF_A0(sp);
+# define PUSHARGS_2	PUSHARGS_1 REG_S a1, STKOFF_A1(sp);
+# define PUSHARGS_3	PUSHARGS_2 REG_S a2, STKOFF_A2(sp);
+# define PUSHARGS_4	PUSHARGS_3 REG_S a3, STKOFF_A3(sp);
+# define PUSHARGS_5	PUSHARGS_4 REG_S a4, STKOFF_A4(sp);
+# define PUSHARGS_6	PUSHARGS_5 REG_S a5, STKOFF_A5(sp);
+
+# define POPARGS_0	/* nothing to do */
+# define POPARGS_1	POPARGS_0 REG_L a0, STKOFF_A0(sp);
+# define POPARGS_2	POPARGS_1 REG_L a1, STKOFF_A1(sp);
+# define POPARGS_3	POPARGS_2 REG_L a2, STKOFF_A2(sp);
+# define POPARGS_4	POPARGS_3 REG_L a3, STKOFF_A3(sp);
+# define POPARGS_5	POPARGS_4 REG_L a4, STKOFF_A4(sp);
+# define POPARGS_6	POPARGS_5 REG_L a5, STKOFF_A5(sp);
+
+/* Save an even number of slots.  Should be 0 if an even number of slots
+   are used below, or SZREG if an odd number are used.  */
+# define STK_PAD	SZREG
+
+/* Place values that we are more likely to use later in this sequence, i.e.
+   closer to the SP at function entry.  If you do that, the are more
+   likely to already be in your d-cache.  */
+# define STKOFF_A5	(STK_PAD)
+# define STKOFF_A4	(STKOFF_A5 + SZREG)
+# define STKOFF_A3	(STKOFF_A4 + SZREG)
+# define STKOFF_A2	(STKOFF_A3 + SZREG)	/* MT and more args.  */
+# define STKOFF_A1	(STKOFF_A2 + SZREG)	/* MT and 2 args.  */
+# define STKOFF_A0	(STKOFF_A1 + SZREG)	/* MT and 1 arg.  */
+# define STKOFF_RA	(STKOFF_A0 + SZREG)	/* Used if MT.  */
+# define STKOFF_SC_V0	(STKOFF_RA + SZREG)	/* Used if MT.  */
+# define STKOFF_SC_ERR	(STKOFF_SC_V0 + SZREG)	/* Used if MT.  */
+# define STKOFF_SVMSK	(STKOFF_SC_ERR + SZREG)	/* Used if MT.  */
+# define STKOFF_GP	(STKOFF_SVMSK + SZREG)	/* Always used.  */
+
+# define STKSPACE	(STKOFF_GP + SZREG)
+# define SAVESTK 	PTR_SUBU sp, STKSPACE
+# define RESTORESTK 	PTR_ADDU sp, STKSPACE
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	PTR_LA t9, __pthread_enable_asynccancel; jalr t9;
+#  define CDISABLE	PTR_LA t9, __pthread_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif defined IS_IN_librt
+#  define CENABLE	PTR_LA t9, __librt_enable_asynccancel; jalr t9;
+#  define CDISABLE	PTR_LA t9, __librt_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __librt_multiple_threads
+# else
+#  define CENABLE	PTR_LA t9, __libc_enable_asynccancel; jalr t9;
+#  define CDISABLE	PTR_LA t9, __libc_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads
+#endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h
new file mode 100644
index 0000000000..1fff782397
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h
@@ -0,0 +1,143 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Guido Guenther <agx@sigxcpu.org>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+#ifdef __PIC__
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .align 2;								      \
+  99: la t9,__syscall_error;						      \
+  jr t9;								      \
+  ENTRY (name)								      \
+    .set noreorder;							      \
+    .cpload t9;								      \
+    .set reorder;							      \
+    SINGLE_THREAD_P(t0);						      \
+    bne zero, t0, L(pseudo_cancel);					      \
+    .set noreorder;							      \
+    li v0, SYS_ify(syscall_name);					      \
+    syscall;								      \
+    .set reorder;							      \
+    bne a3, zero, SYSCALL_ERROR_LABEL;			       		      \
+    ret;								      \
+  L(pseudo_cancel):							      \
+    SAVESTK_##args;						              \
+    sw ra, 28(sp);							      \
+    sw gp, 32(sp);							      \
+    PUSHARGS_##args;			/* save syscall args */	      	      \
+    CENABLE;								      \
+    lw gp, 32(sp);							      \
+    sw v0, 44(sp);			/* save mask */			      \
+    POPARGS_##args;			/* restore syscall args */	      \
+    .set noreorder;							      \
+    li v0, SYS_ify (syscall_name);				      	      \
+    syscall;								      \
+    .set reorder;							      \
+    sw v0, 36(sp);			/* save syscall result */             \
+    sw a3, 40(sp);			/* save syscall error flag */	      \
+    lw a0, 44(sp);			/* pass mask as arg1 */		      \
+    CDISABLE;								      \
+    lw gp, 32(sp);							      \
+    lw v0, 36(sp);			/* restore syscall result */          \
+    lw a3, 40(sp);			/* restore syscall error flag */      \
+    lw ra, 28(sp);			/* restore return address */	      \
+    RESTORESTK;							              \
+    bne a3, zero, SYSCALL_ERROR_LABEL;					      \
+  L(pseudo_end):
+#endif
+
+# define PUSHARGS_0	/* nothing to do */
+# define PUSHARGS_1	PUSHARGS_0 sw a0, 0(sp);
+# define PUSHARGS_2	PUSHARGS_1 sw a1, 4(sp);
+# define PUSHARGS_3	PUSHARGS_2 sw a2, 8(sp);
+# define PUSHARGS_4	PUSHARGS_3 sw a3, 12(sp);
+# define PUSHARGS_5	PUSHARGS_4 /* handeld by SAVESTK_## */
+# define PUSHARGS_6	PUSHARGS_5
+# define PUSHARGS_7	PUSHARGS_6
+
+# define POPARGS_0	/* nothing to do */
+# define POPARGS_1	POPARGS_0 lw a0, 0(sp);
+# define POPARGS_2	POPARGS_1 lw a1, 4(sp);
+# define POPARGS_3	POPARGS_2 lw a2, 8(sp);
+# define POPARGS_4	POPARGS_3 lw a3, 12(sp);
+# define POPARGS_5	POPARGS_4 /* args already in new stackframe */
+# define POPARGS_6	POPARGS_5
+# define POPARGS_7	POPARGS_6
+
+
+# define STKSPACE	48
+# define SAVESTK_0 	subu sp, STKSPACE
+# define SAVESTK_1      SAVESTK_0
+# define SAVESTK_2      SAVESTK_1
+# define SAVESTK_3      SAVESTK_2
+# define SAVESTK_4      SAVESTK_3
+# define SAVESTK_5      lw t0, 16(sp);		\
+			subu sp, STKSPACE;	\
+			sw t0, 16(sp)
+
+# define SAVESTK_6      lw t0, 16(sp);		\
+			lw t1, 20(sp);		\
+			subu sp, STKSPACE;	\
+			sw t0, 16(sp);		\
+			sw t1, 20(sp)
+
+# define SAVESTK_7      lw t0, 16(sp);		\
+			lw t1, 20(sp);		\
+			lw t2, 24(sp);		\
+			subu sp, STKSPACE;	\
+			sw t0, 16(sp);		\
+			sw t1, 20(sp);		\
+			sw t2, 24(sp)
+
+# define RESTORESTK 	addu sp, STKSPACE
+
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	la t9, __pthread_enable_asynccancel; jalr t9;
+#  define CDISABLE	la t9, __pthread_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif defined IS_IN_librt
+#  define CENABLE	la t9, __librt_enable_asynccancel; jalr t9;
+#  define CDISABLE	la t9, __librt_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __librt_multiple_threads
+# else
+#  define CENABLE	la t9, __libc_enable_asynccancel; jalr t9;
+#  define CDISABLE	la t9, __libc_disable_asynccancel; jalr t9;
+#  define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads
+#endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c b/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c
new file mode 100644
index 0000000000..e9c2b6e79a
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c
@@ -0,0 +1,287 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contribute by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <not-cancel.h>
+
+
+#ifdef __NR_mq_notify
+
+/* Defined in the kernel headers: */
+#define NOTIFY_COOKIE_LEN	32	/* Length of the cookie used.  */
+#define NOTIFY_WOKENUP		1	/* Code for notifcation.  */
+#define NOTIFY_REMOVED		2	/* Code for closed message queue
+					   of de-notifcation.  */
+
+
+/* Data structure for the queued notification requests.  */
+union notify_data
+{
+  struct
+  {
+    void (*fct) (union sigval);	/* The function to run.  */
+    union sigval param;		/* The parameter to pass.  */
+    pthread_attr_t *attr;	/* Attributes to create the thread with.  */
+    /* NB: on 64-bit machines the struct as a size of 24 bytes.  Which means
+       byte 31 can still be used for returning the status.  */
+  };
+  char raw[NOTIFY_COOKIE_LEN];
+};
+
+
+/* Keep track of the initialization.  */
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+
+/* The netlink socket.  */
+static int netlink_socket = -1;
+
+
+/* Barrier used to make sure data passed to the new thread is not
+   resused by the parent.  */
+static pthread_barrier_t notify_barrier;
+
+
+/* Modify the signal mask.  We move this into a separate function so
+   that the stack space needed for sigset_t is not deducted from what
+   the thread can use.  */
+static int
+__attribute__ ((noinline))
+change_sigmask (int how, sigset_t *oss)
+{
+  sigset_t ss;
+  sigfillset (&ss);
+  return pthread_sigmask (how, &ss, oss);
+}
+
+
+/* The function used for the notification.  */
+static void *
+notification_function (void *arg)
+{
+  /* Copy the function and parameter so that the parent thread can go
+     on with its life.  */
+  volatile union notify_data *data = (volatile union notify_data *) arg;
+  void (*fct) (union sigval) = data->fct;
+  union sigval param = data->param;
+
+  /* Let the parent go.  */
+  (void) pthread_barrier_wait (&notify_barrier);
+
+  /* Make the thread detached.  */
+  (void) pthread_detach (pthread_self ());
+
+  /* The parent thread has all signals blocked.  This is probably a
+     bit surprising for this thread.  So we unblock all of them.  */
+  (void) change_sigmask (SIG_UNBLOCK, NULL);
+
+  /* Now run the user code.  */
+  fct (param);
+
+  /* And we are done.  */
+  return NULL;
+}
+
+
+/* Helper thread.  */
+static void *
+helper_thread (void *arg)
+{
+  while (1)
+    {
+      union notify_data data;
+
+      ssize_t n = recv (netlink_socket, &data, sizeof (data),
+			MSG_NOSIGNAL | MSG_WAITALL);
+      if (n < NOTIFY_COOKIE_LEN)
+	continue;
+
+      if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP)
+	{
+	  /* Just create the thread as instructed.  There is no way to
+	     report a problem with creating a thread.  */
+	  pthread_t th;
+	  if (__builtin_expect (pthread_create (&th, data.attr,
+						notification_function, &data)
+				== 0, 0))
+	    /* Since we passed a pointer to DATA to the new thread we have
+	       to wait until it is done with it.  */
+	    (void) pthread_barrier_wait (&notify_barrier);
+	}
+      else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
+	/* The only state we keep is the copy of the thread attributes.  */
+	free (data.attr);
+    }
+  return NULL;
+}
+
+
+static void
+reset_once (void)
+{
+  once = PTHREAD_ONCE_INIT;
+}
+
+
+static void
+init_mq_netlink (void)
+{
+  /* This code might be called a second time after fork().  The file
+     descriptor is inherited from the parent.  */
+  if (netlink_socket == -1)
+    {
+      /* Just a normal netlink socket, not bound.  */
+      netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0);
+      /* No need to do more if we have no socket.  */
+      if (netlink_socket == -1)
+	return;
+
+      /* Make sure the descriptor is closed on exec.  */
+      if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0)
+	goto errout;
+    }
+
+  int err = 1;
+
+  /* Initialize the barrier.  */
+  if (__builtin_expect (pthread_barrier_init (&notify_barrier, NULL, 2) == 0,
+			0))
+    {
+      /* Create the helper thread.  */
+      pthread_attr_t attr;
+      (void) pthread_attr_init (&attr);
+      (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+      /* We do not need much stack space, the bare minimum will be enough.  */
+      (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+
+      /* Temporarily block all signals so that the newly created
+	 thread inherits the mask.  */
+      sigset_t oss;
+      int have_no_oss = change_sigmask (SIG_BLOCK, &oss);
+
+      pthread_t th;
+      err = pthread_create (&th, &attr, helper_thread, NULL);
+
+      /* Reset the signal mask.  */
+      if (!have_no_oss)
+	pthread_sigmask (SIG_SETMASK, &oss, NULL);
+
+      (void) pthread_attr_destroy (&attr);
+
+      if (err == 0)
+	{
+	  static int added_atfork;
+
+	  if (added_atfork == 0
+	      && pthread_atfork (NULL, NULL, reset_once) != 0)
+	    {
+	      /* The child thread will call recv() which is a
+		 cancellation point.  */
+	      (void) pthread_cancel (th);
+	      err = 1;
+	    }
+	  else
+	    added_atfork = 1;
+	}
+    }
+
+  if (err != 0)
+    {
+    errout:
+      close_not_cancel_no_status (netlink_socket);
+      netlink_socket = -1;
+    }
+}
+
+
+/* Register notification upon message arrival to an empty message queue
+   MQDES.  */
+int
+mq_notify (mqd_t mqdes, const struct sigevent *notification)
+{
+  /* Make sure the type is correctly defined.  */
+  assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN);
+
+  /* Special treatment needed for SIGEV_THREAD.  */
+  if (notification == NULL || notification->sigev_notify != SIGEV_THREAD)
+    return INLINE_SYSCALL (mq_notify, 2, mqdes, notification);
+
+  /* The kernel cannot directly start threads.  This will have to be
+     done at userlevel.  Since we cannot start threads from signal
+     handlers we have to create a dedicated thread which waits for
+     notifications for arriving messages and creates threads in
+     response.  */
+
+  /* Initialize only once.  */
+  pthread_once (&once, init_mq_netlink);
+
+  /* If we cannot create the netlink socket we cannot provide
+     SIGEV_THREAD support.  */
+  if (__builtin_expect (netlink_socket == -1, 0))
+    {
+      __set_errno (ENOSYS);
+      return -1;
+    }
+
+  /* Create the cookie.  It will hold almost all the state.  */
+  union notify_data data;
+  memset (&data, '\0', sizeof (data));
+  data.fct = notification->sigev_notify_function;
+  data.param = notification->sigev_value;
+
+  if (notification->sigev_notify_attributes != NULL)
+    {
+      /* The thread attribute has to be allocated separately.  */
+      data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t));
+      if (data.attr == NULL)
+	return -1;
+
+      memcpy (data.attr, notification->sigev_notify_attributes,
+	      sizeof (pthread_attr_t));
+    }
+
+  /* Construct the new request.  */
+  struct sigevent se;
+  se.sigev_notify = SIGEV_THREAD;
+  se.sigev_signo = netlink_socket;
+  se.sigev_value.sival_ptr = &data;
+
+  /* Tell the kernel.  */
+  int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
+
+  /* If it failed, free the allocated memory.  */
+  if (__builtin_expect (retval != 0, 0))
+    free (data.attr);
+
+  return retval;
+}
+
+#else
+# include <sysdeps/generic/mq_notify.c>
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile
new file mode 100644
index 0000000000..e98c9bd866
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -0,0 +1,2 @@
+# pull in __syscall_error routine
+libpthread-routines += sysdep
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions
new file mode 100644
index 0000000000..326307c30c
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_2.3.4 {
+    longjmp;  siglongjmp;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
new file mode 100644
index 0000000000..0ee10c1c3a
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  .section ".text";							\
+  ENTRY (name)								\
+    SINGLE_THREAD_P;							\
+    bne- .Lpseudo_cancel;						\
+    DO_CALL (SYS_ify (syscall_name));					\
+    PSEUDO_RET;								\
+  .Lpseudo_cancel:							\
+    stwu 1,-48(1);							\
+    mflr 9;								\
+    stw 9,52(1);							\
+    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
+    CENABLE;								\
+    stw 3,16(1);	/* store CENABLE return value (MASK).  */	\
+    UNDOCARGS_##args;	/* restore syscall args.  */			\
+    DO_CALL (SYS_ify (syscall_name));					\
+    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
+    stw 3,8(1);								\
+    stw 0,12(1);							\
+    lwz 3,16(1);	/* pass MASK to CDISABLE.  */			\
+    CDISABLE;								\
+    lwz 4,52(1);							\
+    lwz 0,12(1);	/* restore CR/R3. */				\
+    lwz 3,8(1);								\
+    mtlr 4;								\
+    mtcr 0;								\
+    addi 1,1,48;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+
+# define DOCARGS_1	stw 3,20(1); DOCARGS_0
+# define UNDOCARGS_1	lwz 3,20(1); UNDOCARGS_0
+
+# define DOCARGS_2	stw 4,24(1); DOCARGS_1
+# define UNDOCARGS_2	lwz 4,24(1); UNDOCARGS_1
+
+# define DOCARGS_3	stw 5,28(1); DOCARGS_2
+# define UNDOCARGS_3	lwz 5,28(1); UNDOCARGS_2
+
+# define DOCARGS_4	stw 6,32(1); DOCARGS_3
+# define UNDOCARGS_4	lwz 6,32(1); UNDOCARGS_3
+
+# define DOCARGS_5	stw 7,36(1); DOCARGS_4
+# define UNDOCARGS_5	lwz 7,36(1); UNDOCARGS_4
+
+# define DOCARGS_6	stw 8,40(1); DOCARGS_5
+# define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
+# elif !defined NOT_IN_libc
+#  define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel)
+# else
+#  define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel)
+# endif
+
+# ifdef HAVE_TLS_SUPPORT
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P						\
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
+#  else
+#   define SINGLE_THREAD_P						\
+  lwz 10,MULTIPLE_THREADS_OFFSET(2);					\
+  cmpwi 10,0
+#  endif
+# else
+#  if !defined NOT_IN_libc
+#   define __local_multiple_threads __libc_multiple_threads
+#  else
+#   define __local_multiple_threads __librt_multiple_threads
+#  endif
+#  ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+#  else
+#   if !defined PIC
+#    define SINGLE_THREAD_P						\
+  lis 10,__local_multiple_threads@ha;					\
+  lwz 10,__local_multiple_threads@l(10);				\
+  cmpwi 10,0
+#   else
+#    define SINGLE_THREAD_P						\
+  mflr 9;								\
+  bl _GLOBAL_OFFSET_TABLE_@local-4;					\
+  mflr 10;								\
+  mtlr 9;								\
+  lwz 10,__local_multiple_threads@got(10);				\
+  lwz 10,0(10);								\
+  cmpwi 10,0
+#   endif
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
new file mode 100644
index 0000000000..ee6254a950
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
@@ -0,0 +1,78 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.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)
+
+#ifdef __NR_vfork
+# ifdef SHARED
+	mflr	9
+	bl	_GLOBAL_OFFSET_TABLE_@local-4
+	mflr	10
+	mtlr	9
+	lwz	10,__libc_pthread_functions@got(10)
+	lwz	10,0(10)
+# else
+	.weak	pthread_create
+	lis	10,pthread_create@ha
+	la	10,pthread_create@l(10)
+# endif
+
+	cmpwi	10,0
+	bne-	.Lhidden_fork
+
+	DO_CALL (SYS_ify (vfork));
+
+# ifdef __ASSUME_VFORK_SYSCALL
+	PSEUDO_RET
+# else
+	bnslr+
+	/* Check if vfork syscall is known at all.  */
+	cmpwi	r3,ENOSYS
+	bne-	.Lsyscall_error
+
+# endif
+
+.Lhidden_fork:
+	b	HIDDEN_JUMPTARGET(__fork)
+
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* If we don't have vfork, fork is close enough.  */
+
+	DO_CALL (SYS_ify (fork));
+	bnslr+
+
+.Lsyscall_error:
+	b	JUMPTARGET(__syscall_error)
+#endif
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
new file mode 100644
index 0000000000..0c74676766
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  .section ".text";							\
+  ENTRY (name)								\
+    SINGLE_THREAD_P;							\
+    bne- .Lpseudo_cancel;						\
+    DO_CALL (SYS_ify (syscall_name));					\
+    PSEUDO_RET;								\
+  .Lpseudo_cancel:							\
+    stdu 1,-128(1);							\
+    mflr 9;								\
+    std  9,128+16(1);							\
+    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
+    CENABLE;								\
+    std  3,72(1);	/* store CENABLE return value (MASK).  */	\
+    UNDOCARGS_##args;	/* restore syscall args.  */			\
+    DO_CALL (SYS_ify (syscall_name));					\
+    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
+    std  3,64(1);								\
+    std  0,8(1);							\
+    ld   3,72(1);	/* pass MASK to CDISABLE.  */			\
+    CDISABLE;								\
+    ld   9,128+16(1);							\
+    ld   0,8(1);	/* restore CR/R3. */				\
+    ld   3,64(1);								\
+    mtlr 9;								\
+    mtcr 0;								\
+    addi 1,1,128;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+
+# define DOCARGS_1	std 3,80(1); DOCARGS_0
+# define UNDOCARGS_1	ld 3,80(1); UNDOCARGS_0
+
+# define DOCARGS_2	std 4,88(1); DOCARGS_1
+# define UNDOCARGS_2	ld 4,88(1); UNDOCARGS_1
+
+# define DOCARGS_3	std 5,96(1); DOCARGS_2
+# define UNDOCARGS_3	ld 5,96(1); UNDOCARGS_2
+
+# define DOCARGS_4	std 6,104(1); DOCARGS_3
+# define UNDOCARGS_4	ld 6,104(1); UNDOCARGS_3
+
+# define DOCARGS_5	std 7,112(1); DOCARGS_4
+# define UNDOCARGS_5	ld 7,112(1); UNDOCARGS_4
+
+# define DOCARGS_6	std 8,120(1); DOCARGS_5
+# define UNDOCARGS_6	ld 8,120(1); UNDOCARGS_5
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# else
+#  define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel); nop
+#  define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel); nop
+#  define __local_multiple_threads __librt_multiple_threads
+# endif
+
+# ifdef HAVE_TLS_SUPPORT
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P						\
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
+#  else
+#   define SINGLE_THREAD_P						\
+  lwz 10,MULTIPLE_THREADS_OFFSET(13);					\
+  cmpwi 10,0
+#  endif
+# else /* !HAVE_TLS_SUPPORT */
+#  ifndef __ASSEMBLER__
+extern int __local_multiple_threads
+#   if !defined NOT_IN_libc || defined IS_IN_libpthread
+  attribute_hidden;
+#   else
+  ;
+#   endif
+#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+#  else
+#   define SINGLE_THREAD_P						\
+	.section	".toc","aw";					\
+.LC__local_multiple_threads:;						\
+	.tc __local_multiple_threads[TC],__local_multiple_threads;	\
+  .previous;								\
+  ld    10,.LC__local_multiple_threads@toc(2);				\
+  lwz   10,0(10);							\
+  cmpwi 10,0
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
new file mode 100644
index 0000000000..b408e31b7b
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
@@ -0,0 +1,91 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.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.  */
+
+#ifdef SHARED
+	.section	".toc","aw"
+.LC0:
+	.tc __libc_pthread_functions[TC],__libc_pthread_functions
+	.section	".text"
+	.align 2
+#endif
+
+ENTRY (__vfork)
+
+#ifdef __NR_vfork
+
+# ifdef SHARED
+  ld  10,.LC0@toc(2)
+  ld  10,0(10)
+  cmpwi  10,0
+  bne-  HIDDEN_JUMPTARGET(__fork)
+# else
+  .weak  pthread_create
+	lis  10,pthread_create@highest
+	ori  10,10,pthread_create@higher
+  sldi 10,10,32
+  oris 10,10,pthread_create@h
+  ori  10,10,pthread_create@l
+  cmpwi  10,0
+  bne-  .Lhidden_fork
+# endif
+
+	DO_CALL (SYS_ify (vfork));
+
+# ifdef __ASSUME_VFORK_SYSCALL
+  PSEUDO_RET
+# else
+  bnslr+
+  /* Check if vfork syscall is known at all.  */
+  cmpdi	r3,ENOSYS
+# ifdef SHARED
+  bne	JUMPTARGET(__syscall_error)
+# else
+  bne-  .Lsyscall_error
+# endif
+
+# endif
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+	/* If we don't have vfork, fork is close enough.  */
+
+	DO_CALL (SYS_ify (fork));
+	PSEUDO_RET
+#endif
+
+# ifndef SHARED
+.Lhidden_fork:
+	b	HIDDEN_JUMPTARGET(__fork)
+.Lsyscall_error:
+	b	JUMPTARGET(__syscall_error)
+# endif
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c
new file mode 100644
index 0000000000..177256c7fb
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c
@@ -0,0 +1,70 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program 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.               */
+/*                                                                      */
+/* This program 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.                 */
+
+/* Redefine siglongjmp and longjmp so that they interact correctly
+   with cleanup handlers */
+/* Derived from linuxthreads/ptlongjmp.c & added AltiVec/VMX versioning. */
+#include "pthread.h"
+#include <setjmp.h>
+#include <bits/wordsize.h>
+#include <shlib-compat.h>
+#if defined SHARED
+# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4)
+
+/* These functions are not declared anywhere since they shouldn't be
+   used at another place but here.  */
+extern void __novmx__libc_siglongjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+extern void __novmx__libc_longjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+
+
+void __novmx_siglongjmp (sigjmp_buf env, int val)
+{
+  __novmx__libc_siglongjmp (env, val);
+}
+
+void __novmx_longjmp (jmp_buf env, int val)
+{
+  __novmx__libc_longjmp (env, val);
+}
+
+#  if __WORDSIZE == 64
+symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3);
+symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3);
+#  else
+symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0);
+symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0);
+#  endif
+# endif  /* SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) ) */
+
+/* These functions are not declared anywhere since they shouldn't be
+   used at another place but here.  */
+extern void __vmx__libc_siglongjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+extern void __vmx__libc_longjmp (sigjmp_buf env, int val)
+     __attribute__ ((noreturn));
+
+void __vmx_siglongjmp (sigjmp_buf env, int val)
+{
+  __vmx__libc_siglongjmp (env, val);
+}
+
+void __vmx_longjmp (jmp_buf env, int val)
+{
+  __vmx__libc_longjmp (env, val);
+}
+default_symbol_version (__vmx_longjmp,longjmp,GLIBC_2.3.4);
+default_symbol_version (__vmx_siglongjmp,siglongjmp,GLIBC_2.3.4);
+#endif /* SHARED */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c
new file mode 100644
index 0000000000..5528c55ca5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c
@@ -0,0 +1,56 @@
+/* Internal sigsuspend system call for LinuxThreads.  Generic Linux version.
+   Copyright (C) 2003 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 <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <linuxthreads/internals.h>
+
+#include "kernel-features.h"
+
+void
+__pthread_sigsuspend (const sigset_t *set)
+{
+  INTERNAL_SYSCALL_DECL (err);
+#if !__ASSUME_REALTIME_SIGNALS
+  static int __pthread_missing_rt_sigs;
+
+# ifdef __NR_rt_sigsuspend
+  /* First try the RT signals.  */
+  if (!__pthread_missing_rt_sigs)
+    {
+      /* XXX The size argument hopefully will have to be changed to the
+	 real size of the user-level sigset_t.  */
+      int r;
+      r = INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+      if (INTERNAL_SYSCALL_ERRNO (r, err) != ENOSYS)
+	return;
+
+      __pthread_missing_rt_sigs = 1;
+    }
+# endif
+
+  INTERNAL_SYSCALL (sigsuspend, err, 3, 0, 0, set->__val[0]);
+#else
+  INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+#endif
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/raise.c b/linuxthreads/sysdeps/unix/sysv/linux/raise.c
new file mode 100644
index 0000000000..9dad2b2697
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/raise.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991, 1996, 2002, 2003 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 <signal.h>
+#include <unistd.h>
+#include <bits/libc-lock.h>
+
+#ifndef SHARED
+weak_extern (__pthread_raise)
+#endif
+
+/* Raise the signal SIG.  */
+int
+raise (sig)
+     int sig;
+{
+  return __libc_maybe_call2 (pthread_raise, (sig),
+			     __kill (__getpid (), sig));
+}
+libc_hidden_def (raise)
+weak_alias (raise, gsignal)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c
new file mode 100644
index 0000000000..e4490e73e9
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c
@@ -0,0 +1,88 @@
+/* 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.  */
+  __libc_lock_lock (__fork_block.lock);
+
+  /* Now that we have all the handlers allocate enqueue them.  */
+  if (new_prepare != NULL)
+    list_add_tail (&new_prepare->list, &__fork_block.prepare_list);
+  if (new_parent != NULL)
+    list_add_tail (&new_parent->list, &__fork_block.parent_list);
+  if (new_child != NULL)
+    list_add_tail (&new_child->list, &__fork_block.child_list);
+
+  /* Release the lock.  */
+  __libc_lock_unlock (__fork_block.lock);
+
+  return 0;
+}
+libc_hidden_def (__register_atfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
new file mode 100644
index 0000000000..bee7639f06
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
@@ -0,0 +1,72 @@
+/* bits/typesizes.h -- underlying types for *_t.  Linux/s390 version.
+   Copyright (C) 2003 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 _BITS_TYPES_H
+# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TYPESIZES_H
+#define	_BITS_TYPESIZES_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#define __DEV_T_TYPE		__UQUAD_TYPE
+#define __UID_T_TYPE		__U32_TYPE
+#define __GID_T_TYPE		__U32_TYPE
+#define __INO_T_TYPE		__ULONGWORD_TYPE
+#define __INO64_T_TYPE		__UQUAD_TYPE
+#define __MODE_T_TYPE		__U32_TYPE
+#define __NLINK_T_TYPE		__UWORD_TYPE
+#define __OFF_T_TYPE		__SLONGWORD_TYPE
+#define __OFF64_T_TYPE		__SQUAD_TYPE
+#define __PID_T_TYPE		__S32_TYPE
+#define __RLIM_T_TYPE		__ULONGWORD_TYPE
+#define __RLIM64_T_TYPE		__UQUAD_TYPE
+#define	__BLKCNT_T_TYPE		__SLONGWORD_TYPE
+#define	__BLKCNT64_T_TYPE	__SQUAD_TYPE
+#define	__FSBLKCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSBLKCNT64_T_TYPE	__UQUAD_TYPE
+#define	__FSFILCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSFILCNT64_T_TYPE	__UQUAD_TYPE
+#define	__ID_T_TYPE		__U32_TYPE
+#define __CLOCK_T_TYPE		__SLONGWORD_TYPE
+#define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __USECONDS_T_TYPE	__U32_TYPE
+#define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
+#define __DADDR_T_TYPE		__S32_TYPE
+#define __SWBLK_T_TYPE		__SLONGWORD_TYPE
+#define __KEY_T_TYPE		__S32_TYPE
+#define __CLOCKID_T_TYPE	__S32_TYPE
+#define __TIMER_T_TYPE		__S32_TYPE
+#define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE
+#define __FSID_T_TYPE		struct { int __val[2]; }
+#if defined __GNUC__ && __GNUC__ <= 2
+/* Compatibility with g++ 2.95.x.  */
+#define __SSIZE_T_TYPE		__SWORD_TYPE
+#else
+/* size_t is unsigned long int on s390 -m31.  */
+#define __SSIZE_T_TYPE		__SLONGWORD_TYPE
+#endif
+
+/* Number of descriptors that can fit in an `fd_set'.  */
+#define	__FD_SETSIZE		1024
+
+
+#endif /* bits/typesizes.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c
new file mode 100644
index 0000000000..b7d901c4c6
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c
@@ -0,0 +1,154 @@
+/* Special .init and .fini section support for S/390.
+   Copyright (C) 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 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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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. */
+
+__asm__ ("\
+\n\
+#include \"defs.h\"\n\
+\n\
+/*@HEADER_ENDS*/\n\
+\n\
+/*@TESTS_BEGIN*/\n\
+\n\
+/*@TESTS_END*/\n\
+\n\
+/*@_init_PROLOG_BEGINS*/\n\
+\n\
+	.section .init\n\
+#NO_APP\n\
+	.align 4\n\
+.globl _init\n\
+	.type	 _init,@function\n\
+_init:\n\
+#	leaf function           0\n\
+#	automatics              0\n\
+#	outgoing args           0\n\
+#	need frame pointer      0\n\
+#	call alloca             0\n\
+#	has varargs             0\n\
+#	incoming args (stack)   0\n\
+#	function length         36\n\
+	STM	6,15,24(15)\n\
+	BRAS	13,.LTN1_0\n\
+.LT1_0:\n\
+.LC13:\n\
+	.long	__pthread_initialize_minimal@PLT-.LT1_0\n\
+.LC14:\n\
+	.long	__gmon_start__@GOT\n\
+.LC15:\n\
+	.long	_GLOBAL_OFFSET_TABLE_-.LT1_0\n\
+.LTN1_0:\n\
+	LR	1,15\n\
+	AHI	15,-96\n\
+	ST	1,0(15)\n\
+	L	12,.LC15-.LT1_0(13)\n\
+	AR	12,13\n\
+	L     1,.LC13-.LT1_0(13)\n\
+	LA    1,0(1,13)\n\
+	BASR  14,1\n\
+	L     1,.LC14-.LT1_0(13)\n\
+	L     1,0(1,12)\n\
+	LTR   1,1\n\
+	JE    .L22\n\
+	BASR  14,1\n\
+.L22:\n\
+#APP\n\
+	.align 4,0x07\n\
+	END_INIT\n\
+\n\
+/*@_init_PROLOG_ENDS*/\n\
+\n\
+/*@_init_EPILOG_BEGINS*/\n\
+	.align 4\n\
+	.section .init\n\
+#NO_APP\n\
+	.align 4\n\
+	L	4,152(15)\n\
+	LM	6,15,120(15)\n\
+	BR	4\n\
+#APP\n\
+	END_INIT\n\
+\n\
+/*@_init_EPILOG_ENDS*/\n\
+\n\
+/*@_fini_PROLOG_BEGINS*/\n\
+	.section .fini\n\
+#NO_APP\n\
+	.align 4\n\
+.globl _fini\n\
+	.type	 _fini,@function\n\
+_fini:\n\
+#	leaf function           0\n\
+#	automatics              0\n\
+#	outgoing args           0\n\
+#	need frame pointer      0\n\
+#	call alloca             0\n\
+#	has varargs             0\n\
+#	incoming args (stack)   0\n\
+#	function length         30\n\
+	STM	6,15,24(15)\n\
+	BRAS	13,.LTN2_0\n\
+.LT2_0:\n\
+.LC17:\n\
+	.long	_GLOBAL_OFFSET_TABLE_-.LT2_0\n\
+.LTN2_0:\n\
+	LR	1,15\n\
+	AHI	15,-96\n\
+	ST	1,0(15)\n\
+	L	12,.LC17-.LT2_0(13)\n\
+	AR	12,13\n\
+#APP\n\
+	.align 4,0x07\n\
+	END_FINI\n\
+\n\
+/*@_fini_PROLOG_ENDS*/\n\
+\n\
+/*@_fini_EPILOG_BEGINS*/\n\
+	.align 4\n\
+	.section .fini\n\
+#NO_APP\n\
+	.align 4\n\
+	L	4,152(15)\n\
+	LM	6,15,120(15)\n\
+	BR	4\n\
+#APP\n\
+	END_FINI\n\
+\n\
+/*@_fini_EPILOG_ENDS*/\n\
+\n\
+/*@TRAILER_BEGINS*/\
+");
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
new file mode 100644
index 0000000000..06f7aed7dc
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+#  define PSEUDO_CANCEL(name, syscall_name, args)			      \
+L(pseudo_cancel):							      \
+	STM_##args							      \
+	stm	%r12,%r15,48(%r15);					      \
+	lr	%r14,%r15;						      \
+	ahi	%r15,-96;						      \
+	st	%r14,0(%r15);						      \
+	basr    %r13,0;							      \
+0:	l	%r1,1f-0b(%r13);					      \
+	bas	%r14,0(%r1,%r13);					      \
+	lr	%r0,%r2;						      \
+	LM_##args							      \
+	DO_CALL(syscall_name, args);					      \
+	l	%r1,2f-0b(%r13);					      \
+	lr	%r12,%r2;						      \
+	lr	%r2,%r0;						      \
+	bas	%r14,0(%r1,%r13);					      \
+	lr	%r2,%r12;						      \
+	lm	%r12,%r15,48+96(%r15);					      \
+	j	L(pseudo_check);					      \
+1:	.long	CENABLE-0b;						      \
+2:	.long	CDISABLE-0b;
+
+# else /* !libc.so && !libpthread.so */
+
+#  define PSEUDO_CANCEL(name, syscall_name, args)			      \
+L(pseudo_cancel):							      \
+	STM_##args							      \
+	stm	%r11,%r15,44(%r15);					      \
+	lr	%r14,%r15;						      \
+	ahi	%r15,-96;						      \
+	st	%r14,0(%r15);						      \
+	basr    %r13,0;							      \
+0:	l	%r12,3f-0b(%r13);					      \
+	l	%r1,1f-0b(%r13);					      \
+	la	%r12,0(%r12,%r13);					      \
+	bas	%r14,0(%r1,%r13);					      \
+	lr	%r0,%r2;						      \
+	LM_##args							      \
+	DO_CALL(syscall_name, args);					      \
+	l	%r1,2f-0b(%r13);					      \
+	lr	%r11,%r2;						      \
+	lr	%r2,%r0;						      \
+	bas	%r14,0(%r1,%r13);					      \
+	lr	%r2,%r11;						      \
+	lm	%r11,%r15,44+96(%r15);					      \
+	j	L(pseudo_check);					      \
+1:	.long	CENABLE@PLT-0b;						      \
+2:	.long	CDISABLE@PLT-0b;					      \
+3:	.long	_GLOBAL_OFFSET_TABLE_-0b;
+
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+PSEUDO_CANCEL(name, syscall_name, args)					      \
+ENTRY(name)								      \
+	SINGLE_THREAD_P(%r1)						      \
+	jne	L(pseudo_cancel);					      \
+	DO_CALL(syscall_name, args);					      \
+L(pseudo_check):							      \
+	lhi	%r4,-4095;						      \
+	clr	%r2,%r4;						      \
+	jnl	SYSCALL_ERROR_LABEL;					      \
+L(pseudo_end):
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	__pthread_enable_asynccancel
+#  define CDISABLE	__pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+#  define CENABLE	__libc_enable_asynccancel
+#  define CDISABLE	__libc_disable_asynccancel
+# else
+#  define CENABLE	__librt_enable_asynccancel
+#  define CDISABLE	__librt_disable_asynccancel
+# endif
+
+#define STM_0		/* Nothing */
+#define STM_1		st %r2,8(%r15);
+#define STM_2		stm %r2,%r3,8(%r15);
+#define STM_3		stm %r2,%r4,8(%r15);
+#define STM_4		stm %r2,%r5,8(%r15);
+#define STM_5		stm %r2,%r5,8(%r15);
+
+#define LM_0		/* Nothing */
+#define LM_1		l %r2,8+96(%r15);
+#define LM_2		lm %r2,%r3,8+96(%r15);
+#define LM_3		lm %r2,%r4,8+96(%r15);
+#define LM_4		lm %r2,%r5,8+96(%r15);
+#define LM_5		lm %r2,%r5,8+96(%r15);
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P(reg) \
+	ear	reg,%a0;						      \
+	icm	reg,15,MULTIPLE_THREADS_OFFSET(reg);
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S
new file mode 100644
index 0000000000..6dfeca86d4
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S
@@ -0,0 +1,69 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+   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-cancel.h>
+#define _ERRNO_H	1
+#include <bits/errno.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)
+	basr	%r1,0
+0:
+#ifdef SHARED
+	al	%r1,4f-0b(%r1)
+	l	%r1,0(%r1)
+	ltr	%r1,%r1
+#else
+	icm	%r1,15,4f-0b(%r1)
+#endif
+	jne	1f
+
+	/* Do vfork system call.  */
+	svc	SYS_ify (vfork)
+
+	/* Check for error.  */
+	lhi	%r4,-4095
+	clr	%r2,%r4
+	jnl	SYSCALL_ERROR_LABEL
+
+	/* Normal return.  */
+	br	%r14
+1:
+	basr	%r1,0
+2:
+	al	%r1,3f-2b(%r1)
+	br	%r1
+3:
+	.long	HIDDEN_JUMPTARGET(__fork)-2b
+4:
+#ifdef SHARED
+	.long	__libc_pthread_functions-0b
+#else
+	.weak	pthread_create
+	.long	pthread_create
+#endif
+PSEUDO_END(__vfork)
+
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c
new file mode 100644
index 0000000000..540443e6a3
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c
@@ -0,0 +1,137 @@
+/* Special .init and .fini section support for 64 bit S/390.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
+   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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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. */
+
+__asm__ ("\
+\n\
+#include \"defs.h\"\n\
+\n\
+/*@HEADER_ENDS*/\n\
+\n\
+/*@TESTS_BEGIN*/\n\
+\n\
+/*@TESTS_END*/\n\
+\n\
+/*@_init_PROLOG_BEGINS*/\n\
+\n\
+	.section .init\n\
+#NO_APP\n\
+	.align 4\n\
+.globl _init\n\
+	.type	 _init,@function\n\
+_init:\n\
+#	leaf function           0\n\
+#	automatics              0\n\
+#	outgoing args           0\n\
+#	need frame pointer      0\n\
+#	call alloca             0\n\
+#	has varargs             0\n\
+#	incoming args (stack)   0\n\
+#	function length         36\n\
+	STMG	6,15,48(15)\n\
+	LGR	1,15\n\
+	AGHI	15,-160\n\
+	STG	1,0(15)\n\
+	LARL	12,_GLOBAL_OFFSET_TABLE_\n\
+	BRASL	14,__pthread_initialize_minimal@PLT\n\
+	LARL	1,__gmon_start__@GOTENT\n\
+	LG	1,0(1)\n\
+	LTGR	1,1\n\
+	JE	.L22\n\
+	BASR	14,1\n\
+.L22:\n\
+#APP\n\
+	.align 4,0x07\n\
+	END_INIT\n\
+\n\
+/*@_init_PROLOG_ENDS*/\n\
+\n\
+/*@_init_EPILOG_BEGINS*/\n\
+	.align 4\n\
+	.section .init\n\
+#NO_APP\n\
+	.align 4\n\
+	LG	4,272(15)\n\
+	LMG	6,15,208(15)\n\
+	BR	4\n\
+#APP\n\
+	END_INIT\n\
+\n\
+/*@_init_EPILOG_ENDS*/\n\
+\n\
+/*@_fini_PROLOG_BEGINS*/\n\
+	.section .fini\n\
+#NO_APP\n\
+	.align 4\n\
+.globl _fini\n\
+	.type	 _fini,@function\n\
+_fini:\n\
+#	leaf function           0\n\
+#	automatics              0\n\
+#	outgoing args           0\n\
+#	need frame pointer      0\n\
+#	call alloca             0\n\
+#	has varargs             0\n\
+#	incoming args (stack)   0\n\
+#	function length         30\n\
+	STMG	6,15,48(15)\n\
+	LGR	1,15\n\
+	AGHI	15,-160\n\
+	STG	1,0(15)\n\
+	LARL	12,_GLOBAL_OFFSET_TABLE_\n\
+#APP\n\
+	.align 4,0x07\n\
+	END_FINI\n\
+\n\
+/*@_fini_PROLOG_ENDS*/\n\
+\n\
+/*@_fini_EPILOG_BEGINS*/\n\
+	.align 4\n\
+	.section .fini\n\
+#NO_APP\n\
+	.align 4\n\
+	LG	4,272(15)\n\
+	LMG	6,15,208(15)\n\
+	BR	4\n\
+#APP\n\
+	END_FINI\n\
+\n\
+/*@_fini_EPILOG_ENDS*/\n\
+\n\
+/*@TRAILER_BEGINS*/\n\
+	");
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c
new file mode 100644
index 0000000000..d57283ad23
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c
@@ -0,0 +1 @@
+#include "../../ia64/pt-sigsuspend.c"
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
new file mode 100644
index 0000000000..f71ef3f689
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+L(pseudo_cancel):							      \
+	STM_##args							      \
+	stmg	%r13,%r15,104(%r15);					      \
+	lgr	%r14,%r15;						      \
+	aghi	%r15,-160;						      \
+	stg	%r14,0(%r15);						      \
+	brasl	%r14,CENABLE;						      \
+	lgr	%r0,%r2;						      \
+	LM_##args							      \
+	DO_CALL(syscall_name, args);					      \
+	lgr	%r13,%r2;						      \
+	lgr	%r2,%r0;						      \
+	brasl	%r14,CDISABLE;						      \
+	lgr	%r2,%r13;						      \
+	lmg	%r13,%r15,104+160(%r15);				      \
+	j	L(pseudo_check);					      \
+ENTRY(name)								      \
+	SINGLE_THREAD_P							      \
+	jne	L(pseudo_cancel);					      \
+	DO_CALL(syscall_name, args);					      \
+L(pseudo_check):							      \
+	lghi	%r4,-4095;						      \
+	clgr	%r2,%r4;						      \
+	jgnl	SYSCALL_ERROR_LABEL;					      \
+L(pseudo_end):
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	__pthread_enable_asynccancel
+#  define CDISABLE	__pthread_disable_asynccancel
+#  define __local_multiple_threads	__pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE	__libc_enable_asynccancel
+#  define CDISABLE	__libc_disable_asynccancel
+#  define __local_multiple_threads	__libc_multiple_threads
+# else
+#  define CENABLE	__librt_enable_asynccancel@PLT
+#  define CDISABLE	__librt_disable_asynccancel@PLT
+# endif
+
+#define STM_0		/* Nothing */
+#define STM_1		stg %r2,16(%r15);
+#define STM_2		stmg %r2,%r3,16(%r15);
+#define STM_3		stmg %r2,%r4,16(%r15);
+#define STM_4		stmg %r2,%r5,16(%r15);
+#define STM_5		stmg %r2,%r5,16(%r15);
+
+#define LM_0		/* Nothing */
+#define LM_1		lg %r2,16+160(%r15);
+#define LM_2		lmg %r2,%r3,16+160(%r15);
+#define LM_3		lmg %r2,%r4,16+160(%r15);
+#define LM_4		lmg %r2,%r5,16+160(%r15);
+#define LM_5		lmg %r2,%r5,16+160(%r15);
+
+# if !defined NOT_IN_libc || defined IS_IN_libpthread
+#  ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P \
+  __builtin_expect (__local_multiple_threads == 0, 1)
+#  else
+#   define SINGLE_THREAD_P \
+	larl	%r1,__local_multiple_threads;				      \
+	icm	%r0,15,0(%r1);
+#  endif
+
+# else
+
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+#  else
+#   define SINGLE_THREAD_P \
+	ear	%r1,%a0;						      \
+	sllg	%r1,%r1,32;						      \
+	ear	%r1,%a1;						      \
+	icm	%r1,15,MULTIPLE_THREADS_OFFSET(%r1);
+#  endif
+
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
new file mode 100644
index 0000000000..199f0017ff
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+   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-cancel.h>
+#define _ERRNO_H	1
+#include <bits/errno.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)
+#ifdef SHARED
+	larl	%r1,__libc_pthread_functions
+	lg	%r1,0(%r1)
+#else
+	.weak	pthread_create
+	larl	%r1,pthread_create
+#endif
+	ltgr	%r1,%r1
+	jgne	HIDDEN_JUMPTARGET(__fork)
+
+	/* Do vfork system call.  */
+	svc	SYS_ify (vfork)
+
+	/* Check for error.  */
+	lghi	%r4,-4095
+	clgr	%r2,%r4
+	jgnl	SYSCALL_ERROR_LABEL
+
+	/* Normal return.  */
+	br	%r14
+PSEUDO_END(__vfork)
+
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c
new file mode 100644
index 0000000000..1cdb98f0f7
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c
@@ -0,0 +1,143 @@
+/* Special .init and .fini section support for SH. Linuxthread version.
+   Copyright (C) 2000, 2001, 2003 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.
+
+   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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. */
+
+__asm__ ("\n\
+\n\
+#include \"defs.h\"\n\
+\n\
+/*@HEADER_ENDS*/\n\
+\n\
+/*@TESTS_BEGIN*/\n\
+\n\
+/*@TESTS_END*/\n\
+\n\
+/*@_init_PROLOG_BEGINS*/\n\
+	.section .init\n\
+	.align 5\n\
+	.global	_init\n\
+	.type	_init,@function\n\
+_init:\n\
+	mov.l	r12,@-r15\n\
+	mov.l	r14,@-r15\n\
+	sts.l	pr,@-r15\n\
+	mova	.L22,r0\n\
+	mov.l	.L22,r12\n\
+	add	r0,r12\n\
+	mova	.L24,r0\n\
+	mov.l	.L24,r1\n\
+	add	r0,r1\n\
+	jsr	@r1\n\
+	 nop\n\
+	mova	.L23,r0\n\
+	mov.l	.L23,r1\n\
+	add	r0,r1\n\
+	jsr	@r1\n\
+	 mov	r15,r14\n\
+	bra	1f\n\
+	 nop\n\
+	.align 2\n\
+.L22:\n\
+	.long	_GLOBAL_OFFSET_TABLE_\n\
+.L23:\n\
+	.long	__gmon_start__@PLT\n\
+.L24:\n\
+	.long	__pthread_initialize_minimal@PLT\n\
+1:\n\
+	ALIGN\n\
+	END_INIT\n\
+\n\
+/*@_init_PROLOG_ENDS*/\n\
+\n\
+/*@_init_EPILOG_BEGINS*/\n\
+	.section .init\n\
+	mov	r14,r15\n\
+	lds.l	@r15+,pr\n\
+	mov.l	@r15+,r14\n\
+	rts	\n\
+	mov.l	@r15+,r12\n\
+	END_INIT\n\
+	.section .text\n\
+	.align 5\n\
+	.weak	__gmon_start__\n\
+	.type	__gmon_start__,@function\n\
+__gmon_start__:\n\
+	mov.l	r14,@-r15\n\
+	mov	r15,r14\n\
+	mov	r14,r15\n\
+	rts	\n\
+	mov.l	@r15+,r14\n\
+	\n\
+/*@_init_EPILOG_ENDS*/\n\
+\n\
+/*@_fini_PROLOG_BEGINS*/\n\
+	.section .fini\n\
+	.align 5\n\
+	.global	_fini\n\
+	.type	_fini,@function\n\
+_fini:\n\
+	mov.l	r12,@-r15\n\
+	mov.l	r14,@-r15\n\
+	sts.l	pr,@-r15\n\
+	mova	.L27,r0\n\
+	mov.l	.L27,r12\n\
+	add	r0,r12\n\
+	mov	r15,r14\n\
+	ALIGN\n\
+	END_FINI\n\
+	bra	1f\n\
+	 nop\n\
+	.align	2\n\
+.L27:\n\
+	.long	_GLOBAL_OFFSET_TABLE_\n\
+1:\n\
+/*@_fini_PROLOG_ENDS*/\n\
+\n\
+/*@_fini_EPILOG_BEGINS*/\n\
+	.section .fini\n\
+	mov	r14,r15\n\
+	lds.l	@r15+,pr\n\
+	mov.l	@r15+,r14\n\
+	rts	\n\
+	mov.l	@r15+,r12\n\
+\n\
+	END_FINI\n\
+	\n\
+/*@_fini_EPILOG_ENDS*/\n\
+\n\
+/*@TRAILER_BEGINS*/\n\
+");
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h b/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h
new file mode 100644
index 0000000000..2c0cbe99ac
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h
@@ -0,0 +1,24 @@
+/* Determine whether the host has multiple processors.  SH 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 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.  */
+
+static inline int
+is_smp_system (void)
+{
+  return 0;
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
new file mode 100644
index 0000000000..03c6fedbfe
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
@@ -0,0 +1,227 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#include <pt-machine.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# define _IMM12 #-12
+# define _IMM16 #-16
+# define _IMP16 #16
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+  .text; \
+  ENTRY (name); \
+    SINGLE_THREAD_P; \
+    bf .Lpseudo_cancel; \
+    DO_CALL (syscall_name, args); \
+    mov r0,r1; \
+    mov _IMM12,r2; \
+    shad r2,r1; \
+    not r1,r1; \
+    tst r1,r1; \
+    bt .Lsyscall_error; \
+    bra .Lpseudo_end; \
+     nop; \
+ .Lpseudo_cancel: \
+    sts.l pr,@-r15; \
+    add _IMM16,r15; \
+    SAVE_ARGS_##args; \
+    CENABLE; \
+    LOAD_ARGS_##args; \
+    add _IMP16,r15; \
+    lds.l @r15+,pr; \
+    DO_CALL(syscall_name, args); \
+    SYSCALL_INST_PAD; \
+    sts.l pr,@-r15; \
+    mov.l r0,@-r15; \
+    CDISABLE; \
+    mov.l @r15+,r0; \
+    lds.l @r15+,pr; \
+    mov r0,r1; \
+    mov _IMM12,r2; \
+    shad r2,r1; \
+    not r1,r1; \
+    tst r1,r1; \
+    bf .Lpseudo_end; \
+ .Lsyscall_error: \
+    SYSCALL_ERROR_HANDLER; \
+ .Lpseudo_end:
+
+# undef PSEUDO_END
+# define PSEUDO_END(sym) \
+  END (sym)
+
+# define SAVE_ARGS_0	/* Nothing.  */
+# define SAVE_ARGS_1	SAVE_ARGS_0; mov.l r4,@(0,r15)
+# define SAVE_ARGS_2	SAVE_ARGS_1; mov.l r5,@(4,r15)
+# define SAVE_ARGS_3	SAVE_ARGS_2; mov.l r6,@(8,r15)
+# define SAVE_ARGS_4	SAVE_ARGS_3; mov.l r7,@(12,r15)
+# define SAVE_ARGS_5	SAVE_ARGS_4
+# define SAVE_ARGS_6	SAVE_ARGS_5
+
+# define LOAD_ARGS_0	/* Nothing.  */
+# define LOAD_ARGS_1	LOAD_ARGS_0; mov.l @(0,r15),r4
+# define LOAD_ARGS_2	LOAD_ARGS_1; mov.l @(4,r15),r5
+# define LOAD_ARGS_3	LOAD_ARGS_2; mov.l @(8,r15),r6
+# define LOAD_ARGS_4	LOAD_ARGS_3; mov.l @(12,r15),r7
+# define LOAD_ARGS_5	LOAD_ARGS_4
+# define LOAD_ARGS_6	LOAD_ARGS_5
+
+# ifdef IS_IN_libpthread
+#  define __local_enable_asynccancel	__pthread_enable_asynccancel
+#  define __local_disable_asynccancel	__pthread_disable_asynccancel
+#  define __local_multiple_threads	__pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define __local_enable_asynccancel	__libc_enable_asynccancel
+#  define __local_disable_asynccancel	__libc_disable_asynccancel
+#  define __local_multiple_threads	__libc_multiple_threads
+# else
+#  define __local_enable_asynccancel	__librt_enable_asynccancel
+#  define __local_disable_asynccancel	__librt_disable_asynccancel
+#  define __local_multiple_threads	__librt_multiple_threads
+# endif
+
+# if defined IS_IN_librt && defined PIC
+#  define CENABLE \
+	mov.l r12,@-r15; \
+	mov.l 1f,r12; \
+	mova 1f,r0; \
+	add r0,r12; \
+	mov.l 2f,r0; \
+	bsrf r0; \
+	 nop; \
+     0: bra 3f; \
+	 mov r0,r2; \
+	.align 2; \
+     1: .long _GLOBAL_OFFSET_TABLE_; \
+     2: .long __local_enable_asynccancel@PLT - (0b-.); \
+     3: mov.l @r15+,r12
+
+#  define CDISABLE \
+	mov.l r12,@-r15; \
+	mov.l 1f,r12; \
+	mova 1f,r0; \
+	add r0,r12; \
+	mov.l 2f,r0; \
+	bsrf r0; \
+	 mov r2,r4; \
+     0: bra 3f; \
+	 nop; \
+	.align 2; \
+     1: .long _GLOBAL_OFFSET_TABLE_; \
+     2: .long __local_disable_asynccancel@PLT - (0b-.); \
+     3: mov.l @r15+,r12
+# else
+#  define CENABLE \
+	mov.l 1f,r0; \
+	bsrf r0; \
+	 nop; \
+     0: bra 2f; \
+	 mov r0,r2; \
+	.align 2; \
+     1: .long __local_enable_asynccancel - 0b; \
+     2:
+
+#  define CDISABLE \
+	mov.l 1f,r0; \
+	bsrf r0; \
+	 mov r2,r4; \
+     0: bra 2f; \
+	 nop; \
+	.align 2; \
+     1: .long __local_disable_asynccancel - 0b; \
+     2:
+# endif
+
+# ifndef __ASSEMBLER__
+#  if defined FLOATING_STACKS && USE___THREAD && defined PIC
+#   define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
+#  else
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+#  endif
+# else
+#  if !defined PIC
+#   define SINGLE_THREAD_P \
+	mov.l 1f,r0; \
+	mov.l @r0,r0; \
+	bra 2f; \
+	 tst r0,r0; \
+	.align 2; \
+     1: .long __local_multiple_threads; \
+     2:
+#  elif defined FLOATING_STACKS && USE___THREAD
+#   define SINGLE_THREAD_P \
+	stc gbr,r0; \
+	mov.w 0f,r1; \
+	sub r1,r0; \
+	mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \
+	bra 1f; \
+	 tst r0,r0; \
+     0: .word TLS_PRE_TCB_SIZE; \
+     1:
+
+#  else
+#   if !defined NOT_IN_libc || defined IS_IN_libpthread
+#    define SINGLE_THREAD_P \
+	mov r12,r2; \
+	mov.l 0f,r12; \
+	mova 0f,r0; \
+	add r0,r12; \
+	mov.l 1f,r0; \
+	mov.l @(r0,r12),r0; \
+	mov r2,r12; \
+	bra 2f; \
+	 tst r0,r0; \
+	.align 2; \
+     0: .long _GLOBAL_OFFSET_TABLE_; \
+     1: .long __local_multiple_threads@GOTOFF; \
+     2:
+#   else
+#    define SINGLE_THREAD_P \
+	mov r12,r2; \
+	mov.l 0f,r12; \
+	mova 0f,r0; \
+	add r0,r12; \
+	mov.l 1f,r0; \
+	mov.l @(r0,r12),r0; \
+	mov.l @r0,r0; \
+	mov r2,r12; \
+	bra 2f; \
+	 tst r0,r0; \
+	.align 2; \
+     0: .long _GLOBAL_OFFSET_TABLE_; \
+     1: .long __local_multiple_threads@GOT; \
+     2:
+#   endif
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S
new file mode 100644
index 0000000000..f230c01226
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S
@@ -0,0 +1,77 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.h>
+#define _ERRNO_H	1
+#include <bits/errno.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)
+#ifdef SHARED
+	mov.l	.Lgot, r1
+	mova	.Lgot, r0
+	add	r0, r1
+	mov.l	.Lpthread_func, r0
+	mov.l	@(r0,r1), r0
+#else
+	mov.l	.Lpthread_create, r0
+#endif
+	tst	r0, r0
+	bf	.Lhidden_fork
+
+	mov.w	.L1, r3
+	trapa	#0x10
+	mov     r0, r1
+	mov	#-12, r2
+	shad	r2, r1
+	not	r1, r1			// r1=0 means r0 = -1 to -4095
+	tst	r1, r1			// i.e. error in linux
+	bf	.Lpseudo_end
+	SYSCALL_ERROR_HANDLER
+.Lpseudo_end:
+	rts
+	 nop
+.L1:	.word	__NR_vfork
+	.align	2
+#ifdef SHARED
+.Lgot:
+	.long	_GLOBAL_OFFSET_TABLE_
+.Lpthread_func:
+	.long	__libc_pthread_functions@GOTOFF
+#else
+.Lpthread_create:
+	.weak	pthread_create
+	.long	pthread_create
+#endif
+
+.Lhidden_fork:	
+	mov.l	.L2, r1
+	braf	r1
+	 nop
+1:
+	.align 2
+.L2:	.long	HIDDEN_JUMPTARGET(__fork)-1b
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
new file mode 100644
index 0000000000..fdec09455a
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 1997, 1998, 2000, 2002, 2003 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 <errno.h>
+#include <signal.h>
+#define __need_NULL
+#include <stddef.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+#include <bits/libc-lock.h>
+
+extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded,
+				      const struct timespec *__unbounded, size_t);
+
+
+/* Return any pending signal or wait for one for the given time.  */
+static inline int
+do_sigwait (const sigset_t *set, int *sig)
+{
+  int ret;
+
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
+#ifdef INTERNAL_SYSCALL
+  INTERNAL_SYSCALL_DECL (err);
+  ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, CHECK_SIGSET (set),
+			  NULL, NULL, _NSIG / 8);
+  if (! INTERNAL_SYSCALL_ERROR_P (ret, err))
+    {
+      *sig = ret;
+      ret = 0;
+    }
+  else
+    ret = INTERNAL_SYSCALL_ERRNO (ret, err);
+#else
+  ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
+			NULL, NULL, _NSIG / 8);
+  if (ret != -1)
+    {
+      *sig = ret;
+      ret = 0;
+    }
+  else
+    ret = errno;
+#endif
+
+  return ret;
+}
+
+#ifndef SHARED
+weak_extern (__pthread_sigwait)
+#endif
+
+int
+__sigwait (set, sig)
+     const sigset_t *set;
+     int *sig;
+{
+#ifndef NOT_IN_libc
+  return __libc_maybe_call2 (pthread_sigwait, (set, sig),
+			     do_sigwait (set, sig));
+#else
+  return do_sigwait (set, sig);
+#endif
+}
+libc_hidden_def (__sigwait)
+weak_alias (__sigwait, sigwait)
+strong_alias (__sigwait, __libc_sigwait)
+
+/* Cancellation is handled in __pthread_sigwait.  */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/smp.h b/linuxthreads/sysdeps/unix/sysv/linux/smp.h
new file mode 100644
index 0000000000..81289294b4
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/smp.h
@@ -0,0 +1,48 @@
+/* Determine whether the host has multiple processors.  Linux version.
+   Copyright (C) 1996, 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 <sys/sysctl.h>
+
+/* Test whether the machine has more than one processor.  This is not the
+   best test but good enough.  More complicated tests would require `malloc'
+   which is not available at that time.  */
+static inline int
+is_smp_system (void)
+{
+  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION };
+  char buf[512];
+  size_t reslen = sizeof (buf);
+
+  /* Try reading the number using `sysctl' first.  */
+  if (__sysctl ((int *) sysctl_args,
+		sizeof (sysctl_args) / sizeof (sysctl_args[0]),
+		buf, &reslen, NULL, 0) < 0)
+    {
+      /* This was not successful.  Now try reading the /proc filesystem.  */
+      int fd = __open ("/proc/sys/kernel/version", O_RDONLY);
+      if (__builtin_expect (fd, 0) == -1
+	  || (reslen = __read (fd, buf, sizeof (buf))) <= 0)
+	/* This also didn't work.  We give up and say it's a UP machine.  */
+	buf[0] = '\0';
+
+      __close (fd);
+    }
+
+  return strstr (buf, "SMP") != NULL;
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions b/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions
new file mode 100644
index 0000000000..d102772482
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions
@@ -0,0 +1,6 @@
+libpthread {
+  GLIBC_2.3.3 {
+    # Changed PTHREAD_STACK_MIN.
+    pthread_attr_setstack; pthread_attr_setstacksize;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c
new file mode 100644
index 0000000000..0d6da82919
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c
@@ -0,0 +1,33 @@
+#include <shlib-compat.h>
+
+#define aio_cancel64 XXX
+#include <aio.h>
+#undef aio_cancel64
+#include <errno.h>
+
+extern __typeof (aio_cancel) __new_aio_cancel;
+extern __typeof (aio_cancel) __old_aio_cancel;
+
+#define aio_cancel	__new_aio_cancel
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__new_aio_cancel, __new_aio_cancel64);
+versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3);
+versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3);
+
+#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3)
+
+#undef ECANCELED
+#define aio_cancel	__old_aio_cancel
+#define ECANCELED	125
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__old_aio_cancel, __old_aio_cancel64);
+compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1);
+compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1);
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h
new file mode 100644
index 0000000000..27ffa668f4
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h
@@ -0,0 +1,92 @@
+/* Minimum guaranteed maximum values for system limits.  Linux/SPARC version.
+   Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+   and defines LINK_MAX although filesystems have different maxima.  A
+   similar thing is true for OPEN_MAX: the limit can be changed at
+   runtime and therefore the macro must not be defined.  Remove this
+   after including the header if necessary.  */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information.  */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN?  */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX?  */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX?  */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process.  */
+#define _POSIX_THREAD_KEYS_MAX	128
+/* This is the value this implementation supports.  */
+#define PTHREAD_KEYS_MAX	1024
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process.  */
+#define _POSIX_THREAD_THREADS_MAX	64
+/* This is the value this implementation supports.  */
+#define PTHREAD_THREADS_MAX	16384
+
+/* 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	24576
+
+/* Maximum number of POSIX timers available.  */
+#define TIMER_MAX	256
+
+/* Maximum number of timer expiration overruns.  */
+#define DELAYTIMER_MAX	2147483647
+
+/* Maximum tty name length.  */
+#define TTY_NAME_MAX		32
+
+/* Maximum login name length.  This is arbitrary.  */
+#define LOGIN_NAME_MAX		256
+
+/* Maximum host name length.  */
+#define HOST_NAME_MAX		64
+
+/* Maximum message queue priority level.  */
+#define MQ_PRIO_MAX		32768
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
new file mode 100644
index 0000000000..7e4253789c
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
@@ -0,0 +1,66 @@
+/* bits/typesizes.h -- underlying types for *_t.  Linux/SPARC version.
+   Copyright (C) 2002, 2003 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 _BITS_TYPES_H
+# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TYPESIZES_H
+#define	_BITS_TYPESIZES_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#define __DEV_T_TYPE		__UQUAD_TYPE
+#define __UID_T_TYPE		__U32_TYPE
+#define __GID_T_TYPE		__U32_TYPE
+#define __INO_T_TYPE		__ULONGWORD_TYPE
+#define __INO64_T_TYPE		__UQUAD_TYPE
+#define __MODE_T_TYPE		__U32_TYPE
+#define __NLINK_T_TYPE		__U32_TYPE
+#define __OFF_T_TYPE		__SLONGWORD_TYPE
+#define __OFF64_T_TYPE		__SQUAD_TYPE
+#define __PID_T_TYPE		__S32_TYPE
+#define __RLIM_T_TYPE		__ULONGWORD_TYPE
+#define __RLIM64_T_TYPE		__UQUAD_TYPE
+#define	__BLKCNT_T_TYPE		__SLONGWORD_TYPE
+#define	__BLKCNT64_T_TYPE	__SQUAD_TYPE
+#define	__FSBLKCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSBLKCNT64_T_TYPE	__UQUAD_TYPE
+#define	__FSFILCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSFILCNT64_T_TYPE	__UQUAD_TYPE
+#define	__ID_T_TYPE		__U32_TYPE
+#define __CLOCK_T_TYPE		__SLONGWORD_TYPE
+#define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __USECONDS_T_TYPE	__U32_TYPE
+#define __SUSECONDS_T_TYPE	__S32_TYPE
+#define __DADDR_T_TYPE		__S32_TYPE
+#define __SWBLK_T_TYPE		__SLONGWORD_TYPE
+#define __KEY_T_TYPE		__S32_TYPE
+#define __CLOCKID_T_TYPE	__S32_TYPE
+#define __TIMER_T_TYPE		__S32_TYPE
+#define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE
+#define __FSID_T_TYPE		struct { int __val[2]; }
+#define __SSIZE_T_TYPE		__SWORD_TYPE
+
+/* Number of descriptors that can fit in an `fd_set'.  */
+#define	__FD_SETSIZE		1024
+
+
+#endif /* bits/typesizes.h */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h
new file mode 100644
index 0000000000..793cb1d5f9
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 ARCH_FORK() \
+({									\
+  register long __o0 __asm__ ("o0");					\
+  register long __o1 __asm__ ("o1");					\
+  register long __g1 __asm__ ("g1") = __NR_fork;			\
+  __asm __volatile (__SYSCALL_STRING					\
+		    : "=r" (__g1), "=r" (__o0), "=r" (__o1)		\
+		    : "0" (__g1)					\
+		    : __SYSCALL_CLOBBERS);				\
+  __o0 == -1 ? __o0 : (__o0 & (__o1 - 1));				\
+})
+
+#include_next <fork.h>
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
new file mode 100644
index 0000000000..dd3f52a989
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;			      \
+	cmp %g1, 0;							      \
+	bne 1f;								      \
+	 mov SYS_ify(syscall_name), %g1;				      \
+	ta 0x10;							      \
+	bcs __syscall_error_handler;					      \
+	 nop;								      \
+	.subsection 2;							      \
+1:	save %sp, -96, %sp;						      \
+	CENABLE;							      \
+	 nop;								      \
+	mov %o0, %l0;							      \
+	COPY_ARGS_##args						      \
+	mov SYS_ify(syscall_name), %g1;					      \
+	ta 0x10;							      \
+	bcs __syscall_error_handler2;					      \
+	 mov %o0, %l1;							      \
+	CDISABLE;							      \
+	 mov %l0, %o0;							      \
+	jmpl %i7 + 8, %g0;						      \
+	 restore %g0, %l1, %o0;						      \
+	.previous;							      \
+	SYSCALL_ERROR_HANDLER						      \
+	SYSCALL_ERROR_HANDLER2
+
+#define SYSCALL_ERROR_HANDLER2						      \
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
+	.global __errno_location;					      \
+        .type   __errno_location,@function;				      \
+	CDISABLE;							      \
+	 mov	%l0, %o0;						      \
+	call	__errno_location;					      \
+	 nop;								      \
+	st	%l1, [%o0];						      \
+	jmpl	%i7 + 8, %g0;						      \
+	 restore %g0, -1, %o0;						      \
+	.previous;
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel
+#  define CDISABLE	call __pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+#  define CENABLE	call __libc_enable_asynccancel
+#  define CDISABLE	call __libc_disable_asynccancel
+# else
+#  define CENABLE	call __librt_enable_asynccancel
+#  define CDISABLE	call __librt_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
new file mode 100644
index 0000000000..132da67a14
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S
@@ -0,0 +1,65 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.h>
+
+	.text
+#ifdef SHARED
+.LLGETPC0:
+	retl
+	 add	%o7, %o0, %o0
+#endif
+ENTRY(__vfork)
+#ifdef SHARED
+	mov	%o7, %o1
+	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %o0
+	call	.LLGETPC0
+	 add	%o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0
+	sethi	%hi(__libc_pthread_functions), %o2
+	mov	%o1, %o7
+	or	%o2, %lo(__libc_pthread_functions), %o2
+	ld	[%o0 + %o2], %o2
+	ld	[%o2], %o2
+	cmp	%o2, 0
+#else
+	.weak	pthread_create
+	sethi	%hi(pthread_create), %o0
+	orcc	%o0, %lo(pthread_create), %o0
+#endif
+#if defined SHARED && !defined BROKEN_SPARC_WDISP22
+	bne	HIDDEN_JUMPTARGET(__fork)
+#else
+	bne	1f
+#endif
+	 mov	__NR_vfork, %g1
+	ta	0x10
+	bcs	__syscall_error_handler
+	 nop
+	sub	%o1, 1, %o1
+	retl
+	 and	%o0, %o1, %o0
+#if !defined SHARED || defined BROKEN_SPARC_WDISP22
+1:	mov	%o7, %g1
+	call	HIDDEN_JUMPTARGET(__fork)
+	 mov	%g1, %o7
+#endif
+	SYSCALL_ERROR_HANDLER
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
new file mode 100644
index 0000000000..90203051ae
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
@@ -0,0 +1,5 @@
+# glibc makefile fragment for linuxthreads on sparc/sparc64.
+
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sigprocmask
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c
new file mode 100644
index 0000000000..d57283ad23
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c
@@ -0,0 +1 @@
+#include "../../ia64/pt-sigsuspend.c"
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
new file mode 100644
index 0000000000..80834292e5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <tls.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;			      \
+	brnz,pn %g1, 1f;						      \
+	 mov SYS_ify(syscall_name), %g1;				      \
+	ta 0x6d;							      \
+	bcs,pn %xcc, __syscall_error_handler;				      \
+	 nop;								      \
+	.subsection 2;							      \
+1:	save %sp, -192, %sp;						      \
+	CENABLE;							      \
+	 nop;								      \
+	mov %o0, %l0;							      \
+	COPY_ARGS_##args						      \
+	mov SYS_ify(syscall_name), %g1;					      \
+	ta 0x6d;							      \
+	bcs,pn %xcc, __syscall_error_handler2;				      \
+	 mov %o0, %l1;							      \
+	CDISABLE;							      \
+	 mov %l0, %o0;							      \
+	jmpl %i7 + 8, %g0;						      \
+	 restore %g0, %l1, %o0;						      \
+	.previous;							      \
+	SYSCALL_ERROR_HANDLER						      \
+	SYSCALL_ERROR_HANDLER2
+
+#define SYSCALL_ERROR_HANDLER2						      \
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
+	.global __errno_location;					      \
+        .type   __errno_location,@function;				      \
+	CDISABLE;							      \
+	 mov	%l0, %o0;						      \
+	call	__errno_location;					      \
+	 nop;								      \
+	st	%l1, [%o0];						      \
+	jmpl	%i7 + 8, %g0;						      \
+	 restore %g0, -1, %o0;						      \
+	.previous;
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel
+#  define CDISABLE	call __pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+#  define CENABLE	call __libc_enable_asynccancel
+#  define CDISABLE	call __libc_disable_asynccancel
+# else
+#  define CENABLE	call __librt_enable_asynccancel
+#  define CDISABLE	call __librt_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
new file mode 100644
index 0000000000..8a6d2771e8
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S
@@ -0,0 +1,64 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.h>
+
+#ifdef SHARED
+.LLGETPC0:
+	retl
+	 add	%o7, %o0, %o0
+#endif
+ENTRY(__vfork)
+#ifdef SHARED
+	mov	%o7, %o1
+	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %o0
+	call	.LLGETPC0
+	 add	%o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0
+	sethi	%hi(__libc_pthread_functions), %o2
+	mov	%o1, %o7
+	or	%o2, %lo(__libc_pthread_functions), %o2
+	ldx	[%o0 + %o2], %o2
+	ldx	[%o2], %o0
+#else
+	.weak	pthread_create
+	sethi	%hi(pthread_create), %o0
+	or	%o0, %lo(pthread_create), %o0
+#endif
+#if defined SHARED && !defined BROKEN_SPARC_WDISP22
+	cmp	%o0, 0
+	bne	HIDDEN_JUMPTARGET(__fork)
+#else
+	brnz,pn	%o0, 1f
+#endif
+	 mov	__NR_vfork, %g1
+	ta	0x6d
+	bcs,pn	%xcc, __syscall_error_handler
+	 nop
+	sub	%o1, 1, %o1
+	retl
+	 and	%o0, %o1, %o0
+#if !defined SHARED || defined BROKEN_SPARC_WDISP22
+1:	mov	%o7, %g1
+	call	HIDDEN_JUMPTARGET(__fork)
+	 mov	%g1, %o7
+#endif
+	SYSCALL_ERROR_HANDLER
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c
new file mode 100644
index 0000000000..dad273fdf5
--- /dev/null
+++ b/linuxthreads/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.  */
+  __libc_lock_lock (__fork_block.lock);
+
+  list_t *runp;
+  list_t *prevp;
+
+  list_for_each_prev_safe (runp, prevp, &__fork_block.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_block.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_block.child_list)
+    if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+      list_del (runp);
+
+  /* Release the lock.  */
+  __libc_lock_unlock (__fork_block.lock);
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile
new file mode 100644
index 0000000000..b5e5d5d480
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile
@@ -0,0 +1,4 @@
+ifeq ($(subdir),linuxthreads)
+CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions \
+		       -fno-asynchronous-unwind-tables $(fno-unit-at-a-time)
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c
new file mode 100644
index 0000000000..3a0c2afc0f
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c
@@ -0,0 +1 @@
+#include "../ia64/pt-sigsuspend.c"
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
new file mode 100644
index 0000000000..742dbeb0de
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <tls.h>
+#include <pt-machine.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+    SINGLE_THREAD_P;							      \
+    jne L(pseudo_cancel);						      \
+    DO_CALL (syscall_name, args);					      \
+    cmpq $-4095, %rax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+    ret;								      \
+  L(pseudo_cancel):							      \
+    /* Save registers that might get destroyed.  */			      \
+    SAVESTK_##args							      \
+    PUSHARGS_##args							      \
+    CENABLE								      \
+    /* Restore registers.  */						      \
+    POPARGS_##args							      \
+    /* The return value from CENABLE is argument for CDISABLE.  */	      \
+    movq %rax, (%rsp);							      \
+    movq $SYS_ify (syscall_name), %rax;					      \
+    syscall;								      \
+    movq (%rsp), %rdi;							      \
+    /* Save %rax since it's the error code from the syscall.  */	      \
+    movq %rax, 8(%rsp);							      \
+    CDISABLE								      \
+    movq 8(%rsp), %rax;							      \
+    RESTSTK_##args							      \
+    cmpq $-4095, %rax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+  L(pseudo_end):
+
+# define PUSHARGS_0	/* Nothing.  */
+# define PUSHARGS_1	PUSHARGS_0 movq %rdi, 8(%rsp);
+# define PUSHARGS_2	PUSHARGS_1 movq %rsi, 16(%rsp);
+# define PUSHARGS_3	PUSHARGS_2 movq %rdx, 24(%rsp);
+# define PUSHARGS_4	PUSHARGS_3 movq %rcx, 32(%rsp);
+# define PUSHARGS_5	PUSHARGS_4 movq %r8, 40(%rsp);
+# define PUSHARGS_6	PUSHARGS_5 movq %r9, 48(%rsp);
+
+# define POPARGS_0	/* Nothing.  */
+# define POPARGS_1	POPARGS_0 movq 8(%rsp), %rdi;
+# define POPARGS_2	POPARGS_1 movq 16(%rsp), %rsi;
+# define POPARGS_3	POPARGS_2 movq 24(%rsp), %rdx;
+# define POPARGS_4	POPARGS_3 movq 32(%rsp), %r10;
+# define POPARGS_5	POPARGS_4 movq 40(%rsp), %r8;
+# define POPARGS_6	POPARGS_5 movq 48(%rsp), %r9;
+
+/* We always have to align the stack before calling a function.  */
+# define SAVESTK_0	subq $24, %rsp;cfi_adjust_cfa_offset(24);
+# define SAVESTK_1	SAVESTK_0
+# define SAVESTK_2	SAVESTK_1
+# define SAVESTK_3	subq $40, %rsp;cfi_adjust_cfa_offset(40);
+# define SAVESTK_4	SAVESTK_3
+# define SAVESTK_5	subq $56, %rsp;cfi_adjust_cfa_offset(56);
+# define SAVESTK_6	SAVESTK_5
+
+# define RESTSTK_0	addq $24,%rsp;cfi_adjust_cfa_offset(-24);
+# define RESTSTK_1	RESTSTK_0
+# define RESTSTK_2	RESTSTK_1
+# define RESTSTK_3	addq $40, %rsp;cfi_adjust_cfa_offset(-40);
+# define RESTSTK_4	RESTSTK_3
+# define RESTSTK_5	addq $56, %rsp;cfi_adjust_cfa_offset(-56);
+# define RESTSTK_6	RESTSTK_5
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel;
+#  define CDISABLE	call __pthread_disable_asynccancel;
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE	call __libc_enable_asynccancel;
+#  define CDISABLE	call __libc_disable_asynccancel;
+#  define __local_multiple_threads __libc_multiple_threads
+# else
+#  define CENABLE	call __librt_enable_asynccancel@plt;
+#  define CDISABLE	call __librt_disable_asynccancel@plt;
+# endif
+
+# if defined IS_IN_libpthread || !defined NOT_IN_libc
+#  ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P \
+  __builtin_expect (__local_multiple_threads == 0, 1)
+#  else
+#   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
+#  endif
+
+# else
+
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   p_header.data.multiple_threads) == 0, 1)
+#  else
+#   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET
+#  endif
+
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S
new file mode 100644
index 0000000000..25d1d3f96a
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S
@@ -0,0 +1,62 @@
+/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep-cancel.h>
+#define _ERRNO_H	1
+#include <bits/errno.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)
+
+#ifdef SHARED
+	cmpq	$0, __libc_pthread_functions(%rip)
+#else
+	.weak	pthread_create
+	movq	$pthread_create, %rax
+	testq	%rax, %rax
+#endif
+	jne	HIDDEN_JUMPTARGET (__fork)
+
+	/* Pop the return PC value into RDI.  We need a register that
+	   is preserved by the syscall and that we're allowed to destroy. */
+	popq	%rdi
+	cfi_adjust_cfa_offset(-8)
+
+	/* Stuff the syscall number in RAX and enter into the kernel.  */
+	movl	$SYS_ify (vfork), %eax
+	syscall
+
+	/* Push back the return PC.  */
+	pushq	%rdi
+	cfi_adjust_cfa_offset(8)
+
+	cmpl	$-4095, %eax
+	jae SYSCALL_ERROR_LABEL		/* Branch forward if it failed.  */
+
+	/* Normal return.  */
+.Lpseudo_end:
+	ret
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/linuxthreads/sysdeps/x86_64/Makefile b/linuxthreads/sysdeps/x86_64/Makefile
new file mode 100644
index 0000000000..81bddf688c
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/linuxthreads/sysdeps/x86_64/Versions b/linuxthreads/sysdeps/x86_64/Versions
new file mode 100644
index 0000000000..32da57080d
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/Versions
@@ -0,0 +1,5 @@
+libpthread {
+  GLIBC_PRIVATE {
+    __pthread_clock_gettime; __pthread_clock_settime;
+  }
+}
diff --git a/linuxthreads/sysdeps/x86_64/pspinlock.c b/linuxthreads/sysdeps/x86_64/pspinlock.c
new file mode 100644
index 0000000000..e1b2a66841
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/pspinlock.c
@@ -0,0 +1,97 @@
+/* POSIX spinlock implementation.  x86-64 version.
+   Copyright (C) 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 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 <pthread.h>
+#include "internals.h"
+
+/* This implementation is similar to the one used in the Linux kernel.
+   But the kernel is byte instructions for the memory access.  This is
+   faster but unusable here.  The problem is that only 128
+   threads/processes could use the spinlock at the same time.  If (by
+   a design error in the program) a thread/process would hold the
+   spinlock for a time long enough to accumulate 128 waiting
+   processes, the next one will find a positive value in the spinlock
+   and assume it is unlocked.  We cannot accept that.  */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("\n"
+     "1:\n\t"
+     "lock; decl %0\n\t"
+     "js 2f\n\t"
+     ".section .text.spinlock,\"ax\"\n"
+     "2:\n\t"
+     "cmpl $0,%0\n\t"
+     "rep; nop\n\t"
+     "jle 2b\n\t"
+     "jmp 1b\n\t"
+     ".previous"
+     : "=m" (*lock));
+  return 0;
+}
+weak_alias (__pthread_spin_lock, pthread_spin_lock)
+
+
+int
+__pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  int oldval;
+
+  asm volatile
+    ("xchgl %0,%1"
+     : "=r" (oldval), "=m" (*lock)
+     : "0" (0));
+  return oldval > 0 ? 0 : EBUSY;
+}
+weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
+
+
+int
+__pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  asm volatile
+    ("movl $1,%0"
+     : "=m" (*lock));
+  return 0;
+}
+weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
+
+
+int
+__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  /* We can ignore the `pshared' parameter.  Since we are busy-waiting
+     all processes which can access the memory location `lock' points
+     to can use the spinlock.  */
+  *lock = 1;
+  return 0;
+}
+weak_alias (__pthread_spin_init, pthread_spin_init)
+
+
+int
+__pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  /* Nothing to do.  */
+  return 0;
+}
+weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
diff --git a/linuxthreads/sysdeps/x86_64/pt-machine.h b/linuxthreads/sysdeps/x86_64/pt-machine.h
new file mode 100644
index 0000000000..df187a7c03
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/pt-machine.h
@@ -0,0 +1,225 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   x86-64 version.
+   Copyright (C) 2001, 2002, 2003, 2004 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 _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef __ASSEMBLER__
+# include <stddef.h>	/* For offsetof.  */
+# include <stdlib.h>	/* For abort().  */
+# include <asm/prctl.h>
+
+
+# ifndef PT_EI
+#  define PT_EI extern inline __attribute__ ((always_inline))
+# endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+# define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"xchgl %k0, %1"
+	: "=r"(ret), "=m"(*spinlock)
+	: "0"(1), "m"(*spinlock)
+	: "memory");
+
+  return ret;
+}
+
+
+/* Compare-and-swap for semaphores.  */
+# define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+
+/* 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 \
+({									      \
+  register pthread_descr __self;					      \
+  __asm__ ("movq %%fs:%c1,%0" : "=r" (__self)				      \
+	   : "i" (offsetof (struct _pthread_descr_struct,		      \
+			    p_header.data.self)));			      \
+  __self;								      \
+})
+
+/* Prototype for the system call.  */
+extern int __arch_prctl (int __code, unsigned long __addr);
+
+/* Initialize the thread-unique value.  */
+# define INIT_THREAD_SELF(descr, nr) \
+{									      \
+  if (__arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0)		      \
+    abort ();								      \
+}
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) \
+({									      \
+  __typeof__ (descr->member) __value;					      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %%fs:%P2,%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%fs:%P2,%k0"				      \
+			  : "=r" (__value)				      \
+			  : "0" (0),					      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movq %%fs:%P1,%0"				      \
+			    : "=r" (__value)				      \
+			    : "i" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+  __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__ __volatile__ ("movb %%fs:(%2),%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%fs:(%2),%k0"				      \
+			  : "=r" (__value)				      \
+			  : "0" (0),					      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movq %%fs:(%1),%0"				      \
+			    : "=r" (__value)				      \
+			    : "r" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+  __value;								      \
+})
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%fs:%P1" :				      \
+			  : "q" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %k0,%%fs:%P1" :				      \
+			  : "r" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movq %0,%%fs:%P1" :			      \
+			    : "r" (__value),				      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+})
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM_NC(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%fs:(%1)" :				      \
+			  : "q" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %k0,%%fs:(%1)" :			      \
+			  : "r" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movq %0,%%fs:(%1)"	:			      \
+			    : "r" (__value),				      \
+			      "r" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+})
+
+#endif /* !__ASSEMBLER__ */
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS	1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE	32*1024*1024
+
+/* The ia32e really want some help to prevent overheating.  */
+#define BUSY_WAIT_NOP	__asm__ ("rep; nop")
+
+#endif /* pt-machine.h */
diff --git a/linuxthreads/sysdeps/x86_64/tcb-offsets.sym b/linuxthreads/sysdeps/x86_64/tcb-offsets.sym
new file mode 100644
index 0000000000..aee6be2570
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/tcb-offsets.sym
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads)
diff --git a/linuxthreads/sysdeps/x86_64/tls.h b/linuxthreads/sysdeps/x86_64/tls.h
new file mode 100644
index 0000000000..63feebdb2c
--- /dev/null
+++ b/linuxthreads/sysdeps/x86_64/tls.h
@@ -0,0 +1,129 @@
+/* Definitions for thread-local data handling.  linuxthreads/x86-64 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.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.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif
+
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/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_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* 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_descr_struct *__descr;				      \
+     THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+/* 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(descr, secondcall)					      \
+  ({									      \
+    void *_descr = (descr);						      \
+    tcbhead_t *head = _descr;						      \
+    long int _result;							      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    asm volatile ("syscall"						      \
+		  : "=a" (_result)					      \
+		  : "0" ((unsigned long int) __NR_arch_prctl),		      \
+		    "D" ((unsigned long int) ARCH_SET_FS),		      \
+		    "S" (_descr)					      \
+		  : "memory", "cc", "r11", "cx");			      \
+									      \
+    _result ? "cannot set %fs base address for thread-local storage" : 0;     \
+  })
+
+/* Indicate that dynamic linker shouldn't try to initialize TLS even
+   when no PT_TLS segments are found in the program and libraries
+   it is linked against.  */
+#  define TLS_INIT_TP_EXPENSIVE 1
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+
+# endif	/* HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff --git a/linuxthreads/tst-_res1.c b/linuxthreads/tst-_res1.c
new file mode 100644
index 0000000000..651e3cc40d
--- /dev/null
+++ b/linuxthreads/tst-_res1.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Test whether _res in glibc 2.1.x and earlier (before __res_state()
+   was introduced) works.  Portable programs should never do the
+   dirty things below.  */
+
+#include <pthread.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void *tf (void *resp)
+{
+  if (resp == &_res || resp == __res_state ())
+    abort ();
+  _res.retry = 24;
+  return NULL;
+}
+
+void do_test (struct __res_state *resp)
+{
+  if (resp != &_res || resp != __res_state ())
+    abort ();
+  if (_res.retry != 12)
+    abort ();
+}
+
+int main (void)
+{
+#undef _res
+  extern struct __res_state _res;
+  pthread_t th;
+
+  _res.retry = 12;
+  if (pthread_create (&th, NULL, tf, &_res) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  do_test (&_res);
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  do_test (&_res);
+
+  exit (0);
+}
diff --git a/linuxthreads/tst-_res1mod1.c b/linuxthreads/tst-_res1mod1.c
new file mode 100644
index 0000000000..73b190e6ba
--- /dev/null
+++ b/linuxthreads/tst-_res1mod1.c
@@ -0,0 +1,23 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <resolv.h>
+#undef _res
+
+struct __res_state _res;
diff --git a/linuxthreads/tst-_res1mod2.c b/linuxthreads/tst-_res1mod2.c
new file mode 100644
index 0000000000..d2a3509c6d
--- /dev/null
+++ b/linuxthreads/tst-_res1mod2.c
@@ -0,0 +1 @@
+/* Nothing.  */
diff --git a/linuxthreads/tst-align.c b/linuxthreads/tst-align.c
new file mode 100644
index 0000000000..2de9d7a107
--- /dev/null
+++ b/linuxthreads/tst-align.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static void *
+tf (void *arg)
+{
+  bool ok = true;
+
+  puts ("in thread");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? NULL : (void *) -1l;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != NULL)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-attr1.c b/linuxthreads/tst-attr1.c
new file mode 100644
index 0000000000..7960cf930a
--- /dev/null
+++ b/linuxthreads/tst-attr1.c
@@ -0,0 +1,358 @@
+/* pthread_getattr_np test.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stackinfo.h>
+
+static void *
+tf (void *arg)
+{
+  pthread_attr_t a, *ap, a2;
+  int err;
+  void *result = NULL;
+
+  if (arg == NULL)
+    {
+      ap = &a2;
+      err = pthread_attr_init (ap);
+      if (err)
+        {
+          error (0, err, "pthread_attr_init failed");
+          return tf;
+        }
+    }
+  else
+    ap = (pthread_attr_t *) arg;
+
+  err = pthread_getattr_np (pthread_self (), &a);
+  if (err)
+    {
+      error (0, err, "pthread_getattr_np failed");
+      result = tf;
+    }
+
+  int detachstate1, detachstate2;
+  err = pthread_attr_getdetachstate (&a, &detachstate1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getdetachstate failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getdetachstate (ap, &detachstate2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getdetachstate failed");
+	  result = tf;
+	}
+      else if (detachstate1 != detachstate2)
+	{
+	  error (0, 0, "detachstate differs %d != %d",
+		 detachstate1, detachstate2);
+	  result = tf;
+	}
+    }
+
+  void *stackaddr;
+  size_t stacksize;
+  err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getstack failed");
+      result = tf;
+    }
+  else if ((void *) &a < stackaddr
+	   || (void *) &a >= stackaddr + stacksize)
+    {
+      error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack");
+      result = tf;
+    }
+  else
+    printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize,
+	    stacksize);
+
+  size_t guardsize1, guardsize2;
+  err = pthread_attr_getguardsize (&a, &guardsize1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getguardsize failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getguardsize (ap, &guardsize2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getguardsize failed");
+	  result = tf;
+	}
+      else if (guardsize1 != guardsize2)
+	{
+	  error (0, 0, "guardsize differs %zd != %zd",
+		 guardsize1, guardsize2);
+	  result = tf;
+	}
+      else
+	printf ("thread guardsize %zd\n", guardsize1);
+    }
+
+  int scope1, scope2;
+  err = pthread_attr_getscope (&a, &scope1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getscope failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getscope (ap, &scope2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getscope failed");
+	  result = tf;
+	}
+      else if (scope1 != scope2)
+	{
+	  error (0, 0, "scope differs %d != %d",
+		 scope1, scope2);
+	  result = tf;
+	}
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = tf;
+    }
+
+  if (ap == &a2)
+    {
+      err = pthread_attr_destroy (ap);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_destroy failed");
+	  result = tf;
+	}
+    }
+
+  return result;
+}
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  pthread_attr_t a;
+
+  int err = pthread_attr_init (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_init failed");
+      result = 1;
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  err = pthread_getattr_np (pthread_self (), &a);
+  if (err)
+    {
+      error (0, err, "pthread_getattr_np failed");
+      result = 1;
+    }
+
+  int detachstate;
+  err = pthread_attr_getdetachstate (&a, &detachstate);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getdetachstate failed");
+      result = 1;
+    }
+  else if (detachstate != PTHREAD_CREATE_JOINABLE)
+    {
+      error (0, 0, "initial thread not joinable");
+      result = 1;
+    }
+
+  void *stackaddr;
+  size_t stacksize;
+  err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getstack failed");
+      result = 1;
+    }
+  else if ((void *) &a < stackaddr
+	   || (void *) &a >= stackaddr + stacksize)
+    {
+      error (0, 0, "pthread_attr_getstack returned range does not cover main's stack");
+      result = 1;
+    }
+  else
+    printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr,
+	    stackaddr + stacksize, stacksize);
+
+  size_t guardsize;
+  err = pthread_attr_getguardsize (&a, &guardsize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getguardsize failed");
+      result = 1;
+    }
+  else if (guardsize != 0)
+    {
+      error (0, 0, "pthread_attr_getguardsize returned %zd != 0",
+	     guardsize);
+      result = 1;
+    }
+
+  int scope;
+  err = pthread_attr_getscope (&a, &scope);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getscope failed");
+      result = 1;
+    }
+  else if (scope != PTHREAD_SCOPE_SYSTEM)
+    {
+      error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM",
+	     scope);
+      result = 1;
+    }
+
+  int inheritsched;
+  err = pthread_attr_getinheritsched (&a, &inheritsched);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getinheritsched failed");
+      result = 1;
+    }
+  else if (inheritsched != PTHREAD_INHERIT_SCHED)
+    {
+      error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED",
+	     inheritsched);
+      result = 1;
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  pthread_t th;
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err)
+    {
+      error (0, err, "pthread_create #1 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #1 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_init (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_init failed");
+      result = 1;
+    }
+
+  err = pthread_create (&th, &a, tf, &a);
+  if (err)
+    {
+      error (0, err, "pthread_create #2 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #2 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE));
+  if (err)
+    {
+      error (0, err, "pthread_attr_setguardsize failed");
+      result = 1;
+    }
+
+  err = pthread_create (&th, &a, tf, &a);
+  if (err)
+    {
+      error (0, err, "pthread_create #3 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #3 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel-static.c b/linuxthreads/tst-cancel-static.c
new file mode 100644
index 0000000000..1c879eba8b
--- /dev/null
+++ b/linuxthreads/tst-cancel-static.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/linuxthreads/tst-cancel-wrappers.sh b/linuxthreads/tst-cancel-wrappers.sh
new file mode 100644
index 0000000000..d6f16d1ed2
--- /dev/null
+++ b/linuxthreads/tst-cancel-wrappers.sh
@@ -0,0 +1,92 @@
+#! /bin/sh
+# Test whether all cancelable functions are cancelable.
+# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+# Contributed by Jakub Jelinek <jakub@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.
+
+while [ $# -gt 0 ]; do
+  ( nm -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
+C["accept"]=1
+C["close"]=1
+C["connect"]=1
+C["creat"]=1
+C["fcntl"]=1
+C["fsync"]=1
+C["msgrcv"]=1
+C["msgsnd"]=1
+C["msync"]=1
+C["nanosleep"]=1
+C["open"]=1
+C["open64"]=1
+C["pause"]=1
+C["poll"]=1
+C["pread"]=1
+C["pread64"]=1
+C["pselect"]=1
+C["pwrite"]=1
+C["pwrite64"]=1
+C["read"]=1
+C["readv"]=1
+C["recv"]=1
+C["recvfrom"]=1
+C["recvmsg"]=1
+C["select"]=1
+C["send"]=1
+C["sendmsg"]=1
+C["sendto"]=1
+C["sigpause"]=1
+C["sigsuspend"]=1
+C["sigwait"]=1
+C["sigwaitinfo"]=1
+C["system"]=1
+C["tcdrain"]=1
+C["wait"]=1
+C["waitid"]=1
+C["waitpid"]=1
+C["write"]=1
+C["writev"]=1
+C["__xpg_sigpause"]=1
+}
+/:$/ {
+  if (seen)
+    {
+      if (!seen_enable || !seen_disable)
+	{
+	  printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
+	  ret = 1
+	}
+    }
+  seen=""
+  seen_enable=""
+  seen_disable=""
+  object=gensub(/^.*\[(.*)\]:$/,"\\1","",$0)
+  next
+}
+{
+  if (C[$1] && $2 ~ /^[TW]$/)
+    seen=$1
+  else if ($1 ~ /^([.]|)__(libc|pthread)_enable_asynccancel$/ && $2 == "U")
+    seen_enable=1
+  else if ($1 ~ /^([.]|)__(libc|pthread)_disable_asynccancel$/ && $2 == "U")
+    seen_disable=1
+}
+END {
+  exit ret
+}' || exit
+  shift
+done
diff --git a/linuxthreads/tst-cancel.c b/linuxthreads/tst-cancel.c
new file mode 100644
index 0000000000..59c6f1f511
--- /dev/null
+++ b/linuxthreads/tst-cancel.c
@@ -0,0 +1,214 @@
+/* Tests for cancelation handling.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int fd;
+
+pthread_barrier_t bar;
+
+
+#ifdef NOT_YET
+static void
+cleanup (void *arg)
+{
+  int nr = (int) (long int) arg;
+  char s[30];
+  char *cp = stpcpy (s, "cleanup ");
+  *cp++ = '0' + nr;
+  *cp++ = '\n';
+  __libc_lseek (fd, 0, SEEK_END);
+  __libc_write (fd, s, cp - s);
+}
+
+
+static void *
+t1 (void *arg)
+{
+  pthread_cleanup_push (cleanup, (void *) (long int) 1);
+  return NULL;
+  pthread_cleanup_pop (0);
+}
+
+
+static void
+inner (int a)
+{
+  pthread_cleanup_push (cleanup, (void *) (long int) a);
+  if (a)
+    return;
+  pthread_cleanup_pop (0);
+}
+
+
+static void *
+t2 (void *arg)
+{
+  pthread_cleanup_push (cleanup, (void *) (long int) 2);
+  inner ((int) (long int) arg);
+  return NULL;
+  pthread_cleanup_pop (0);
+}
+#endif
+
+/* This does not work yet.  */
+volatile int cleanupokcnt;
+
+static void
+cleanupok (void *arg)
+{
+  ++cleanupokcnt;
+}
+
+#ifdef NOT_YET
+static void *
+t3 (void *arg)
+{
+  pthread_cleanup_push (cleanupok, (void *) (long int) 4);
+  inner ((int) (long int) arg);
+  pthread_exit (NULL);
+  pthread_cleanup_pop (0);
+}
+#endif
+
+static void
+innerok (int a)
+{
+  pthread_cleanup_push (cleanupok, (void *) (long int) a);
+  pthread_exit (NULL);
+  pthread_cleanup_pop (0);
+}
+
+
+static void *
+t4 (void *arg)
+{
+  pthread_cleanup_push (cleanupok, (void *) (long int) 6);
+  innerok ((int) (long int) arg);
+  pthread_cleanup_pop (0);
+  return NULL;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  pthread_t td;
+  int err;
+  char *tmp;
+  const char *prefix;
+  const char template[] = "thtstXXXXXX";
+  struct stat64 st;
+  int result = 0;
+
+  prefix = argc > 1 ? argv[1] : "";
+  tmp = (char *) alloca (strlen (prefix) + sizeof template);
+  strcpy (stpcpy (tmp, prefix), template);
+
+  fd = mkstemp (tmp);
+  if (fd == -1)
+    {
+      printf ("cannot create temporary file: %m");
+      exit (1);
+    }
+  unlink (tmp);
+
+  err = pthread_barrier_init (&bar, NULL, 2);
+  if (err != 0 )
+    {
+      printf ("cannot create barrier: %s\n", strerror (err));
+      exit (1);
+    }
+
+#ifdef NOT_YET
+  err = pthread_create (&td, NULL, t1, NULL);
+  if (err != 0)
+    {
+      printf ("cannot create thread t1: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_join (td, NULL);
+  if (err != 0)
+    {
+      printf ("cannot join thread: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_create (&td, NULL, t2, (void *) 3);
+  if (err != 0)
+    {
+      printf ("cannot create thread t2: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_join (td, NULL);
+  if (err != 0)
+    {
+      printf ("cannot join thread: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_create (&td, NULL, t3, (void *) 5);
+  if (err != 0)
+    {
+      printf ("cannot create thread t3: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_join (td, NULL);
+  if (err != 0)
+    {
+      printf ("cannot join thread: %s\n", strerror (err));
+      exit (1);
+    }
+#endif
+
+  err = pthread_create (&td, NULL, t4, (void *) 7);
+  if (err != 0)
+    {
+      printf ("cannot create thread t4: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_join (td, NULL);
+  if (err != 0)
+    {
+      printf ("cannot join thread: %s\n", strerror (err));
+      exit (1);
+    }
+
+  if (fstat64 (fd, &st) < 0)
+    {
+      printf ("cannot stat temporary file: %m\n");
+      result = 1;
+    }
+  else if (st.st_size != 0)
+    {
+      char buf[512];
+      puts ("some cleanup handlers ran:");
+      fflush (stdout);
+      __lseek (fd, 0, SEEK_SET);
+      while (1)
+	{
+	  ssize_t n = read (fd, buf, sizeof buf);
+	  if (n <= 0)
+	    break;
+	  write (STDOUT_FILENO, buf, n);
+	}
+      result = 1;
+    }
+
+  // if (cleanupokcnt != 3)  will be three once t3 runs
+  if (cleanupokcnt != 2)
+    {
+      printf ("cleanupokcnt = %d\n", cleanupokcnt);
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/linuxthreads/tst-cancel1.c b/linuxthreads/tst-cancel1.c
new file mode 100644
index 0000000000..99a8339f0c
--- /dev/null
+++ b/linuxthreads/tst-cancel1.c
@@ -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.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+  if (arg != (void *) 42l)
+    cntr = 42;
+  else
+    cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  int err;
+
+  pthread_cleanup_push (cleanup, (void *) 42l);
+
+  err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+  if (err != 0)
+    {
+      printf ("setcanceltype failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&m2);
+  if (err != 0)
+    {
+      printf ("child: mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int err;
+  pthread_t th;
+  int result = 0;
+  void *retval;
+
+  /* Get the mutexes.  */
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_cancel (th);
+  if (err != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_join (th, &retval);
+  if (err != 0)
+    {
+      printf ("join failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (retval != PTHREAD_CANCELED)
+    {
+      printf ("wrong return value: %p\n", retval);
+      result = 1;
+    }
+
+  if (cntr == 42)
+    {
+      puts ("cleanup handler called with wrong argument");
+      result = 1;
+    }
+  else if (cntr != 1)
+    {
+      puts ("cleanup handling not called");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel2.c b/linuxthreads/tst-cancel2.c
new file mode 100644
index 0000000000..6d80f8ae5e
--- /dev/null
+++ b/linuxthreads/tst-cancel2.c
@@ -0,0 +1,100 @@
+/* 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>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  /* The buffer size must be larger than the pipe size so that the
+     write blocks.  */
+  char buf[100000];
+
+  if (write (fd[1], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("write succeeded");
+      return (void *) 1l;
+    }
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the write in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel3.c b/linuxthreads/tst-cancel3.c
new file mode 100644
index 0000000000..86c482bcc1
--- /dev/null
+++ b/linuxthreads/tst-cancel3.c
@@ -0,0 +1,98 @@
+/* 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>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+
+  if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("read succeeded");
+      return (void *) 1l;
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the read in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel4.c b/linuxthreads/tst-cancel4.c
new file mode 100644
index 0000000000..03f6bfe056
--- /dev/null
+++ b/linuxthreads/tst-cancel4.c
@@ -0,0 +1,469 @@
+/* Copyright (C) 2002, 2003, 2004 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.  */
+
+/* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
+   exit to be called more than once.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+/* The following interfaces are defined to be cancellation points but
+   tests are not yet implemented:
+
+     accept()              aio_suspend()      clock_nanosleep()
+     close()               connect()          creat()
+     fcntl()               fsync()            getmsg()
+     getpmsg()             lockf()            mq_receive()
+     mq_send()             mq_timedreceive()  mq_timedsend()
+     msgrcv()              msgsnd()           msync()
+                           open()             pause()
+                           pread()            pthread_cond_timedwait()
+     pthread_cond_wait()   pthread_join()     pthread_testcancel()
+     putmsg()              putpmsg()          pwrite()
+                                              recv()
+     recvfrom()            recvmsg()
+     sem_timedwait()       sem_wait()         send()
+     sendmsg()             sendto()           sigpause()
+     sigsuspend()          sigtimedwait()     sigwait()
+     sigwaitinfo()                            system()
+     tcdrain()
+
+   Since STREAMS are not supported in the standard Linux kernel there
+   is no need to test the STREAMS related functions.
+*/
+
+/* Pipe descriptors.  */
+static int fds[2];
+
+/* Often used barrier for two threads.  */
+static pthread_barrier_t b2;
+
+
+static void *
+tf_read  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100];
+  ssize_t s = read (fds[0], buf, sizeof (buf));
+
+  printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_readv  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100];
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  ssize_t s = readv (fds[0], iov, 1);
+
+  printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_write  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100000];
+  memset (buf, '\0', sizeof (buf));
+  ssize_t s = write (fds[1], buf, sizeof (buf));
+
+  printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_writev  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100000];
+  memset (buf, '\0', sizeof (buf));
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  ssize_t s = writev (fds[1], iov, 1);
+
+  printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  sleep (1000000);
+
+  printf ("%s: sleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  usleep ((useconds_t) ULONG_MAX);
+
+  printf ("%s: usleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 };
+  while (nanosleep (&ts, &ts) != 0)
+    continue;
+
+  printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fds[0], &rfs);
+
+  int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL);
+
+  printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fds[0], &rfs);
+
+  int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
+
+  printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } };
+
+  int s = poll (rfs, 1, -1);
+
+  printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+  int s = wait (NULL);
+
+  printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+  int s = waitpid (-1, NULL, 0);
+
+  printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+#ifndef WEXITED
+# define WEXITED 0
+#endif
+  siginfo_t si;
+  int s = waitid (P_PID, pid, &si, WEXITED);
+
+  printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static struct
+{
+  void *(*tf) (void *);
+  int nb;
+} tests[] =
+{
+  { tf_read, 2 },
+  { tf_readv, 2 },
+  { tf_select, 2 },
+  { tf_pselect, 2 },
+  { tf_poll, 2 },
+  { tf_write, 2 },
+  { tf_writev, 2},
+  { tf_sleep, 2 },
+  { tf_usleep, 2 },
+  { tf_nanosleep, 2 },
+  { tf_wait, 2 },
+  { tf_waitid, 2 },
+  { tf_waitpid, 2 },
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+  if (pipe (fds) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  int cnt;
+  for (cnt = 0; cnt < ntest_tf; ++cnt)
+    {
+      printf ("round %d\n", cnt);
+
+      if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+	{
+	  puts ("b2 init failed");
+	  exit (1);
+	}
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+	{
+	  printf ("create for round %d test failed\n", cnt);
+	  exit (1);
+	}
+
+      puts ("barrier waits");
+
+      int r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      puts ("nanosleep delay");
+
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("cancel in round %d failed\n", cnt);
+	  exit (1);
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("join in round %d failed\n", cnt);
+	  exit (1);
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("thread in round %d not canceled\n", cnt);
+	  exit (1);
+	}
+      printf ("test %d successful\n", cnt);
+
+      if (pthread_barrier_destroy (&b2) != 0)
+	{
+	  puts ("barrier_destroy failed");
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel5.c b/linuxthreads/tst-cancel5.c
new file mode 100644
index 0000000000..1c879eba8b
--- /dev/null
+++ b/linuxthreads/tst-cancel5.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/linuxthreads/tst-cancel6.c b/linuxthreads/tst-cancel6.c
new file mode 100644
index 0000000000..94de85830b
--- /dev/null
+++ b/linuxthreads/tst-cancel6.c
@@ -0,0 +1,79 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+  fgets (buf, sizeof (buf), arg);
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int fd[2];
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  FILE *fp = fdopen (fd[0], "r");
+  if (fp == NULL)
+    {
+      puts ("fdopen failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, fp) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel7.c b/linuxthreads/tst-cancel7.c
new file mode 100644
index 0000000000..11298eae26
--- /dev/null
+++ b/linuxthreads/tst-cancel7.c
@@ -0,0 +1,111 @@
+/* Test for pthread cancellation of mutex blocks.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_barrier_t b;
+int value = 0;
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_mutex_lock (&lock);
+  ++value;
+  pthread_testcancel ();
+  ++value;
+  pthread_mutex_unlock (&lock);
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_lock (&lock);
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+
+  if (value == 0)
+    {
+      puts ("thread cancelled in the pthread_mutex_lock call");
+      return 1;
+    }
+
+  if (value != 1)
+    {
+      puts ("thread not cancelled in pthread_testcancel call");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-cancel8.c b/linuxthreads/tst-cancel8.c
new file mode 100644
index 0000000000..478d104fb3
--- /dev/null
+++ b/linuxthreads/tst-cancel8.c
@@ -0,0 +1,287 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static void *
+tf (void *arg)
+{
+  return NULL;
+}
+
+static void
+handler (int sig)
+{
+}
+
+static void __attribute__ ((noinline))
+clobber_lots_of_regs (void)
+{
+#define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
+#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
+#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#define X1(n) __asm __volatile ("" : : "r" (r##n));
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#undef X2
+#undef X3
+}
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int old, rc;
+  int ret = 0;
+  int fd[2];
+
+  rc = pipe (fd);
+  if (rc < 0)
+    error (EXIT_FAILURE, errno, "couldn't create pipe");
+
+  rc = pthread_create (&th, NULL, tf, NULL);
+  if (rc)
+    error (EXIT_FAILURE, rc, "couldn't create thread");
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "1st pthread_setcanceltype failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[0]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[1]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGALRM, &sa, NULL);
+
+  struct itimerval it;
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  char fname[] = "/tmp/tst-lt-cancel8-dir-XXXXXX\0foo/bar";
+  char *enddir = strchr (fname, '\0');
+  if (mkdtemp (fname) == NULL)
+    {
+      error (0, errno, "mkdtemp failed");
+      ret = 1;
+    }
+  *enddir = '/';
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  *enddir = '\0';
+  rmdir (fname);
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  pthread_join (th, NULL);
+
+  return ret;
+}
+
+#define TIMEOUT 20
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-clock1.c b/linuxthreads/tst-clock1.c
new file mode 100644
index 0000000000..bca40956e2
--- /dev/null
+++ b/linuxthreads/tst-clock1.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+static pthread_barrier_t b2;
+static pthread_barrier_t bN;
+
+
+static void *
+tf (void *arg)
+{
+  int e = pthread_barrier_wait (&b2);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&bN);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+#endif
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+# define N 10
+
+# if _POSIX_THREAD_CPUTIME == 0
+  if (sysconf (_SC_THREAD_CPUTIME) < 0)
+    {
+      puts ("_POSIX_THREAD_CPUTIME option not available");
+      return 0;
+    }
+# endif
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0
+      || pthread_barrier_init (&bN, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+  pthread_t th[N + 1];
+  clockid_t cl[N + 1];
+# ifndef CLOCK_THREAD_CPUTIME_ID
+  if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
+    {
+      puts ("own pthread_getcpuclockid failed");
+      return 1;
+    }
+# else
+  cl[0] = CLOCK_THREAD_CPUTIME_ID;
+# endif
+
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int i;
+  int e;
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_create (&th[i], &at, tf, NULL) != 0)
+	{
+	  puts ("create failed");
+	  return 1;
+	}
+
+      e = pthread_barrier_wait (&b2);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  return 1;
+	}
+
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+      if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
+	{
+	  puts ("pthread_getcpuclockid failed");
+	  return 1;
+	}
+    }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  struct timespec t[N + 1];
+  for (i = 0; i < N + 1; ++i)
+    if (clock_gettime (cl[i], &t[i]) != 0)
+      {
+	printf ("clock_gettime round %d failed\n", i);
+	return 1;
+      }
+
+  for (i = 0; i < N; ++i)
+    {
+      struct timespec diff;
+
+      diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
+      diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
+      if (diff.tv_nsec < 0)
+	{
+	  diff.tv_nsec += 1000000000;
+	  --diff.tv_sec;
+	}
+
+      if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
+	{
+	  printf ("\
+difference between thread %d and %d too small (%ld.%09ld)\n",
+		  i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+	  return 1;
+	}
+
+      printf ("diff %d->%d: %ld.%09ld\n",
+	      i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+    }
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 0;
+  for (i = 0; i < N + 1; ++i)
+    if (clock_settime (cl[i], &ts) != 0)
+      {
+	printf ("clock_settime(%d) round %d failed\n", cl[i], i);
+	return 1;
+      }
+
+  for (i = 0; i < N + 1; ++i)
+    {
+      if (clock_gettime (cl[i], &ts) != 0)
+	{
+	  puts ("clock_gettime failed");
+	  return 1;
+	}
+
+      if (ts.tv_sec > t[i].tv_sec
+	  || (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
+	{
+	  puts ("clock_settime didn't reset clock");
+	  return 1;
+	}
+    }
+#endif
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-context.c b/linuxthreads/tst-context.c
new file mode 100644
index 0000000000..2938a9f7fa
--- /dev/null
+++ b/linuxthreads/tst-context.c
@@ -0,0 +1,116 @@
+/* Ack, a hack!  We need to get the proper definition, or lack thereof,
+   for FLOATING_STACKS.  But when !IS_IN_libpthread, this can get defined
+   incidentally by <tls.h>.  So kludge around it.  */
+
+#define IS_IN_libpthread
+#include <tls.h>
+#undef IS_IN_libpthread
+#undef USE___THREAD
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+
+#define N	4
+
+#ifdef FLOATING_STACKS
+static char stacks[N][8192];
+static ucontext_t ctx[N][2];
+static volatile int failures;
+
+static void
+fct (long int n)
+{
+  /* Just to use the thread local descriptor.  */
+  printf ("%ld: in %s now\n", n, __FUNCTION__);
+  errno = 0;
+}
+
+static void *
+threadfct (void *arg)
+{
+  int n = (int) (long int) arg;
+
+  if (getcontext (&ctx[n][1]) != 0)
+    {
+      printf ("%d: cannot get context: %m\n", n);
+      exit (1);
+    }
+
+  printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
+
+  ctx[n][1].uc_stack.ss_sp = stacks[n];
+  ctx[n][1].uc_stack.ss_size = 8192;
+  ctx[n][1].uc_link = &ctx[n][0];
+  makecontext (&ctx[n][1], (void (*) (void)) fct, 1, (long int) n);
+
+  printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
+
+  if (swapcontext (&ctx[n][0], &ctx[n][1]) != 0)
+    {
+      ++failures;
+      printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
+    }
+  else
+    printf ("%d: back in %s\n", n, __FUNCTION__);
+
+  return NULL;
+}
+#endif
+
+
+#ifdef FLOATING_STACKS
+static volatile int global;
+#endif
+
+int
+main (void)
+{
+#ifndef FLOATING_STACKS
+  puts ("not supported");
+  return 0;
+#else
+  int n;
+  pthread_t th[N];
+  ucontext_t mctx;
+
+  puts ("making contexts");
+  if (getcontext (&mctx) != 0)
+    {
+      if (errno == ENOSYS)
+	{
+	  puts ("context handling not supported");
+	  exit (0);
+	}
+
+      printf ("%s: getcontext: %m\n", __FUNCTION__);
+      exit (1);
+    }
+
+  /* Play some tricks with this context.  */
+  if (++global == 1)
+    if (setcontext (&mctx) != 0)
+      {
+	printf ("%s: setcontext: %m\n", __FUNCTION__);
+	exit (1);
+      }
+  if (global != 2)
+    {
+      printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
+      exit (1);
+    }
+
+  for (n = 0; n < N; ++n)
+    if (pthread_create (&th[n], NULL, threadfct, (void *) (long int) n) != 0)
+      error (EXIT_FAILURE, errno, "cannot create all threads");
+
+  for (n = 0; n < N; ++n)
+    pthread_join (th[n], NULL);
+
+  return failures;
+#endif
+}
diff --git a/linuxthreads/tst-popen.c b/linuxthreads/tst-popen.c
new file mode 100644
index 0000000000..f76a6e79e5
--- /dev/null
+++ b/linuxthreads/tst-popen.c
@@ -0,0 +1,37 @@
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *
+dummy (void *x)
+{
+  return NULL;
+}
+
+static char buf[sizeof "something\n"];
+
+static int
+do_test (void)
+{
+  FILE *f;
+  pthread_t p;
+
+  pthread_create (&p, NULL, dummy, NULL);
+  f = popen ("echo something", "r");
+  if (f == NULL)
+    error (EXIT_FAILURE, errno, "popen failed");
+  if (fgets (buf, sizeof (buf), f) == NULL)
+    error (EXIT_FAILURE, 0, "fgets failed");
+  if (strcmp (buf, "something\n"))
+    error (EXIT_FAILURE, 0, "read wrong data");
+  if (pclose (f))
+    error (EXIT_FAILURE, errno, "pclose returned non-zero");
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-popen2.c b/linuxthreads/tst-popen2.c
new file mode 100644
index 0000000000..3ff69acd52
--- /dev/null
+++ b/linuxthreads/tst-popen2.c
@@ -0,0 +1,41 @@
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *
+dummy (void *x)
+{
+  return NULL;
+}
+
+static char buf[sizeof "something\n"];
+
+static int
+do_test (void)
+{
+  FILE *f;
+  pthread_t p;
+  int err;
+
+  f = popen ("echo something", "r");
+  if (f == NULL)
+    error (EXIT_FAILURE, errno, "popen failed");
+  if (fgets (buf, sizeof (buf), f) == NULL)
+    error (EXIT_FAILURE, 0, "fgets failed");
+  if (strcmp (buf, "something\n"))
+    error (EXIT_FAILURE, 0, "read wrong data");
+  if (pclose (f))
+    error (EXIT_FAILURE, errno, "pclose returned non-zero");
+  if ((err = pthread_create (&p, NULL, dummy, NULL)))
+    error (EXIT_FAILURE, err, "pthread_create failed");
+  if ((err = pthread_join (p, NULL)))
+    error (EXIT_FAILURE, err, "pthread_join failed");
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-signal.c b/linuxthreads/tst-signal.c
new file mode 100644
index 0000000000..5eb0170c6c
--- /dev/null
+++ b/linuxthreads/tst-signal.c
@@ -0,0 +1,64 @@
+/* Test sigaction wrapper.  */
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@suse.de>.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+int
+main (int argc, char *argv[])
+{
+  struct sigaction old_sa, new_sa;
+
+  if (sigaction (SIGHUP, NULL, &old_sa) < 0)
+    {
+      printf ("cannot get signal action for SIGHUP: %m\n");
+      exit (1);
+    }
+
+  if (old_sa.sa_handler != SIG_IGN)
+    {
+      printf ("SIGHUP action should be SIG_IGN, is %p\n",
+	      (void *) old_sa.sa_handler);
+      exit (1);
+    }
+
+  new_sa.sa_handler = SIG_DFL;
+  if (sigaction (SIGHUP, &new_sa, NULL) < 0)
+    {
+      printf ("cannot set signal action for SIGHUP: %m\n");
+      exit (1);
+    }
+
+  if (sigaction (SIGHUP, NULL, &old_sa) < 0)
+    {
+      printf ("cannot get signal action for SIGHUP: %m\n");
+      exit (1);
+    }
+
+  if (old_sa.sa_handler != SIG_DFL)
+    {
+      printf ("SIGHUP action should be SIG_DFL, is %p\n",
+	      (void *) old_sa.sa_handler);
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/linuxthreads/tst-signal.sh b/linuxthreads/tst-signal.sh
new file mode 100644
index 0000000000..fb58193822
--- /dev/null
+++ b/linuxthreads/tst-signal.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Testing the sigaction wrapper.
+# 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.
+
+common_objpfx=$1; shift
+
+# set up to ignore SIGHUP
+trap '' 1
+
+exec ${common_objpfx}elf/ld.so --library-path $common_objpfx:${common_objpfx}linuxthreads \
+     ${common_objpfx}linuxthreads/tst-signal
diff --git a/linuxthreads/tst-stack1.c b/linuxthreads/tst-stack1.c
new file mode 100644
index 0000000000..057bfa3f9f
--- /dev/null
+++ b/linuxthreads/tst-stack1.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Test pthread_create/pthread_join with user defined stacks.  */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int seen;
+
+static void *
+tf (void *p)
+{
+  ++seen;
+  return NULL;
+}
+
+#define N 16
+
+static int
+do_test (void)
+{
+  void *stack;
+  int res = posix_memalign (&stack, getpagesize (), N * 4 * PTHREAD_STACK_MIN);
+  if (res)
+    {
+      printf ("malloc failed %s\n", strerror (res));
+      return 1;
+    }
+
+  pthread_attr_t attr;
+  pthread_attr_init (&attr);
+
+  int result = 0;
+  for (int i = 0; i < N; ++i)
+    {
+      res = pthread_attr_setstack (&attr, stack + i * 4 * PTHREAD_STACK_MIN,
+				   4 * PTHREAD_STACK_MIN);
+      if (res)
+	{
+	  printf ("pthread_attr_setstack failed %d\n", res);
+	  result = 1;
+	  continue;
+	}
+
+      /* Create the thread.  */
+      pthread_t th;
+      res = pthread_create (&th, &attr, tf, NULL);
+      if (res)
+	{
+	  printf ("pthread_create failed %d\n", res);
+	  result = 1;
+	}
+      else
+	{
+	  res = pthread_join (th, NULL);
+	  if (res)
+	    {
+	      printf ("pthread_join failed %d\n", res);
+	      result = 1;
+	    }
+	}
+    }
+
+  pthread_attr_destroy (&attr);
+
+  if (seen != N)
+    {
+      printf ("seen %d != %d\n", seen, N);
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-static-locale.c b/linuxthreads/tst-static-locale.c
new file mode 100644
index 0000000000..3c88e729ba
--- /dev/null
+++ b/linuxthreads/tst-static-locale.c
@@ -0,0 +1,13 @@
+/* Test that the thread-local locale works right in the main thread
+   when statically linked.  */
+
+#include "../locale/tst-C-locale.c"
+
+#include <pthread.h>
+
+/* This is never called, just here to get pthreads linked in.  */
+void
+useless (void)
+{
+  pthread_create (0, 0, 0, 0);
+}
diff --git a/linuxthreads/tst-tls1.c b/linuxthreads/tst-tls1.c
new file mode 100644
index 0000000000..3638b75455
--- /dev/null
+++ b/linuxthreads/tst-tls1.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Check alignment, overlapping and layout of TLS variables.  */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/param.h>
+
+#include "tst-tls1.h"
+
+#ifdef TLS_REGISTER
+
+struct tls_obj tls_registry[64];
+
+static int
+tls_addr_cmp (const void *a, const void *b)
+{
+  if (((struct tls_obj *)a)->addr < ((struct tls_obj *)b)->addr)
+    return -1;
+  if (((struct tls_obj *)a)->addr > ((struct tls_obj *)b)->addr)
+    return 1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  size_t cnt, i;
+  int res = 0;
+  uintptr_t min_addr = ~(uintptr_t) 0, max_addr = 0;
+
+  for (cnt = 0; tls_registry[cnt].name; ++cnt);
+
+  qsort (tls_registry, cnt, sizeof (struct tls_obj), tls_addr_cmp);
+
+  for (i = 0; i < cnt; ++i)
+    {
+      printf ("%s = %p, size %zd, align %zd",
+	      tls_registry[i].name, (void *) tls_registry[i].addr,
+	      tls_registry[i].size, tls_registry[i].align);
+      if (tls_registry[i].addr & (tls_registry[i].align - 1))
+	{
+	  fputs (", WRONG ALIGNMENT", stdout);
+	  res = 1;
+	}
+      if (i > 0
+	  && (tls_registry[i - 1].addr + tls_registry[i - 1].size
+	      > tls_registry[i].addr))
+	{
+	  fputs (", ADDRESS OVERLAP", stdout);
+	  res = 1;
+	}
+      puts ("");
+      min_addr = MIN (tls_registry[i].addr, min_addr);
+      max_addr = MAX (tls_registry[i].addr + tls_registry[i].size,
+		      max_addr);
+    }
+
+  if (cnt > 1)
+    printf ("Initial TLS used block size %zd\n",
+	    (size_t) (max_addr - min_addr));
+  return res;
+}
+
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/linuxthreads/tst-tls1.h b/linuxthreads/tst-tls1.h
new file mode 100644
index 0000000000..b7c14eb82c
--- /dev/null
+++ b/linuxthreads/tst-tls1.h
@@ -0,0 +1,28 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <tls.h>
+
+#if USE_TLS && HAVE___THREAD
+
+struct tls_obj
+{
+  const char *name;
+  uintptr_t addr;
+  size_t size;
+  size_t align;
+};
+extern struct tls_obj tls_registry[];
+
+#define TLS_REGISTER(x)				\
+static void __attribute__((constructor))	\
+tls_register_##x (void)				\
+{						\
+  size_t i;					\
+  for (i = 0; tls_registry[i].name; ++i);	\
+  tls_registry[i].name = #x;			\
+  tls_registry[i].addr = (uintptr_t) &x;	\
+  tls_registry[i].size = sizeof (x);		\
+  tls_registry[i].align = __alignof__ (x);	\
+}
+
+#endif
diff --git a/linuxthreads/tst-tls1mod.c b/linuxthreads/tst-tls1mod.c
new file mode 100644
index 0000000000..a93d2cb9e6
--- /dev/null
+++ b/linuxthreads/tst-tls1mod.c
@@ -0,0 +1,6 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+/* Ensure tls_registry is exported from the binary.  */
+void *tst_tls1mod attribute_hidden = tls_registry;
+#endif
diff --git a/linuxthreads/tst-tls1moda.c b/linuxthreads/tst-tls1moda.c
new file mode 100644
index 0000000000..a652ef981f
--- /dev/null
+++ b/linuxthreads/tst-tls1moda.c
@@ -0,0 +1,6 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+static __thread char a [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (a)
+#endif
diff --git a/linuxthreads/tst-tls1modb.c b/linuxthreads/tst-tls1modb.c
new file mode 100644
index 0000000000..be8c95b486
--- /dev/null
+++ b/linuxthreads/tst-tls1modb.c
@@ -0,0 +1,6 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+static __thread int b;
+TLS_REGISTER (b)
+#endif
diff --git a/linuxthreads/tst-tls1modc.c b/linuxthreads/tst-tls1modc.c
new file mode 100644
index 0000000000..e1094bf7aa
--- /dev/null
+++ b/linuxthreads/tst-tls1modc.c
@@ -0,0 +1,6 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+static __thread int c;
+TLS_REGISTER (c)
+#endif
diff --git a/linuxthreads/tst-tls1modd.c b/linuxthreads/tst-tls1modd.c
new file mode 100644
index 0000000000..cd68e0c26a
--- /dev/null
+++ b/linuxthreads/tst-tls1modd.c
@@ -0,0 +1,6 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+static __thread int d;
+TLS_REGISTER (d)
+#endif
diff --git a/linuxthreads/tst-tls1mode.c b/linuxthreads/tst-tls1mode.c
new file mode 100644
index 0000000000..845d31a4e4
--- /dev/null
+++ b/linuxthreads/tst-tls1mode.c
@@ -0,0 +1,8 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+static __thread int e1 = 24;
+static __thread char e2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (e1)
+TLS_REGISTER (e2)
+#endif
diff --git a/linuxthreads/tst-tls1modf.c b/linuxthreads/tst-tls1modf.c
new file mode 100644
index 0000000000..a292e56c57
--- /dev/null
+++ b/linuxthreads/tst-tls1modf.c
@@ -0,0 +1,9 @@
+#include <tst-tls1.h>
+
+#ifdef TLS_REGISTER
+char tst_tls1modf[60] attribute_hidden = { 26 };
+static __thread int f1 = 24;
+static __thread char f2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (f1)
+TLS_REGISTER (f2)
+#endif
diff --git a/linuxthreads/tst-tls2.sh b/linuxthreads/tst-tls2.sh
new file mode 100644
index 0000000000..0d13963d5e
--- /dev/null
+++ b/linuxthreads/tst-tls2.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+common_objpfx=$1; shift
+elf_objpfx=$1; shift
+rtld_installed_name=$1; shift
+logfile=$common_objpfx/linuxthreads/tst-tls2.out
+
+# We have to find libc and linuxthreads
+library_path=${common_objpfx}:${common_objpfx}linuxthreads
+tst_tls1="${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+	  ${common_objpfx}/linuxthreads/tst-tls1"
+
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
+> $logfile
+fail=0
+
+for aligned in a e f; do
+  echo "preload tst-tls1mod{$aligned,b,c,d}.so" >> $logfile
+  echo "===============" >> $logfile
+  LD_PRELOAD=`echo ${common_objpfx}linuxthreads/tst-tls1mod{$aligned,b,c,d}.so \
+	      | sed 's/:$//;s/: /:/g'` ${tst_tls1} >> $logfile || fail=1
+  echo >> $logfile
+
+  echo "preload tst-tls1mod{b,$aligned,c,d}.so" >> $logfile
+  echo "===============" >> $logfile
+  LD_PRELOAD=`echo ${common_objpfx}linuxthreads/tst-tls1mod{b,$aligned,c,d}.so \
+	      | sed 's/:$//;s/: /:/g'` ${tst_tls1} >> $logfile || fail=1
+  echo >> $logfile
+
+  echo "preload tst-tls1mod{b,c,d,$aligned}.so" >> $logfile
+  echo "===============" >> $logfile
+  LD_PRELOAD=`echo ${common_objpfx}linuxthreads/tst-tls1mod{b,c,d,$aligned}.so \
+	      | sed 's/:$//;s/: /:/g'` ${tst_tls1} >> $logfile || fail=1
+  echo >> $logfile
+done
+
+echo "preload tst-tls1mod{d,a,b,c,e}" >> $logfile
+echo "===============" >> $logfile
+LD_PRELOAD=`echo ${common_objpfx}linuxthreads/tst-tls1mod{d,a,b,c,e}.so \
+	    | sed 's/:$//;s/: /:/g'` ${tst_tls1} >> $logfile || fail=1
+echo >> $logfile
+
+echo "preload tst-tls1mod{d,a,b,e,f}" >> $logfile
+echo "===============" >> $logfile
+LD_PRELOAD=`echo ${common_objpfx}linuxthreads/tst-tls1mod{d,a,b,e,f}.so \
+	    | sed 's/:$//;s/: /:/g'` ${tst_tls1} >> $logfile || fail=1
+echo >> $logfile
+
+exit $fail
diff --git a/linuxthreads/tststack.c b/linuxthreads/tststack.c
new file mode 100644
index 0000000000..02b15cb8bc
--- /dev/null
+++ b/linuxthreads/tststack.c
@@ -0,0 +1,74 @@
+/* Tests for variable stack size handling.
+   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   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 <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+
+static void *f1 (void *);
+static void *f2 (void *);
+
+int
+main (void)
+{
+  pthread_attr_t attr;
+  pthread_t th1 = 0;
+  pthread_t th2 = 0;
+  void *res1;
+  void *res2;
+
+  pthread_attr_init (&attr);
+  if (pthread_attr_setstacksize (&attr, MAX (70*1024, PTHREAD_STACK_MIN)) != 0)
+    {
+      puts ("invalid stack size");
+      return 1;
+    }
+
+  pthread_create (&th1, NULL, f1, NULL);
+  pthread_create (&th2, &attr, f2, NULL);
+
+  pthread_join (th1, &res1);
+  pthread_join (th2, &res2);
+
+  printf ("res1 = %p\n", res1);
+  printf ("res2 = %p\n", res2);
+
+  return res1 != (void *) 1 || res2 != (void *) 2;
+}
+
+static void *
+f1 (void *parm)
+{
+  printf ("This is `%s'\n", __FUNCTION__);
+  fflush (stdout);
+
+  return (void *) 1;
+}
+
+static void *
+f2 (void *parm)
+{
+  printf ("This is `%s'\n", __FUNCTION__);
+  fflush (stdout);
+  sleep (1);
+
+  return (void *) 2;
+}
diff --git a/linuxthreads/unload.c b/linuxthreads/unload.c
new file mode 100644
index 0000000000..234d27f904
--- /dev/null
+++ b/linuxthreads/unload.c
@@ -0,0 +1,45 @@
+/* Tests for non-unloading of libpthread.
+   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   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 <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnu/lib-names.h>
+
+int
+main (void)
+{
+  void *p = dlopen (PREFIX LIBPTHREAD_SO, RTLD_LAZY);
+
+  if (p == NULL)
+    {
+      printf ("failed to load %s: %s\n", LIBPTHREAD_SO, dlerror ());
+      exit (1);
+    }
+
+  if (dlclose (p) != 0)
+    {
+      printf ("dlclose (%s) failed: %s\n", LIBPTHREAD_SO, dlerror ());
+      exit (1);
+    }
+
+  puts ("seems to work");
+
+  exit (0);
+}