aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-05 00:57:29 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-05 00:57:29 +0000
commit535b764df5ca722066c2db615190e6a70688c6a6 (patch)
tree06f6ba9853ac4e8f698fc1e3b0b4cb80ffd06bae
parent67ddea92542c12f2099a89dbc58a045a65bb7771 (diff)
downloadglibc-535b764df5ca722066c2db615190e6a70688c6a6.tar.xz
glibc-535b764df5ca722066c2db615190e6a70688c6a6.zip
Update.
* 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.
-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