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.
This commit is contained in:
Ulrich Drepper 2002-02-23 08:47:54 +00:00
parent e413826144
commit 557fab43bd
15 changed files with 291 additions and 85 deletions

View File

@ -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> 2002-02-22 Ulrich Drepper <drepper@redhat.com>
* elf/Versions: Add _dl_allocate_tls and _dl_deallocate_tls. * elf/Versions: Add _dl_allocate_tls and _dl_deallocate_tls.

View File

@ -59,9 +59,7 @@ before-compile += $(objpfx)abi-tag.h
generated += abi-tag.h generated += abi-tag.h
endif endif
ifeq (yes,$(gnu-ld)) ifneq (yes,$(gnu-ld))
libc-init = set-init
else
libc-init = munch-init libc-init = munch-init
$(objpfx)munch-init.c: munch.awk munch-tmpl.c $(+subdir_inits) $(objpfx)munch-init.c: munch.awk munch-tmpl.c $(+subdir_inits)
$(AWK) -f $< subdirs='$(+init_subdirs)' $(word 2,$^) > $@-t $(AWK) -f $< subdirs='$(+init_subdirs)' $(word 2,$^) > $@-t

View File

@ -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> 2002-02-17 Andreas Schwab <schwab@suse.de>
* signals.c (sigwait): Check for old sighandler being SIG_ERR, * signals.c (sigwait): Check for old sighandler being SIG_ERR,

View File

@ -102,8 +102,10 @@ struct _pthread_descr_struct {
/* XXX Remove this union for IA-64 style TLS module */ /* XXX Remove this union for IA-64 style TLS module */
union { union {
struct { 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; union dtv *dtvp;
pthread_descr self; /* Pointer to this structure */
} data; } data;
void *__padding[16]; void *__padding[16];
} p_header; } p_header;
@ -157,6 +159,9 @@ struct _pthread_descr_struct {
int p_inheritsched; /* copied from the thread attribute */ int p_inheritsched; /* copied from the thread attribute */
#if HP_TIMING_AVAIL #if HP_TIMING_AVAIL
hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */
#endif
#ifdef USE_TLS
char *p_stackaddr; /* Stack address. */
#endif #endif
/* New elements must be added at the end. */ /* New elements must be added at the end. */
} __attribute__ ((aligned(32))); /* We need to align the structure so that } __attribute__ ((aligned(32))); /* We need to align the structure so that

View File

@ -23,6 +23,7 @@
#include <unistd.h> #include <unistd.h>
#include <stackinfo.h> #include <stackinfo.h>
#include <tls.h>
#include "descr.h" #include "descr.h"
extern long int testandset (int *spinlock); extern long int testandset (int *spinlock);

View File

@ -14,6 +14,7 @@
/* The "thread manager" thread: manages creation and termination of threads */ /* The "thread manager" thread: manages creation and termination of threads */
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <sched.h> #include <sched.h>
#include <stddef.h> #include <stddef.h>
@ -27,6 +28,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> /* for waitpid macros */ #include <sys/wait.h> /* for waitpid macros */
#include <ldsodefs.h>
#include "pthread.h" #include "pthread.h"
#include "internals.h" #include "internals.h"
#include "spinlock.h" #include "spinlock.h"
@ -34,9 +36,23 @@
#include "semaphore.h" #include "semaphore.h"
/* Array of active threads. Entry 0 is reserved for the initial thread. */ /* Array of active threads. Entry 0 is reserved for the initial thread. */
struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] = struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]
{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0}, #ifdef USE_TLS
{ __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ }; # 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. */ /* For debugging purposes put the maximum number of threads in a variable. */
const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; 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. */ /* Pointer to thread descriptor with last event. */
volatile pthread_descr __pthread_last_event; volatile pthread_descr __pthread_last_event;
static pthread_descr manager_thread;
/* Mapping from stack segment to thread descriptor. */ /* Mapping from stack segment to thread descriptor. */
/* Stack segment numbers are also indices into the __pthread_handles array. */ /* Stack segment numbers are also indices into the __pthread_handles array. */
/* Stack segment number 0 is reserved for the initial thread. */ /* 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)); __attribute__ ((noreturn));
static void pthread_reap_children(void); static void pthread_reap_children(void);
static void pthread_kill_all_threads(int sig, int main_thread_also); 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)); void (*fn)(void *, pthread_descr));
/* The server thread managing requests for thread creation and termination */ /* The server thread managing requests for thread creation and termination */
@ -109,7 +127,8 @@ int
__attribute__ ((noreturn)) __attribute__ ((noreturn))
__pthread_manager(void *arg) __pthread_manager(void *arg)
{ {
int reqfd = (int) (long int) arg; pthread_descr self = manager_thread = arg;
int reqfd = __pthread_manager_reader;
struct pollfd ufd; struct pollfd ufd;
sigset_t manager_mask; sigset_t manager_mask;
int n; int n;
@ -117,11 +136,11 @@ __pthread_manager(void *arg)
/* If we have special thread_self processing, initialize it. */ /* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF #ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_manager_thread, 1); INIT_THREAD_SELF(self, 1);
#endif #endif
/* Set the error variable. */ /* Set the error variable. */
__pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno; self->p_errnop = &self->p_errno;
__pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno; self->p_h_errnop = &self->p_h_errno;
/* Block all signals except __pthread_sig_cancel and SIGTRAP */ /* Block all signals except __pthread_sig_cancel and SIGTRAP */
sigfillset(&manager_mask); sigfillset(&manager_mask);
sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ 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. */ /* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF #ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_manager_thread, 1); INIT_THREAD_SELF(arg, 1);
#endif #endif
/* Get the lock the manager will free once all is correctly set up. */ /* 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. */ /* 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); return __pthread_manager(arg);
} }
@ -270,7 +289,7 @@ pthread_start_thread(void *arg)
__sched_setscheduler(THREAD_GETMEM(self, p_pid), __sched_setscheduler(THREAD_GETMEM(self, p_pid),
THREAD_GETMEM(self, p_start_args.schedpolicy), THREAD_GETMEM(self, p_start_args.schedpolicy),
&self->p_start_args.schedparam); &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 /* Default scheduling required, but thread manager runs in realtime
scheduling: switch new thread to SCHED_OTHER policy */ scheduling: switch new thread to SCHED_OTHER policy */
{ {
@ -315,10 +334,14 @@ pthread_start_thread_event(void *arg)
pthread_start_thread (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, static int pthread_allocate_stack(const pthread_attr_t *attr,
pthread_descr default_new_thread, pthread_descr default_new_thread,
int pagesize, int pagesize,
pthread_descr * out_new_thread, char ** out_new_thread,
char ** out_new_thread_bottom, char ** out_new_thread_bottom,
char ** out_guardaddr, char ** out_guardaddr,
size_t * out_guardsize) size_t * out_guardsize)
@ -328,12 +351,23 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
char * guardaddr; char * guardaddr;
size_t stacksize, guardsize; 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) if (attr != NULL && attr->__stackaddr_set)
{ {
#ifdef _STACK_GROWS_UP #ifdef _STACK_GROWS_UP
/* The user provided a stack. */ /* 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 = (pthread_descr) attr->__stackaddr;
new_thread_bottom = (char *) (new_thread + 1); new_thread_bottom = (char *) (new_thread + 1);
# endif
guardaddr = attr->__stackaddr + attr->__stacksize; guardaddr = attr->__stackaddr + attr->__stacksize;
guardsize = 0; guardsize = 0;
#else #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 addresses, stackaddr would be the lowest address in the stack
segment, so that it is consistently close to the initial sp segment, so that it is consistently close to the initial sp
value. */ value. */
# ifdef USE_TLS
new_thread = (pthread_descr) attr->__stackaddr;
# else
new_thread = new_thread =
(pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
# endif
new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
guardaddr = new_thread_bottom; guardaddr = new_thread_bottom;
guardsize = 0; guardsize = 0;
@ -356,16 +394,18 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
#ifndef THREAD_SELF #ifndef THREAD_SELF
__pthread_nonstandard_stacks = 1; __pthread_nonstandard_stacks = 1;
#endif #endif
#ifndef USE_TLS
/* Clear the thread data structure. */ /* Clear the thread data structure. */
memset (new_thread, '\0', sizeof (*new_thread)); memset (new_thread, '\0', sizeof (*new_thread));
#endif
} }
else else
{ {
#ifdef NEED_SEPARATE_REGISTER_STACK #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 */ /* Try to make stacksize/2 a multiple of pagesize */
#else #else
size_t granularity = pagesize; const size_t granularity = pagesize;
#endif #endif
void *map_addr; void *map_addr;
@ -397,22 +437,35 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
mprotect (guardaddr, guardsize, PROT_NONE); mprotect (guardaddr, guardsize, PROT_NONE);
new_thread_bottom = (char *) map_addr; 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 new_thread = ((pthread_descr) (new_thread_bottom + stacksize
+ guardsize)) - 1; + guardsize)) - 1;
# endif
# elif _STACK_GROWS_DOWN # elif _STACK_GROWS_DOWN
guardaddr = map_addr; guardaddr = map_addr;
if (guardsize > 0) if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE); mprotect (guardaddr, guardsize, PROT_NONE);
new_thread_bottom = (char *) map_addr + guardsize; 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; new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;
# endif
# elif _STACK_GROWS_UP # elif _STACK_GROWS_UP
guardaddr = map_addr + stacksize; guardaddr = map_addr + stacksize;
if (guardsize > 0) if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE); mprotect (guardaddr, guardsize, PROT_NONE);
new_thread = (pthread_descr) map_addr; new_thread = (pthread_descr) map_addr;
# ifdef USE_TLS
new_thread_bottom = (char *) new_thread;
# else
new_thread_bottom = (char *) (new_thread + 1); new_thread_bottom = (char *) (new_thread + 1);
# endif
# else # else
# error You must define a stack direction # error You must define a stack direction
# endif /* 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 /* !NEED_SEPARATE_REGISTER_STACK */
#endif /* !FLOATING_STACKS */ #endif /* !FLOATING_STACKS */
} }
*out_new_thread = new_thread; *out_new_thread = (char *) new_thread;
*out_new_thread_bottom = new_thread_bottom; *out_new_thread_bottom = new_thread_bottom;
*out_guardaddr = guardaddr; *out_guardaddr = guardaddr;
*out_guardsize = guardsize; *out_guardsize = guardsize;
@ -528,12 +581,19 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
size_t sseg; size_t sseg;
int pid; int pid;
pthread_descr new_thread; pthread_descr new_thread;
char *stack_addr;
char * new_thread_bottom; char * new_thread_bottom;
pthread_t new_thread_id; pthread_t new_thread_id;
char *guardaddr = NULL; char *guardaddr = NULL;
size_t guardsize = 0; size_t guardsize = 0;
int pagesize = __getpagesize(); 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 /* 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 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) if (__pthread_handles[sseg].h_descr != NULL)
continue; continue;
if (pthread_allocate_stack(attr, thread_segment(sseg), if (pthread_allocate_stack(attr, thread_segment(sseg),
pagesize, pagesize, &stack_addr, &new_thread_bottom,
&new_thread, &new_thread_bottom,
&guardaddr, &guardsize) == 0) &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++; __pthread_handles_num++;
/* Allocate new thread identifier */ /* Allocate new thread identifier */
@ -768,20 +834,32 @@ static void pthread_free(pthread_descr th)
/* Free the stack and thread descriptor area */ /* Free the stack and thread descriptor area */
char *guardaddr = th->p_guardaddr; char *guardaddr = th->p_guardaddr;
#ifdef _STACK_GROWS_UP #ifdef _STACK_GROWS_UP
# ifdef USE_TLS
size_t stacksize = guardaddr - th->p_stackaddr;
# else
size_t stacksize = guardaddr - (char *)th; size_t stacksize = guardaddr - (char *)th;
# endif
guardaddr = (char *)th; guardaddr = (char *)th;
#else #else
/* Guardaddr is always set, even if guardsize is 0. This allows /* Guardaddr is always set, even if guardsize is 0. This allows
us to compute everything else. */ 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; 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. */ /* Take account of the register stack, which is below guardaddr. */
guardaddr -= stacksize; guardaddr -= stacksize;
stacksize *= 2; stacksize *= 2;
#endif # endif
#endif #endif
/* Unmap the stack. */ /* Unmap the stack. */
munmap(guardaddr, stacksize + guardsize); 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)) void (*fn)(void *, pthread_descr))
{ {
pthread_descr th; pthread_descr th;
@ -974,10 +1052,10 @@ void __pthread_manager_adjust_prio(int thread_prio)
{ {
struct sched_param param; struct sched_param param;
if (thread_prio <= __pthread_manager_thread.p_priority) return; if (thread_prio <= manager_thread->p_priority) return;
param.sched_priority = param.sched_priority =
thread_prio < __sched_get_priority_max(SCHED_FIFO) thread_prio < __sched_get_priority_max(SCHED_FIFO)
? thread_prio + 1 : thread_prio; ? thread_prio + 1 : thread_prio;
__sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param); __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
__pthread_manager_thread.p_priority = thread_prio; manager_thread->p_priority = thread_prio;
} }

View File

@ -31,6 +31,7 @@
#include "spinlock.h" #include "spinlock.h"
#include "restart.h" #include "restart.h"
#include <ldsodefs.h> #include <ldsodefs.h>
#include <tls.h>
/* We need the global/static resolver state here. */ /* We need the global/static resolver state here. */
#include <resolv.h> #include <resolv.h>
@ -47,12 +48,18 @@ extern struct __res_state _res;
extern int _errno; extern int _errno;
extern int _h_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 */ /* Descriptor of the initial thread */
struct _pthread_descr_struct __pthread_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 */ &__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, variables, the p_pid and p_priority fields,
and the address for identification. */ and the address for identification. */
#define manager_thread (&__pthread_manager_thread)
struct _pthread_descr_struct __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 */ NULL, /* pthread_descr p_nextlive */
@ -158,11 +166,16 @@ struct _pthread_descr_struct __pthread_manager_thread = {
NULL, /* pthread_readlock_info *p_readlock_free; */ NULL, /* pthread_readlock_info *p_readlock_free; */
0 /* int p_untracked_readlock_count; */ 0 /* int p_untracked_readlock_count; */
}; };
#endif
/* Pointer to the main thread (the father of the thread manager thread) */ /* Pointer to the main thread (the father of the thread manager thread) */
/* Originally, this is the initial thread, but this changes after fork() */ /* 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; pthread_descr __pthread_main_thread = &__pthread_initial_thread;
#endif
/* Limit between the stack of the initial thread (above) and the /* Limit between the stack of the initial thread (above) and the
stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
@ -386,13 +399,44 @@ extern void *__dso_handle __attribute__ ((weak));
void void
__pthread_initialize_minimal(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 /* If we have special thread_self processing, initialize that for the
main thread now. */ main thread now. */
#ifdef INIT_THREAD_SELF # ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_initial_thread, 0); INIT_THREAD_SELF(&__pthread_initial_thread, 0);
# endif
#endif #endif
#if HP_TIMING_AVAIL #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); __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset);
# endif
#endif #endif
} }
@ -461,10 +505,17 @@ static void pthread_initialize(void)
(char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
# endif # endif
#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. */ /* Update the descriptor for the initial thread. */
__pthread_initial_thread.p_pid = __getpid(); __pthread_initial_thread.p_pid = __getpid();
/* Likewise for the resolver state _res. */ /* Likewise for the resolver state _res. */
__pthread_initial_thread.p_resp = &_res; __pthread_initial_thread.p_resp = &_res;
#endif
#ifdef __SIGRTMIN #ifdef __SIGRTMIN
/* Initialize real-time signals. */ /* Initialize real-time signals. */
init_rtsigs (); init_rtsigs ();
@ -513,6 +564,8 @@ int __pthread_initialize_manager(void)
int manager_pipe[2]; int manager_pipe[2];
int pid; int pid;
struct pthread_request request; struct pthread_request request;
int report_events;
pthread_descr tcb;
#ifndef HAVE_Z_NODELETE #ifndef HAVE_Z_NODELETE
if (__builtin_expect (&__dso_handle != NULL, 1)) if (__builtin_expect (&__dso_handle != NULL, 1))
@ -535,37 +588,76 @@ int __pthread_initialize_manager(void)
free(__pthread_manager_thread_bos); free(__pthread_manager_thread_bos);
return -1; return -1;
} }
#ifdef USE_TLS
/* Allocate memory for the thread descriptor and the dtv. */
manager_thread = tcb = _dl_allocate_tls ();
if (tcb == NULL) {
free(__pthread_manager_thread_bos);
__libc_close(manager_pipe[0]);
__libc_close(manager_pipe[1]);
return -1;
}
/* Initialize the descriptor. */
tcb->p_header.data.self = tcb;
tcb->p_lock = &__pthread_handles[1].h_lock;
tcb->p_errnop = &tcb->p_errno;
tcb->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager);
tcb->p_nr = 1;
# if __LT_SPINLOCK_INIT != 0
self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER;
# endif
#else
tcb = &__pthread_manager_thread;
#endif
__pthread_manager_request = manager_pipe[1]; /* writing end */
__pthread_manager_reader = manager_pipe[0]; /* reading end */
/* Start the thread manager */ /* Start the thread manager */
pid = 0; pid = 0;
if (__builtin_expect (__pthread_initial_thread.p_report_events, 0)) #ifdef USE_TLS
report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
#else
report_events = __pthread_initial_thread.p_report_events;
#endif
if (__builtin_expect (report_events, 0))
{ {
/* It's a bit more complicated. We have to report the creation of /* It's a bit more complicated. We have to report the creation of
the manager thread. */ the manager thread. */
int idx = __td_eventword (TD_CREATE); int idx = __td_eventword (TD_CREATE);
uint32_t mask = __td_eventmask (TD_CREATE); uint32_t mask = __td_eventmask (TD_CREATE);
uint32_t event_bits;
if ((mask & (__pthread_threads_events.event_bits[idx] #ifdef USE_TLS
| __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx])) event_bits = THREAD_GETMEM_NC (((pthread_descr) NULL),
p_eventbuf.eventmask.event_bits[idx]);
#else
event_bits = __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx];
#endif
if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits))
!= 0) != 0)
{ {
__pthread_lock(__pthread_manager_thread.p_lock, NULL); __pthread_lock(tcb->p_lock, NULL);
#ifdef NEED_SEPARATE_REGISTER_STACK #ifdef NEED_SEPARATE_REGISTER_STACK
pid = __clone2(__pthread_manager_event, pid = __clone2(__pthread_manager_event,
(void **) __pthread_manager_thread_bos, (void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE, THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]); tcb);
#elif _STACK_GROWS_UP #elif _STACK_GROWS_UP
pid = __clone(__pthread_manager_event, pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_bos, (void **) __pthread_manager_thread_bos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]); tcb);
#else #else
pid = __clone(__pthread_manager_event, pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_tos, (void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]); tcb);
#endif #endif
if (pid != -1) if (pid != -1)
@ -574,19 +666,18 @@ int __pthread_initialize_manager(void)
the newly created thread's data structure. We cannot let the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was the new thread do this since we don't know whether it was
already scheduled when we send the event. */ already scheduled when we send the event. */
__pthread_manager_thread.p_eventbuf.eventdata = tcb->p_eventbuf.eventdata = tcb;
&__pthread_manager_thread; tcb->p_eventbuf.eventnum = TD_CREATE;
__pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE; __pthread_last_event = tcb;
__pthread_last_event = &__pthread_manager_thread; tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; tcb->p_pid = pid;
__pthread_manager_thread.p_pid = pid;
/* Now call the function which signals the event. */ /* Now call the function which signals the event. */
__linuxthreads_create_event (); __linuxthreads_create_event ();
} }
/* Now restart the thread. */ /* Now restart the thread. */
__pthread_unlock(__pthread_manager_thread.p_lock); __pthread_unlock(tcb->p_lock);
} }
} }
@ -595,16 +686,13 @@ int __pthread_initialize_manager(void)
#ifdef NEED_SEPARATE_REGISTER_STACK #ifdef NEED_SEPARATE_REGISTER_STACK
pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE, THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
(void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP #elif _STACK_GROWS_UP
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
(void *)(long)manager_pipe[0]);
#else #else
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
(void *)(long)manager_pipe[0]);
#endif #endif
} }
if (__builtin_expect (pid, 0) == -1) { if (__builtin_expect (pid, 0) == -1) {
@ -613,10 +701,8 @@ int __pthread_initialize_manager(void)
__libc_close(manager_pipe[1]); __libc_close(manager_pipe[1]);
return -1; return -1;
} }
__pthread_manager_request = manager_pipe[1]; /* writing end */ tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_reader = manager_pipe[0]; /* reading end */ tcb->p_pid = pid;
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_pid = pid;
/* Make gdb aware of new thread manager */ /* Make gdb aware of new thread manager */
if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
{ {
@ -725,7 +811,7 @@ static pthread_descr thread_self_stack(void)
pthread_handle h; pthread_handle h;
if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
return &__pthread_manager_thread; return manager_thread;
h = __pthread_handles + 2; h = __pthread_handles + 2;
while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
h++; h++;
@ -805,7 +891,11 @@ static void pthread_onexit_process(int retcode, void *arg)
children, so that timings for main thread account for all threads. */ children, so that timings for main thread account for all threads. */
if (self == __pthread_main_thread) if (self == __pthread_main_thread)
{ {
#ifdef USE_TLS
waitpid(manager_thread->p_pid, NULL, __WCLONE);
#else
waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
#endif
/* Since all threads have been asynchronously terminated /* Since all threads have been asynchronously terminated
(possibly holding locks), free cannot be used any more. */ (possibly holding locks), free cannot be used any more. */
/*free (__pthread_manager_thread_bos);*/ /*free (__pthread_manager_thread_bos);*/
@ -850,7 +940,7 @@ static void pthread_handle_sigcancel(int sig)
pthread_descr self = thread_self(); pthread_descr self = thread_self();
sigjmp_buf * jmpbuf; sigjmp_buf * jmpbuf;
if (self == &__pthread_manager_thread) if (self == manager_thread)
{ {
#ifdef THREAD_SELF #ifdef THREAD_SELF
/* A new thread might get a cancel signal before it is fully /* A new thread might get a cancel signal before it is fully
@ -858,7 +948,7 @@ static void pthread_handle_sigcancel(int sig)
manager thread. Double check that this is really the manager manager thread. Double check that this is really the manager
thread. */ thread. */
pthread_descr real_self = thread_self_stack(); pthread_descr real_self = thread_self_stack();
if (real_self == &__pthread_manager_thread) if (real_self == manager_thread)
{ {
__pthread_manager_sighandler(sig); __pthread_manager_sighandler(sig);
return; return;
@ -876,8 +966,13 @@ static void pthread_handle_sigcancel(int sig)
if (__builtin_expect (__pthread_exit_requested, 0)) { if (__builtin_expect (__pthread_exit_requested, 0)) {
/* Main thread should accumulate times for thread manager and its /* Main thread should accumulate times for thread manager and its
children, so that timings for main thread account for all threads. */ children, so that timings for main thread account for all threads. */
if (self == __pthread_main_thread) if (self == __pthread_main_thread) {
#ifdef USE_TLS
waitpid(manager_thread->p_pid, NULL, __WCLONE);
#else
waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
#endif
}
_exit(__pthread_exit_code); _exit(__pthread_exit_code);
} }
if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)

View File

@ -32,15 +32,13 @@ typedef union dtv
typedef struct typedef struct
{ {
void *tcb; void *tcb; /* Pointer to the TCB. Not necessary the
thread descriptor used by libpthread. */
dtv_t *dtv; dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
} tcbhead_t; } tcbhead_t;
/* Get the thread descriptor definition. */
#include <linuxthreads/descr.h>
/* We can support TLS only if the floating-stack support is available. */ /* We can support TLS only if the floating-stack support is available. */
#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT #if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
@ -50,6 +48,10 @@ typedef struct
/* Signal that TLS support is available. */ /* Signal that TLS support is available. */
# define USE_TLS 1 # define USE_TLS 1
/* Get the thread descriptor definition. */
# include <linuxthreads/descr.h>
/* This is the size of the initial TCB. */ /* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
@ -77,6 +79,10 @@ typedef struct
({ struct _pthread_descr_struct *__descr; \ ({ struct _pthread_descr_struct *__descr; \
THREAD_SETMEM (__descr, p_header.data.dtvp, dtv); }) THREAD_SETMEM (__descr, p_header.data.dtvp, dtv); })
/* Return dtv of given thread descriptor. */
# define GET_DTV(descr) \
(((tcbhead_t *) descr)->dtv)
/* Code to initially initialize the thread pointer. This might need /* Code to initially initialize the thread pointer. This might need
special attention since 'errno' is not yet available and if the special attention since 'errno' is not yet available and if the
operation can cause a failure 'errno' must not be touched. */ operation can cause a failure 'errno' must not be touched. */
@ -89,6 +95,8 @@ typedef struct
tcbhead_t *head = _descr; \ tcbhead_t *head = _descr; \
\ \
head->tcb = _descr; \ head->tcb = _descr; \
/* For now the thread descriptor isat the same address. */ \
head->self = _descr; \
\ \
asm ("pushl %%ebx\n\t" \ asm ("pushl %%ebx\n\t" \
"movl $1, %%ebx\n\t" \ "movl $1, %%ebx\n\t" \

View File

@ -1,5 +1,5 @@
/* Define and initialize `__progname' et. al. /* Define and initialize `__progname' et. al.
Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Copyright (C) 1994,1995,1996,1997,1998,2002 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -25,16 +25,6 @@ weak_alias (__progname_full, program_invocation_name)
weak_alias (__progname, program_invocation_short_name) weak_alias (__progname, program_invocation_short_name)
#ifdef HAVE_GNU_LD
static
#endif /* HAVE_GNU_LD */
void __init_misc (int argc, char **argv, char **envp)
__attribute__ ((unused));
#ifdef HAVE_GNU_LD
static
#endif /* HAVE_GNU_LD */
void void
__init_misc (int argc, char **argv, char **envp) __init_misc (int argc, char **argv, char **envp)
{ {
@ -48,7 +38,3 @@ __init_misc (int argc, char **argv, char **envp)
__progname_full = argv[0]; __progname_full = argv[0];
} }
} }
#ifdef HAVE_GNU_LD
text_set_element (__libc_subinit, __init_misc);
#endif

View File

@ -186,6 +186,7 @@ endif
ifeq ($(subdir),csu) ifeq ($(subdir),csu)
sysdep_routines += set-init
extra-objs += static-start.o extra-objs += static-start.o
# We need special startup code for statically linked binaries. # We need special startup code for statically linked binaries.

View File

@ -29,6 +29,7 @@
extern void __mach_init (void); extern void __mach_init (void);
extern void __libc_init (int, char **, char **); extern void __libc_init (int, char **, char **);
extern void __init_misc (int, char **, char **);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS
extern void __getopt_clean_environment (char **); extern void __getopt_clean_environment (char **);
#endif #endif
@ -64,6 +65,7 @@ posixland_init (int argc, char **argv, char **envp)
__libc_argv = argv; __libc_argv = argv;
__environ = envp; __environ = envp;
__init_misc (argc, argv, envp);
__libc_init (argc, argv, envp); __libc_init (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS

View File

@ -1,5 +1,5 @@
/* Initialization code run first thing by the ELF startup code. For Mips/Hurd. /* Initialization code run first thing by the ELF startup code. For Mips/Hurd.
Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. Copyright (C) 1996,1997,1998,2000,2001,2002 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -27,6 +27,7 @@
extern void __mach_init (void); extern void __mach_init (void);
extern void __libc_init (int, char **, char **); extern void __libc_init (int, char **, char **);
extern void __init_misc (int, char **, char **);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS
extern void __getopt_clean_environment (char **); extern void __getopt_clean_environment (char **);
#endif #endif
@ -106,6 +107,7 @@ init1 (int argc, char *arg0, ...)
d->portarray, d->portarraysize, d->portarray, d->portarraysize,
d->intarray, d->intarraysize); d->intarray, d->intarraysize);
__init_misc (argc, argv, __environ);
__libc_init (argc, argv, __environ); __libc_init (argc, argv, __environ);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS

View File

@ -1,5 +1,5 @@
/* Initialization code run first thing by the ELF startup code. PowerPC/Hurd. /* Initialization code run first thing by the ELF startup code. PowerPC/Hurd.
Copyright (C) 1995,96,97,98,99,2000,01 Free Software Foundation, Inc. Copyright (C) 1995-2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -29,6 +29,7 @@
extern void __mach_init (void); extern void __mach_init (void);
extern void __libc_init (int, char **, char **); extern void __libc_init (int, char **, char **);
extern void __init_misc (int, char **, char **);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS
extern void __getopt_clean_environment (char **); extern void __getopt_clean_environment (char **);
#endif #endif
@ -69,6 +70,7 @@ posixland_init (int argc, char **argv, char **envp)
__libc_argv = argv; __libc_argv = argv;
__environ = envp; __environ = envp;
__init_misc (argc, argv, envp);
__libc_init (argc, argv, envp); __libc_init (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS

View File

@ -33,7 +33,7 @@
# include "dl-osinfo.h" # include "dl-osinfo.h"
#endif #endif
extern void __libc_init (int, char **, char **); extern void __init_misc (int, char **, char **);
/* The function is called from assembly stubs the compiler can't see. */ /* The function is called from assembly stubs the compiler can't see. */
static void init (int, char **, char **) __attribute__ ((unused)); static void init (int, char **, char **) __attribute__ ((unused));
@ -89,7 +89,7 @@ init (int argc, char **argv, char **envp)
__libc_init_secure (); __libc_init_secure ();
#endif #endif
__libc_init (argc, argv, envp); __init_misc (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS #ifdef USE_NONOPTION_FLAGS
/* This is a hack to make the special getopt in GNU libc working. */ /* This is a hack to make the special getopt in GNU libc working. */