* sysdeps/pthread/bits/libc-tsd.h: Include <tls.h>.

[USE_TLS && HAVE___THREAD]: Just include the sysdeps/generic file,
	which does the right thing when __thread support is available.
	* descr.h (struct _pthread_descr_struct) [USE_TLS && HAVE___THREAD]:
	Omit `p_libc_specific', `p_errnop', `p_errno', `p_h_errnop',
	`p_h_errno', `p_resp', and `p_res' members.
	* pthread.c (__pthread_initialize_minimal) [USE_TLS && HAVE___THREAD]:
	Don't initialize `p_errnop' and `p_h_errnop' members.
	(__pthread_reset_main_thread): Likewise.
	(__pthread_initialize_manager): Likewise.
	* manager.c (__pthread_manager, pthread_handle_create): Likewise.
	* pthread.c (pthread_initialize) [USE_TLS && HAVE___THREAD]:
	Don't initialize `p_resp' member.
	(__pthread_reset_main_thread): Likewise.
	* manager.c (pthread_handle_create): Likewise.
	* specific.c (libc_internal_tsd_set, libc_internal_tsd_get):
	Conditionalize these on [!(USE_TLS && HAVE___THREAD)].
	* errno.c [USE_TLS && HAVE___THREAD]
	(__h_errno_location, __res_state): Don't define these at all.

	* sysdeps/i386/tls.h (INSTALL_DTV): Add parens around arguments!
	(INSTALL_NEW_DTV, GET_DTV): Likewise.
	* sysdeps/sh/tls.h (INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV): Likewise.

	* weaks.c: Don't include <errno.h> here.

2002-08-01  Roland McGrath  <roland@redhat.com>

	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): New macro, broken out of
	TLS_INIT_TP.
	(TLS_DO_SET_THREAD_AREA): New macro, uses thread_set_area syscall.
	(TLS_SETUP_GS_SEGMENT): New macro, try one or the other or both.
	(TLS_INIT_TP): Use that.
This commit is contained in:
Roland McGrath 2002-08-02 03:32:24 +00:00
parent ae8f7f19fa
commit c2afe83352
26 changed files with 228 additions and 102 deletions

View File

@ -1,5 +1,5 @@
/* libc-internal interface for thread-specific data. Stub version. /* libc-internal interface for thread-specific data. Stub or TLS version.
Copyright (C) 1998, 2001 Free Software Foundation, Inc. Copyright (C) 1998,2001,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -17,8 +17,8 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#ifndef _BITS_LIBC_TSD_H #ifndef _GENERIC_BITS_LIBC_TSD_H
#define _BITS_LIBC_TSD_H 1 #define _GENERIC_BITS_LIBC_TSD_H 1
/* This file defines the following macros for accessing a small fixed /* This file defines the following macros for accessing a small fixed
set of thread-specific `void *' data used only internally by libc. set of thread-specific `void *' data used only internally by libc.
@ -40,13 +40,22 @@
Some implementations may not provide any enum at all and instead Some implementations may not provide any enum at all and instead
using string pasting in the macros. */ using string pasting in the macros. */
/* This is the generic/stub implementation for wholly single-threaded #include <tls.h>
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; /* When full support for __thread variables is available, this interface is
#define __libc_tsd_get(KEY) (__libc_tsd_##KEY##_data) just a trivial wrapper for it. Without TLS, this is the generic/stub
#define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY##_data = (VALUE)) 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. */
#if USE_TLS && HAVE___THREAD
# define __libc_tsd_define(CLASS, KEY) CLASS __thread void *__libc_tsd_##KEY;
#else
# define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY;
#endif
#define __libc_tsd_get(KEY) (__libc_tsd_##KEY)
#define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY = (VALUE))
#endif /* bits/libc-tsd.h */ #endif /* bits/libc-tsd.h */

View File

@ -1166,8 +1166,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
elf_get_dynamic_info (l); elf_get_dynamic_info (l);
/* Make sure we are dlopen()ing an object which has the DF_1_NOOPEN /* Make sure we are not dlopen'ing an object
flag set. */ that has the DF_1_NOOPEN flag set. */
if ((__builtin_expect (l->l_flags_1 & DF_1_NOOPEN, 0) if ((__builtin_expect (l->l_flags_1 & DF_1_NOOPEN, 0)
#ifdef USE_TLS #ifdef USE_TLS
|| __builtin_expect (l->l_flags & DF_STATIC_TLS, 0) || __builtin_expect (l->l_flags & DF_STATIC_TLS, 0)
@ -1861,7 +1861,7 @@ cannot create shared object descriptor"));
} }
else else
INTUSE(_dl_signal_error) (errno, name, NULL, INTUSE(_dl_signal_error) (errno, name, NULL,
N_("cannot open shared object file")); N_("cannot open shared object file"));
} }
return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode); return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode);

View File

@ -1,13 +1,20 @@
#ifndef _ERRNO_H
#include <stdlib/errno.h> #include <stdlib/errno.h>
#ifdef _ERRNO_H #ifdef _ERRNO_H
#if USE_TLS && HAVE___THREAD # include <tls.h> /* Defines USE_TLS. */
# undef errno
extern __thread int errno;
# define __set_errno(val) (errno = (val))
#else
# define __set_errno(val) (*__errno_location ()) = (val)
#endif
#endif # if USE_TLS && HAVE___THREAD
# undef errno
# define errno errno /* For #ifndef errno tests. */
extern __thread int errno;
# define __set_errno(val) (errno = (val))
# else
# define __set_errno(val) (*__errno_location ()) = (val)
# endif
#endif /* _ERRNO_H */
#endif /* ! _ERRNO_H */

View File

@ -1,6 +1,26 @@
#ifndef _NETDB_H #ifndef _NETDB_H
#include <resolv/netdb.h> #include <resolv/netdb.h>
/* Macros for accessing h_errno from inside libc. */
# ifdef _LIBC_REENTRANT
# include <tls.h>
# if USE_TLS && HAVE___THREAD
# undef h_errno
# define h_errno h_errno /* For #ifndef h_errno tests. */
extern __thread int h_errno;
# define __set_h_errno(x) (h_errno = (x))
# else
static inline int
__set_h_errno (int __err)
{
return *__h_errno_location () = __err;
}
# endif
# else
# undef h_errno
# define __set_h_errno(x) (h_errno = (x))
# endif /* _LIBC_REENTRANT */
/* Document internal interfaces. */ /* Document internal interfaces. */
extern int __gethostent_r (struct hostent *__restrict __result_buf, extern int __gethostent_r (struct hostent *__restrict __result_buf,
char *__restrict __buf, size_t __buflen, char *__restrict __buf, size_t __buflen,

View File

@ -11,6 +11,19 @@
#include <resolv/resolv.h> #include <resolv/resolv.h>
#ifdef _RESOLV_H_ #ifdef _RESOLV_H_
# ifdef _LIBC_REENTRANT
# include <tls.h>
# if USE_TLS && HAVE___THREAD
# undef _res
extern __thread struct __res_state _res;
# endif
# else
# ifndef __BIND_NOSTATIC
extern struct __res_state _res;
# endif
# endif
/* Now define the internal interfaces. */ /* Now define the internal interfaces. */
extern int __res_vinit (res_state, int); extern int __res_vinit (res_state, int);
extern void _sethtent (int); extern void _sethtent (int);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. /* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -20,12 +20,19 @@
#include <netdb.h> #include <netdb.h>
#undef h_errno #undef h_errno
#include <tls.h>
/* We need to have the error status variable of the resolver /* We need to have the error status variable of the resolver
accessible in the libc. */ accessible in the libc. */
#if USE_TLS && HAVE___THREAD
__thread int h_errno;
#else
int h_errno = 0; int h_errno = 0;
weak_alias (h_errno, _h_errno) weak_alias (h_errno, _h_errno)
#endif
/* When threaded, h_errno may be a per-process variable. */ /* When threaded, h_errno may be a per-thread variable. */
int * int *
weak_const_function weak_const_function
__h_errno_location (void) __h_errno_location (void)

View File

@ -35,6 +35,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifdef __GNUC__ #ifdef __GNUC__
# undef alloca
# define alloca __builtin_alloca # define alloca __builtin_alloca
# define HAVE_ALLOCA 1 # define HAVE_ALLOCA 1
#else #else

View File

@ -1,3 +1,39 @@
2002-07-30 Roland McGrath <roland@redhat.com>
* sysdeps/pthread/bits/libc-tsd.h: Include <tls.h>.
[USE_TLS && HAVE___THREAD]: Just include the sysdeps/generic file,
which does the right thing when __thread support is available.
* descr.h (struct _pthread_descr_struct) [USE_TLS && HAVE___THREAD]:
Omit `p_libc_specific', `p_errnop', `p_errno', `p_h_errnop',
`p_h_errno', `p_resp', and `p_res' members.
* pthread.c (__pthread_initialize_minimal) [USE_TLS && HAVE___THREAD]:
Don't initialize `p_errnop' and `p_h_errnop' members.
(__pthread_reset_main_thread): Likewise.
(__pthread_initialize_manager): Likewise.
* manager.c (__pthread_manager, pthread_handle_create): Likewise.
* pthread.c (pthread_initialize) [USE_TLS && HAVE___THREAD]:
Don't initialize `p_resp' member.
(__pthread_reset_main_thread): Likewise.
* manager.c (pthread_handle_create): Likewise.
* specific.c (libc_internal_tsd_set, libc_internal_tsd_get):
Conditionalize these on [!(USE_TLS && HAVE___THREAD)].
* errno.c [USE_TLS && HAVE___THREAD]
(__h_errno_location, __res_state): Don't define these at all.
* sysdeps/i386/tls.h (INSTALL_DTV): Add parens around arguments!
(INSTALL_NEW_DTV, GET_DTV): Likewise.
* sysdeps/sh/tls.h (INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV): Likewise.
* weaks.c: Don't include <errno.h> here.
2002-08-01 Roland McGrath <roland@redhat.com>
* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): New macro, broken out of
TLS_INIT_TP.
(TLS_DO_SET_THREAD_AREA): New macro, uses thread_set_area syscall.
(TLS_SETUP_GS_SEGMENT): New macro, try one or the other or both.
(TLS_INIT_TP): Use that.
2002-08-02 Jakub Jelinek <jakub@redhat.com> 2002-08-02 Jakub Jelinek <jakub@redhat.com>
* sysdeps/i386/useldt.h (DO_MODIFY_LDT): Move from INIT_THREAD_SELF. * sysdeps/i386/useldt.h (DO_MODIFY_LDT): Move from INIT_THREAD_SELF.

View File

@ -130,15 +130,19 @@ struct _pthread_descr_struct {
char p_cancelstate; /* cancellation state */ char p_cancelstate; /* cancellation state */
char p_canceltype; /* cancellation type (deferred/async) */ char p_canceltype; /* cancellation type (deferred/async) */
char p_canceled; /* cancellation request pending */ char p_canceled; /* cancellation request pending */
int * p_errnop; /* pointer to used errno variable */
int p_errno; /* error returned by last system call */
int * p_h_errnop; /* pointer to used h_errno variable */
int p_h_errno; /* error returned by last netdb function */
char * p_in_sighandler; /* stack address of sighandler, or NULL */ char * p_in_sighandler; /* stack address of sighandler, or NULL */
char p_sigwaiting; /* true if a sigwait() is in progress */ char p_sigwaiting; /* true if a sigwait() is in progress */
struct pthread_start_args p_start_args; /* arguments for thread creation */ struct pthread_start_args p_start_args; /* arguments for thread creation */
void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
#if !(USE_TLS && HAVE___THREAD)
void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
int * p_errnop; /* pointer to used errno variable */
int p_errno; /* error returned by last system call */
int * p_h_errnop; /* pointer to used h_errno variable */
int p_h_errno; /* error returned by last netdb function */
struct __res_state *p_resp; /* Pointer to resolver state */
struct __res_state p_res; /* per-thread resolver state */
#endif
int p_userstack; /* nonzero if the user provided the stack */ int p_userstack; /* nonzero if the user provided the stack */
void *p_guardaddr; /* address of guard area or NULL */ void *p_guardaddr; /* address of guard area or NULL */
size_t p_guardsize; /* size of guard area */ size_t p_guardsize; /* size of guard area */
@ -154,8 +158,6 @@ struct _pthread_descr_struct {
pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ pthread_readlock_info *p_readlock_list; /* List of readlock info structs */
pthread_readlock_info *p_readlock_free; /* Free list of structs */ pthread_readlock_info *p_readlock_free; /* Free list of structs */
int p_untracked_readlock_count; /* Readlocks not tracked by list */ int p_untracked_readlock_count; /* Readlocks not tracked by list */
struct __res_state *p_resp; /* Pointer to resolver state */
struct __res_state p_res; /* per-thread resolver state */
int p_inheritsched; /* copied from the thread attribute */ int p_inheritsched; /* copied from the thread attribute */
#if HP_TIMING_AVAIL #if HP_TIMING_AVAIL
hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */

View File

@ -28,7 +28,6 @@ int * __errno_location()
pthread_descr self = thread_self(); pthread_descr self = thread_self();
return THREAD_GETMEM (self, p_errnop); return THREAD_GETMEM (self, p_errnop);
} }
#endif
int * __h_errno_location() int * __h_errno_location()
{ {
@ -42,3 +41,4 @@ struct __res_state * __res_state()
pthread_descr self = thread_self(); pthread_descr self = thread_self();
return THREAD_GETMEM (self, p_resp); return THREAD_GETMEM (self, p_resp);
} }
#endif

View File

@ -138,9 +138,11 @@ __pthread_manager(void *arg)
#ifdef INIT_THREAD_SELF #ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(self, 1); INIT_THREAD_SELF(self, 1);
#endif #endif
#if !(USE_TLS && HAVE___THREAD)
/* Set the error variable. */ /* Set the error variable. */
self->p_errnop = &self->p_errno; self->p_errnop = &self->p_errno;
self->p_h_errnop = &self->p_h_errno; self->p_h_errnop = &self->p_h_errno;
#endif
/* Block all signals except __pthread_sig_cancel and SIGTRAP */ /* Block all signals except __pthread_sig_cancel and SIGTRAP */
sigfillset(&manager_mask); sigfillset(&manager_mask);
sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
@ -640,9 +642,11 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
new_thread->p_lock = &(__pthread_handles[sseg].h_lock); new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
#if !(USE_TLS && HAVE___THREAD)
new_thread->p_errnop = &new_thread->p_errno; new_thread->p_errnop = &new_thread->p_errno;
new_thread->p_h_errnop = &new_thread->p_h_errno; new_thread->p_h_errnop = &new_thread->p_h_errno;
new_thread->p_resp = &new_thread->p_res; new_thread->p_resp = &new_thread->p_res;
#endif
new_thread->p_guardaddr = guardaddr; new_thread->p_guardaddr = guardaddr;
new_thread->p_guardsize = guardsize; new_thread->p_guardsize = guardsize;
new_thread->p_header.data.self = new_thread; new_thread->p_header.data.self = new_thread;

View File

@ -33,27 +33,28 @@
#include <ldsodefs.h> #include <ldsodefs.h>
#include <tls.h> #include <tls.h>
/* We need the global/static resolver state here. */
#include <resolv.h>
#undef _res
extern struct __res_state _res;
/* Sanity check. */ /* Sanity check. */
#if __ASSUME_REALTIME_SIGNALS && !defined __SIGRTMIN #if __ASSUME_REALTIME_SIGNALS && !defined __SIGRTMIN
# error "This must not happen; new kernel assumed but old headers" # error "This must not happen; new kernel assumed but old headers"
#endif #endif
/* These variables are used by the setup code. */
extern int _errno;
extern int _h_errno;
#ifdef USE_TLS #ifdef USE_TLS
/* We need only a few variables. */ /* We need only a few variables. */
static pthread_descr manager_thread; static pthread_descr manager_thread;
#else #else
/* These variables are used by the setup code. */
extern int _errno;
extern int _h_errno;
/* We need the global/static resolver state here. */
#include <resolv.h>
#undef _res
extern struct __res_state _res;
/* Descriptor of the initial thread */ /* Descriptor of the initial thread */
struct _pthread_descr_struct __pthread_initial_thread = { struct _pthread_descr_struct __pthread_initial_thread = {
@ -83,16 +84,18 @@ struct _pthread_descr_struct __pthread_initial_thread = {
0, /* char p_cancelstate */ 0, /* char p_cancelstate */
0, /* char p_canceltype */ 0, /* char p_canceltype */
0, /* char p_canceled */ 0, /* char p_canceled */
&_errno, /* int *p_errnop */
0, /* int p_errno */
&_h_errno, /* int *p_h_errnop */
0, /* int p_h_errno */
NULL, /* char * p_in_sighandler */ NULL, /* char * p_in_sighandler */
0, /* char p_sigwaiting */ 0, /* char p_sigwaiting */
PTHREAD_START_ARGS_INITIALIZER(NULL), PTHREAD_START_ARGS_INITIALIZER(NULL),
/* struct pthread_start_args p_start_args */ /* struct pthread_start_args p_start_args */
{NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
{NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
&_errno, /* int *p_errnop */
0, /* int p_errno */
&_h_errno, /* int *p_h_errnop */
0, /* int p_h_errno */
&_res, /* struct __res_state *p_resp */
{}, /* struct __res_state p_res */
1, /* int p_userstack */ 1, /* int p_userstack */
NULL, /* void * p_guardaddr */ NULL, /* void * p_guardaddr */
0, /* size_t p_guardsize */ 0, /* size_t p_guardsize */
@ -141,16 +144,18 @@ struct _pthread_descr_struct __pthread_manager_thread = {
0, /* char p_cancelstate */ 0, /* char p_cancelstate */
0, /* char p_canceltype */ 0, /* char p_canceltype */
0, /* char p_canceled */ 0, /* char p_canceled */
&__pthread_manager_thread.p_errno, /* int *p_errnop */
0, /* int p_errno */
NULL, /* int *p_h_errnop */
0, /* int p_h_errno */
NULL, /* char * p_in_sighandler */ NULL, /* char * p_in_sighandler */
0, /* char p_sigwaiting */ 0, /* char p_sigwaiting */
PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), PTHREAD_START_ARGS_INITIALIZER(__pthread_manager),
/* struct pthread_start_args p_start_args */ /* struct pthread_start_args p_start_args */
{NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
{NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
&__pthread_manager_thread.p_errno, /* int *p_errnop */
0, /* int p_errno */
NULL, /* int *p_h_errnop */
0, /* int p_h_errno */
NULL, /* struct __res_state *p_resp */
{}, /* struct __res_state p_res */
0, /* int p_userstack */ 0, /* int p_userstack */
NULL, /* void * p_guardaddr */ NULL, /* void * p_guardaddr */
0, /* size_t p_guardsize */ 0, /* size_t p_guardsize */
@ -423,8 +428,10 @@ __pthread_initialize_minimal(void)
self->p_nextlive = self->p_prevlive = self; self->p_nextlive = self->p_prevlive = self;
self->p_tid = PTHREAD_THREADS_MAX; self->p_tid = PTHREAD_THREADS_MAX;
self->p_lock = &__pthread_handles[0].h_lock; self->p_lock = &__pthread_handles[0].h_lock;
# ifndef HAVE___THREAD
self->p_errnop = &_errno; self->p_errnop = &_errno;
self->p_h_errnop = &_h_errno; self->p_h_errnop = &_h_errno;
# endif
/* self->p_start_args need not be initialized, it's all zero. */ /* self->p_start_args need not be initialized, it's all zero. */
self->p_userstack = 1; self->p_userstack = 1;
# if __LT_SPINLOCK_INIT != 0 # if __LT_SPINLOCK_INIT != 0
@ -521,8 +528,10 @@ static void pthread_initialize(void)
#ifdef USE_TLS #ifdef USE_TLS
/* Update the descriptor for the initial thread. */ /* Update the descriptor for the initial thread. */
THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid()); THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid());
# ifndef HAVE___THREAD
/* Likewise for the resolver state _res. */ /* Likewise for the resolver state _res. */
THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res); THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res);
# endif
#else #else
/* Update the descriptor for the initial thread. */ /* Update the descriptor for the initial thread. */
__pthread_initial_thread.p_pid = __getpid(); __pthread_initial_thread.p_pid = __getpid();
@ -615,7 +624,9 @@ int __pthread_initialize_manager(void)
/* Initialize the descriptor. */ /* Initialize the descriptor. */
tcb->p_header.data.self = tcb; tcb->p_header.data.self = tcb;
tcb->p_lock = &__pthread_handles[1].h_lock; tcb->p_lock = &__pthread_handles[1].h_lock;
# ifndef HAVE___THREAD
tcb->p_errnop = &tcb->p_errno; tcb->p_errnop = &tcb->p_errno;
# endif
tcb->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); tcb->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager);
tcb->p_nr = 1; tcb->p_nr = 1;
# if __LT_SPINLOCK_INIT != 0 # if __LT_SPINLOCK_INIT != 0
@ -1048,10 +1059,12 @@ void __pthread_reset_main_thread(void)
__pthread_main_thread = self; __pthread_main_thread = self;
THREAD_SETMEM(self, p_nextlive, self); THREAD_SETMEM(self, p_nextlive, self);
THREAD_SETMEM(self, p_prevlive, self); THREAD_SETMEM(self, p_prevlive, self);
#if !(USE_TLS && HAVE___THREAD)
/* Now this thread modifies the global variables. */ /* Now this thread modifies the global variables. */
THREAD_SETMEM(self, p_errnop, &_errno); THREAD_SETMEM(self, p_errnop, &_errno);
THREAD_SETMEM(self, p_h_errnop, &_h_errno); THREAD_SETMEM(self, p_h_errnop, &_h_errno);
THREAD_SETMEM(self, p_resp, &_res); THREAD_SETMEM(self, p_resp, &_res);
#endif
if (getrlimit (RLIMIT_STACK, &limit) == 0 if (getrlimit (RLIMIT_STACK, &limit) == 0
&& limit.rlim_cur != limit.rlim_max) { && limit.rlim_cur != limit.rlim_max) {

View File

@ -204,6 +204,8 @@ void __pthread_destroy_specifics()
__pthread_unlock(THREAD_GETMEM(self, p_lock)); __pthread_unlock(THREAD_GETMEM(self, p_lock));
} }
#if !(USE_TLS && HAVE___THREAD)
/* Thread-specific data for libc. */ /* Thread-specific data for libc. */
static int static int
@ -226,3 +228,5 @@ libc_internal_tsd_get(enum __libc_tsd_key_t key)
} }
void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key) void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
= libc_internal_tsd_get; = libc_internal_tsd_get;
#endif

View File

@ -1,5 +1,5 @@
/* libc-internal interface for thread-specific data. LinuxThreads version. /* libc-internal interface for thread-specific data. LinuxThreads version.
Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. Copyright (C) 1997,98,99,2001,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -20,13 +20,21 @@
#ifndef _BITS_LIBC_TSD_H #ifndef _BITS_LIBC_TSD_H
#define _BITS_LIBC_TSD_H 1 #define _BITS_LIBC_TSD_H 1
/* Fast thread-specific data internal to libc. */ /* Fast thread-specific data internal to libc. */
enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
_LIBC_TSD_KEY_DL_ERROR, _LIBC_TSD_KEY_DL_ERROR,
_LIBC_TSD_KEY_RPC_VARS, _LIBC_TSD_KEY_RPC_VARS,
_LIBC_TSD_KEY_N }; _LIBC_TSD_KEY_N };
#include <tls.h>
#if USE_TLS && HAVE___THREAD
/* When __thread works, the generic definition is what we want. */
# include <sysdeps/generic/bits/libc-tsd.h>
#else
extern void *(*__libc_internal_tsd_get) (enum __libc_tsd_key_t) __THROW; extern void *(*__libc_internal_tsd_get) (enum __libc_tsd_key_t) __THROW;
extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t, extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t,
__const void *) __THROW; __const void *) __THROW;
@ -41,4 +49,6 @@ extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t,
? __libc_internal_tsd_set (_LIBC_TSD_KEY_##KEY, (VALUE)) \ ? __libc_internal_tsd_set (_LIBC_TSD_KEY_##KEY, (VALUE)) \
: ((__libc_tsd_##KEY##_data = (VALUE)), 0)) : ((__libc_tsd_##KEY##_data = (VALUE)), 0))
#endif
#endif /* bits/libc-tsd.h */ #endif /* bits/libc-tsd.h */

View File

@ -73,16 +73,16 @@ typedef struct
/* Install the dtv pointer. The pointer passed is to the element with /* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */ index -1 which contain the length. */
# define INSTALL_DTV(descr, dtvp) \ # define INSTALL_DTV(descr, dtvp) \
((tcbhead_t *) descr)->dtv = dtvp + 1 ((tcbhead_t *) (descr))->dtv = dtvp + 1
/* Install new dtv for current thread. */ /* Install new dtv for current thread. */
# define INSTALL_NEW_DTV(dtv) \ # define INSTALL_NEW_DTV(dtv) \
({ struct _pthread_descr_struct *__descr; \ ({ struct _pthread_descr_struct *__descr; \
THREAD_SETMEM (__descr, p_header.data.dtvp, dtv); }) THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
/* Return dtv of given thread descriptor. */ /* Return dtv of given thread descriptor. */
# define GET_DTV(descr) \ # define GET_DTV(descr) \
(((tcbhead_t *) descr)->dtv) (((tcbhead_t *) (descr))->dtv)
/* Code to initially initialize the thread pointer. This might need /* Code to initially initialize the thread pointer. This might need
special attention since 'errno' is not yet available and if the special attention since 'errno' is not yet available and if the
@ -94,7 +94,7 @@ typedef struct
tcbhead_t *head = _descr; \ tcbhead_t *head = _descr; \
\ \
head->tcb = _descr; \ head->tcb = _descr; \
/* For now the thread descriptor is at the same address. */ \ /* For now the thread descriptor is at the same address. */ \
head->self = _descr; \ head->self = _descr; \
\ \
asm ("ldc %0,gbr" : : "r" (_descr)); \ asm ("ldc %0,gbr" : : "r" (_descr)); \

View File

@ -1,5 +1,5 @@
/* The weak pthread functions for Linux. /* The weak pthread functions for Linux.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -17,7 +17,6 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <shlib-compat.h> #include <shlib-compat.h>

View File

@ -516,6 +516,9 @@ Void_t *(*__morecore)(ptrdiff_t) = __default_morecore;
#if (__STD_C || defined(HAVE_MEMCPY)) #if (__STD_C || defined(HAVE_MEMCPY))
#ifdef _LIBC
# include <string.h>
#else
#ifdef WIN32 #ifdef WIN32
/* On Win32 memset and memcpy are already declared in windows.h */ /* On Win32 memset and memcpy are already declared in windows.h */
#else #else
@ -528,6 +531,7 @@ Void_t* memcpy();
#endif #endif
#endif #endif
#endif #endif
#endif
/* /*
MALLOC_FAILURE_ACTION is the action to take before "return 0" when MALLOC_FAILURE_ACTION is the action to take before "return 0" when

View File

@ -1,5 +1,5 @@
/* `fd_set' type and related macros, and `select'/`pselect' declarations. /* `fd_set' type and related macros, and `select'/`pselect' declarations.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -54,6 +54,10 @@ typedef __suseconds_t suseconds_t;
/* The fd_set member is required to be an array of longs. */ /* The fd_set member is required to be an array of longs. */
typedef long int __fd_mask; typedef long int __fd_mask;
/* Some versions of <linux/posix_types.h> define these macros. */
#undef __NFDBITS
#undef __FDELT
#undef __FDMASK
/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ /* It's easier to assume 8-bit bytes than to get CHAR_BIT. */
#define __NFDBITS (8 * sizeof (__fd_mask)) #define __NFDBITS (8 * sizeof (__fd_mask))
#define __FDELT(d) ((d) / __NFDBITS) #define __FDELT(d) ((d) / __NFDBITS)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. /* Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -59,23 +59,8 @@ extern int h_errno;
/* Function to get address of global `h_errno' variable. */ /* Function to get address of global `h_errno' variable. */
extern int *__h_errno_location (void) __THROW __attribute__ ((__const__)); extern int *__h_errno_location (void) __THROW __attribute__ ((__const__));
#ifdef _LIBC
# ifdef _LIBC_REENTRANT
static inline int
__set_h_errno (int __err)
{
return *__h_errno_location () = __err;
}
# else
# define __set_h_errno(x) (h_errno = (x))
# endif /* _LIBC_REENTRANT */
#endif /* _LIBC */
#if !defined _LIBC || defined _LIBC_REENTRANT
/* Use a macro to access always the thread specific `h_errno' variable. */ /* Use a macro to access always the thread specific `h_errno' variable. */
# define h_errno (*__h_errno_location ()) #define h_errno (*__h_errno_location ())
#endif
/* Possible values left in `h_errno'. */ /* Possible values left in `h_errno'. */

View File

@ -39,8 +39,6 @@ static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixi
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#undef _res
const char *_res_opcodes[] = { const char *_res_opcodes[] = {
"QUERY", "QUERY",
"IQUERY", "IQUERY",
@ -71,9 +69,9 @@ const char *_res_sectioncodes[] = {
#ifndef __BIND_NOSTATIC #ifndef __BIND_NOSTATIC
#ifdef _LIBC #ifdef _LIBC
extern struct __res_state _res;
#else
/* The definition has been moved to res_libc.c. */ /* The definition has been moved to res_libc.c. */
#else
#undef _res
struct __res_state _res struct __res_state _res
# if defined(__BIND_RES_TEXT) # if defined(__BIND_RES_TEXT)
= { RES_TIMEOUT, } /* Motorola, et al. */ = { RES_TIMEOUT, } /* Motorola, et al. */

View File

@ -22,8 +22,15 @@
#undef _res #undef _res
#include <tls.h>
#if USE_TLS && HAVE___THREAD
/* With __thread support, this per-thread variable is used in all cases. */
__thread struct __res_state _res;
#else
/* The resolver state for use by single-threaded programs. */ /* The resolver state for use by single-threaded programs. */
struct __res_state _res; struct __res_state _res;
#endif
/* This function is used to access the resolver state in /* This function is used to access the resolver state in
single-threaded programs. */ single-threaded programs. */

View File

@ -224,16 +224,10 @@ struct res_sym {
/* 0x00008000 */ /* 0x00008000 */
/* Things involving an internal (static) resolver context. */ /* Things involving an internal (static) resolver context. */
#if !defined _LIBC || defined _LIBC_REENTRANT
__BEGIN_DECLS __BEGIN_DECLS
extern struct __res_state *__res_state(void) __attribute__ ((__const__)); extern struct __res_state *__res_state(void) __attribute__ ((__const__));
__END_DECLS __END_DECLS
#define _res (*__res_state()) #define _res (*__res_state())
#else
#ifndef __BIND_NOSTATIC
extern struct __res_state _res;
#endif
#endif
#ifndef __BIND_NOSTATIC #ifndef __BIND_NOSTATIC
#define fp_nquery __fp_nquery #define fp_nquery __fp_nquery

View File

@ -8,11 +8,9 @@
#ifdef _RPC_THREAD_SAFE_ #ifdef _RPC_THREAD_SAFE_
/* Variable used in non-threaded applications or for the first thread. */ /* Variable used in non-threaded applications or for the first thread. */
static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem; static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
static struct rpc_thread_variables *__libc_tsd_RPC_VARS_data = __libc_tsd_define (static, RPC_VARS)
&__libc_tsd_RPC_VARS_mem;
/* /*
* Task-variable destructor * Task-variable destructor
@ -20,7 +18,7 @@ static struct rpc_thread_variables *__libc_tsd_RPC_VARS_data =
void void
__rpc_thread_destroy (void) __rpc_thread_destroy (void)
{ {
struct rpc_thread_variables *tvp = __rpc_thread_variables(); struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS);
if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) { if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
__rpc_thread_svc_cleanup (); __rpc_thread_svc_cleanup ();
@ -61,7 +59,7 @@ __rpc_thread_variables (void)
if (tvp != NULL) if (tvp != NULL)
__libc_tsd_set (RPC_VARS, tvp); __libc_tsd_set (RPC_VARS, tvp);
else else
tvp = __libc_tsd_RPC_VARS_data; tvp = __libc_tsd_get (RPC_VARS);
} }
} }
return tvp; return tvp;

View File

@ -1,5 +1,5 @@
/* libc-internal interface for thread-specific data. Stub version. /* libc-internal interface for thread-specific data. Stub or TLS version.
Copyright (C) 1998, 2001 Free Software Foundation, Inc. Copyright (C) 1998,2001,02 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -17,8 +17,8 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#ifndef _BITS_LIBC_TSD_H #ifndef _GENERIC_BITS_LIBC_TSD_H
#define _BITS_LIBC_TSD_H 1 #define _GENERIC_BITS_LIBC_TSD_H 1
/* This file defines the following macros for accessing a small fixed /* This file defines the following macros for accessing a small fixed
set of thread-specific `void *' data used only internally by libc. set of thread-specific `void *' data used only internally by libc.
@ -40,13 +40,22 @@
Some implementations may not provide any enum at all and instead Some implementations may not provide any enum at all and instead
using string pasting in the macros. */ using string pasting in the macros. */
/* This is the generic/stub implementation for wholly single-threaded #include <tls.h>
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; /* When full support for __thread variables is available, this interface is
#define __libc_tsd_get(KEY) (__libc_tsd_##KEY##_data) just a trivial wrapper for it. Without TLS, this is the generic/stub
#define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY##_data = (VALUE)) 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. */
#if USE_TLS && HAVE___THREAD
# define __libc_tsd_define(CLASS, KEY) CLASS __thread void *__libc_tsd_##KEY;
#else
# define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY;
#endif
#define __libc_tsd_get(KEY) (__libc_tsd_##KEY)
#define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY = (VALUE))
#endif /* bits/libc-tsd.h */ #endif /* bits/libc-tsd.h */

View File

@ -1,5 +1,5 @@
/* Generic asm macros used on many machines. /* Generic asm macros used on many machines.
Copyright (C) 1991, 92, 93, 96, 98 Free Software Foundation, Inc. Copyright (C) 1991,92,93,96,98,2002 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -36,8 +36,10 @@
#endif #endif
#ifdef __ASSEMBLER__
/* Mark the end of function named SYM. This is used on some platforms /* Mark the end of function named SYM. This is used on some platforms
to generate correct debugging information. */ to generate correct debugging information. */
#ifndef END #ifndef END
#define END(sym) #define END(sym)
#endif #endif
#endif /* __ASSEMBLER__ */

View File

@ -33,12 +33,12 @@
#undef SYS_ify #undef SYS_ify
#define SYS_ify(syscall_name) __NR_##syscall_name #define SYS_ify(syscall_name) __NR_##syscall_name
#ifdef __ASSEMBLER__
/* ELF-like local names start with `.L'. */ /* ELF-like local names start with `.L'. */
#undef L #undef L
#define L(name) .L##name #define L(name) .L##name
#ifdef __ASSEMBLER__
/* Linux uses a negative return value to indicate syscall errors, /* Linux uses a negative return value to indicate syscall errors,
unlike most Unices, which use the condition codes' carry flag. unlike most Unices, which use the condition codes' carry flag.