aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-23 08:47:54 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-23 08:47:54 +0000
commit557fab43bd3cf75f87ba7efb65c9f4884e261a6c (patch)
treea45a8e10024f1cd566da25113e7dc2f45b8bd9e3
parente413826144bcd0a910e8a6f942ec34a368f65613 (diff)
downloadglibc-557fab43bd3cf75f87ba7efb65c9f4884e261a6c.tar.xz
glibc-557fab43bd3cf75f87ba7efb65c9f4884e261a6c.zip
Update.
2002-02-23 Ulrich Drepper <drepper@redhat.com> * csu/set-init.c: Moved to... * sysdeps/mach/hurd/set-init.c: ...here. New file. * csu/Makefile: Don't compile set-init. * sysdeps/mach/hurd/Makefile: Compile set-init for subdir csu. * sysdeps/mach/hurd/i386/init-first.c: Call __init_misc in addition to __libc_init. * sysdeps/mach/hurd/mips/init-first.c: Likewise. * sysdeps/mach/hurd/powerpc/init-first.c: Likewise. * sysdeps/unix/sysv/linux/init-first.c: Call __init_misc instead of __libc_init. * misc/init-misc.c: Always export __init_misc. Don't define hooks for __libc_subinit.
-rw-r--r--ChangeLog15
-rw-r--r--csu/Makefile4
-rw-r--r--linuxthreads/ChangeLog13
-rw-r--r--linuxthreads/descr.h7
-rw-r--r--linuxthreads/internals.h1
-rw-r--r--linuxthreads/manager.c130
-rw-r--r--linuxthreads/pthread.c157
-rw-r--r--linuxthreads/sysdeps/i386/tls.h18
-rw-r--r--misc/init-misc.c16
-rw-r--r--sysdeps/mach/hurd/Makefile1
-rw-r--r--sysdeps/mach/hurd/i386/init-first.c2
-rw-r--r--sysdeps/mach/hurd/mips/init-first.c4
-rw-r--r--sysdeps/mach/hurd/powerpc/init-first.c4
-rw-r--r--sysdeps/mach/hurd/set-init.c (renamed from csu/set-init.c)0
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c4
15 files changed, 291 insertions, 85 deletions
diff --git a/ChangeLog b/ChangeLog
index 41d839c8b4..dbe013ef48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2002-02-23 Ulrich Drepper <drepper@redhat.com>
+
+ * csu/set-init.c: Moved to...
+ * sysdeps/mach/hurd/set-init.c: ...here. New file.
+ * csu/Makefile: Don't compile set-init.
+ * sysdeps/mach/hurd/Makefile: Compile set-init for subdir csu.
+ * sysdeps/mach/hurd/i386/init-first.c: Call __init_misc in addition
+ to __libc_init.
+ * sysdeps/mach/hurd/mips/init-first.c: Likewise.
+ * sysdeps/mach/hurd/powerpc/init-first.c: Likewise.
+ * sysdeps/unix/sysv/linux/init-first.c: Call __init_misc instead of
+ __libc_init.
+ * misc/init-misc.c: Always export __init_misc. Don't define hooks for
+ __libc_subinit.
+
2002-02-22 Ulrich Drepper <drepper@redhat.com>
* elf/Versions: Add _dl_allocate_tls and _dl_deallocate_tls.
diff --git a/csu/Makefile b/csu/Makefile
index 012cbbe209..994e2b29de 100644
--- a/csu/Makefile
+++ b/csu/Makefile
@@ -59,9 +59,7 @@ before-compile += $(objpfx)abi-tag.h
generated += abi-tag.h
endif
-ifeq (yes,$(gnu-ld))
-libc-init = set-init
-else
+ifneq (yes,$(gnu-ld))
libc-init = munch-init
$(objpfx)munch-init.c: munch.awk munch-tmpl.c $(+subdir_inits)
$(AWK) -f $< subdirs='$(+init_subdirs)' $(word 2,$^) > $@-t
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 762b29e2c7..2fc0a623d1 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,16 @@
+2002-02-23 Ulrich Drepper <drepper@redhat.com>
+
+ * descr.h (struct _pthread_descr_struct): Update p_header for TLS.
+ Add p_stackaddr element #if USE_TLS.
+ * internals.c: Include <tls.h>.
+ * manager.c: Integrate creating and handling of thread descriptor
+ for TLS.
+ * pthread.c: Likewise.
+ * sysdeps/i386/tls.h (tcbhead_t): Add self pointer.
+ Include <linuxthreads/descr.h> only if TLS is really used.
+ (GET_DTV): New macro.
+ (TLS_INIT_TP): Initialize self pointer.
+
2002-02-17 Andreas Schwab <schwab@suse.de>
* signals.c (sigwait): Check for old sighandler being SIG_ERR,
diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h
index a2cddb1212..d0c31da9b2 100644
--- a/linuxthreads/descr.h
+++ b/linuxthreads/descr.h
@@ -102,8 +102,10 @@ struct _pthread_descr_struct {
/* XXX Remove this union for IA-64 style TLS module */
union {
struct {
- pthread_descr self; /* Pointer to this structure */
+ void *tcb; /* Pointer to the TCB. This is not always
+ the address of this thread descriptor. */
union dtv *dtvp;
+ pthread_descr self; /* Pointer to this structure */
} data;
void *__padding[16];
} p_header;
@@ -158,6 +160,9 @@ struct _pthread_descr_struct {
#if HP_TIMING_AVAIL
hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */
#endif
+#ifdef USE_TLS
+ char *p_stackaddr; /* Stack address. */
+#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
diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h
index 056e36d885..209812c3da 100644
--- a/linuxthreads/internals.h
+++ b/linuxthreads/internals.h
@@ -23,6 +23,7 @@
#include <unistd.h>
#include <stackinfo.h>
+#include <tls.h>
#include "descr.h"
extern long int testandset (int *spinlock);
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c
index 9e4fcacb48..efbbf51b41 100644
--- a/linuxthreads/manager.c
+++ b/linuxthreads/manager.c
@@ -14,6 +14,7 @@
/* The "thread manager" thread: manages creation and termination of threads */
+#include <assert.h>
#include <errno.h>
#include <sched.h>
#include <stddef.h>
@@ -27,6 +28,7 @@
#include <sys/time.h>
#include <sys/wait.h> /* for waitpid macros */
+#include <ldsodefs.h>
#include "pthread.h"
#include "internals.h"
#include "spinlock.h"
@@ -34,9 +36,23 @@
#include "semaphore.h"
/* Array of active threads. Entry 0 is reserved for the initial thread. */
-struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
-{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0},
- { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ };
+struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]
+#ifdef USE_TLS
+# if __LT_SPINLOCK_INIT != 0
+= {
+ { __LOCK_INITIALIZER, NULL, 0},
+ { __LOCK_INITIALIZER, NULL, 0},
+ /* All NULLs */
+}
+# endif
+#else
+= {
+ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0},
+ { __LOCK_INITIALIZER, &__pthread_manager_thread, 0},
+ /* All NULLs */
+}
+#endif
+;
/* For debugging purposes put the maximum number of threads in a variable. */
const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX;
@@ -60,6 +76,8 @@ volatile td_thr_events_t __pthread_threads_events;
/* Pointer to thread descriptor with last event. */
volatile pthread_descr __pthread_last_event;
+static pthread_descr manager_thread;
+
/* Mapping from stack segment to thread descriptor. */
/* Stack segment numbers are also indices into the __pthread_handles array. */
/* Stack segment number 0 is reserved for the initial thread. */
@@ -100,7 +118,7 @@ static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
__attribute__ ((noreturn));
static void pthread_reap_children(void);
static void pthread_kill_all_threads(int sig, int main_thread_also);
-static void pthread_for_each_thread(void *arg,
+static void pthread_for_each_thread(void *arg,
void (*fn)(void *, pthread_descr));
/* The server thread managing requests for thread creation and termination */
@@ -109,7 +127,8 @@ int
__attribute__ ((noreturn))
__pthread_manager(void *arg)
{
- int reqfd = (int) (long int) arg;
+ pthread_descr self = manager_thread = arg;
+ int reqfd = __pthread_manager_reader;
struct pollfd ufd;
sigset_t manager_mask;
int n;
@@ -117,11 +136,11 @@ __pthread_manager(void *arg)
/* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_manager_thread, 1);
+ INIT_THREAD_SELF(self, 1);
#endif
/* Set the error variable. */
- __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
- __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
+ self->p_errnop = &self->p_errno;
+ self->p_h_errnop = &self->p_h_errno;
/* Block all signals except __pthread_sig_cancel and SIGTRAP */
sigfillset(&manager_mask);
sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
@@ -227,13 +246,13 @@ int __pthread_manager_event(void *arg)
{
/* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_manager_thread, 1);
+ INIT_THREAD_SELF(arg, 1);
#endif
/* Get the lock the manager will free once all is correctly set up. */
- __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL);
+ __pthread_lock (THREAD_GETMEM(((pthread_descr) arg), p_lock), NULL);
/* Free it immediately. */
- __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock));
+ __pthread_unlock (THREAD_GETMEM(((pthread_descr) arg), p_lock));
return __pthread_manager(arg);
}
@@ -270,7 +289,7 @@ pthread_start_thread(void *arg)
__sched_setscheduler(THREAD_GETMEM(self, p_pid),
THREAD_GETMEM(self, p_start_args.schedpolicy),
&self->p_start_args.schedparam);
- else if (__pthread_manager_thread.p_priority > 0)
+ else if (manager_thread->p_priority > 0)
/* Default scheduling required, but thread manager runs in realtime
scheduling: switch new thread to SCHED_OTHER policy */
{
@@ -315,10 +334,14 @@ pthread_start_thread_event(void *arg)
pthread_start_thread (arg);
}
+#if defined USE_TLS && !FLOATING_STACKS
+# error "TLS can only work with floating stacks"
+#endif
+
static int pthread_allocate_stack(const pthread_attr_t *attr,
pthread_descr default_new_thread,
int pagesize,
- pthread_descr * out_new_thread,
+ char ** out_new_thread,
char ** out_new_thread_bottom,
char ** out_guardaddr,
size_t * out_guardsize)
@@ -328,12 +351,23 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
char * guardaddr;
size_t stacksize, guardsize;
+#ifdef USE_TLS
+ /* TLS cannot work with fixed thread descriptor addresses. */
+ assert (default_new_thread == NULL);
+#endif
+
if (attr != NULL && attr->__stackaddr_set)
{
#ifdef _STACK_GROWS_UP
/* The user provided a stack. */
+# ifdef USE_TLS
+ /* This value is not needed. */
+ new_thread = (pthread_descr) attr->__stackaddr;
+ new_thread_bottom = (char *) new_thread;
+# else
new_thread = (pthread_descr) attr->__stackaddr;
new_thread_bottom = (char *) (new_thread + 1);
+# endif
guardaddr = attr->__stackaddr + attr->__stacksize;
guardsize = 0;
#else
@@ -347,8 +381,12 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
addresses, stackaddr would be the lowest address in the stack
segment, so that it is consistently close to the initial sp
value. */
+# ifdef USE_TLS
+ new_thread = (pthread_descr) attr->__stackaddr;
+# else
new_thread =
(pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
+# endif
new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
guardaddr = new_thread_bottom;
guardsize = 0;
@@ -356,16 +394,18 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
#ifndef THREAD_SELF
__pthread_nonstandard_stacks = 1;
#endif
+#ifndef USE_TLS
/* Clear the thread data structure. */
memset (new_thread, '\0', sizeof (*new_thread));
+#endif
}
else
{
#ifdef NEED_SEPARATE_REGISTER_STACK
- size_t granularity = 2 * pagesize;
+ const size_t granularity = 2 * pagesize;
/* Try to make stacksize/2 a multiple of pagesize */
#else
- size_t granularity = pagesize;
+ const size_t granularity = pagesize;
#endif
void *map_addr;
@@ -397,22 +437,35 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
mprotect (guardaddr, guardsize, PROT_NONE);
new_thread_bottom = (char *) map_addr;
+# ifdef USE_TLS
+ new_thread = ((pthread_descr) (new_thread_bottom + stacksize
+ + guardsize));
+# else
new_thread = ((pthread_descr) (new_thread_bottom + stacksize
+ guardsize)) - 1;
+# endif
# elif _STACK_GROWS_DOWN
guardaddr = map_addr;
if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE);
new_thread_bottom = (char *) map_addr + guardsize;
+# ifdef USE_TLS
+ new_thread = ((pthread_descr) (new_thread_bottom + stacksize));
+# else
new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;
+# endif
# elif _STACK_GROWS_UP
guardaddr = map_addr + stacksize;
if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE);
new_thread = (pthread_descr) map_addr;
+# ifdef USE_TLS
+ new_thread_bottom = (char *) new_thread;
+# else
new_thread_bottom = (char *) (new_thread + 1);
+# endif
# else
# error You must define a stack direction
# endif /* Stack direction */
@@ -512,7 +565,7 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
# endif /* !NEED_SEPARATE_REGISTER_STACK */
#endif /* !FLOATING_STACKS */
}
- *out_new_thread = new_thread;
+ *out_new_thread = (char *) new_thread;
*out_new_thread_bottom = new_thread_bottom;
*out_guardaddr = guardaddr;
*out_guardsize = guardsize;
@@ -528,12 +581,19 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
size_t sseg;
int pid;
pthread_descr new_thread;
+ char *stack_addr;
char * new_thread_bottom;
pthread_t new_thread_id;
char *guardaddr = NULL;
size_t guardsize = 0;
int pagesize = __getpagesize();
- int saved_errno;
+ int saved_errno = 0;
+
+#ifdef USE_TLS
+ new_thread = _dl_allocate_tls ();
+ if (new_thread == NULL)
+ return EAGAIN;
+#endif
/* First check whether we have to change the policy and if yes, whether
we can do this. Normally this should be done by examining the
@@ -549,10 +609,16 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
if (__pthread_handles[sseg].h_descr != NULL)
continue;
if (pthread_allocate_stack(attr, thread_segment(sseg),
- pagesize,
- &new_thread, &new_thread_bottom,
+ pagesize, &stack_addr, &new_thread_bottom,
&guardaddr, &guardsize) == 0)
- break;
+ {
+#ifdef USE_TLS
+ new_thread->p_stackaddr = stack_addr;
+#else
+ new_thread = (pthread_descr) stack_addr;
+#endif
+ break;
+ }
}
__pthread_handles_num++;
/* Allocate new thread identifier */
@@ -768,20 +834,32 @@ static void pthread_free(pthread_descr th)
/* Free the stack and thread descriptor area */
char *guardaddr = th->p_guardaddr;
#ifdef _STACK_GROWS_UP
+# ifdef USE_TLS
+ size_t stacksize = guardaddr - th->p_stackaddr;
+# else
size_t stacksize = guardaddr - (char *)th;
+# endif
guardaddr = (char *)th;
#else
/* Guardaddr is always set, even if guardsize is 0. This allows
us to compute everything else. */
+# ifdef USE_TLS
+ size_t stacksize = th->p_stackaddr - guardaddr - guardsize;
+# else
size_t stacksize = (char *)(th+1) - guardaddr - guardsize;
-#ifdef NEED_SEPARATE_REGISTER_STACK
+# endif
+# ifdef NEED_SEPARATE_REGISTER_STACK
/* Take account of the register stack, which is below guardaddr. */
guardaddr -= stacksize;
stacksize *= 2;
-#endif
+# endif
#endif
/* Unmap the stack. */
munmap(guardaddr, stacksize + guardsize);
+
+#ifdef USE_TLS
+ _dl_deallocate_tls (th);
+#endif
}
}
@@ -896,7 +974,7 @@ static void pthread_kill_all_threads(int sig, int main_thread_also)
}
}
-static void pthread_for_each_thread(void *arg,
+static void pthread_for_each_thread(void *arg,
void (*fn)(void *, pthread_descr))
{
pthread_descr th;
@@ -974,10 +1052,10 @@ void __pthread_manager_adjust_prio(int thread_prio)
{
struct sched_param param;
- if (thread_prio <= __pthread_manager_thread.p_priority) return;
+ if (thread_prio <= manager_thread->p_priority) return;
param.sched_priority =
thread_prio < __sched_get_priority_max(SCHED_FIFO)
? thread_prio + 1 : thread_prio;
- __sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
- __pthread_manager_thread.p_priority = thread_prio;
+ __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
+ manager_thread->p_priority = thread_prio;
}
diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c
index 2901d9c24f..314360d477 100644
--- a/linuxthreads/pthread.c
+++ b/linuxthreads/pthread.c
@@ -31,6 +31,7 @@
#include "spinlock.h"
#include "restart.h"
#include <ldsodefs.h>
+#include <tls.h>
/* We need the global/static resolver state here. */
#include <resolv.h>
@@ -47,12 +48,18 @@ extern struct __res_state _res;
extern int _errno;
extern int _h_errno;
+#ifdef USE_TLS
+
+/* We need only a few variables. */
+static pthread_descr manager_thread;
+
+#else
/* Descriptor of the initial thread */
struct _pthread_descr_struct __pthread_initial_thread = {
{
{
- &__pthread_initial_thread /* pthread_descr self */
+ .self = &__pthread_initial_thread /* pthread_descr self */
}
},
&__pthread_initial_thread, /* pthread_descr p_nextlive */
@@ -106,10 +113,11 @@ struct _pthread_descr_struct __pthread_initial_thread = {
variables, the p_pid and p_priority fields,
and the address for identification. */
+#define manager_thread (&__pthread_manager_thread)
struct _pthread_descr_struct __pthread_manager_thread = {
{
{
- &__pthread_manager_thread /* pthread_descr self */
+ .self = &__pthread_manager_thread /* pthread_descr self */
}
},
NULL, /* pthread_descr p_nextlive */
@@ -158,11 +166,16 @@ struct _pthread_descr_struct __pthread_manager_thread = {
NULL, /* pthread_readlock_info *p_readlock_free; */
0 /* int p_untracked_readlock_count; */
};
+#endif
/* Pointer to the main thread (the father of the thread manager thread) */
/* Originally, this is the initial thread, but this changes after fork() */
+#ifdef USE_TLS
+pthread_descr __pthread_main_thread;
+#else
pthread_descr __pthread_main_thread = &__pthread_initial_thread;
+#endif
/* Limit between the stack of the initial thread (above) and the
stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
@@ -386,13 +399,44 @@ extern void *__dso_handle __attribute__ ((weak));
void
__pthread_initialize_minimal(void)
{
+#ifdef USE_TLS
+ pthread_descr self = THREAD_SELF;
+
+ /* The memory for the thread descriptor was allocated elsewhere as
+ part of the TLS allocation. We have to initialize the data
+ structure by hand. This initialization must mirror the struct
+ definition above. */
+ self->p_header.data.self = self;
+ self->p_nextlive = self->p_prevlive = self;
+ self->p_tid = PTHREAD_THREADS_MAX;
+ self->p_lock = &__pthread_handles[0].h_lock;
+ self->p_errnop = &_errno;
+ self->p_h_errnop = &_h_errno;
+ /* self->p_start_args need not be initialized, it's all zero. */
+ self->p_userstack = 1;
+# if __LT_SPINLOCK_INIT != 0
+ self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER;
+# endif
+
+ /* Another variable which points to the thread descriptor. */
+ __pthread_main_thread = self;
+
+ /* And fill in the pointer the the thread __pthread_handles array. */
+ __pthread_handles[0].h_descr = self;
+#else
/* If we have special thread_self processing, initialize that for the
main thread now. */
-#ifdef INIT_THREAD_SELF
+# ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_initial_thread, 0);
+# endif
#endif
+
#if HP_TIMING_AVAIL
+# ifdef USE_TLS
+ self->p_cpuclock_offset = GL(dl_cpuclock_offset);
+# else
__pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset);
+# endif
#endif
}
@@ -461,10 +505,17 @@ static void pthread_initialize(void)
(char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
# endif
#endif
+#ifdef USE_TLS
+ /* Update the descriptor for the initial thread. */
+ THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid());
+ /* Likewise for the resolver state _res. */
+ THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res);
+#else
/* Update the descriptor for the initial thread. */
__pthread_initial_thread.p_pid = __getpid();
/* Likewise for the resolver state _res. */
__pthread_initial_thread.p_resp = &_res;
+#endif
#ifdef __SIGRTMIN
/* Initialize real-time signals. */
init_rtsigs ();
@@ -513,6 +564,8 @@ int __pthread_initialize_manager(void)
int manager_pipe[2];
int pid;
struct pthread_request request;
+ int report_events;
+ pthread_descr tcb;
#ifndef HAVE_Z_NODELETE
if (__builtin_expe