This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Don't rely on dl_dynamic_weak for linuxthreads


Hi!

The following patch changes linuxthreads to match recent changes in NPTL,
ie. that dl_dynamic_weak could be finally turned off.
Only IA-32 and x86-64 arches done so far, x86-64 untested yet.
For other linux arches using linuxthreads, sysdep-cancel.h header has to
be implemented and any arch specific routines tst-cancel-wrappers.sh
test complains during make check need to have added the cancellation
stuff.
This (and similarly the recent NPTL changes) tie closely libc.so
and libpthread.so, so one has to always ensure both these libraries
come from the same glibc build.
There is a tiny NPTL patch in it as well (
#include <signal.h>
int main (void) { return SIGRTMIN; } 
proglet does not link statically with -lpthread without it).

2002-12-17  Jakub Jelinek  <jakub@redhat.com>

linuxthreads/
	* 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.

libc/
	* malloc/thread-m.h (mutex_init, mutex_lock, mutex_trylock,
	mutex_unlock): If not building NPTL, use __libc_maybe_call2 if
	available, otherwise __libc_maybe_call.
	* sysdeps/unix/sysv/linux/x86_64/recv.c: Add support for
	cancellation handling.
	* sysdeps/unix/sysv/linux/x86_64/send.c: Likewise.

nptl/
	* Makefile (libpthread-shared-only-routines): Add pt-allocrtsig.
	(tests): Depend on $(objpfx)tst-cancel-wrappers.out.
	($(objpfx)tst-cancel-wrappers.out): New rule.
	* tst-cancel-wrappers.sh: New test.
	* tst-locale1.c: Include signal.h.
	(uselocale): Test static linking of __libc_current_sigrt*.

--- libc/linuxthreads/wrapsyscall.c.jj	2002-12-15 22:43:25.000000000 +0100
+++ libc/linuxthreads/wrapsyscall.c	2002-07-23 20:50:16.000000000 +0200
@@ -1,233 +0,0 @@
-/* Wrapper arpund system calls to provide cancelation points.
-   Copyright (C) 1996-1999,2000-2002 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public License as
-   published by the Free Software Foundation; either version 2.1 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General 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 <fcntl.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <sys/poll.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-
-
-#ifndef SHARED
-/* We need a hook to force this file to be linked in when static
-   libpthread is used.  */
-const int __pthread_provide_wrappers = 0;
-#endif
-
-
-#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \
-extern res_type __libc_##name param_list;				      \
-res_type								      \
-name param_list								      \
-{									      \
-  res_type result;							      \
-  int oldtype;								      \
-  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);	      \
-  result = __libc_##name params;					      \
-  pthread_setcanceltype (oldtype, NULL);				      \
-  return result;							      \
-}
-
-#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \
-res_type __libc_##name param_list;					      \
-res_type								      \
-name param_list								      \
-{									      \
-  res_type result;							      \
-  int oldtype;								      \
-  va_list ap;								      \
-  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);	      \
-  va_start (ap, last_arg);						      \
-  result = __libc_##name params;					      \
-  va_end (ap);								      \
-  pthread_setcanceltype (oldtype, NULL);				      \
-  return result;							      \
-}
-
-#define PROMOTE_INTEGRAL_TYPE(type) __typeof__ ((type) 0 + 0)
-
-
-/* close(2).  */
-CANCELABLE_SYSCALL (int, close, (int fd), (fd))
-strong_alias (close, __close)
-
-
-/* fcntl(2).  */
-CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...),
-		       (fd, cmd, va_arg (ap, long int)), cmd)
-strong_alias (fcntl, __fcntl)
-
-
-/* fsync(2).  */
-CANCELABLE_SYSCALL (int, fsync, (int fd), (fd))
-
-
-/* lseek(2).  */
-CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence),
-		    (fd, offset, whence))
-strong_alias (lseek, __lseek)
-
-
-/* lseek64(2).  */
-CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence),
-		    (fd, offset, whence))
-
-
-/* msync(2).  */
-CANCELABLE_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags),
-		    (addr, length, flags))
-
-
-/* nanosleep(2).  */
-CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time,
-				     struct timespec *remaining),
-		    (requested_time, remaining))
-strong_alias (nanosleep, __nanosleep)
-
-
-/* open(2).  */
-CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...),
-		       (pathname, flags,
-			va_arg (ap, PROMOTE_INTEGRAL_TYPE (mode_t))),
-		       flags)
-strong_alias (open, __open)
-
-
-/* open64(3).  */
-CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...),
-		       (pathname, flags,
-			va_arg (ap, PROMOTE_INTEGRAL_TYPE (mode_t))),
-		       flags)
-strong_alias (open64, __open64)
-
-
-/* pause(2).  */
-CANCELABLE_SYSCALL (int, pause, (void), ())
-
-
-/* pread(3).  */
-CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count,
-				     off_t offset),
-		    (fd, buf, count, offset))
-
-
-/* pread64(3).  */
-CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count,
-				       off64_t offset),
-		    (fd, buf, count, offset))
-strong_alias (pread64, __pread64)
-
-
-/* pwrite(3).  */
-CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n,
-				      off_t offset),
-		    (fd, buf, n, offset))
-
-
-/* pwrite64(3).  */
-CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n,
-					off64_t offset),
-		    (fd, buf, n, offset))
-strong_alias (pwrite64, __pwrite64)
-
-
-/* read(2).  */
-CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count),
-		    (fd, buf, count))
-strong_alias (read, __read)
-
-
-/* system(3).  */
-CANCELABLE_SYSCALL (int, system, (const char *line), (line))
-
-
-/* tcdrain(2).  */
-CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd))
-
-
-/* wait(2).  */
-CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc))
-strong_alias (wait, __wait)
-
-
-/* waitpid(2).  */
-CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc,
-				       int options),
-		    (pid, stat_loc, options))
-
-
-/* write(2).  */
-CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n),
-		    (fd, buf, n))
-strong_alias (write, __write)
-
-
-/* The following system calls are thread cancellation points specified
-   in XNS.  */
-
-/* accept(2).  */
-CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr,
-				  socklen_t *addr_len),
-		    (fd, addr, addr_len))
-
-/* connect(2).  */
-CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr,
-				     socklen_t len),
-		    (fd, addr, len))
-strong_alias (connect, __connect)
-
-/* recv(2).  */
-CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags),
-		    (fd, buf, n, flags))
-
-/* recvfrom(2).  */
-CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags,
-					__SOCKADDR_ARG addr, socklen_t *addr_len),
-		    (fd, buf, n, flags, addr, addr_len))
-
-/* recvmsg(2).  */
-CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags),
-		    (fd, message, flags))
-
-/* send(2).  */
-CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n,
-				    int flags),
-		    (fd, buf, n, flags))
-strong_alias (send, __send)
-
-/* sendmsg(2).  */
-CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message,
-				       int flags),
-		    (fd, message, flags))
-
-/* sendto(2).  */
-CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n,
-				      int flags, __CONST_SOCKADDR_ARG addr,
-				      socklen_t addr_len),
-		    (fd, buf, n, flags, addr, addr_len))
--- libc/linuxthreads/weaks.c.jj	2002-11-20 02:22:19.000000000 +0100
+++ libc/linuxthreads/weaks.c	2002-07-23 20:50:16.000000000 +0200
@@ -1,97 +0,0 @@
-/* The weak pthread functions for Linux.
-   Copyright (C) 1996,97,98,99,2000,01,02 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 <limits.h>
-#include <stdlib.h>
-#include <shlib-compat.h>
-#include <bp-sym.h>
-
-extern int __pthread_return_0 (void);
-extern int __pthread_return_1 (void);
-extern void __pthread_return_void (void);
-extern void weak_function pthread_exit (void *__retval)
-     __attribute__ ((noreturn));
-
-/* Those are pthread functions which return 0 if successful. */
-weak_alias (__pthread_return_0, BP_SYM (__libc_pthread_attr_init_2_1))
-versioned_symbol (libpthread, BP_SYM (__libc_pthread_attr_init_2_1),
-		  BP_SYM (pthread_attr_init), GLIBC_2_1);
-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-weak_alias (__pthread_return_0, BP_SYM (__libc_pthread_attr_init_2_0))
-compat_symbol (libpthread, BP_SYM (__libc_pthread_attr_init_2_0),
-	       BP_SYM (pthread_attr_init), GLIBC_2_0);
-#endif
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_destroy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setdetachstate))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getdetachstate))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setschedparam))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getschedparam))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setschedpolicy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getschedpolicy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setinheritsched))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getinheritsched))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setscope))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getscope))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setstackaddr))
-weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setstacksize))
-weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_init))
-weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_destroy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_lock))
-weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_unlock))
-weak_alias (__pthread_return_0, BP_SYM (pthread_condattr_init))
-weak_alias (__pthread_return_0, BP_SYM (pthread_condattr_destroy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_setschedparam))
-weak_alias (__pthread_return_0, BP_SYM (pthread_getschedparam))
-weak_alias (__pthread_return_0, BP_SYM (pthread_setcancelstate))
-weak_alias (__pthread_return_0, BP_SYM (pthread_setcanceltype))
-weak_alias (__pthread_return_0, pthread_self)
-weak_alias (__pthread_return_0, BP_SYM (pthread_cond_init))
-weak_alias (__pthread_return_0, BP_SYM (pthread_cond_destroy))
-weak_alias (__pthread_return_0, BP_SYM (pthread_cond_wait))
-weak_alias (__pthread_return_0, BP_SYM (pthread_cond_signal))
-weak_alias (__pthread_return_0, BP_SYM (pthread_cond_broadcast))
-
-
-/* Those are pthread functions which return 1 if successful. */
-weak_alias (__pthread_return_1, pthread_equal)
-
-/* pthread_exit () is a special case. */
-void
-weak_function
-pthread_exit (void *retval)
-{
-  exit (EXIT_SUCCESS);
-}
-
-int
-__pthread_return_0 (void)
-{
-  return 0;
-}
-
-int
-__pthread_return_1 (void)
-{
-  return 1;
-}
-
-void
-__pthread_return_void (void)
-{
-}
--- libc/linuxthreads/Makefile.jj	2002-11-20 02:23:28.000000000 +0100
+++ libc/linuxthreads/Makefile	2002-12-17 23:00:41.000000000 +0100
@@ -26,20 +26,29 @@ linuxthreads-version := $(shell sed -n '
 
 headers := pthread.h semaphore.h
 distribute := internals.h queue.h restart.h spinlock.h smp.h tst-signal.sh \
-	      libc-tsd.c
+	      tst-cancel-wrappers.sh libc-tsd.c
 
-routines := weaks no-tsd
-shared-only-routines = weaks
+routines := forward no-tsd libc-cancellation libc_pthread_init
+shared-only-routines = forward
 
 extra-libs := libpthread
 extra-libs-others := $(extra-libs)
 
 libpthread-routines := attr cancel condvar join manager mutex ptfork \
 		       ptlongjmp pthread signals specific errno lockfile \
-		       semaphore spinlock wrapsyscall rwlock pt-machine \
+		       semaphore spinlock rwlock pt-machine \
 		       oldsemaphore events getcpuclockid pspinlock barrier \
 		       ptclock_gettime ptclock_settime sighandler \
-		       pthandles libc-tls-loc
+		       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
+
+libpthread-shared-only-routines = pt-allocrtsig
 
 nodelete-yes = -Wl,--enable-new-dtags,-z,nodelete
 initfirst-yes = -Wl,--enable-new-dtags,-z,initfirst
@@ -194,8 +203,13 @@ endif
 
 ifeq (no,$(cross-compiling))
 ifeq (yes,$(build-shared))
-tests: $(objpfx)tst-signal.out
+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 > $@
 endif
 endif
--- libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h.jj	2002-12-06 12:28:20.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h	2002-12-17 19:33:44.000000000 +0100
@@ -23,6 +23,10 @@
 
 #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;
@@ -90,19 +94,30 @@ typedef pthread_key_t __libc_key_t;
 #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
 
-#ifdef __PIC__
-# define __libc_maybe_call(FUNC, ARGS, ELSE) \
+#if defined _LIBC && defined IS_IN_libpthread
+# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
+#else
+# ifdef __PIC__
+#  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) \
+# else
+#  define __libc_maybe_call(FUNC, ARGS, ELSE) \
   (FUNC != NULL ? FUNC ARGS : ELSE)
+# endif
+#endif
+#if defined _LIBC && !defined NOT_IN_libc && defined __PIC__
+# define __libc_maybe_call2(FUNC, ARGS, ELSE) \
+  ({__libc_pthread_functions.ptr_##FUNC != NULL \
+    ? __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.  */
 #define __libc_lock_init(NAME) \
-  (__libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0))
+  (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
 #define __libc_rwlock_init(NAME) \
   (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
 
@@ -125,7 +140,7 @@ typedef pthread_key_t __libc_key_t;
    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_call (__pthread_mutex_destroy, (&(NAME)), 0));
+  (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
 #define __libc_rwlock_fini(NAME) \
   (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
 
@@ -135,7 +150,7 @@ typedef pthread_key_t __libc_key_t;
 
 /* Lock the named lock variable.  */
 #define __libc_lock_lock(NAME) \
-  (__libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0));
+  (__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) \
@@ -147,7 +162,7 @@ typedef pthread_key_t __libc_key_t;
 
 /* Try to lock the named lock variable.  */
 #define __libc_lock_trylock(NAME) \
-  (__libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0))
+  (__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) \
@@ -160,7 +175,7 @@ typedef pthread_key_t __libc_key_t;
 
 /* Unlock the named lock variable.  */
 #define __libc_lock_unlock(NAME) \
-  (__libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0));
+  (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
 #define __libc_rwlock_unlock(NAME) \
   (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
 
--- libc/linuxthreads/sysdeps/pthread/flockfile.c.jj	2002-12-17 19:35:07.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/flockfile.c	2002-12-17 13:56:28.000000000 +0100
@@ -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)
+strong_alias (__flockfile, flockfile)
--- libc/linuxthreads/sysdeps/pthread/ftrylockfile.c.jj	2002-12-17 19:35:14.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/ftrylockfile.c	2002-12-17 13:56:28.000000000 +0100
@@ -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)
--- libc/linuxthreads/sysdeps/pthread/funlockfile.c.jj	2002-12-17 19:35:17.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/funlockfile.c	2002-12-17 13:56:28.000000000 +0100
@@ -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)
--- libc/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h.jj	2002-12-16 18:50:42.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h	2002-12-17 18:40:28.000000000 +0100
@@ -0,0 +1,124 @@
+/* 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>
+#include <tls.h>
+#include <pt-machine.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#if defined FLOATING_STACKS && defined HAVE___THREAD
+# define MULTIPLE_THREADS_OFFSET	12
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# 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							      \
+    PUSHARGS_##args							      \
+    DOCARGS_##args							      \
+    movl $SYS_ify (syscall_name), %eax;					      \
+    int $0x80								      \
+    POPARGS_##args;							      \
+    POPCARGS_##args							      \
+    cmpl $-4095, %eax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+  L(pseudo_end):
+
+# define SAVE_OLDTYPE_0	movl %eax, %edx;
+# 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 DOCARGS_0	DOARGS_0
+# define DOCARGS_1	DOARGS_1
+# define DOCARGS_2	_DOARGS_2 (12)
+# define DOCARGS_3	_DOARGS_3 (20)
+# define DOCARGS_4	_DOARGS_4 (28)
+# define DOCARGS_5	_DOARGS_5 (36)
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel;
+#  define CDISABLE	call __pthread_disable_asynccancel
+# else
+#  define CENABLE	call __libc_enable_asynccancel;
+#  define CDISABLE	call __libc_disable_asynccancel
+# endif
+# define POPCARGS_0	pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax;
+# define POPCARGS_1	POPCARGS_0
+# define POPCARGS_2	xchgl (%esp), %eax; CDISABLE; popl %eax;
+# define POPCARGS_3	POPCARGS_2
+# define POPCARGS_4	POPCARGS_2
+# define POPCARGS_5	POPCARGS_2
+
+#if !defined NOT_IN_libc
+# define __local_multiple_threads __libc_multiple_threads
+#else
+# define __local_multiple_threads __pthread_multiple_threads
+#endif
+
+# ifndef ASSEMBLER
+#  if defined MULTIPLE_THREADS_OFFSET && 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 attribute_hidden;
+#   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 MULTIPLE_THREADS_OFFSET
+#   define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
+#  else
+#   if !defined HAVE_HIDDEN || !USE___THREAD
+#    define SINGLE_THREAD_P \
+  SETUP_PIC_REG (cx);				\
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;		\
+  cmpl $0, __local_multiple_threads@GOTOFF(%ecx)
+#   else
+#    define SINGLE_THREAD_P \
+  call __i686.get_pc_thunk.cx;			\
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;		\
+  cmpl $0, __local_multiple_threads@GOTOFF(%ecx)
+#   endif
+#  endif
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h.jj	2002-12-17 16:50:16.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h	2002-12-17 17:51:28.000000000 +0100
@@ -0,0 +1,118 @@
+/* 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>
+#include <tls.h>
+#include <pt-machine.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# 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):							      \
+    SAVESTK_##args							      \
+    PUSHARGS_##args							      \
+    CENABLE								      \
+    POPARGS_##args							      \
+    movq %rax, OLDTYPE_##args;						      \
+    movq $SYS_ify (syscall_name), %rax;					      \
+    syscall;								      \
+    xchgq %rax, OLDTYPE_##args;						      \
+    CDISABLE								      \
+    movq OLDTYPE_##args, %rax;						      \
+    RESTSTK_##args							      \
+    cmpq $-4095, %rax;							      \
+    jae SYSCALL_ERROR_LABEL;						      \
+  L(pseudo_end):
+
+# define PUSHARGS_0	/* Nothing.  */
+# define PUSHARGS_1	PUSHARGS_0 movq %rdi, (%rsp);
+# define PUSHARGS_2	PUSHARGS_1 movq %rsi, 8(%rsp);
+# define PUSHARGS_3	PUSHARGS_2 movq %rdx, 16(%rsp);
+# define PUSHARGS_4	PUSHARGS_3 movq %rcx, 24(%rsp);
+# define PUSHARGS_5	PUSHARGS_4 movq %r8, 32(%rsp);
+# define PUSHARGS_6	PUSHARGS_5 movq %r9, 40(%rsp);
+
+# define POPARGS_0	/* Nothing.  */
+# define POPARGS_1	POPARGS_0 movq (%rsp), %rdi;
+# define POPARGS_2	POPARGS_1 movq 8(%rsp), %rsi;
+# define POPARGS_3	POPARGS_2 movq 16(%rsp), %rdx;
+# define POPARGS_4	POPARGS_3 movq 24(%rsp), %r10;
+# define POPARGS_5	POPARGS_4 movq 32(%rsp), %r8;
+# define POPARGS_6	POPARGS_5 movq 40(%rsp), %r9;
+
+# define SAVESTK_0	/* Nothing.  */
+# define SAVESTK_1	subq $16, %rsp;
+# define SAVESTK_2	SAVESTK_1;
+# define SAVESTK_3	subq $32, %rsp;
+# define SAVESTK_4	SAVESTK_3;
+# define SAVESTK_5	subq $48, %rsp;
+# define SAVESTK_6	subq $64, %rsp;
+
+# define RESTSTK_0	/* Nothing.  */
+# define RESTSTK_1	addq $16, %rsp;
+# define RESTSTK_2	RESTSTK_1;
+# define RESTSTK_3	addq $32, %rsp;
+# define RESTSTK_4	RESTSTK_3;
+# define RESTSTK_5	addq $48, %rsp;
+# define RESTSTK_6	addq $64, %rsp;
+
+# define OLDTYPE_0	%r9
+# define OLDTYPE_1	OLDTYPE_0
+# define OLDTYPE_2	OLDTYPE_0
+# define OLDTYPE_3	OLDTYPE_0
+# define OLDTYPE_4	OLDTYPE_0
+# define OLDTYPE_5	OLDTYPE_0
+# define OLDTYPE_6	48(%rsp)
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel;
+#  define CDISABLE	call __pthread_disable_asynccancel;
+#  define __local_multiple_threads __pthread_multiple_threads
+# else
+#  define CENABLE	call __libc_enable_asynccancel;
+#  define CDISABLE	call __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
+#  define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c.jj	2002-12-17 13:29:10.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c	2002-12-17 13:31:18.000000000 +0100
@@ -0,0 +1,85 @@
+/* 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);
+
+/* 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);
+
+/* 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);
--- libc/linuxthreads/libc-cancellation.c.jj	2002-12-16 17:18:39.000000000 +0100
+++ libc/linuxthreads/libc-cancellation.c	2002-12-17 20:37:48.000000000 +0100
@@ -0,0 +1,61 @@
+/* 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;
+
+/* 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 = 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)
+    __libc_maybe_call2 (pthread_do_exit,
+			(PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0);
+  return oldtype;
+}
+
+void
+internal_function attribute_hidden
+__libc_disable_asynccancel (int oldtype)
+{
+  pthread_descr self = thread_self();
+  THREAD_SETMEM(self, p_canceltype, oldtype);
+}
+
+#endif
--- libc/linuxthreads/cancel.c.jj	2002-08-03 05:51:30.000000000 +0200
+++ libc/linuxthreads/cancel.c	2002-12-17 21:46:34.000000000 +0100
@@ -30,7 +30,7 @@
 #endif
 
 
-int pthread_setcancelstate(int state, int * oldstate)
+int __pthread_setcancelstate(int state, int * oldstate)
 {
   pthread_descr self = thread_self();
   if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE)
@@ -43,8 +43,9 @@ int pthread_setcancelstate(int state, in
     __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
   return 0;
 }
+strong_alias (__pthread_setcancelstate, pthread_setcancelstate);
 
-int pthread_setcanceltype(int type, int * oldtype)
+int __pthread_setcanceltype(int type, int * oldtype)
 {
   pthread_descr self = thread_self();
   if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
@@ -57,6 +58,33 @@ int pthread_setcanceltype(int type, int 
     __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)
 {
@@ -210,14 +238,3 @@ void __pthread_perform_cleanup(char *cur
     __rpc_thread_destroy ();
 #endif
 }
-
-#ifndef SHARED
-/* We need a hook to force the cancelation wrappers and file locking
-   to be linked in when static libpthread is used.  */
-extern const int __pthread_provide_wrappers;
-static const int *const __pthread_require_wrappers =
-  &__pthread_provide_wrappers;
-extern const int __pthread_provide_lockfile;
-static const int *const __pthread_require_lockfile =
-  &__pthread_provide_lockfile;
-#endif
--- libc/linuxthreads/pthread.c.jj	2002-12-06 12:12:48.000000000 +0100
+++ libc/linuxthreads/pthread.c	2002-12-17 22:48:19.000000000 +0100
@@ -33,12 +33,11 @@
 #include "smp.h"
 #include <ldsodefs.h>
 #include <tls.h>
-#include <locale.h>		/* for __uselocale */
 #include <version.h>
 
 /* Sanity check.  */
-#if __ASSUME_REALTIME_SIGNALS && !defined __SIGRTMIN
-# error "This must not happen; new kernel assumed but old headers"
+#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3
+# error "This must not happen"
 #endif
 
 #if !(USE_TLS && HAVE___THREAD)
@@ -86,6 +85,7 @@ struct _pthread_descr_struct __pthread_i
 #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)
@@ -116,6 +116,8 @@ char *__pthread_initial_thread_bos;
 
 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;
@@ -177,109 +179,38 @@ static void pthread_handle_sigdebug(int 
    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.  */
-#ifndef __SIGRTMIN
-static int current_rtmin = -1;
-static int current_rtmax = -1;
-int __pthread_sig_restart = SIGUSR1;
-int __pthread_sig_cancel = SIGUSR2;
-int __pthread_sig_debug;
-#else
-static int current_rtmin;
-static int current_rtmax;
-
-#if __SIGRTMAX - __SIGRTMIN >= 3
 int __pthread_sig_restart = __SIGRTMIN;
 int __pthread_sig_cancel = __SIGRTMIN + 1;
 int __pthread_sig_debug = __SIGRTMIN + 2;
-#else
-int __pthread_sig_restart = SIGUSR1;
-int __pthread_sig_cancel = SIGUSR2;
-int __pthread_sig_debug;
-#endif
 
-static int rtsigs_initialized;
+extern int __libc_current_sigrtmin_private (void);
 
 #if !__ASSUME_REALTIME_SIGNALS
-# include "testrtsig.h"
-#endif
+static int rtsigs_initialized;
 
 static void
 init_rtsigs (void)
 {
-#if !__ASSUME_REALTIME_SIGNALS
-  if (__builtin_expect (!kernel_has_rtsig (), 0))
+  if (rtsigs_initialized)
+    return;
+
+  if (__builtin_expect (__libc_current_sigrtmin_private () == -1))
     {
-      current_rtmin = -1;
-      current_rtmax = -1;
-# if __SIGRTMAX - __SIGRTMIN >= 3
       __pthread_sig_restart = SIGUSR1;
       __pthread_sig_cancel = SIGUSR2;
       __pthread_sig_debug = 0;
-# endif
     }
   else
-#endif	/* __ASSUME_REALTIME_SIGNALS */
     {
-#if __SIGRTMAX - __SIGRTMIN >= 3
-      current_rtmin = __SIGRTMIN + 3;
-# if !__ASSUME_REALTIME_SIGNALS
       __pthread_restart = __pthread_restart_new;
       __pthread_suspend = __pthread_wait_for_restart_signal;
       __pthread_timedsuspend = __pthread_timedsuspend_new;
-# endif /* __ASSUME_REALTIME_SIGNALS */
-#else
-      current_rtmin = __SIGRTMIN;
-#endif
-
-      current_rtmax = __SIGRTMAX;
     }
 
   rtsigs_initialized = 1;
 }
 #endif
 
-/* Return number of available real-time signal with highest priority.  */
-int
-__libc_current_sigrtmin (void)
-{
-#ifdef __SIGRTMIN
-  if (__builtin_expect (!rtsigs_initialized, 0))
-    init_rtsigs ();
-#endif
-  return current_rtmin;
-}
-
-/* Return number of available real-time signal with lowest priority.  */
-int
-__libc_current_sigrtmax (void)
-{
-#ifdef __SIGRTMIN
-  if (__builtin_expect (!rtsigs_initialized, 0))
-    init_rtsigs ();
-#endif
-  return current_rtmax;
-}
-
-/* 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)
-{
-#ifndef __SIGRTMIN
-  return -1;
-#else
-  if (__builtin_expect (!rtsigs_initialized, 0))
-    init_rtsigs ();
-  if (__builtin_expect (current_rtmin == -1, 0)
-      || __builtin_expect (current_rtmin > current_rtmax, 0))
-    /* We don't have anymore signal available.  */
-    return -1;
-
-  return high ? current_rtmin++ : current_rtmax--;
-#endif
-}
-
 
 /* Initialize the pthread library.
    Initialization is split in two functions:
@@ -299,6 +230,49 @@ extern void *__dso_handle __attribute__ 
 extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
 #endif
 
+#ifdef SHARED
+static struct pthread_functions pthread_functions =
+  {
+    .ptr_pthread_attr_destroy = __pthread_attr_destroy,
+    .ptr_pthread_attr_init_2_0 = __pthread_attr_init_2_0,
+    .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_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
+  };
+# 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.  */
@@ -413,11 +387,7 @@ cannot allocate TLS data structures for 
 # endif
 #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
+  __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions);
 }
 
 
@@ -520,7 +490,7 @@ static void pthread_initialize(void)
   /* Likewise for the resolver state _res.  */
   __pthread_initial_thread.p_resp = &_res;
 #endif
-#ifdef __SIGRTMIN
+#if !__ASSUME_REALTIME_SIGNALS
   /* Initialize real-time signals. */
   init_rtsigs ();
 #endif
@@ -577,6 +547,15 @@ int __pthread_initialize_manager(void)
   int report_events;
   pthread_descr tcb;
 
+  __pthread_multiple_threads = 1;
+  __pthread_main_thread->p_header.data.multiple_threads = 1;
+  * __libc_multiple_threads_ptr = 1;
+#ifdef MULTIPLE_THREADS_OFFSET
+  if (offsetof(struct _pthread_descr_struct, p_header.data.multiple_threads)
+      != MULTIPLE_THREADS_OFFSET)
+    abort ();
+#endif
+
 #ifndef HAVE_Z_NODELETE
   if (__builtin_expect (&__dso_handle != NULL, 1))
     __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,
@@ -613,6 +592,7 @@ int __pthread_initialize_manager(void)
   /* Initialize the descriptor.  */
   tcb->p_header.data.tcb = tcb;
   tcb->p_header.data.self = tcb;
+  tcb->p_header.data.multiple_threads = 1;
   tcb->p_lock = &__pthread_handles[1].h_lock;
 # ifndef HAVE___THREAD
   tcb->p_errnop = &tcb->p_errno;
@@ -797,16 +777,18 @@ compat_symbol (libpthread, __pthread_cre
 
 /* Simple operations on thread identifiers */
 
-pthread_t pthread_self(void)
+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)
+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 */
 
@@ -849,8 +831,8 @@ static pthread_descr thread_self_stack(v
 
 /* Thread scheduling */
 
-int pthread_setschedparam(pthread_t thread, int policy,
-                          const struct sched_param *param)
+int __pthread_setschedparam(pthread_t thread, int policy,
+                            const struct sched_param *param)
 {
   pthread_handle handle = thread_handle(thread);
   pthread_descr th;
@@ -872,9 +854,10 @@ int pthread_setschedparam(pthread_t thre
     __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)
+int __pthread_getschedparam(pthread_t thread, int *policy,
+                            struct sched_param *param)
 {
   pthread_handle handle = thread_handle(thread);
   int pid, pol;
@@ -892,6 +875,7 @@ int pthread_getschedparam(pthread_t thre
   *policy = pol;
   return 0;
 }
+strong_alias (__pthread_getschedparam, pthread_getschedparam);
 
 int __pthread_yield (void)
 {
@@ -1319,15 +1303,3 @@ void __pthread_message(const char * fmt,
 }
 
 #endif
-
-
-#ifndef SHARED
-/* We need a hook to force the cancelation wrappers and file locking
-   to be linked in when static libpthread is used.  */
-extern const int __pthread_provide_wrappers;
-static const int *const __pthread_require_wrappers =
-  &__pthread_provide_wrappers;
-extern const int __pthread_provide_lockfile;
-static const int *const __pthread_require_lockfile =
-  &__pthread_provide_lockfile;
-#endif
--- libc/linuxthreads/internals.h.jj	2002-09-20 22:04:23.000000000 +0200
+++ libc/linuxthreads/internals.h	2002-12-17 17:15:02.000000000 +0100
@@ -294,6 +294,24 @@ extern int __pthread_attr_setstack (pthr
 				    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,
@@ -305,6 +323,36 @@ extern int __pthread_mutexattr_setpshare
 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_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 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);
@@ -339,7 +387,6 @@ extern int __pthread_spin_destroy (pthre
 extern int __pthread_clock_gettime (hp_timing_t freq, struct timespec *tp);
 extern void __pthread_clock_settime (hp_timing_t offset);
 
-
 /* Global pointers to old or new suspend functions */
 
 extern void (*__pthread_restart)(pthread_descr);
@@ -386,4 +433,76 @@ extern void __pthread_sighandler_rt(int 
 				    struct ucontext *uc);
 extern void __pthread_null_sighandler(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;
+
+#if !defined NOT_IN_libc
+# define LIBC_CANCEL_ASYNC() \
+  __libc_enable_asynccancel ()
+# define LIBC_CANCEL_RESET(oldtype) \
+  __libc_disable_asynccancel (oldtype)
+#elif defined NOT_IN_libc && defined IS_IN_libpthread
+# define LIBC_CANCEL_ASYNC() \
+  __pthread_enable_asynccancel ()
+# define LIBC_CANCEL_RESET(oldtype) \
+  __pthread_disable_asynccancel (oldtype)
+#else
+# define LIBC_CANCEL_ASYNC()    0 /* Just a dummy value.  */
+# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it.  */
+#endif
+
+/* Data type shared with libc.  The libc uses it to pass on calls to
+   the thread functions.  */
+struct pthread_functions
+{
+  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);
+};
+
+/* Variable in libc.so.  */
+extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+extern int * __libc_pthread_init (const struct pthread_functions *functions);
+
 #endif /* internals.h */
--- libc/linuxthreads/descr.h.jj	2002-10-09 11:10:55.000000000 +0200
+++ libc/linuxthreads/descr.h	2002-12-16 19:23:06.000000000 +0100
@@ -106,6 +106,7 @@ struct _pthread_descr_struct {
 				   the address of this thread descriptor.  */
       union dtv *dtvp;
       pthread_descr self;	/* Pointer to this structure */
+      int multiple_threads;
     } data;
     void *__padding[16];
   } p_header;
--- libc/linuxthreads/manager.c.jj	2002-10-22 18:08:23.000000000 +0200
+++ libc/linuxthreads/manager.c	2002-12-16 20:12:18.000000000 +0100
@@ -633,6 +633,7 @@ static int pthread_handle_create(pthread
      initialized to zero already have this value.  */
   new_thread->p_header.data.tcb = new_thread;
   new_thread->p_header.data.self = new_thread;
+  new_thread->p_header.data.multiple_threads = 1;
   new_thread->p_tid = new_thread_id;
   new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
   new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
--- libc/linuxthreads/forward.c.jj	2002-12-16 20:15:56.000000000 +0100
+++ libc/linuxthreads/forward.c	2002-12-17 12:57:46.000000000 +0100
@@ -0,0 +1,146 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <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;
+
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+# define FORWARD4(name, export, rettype, decl, params, defaction, version) \
+rettype									      \
+__noexport_##name decl							      \
+{									      \
+  if (__libc_pthread_functions.ptr_##name == NULL)			      \
+    defaction;								      \
+									      \
+  return __libc_pthread_functions.ptr_##name params;			      \
+}									      \
+compat_symbol (libc, __noexport_##name, export, version)
+
+# define FORWARD3(name, rettype, decl, params, defaction, version) \
+  FORWARD4 (name, name, rettype, decl, params, defaction, version)
+
+# define FORWARD2(name, decl, params, defretval, version) \
+  FORWARD3 (name, int, decl, params, return defretval, version)
+
+# define FORWARD(name, decl, params, defretval) \
+  FORWARD2 (name, decl, params, defretval, GLIBC_2_0)
+
+
+FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1)
+FORWARD4 (pthread_attr_init_2_0, pthread_attr_init, int,
+	  (pthread_attr_t *attr), (attr), 0, GLIBC_2_0);
+#endif
+
+FORWARD4 (pthread_attr_init_2_1, pthread_attr_init, int,
+	  (pthread_attr_t *attr), (attr), 0, 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);
+
+FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0);
+
+FORWARD (pthread_cond_init,
+	 (pthread_cond_t *cond, const pthread_condattr_t *cond_attr),
+	 (cond, cond_attr), 0);
+
+FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0);
+
+FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex),
+	 (cond, mutex), 0);
+
+
+FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
+	 (thread1, thread2), 1);
+
+
+FORWARD3 (pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS),
+	  GLIBC_2_0);
+
+
+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);
+
+
+FORWARD3 (pthread_self, pthread_t, (void), (), return 0, GLIBC_2_0);
+
+
+FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate),
+	 0);
+
+FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0);
+
+
+#endif
--- libc/linuxthreads/condvar.c.jj	2001-04-10 23:07:55.000000000 +0200
+++ libc/linuxthreads/condvar.c	2002-12-17 01:03:27.000000000 +0100
@@ -25,19 +25,21 @@
 #include "queue.h"
 #include "restart.h"
 
-int pthread_cond_init(pthread_cond_t *cond,
-                      const pthread_condattr_t *cond_attr)
+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;
 }
+strong_alias (__pthread_cond_init, pthread_cond_init)
 
-int pthread_cond_destroy(pthread_cond_t *cond)
+int __pthread_cond_destroy(pthread_cond_t *cond)
 {
   if (cond->__c_waiting != NULL) return EBUSY;
   return 0;
 }
+strong_alias (__pthread_cond_destroy, pthread_cond_destroy)
 
 /* Function called by pthread_cancel to remove the thread from
    waiting on a condition variable queue. */
@@ -55,7 +57,7 @@ static int cond_extricate_func(void *obj
   return did_remove;
 }
 
-int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
   volatile pthread_descr self = thread_self();
   pthread_extricate_if extr;
@@ -132,6 +134,7 @@ int pthread_cond_wait(pthread_cond_t *co
   pthread_mutex_lock(mutex);
   return 0;
 }
+strong_alias (__pthread_cond_wait, pthread_cond_wait)
 
 static int
 pthread_cond_timedwait_relative(pthread_cond_t *cond,
@@ -234,7 +237,7 @@ int pthread_cond_timedwait(pthread_cond_
   return pthread_cond_timedwait_relative(cond, mutex, abstime);
 }
 
-int pthread_cond_signal(pthread_cond_t *cond)
+int __pthread_cond_signal(pthread_cond_t *cond)
 {
   pthread_descr th;
 
@@ -248,8 +251,9 @@ int pthread_cond_signal(pthread_cond_t *
   }
   return 0;
 }
+strong_alias (__pthread_cond_signal, pthread_cond_signal)
 
-int pthread_cond_broadcast(pthread_cond_t *cond)
+int __pthread_cond_broadcast(pthread_cond_t *cond)
 {
   pthread_descr tosignal, th;
 
@@ -266,16 +270,19 @@ int pthread_cond_broadcast(pthread_cond_
   }
   return 0;
 }
+strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast)
 
-int pthread_condattr_init(pthread_condattr_t *attr)
+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)
+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)
 {
--- libc/linuxthreads/join.c.jj	2001-09-12 05:51:41.000000000 +0200
+++ libc/linuxthreads/join.c	2002-12-17 01:09:22.000000000 +0100
@@ -23,10 +23,11 @@
 #include "spinlock.h"
 #include "restart.h"
 
-void pthread_exit(void * retval)
+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)
 {
--- libc/linuxthreads/attr.c.jj	2002-02-24 05:51:50.000000000 +0100
+++ libc/linuxthreads/attr.c	2002-12-17 01:27:41.000000000 +0100
@@ -56,12 +56,13 @@ compat_symbol (libpthread, __pthread_att
 	       GLIBC_2_0);
 #endif
 
-int pthread_attr_destroy(pthread_attr_t *attr)
+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)
+int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
 {
   if (detachstate < PTHREAD_CREATE_JOINABLE ||
       detachstate > PTHREAD_CREATE_DETACHED)
@@ -69,15 +70,17 @@ int pthread_attr_setdetachstate(pthread_
   attr->__detachstate = detachstate;
   return 0;
 }
+strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate);
 
-int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
+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 __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);
@@ -87,43 +90,49 @@ int pthread_attr_setschedparam(pthread_a
   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)
+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)
+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)
+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)
+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)
+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)
+int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
 {
   switch (scope) {
   case PTHREAD_SCOPE_SYSTEM:
@@ -135,12 +144,14 @@ int pthread_attr_setscope(pthread_attr_t
     return EINVAL;
   }
 }
+strong_alias (__pthread_attr_setscope, pthread_attr_setscope);
 
-int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
+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)
 {
--- libc/linuxthreads/mutex.c.jj	2001-05-24 09:22:39.000000000 +0200
+++ libc/linuxthreads/mutex.c	2002-12-17 15:49:27.000000000 +0100
@@ -36,6 +36,7 @@ int __pthread_mutex_init(pthread_mutex_t
   return 0;
 }
 strong_alias (__pthread_mutex_init, pthread_mutex_init)
+hidden_def (__pthread_mutex_init)
 
 int __pthread_mutex_destroy(pthread_mutex_t * mutex)
 {
@@ -55,6 +56,7 @@ int __pthread_mutex_destroy(pthread_mute
   }
 }
 strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
+hidden_def (__pthread_mutex_destroy)
 
 int __pthread_mutex_trylock(pthread_mutex_t * mutex)
 {
@@ -91,6 +93,7 @@ int __pthread_mutex_trylock(pthread_mute
   }
 }
 strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
+hidden_def (__pthread_mutex_trylock)
 
 int __pthread_mutex_lock(pthread_mutex_t * mutex)
 {
@@ -124,6 +127,7 @@ int __pthread_mutex_lock(pthread_mutex_t
   }
 }
 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)
@@ -199,6 +203,7 @@ int __pthread_mutex_unlock(pthread_mutex
   }
 }
 strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
+hidden_def (__pthread_mutex_unlock)
 
 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
 {
--- libc/linuxthreads/libc_pthread_init.c.jj	2002-12-17 01:38:10.000000000 +0100
+++ libc/linuxthreads/libc_pthread_init.c	2002-12-17 18:12:37.000000000 +0100
@@ -0,0 +1,53 @@
+/* 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 <string.h>
+#include <tls.h>
+#include <locale.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
+
+#ifdef MULTIPLE_THREADS_OFFSET
+  /* We have a macro which is used in asm code describing data layout.
+     Make sure it does not get out of date.  */
+  if (offsetof (struct _pthread_descr_struct, p_header.data.multiple_threads)
+      != MULTIPLE_THREADS_OFFSET)
+    abort ();
+#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;
+}
--- libc/linuxthreads/pt-system.c.jj	2002-12-17 02:07:35.000000000 +0100
+++ libc/linuxthreads/pt-system.c	2002-12-17 02:08:42.000000000 +0100
@@ -0,0 +1,32 @@
+/* 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 <stdlib.h>
+#include <sysdep-cancel.h>
+
+
+int
+system (const char *line)
+{
+  int oldtype = LIBC_CANCEL_ASYNC ();
+  int result = __libc_system (line);
+  LIBC_CANCEL_RESET (oldtype);
+  return result;
+}
--- libc/linuxthreads/Versions.jj	2002-12-15 22:44:21.000000000 +0100
+++ libc/linuxthreads/Versions	2002-12-17 18:55:36.000000000 +0100
@@ -22,6 +22,9 @@ libc {
     __libc_internal_tsd_address; __libc_alloca_cutoff;
     __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;
--- libc/linuxthreads/lockfile.c.jj	2002-12-16 14:17:15.000000000 +0100
+++ libc/linuxthreads/lockfile.c	2002-12-17 15:55:03.000000000 +0100
@@ -21,80 +21,51 @@
 #include <stdio.h>
 #include <pthread.h>
 #include "internals.h"
-
-#ifdef USE_IN_LIBIO
 #include "../libio/libioP.h"
-#endif
-
-#ifndef SHARED
-/* We need a hook to force this file to be linked in when static
-   libpthread is used.  */
-const int __pthread_provide_lockfile = 0;
-#endif
 
 void
 __flockfile (FILE *stream)
 {
-#ifdef USE_IN_LIBIO
   __pthread_mutex_lock (stream->_lock);
-#else
-#endif
 }
-#ifdef USE_IN_LIBIO
 #undef _IO_flockfile
 strong_alias (__flockfile, _IO_flockfile)
-#endif
 weak_alias (__flockfile, flockfile);
 
 
 void
 __funlockfile (FILE *stream)
 {
-#ifdef USE_IN_LIBIO
   __pthread_mutex_unlock (stream->_lock);
-#else
-#endif
 }
-#ifdef USE_IN_LIBIO
 #undef _IO_funlockfile
 strong_alias (__funlockfile, _IO_funlockfile)
-#endif
 weak_alias (__funlockfile, funlockfile);
 
 
 int
 __ftrylockfile (FILE *stream)
 {
-#ifdef USE_IN_LIBIO
   return __pthread_mutex_trylock (stream->_lock);
-#else
-#endif
 }
-#ifdef USE_IN_LIBIO
 strong_alias (__ftrylockfile, _IO_ftrylockfile)
-#endif
 weak_alias (__ftrylockfile, ftrylockfile);
 
 void
 __flockfilelist(void)
 {
-#ifdef USE_IN_LIBIO
   _IO_list_lock();
-#endif
 }
 
 void
 __funlockfilelist(void)
 {
-#ifdef USE_IN_LIBIO
   _IO_list_unlock();
-#endif
 }
 
 void
 __fresetlockfiles (void)
 {
-#ifdef USE_IN_LIBIO
   _IO_ITER i;
 
   pthread_mutexattr_t attr;
@@ -112,5 +83,4 @@ __fresetlockfiles (void)
   __pthread_mutexattr_destroy (&attr);
 
   _IO_list_resetlock();
-#endif
 }
--- libc/linuxthreads/tst-cancel-wrappers.sh.jj	2002-12-17 22:02:39.000000000 +0100
+++ libc/linuxthreads/tst-cancel-wrappers.sh	2002-12-17 22:04:55.000000000 +0100
@@ -0,0 +1,96 @@
+#! /bin/sh
+# Test whether all cancellable functions are cancellable.
+# 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.
+
+while [ $# -gt 0 ]; do
+  ( nm -P $1; echo 'end[end]:' ) | awk ' BEGIN {
+C["accept"]=1
+C["close"]=1
+C["connect"]=1
+C["creat"]=1
+C["fcntl"]=1
+C["fsync"]=1
+C["llseek"]=1
+C["lseek"]=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)
+    {
+      # signals.c in linuxthreads does the cancellation checks not using
+      # *_{enable,disable}_asynccancel.
+      if ((!seen_enable || !seen_disable) && !(object ~ /^signals.o/))
+	{
+	  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
--- libc/linuxthreads/pt-allocrtsig.c.jj	2002-12-17 22:48:39.000000000 +0100
+++ libc/linuxthreads/pt-allocrtsig.c	2002-11-26 23:49:48.000000000 +0100
@@ -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);
+}
--- libc/malloc/thread-m.h.jj	2002-12-17 16:30:43.000000000 +0100
+++ libc/malloc/thread-m.h	2002-12-17 16:30:02.000000000 +0100
@@ -35,21 +35,42 @@
 
 #ifdef PTHREAD_MUTEX_INITIALIZER
 
-/* mutex */
 __libc_lock_define (typedef, mutex_t)
 
-/* Even if not linking with libpthread, ensure usability of mutex as
-   an `in use' flag, see also the NO_THREADS case below.  Assume
-   pthread_mutex_t is at least one int wide.  */
+#if defined(LLL_LOCK_INITIALIZER) && !defined(NOT_IN_libc)
+
+/* Assume NPTL.  */
+
+#define mutex_init(m)		__libc_lock_init (*(m))
+#define mutex_lock(m)		__libc_lock_lock (*(m))
+#define mutex_trylock(m)	__libc_lock_trylock (*(m))
+#define mutex_unlock(m)		__libc_lock_unlock (*(m))
+
+#elif defined(__libc_maybe_call2)
 
 #define mutex_init(m)		\
-  __libc_lock_init (*m)
+  __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
 #define mutex_lock(m)		\
-  __libc_lock_lock (*m)
+  __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
 #define mutex_trylock(m)	\
-  __libc_lock_trylock (*m)
+  __libc_maybe_call2 (pthread_mutex_trylock, (m), \
+		      (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
 #define mutex_unlock(m)		\
-  __libc_lock_unlock (*m)
+  __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0))
+
+#else
+
+#define mutex_init(m)		\
+  __libc_maybe_call (__pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
+#define mutex_lock(m)		\
+  __libc_maybe_call (__pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
+#define mutex_trylock(m)	\
+  __libc_maybe_call (__pthread_mutex_trylock, (m), \
+		     (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
+#define mutex_unlock(m)		\
+  __libc_maybe_call (__pthread_mutex_unlock, (m), (*(int *)(m) = 0))
+
+#endif
 
 #define thread_atfork(prepare, parent, child) \
    (__pthread_atfork != NULL ? __pthread_atfork(prepare, parent, child) : 0)
--- libc/sysdeps/unix/sysv/linux/x86_64/recv.c.jj	2001-09-19 12:31:31.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/x86_64/recv.c	2002-12-17 20:00:17.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -18,7 +18,7 @@
 
 #include <errno.h>
 #include <sys/socket.h>
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 
 /* Read N bytes into BUF from socket FD.
    Returns the number read or -1 for errors.  */
@@ -26,8 +26,16 @@
 ssize_t
 __libc_recv (int fd, void *buf, size_t n, int flags)
 {
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (recvfrom, 6, fd, buf, n, flags, NULL, NULL);
 
-  return INLINE_SYSCALL (recvfrom, 6, fd, buf, n, flags, NULL, NULL);
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = INLINE_SYSCALL (recvfrom, 6, fd, buf, n, flags, NULL, NULL);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 
 weak_alias (__libc_recv, __recv)
--- libc/sysdeps/unix/sysv/linux/x86_64/send.c.jj	2002-08-03 08:57:53.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/x86_64/send.c	2002-12-17 20:01:44.000000000 +0100
@@ -18,13 +18,22 @@
 
 #include <errno.h>
 #include <sys/socket.h>
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 
 /* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
 ssize_t
 __libc_send (int fd, const void *buf, size_t n, int flags)
 {
-  return INLINE_SYSCALL (sendto, 6, fd, buf, n, flags, NULL, NULL);
+  if (SINGLE_THREAD_P)
+    return INLINE_SYSCALL (sendto, 6, fd, buf, n, flags, NULL, NULL);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  ssize_t result = INLINE_SYSCALL (sendto, 6, fd, buf, n, flags, NULL, NULL);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
 }
 
 weak_alias (__libc_send, __send)
--- libc/nptl/tst-cancel-wrappers.sh.jj	2002-12-17 22:02:39.000000000 +0100
+++ libc/nptl/tst-cancel-wrappers.sh	2002-12-17 21:34:09.000000000 +0100
@@ -0,0 +1,94 @@
+#! /bin/sh
+# Test whether all cancellable functions are cancellable.
+# 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.
+
+while [ $# -gt 0 ]; do
+  ( nm -P $1; echo 'end[end]:' ) | awk ' BEGIN {
+C["accept"]=1
+C["close"]=1
+C["connect"]=1
+C["creat"]=1
+C["fcntl"]=1
+C["fsync"]=1
+C["llseek"]=1
+C["lseek"]=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
--- libc/nptl/Makefile.jj	2002-12-17 13:56:28.000000000 +0100
+++ libc/nptl/Makefile	2002-12-17 23:02:25.000000000 +0100
@@ -107,6 +107,8 @@ libpthread-routines = init events \
 		      herrno res pt-allocrtsig \
 		      pthread_kill_other_threads
 
+libpthread-shared-only-routines = pt-allocrtsig
+
 libpthread-nonshared = pthread_atfork
 
 
@@ -241,3 +243,14 @@ $(objpfx)crti.o: $(objpfx)crti.S $(objpf
 
 generated += crti.S defs.h pt-initfini.s
 endif
+
+ifeq (no,$(cross-compiling))
+ifeq (yes,$(build-shared))
+tests: $(objpfx)tst-cancel-wrappers.out
+$(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 > $@
+endif
+endif
--- libc/nptl/tst-locale1.c.jj	2002-12-03 07:01:38.000000000 +0100
+++ libc/nptl/tst-locale1.c	2002-12-17 22:59:45.000000000 +0100
@@ -4,10 +4,14 @@
 #include "../locale/tst-C-locale.c"
 
 #include <pthread.h>
+#include <signal.h>
 
 /* This is never called, just here to get pthreads linked in.  */
-void
+int
 useless (void)
 {
   pthread_create (0, 0, 0, 0);
+  /* This is to check __libc_current_sigrt* can be used in statically
+     linked apps.  */
+  return SIGRTMIN;
 }

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]