Update.
authorUlrich Drepper <drepper@redhat.com>
Tue, 5 Feb 2002 00:57:29 +0000 (00:57 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 5 Feb 2002 00:57:29 +0000 (00:57 +0000)
* 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.

22 files changed:
ChangeLog
elf/Makefile
elf/rtld.c
include/resolv.h
linuxthreads/ChangeLog
linuxthreads/descr.h [new file with mode: 0644]
linuxthreads/internals.h
linuxthreads/sysdeps/i386/tls.h [new file with mode: 0644]
linuxthreads_db/ChangeLog
linuxthreads_db/td_ta_event_getmsg.c
linuxthreads_db/td_ta_map_id2thr.c
linuxthreads_db/td_ta_map_lwp2thr.c
linuxthreads_db/td_ta_thr_iter.c
linuxthreads_db/td_ta_tsd_iter.c
linuxthreads_db/td_thr_tsd.c
linuxthreads_db/td_thr_validate.c
linuxthreads_db/thread_dbP.h
resolv/resolv.h
sysdeps/generic/ldsodefs.h
sysdeps/generic/tls.h [new file with mode: 0644]
sysdeps/i386/dl-machine.h
sysdeps/i386/elf/configure

index f6c2bac..4931ba5 100644 (file)
--- 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.
index 1227774..e84c6d1 100644 (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
 
index e2360e3..b7439b2 100644 (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)
     {
index fe79c16..d4a531f 100644 (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
index 6f9c936..f55477e 100644 (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
diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h
new file mode 100644 (file)
index 0000000..4cfad89
--- /dev/null
@@ -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 */
index 8297c78..e1768b4 100644 (file)
 /* 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 (file)
index 0000000..17f6e0a
--- /dev/null
@@ -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 */
index 17a391a..d4cf2aa 100644 (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.
index 31ac80b..c3a4492 100644 (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
index 184f2de..e6be74f 100644 (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
index e7addf9..1fc614c 100644 (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
index 80ee539..7d70858 100644 (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
index 4dbc8dd..2eb41f6 100644 (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
index 0dd37f8..aa362fe 100644 (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
index 8821f0e..fcce270 100644 (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
index 8e87bae..5d88a81 100644 (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.  */
index bb8c782..238ea59 100644 (file)
  */
 
 #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_ */
index 0f63799..08785a8 100644 (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.  */
diff --git a/sysdeps/generic/tls.h b/sysdeps/generic/tls.h
new file mode 100644 (file)
index 0000000..3820162
--- /dev/null
@@ -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
index 69a0c55..f791fa3 100644 (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
     }
index e12bf4a..ca7f567 100755 (executable)
@@ -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