* 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.
This commit is contained in:
Ulrich Drepper 2002-02-05 00:57:29 +00:00
parent 67ddea9254
commit 535b764df5
22 changed files with 513 additions and 197 deletions

View file

@ -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.

View file

@ -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

View file

@ -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)
{

View file

@ -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

View file

@ -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

168
linuxthreads/descr.h Normal file
View file

@ -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 */

View file

@ -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. */

View file

@ -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 */

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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. */

View file

@ -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_ */

View file

@ -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. */

22
sysdeps/generic/tls.h Normal file
View file

@ -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

View file

@ -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
}

View file

@ -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