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]

Re: Allowing multiple threads packages, a new threads package


Thanks for the reply.  I'll do as you describe, although the patch is
over 1100 lines long, I hope that's ok.

This patch modifies libc to allow external threads packages to provide
their services (mutexes, condition variables, etc.) to libc.  In
include/bits/libc-lock.h, it defines some dummy data structures for
the thread data structures (the real ones must fit inside the dummy
ones).  It defines operations that the threads package must define
and uses weak references for these in case a threads package doesn't
exist.  Also, all the initializers for thread data structures are
removed.  This part is kind of yucky, it uses the .ctors section,
but maybe that's ok.

I think it's a good thing to allow multiple threads packages with
libc, I don't think a single threads package can meet the needs of all
applications.  This may not be the best way to handle what I want, but
hopefully this type of function can be added to glibc.  And I am
willing to work on whatever way comes out as best.

Thanks,

-Corey


2001-08-28  Corey Minyard <minyard@acm.org>

        * linuxthreads/sysdeps/pthread/bits/libc-lock.h:
        Converted from a __pthread based interface to a __libcThr
        interface and no longer use any pthread stuff for this.
        Define local data structures to hold thread data for
        mutexes, conds, etc.

	* linuxthreads/sysdeps/pthread/bits/stdio-lock.h:
	Converted over to use libc-lock.h for these locks.

        * linuxthreads/ptfork.c, linuxthreads/Versions, linuxthreads/join.c,
        linuxthreads/pthread.c, linuxthreads/mutex.c, linuxthreads/cancel.c,
        linuxthreads/specific.c, linuxthreads/rwlock.c,
        linuxthreads/lockfile.c, linuxthreads/condvar.c:
        Added aliases for all the __libcThr calls.

        * malloc/thread-m.h, malloc/malloc.c, iconv/gconv_conf.c,
        intl/dcigettext.c, sysdeps/generic/opensock.c, inet/getnameinfo.c,
        libio/stdfiles.c, libio/oldstdfiles.c, libio/genops.c:
        Fixed various mutex initialization problems, converted everything
        over to the thread operations defined in include/bits/libc-locks.h

        * Makefile: Added include/bits/libc-tsd.h to the set of things
        installed on the user system, so other threads packages can
        get at the keys in it.

        * elf/dl-open.c, elf/dl-close.c, elf/dl-lookup.c, elf/dl-misc.c,
        elf/Versions, elf/dl-support.c, elf/rtld.c:
        Fixed the dl_load_lock so it won't be used until after the
        system is initialized.

--- libio/stdfiles.corig2	Tue Aug 15 13:16:20 2000
+++ libio/stdfiles.c	Tue Apr 10 14:26:51 2001
@@ -35,7 +35,7 @@
 #ifdef _IO_MTSAFE_IO
 # if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
 #  define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
-  static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \
+  _IO_lock_define_initialized(static, _IO_stdfile_##FD##_lock); \
   static struct _IO_wide_data _IO_wide_data_##FD \
     = { ._wide_vtable = &_IO_wfile_jumps }; \
   struct _IO_FILE_plus NAME \
--- libio/oldstdfiles.corig2	Thu Jun 29 14:39:58 2000
+++ libio/oldstdfiles.c	Tue Apr 10 14:25:07 2001
@@ -37,7 +37,7 @@
 
 #ifdef _IO_MTSAFE_IO
 #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
-  static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \
+  _IO_lock_define_initialized(static, _IO_stdfile_##FD##_lock); \
   struct _IO_FILE_plus NAME \
     = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, NULL), &_IO_old_file_jumps};
 #else
--- libio/genops.corig2	Sun Oct  8 19:04:51 2000
+++ libio/genops.c	Tue Apr 10 14:25:07 2001
@@ -32,7 +32,7 @@
 #include <string.h>
 
 #ifdef _IO_MTSAFE_IO
-static _IO_lock_t list_all_lock = _IO_lock_initializer;
+_IO_lock_define_initialized(static, list_all_lock);
 #endif
 
 void
--- Makefileorig2	Tue Apr 10 14:04:38 2001
+++ Makefile	Tue Apr 10 14:25:07 2001
@@ -65,7 +65,7 @@
 
 headers := errno.h sys/errno.h bits/errno.h limits.h values.h	\
 	   features.h gnu-versions.h bits/libc-lock.h bits/xopen_lim.h	\
-	   gnu/libc-version.h
+	   bits/libc-tsd.h gnu/libc-version.h
 
 echo-headers: subdir_echo-headers
 
--- linuxthreads/ptfork.corig2	Fri Jun  9 14:17:35 2000
+++ linuxthreads/ptfork.c	Tue Apr 10 14:25:07 2001
@@ -113,3 +113,7 @@
   return __fork();
 }
 weak_alias (__vfork, vfork);
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (__pthread_atfork, __libcThr_atfork)
--- linuxthreads/Versionsorig2	Thu Sep 14 14:24:16 2000
+++ linuxthreads/Versions	Tue Apr 10 18:27:28 2001
@@ -154,5 +154,39 @@
 
     # New internal function.
     __pthread_initialize_minimal;
+
+    __libcThr_mutex_init;
+    __libcThr_mutex_destroy;
+    __libcThr_mutex_lock;
+    __libcThr_mutex_trylock;
+    __libcThr_mutex_unlock;
+    __libcThr_rwlock_init;
+    __libcThr_rwlock_destroy;
+    __libcThr_rwlock_rdlock;
+    __libcThr_rwlock_wrlock;
+    __libcThr_rwlock_tryrdlock;
+    __libcThr_rwlock_trywrlock;
+    __libcThr_rwlock_unlock;
+    __libcThr_key_create;
+    __libcThr_key_delete;
+    __libcThr_setspecific;
+    __libcThr_getspecific;
+    __libcThr_once;
+    __libcThr_init_threads;
+    __libcThr_atfork;
+    __libcThr_mutex_init_recursive_np;
+    _libcThr_cleanup_push_defer;
+    _libcThr_cleanup_pop_restore;
+    __libcThr_thread_create;
+    __libcThr_thread_detach;
+    __libcThr_thread_exit;
+    __libcThr_self;
+    __libcThr_getschedparam;
+    __libcThr_setschedparam;
+    __libcThr_cond_init;
+    __libcThr_cond_destroy;
+    __libcThr_cond_broadcast;
+    __libcThr_cond_signal;
+    __libcThr_cond_wait;
   }
 }
--- linuxthreads/join.corig2	Wed Jun 21 13:11:00 2000
+++ linuxthreads/join.c	Tue Apr 10 14:25:07 2001
@@ -210,3 +210,8 @@
   }
   return 0;
 }
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (pthread_detach, __libcThr_thread_detach)
+strong_alias (pthread_exit, __libcThr_thread_exit)
--- linuxthreads/pthread.corig2	Sun Oct  8 19:04:51 2000
+++ linuxthreads/pthread.c	Tue Apr 10 14:25:07 2001
@@ -1087,3 +1087,11 @@
 static const int *const __pthread_require_wrappers =
   &__pthread_provide_wrappers;
 #endif
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (__pthread_initialize, __libcThr_init_threads)
+strong_alias (__pthread_create_2_1, __libcThr_thread_create)
+strong_alias (pthread_self, __libcThr_self)
+strong_alias (pthread_getschedparam, __libcThr_getschedparam)
+strong_alias (pthread_setschedparam, __libcThr_setschedparam)
--- linuxthreads/mutex.corig2	Sun Oct  8 19:04:51 2000
+++ linuxthreads/mutex.c	Tue Apr 10 18:24:14 2001
@@ -350,3 +350,24 @@
   else
     fork_generation = 0;
 }
+
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (__pthread_mutex_init, __libcThr_mutex_init)
+strong_alias (__pthread_mutex_destroy, __libcThr_mutex_destroy)
+strong_alias (__pthread_mutex_lock, __libcThr_mutex_lock)
+strong_alias (__pthread_mutex_trylock, __libcThr_mutex_trylock)
+strong_alias (__pthread_mutex_unlock, __libcThr_mutex_unlock)
+strong_alias (__pthread_once, __libcThr_once)
+
+void
+__libcThr_mutex_init_recursive_np(pthread_mutex_t * mutex)
+{
+  pthread_mutexattr_t attr;
+
+  __pthread_mutexattr_init (&attr);
+  __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+  __pthread_mutex_init (mutex, &attr);
+  __pthread_mutexattr_destroy (&attr);                                
+}
--- linuxthreads/cancel.corig2	Wed Nov  8 16:10:17 2000
+++ linuxthreads/cancel.c	Tue Apr 10 14:25:07 2001
@@ -172,3 +172,8 @@
 static const int * const __pthread_require_wrappers =
   &__pthread_provide_wrappers;
 #endif
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (_pthread_cleanup_push_defer, _libcThr_cleanup_push_defer)
+strong_alias (_pthread_cleanup_pop_restore, _libcThr_cleanup_pop_restore)
--- linuxthreads/specific.corig2	Tue Oct 17 16:53:59 2000
+++ linuxthreads/specific.c	Tue Apr 10 14:25:07 2001
@@ -58,7 +58,7 @@
 
 /* Delete a key */
 
-int pthread_key_delete(pthread_key_t key)
+int __pthread_key_delete(pthread_key_t key)
 {
   pthread_descr self = thread_self();
   pthread_descr th;
@@ -91,6 +91,7 @@
   pthread_mutex_unlock(&pthread_keys_mutex);
   return 0;
 }
+strong_alias (__pthread_key_delete, pthread_key_delete)
 
 /* Set the value of a key */
 
@@ -189,3 +190,10 @@
 }
 void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
      = libc_internal_tsd_get;
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (__pthread_key_create, __libcThr_key_create)
+strong_alias (__pthread_key_delete, __libcThr_key_delete)
+strong_alias (__pthread_setspecific, __libcThr_setspecific)
+strong_alias (__pthread_getspecific, __libcThr_getspecific)
--- linuxthreads/sysdeps/pthread/bits/stdio-lock.horig2	Thu Sep  7 13:56:28 2000
+++ linuxthreads/sysdeps/pthread/bits/stdio-lock.h	Tue Apr 10 18:21:54 2001
@@ -17,21 +17,15 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <pthread.h>
+#include <bits/libc-lock.h>
 
-typedef pthread_mutex_t _IO_lock_t;
+typedef __libc_lock_t _IO_lock_t;
 
 /* We need recursive (counting) mutexes.  */
-#define _IO_lock_initializer PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
-
-
+#define _IO_lock_define_initialized(CLASS,_name) \
+     __libc_lock_define_initialized_recursive(CLASS,_name)
 #define _IO_cleanup_region_start(_fct, _fp) \
-  { struct _pthread_cleanup_buffer _buffer;				      \
-    int _avail = (((_fp)->_flags & _IO_USER_LOCK) == 0			      \
-		  && _pthread_cleanup_push_defer != NULL);		      \
-    if (_avail) {							      \
-      _pthread_cleanup_push_defer (&_buffer, (_fct), (_fp));		      \
-    }
+     __libc_cleanup_region_start(_fct, _fp)
 #define _IO_cleanup_region_end(_doit) \
      __libc_cleanup_region_end (_doit)
 #define _IO_lock_init(_name) \
--- linuxthreads/sysdeps/pthread/bits/libc-lock.horig2	Tue Oct 17 16:54:00 2000
+++ linuxthreads/sysdeps/pthread/bits/libc-lock.h	Tue Apr 10 20:53:00 2001
@@ -17,22 +17,110 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+/* This is a dynamic thread abstraction layer, it allows different
+   thread packages to be used with libc.  The threads package has to
+   supply the given functions and it's data structures must fit into
+   the given memory spaces, but that's it.  This is strongly POSIX
+   based (no big surprise :-) */
+ 
 #ifndef _BITS_LIBC_LOCK_H
 #define _BITS_LIBC_LOCK_H 1
 
-#include <pthread.h>
+#include <features.h>
+#include <stdlib.h>
 
-/* Mutex type.  */
-#ifdef _LIBC
-typedef pthread_mutex_t __libc_lock_t;
-typedef pthread_rwlock_t __libc_rwlock_t;
-#else
-typedef struct __libc_lock_opaque__ __libc_lock_t;
-typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
-#endif
+#include <sched.h>
+
+__BEGIN_DECLS
+
+/* Mutex and condition types.  */
+/* We reserve the space taken by 10 pointers for the mutex and
+   condition data structures. */
+typedef struct {
+   void *(data[10]);
+} __libc_lock_t;
+
+typedef struct {
+   void *(data[10]);
+} __libc_cond_t;
+
+typedef struct {
+   void *(data[10]);
+} __libc_rwlock_t;
+
+/* Type for key to thread-specific data */
+typedef unsigned int __libc_key_t;
+
+/* Define once control variable.  */
+typedef unsigned int __libc_once_t;
+
+/* Define a thread variable.  */
+typedef unsigned long int __libc_thread_t;
+
+/* Define a cleanup buffer, 8 pointers. */
+typedef struct {
+   void *(data[8]);
+} __libc_cleanup_t;
+
+/* The threads package must supply these functions. */
+int __libcThr_mutex_init(__libc_lock_t *, void *);
+int __libcThr_mutex_destroy(__libc_lock_t *);
+int __libcThr_mutex_lock(__libc_lock_t *);
+int __libcThr_mutex_trylock(__libc_lock_t *);
+int __libcThr_mutex_unlock(__libc_lock_t *);
+int __libcThr_rwlock_init(__libc_rwlock_t *, void *);
+int __libcThr_rwlock_destroy(__libc_rwlock_t *);
+int __libcThr_rwlock_rdlock(__libc_rwlock_t *);
+int __libcThr_rwlock_wrlock(__libc_rwlock_t *);
+int __libcThr_rwlock_tryrdlock(__libc_rwlock_t *);
+int __libcThr_rwlock_trywrlock(__libc_rwlock_t *);
+int __libcThr_rwlock_unlock(__libc_rwlock_t *);
+int __libcThr_key_create(__libc_key_t *, void (*destructor)(void *));
+int __libcThr_key_delete(__libc_key_t);
+int __libcThr_setspecific(__libc_key_t, const void *data);
+void * __libcThr_getspecific(__libc_key_t);
+int __libcThr_once(__libc_once_t *, void (*once_routine)(void));
+void __libcThr_init_threads(void);
+int __libcThr_atfork(void (*prepare)(void),
+                     void (*parent)(void),
+                     void (*child)(void));
+int __libcThr_mutex_init_recursive_np(__libc_lock_t *);
+void _libcThr_cleanup_push_defer(__libc_cleanup_t * buffer,
+                                 void (*routine)(void *), void * arg);
+void _libcThr_cleanup_pop_restore(__libc_cleanup_t * buffer, int execute);
+
+int __libcThr_thread_create(__libc_thread_t *, void *, void *(*) (void *), void *);
+int __libcThr_thread_detach(__libc_thread_t);
+void __libcThr_thread_exit(void *);
+__libc_thread_t __libcThr_self(void);
+int __libcThr_getschedparam(__libc_thread_t, int *, struct sched_param *);
+int __libcThr_setschedparam(__libc_thread_t, int, struct sched_param *);
+
+int __libcThr_cond_init(__libc_cond_t *, void *);
+int __libcThr_cond_destroy(__libc_cond_t *);
+int __libcThr_cond_broadcast(__libc_cond_t *);
+int __libcThr_cond_signal(__libc_cond_t *);
+int __libcThr_cond_wait(__libc_cond_t *, __libc_lock_t *);
+
+
+#define __libc_init_threads() \
+  (__libcThr_init_threads != NULL ? __libcThr_init_threads () : 0)
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+   state.  */
+#define __libc_lock_init(NAME) \
+  (__libcThr_mutex_init != NULL ? __libcThr_mutex_init (&(NAME), NULL) : 0)
 
-/* Type for key to thread-specific data.  */
-typedef pthread_key_t __libc_key_t;
+/* Initialize the named rwlock variable, leaving it in a consistent, unlocked
+   state.  */
+#define __libc_rwlock_init(NAME) \
+  (__libcThr_rwlock_init != NULL ? __libcThr_rwlock_init (&(NAME), NULL) : 0)
+
+/* Same as last but this time we initialize a recursive mutex.  */
+#define __libc_lock_init_recursive(NAME) \
+  if (__libcThr_mutex_init_recursive_np != NULL) {			      \
+    __libcThr_mutex_init_recursive_np(&(NAME));				      \
+  }
 
 /* Define a lock variable NAME with storage class CLASS.  The lock must be
    initialized with __libc_lock_init before it can be used (or define it
@@ -41,6 +128,7 @@
    definitions you must use a pointer to the lock structure (i.e., NAME
    begins with a `*'), because its storage size will not be known outside
    of libc.  */
+/* This assumes that "0" is the default initializer. */
 #define __libc_lock_define(CLASS,NAME) \
   CLASS __libc_lock_t NAME;
 #define __libc_rwlock_define(CLASS,NAME) \
@@ -55,204 +143,170 @@
    initialized locks must be set to one due to the lack of normal
    atomic operations.) */
 
-#if LT_SPINLOCK_INIT == 0
-#  define __libc_lock_define_initialized(CLASS,NAME) \
-  CLASS __libc_lock_t NAME;
-#else
-#  define __libc_lock_define_initialized(CLASS,NAME) \
-  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
-#endif
+#define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;						      \
+  static void __##NAME##_mutex_init(void)				      \
+    { __libc_lock_init(NAME); }						      \
+  static void (*const __init_##NAME##[1])				      \
+    (void) __attribute__ ((section(".ctors"))) = { __##NAME##_mutex_init };
 
 #define __libc_rwlock_define_initialized(CLASS,NAME) \
-  CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+  CLASS __libc_rwlock_t NAME;						      \
+  static void __##NAME##_rwmutex_init(void)				      \
+    { __libc_rwlock_init(NAME); }					      \
+  static void (*const __init_##NAME##[1])				      \
+    (void) __attribute__ ((section(".ctors"))) = { __##NAME##_rwmutex_init };
 
 /* Define an initialized recursive lock variable NAME with storage
    class CLASS.  */
 #define __libc_lock_define_initialized_recursive(CLASS,NAME) \
-  CLASS __libc_lock_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-
-/* Initialize the named lock variable, leaving it in a consistent, unlocked
-   state.  */
-#define __libc_lock_init(NAME) \
-  (__pthread_mutex_init != NULL ? __pthread_mutex_init (&(NAME), NULL) : 0);
-#define __libc_rwlock_init(NAME) \
-  (__pthread_rwlock_init != NULL ? __pthread_rwlock_init (&(NAME), NULL) : 0);
-
-/* Same as last but this time we initialize a recursive mutex.  */
-#define __libc_lock_init_recursive(NAME) \
-  do {									      \
-    if (__pthread_mutex_init != NULL)					      \
-      {									      \
-	pthread_mutexattr_t __attr;					      \
-	__pthread_mutexattr_init (&__attr);				      \
-	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
-	__pthread_mutex_init (&(NAME), &__attr);			      \
-	__pthread_mutexattr_destroy (&__attr);				      \
-      }									      \
-  } while (0);
+  CLASS __libc_lock_t NAME;						      \
+  static void __##NAME##_recmutex_init(void)				      \
+    { __libc_lock_init_recursive(NAME); }				      \
+  static void (*const __init_##NAME##[1])				      \
+    (void) __attribute__ ((section(".ctors"))) = { __##NAME##_recmutex_init };
 
 /* Finalize the named lock variable, which must be locked.  It cannot be
    used again until __libc_lock_init is called again on it.  This must be
    called on a lock variable before the containing storage is reused.  */
 #define __libc_lock_fini(NAME) \
-  (__pthread_mutex_destroy != NULL ? __pthread_mutex_destroy (&(NAME)) : 0);
+  (__libcThr_mutex_destroy != NULL ? __libcThr_mutex_destroy (&(NAME)) : 0)
 #define __libc_rwlock_fini(NAME) \
-  (__pthread_rwlock_destroy != NULL ? __pthread_rwlock_destroy (&(NAME)) : 0);
+  (__libcThr_rwlock_destroy != NULL ? __libcThr_rwlock_destroy (&(NAME)) : 0)
 
 /* Finalize recursive named lock.  */
 #define __libc_lock_fini_recursive(NAME) __libc_lock_fini (NAME)
 
 /* Lock the named lock variable.  */
 #define __libc_lock_lock(NAME) \
-  (__pthread_mutex_lock != NULL ? __pthread_mutex_lock (&(NAME)) : 0);
+  (__libcThr_mutex_lock != NULL ? __libcThr_mutex_lock (&(NAME)) : 0)
 #define __libc_rwlock_rdlock(NAME) \
-  (__pthread_rwlock_rdlock != NULL ? __pthread_rwlock_rdlock (&(NAME)) : 0);
+  (__libcThr_rwlock_rdlock != NULL ? __libcThr_rwlock_rdlock (&(NAME)) : 0)
 #define __libc_rwlock_wrlock(NAME) \
-  (__pthread_rwlock_wrlock != NULL ? __pthread_rwlock_wrlock (&(NAME)) : 0);
+  (__libcThr_rwlock_wrlock != NULL ? __libcThr_rwlock_wrlock (&(NAME)) : 0)
 
 /* Lock the recursive named lock variable.  */
 #define __libc_lock_lock_recursive(NAME) __libc_lock_lock (NAME)
 
 /* Try to lock the named lock variable.  */
 #define __libc_lock_trylock(NAME) \
-  (__pthread_mutex_trylock != NULL ? __pthread_mutex_trylock (&(NAME)) : 0)
+  (__libcThr_mutex_trylock != NULL ? __libcThr_mutex_trylock (&(NAME)) : 0)
 #define __libc_rwlock_tryrdlock(NAME) \
-  (__pthread_rwlock_tryrdlock != NULL \
-   ? __pthread_rwlock_tryrdlock (&(NAME)) : 0)
+  (__libcThr_rwlock_tryrdlock != NULL \
+   ? __libcThr_rwlock_tryrdlock (&(NAME)) : 0)
 #define __libc_rwlock_trywrlock(NAME) \
-  (__pthread_rwlock_trywrlock != NULL \
-   ? __pthread_rwlock_trywrlock (&(NAME)) : 0)
+  (__libcThr_rwlock_trywrlock != NULL \
+   ? __libcThr_rwlock_trywrlock (&(NAME)) : 0)
 
 /* Try to lock the recursive named lock variable.  */
 #define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock (NAME)
 
 /* Unlock the named lock variable.  */
 #define __libc_lock_unlock(NAME) \
-  (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (&(NAME)) : 0);
+  (__libcThr_mutex_unlock != NULL ? __libcThr_mutex_unlock (&(NAME)) : 0)
 #define __libc_rwlock_unlock(NAME) \
-  (__pthread_rwlock_unlock != NULL ? __pthread_rwlock_unlock (&(NAME)) : 0);
+  (__libcThr_rwlock_unlock != NULL ? __libcThr_rwlock_unlock (&(NAME)) : 0)
 
 /* Unlock the recursive named lock variable.  */
 #define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock (NAME)
 
 
-/* Define once control variable.  */
-#if PTHREAD_ONCE_INIT == 0
-/* Special case for static variables where we can avoid the initialization
-   if it is zero.  */
-# define __libc_once_define(CLASS, NAME) \
-  CLASS pthread_once_t NAME
-#else
-# define __libc_once_define(CLASS, NAME) \
-  CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
-#endif
+/* Define once control variable.  Assumes it is initialized to 0. */
+#define __libc_once_define(CLASS, NAME) \
+  CLASS __libc_once_t NAME
 
 /* Call handler iff the first call.  */
 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
   do {									      \
-    if (__pthread_once != NULL)						      \
-      __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION));		      \
-    else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \
+    if (__libcThr_once != NULL)						      \
+      __libcThr_once (&(ONCE_CONTROL), (INIT_FUNCTION));		      \
+    else if ((ONCE_CONTROL) == 0) {					      \
       INIT_FUNCTION ();							      \
-      (ONCE_CONTROL) = !PTHREAD_ONCE_INIT;				      \
+      (ONCE_CONTROL) = 1;						      \
     }									      \
   } while (0)
 
 
 /* Start critical region with cleanup.  */
 #define __libc_cleanup_region_start(FCT, ARG) \
-  { struct _pthread_cleanup_buffer _buffer;				      \
-    int _avail = _pthread_cleanup_push_defer != NULL;			      \
+  { __libc_cleanup_t _buffer;				      \
+    int _avail = _libcThr_cleanup_push_defer != NULL;			      \
     if (_avail) {							      \
-      _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG));		      \
+      _libcThr_cleanup_push_defer (&_buffer, (FCT), (ARG));		      \
     }
 
 /* End critical region with cleanup.  */
 #define __libc_cleanup_region_end(DOIT) \
     if (_avail) {							      \
-      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+      _libcThr_cleanup_pop_restore (&_buffer, (DOIT));			      \
     }									      \
   }
 
 /* Sometimes we have to exit the block in the middle.  */
 #define __libc_cleanup_end(DOIT) \
     if (_avail) {							      \
-      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+      _libcThr_cleanup_pop_restore (&_buffer, (DOIT));			      \
     }
 
 /* Create thread-specific key.  */
 #define __libc_key_create(KEY, DESTRUCTOR) \
-  (__pthread_key_create != NULL ? __pthread_key_create (KEY, DESTRUCTOR) : 1)
+  (__libcThr_key_create != NULL ? __libcThr_key_create (KEY, DESTRUCTOR) : 1)
+
+/* Delete thread-specific key.  */
+#define __libc_key_delete(KEY) \
+  (__libcThr_key_delete != NULL ? __libcThr_key_delete (KEY) : 1)
 
 /* Get thread-specific data.  */
 #define __libc_getspecific(KEY) \
-  (__pthread_getspecific != NULL ? __pthread_getspecific (KEY) : NULL)
+  (__libcThr_getspecific != NULL ? __libcThr_getspecific (KEY) : NULL)
 
 /* Set thread-specific data.  */
 #define __libc_setspecific(KEY, VALUE) \
-  (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0)
+  (__libcThr_setspecific != NULL ? __libcThr_setspecific (KEY, VALUE) : 0)
 
 
 /* Register handlers to execute before and after `fork'.  */
 #define __libc_atfork(PREPARE, PARENT, CHILD) \
-  (__pthread_atfork != NULL ? __pthread_atfork (PREPARE, PARENT, CHILD) : 0)
-
-/* Functions that are used by this file and are internal to the GNU C
-   library.  */
+  (__libcThr_atfork != NULL ? __libcThr_atfork (PREPARE, PARENT, CHILD) : 0)
 
-extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
-				 __const pthread_mutexattr_t *__mutex_attr);
+#define __libc_thread_create(TID, FUNC, ARG) \
+  (__libcThr_thread_create != NULL ? __libcThr_thread_create (TID, NULL, FUNC, ARG) : 1)
 
-extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
+#define __libc_thread_detach(TID) \
+  (__libcThr_thread_detach != NULL ? __libcThr_thread_detach(TID) : 1)
 
-extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
+#define __libc_thread_exit(ARG) \
+  (__libcThr_thread_exit != NULL ? __libcThr_thread_exit(ARG) : 1)
 
-extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
+#define __libc_self() \
+  (__libcThr_self != NULL ? __libcThr_self() : 0)
 
-extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+#define __libc_getschedparam(TID, POLICY, PARAM) \
+  (__libcThr_getschedparam != NULL ? __libcThr_getschedparam(TID, POLICY, PARAM) : 0)
 
-extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
+#define __libc_setschedparam(TID, POLICY, PARAM) \
+  (__libcThr_setschedparam != NULL ? __libcThr_setschedparam(TID, POLICY, PARAM) : 0)
 
-extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
+#define __libc_cond_init(COND) \
+  (__libcThr_cond_init != NULL ? __libcThr_cond_init(COND, NULL) : 1)
 
-extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
-					int __kind);
+#define __libc_cond_destroy(COND) \
+  (__libcThr_cond_destroy != NULL ? __libcThr_cond_destroy(COND) : 1)
 
-#ifdef __USE_UNIX98
-extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
-				  __const pthread_rwlockattr_t *__attr);
+#define __libc_cond_broadcast(COND) \
+  (__libcThr_cond_broadcast != NULL ? __libcThr_cond_broadcast(COND) : 1)
 
-extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
+#define __libc_cond_signal(COND) \
+  (__libcThr_cond_signal != NULL ? __libcThr_cond_signal(COND) : 1)
 
-extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
-#endif
-
-extern int __pthread_key_create (pthread_key_t *__key,
-				 void (*__destr_function) (void *));
-
-extern int __pthread_setspecific (pthread_key_t __key,
-				  __const void *__pointer);
-
-extern void *__pthread_getspecific (pthread_key_t __key);
-
-extern int __pthread_once (pthread_once_t *__once_control,
-			   void (*__init_routine) (void));
-
-extern int __pthread_atfork (void (*__prepare) (void),
-			     void (*__parent) (void),
-			     void (*__child) (void));
+#define __libc_cond_wait(COND, MUTEX) \
+  (__libcThr_cond_wait != NULL ? __libcThr_cond_wait(COND, MUTEX) : 1)
 
+/* Functions that are used by this file and are internal to the GNU C
+   library.  */
 
 
-/* Make the pthread functions weak so that we can elide them from
+/* Make the libcThr functions weak so that we can elide them from
    single-threaded processes.  */
 #ifndef __NO_WEAK_PTHREAD_ALIASES
 # ifdef weak_extern
@@ -261,57 +315,80 @@
 #  else
 #   define BP_SYM (sym) sym
 #  endif
-weak_extern (BP_SYM (__pthread_mutex_init))
-weak_extern (BP_SYM (__pthread_mutex_destroy))
-weak_extern (BP_SYM (__pthread_mutex_lock))
-weak_extern (BP_SYM (__pthread_mutex_trylock))
-weak_extern (BP_SYM (__pthread_mutex_unlock))
-weak_extern (BP_SYM (__pthread_mutexattr_init))
-weak_extern (BP_SYM (__pthread_mutexattr_destroy))
-weak_extern (BP_SYM (__pthread_mutexattr_settype))
-weak_extern (BP_SYM (__pthread_rwlock_init))
-weak_extern (BP_SYM (__pthread_rwlock_destroy))
-weak_extern (BP_SYM (__pthread_rwlock_rdlock))
-weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
-weak_extern (BP_SYM (__pthread_rwlock_wrlock))
-weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
-weak_extern (BP_SYM (__pthread_rwlock_unlock))
-weak_extern (BP_SYM (__pthread_key_create))
-weak_extern (BP_SYM (__pthread_setspecific))
-weak_extern (BP_SYM (__pthread_getspecific))
-weak_extern (BP_SYM (__pthread_once))
-weak_extern (__pthread_initialize)
-weak_extern (__pthread_atfork)
-weak_extern (BP_SYM (_pthread_cleanup_push_defer))
-weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
+weak_extern (BP_SYM (__libcThr_mutex_init))
+weak_extern (BP_SYM (__libcThr_mutex_destroy))
+weak_extern (BP_SYM (__libcThr_mutex_lock))
+weak_extern (BP_SYM (__libcThr_mutex_trylock))
+weak_extern (BP_SYM (__libcThr_mutex_unlock))
+weak_extern (BP_SYM (__libcThr_rwlock_init))
+weak_extern (BP_SYM (__libcThr_rwlock_destroy))
+weak_extern (BP_SYM (__libcThr_rwlock_rdlock))
+weak_extern (BP_SYM (__libcThr_rwlock_tryrdlock))
+weak_extern (BP_SYM (__libcThr_rwlock_wrlock))
+weak_extern (BP_SYM (__libcThr_rwlock_trywrlock))
+weak_extern (BP_SYM (__libcThr_rwlock_unlock))
+weak_extern (BP_SYM (__libcThr_key_create))
+weak_extern (BP_SYM (__libcThr_key_delete))
+weak_extern (BP_SYM (__libcThr_setspecific))
+weak_extern (BP_SYM (__libcThr_getspecific))
+weak_extern (BP_SYM (__libcThr_once))
+weak_extern (BP_SYM (__libcThr_init_threads))
+weak_extern (BP_SYM (__libcThr_atfork))
+weak_extern (BP_SYM (__libcThr_mutex_init_recursive_np))
+weak_extern (BP_SYM (_libcThr_cleanup_push_defer))
+weak_extern (BP_SYM (_libcThr_cleanup_pop_restore))
+weak_extern (BP_SYM (__libcThr_thread_create))
+weak_extern (BP_SYM (__libcThr_thread_detach))
+weak_extern (BP_SYM (__libcThr_thread_exit))
+weak_extern (BP_SYM (__libcThr_self))
+weak_extern (BP_SYM (__libcThr_getschedparam))
+weak_extern (BP_SYM (__libcThr_setschedparam))
+weak_extern (BP_SYM (__libcThr_cond_init))
+weak_extern (BP_SYM (__libcThr_cond_destroy))
+weak_extern (BP_SYM (__libcThr_cond_broadcast))
+weak_extern (BP_SYM (__libcThr_cond_signal))
+weak_extern (BP_SYM (__libcThr_cond_wait))
 # else
-#  pragma weak __pthread_mutex_init
-#  pragma weak __pthread_mutex_destroy
-#  pragma weak __pthread_mutex_lock
-#  pragma weak __pthread_mutex_trylock
-#  pragma weak __pthread_mutex_unlock
-#  pragma weak __pthread_mutexattr_init
-#  pragma weak __pthread_mutexattr_destroy
-#  pragma weak __pthread_mutexattr_settype
-#  pragma weak __pthread_rwlock_destroy
-#  pragma weak __pthread_rwlock_rdlock
-#  pragma weak __pthread_rwlock_tryrdlock
-#  pragma weak __pthread_rwlock_wrlock
-#  pragma weak __pthread_rwlock_trywrlock
-#  pragma weak __pthread_rwlock_unlock
-#  pragma weak __pthread_key_create
-#  pragma weak __pthread_setspecific
-#  pragma weak __pthread_getspecific
-#  pragma weak __pthread_once
-#  pragma weak __pthread_initialize
-#  pragma weak __pthread_atfork
-#  pragma weak _pthread_cleanup_push_defer
-#  pragma weak _pthread_cleanup_pop_restore
+#  pragma weak __libcThr_mutex_init
+#  pragma weak __libcThr_mutex_destroy
+#  pragma weak __libcThr_mutex_lock
+#  pragma weak __libcThr_mutex_trylock
+#  pragma weak __libcThr_mutex_unlock
+#  pragma weak __libcThr_rwlock_init
+#  pragma weak __libcThr_rwlock_destroy
+#  pragma weak __libcThr_rwlock_rdlock
+#  pragma weak __libcThr_rwlock_tryrdlock
+#  pragma weak __libcThr_rwlock_wrlock
+#  pragma weak __libcThr_rwlock_trywrlock
+#  pragma weak __libcThr_rwlock_unlock
+#  pragma weak __libcThr_key_create
+#  pragma weak __libcThr_key_delete
+#  pragma weak __libcThr_setspecific
+#  pragma weak __libcThr_getspecific
+#  pragma weak __libcThr_once
+#  pragma weak __libcThr_init_threads
+#  pragma weak __libcThr_atfork
+#  pragma weak __libcThr_mutex_init_recursive_np
+#  pragma weak _libcThr_cleanup_push_defer
+#  pragma weak _libcThr_cleanup_pop_restore
+#  pragma weak __libcThr_thread_create
+#  pragma weak __libcThr_thread_detach
+#  pragma weak __libcThr_thread_exit
+#  pragma weak __libcThr_self
+#  pragma weak __libcThr_getschedparam
+#  pragma weak __libcThr_setschedparam
+#  pragma weak __libcThr_cond_init
+#  pragma weak __libcThr_cond_destroy
+#  pragma weak __libcThr_cond_broadcast
+#  pragma weak __libcThr_cond_signal
+#  pragma weak __libcThr_cond_wait
 # endif
 #endif
 
 /* We need portable names for some functions.  E.g., when they are
    used as argument to __libc_cleanup_region_start.  */
-#define __libc_mutex_unlock __pthread_mutex_unlock
+#define __libc_mutex_unlock __libcThr_mutex_unlock
 
+__END_DECLS
+ 
 #endif	/* bits/libc-lock.h */
--- linuxthreads/rwlock.corig2	Tue Apr 10 18:29:31 2001
+++ linuxthreads/rwlock.c	Tue Apr 10 20:46:01 2001
@@ -655,3 +655,13 @@
 
   return 0;
 }
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (__pthread_rwlock_init, __libcThr_rwlock_init)
+strong_alias (__pthread_rwlock_destroy, __libcThr_rwlock_destroy)
+strong_alias (__pthread_rwlock_rdlock, __libcThr_rwlock_rdlock)
+strong_alias (__pthread_rwlock_wrlock, __libcThr_rwlock_wrlock)
+strong_alias (__pthread_rwlock_tryrdlock, __libcThr_rwlock_tryrdlock)
+strong_alias (__pthread_rwlock_trywrlock, __libcThr_rwlock_trywrlock)
+strong_alias (__pthread_rwlock_unlock, __libcThr_rwlock_unlock)
--- linuxthreads/lockfile.corig2	Thu Sep  7 13:56:28 2000
+++ linuxthreads/lockfile.c	Tue Apr 10 21:24:01 2001
@@ -17,9 +17,8 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <bits/libc-lock.h>
+#define _IO_MTSAFE_IO
 #include <stdio.h>
-#include <pthread.h>
 
 #ifdef USE_IN_LIBIO
 #include "../libio/libioP.h"
@@ -29,7 +28,7 @@
 __flockfile (FILE *stream)
 {
 #ifdef USE_IN_LIBIO
-  __pthread_mutex_lock (stream->_lock);
+  __libc_lock_lock (*stream->_lock);
 #else
 #endif
 }
@@ -44,7 +43,7 @@
 __funlockfile (FILE *stream)
 {
 #ifdef USE_IN_LIBIO
-  __pthread_mutex_unlock (stream->_lock);
+  __libc_lock_unlock (*stream->_lock);
 #else
 #endif
 }
@@ -59,7 +58,7 @@
 __ftrylockfile (FILE *stream)
 {
 #ifdef USE_IN_LIBIO
-  return __pthread_mutex_trylock (stream->_lock);
+  return __libc_lock_trylock (*stream->_lock);
 #else
 #endif
 }
@@ -90,15 +89,8 @@
 #ifdef USE_IN_LIBIO
   _IO_ITER i;
 
-  pthread_mutexattr_t attr;
-
-  __pthread_mutexattr_init (&attr);
-  __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
-
   for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
-    __pthread_mutex_init (_IO_iter_file(i)->_lock, &attr);
-
-  __pthread_mutexattr_destroy (&attr);
+    __libc_lock_init_recursive (*_IO_iter_file(i)->_lock);
 
   _IO_list_resetlock();
 #endif
--- linuxthreads/condvar.corig2	Wed Aug  2 16:52:12 2000
+++ linuxthreads/condvar.c	Tue Apr 10 14:25:07 2001
@@ -294,3 +294,11 @@
 
   return 0;
 }
+
+/* The following are strong aliases for the thread functions used by
+   libc.  See bits/libc-lock.h for more details. */
+strong_alias (pthread_cond_init, __libcThr_cond_init)
+strong_alias (pthread_cond_destroy, __libcThr_cond_destroy)
+strong_alias (pthread_cond_broadcast, __libcThr_cond_broadcast)
+strong_alias (pthread_cond_signal, __libcThr_cond_signal)
+strong_alias (pthread_cond_wait, __libcThr_cond_wait)
--- malloc/thread-m.horig2	Thu Sep 14 14:24:24 2000
+++ malloc/thread-m.h	Tue Apr 10 18:35:13 2001
@@ -33,68 +33,25 @@
 
 #include <bits/libc-lock.h>
 
-#ifdef PTHREAD_MUTEX_INITIALIZER
-
-typedef pthread_t thread_id;
-
-/* mutex */
-typedef pthread_mutex_t	mutex_t;
-
-#define MUTEX_INITIALIZER	PTHREAD_MUTEX_INITIALIZER
+typedef __libc_lock_t 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.  */
 
-#define mutex_init(m)		\
-   (__pthread_mutex_init != NULL \
-    ? __pthread_mutex_init (m, NULL) : (*(int *)(m) = 0))
-#define mutex_lock(m)		\
-   (__pthread_mutex_lock != NULL \
-    ? __pthread_mutex_lock (m) : ((*(int *)(m) = 1), 0))
-#define mutex_trylock(m)	\
-   (__pthread_mutex_trylock != NULL \
-    ? __pthread_mutex_trylock (m) : (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
-#define mutex_unlock(m)		\
-   (__pthread_mutex_unlock != NULL \
-    ? __pthread_mutex_unlock (m) : (*(int*)(m) = 0))
+#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)
 
 #define thread_atfork(prepare, parent, child) \
-   (__pthread_atfork != NULL ? __pthread_atfork(prepare, parent, child) : 0)
-
-#elif defined(MUTEX_INITIALIZER)
-/* Assume hurd, with cthreads */
-
-/* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the
-   mutex itself.  */
-#undef mutex_t
-#define mutex_t struct mutex
-
-#undef mutex_init
-#define mutex_init(m) (__mutex_init(m), 0)
-
-#undef mutex_lock
-#define mutex_lock(m) (__mutex_lock(m), 0)
-
-#undef mutex_unlock
-#define mutex_unlock(m) (__mutex_unlock(m), 0)
-
-#define mutex_trylock(m) (!__mutex_trylock(m))
-
-#define thread_atfork(prepare, parent, child) do {} while(0)
-#define thread_atfork_static(prepare, parent, child) \
- text_set_element(_hurd_fork_prepare_hook, prepare); \
- text_set_element(_hurd_fork_parent_hook, parent); \
- text_set_element(_hurd_fork_child_hook, child);
-
-/* No we're *not* using pthreads.  */
-#define __pthread_initialize ((void (*)(void))0)
+	__libc_atfork(prepare, parent, child)
 
 #else
 
 #define NO_THREADS
 
-#endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */
+#endif /* _LIBC */
 
 #ifndef NO_THREADS
 
@@ -108,14 +65,10 @@
 #define tsd_setspecific(key, data)	__libc_tsd_set (MALLOC, (data))
 #define tsd_getspecific(key, vptr)	((vptr) = __libc_tsd_get (MALLOC))
 
-#endif
-
 #elif defined(USE_PTHREADS) /* Posix threads */
 
 #include <pthread.h>
 
-typedef pthread_t thread_id;
-
 /* mutex */
 typedef pthread_mutex_t mutex_t;
 
@@ -161,8 +114,6 @@
 
 #include <thread.h>
 
-typedef thread_t thread_id;
-
 #define MUTEX_INITIALIZER          { 0 }
 #define mutex_init(m)              mutex_init(m, USYNC_THREAD, NULL)
 
@@ -187,8 +138,6 @@
 #include <sys/prctl.h>
 #include <abi_mutex.h>
 
-typedef int thread_id;
-
 typedef abilock_t mutex_t;
 
 #define MUTEX_INITIALIZER          { 0 }
@@ -212,8 +161,6 @@
 #endif /* defined(_LIBC) */
 
 #ifdef NO_THREADS /* No threads, provide dummy macros */
-
-typedef int thread_id;
 
 /* The mutex functions used to do absolutely nothing, i.e. lock,
    trylock and unlock would always just return 0.  However, even
--- malloc/malloc.corig2	Sun Oct  8 19:05:03 2000
+++ malloc/malloc.c	Tue Apr 10 14:25:07 2001
@@ -1517,7 +1517,6 @@
 #if THREAD_STATS
     0, 0, 0, /* stat_lock_direct, stat_lock_loop, stat_lock_wait */
 #endif
-    MUTEX_INITIALIZER /* mutex */
 };
 
 #undef IAV
@@ -1525,7 +1524,7 @@
 /* Thread specific data */
 
 static tsd_key_t arena_key;
-static mutex_t list_lock = MUTEX_INITIALIZER;
+static mutex_t list_lock;
 
 #if THREAD_STATS
 static int stat_n_heaps = 0;
@@ -1694,9 +1693,8 @@
   __free_hook = free_starter;
 #endif
 #ifdef _LIBC
-  /* Initialize the pthreads interface. */
-  if (__pthread_initialize != NULL)
-    __pthread_initialize();
+  /* Initialize the threads interface. */
+    __libc_init_threads();
 #endif
 #endif /* !defined NO_THREADS */
   mutex_init(&main_arena.mutex);
--- iconv/gconv_conf.corig2	Tue Apr 10 18:48:16 2001
+++ iconv/gconv_conf.c	Tue Apr 10 20:30:01 2001
@@ -396,12 +396,13 @@
 }
 
 
+__libc_lock_define_initialized (static, lock);
+
 /* Determine the directories we are looking for data in.  */
 void
 __gconv_get_path (void)
 {
   struct path_elem *result;
-  __libc_lock_define_initialized (static, lock);
 
   __libc_lock_lock (lock);
 
--- intl/dcigettext.corig2	Tue Apr 10 18:48:41 2001
+++ intl/dcigettext.c	Tue Apr 10 20:30:19 2001
@@ -654,6 +654,7 @@
   /* NOTREACHED */
 }
 
+__libc_lock_define_initialized (static, lock)
 
 char *
 internal_function
@@ -792,7 +793,6 @@
 	  /* We use a bit more efficient memory handling.
 	     We allocate always larger blocks which get used over
 	     time.  This is faster than many small allocations.   */
-	  __libc_lock_define_initialized (static, lock)
 #define INITIAL_BLOCK_SIZE	4080
 	  static unsigned char *freemem;
 	  static size_t freemem_size;
--- sysdeps/generic/opensock.corig2	Tue Apr 10 20:27:26 2001
+++ sysdeps/generic/opensock.c	Tue Apr 10 20:28:52 2001
@@ -19,6 +19,8 @@
 #include <sys/socket.h>
 #include <bits/libc-lock.h>
 
+__libc_lock_define_initialized (static, lock);
+
 /* Return a socket of any type.  The socket can be used in subsequent
    ioctl calls to talk to the kernel.  */
 int internal_function
@@ -28,7 +30,6 @@
      socket().  */
   static int sock_af = -1;
   int fd = -1;
-  __libc_lock_define_initialized (static, lock);
 
   if (sock_af != -1)
     {
--- inet/getnameinfo.corig2	Tue Apr 10 20:33:55 2001
+++ inet/getnameinfo.c	Tue Apr 10 20:34:35 2001
@@ -74,6 +74,8 @@
 
 
 
+__libc_lock_define_initialized (static, lock);
+
 static char *
 internal_function
 nrl_domainname (void)
@@ -83,7 +85,6 @@
 
   if (! not_first)
     {
-      __libc_lock_define_initialized (static, lock);
       __libc_lock_lock (lock);
 
       if (! not_first)
--- elf/dl-open.c.old	Fri Jul  6 00:53:33 2001
+++ elf/dl-open.c	Fri Jul  6 01:02:00 2001
@@ -65,7 +65,8 @@
    This must be a recursive lock since the initializer function of
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
-__libc_lock_define (extern, _dl_load_lock)
+int __dl_load_lock_lock(void);
+int __dl_load_lock_unlock(void);
 
 extern size_t _dl_platformlen;
 
@@ -371,7 +372,7 @@
     _dl_signal_error (EINVAL, file, N_("invalid mode for dlopen()"));
 
   /* Make sure we are alone.  */
-  __libc_lock_lock (_dl_load_lock);
+  __dl_load_lock_lock();
 
   args.file = file;
   args.mode = mode;
@@ -385,7 +386,7 @@
 #endif
 
   /* Release the lock.  */
-  __libc_lock_unlock (_dl_load_lock);
+  __dl_load_lock_unlock();
 
   if (errstring)
     {
--- elf/dl-close.c.old	Fri Jul  6 00:53:15 2001
+++ elf/dl-close.c	Fri Jul  6 01:00:59 2001
@@ -37,7 +37,8 @@
 /* During the program run we must not modify the global data of
    loaded shared object simultanously in two threads.  Therefore we
    protect `dlopen' and `dlclose' in dlclose.c.  */
-__libc_lock_define (extern, _dl_load_lock)
+int __dl_load_lock_lock(void);
+int __dl_load_lock_unlock(void);
 
 void
 internal_function
@@ -63,7 +64,7 @@
     _dl_signal_error (0, map->l_name, N_("shared object not open"));
 
   /* Acquire the lock.  */
-  __libc_lock_lock (_dl_load_lock);
+  __dl_load_lock_lock();
 
   /* Decrement the reference count.  */
   if (map->l_opencount > 1 || map->l_type != lt_loaded)
@@ -85,7 +86,7 @@
       /* One decrement the object itself, not the dependencies.  */
       --map->l_opencount;
 
-      __libc_lock_unlock (_dl_load_lock);
+      __dl_load_lock_unlock();
       return;
     }
 
@@ -282,7 +283,7 @@
   free (list);
 
   /* Release the lock.  */
-  __libc_lock_unlock (_dl_load_lock);
+  __dl_load_lock_unlock();
 }
 
 
--- elf/dl-lookup.c.old	Fri Jul  6 00:53:22 2001
+++ elf/dl-lookup.c	Fri Jul  6 01:01:38 2001
@@ -68,7 +68,8 @@
    This must be a recursive lock since the initializer function of
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
-__libc_lock_define (extern, _dl_load_lock)
+int __dl_load_lock_lock(void);
+int __dl_load_lock_unlock(void);
 
 
 /* We have two different situations when looking up a simple: with or
@@ -93,7 +94,7 @@
   int result = 0;
 
   /* Make sure nobody can unload the object while we are at it.  */
-  __libc_lock_lock (_dl_load_lock);
+  __dl_load_lock_lock();
 
   /* Determine whether UNDEF_MAP already has a reference to MAP.  First
      look in the normal dependencies.  */
@@ -176,7 +177,7 @@
     }
 
   /* Release the lock.  */
-  __libc_lock_unlock (_dl_load_lock);
+  __dl_load_lock_unlock();
 
   return result;
 }
--- elf/dl-misc.c.old	Fri Jul  6 02:24:42 2001
+++ elf/dl-misc.c	Fri Jul  6 02:28:27 2001
@@ -26,6 +26,30 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <stdio-common/_itoa.h>
+#include <bits/libc-lock.h>
+
+extern int _dl_load_lock_initialized;
+__libc_lock_define (extern , _dl_load_lock)
+
+int
+__dl_load_lock_lock(void)
+{
+    if (_dl_load_lock_initialized) {
+	return __libc_lock_lock(_dl_load_lock);
+    }
+
+    return 0;
+}
+
+int
+__dl_load_lock_unlock(void)
+{
+    if (_dl_load_lock_initialized) {
+	return __libc_lock_unlock(_dl_load_lock);
+    }
+
+    return 0;
+}
 
 #ifndef MAP_ANON
 /* This is the only dl-sysdep.c function that is actually needed at run-time
--- elf/Versions.old	Fri Jul  6 02:35:16 2001
+++ elf/Versions	Fri Jul  6 02:34:57 2001
@@ -55,6 +55,7 @@
     _dl_debug_files;
 
     _dl_init; _dl_load_lock; _dl_argv; _dl_nloaded; _dl_check_map_versions;
+    __dl_load_lock_lock; __dl_load_lock_unlock; _dl_load_lock_initialized;
 
     # this is defined in ld.so and overridden by libc
     _dl_init_first;
--- elf/dl-support.c.old	Fri Jul  6 00:51:02 2001
+++ elf/dl-support.c	Fri Jul  6 01:02:53 2001
@@ -105,7 +105,8 @@
    This must be a recursive lock since the initializer function of
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
+int _dl_load_lock_initialized = 1;
 __libc_lock_define_initialized_recursive (, _dl_load_lock)
 
 
 #ifdef HAVE_AUX_VECTOR
--- elf/rtld.c.old	Fri Jul  6 00:50:55 2001
+++ elf/rtld.c	Fri Jul  6 02:25:10 2001
@@ -125,7 +125,8 @@
    This must be a recursive lock since the initializer function of
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
-__libc_lock_define_initialized_recursive (, _dl_load_lock)
+int _dl_load_lock_initialized;
+__libc_lock_define (, _dl_load_lock)
 
 /* Set nonzero during loading and initialization of executable and
    libraries, cleared before the executable's entry point runs.  This
@@ -1165,6 +1166,11 @@
   /* We must munmap() the cache file.  */
   _dl_unload_cache ();
 #endif
+
+  /* Now that all the libraries should be in place, initialize the
+     load lock. */
+  _dl_load_lock_initialized = 1;
+  __libc_lock_init_recursive(_dl_load_lock);
 
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */


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