From 535b764df5ca722066c2db615190e6a70688c6a6 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 5 Feb 2002 00:57:29 +0000 Subject: [PATCH] Update. * elf/rtld.c (_dl_start_final): Allocate TLS and initialize thread-pointer as soon as possible. * sysdeps/generic/ldsodefs.h: Include . 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. --- ChangeLog | 13 +++ elf/Makefile | 2 +- elf/rtld.c | 75 ++++++++++++++++ include/resolv.h | 2 + linuxthreads/ChangeLog | 6 ++ linuxthreads/descr.h | 168 +++++++++++++++++++++++++++++++++++ linuxthreads/internals.h | 141 +---------------------------- linuxthreads/sysdeps/i386/tls.h | 95 ++++++++++++++++++++ linuxthreads_db/ChangeLog | 11 +++ linuxthreads_db/td_ta_event_getmsg.c | 3 +- linuxthreads_db/td_ta_map_id2thr.c | 3 +- linuxthreads_db/td_ta_map_lwp2thr.c | 3 +- linuxthreads_db/td_ta_thr_iter.c | 3 +- linuxthreads_db/td_ta_tsd_iter.c | 3 +- linuxthreads_db/td_thr_tsd.c | 3 +- linuxthreads_db/td_thr_validate.c | 3 +- linuxthreads_db/thread_dbP.h | 2 +- resolv/resolv.h | 101 +++++++++++---------- sysdeps/generic/ldsodefs.h | 6 ++ sysdeps/generic/tls.h | 22 +++++ sysdeps/i386/dl-machine.h | 39 +++++++- sysdeps/i386/elf/configure | 6 +- 22 files changed, 513 insertions(+), 197 deletions(-) create mode 100644 linuxthreads/descr.h create mode 100644 linuxthreads/sysdeps/i386/tls.h create mode 100644 sysdeps/generic/tls.h diff --git a/ChangeLog b/ChangeLog index f6c2bac..4931ba5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2002-02-04 Ulrich Drepper + * elf/rtld.c (_dl_start_final): Allocate TLS and initialize + thread-pointer as soon as possible. + * sysdeps/generic/ldsodefs.h: Include . 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 1227774..e84c6d1 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 e2360e3..b7439b2 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 fe79c16..d4a531f 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -10,6 +10,7 @@ #include +#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 6f9c936..f55477e 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,9 @@ +2002-02-04 Ulrich Drepper + + * internals.h: Move thread descriptor definition... + * descr.h.: ...here. New file. + * sysdeps/i386/tls.h: New file. + 2002-02-01 H.J. Lu * sysdeps/mips/pspinlock.c (__pthread_spin_lock): Use a diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h new file mode 100644 index 0000000..4cfad89 --- /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 +#include +#include +#include +#include +#include +#include /* for _LIBC_TSD_KEY_N */ + + +/* The type of thread descriptors */ +typedef struct _pthread_descr_struct *pthread_descr; + + +/* Some more includes. */ +#include +#include + + +/* 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 8297c78..e1768b4 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -20,21 +20,15 @@ /* Includes */ #include -#include -#include -#include #include #include -#include -#include /* 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 #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 0000000..17f6e0a --- /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 + + +/* We can support TLS only if the floating-stack support is available. */ +#if FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Get system call information. */ +# include + +/* 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 17a391a..d4cf2aa 100644 --- a/linuxthreads_db/ChangeLog +++ b/linuxthreads_db/ChangeLog @@ -1,3 +1,14 @@ +2002-02-04 Ulrich Drepper + + * thread_dbP.h: Include descr.h instead of internals.h. + * td_ta_event_getmsg.c: Also include . + * 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 * 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 31ac80b..c3a4492 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 , 1999. @@ -22,6 +22,7 @@ #include #include "thread_dbP.h" +#include td_err_e diff --git a/linuxthreads_db/td_ta_map_id2thr.c b/linuxthreads_db/td_ta_map_id2thr.c index 184f2de..e6be74f 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include td_err_e diff --git a/linuxthreads_db/td_ta_map_lwp2thr.c b/linuxthreads_db/td_ta_map_lwp2thr.c index e7addf9..1fc614c 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include td_err_e diff --git a/linuxthreads_db/td_ta_thr_iter.c b/linuxthreads_db/td_ta_thr_iter.c index 80ee539..7d70858 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include #include static int diff --git a/linuxthreads_db/td_ta_tsd_iter.c b/linuxthreads_db/td_ta_tsd_iter.c index 4dbc8dd..2eb41f6 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include #include td_err_e diff --git a/linuxthreads_db/td_thr_tsd.c b/linuxthreads_db/td_thr_tsd.c index 0dd37f8..aa362fe 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include td_err_e diff --git a/linuxthreads_db/td_thr_validate.c b/linuxthreads_db/td_thr_validate.c index 8821f0e..fcce270 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 , 1999. @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include "thread_dbP.h" +#include td_err_e diff --git a/linuxthreads_db/thread_dbP.h b/linuxthreads_db/thread_dbP.h index 8e87bae..5d88a81 100644 --- a/linuxthreads_db/thread_dbP.h +++ b/linuxthreads_db/thread_dbP.h @@ -5,7 +5,7 @@ #include #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 bb8c782..238ea59 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 -#if (!defined(BSD)) || (BSD < 199306) -# include -#else -# include +# include +# if (!defined(BSD)) || (BSD < 199306) +# include +# else +# include +# endif +# include +# include +# include #endif -#include -#include #include -#include - -/* - * 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 0f63799..08785a8 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -35,6 +35,7 @@ #include #include #include +#include __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 0000000..3820162 --- /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 69a0c55..f791fa3 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 e12bf4a..ca7f567 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 -- 2.7.4