This is the mail archive of the libc-hacker@sourceware.cygnus.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]

libc-internal thread-specific data revamp


The following patches revamp the facilities for libc-internal
thread-specific data used by malloc and the dynamic linker.

I have built libc for i686-linux and i486-gnu (hurd) using these changes.
On Linux, `make check' succeeds and the *.out files eyeball ok.
(For Hurd, I have only in fact tested that it compiles and links.)

These patches do several things, each for pretty much independent reasons.

Firstly, I have moved the internal tsd definitions out of <bits/libc-lock.h>
to a new file <bits/libc-tsd.h>.  This is mostly just aesthetic.  The
functionality is independent and not really directly related to locks
(except they obviously both are closely intertwined with the thread system).
This also allowed me to add a new mach/hurd/bits/libc-tsd.h while still
using mach/bits/libc-lock.h for both hurd and non-hurd mach (not that any
such platform is actually supported).  Also, I like the theory of minimal
inclusion (compiler goes faster); since some places use tsd without using
any of the rest of the stuff in libc-lock.h, this avoids processing all
those unnecessary decls.
(Note that I have not touched __libc_getspecific/__libc_setspecific, the
"user-level" tsd functions.  Having the internal tsd stuff in a separate
header from these might make the relation of the two interfaces less
confusing than it is now.)


Second, I have rewritten the source-level interface replacing
__libc_internal_tsd_get and __libc_internal_tsd_set with some new macros,
and changed the uses (dl-error.c and malloc/thread-m.h) accordingly.  There
are several motivations for this.  The first and foremost is to avoid the
gratuitous `if' test on platforms where the action is unconditional; i.e. a
single-thread-only platform, or the Hurd, which for these internal
variables is effectively always multithreaded even in "single-threaded"
programs.  It also simplifies the code in the places where the macros are
used, since the macros take care of defining the static/global slot for
single-threaded programs to use.

The new interface provides a __libc_tsd_define macro in the style of
__libc_lock_define, which is responsible for defining/declaring any
necessary static/global variable where single-threaded programs store their
data; and simple get/set macros, which are responsible for doing any
necessary single- vs multi-threaded conditional.

I have provided a sysdeps/generic/bits/libc-tsd.h file that would be used
for a purely single-threaded configuration of libc.  It has a comment
describing the macro interface, and the implementation there trivially
demonstrates the flexibility of this interface over the existing one.

You may note that the new __libc_tsd_* macros use unprefixed names for the
key.  This is not a problem because this header and its use are all
internal to libc code.  The motivation for this, as well as brevity, is the
elegance of the Hurd implementation.  Since for the Hurd this is really
just a libc-internal alias for existing Hurd-specific functionality,
removing the `_LIBC_TSD_' prefix allows me to do this aliasing for the
general case without having to update two Hurd places when we add another
internal key (we will just add it to <hurd/threadvar.h> and
sysdeps/mach/hurd/bits/libc-tsd.h won't need to change at all).


Finally, I have changed the linuxthreads implementation to use a normal
global/common pointer variable that might be uninitialized (zero) instead
of a weak symbol that might be absent (zero).  The sole motivation for this
is to remove the (self-described) horrible kludge in dl-error.c for using
tsd during dynamic linker bootstrap.  I think the cost for this approach is
very small or almost none, and well worth it for getting rid of that kludge
(and its extra run-time comparison, which is done every time the code runs,
though it's only ever needed at startup time).  In PIC, a local-to-libc
global variable is basically the same as a GOT slot for accessing it at
runtime.  In non-PIC, it uses one additional bss word and the runtime
access cost is a load from that word rather than using a constant in the
compare instruction.

This changes the ABI of two exported symbols on Linux platforms, but since
it is only the ABI between libc and libpthread, I don't think it will be a
problem.  The symbol versions or names should probably change though.


The patches to the code are at the end of this message.  The new files are
there as patches against /dev/null, and the other changes are from cvs diff
postprocessed to fix the file names, but I think the whole thing should
apply fine with patch -p0.

Here are the entries for the main ChangeLog:


1998-11-29  Roland McGrath  <roland@baalperazim.frob.com>

	* malloc/thread-m.h [_LIBC]: Include <bits/libc-tsd.h>, and
	remove tsd stuff from pthreads/cthreads libc sections.
	Use __libc_tsd_define for MALLOC key.
	[_LIBC] (tsd_key_t, tsd_key_create): Define to a zero-size type and a
	no-op, respectively.
	[_LIBC] (tsd_setspecific, tsd_getspecific): Use __libc_tsd_get/set.

	* elf/dl-error.c: Include <bits/libc-tsd.h>.
	Use __libc_tsd_define for DL_ERROR key.
	(tsd_setspecific, tsd_getspecific): Rewritten using __libc_tsd_get/set.

	* sysdeps/mach/hurd/bits/libc-tsd.h: New file.
	* sysdeps/generic/bits/libc-tsd.h: New file.
	* Makefile (distribute): Add bits/libc-tsd.h.

1998-10-12  Roland McGrath  <roland@baalperazim.frob.com>

	* elf/dl-error.c: Remove kludge to check for ld.so load address.
	There is no need if weak undefined symbols are not used in ld.so;
	see linuxthreads/ChangeLog for changes to files
	linuxthreads/sysdeps/pthread/bits/libc-lock.h and
	linuxthreads/sysdeps/pthread/bits/libc-tsd.h.


and here are the entries for linuxthreads/ChangeLog:

1998-11-29  Roland McGrath  <roland@baalperazim.frob.com>

	* sysdeps/pthread/bits/libc-tsd.h (__libc_tsd_define, __libc_tsd_get,
	__libc_tsd_set): New macros for new interface.
	* no-tsd.c: New file, provide uninitialized defns of
	__libc_internal_tsd_get and __libc_internal_tsd_set.
	* Makefile (routines): Add no-tsd.

1998-10-12  Roland McGrath  <roland@baalperazim.frob.com>

	* internals.h: Include <bits/libc-tsd.h>, not <bits/libc-lock.h>.
	* sysdeps/pthread/bits/libc-lock.h (__libc_internal_tsd_get,
	__libc_internal_tsd_set): Move decls to ...
	* sysdeps/pthread/bits/libc-tsd.h: New file for __libc_internal_tsd_*
	declarations.

	* sysdeps/pthread/bits/libc-lock.h (__libc_internal_tsd_get,
	__libc_internal_tsd_set): Make these pointers to functions, not
	functions; remove #pragma weak decls for them.
	* specific.c (__libc_internal_tsd_get, __libc_internal_tsd_set):
	Define static functions and initialized pointers to them.


Patches follow.


Enjoy,
Roland


--- /dev/null	Tue May  5 16:32:27 1998
+++ sysdeps/generic/bits/libc-tsd.h	Sun Nov 29 15:54:32 1998
@@ -0,0 +1,51 @@
+/* libc-internal interface for thread-specific data.  Stub version.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_LIBC_TSD_H
+#define _BITS_LIBC_TSD_H 1
+
+/* This file defines the following macros for accessing a small fixed
+   set of thread-specific `void *' data used only internally by libc.
+
+   __libc_tsd_define(CLASS, KEY)	-- Define or declare a `void *' datum
+   					   for KEY.  CLASS can be `static' for
+					   keys used in only one source file,
+					   empty for global definitions, or
+					   `extern' for global declarations.
+   __libc_tsd_get(KEY)			-- Return the `void *' datum for KEY.
+   __libc_tsd_set(KEY, VALUE)		-- Set the datum for KEY to VALUE.
+
+   The set of available KEY's will usually be provided as an enum,
+   and contains (at least):
+		_LIBC_TSD_KEY_MALLOC
+		_LIBC_TSD_KEY_DL_ERROR
+   All uses must be the literal _LIBC_TSD_* name in the __libc_tsd_* macros.
+   Some implementations may not provide any enum at all and instead
+   using string pasting in the macros.  */
+
+/* This is the generic/stub implementation for wholly single-threaded
+   systems.  We don't define an enum for the possible key values, because
+   the KEYs translate directly into variables by macro magic.  */
+
+#define __libc_tsd_define(CLASS, KEY)	CLASS void *__libc_tsd_##KEY##_data;
+#define __libc_tsd_get(KEY)		(__libc_tsd_##KEY##_data)
+#define __libc_tsd_set(KEY, VALUE)	(__libc_tsd_##KEY##_data = (VALUE))
+
+
+#endif	/* bits/libc-tsd.h */
--- /dev/null	Tue May  5 16:32:27 1998
+++ sysdeps/mach/hurd/bits/libc-tsd.h	Sun Nov 29 15:51:34 1998
@@ -0,0 +1,37 @@
+/* libc-internal interface for thread-specific data.  Hurd version.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_LIBC_TSD_H
+#define _BITS_LIBC_TSD_H 1
+
+#include <hurd/threadvar.h>
+
+#define __libc_tsd_define(CLASS, KEY) /* nothing, always have threadvars */
+
+#define __libc_tsd_threadvar_location(KEY) \
+  ((void **) __hurd_threadvar_location (_HURD_THREADVAR_##KEY))
+
+#define __libc_tsd_get(KEY) \
+  (*__libc_tsd_threadvar_location (KEY))
+
+#define __libc_tsd_set(KEY, VALUE) \
+  (*__libc_tsd_threadvar_location (KEY) = (VALUE))
+
+
+#endif	/* bits/libc-tsd.h */
--- /dev/null	Tue May  5 16:32:27 1998
+++ linuxthreads/no-tsd.c	Sun Nov 29 20:32:46 1998
@@ -0,0 +1,33 @@
+/* libc-internal interface for thread-specific data.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <bits/libc-tsd.h>
+
+/* This file provides uinitialized (common) definitions for the
+   hooks used internally by libc to access thread-specific data.
+
+   When -lpthread is used, it provides initialized definitions for these
+   variables (in specific.c), which override these uninitialized definitions.
+
+   If -lpthread is not used, these uninitialized variables default to zero,
+   which the __libc_tsd_* macros check for.   */
+
+void *(*__libc_internal_tsd_get) __P ((enum __libc_tsd_key_t));
+int (*__libc_internal_tsd_set) __P ((enum __libc_tsd_key_t,
+				     __const void *));
--- /dev/null	Tue May  5 16:32:27 1998
+++ linuxthreads/sysdeps/pthread/bits/libc-tsd.h	Sun Nov 29 15:58:00 1998
@@ -0,0 +1,43 @@
+/* libc-internal interface for thread-specific data.  LinuxThreads version.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_LIBC_TSD_H
+#define _BITS_LIBC_TSD_H 1
+
+
+/* Fast thread-specific data internal to libc.  */
+enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
+			_LIBC_TSD_KEY_DL_ERROR,
+			_LIBC_TSD_KEY_N };
+
+extern void *(*__libc_internal_tsd_get) __P ((enum __libc_tsd_key_t));
+extern int (*__libc_internal_tsd_set) __P ((enum __libc_tsd_key_t,
+					    __const void *));
+
+#define __libc_tsd_define(CLASS, KEY)	CLASS void *__libc_tsd_##KEY##_data;
+#define __libc_tsd_get(KEY) \
+  (__libc_internal_tsd_get != NULL \
+   ? __libc_internal_tsd_get (_LIBC_TSD_KEY_##KEY) \
+   : __libc_tsd_##KEY##_data)
+#define __libc_tsd_set(KEY, VALUE) \
+  (__libc_internal_tsd_set != NULL \
+   ? __libc_internal_tsd_set (_LIBC_TSD_KEY_##KEY, (VALUE)) \
+   : ((__libc_tsd_##KEY##_data = (VALUE)), 0))
+
+#endif	/* bits/libc-tsd.h */

Index: elf/dl-error.c
===================================================================
RCS file: /glibc/cvsfiles/libc/elf/dl-error.c,v
retrieving revision 1.27
diff -u -p -r1.27 dl-error.c
--- elf/dl-error.c	1998/09/22 12:41:52	1.27
+++ elf/dl-error.c	1998/11/29 21:52:18
@@ -22,7 +22,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <elf/ldsodefs.h>
-#include <bits/libc-lock.h>
+#include <bits/libc-tsd.h>
 
 /* This structure communicates state between _dl_catch_error and
    _dl_signal_error.  */
@@ -36,44 +36,11 @@ struct catch
    calls can come from `_dl_map_object_deps', `_dlerror_run', or from
    any of the libc functionality which loads dynamic objects (NSS, iconv).
    Therefore we have to be prepared to save the state in thread-local
-   memory.  `catch' will only be used for the non-threaded case.
+   memory.  */
 
-   Please note the horrible kludge we have to use to check for the
-   thread functions to be defined.  The problem is that while running
-   ld.so standalone (i.e., before the relocation with the available
-   libc symbols) we do not have a real handling of undefined weak symbols.
-   All symbols are relocated, regardless of the availability.  They are
-   relocated relative to the load address of the dynamic linker.  Adding
-   this start address to zero (the value in the GOT for undefined symbols)
-   leads to an address which is the load address of ld.so.  Once we have
-   relocated with the libc values the value is NULL if the function is
-   not available.  Our "solution" is to regard NULL and the ld.so load
-   address as indicators for unavailable weak symbols.   */
-static struct catch *catch;
-
-#ifdef PIC
-# define tsd_setspecific(data) \
-  if (__libc_internal_tsd_set != (void *) _dl_rtld_map.l_addr		      \
-      && __libc_internal_tsd_set != NULL)				      \
-    __libc_internal_tsd_set (_LIBC_TSD_KEY_DL_ERROR, data);		      \
-  else									      \
-    catch = (data)
-# define tsd_getspecific() \
-  (__libc_internal_tsd_set != (void *) _dl_rtld_map.l_addr		      \
-   && __libc_internal_tsd_set != NULL					      \
-   ? (struct catch *) __libc_internal_tsd_get (_LIBC_TSD_KEY_DL_ERROR)	      \
-   : catch)
-#else
-# define tsd_setspecific(data) \
-  if (__libc_internal_tsd_set != NULL)					      \
-    __libc_internal_tsd_set (_LIBC_TSD_KEY_DL_ERROR, data);		      \
-  else									      \
-    catch = (data)
-# define tsd_getspecific() \
-  (__libc_internal_tsd_set != NULL					      \
-   ? (struct catch *) __libc_internal_tsd_get (_LIBC_TSD_KEY_DL_ERROR)	      \
-   : catch)
-#endif
+__libc_tsd_define (static, DL_ERROR)
+#define tsd_getspecific()	__libc_tsd_get (DL_ERROR)
+#define tsd_setspecific(data)	__libc_tsd_set (DL_ERROR, (data))
 
 
 /* This points to a function which is called when an error is
Index: linuxthreads/internals.h
===================================================================
RCS file: /glibc/cvsfiles/libc/linuxthreads/internals.h,v
retrieving revision 1.11
diff -u -p -r1.11 internals.h
--- linuxthreads/internals.h	1998/08/28 13:59:31	1.11
+++ linuxthreads/internals.h	1998/11/29 21:52:24
@@ -16,7 +16,7 @@
 
 /* Includes */
 
-#include <bits/libc-lock.h> /* for _LIBC_TSD_KEY_N */
+#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */
 #include <limits.h>
 #include <setjmp.h>
 #include <signal.h>
Index: linuxthreads/specific.c
===================================================================
RCS file: /glibc/cvsfiles/libc/linuxthreads/specific.c,v
retrieving revision 1.5
diff -u -p -r1.5 specific.c
--- linuxthreads/specific.c	1998/11/18 17:01:16	1.5
+++ linuxthreads/specific.c	1998/11/29 21:52:24
@@ -161,17 +161,23 @@ void __pthread_destroy_specifics()
 
 /* Thread-specific data for libc. */
 
-int __libc_internal_tsd_set(enum __libc_tsd_key_t key, const void * pointer)
+static int
+libc_internal_tsd_set(enum __libc_tsd_key_t key, const void * pointer)
 {
   pthread_descr self = thread_self();
 
   THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer);
   return 0;
 }
+int (*__libc_internal_tsd_set)(enum __libc_tsd_key_t key, const void * pointer)
+     = libc_internal_tsd_set;
 
-void * __libc_internal_tsd_get(enum __libc_tsd_key_t key)
+static void *
+libc_internal_tsd_get(enum __libc_tsd_key_t key)
 {
   pthread_descr self = thread_self();
 
   return THREAD_GETMEM_NC(self, p_libc_specific[key]);
 }
+void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
+     = libc_internal_tsd_get;
Index: linuxthreads/sysdeps/pthread/bits/libc-lock.h
===================================================================
RCS file: /glibc/cvsfiles/libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h,v
retrieving revision 1.7
diff -u -p -r1.7 libc-lock.h
--- linuxthreads/sysdeps/pthread/bits/libc-lock.h	1998/11/18 17:02:20	1.7
+++ linuxthreads/sysdeps/pthread/bits/libc-lock.h	1998/11/29 21:52:26
@@ -149,20 +149,7 @@ typedef pthread_key_t __libc_key_t;
 #define __libc_setspecific(KEY, VALUE) \
   (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0)
 
-#ifdef _LIBC
 
-/* Fast thread-specific data internal to libc.  */
-enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
-			_LIBC_TSD_KEY_DL_ERROR,
-			_LIBC_TSD_KEY_N };
-
-extern void *__libc_internal_tsd_get __P ((enum __libc_tsd_key_t));
-extern int __libc_internal_tsd_set __P ((enum __libc_tsd_key_t,
-					 __const void *));
-
-#endif
-
-
 /* Register handlers to execute before and after `fork'.  */
 #define __libc_atfork(PREPARE, PARENT, CHILD) \
   (__pthread_atfork != NULL ? __pthread_atfork (PREPARE, PARENT, CHILD) : 0)
@@ -183,8 +170,6 @@ weak_extern (__pthread_mutexattr_settype
 weak_extern (__pthread_key_create)
 weak_extern (__pthread_setspecific)
 weak_extern (__pthread_getspecific)
-weak_extern (__libc_internal_tsd_get)
-weak_extern (__libc_internal_tsd_set)
 weak_extern (__pthread_once)
 weak_extern (__pthread_initialize)
 weak_extern (__pthread_atfork)
@@ -202,8 +187,6 @@ weak_extern (_pthread_cleanup_pop_restor
 #  pragma weak __pthread_key_create
 #  pragma weak __pthread_setspecific
 #  pragma weak __pthread_getspecific
-#  pragma weak __libc_internal_tsd_get
-#  pragma weak __libc_internal_tsd_set
 #  pragma weak __pthread_once
 #  pragma weak __pthread_initialize
 #  pragma weak __pthread_atfork
Index: malloc/thread-m.h
===================================================================
RCS file: /glibc/cvsfiles/libc/malloc/thread-m.h,v
retrieving revision 1.8
diff -u -p -r1.8 thread-m.h
--- malloc/thread-m.h	1998/05/25 09:59:37	1.8
+++ malloc/thread-m.h	1998/11/29 21:52:26
@@ -40,20 +40,8 @@ typedef pthread_t thread_id;
 /* mutex */
 typedef pthread_mutex_t	mutex_t;
 
-/* thread specific data */
-typedef void * tsd_key_t;
-
 #define MUTEX_INITIALIZER	PTHREAD_MUTEX_INITIALIZER
 
-#define tsd_key_create(key, destr) ( *(key) = NULL )
-#define tsd_setspecific(key, data) \
-  if (__libc_internal_tsd_set != NULL) {				      \
-    __libc_internal_tsd_set(_LIBC_TSD_KEY_MALLOC, data);		      \
-  } else { (key) = (Void_t *) data; }
-#define tsd_getspecific(key, vptr) \
-  (vptr = (__libc_internal_tsd_get != NULL				      \
-	   ? __libc_internal_tsd_get(_LIBC_TSD_KEY_MALLOC) : (key)))
-
 #define mutex_init(m)		\
    (__pthread_mutex_init != NULL ? __pthread_mutex_init (m, NULL) : 0)
 #define mutex_lock(m)		\
@@ -85,20 +73,6 @@ typedef void * tsd_key_t;
 
 #define mutex_trylock(m) (!__mutex_trylock(m))
 
-#include <hurd/threadvar.h>
-
-/* thread specific data */
-typedef int tsd_key_t;
-
-static int tsd_keys_alloced = 0;
-
-#define tsd_key_create(key, destr) \
-  (assert (tsd_keys_alloced == 0), tsd_keys_alloced++)
-#define tsd_setspecific(key, data) \
-  (*__hurd_threadvar_location (_HURD_THREADVAR_MALLOC) = (unsigned long)(data))
-#define tsd_getspecific(key, vptr) \
-  ((vptr) = (void *)*__hurd_threadvar_location (_HURD_THREADVAR_MALLOC))
-
 #define thread_atfork(prepare, parent, child) do {} while(0)
 #define thread_atfork_static(prepare, parent, child) \
  text_set_element(_hurd_fork_prepare_hook, prepare); \
@@ -113,6 +87,18 @@ static int tsd_keys_alloced = 0;
 #define NO_THREADS
 
 #endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */
+
+
+/* thread specific data */
+
+#include <bits/libc-tsd.h>
+
+typedef int tsd_key_t[0];	/* no key data structure, libc magic does it */
+__libc_tsd_define (, MALLOC)	/* declaration/common definition */
+#define tsd_key_create(key, destr)	((void) (key))
+#define tsd_setspecific(key, data)	__libc_tsd_set (MALLOC, (data))
+#define tsd_getspecific(key, vptr)	((vptr) = __libc_tsd_get (MALLOC))
+
 
 #elif defined(USE_PTHREADS) /* Posix threads */
 
Index: linuxthreads/Makefile
===================================================================
RCS file: /glibc/cvsfiles/libc/linuxthreads/Makefile,v
retrieving revision 1.9
diff -u -r1.9 Makefile
--- linuxthreads/Makefile	1998/11/18 16:57:43	1.9
+++ linuxthreads/Makefile	1998/11/30 01:34:54
@@ -27,7 +27,7 @@
 headers := pthread.h semaphore.h bits/semaphore.h
 distribute := internals.h queue.h restart.h spinlock.h
 
-routines := weaks
+routines := weaks no-tsd
 
 extra-libs := libpthread
 extra-libs-others := $(extra-libs)


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