summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--elf/Makefile2
-rw-r--r--elf/rtld.c75
-rw-r--r--include/resolv.h2
-rw-r--r--linuxthreads/ChangeLog6
-rw-r--r--linuxthreads/descr.h168
-rw-r--r--linuxthreads/internals.h141
-rw-r--r--linuxthreads/sysdeps/i386/tls.h95
-rw-r--r--linuxthreads_db/ChangeLog11
-rw-r--r--linuxthreads_db/td_ta_event_getmsg.c3
-rw-r--r--linuxthreads_db/td_ta_map_id2thr.c3
-rw-r--r--linuxthreads_db/td_ta_map_lwp2thr.c3
-rw-r--r--linuxthreads_db/td_ta_thr_iter.c3
-rw-r--r--linuxthreads_db/td_ta_tsd_iter.c3
-rw-r--r--linuxthreads_db/td_thr_tsd.c3
-rw-r--r--linuxthreads_db/td_thr_validate.c3
-rw-r--r--linuxthreads_db/thread_dbP.h2
-rw-r--r--resolv/resolv.h101
-rw-r--r--sysdeps/generic/ldsodefs.h6
-rw-r--r--sysdeps/generic/tls.h22
-rw-r--r--sysdeps/i386/dl-machine.h39
-rwxr-xr-xsysdeps/i386/elf/configure6
22 files changed, 513 insertions, 197 deletions
diff --git a/ChangeLog b/ChangeLog
index f6c2bac197..4931ba52c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2002-02-04 Ulrich Drepper <drepper@redhat.com>
+ * elf/rtld.c (_dl_start_final): Allocate TLS and initialize
+ thread-pointer as soon as possible.
+ * sysdeps/generic/ldsodefs.h: Include <tls.h>. Define first TLS
+ elements in rtld_global.
+ * sysdeps/generic/tls.h: New file.
+ * elf/Makefile (distribute): Add tls.h.
+ * sysdeps/i386/dl-machine.h (elf_machine_rel): Add support for TLS
+ relocations. Not complete yet.
+
+ * resolv/resolv.h: Allow user to define __need_res_state and only
+ define __res_start structure then.
+ * include/resolv.h: Only declare functions if _RESOLV_H_ is defined.
+
* sysdeps/generic/dl-sysdep.c (_dl_sysdep_start): Move
dl_cpuclock_offset initialization to _dl_start_final.
(_dl_show_auxv): Avoid unnecessary sign extension.
diff --git a/elf/Makefile b/elf/Makefile
index 12277741c4..e84c6d15cc 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -67,7 +67,7 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
reldep6mod4.c reldep6mod3.c reldep6mod2.c reldep6mod1.c \
reldep6mod0.c \
unwind-dw2.c unwind-dw2-fde.c unwind.h unwind-pe.h \
- unwind-dw2-fde.h dwarf2.h dl-procinfo.c
+ unwind-dw2-fde.h dwarf2.h dl-procinfo.c tls.h
include ../Makeconfig
diff --git a/elf/rtld.c b/elf/rtld.c
index e2360e3ae1..b7439b2e7b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -218,6 +218,16 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
which use `alloca'. */
ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr)));
extern char _begin[], _end[];
+#ifdef USE_TLS
+ ElfW(Ehdr) *ehdr;
+ ElfW(Phdr) *phdr;
+ size_t cnt;
+ size_t tlssize = 0;
+ size_t tlsimagesize = 0;
+ const void *tlsimage = NULL;
+ void *tlsblock = NULL;
+ dtv_t initdtv[2];
+#endif
if (HP_TIMING_AVAIL)
{
@@ -244,11 +254,76 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
HP_TIMING_NOW (GL(dl_cpuclock_offset));
#endif
+#if USE_TLS
+ /* Get the dynamic linkers program header. */
+ ehdr = (ElfW(Ehdr) *) bootstrap_map_p->l_addr;
+ phdr = (ElfW(Phdr) *) (bootstrap_map_p->l_addr + ehdr->e_phoff);
+ for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+ if (phdr[cnt].p_type == PT_TLS)
+ {
+ size_t align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
+
+ tlssize = phdr[cnt].p_memsz;
+ tlsimagesize = phdr[cnt].p_filesz;
+ tlsimage = (void *) (bootstrap_map_p->l_addr + phdr[cnt].p_offset);
+
+ /* We can now allocate the initial TLS block. This can happen
+ on the stack. We'll get the final memory later when we
+ know all about the various objects loaded at startup
+ time. */
+# if TLS_TCB_AT_TP
+ tlsblock = alloca (roundup (tlssize, TLS_INIT_TCB_ALIGN)
+ + TLS_INIT_TCB_SIZE
+ + align);
+# elif TLS_DTV_AT_TP
+ tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align)
+ + tlssize
+ + align);
+# else
+ /* In case a model with a different layout for the TCB and DTV
+ is defined add another #elif here and in the following #ifs. */
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+ /* Align the TLS block. */
+ tlsblock = (void *) (((uintptr_t) tlsblock + align - 1)
+ & ~(align - 1));
+
+ /* Initialize the dtv. */
+ initdtv[0].counter = 1;
+
+ /* Initialize the TLS block. */
+# if TLS_TCB_AT_TP
+ initdtv[1].pointer = tlsblock;
+# elif TLS_DTV_AT_TP
+ GL(rtld_tlsoffset) = roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align);
+ initdtv[1].pointer = (char *) tlsblock + GL(rtld_tlsoffset);
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+ memset (__mempcpy (initdtv[1].pointer, tlsimage, tlsimagesize),
+ '\0', tlssize - tlsimagesize);
+
+ /* Initialize the thread pointer. */
+# if TLS_TCB_AT_TP
+ GL(rtld_tlsoffset) = roundup (tlssize, TLS_INIT_TCB_ALIGN);
+ TLS_INIT_TP ((char *) tlsblock + GL(rtld_tlsoffset), initdtv);
+# elif TLS_DTV_AT_TP
+ TLS_INIT_TP (tlsblock, intidtv);
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /* There can only be one PT_TLS entry. */
+ break;
+ }
+#endif /* use TLS */
+
/* Call the OS-dependent function to set up life so we can do things like
file access. It will call `dl_main' (below) to do all the real work
of the dynamic linker, and then unwind our frame and run the user
entry point on the same stack we entered on. */
*start_addr = _dl_sysdep_start (arg, &dl_main);
+
#ifndef HP_TIMING_NONAVAIL
if (HP_TIMING_AVAIL)
{
diff --git a/include/resolv.h b/include/resolv.h
index fe79c16ba3..d4a531f244 100644
--- a/include/resolv.h
+++ b/include/resolv.h
@@ -10,6 +10,7 @@
#include <resolv/resolv.h>
+#ifdef _RESOLV_H_
/* Now define the internal interfaces. */
extern int __res_vinit (res_state, int);
extern void _sethtent (int);
@@ -26,5 +27,6 @@ extern void res_send_setqhook (res_send_qhook __hook);
extern void res_send_setrhook (res_send_rhook __hook);
extern int res_ourserver_p (const res_state __statp,
const struct sockaddr_in6 *__inp);
+#endif
#endif
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 6f9c93687b..f55477ea41 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,9 @@
+2002-02-04 Ulrich Drepper <drepper@redhat.com>
+
+ * internals.h: Move thread descriptor definition...
+ * descr.h.: ...here. New file.
+ * sysdeps/i386/tls.h: New file.
+
2002-02-01 H.J. Lu <hjl@gnu.org>
* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Use a
diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h
new file mode 100644
index 0000000000..4cfad89dcb
--- /dev/null
+++ b/linuxthreads/descr.h
@@ -0,0 +1,168 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix */
+/* threads for Linux. */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU Library General Public License for more details. */
+
+#ifndef _DESCR_H
+#define _DESCR_H 1
+
+#define __need_res_state
+#include <resolv.h>
+#include <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <hp-timing.h>
+#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */
+
+
+/* The type of thread descriptors */
+typedef struct _pthread_descr_struct *pthread_descr;
+
+
+/* Some more includes. */
+#include <pt-machine.h>
+#include <linuxthreads_db/thread_dbP.h>
+
+
+/* Arguments passed to thread creation routine */
+struct pthread_start_args {
+ void *(*start_routine)(void *); /* function to run */
+ void *arg; /* its argument */
+ sigset_t mask; /* initial signal mask for thread */
+ int schedpolicy; /* initial scheduling policy (if any) */
+ struct sched_param schedparam; /* initial scheduling parameters (if any) */
+};
+
+
+/* Callback interface for removing the thread from waiting on an
+ object if it is cancelled while waiting or about to wait.
+ This hold a pointer to the object, and a pointer to a function
+ which ``extricates'' the thread from its enqueued state.
+ The function takes two arguments: pointer to the wait object,
+ and a pointer to the thread. It returns 1 if an extrication
+ actually occured, and hence the thread must also be signalled.
+ It returns 0 if the thread had already been extricated. */
+typedef struct _pthread_extricate_struct {
+ void *pu_object;
+ int (*pu_extricate_func)(void *, pthread_descr);
+} pthread_extricate_if;
+
+
+/* Atomic counter made possible by compare_and_swap */
+struct pthread_atomic {
+ long p_count;
+ int p_spinlock;
+};
+
+
+/* Context info for read write locks. The pthread_rwlock_info structure
+ is information about a lock that has been read-locked by the thread
+ in whose list this structure appears. The pthread_rwlock_context
+ is embedded in the thread context and contains a pointer to the
+ head of the list of lock info structures, as well as a count of
+ read locks that are untracked, because no info structure could be
+ allocated for them. */
+struct _pthread_rwlock_t;
+typedef struct _pthread_rwlock_info {
+ struct _pthread_rwlock_info *pr_next;
+ struct _pthread_rwlock_t *pr_lock;
+ int pr_lock_count;
+} pthread_readlock_info;
+
+
+/* We keep thread specific data in a special data structure, a two-level
+ array. The top-level array contains pointers to dynamically allocated
+ arrays of a certain number of data pointers. So we can implement a
+ sparse array. Each dynamic second-level array has
+ PTHREAD_KEY_2NDLEVEL_SIZE
+ entries. This value shouldn't be too large. */
+#define PTHREAD_KEY_2NDLEVEL_SIZE 32
+
+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
+ keys in each subarray. */
+#define PTHREAD_KEY_1STLEVEL_SIZE \
+ ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
+ / PTHREAD_KEY_2NDLEVEL_SIZE)
+
+
+union dtv;
+
+
+struct _pthread_descr_struct {
+ /* XXX Remove this union for IA-64 style TLS module */
+ union {
+ struct {
+ pthread_descr self; /* Pointer to this structure */
+ union dtv *dtvp;
+ } data;
+ void *__padding[16];
+ } p_header;
+ pthread_descr p_nextlive, p_prevlive;
+ /* Double chaining of active threads */
+ pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */
+ pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */
+ pthread_t p_tid; /* Thread identifier */
+ int p_pid; /* PID of Unix process */
+ int p_priority; /* Thread priority (== 0 if not realtime) */
+ struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
+ int p_signal; /* last signal received */
+ sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */
+ sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */
+ char p_terminated; /* true if terminated e.g. by pthread_exit */
+ char p_detached; /* true if detached */
+ char p_exited; /* true if the assoc. process terminated */
+ void * p_retval; /* placeholder for return value */
+ int p_retcode; /* placeholder for return code */
+ pthread_descr p_joining; /* thread joining on that thread or NULL */
+ struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
+ char p_cancelstate; /* cancellation state */
+ char p_canceltype; /* cancellation type (deferred/async) */
+ char p_canceled; /* cancellation request pending */
+ 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_sigwaiting; /* true if a sigwait() is in progress */
+ struct pthread_start_args p_start_args; /* arguments for thread creation */
+ void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
+ void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
+ int p_userstack; /* nonzero if the user provided the stack */
+ void *p_guardaddr; /* address of guard area or NULL */
+ size_t p_guardsize; /* size of guard area */
+ int p_nr; /* Index of descriptor in __pthread_handles */
+ int p_report_events; /* Nonzero if events must be reported. */
+ td_eventbuf_t p_eventbuf; /* Data for event. */
+ struct pthread_atomic p_resume_count; /* number of times restart() was
+ called on thread */
+ char p_woken_by_cancel; /* cancellation performed wakeup */
+ char p_condvar_avail; /* flag if conditional variable became avail */
+ char p_sem_avail; /* flag if semaphore became available */
+ pthread_extricate_if *p_extricate; /* See above */
+ pthread_readlock_info *p_readlock_list; /* List of readlock info structs */
+ pthread_readlock_info *p_readlock_free; /* Free list of structs */
+ int p_untracked_readlock_count; /* Readlocks not tracked by list */
+ 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 */
+#if HP_TIMING_AVAIL
+ hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */
+#endif
+ /* New elements must be added at the end. */
+} __attribute__ ((aligned(32))); /* We need to align the structure so that
+ doubles are aligned properly. This is 8
+ bytes on MIPS and 16 bytes on MIPS64.
+ 32 bytes might give better cache
+ utilization. */
+
+#endif /* descr.h */
diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h
index 8297c781c8..e1768b4a1f 100644
--- a/linuxthreads/internals.h
+++ b/linuxthreads/internals.h
@@ -20,21 +20,15 @@
/* Includes */
#include <limits.h>
-#include <resolv.h>
-#include <setjmp.h>
-#include <signal.h>
#include <unistd.h>
#include <stackinfo.h>
-#include <sys/types.h>
-#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */
+
+#include "descr.h"
extern long int testandset (int *spinlock);
extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-#include "pt-machine.h"
#include "semaphore.h"
-#include "../linuxthreads_db/thread_dbP.h"
-#include <hp-timing.h>
#ifndef THREAD_GETMEM
# define THREAD_GETMEM(descr, member) descr->member
@@ -49,31 +43,6 @@ extern int __compare_and_swap (long int *p, long int oldval, long int newval);
# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value)
#endif
-/* Arguments passed to thread creation routine */
-
-struct pthread_start_args {
- void * (*start_routine)(void *); /* function to run */
- void * arg; /* its argument */
- sigset_t mask; /* initial signal mask for thread */
- int schedpolicy; /* initial scheduling policy (if any) */
- struct sched_param schedparam; /* initial scheduling parameters (if any) */
-};
-
-
-/* We keep thread specific data in a special data structure, a two-level
- array. The top-level array contains pointers to dynamically allocated
- arrays of a certain number of data pointers. So we can implement a
- sparse array. Each dynamic second-level array has
- PTHREAD_KEY_2NDLEVEL_SIZE
- entries. This value shouldn't be too large. */
-#define PTHREAD_KEY_2NDLEVEL_SIZE 32
-
-/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
- keys in each subarray. */
-#define PTHREAD_KEY_1STLEVEL_SIZE \
- ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
- / PTHREAD_KEY_2NDLEVEL_SIZE)
-
typedef void (*destr_function)(void *);
struct pthread_key_struct {
@@ -85,112 +54,6 @@ struct pthread_key_struct {
#define PTHREAD_START_ARGS_INITIALIZER(fct) \
{ (void *(*) (void *)) fct, NULL, {{0, }}, 0, { 0 } }
-/* The type of thread descriptors */
-
-typedef struct _pthread_descr_struct * pthread_descr;
-
-/* Callback interface for removing the thread from waiting on an
- object if it is cancelled while waiting or about to wait.
- This hold a pointer to the object, and a pointer to a function
- which ``extricates'' the thread from its enqueued state.
- The function takes two arguments: pointer to the wait object,
- and a pointer to the thread. It returns 1 if an extrication
- actually occured, and hence the thread must also be signalled.
- It returns 0 if the thread had already been extricated. */
-
-typedef struct _pthread_extricate_struct {
- void *pu_object;
- int (*pu_extricate_func)(void *, pthread_descr);
-} pthread_extricate_if;
-
-/* Atomic counter made possible by compare_and_swap */
-
-struct pthread_atomic {
- long p_count;
- int p_spinlock;
-};
-
-/* Context info for read write locks. The pthread_rwlock_info structure
- is information about a lock that has been read-locked by the thread
- in whose list this structure appears. The pthread_rwlock_context
- is embedded in the thread context and contains a pointer to the
- head of the list of lock info structures, as well as a count of
- read locks that are untracked, because no info structure could be
- allocated for them. */
-
-struct _pthread_rwlock_t;
-
-typedef struct _pthread_rwlock_info {
- struct _pthread_rwlock_info *pr_next;
- struct _pthread_rwlock_t *pr_lock;
- int pr_lock_count;
-} pthread_readlock_info;
-
-struct _pthread_descr_struct {
- union {
- struct {
- pthread_descr self; /* Pointer to this structure */
- } data;
- void *__padding[16];
- } p_header;
- pthread_descr p_nextlive, p_prevlive;
- /* Double chaining of active threads */
- pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */
- pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */
- pthread_t p_tid; /* Thread identifier */
- int p_pid; /* PID of Unix process */
- int p_priority; /* Thread priority (== 0 if not realtime) */
- struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
- int p_signal; /* last signal received */
- sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */
- sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */
- char p_terminated; /* true if terminated e.g. by pthread_exit */
- char p_detached; /* true if detached */
- char p_exited; /* true if the assoc. process terminated */
- void * p_retval; /* placeholder for return value */
- int p_retcode; /* placeholder for return code */
- pthread_descr p_joining; /* thread joining on that thread or NULL */
- struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
- char p_cancelstate; /* cancellation state */
- char p_canceltype; /* cancellation type (deferred/async) */
- char p_canceled; /* cancellation request pending */
- 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_sigwaiting; /* true if a sigwait() is in progress */
- struct pthread_start_args p_start_args; /* arguments for thread creation */
- void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
- void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
- int p_userstack; /* nonzero if the user provided the stack */
- void *p_guardaddr; /* address of guard area or NULL */
- size_t p_guardsize; /* size of guard area */
- int p_nr; /* Index of descriptor in __pthread_handles */
- int p_report_events; /* Nonzero if events must be reported. */
- td_eventbuf_t p_eventbuf; /* Data for event. */
- struct pthread_atomic p_resume_count; /* number of times restart() was
- called on thread */
- char p_woken_by_cancel; /* cancellation performed wakeup */
- char p_condvar_avail; /* flag if conditional variable became avail */
- char p_sem_avail; /* flag if semaphore became available */
- pthread_extricate_if *p_extricate; /* See above */
- pthread_readlock_info *p_readlock_list; /* List of readlock info structs */
- pthread_readlock_info *p_readlock_free; /* Free list of structs */
- int p_untracked_readlock_count; /* Readlocks not tracked by list */
- 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 */
-#if HP_TIMING_AVAIL
- hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */
-#endif
- /* New elements must be added at the end. */
-} __attribute__ ((aligned(32))); /* We need to align the structure so that
- doubles are aligned properly. This is 8
- bytes on MIPS and 16 bytes on MIPS64.
- 32 bytes might give better cache
- utilization. */
-
/* The type of thread handles. */
diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h
new file mode 100644
index 0000000000..17f6e0ae45
--- /dev/null
+++ b/linuxthreads/sysdeps/i386/tls.h
@@ -0,0 +1,95 @@
+/* Definition for thread-local data handling. linuxthreads/i386 version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+ void *tcb;
+ dtv_t *dtv;
+} tcbhead_t;
+
+
+/* Get the thread descriptor definition. */
+#include <linuxthreads/descr.h>
+
+
+/* We can support TLS only if the floating-stack support is available. */
+#if FLOATING_STACKS && defined HAVE_TLS_SUPPORT
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* Signal that TLS support is available. */
+# define USE_TLS 1
+
+/* This is the size of the initial TCB. */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB. */
+# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The TCB can have any size and the memory following the address the
+ thread pointer points to is unspecified. Allocate the TCB there. */
+# define TLS_TCB_AT_TP 1
+
+/* Code to initially initialize the thread pointer. This might need
+ special attention since 'errno' is not yet available and if the
+ operation can cause a failure 'errno' must not be touched. */
+# define TLS_INIT_TP(descr, dtvp) \
+ do { \
+ void *_descr = (descr); \
+ struct modify_ldt_ldt_s ldt_entry = \
+ { 0, (unsigned long int) _descr, 1048576, 1, 0, 0, 1, 0, 1, 0 }; \
+ int result; \
+ tcbhead_t *head = _descr; \
+ \
+ head->tcb = _descr; \
+ head->dtv = dtvp; \
+ \
+ asm ("pushl %%ebx\n\t" \
+ "movl $1, %%ebx\n\t" \
+ "int $0x80\n\t" \
+ "popl %%ebx" \
+ : "=a" (result) \
+ : "0" (__NR_modify_ldt), "d" (sizeof (ldt_entry)), "c" (&ldt_entry));\
+ \
+ if (__builtin_expect (result, 0) != 0) \
+ /* Nothing else we can do. */ \
+ asm ("hlt"); \
+ } while (0)
+
+#endif
+
+#endif /* tls.h */
diff --git a/linuxthreads_db/ChangeLog b/linuxthreads_db/ChangeLog
index 17a391add8..d4cf2aaeb7 100644
--- a/linuxthreads_db/ChangeLog
+++ b/linuxthreads_db/ChangeLog
@@ -1,3 +1,14 @@
+2002-02-04 Ulrich Drepper <drepper@redhat.com>
+
+ * thread_dbP.h: Include descr.h instead of internals.h.
+ * td_ta_event_getmsg.c: Also include <linuxthreads/internals.h>.
+ * td_ta_map_id2thr.c: Likewise.
+ * td_ta_map_lwp2thr.c: Likewise.
+ * td_ta_thr_iter.c: Likewise.
+ * td_ta_tsd_iter.c: Likewise.
+ * td_thr_tsd.c: Likewise.
+ * td_thr_validate.c: Likewise.
+
2001-12-28 Andreas Jaeger <aj@suse.de>
* td_init.c (td_init): Don't use __FUNCTION__ as literal.
diff --git a/linuxthreads_db/td_ta_event_getmsg.c b/linuxthreads_db/td_ta_event_getmsg.c
index 31ac80b69e..c3a4492a12 100644
--- a/linuxthreads_db/td_ta_event_getmsg.c
+++ b/linuxthreads_db/td_ta_event_getmsg.c
@@ -1,5 +1,5 @@
/* Retrieve event.
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -22,6 +22,7 @@
#include <string.h>
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
td_err_e
diff --git a/linuxthreads_db/td_ta_map_id2thr.c b/linuxthreads_db/td_ta_map_id2thr.c
index 184f2de2e1..e6be74ff19 100644
--- a/linuxthreads_db/td_ta_map_id2thr.c
+++ b/linuxthreads_db/td_ta_map_id2thr.c
@@ -1,5 +1,5 @@
/* Map thread ID to thread handle.
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
td_err_e
diff --git a/linuxthreads_db/td_ta_map_lwp2thr.c b/linuxthreads_db/td_ta_map_lwp2thr.c
index e7addf9cc7..1fc614cc21 100644
--- a/linuxthreads_db/td_ta_map_lwp2thr.c
+++ b/linuxthreads_db/td_ta_map_lwp2thr.c
@@ -1,5 +1,5 @@
/* Which thread is running on an lwp?
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
td_err_e
diff --git a/linuxthreads_db/td_ta_thr_iter.c b/linuxthreads_db/td_ta_thr_iter.c
index 80ee539297..7d7085870f 100644
--- a/linuxthreads_db/td_ta_thr_iter.c
+++ b/linuxthreads_db/td_ta_thr_iter.c
@@ -1,5 +1,5 @@
/* Iterate over a process's threads.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
#include <alloca.h>
static int
diff --git a/linuxthreads_db/td_ta_tsd_iter.c b/linuxthreads_db/td_ta_tsd_iter.c
index 4dbc8dd647..2eb41f6a15 100644
--- a/linuxthreads_db/td_ta_tsd_iter.c
+++ b/linuxthreads_db/td_ta_tsd_iter.c
@@ -1,5 +1,5 @@
/* Iterate over a process's thread-specific data.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
#include <alloca.h>
td_err_e
diff --git a/linuxthreads_db/td_thr_tsd.c b/linuxthreads_db/td_thr_tsd.c
index 0dd37f8f2b..aa362fe68a 100644
--- a/linuxthreads_db/td_thr_tsd.c
+++ b/linuxthreads_db/td_thr_tsd.c
@@ -1,5 +1,5 @@
/* Get a thread-specific data pointer for a thread.
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
td_err_e
diff --git a/linuxthreads_db/td_thr_validate.c b/linuxthreads_db/td_thr_validate.c
index 8821f0e846..fcce270f29 100644
--- a/linuxthreads_db/td_thr_validate.c
+++ b/linuxthreads_db/td_thr_validate.c
@@ -1,5 +1,5 @@
/* Validate a thread handle.
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include "thread_dbP.h"
+#include <linuxthreads/internals.h>
td_err_e
diff --git a/linuxthreads_db/thread_dbP.h b/linuxthreads_db/thread_dbP.h
index 8e87bae52d..5d88a81528 100644
--- a/linuxthreads_db/thread_dbP.h
+++ b/linuxthreads_db/thread_dbP.h
@@ -5,7 +5,7 @@
#include <string.h>
#include "proc_service.h"
#include "thread_db.h"
-#include "../linuxthreads/internals.h"
+#include "../linuxthreads/descr.h"
/* Indeces for the symbol names. */
diff --git a/resolv/resolv.h b/resolv/resolv.h
index bb8c782939..238ea59d65 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -50,39 +50,24 @@
*/
#ifndef _RESOLV_H_
-#define _RESOLV_H_
+#ifndef __need_res_state
+# define _RESOLV_H_
-#include <sys/param.h>
-#if (!defined(BSD)) || (BSD < 199306)
-# include <sys/bitypes.h>
-#else
-# include <sys/types.h>
+# include <sys/param.h>
+# if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+# else
+# include <sys/types.h>
+# endif
+# include <sys/cdefs.h>
+# include <stdio.h>
+# include <arpa/nameser.h>
#endif
-#include <sys/cdefs.h>
-#include <stdio.h>
#include <netinet/in.h>
-#include <arpa/nameser.h>
-
-/*
- * Revision information. This is the release date in YYYYMMDD format.
- * It can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__RES > 19931104)". Do not
- * compare for equality; rather, use it to determine whether your resolver
- * is new enough to contain a certain feature.
- */
-#define __RES 19991006
-
-/*
- * Resolver configuration file.
- * Normally not present, but may contain the address of the
- * inital name server(s) to query and the domain search list.
- */
-
-#ifndef _PATH_RESCONF
-#define _PATH_RESCONF "/etc/resolv.conf"
-#endif
+#ifndef __res_state_defined
+# define __res_state_defined
typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
res_sendhookact;
@@ -101,27 +86,21 @@ typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns,
int anssiz,
int *resplen);
-struct res_sym {
- int number; /* Identifying number, like T_MX */
- char * name; /* Its symbolic name, like "MX" */
- char * humanname; /* Its fun name, like "mail exchanger" */
-};
-
/*
* Global defines and variables for resolver stub.
*/
-#define MAXNS 3 /* max # name servers we'll track */
-#define MAXDFLSRCH 3 /* # default domain levels to try */
-#define MAXDNSRCH 6 /* max # domains in search path */
-#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
+# define MAXNS 3 /* max # name servers we'll track */
+# define MAXDFLSRCH 3 /* # default domain levels to try */
+# define MAXDNSRCH 6 /* max # domains in search path */
+# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
-#define RES_TIMEOUT 5 /* min. seconds between retries */
-#define MAXRESOLVSORT 10 /* number of net to sort on */
-#define RES_MAXNDOTS 15 /* should reflect bit field size */
-#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */
-#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */
-#define RES_DFLRETRY 2 /* Default #/tries. */
-#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */
+# define RES_TIMEOUT 5 /* min. seconds between retries */
+# define MAXRESOLVSORT 10 /* number of net to sort on */
+# define RES_MAXNDOTS 15 /* should reflect bit field size */
+# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */
+# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */
+# define RES_DFLRETRY 2 /* Default #/tries. */
+# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */
struct __res_state {
int retrans; /* retransmition time interval */
@@ -130,7 +109,7 @@ struct __res_state {
int nscount; /* number of name servers */
struct sockaddr_in
nsaddr_list[MAXNS]; /* address of name server */
-#define nsaddr nsaddr_list[0] /* for backward compatibility */
+# define nsaddr nsaddr_list[0] /* for backward compatibility */
u_short id; /* current message id */
char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
char defdname[256]; /* default domain (deprecated) */
@@ -161,6 +140,35 @@ struct __res_state {
};
typedef struct __res_state *res_state;
+# undef __need_res_state
+#endif
+
+#ifdef _RESOLV_H_
+/*
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define __RES 19991006
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+
+struct res_sym {
+ int number; /* Identifying number, like T_MX */
+ char * name; /* Its symbolic name, like "MX" */
+ char * humanname; /* Its fun name, like "mail exchanger" */
+};
/*
* Resolver flags (used to be discrete per-module statics ints).
@@ -374,5 +382,6 @@ int res_nmkquery __P((res_state,
int res_nsend __P((res_state, const u_char *, int, u_char *, int));
void res_nclose __P((res_state));
__END_DECLS
+#endif
#endif /* !_RESOLV_H_ */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 0f63799524..08785a818e 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -35,6 +35,7 @@
#include <dl-lookupcfg.h>
#include <bits/libc-lock.h>
#include <hp-timing.h>
+#include <tls.h>
__BEGIN_DECLS
@@ -286,6 +287,11 @@ struct rtld_global
EXTERN hp_timing_t _dl_hp_timing_overhead;
#endif
+#ifdef USE_TLS
+ /* Offset of the TLS block for ld.so from the thread-pointer. */
+ EXTERN size_t _rtld_tlsoffset;
+#endif
+
/* Name of the shared object to be profiled (if any). */
EXTERN const char *_dl_profile;
/* Map of shared object to be profiled. */
diff --git a/sysdeps/generic/tls.h b/sysdeps/generic/tls.h
new file mode 100644
index 0000000000..3820162ae8
--- /dev/null
+++ b/sysdeps/generic/tls.h
@@ -0,0 +1,22 @@
+/* Definition for thread-local data handling. Generic version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* By default no TLS support is available. This is signaled by the
+ absence of the symbol USE_TLS. */
+#undef USE_TLS
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 69a0c5550e..f791fa3ffa 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -342,7 +342,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
else
#endif
{
-#ifdef RTLD_BOOTSTRAP
+#if defined RTLD_BOOTSTRAP && !defined USE_TLS
Elf32_Addr value;
assert (r_type == R_386_GLOB_DAT || r_type == R_386_JMP_SLOT);
@@ -352,7 +352,9 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
#else
const Elf32_Sym *const refsym = sym;
Elf32_Addr value = RESOLVE (&sym, version, r_type);
+# ifndef RTLD_BOOTSTRAP
if (sym)
+# endif
value += sym->st_value;
switch (r_type)
@@ -361,6 +363,40 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
case R_386_JMP_SLOT:
*reloc_addr = value;
break;
+
+ /* XXX Remove TLS relocations which are not needed. */
+
+ case R_386_TLS_DTPMOD32:
+# ifdef RTLD_BOOTSTRAP
+ /* During startup the dynamic linker is always the module
+ with index 1.
+ XXX If this relocation is necessary move before RESOLVE
+ call. */
+ *reloc_addr = 1;
+# else
+ /* XXX Implement. RESOLVE must return the map from which we
+ get the module ID. */
+ _exit (99);
+# endif
+ break;
+ case R_386_TLS_DTPOFF32:
+# ifndef RTLD_BOOTSTRAP
+ /* During relocation all TLS symbols are defined and used.
+ Therefore the offset is already correct. */
+ *reloc_addr = sym->st_value;
+# endif
+ break;
+ case R_386_TLS_TPOFF32:
+ /* The offset is positive, backward from the thread pointer. */
+# ifdef RTLD_BOOTSTRAP
+ *reloc_addr = GL(rtld_tlsoffset) - sym->st_value;
+# else
+ /* XXX Implement. */
+ _exit (98);
+# endif
+ break;
+
+# ifndef RTLD_BOOTSTRAP
case R_386_32:
*reloc_addr += value;
break;
@@ -390,6 +426,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
+# endif
}
#endif
}
diff --git a/sysdeps/i386/elf/configure b/sysdeps/i386/elf/configure
index e12bf4a164..ca7f567bcb 100755
--- a/sysdeps/i386/elf/configure
+++ b/sysdeps/i386/elf/configure
@@ -9,16 +9,18 @@ if eval "test \"`echo '$''{'libc_cv_386_tls'+set}'`\" = set"; then
else
cat > conftest.s <<\EOF
.section ".tdata", "awT", @progbits
+ .globl foo
foo: .long 1
.section ".tbss", "awT", @nobits
- .comm bar,4,4
+ .globl bar
+bar: .skip 4
.text
baz: leal bar@TLSLDM(%ebx), %eax
leal bar@DTPOFF(%eax), %edx
subl foo@GOTTPOFF(%edx), %eax
subl $bar@TPOFF, %eax
EOF
-if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:22: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
+if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:24: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
libc_cv_386_tls=yes
else
libc_cv_386_tls=no