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

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>
* 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 */
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;
@ -157,6 +159,9 @@ struct _pthread_descr_struct {
int p_inheritsched; /* copied from the thread attribute */
#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

View file

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

View file

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

View file

@ -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_expect (&__dso_handle != NULL, 1))
@ -535,37 +588,76 @@ int __pthread_initialize_manager(void)
free(__pthread_manager_thread_bos);
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 */
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
the manager thread. */
int idx = __td_eventword (TD_CREATE);
uint32_t mask = __td_eventmask (TD_CREATE);
uint32_t event_bits;
if ((mask & (__pthread_threads_events.event_bits[idx]
| __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
#ifdef USE_TLS
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)
{
__pthread_lock(__pthread_manager_thread.p_lock, NULL);
__pthread_lock(tcb->p_lock, NULL);
#ifdef NEED_SEPARATE_REGISTER_STACK
pid = __clone2(__pthread_manager_event,
(void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
tcb);
#elif _STACK_GROWS_UP
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_bos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
tcb);
#else
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
tcb);
#endif
if (pid != -1)
@ -574,19 +666,18 @@ int __pthread_initialize_manager(void)
the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was
already scheduled when we send the event. */
__pthread_manager_thread.p_eventbuf.eventdata =
&__pthread_manager_thread;
__pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
__pthread_last_event = &__pthread_manager_thread;
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_pid = pid;
tcb->p_eventbuf.eventdata = tcb;
tcb->p_eventbuf.eventnum = TD_CREATE;
__pthread_last_event = tcb;
tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1;
tcb->p_pid = pid;
/* Now call the function which signals the event. */
__linuxthreads_create_event ();
}
/* 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
pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
#elif _STACK_GROWS_UP
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
#else
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb);
#endif
}
if (__builtin_expect (pid, 0) == -1) {
@ -613,10 +701,8 @@ int __pthread_initialize_manager(void)
__libc_close(manager_pipe[1]);
return -1;
}
__pthread_manager_request = manager_pipe[1]; /* writing end */
__pthread_manager_reader = manager_pipe[0]; /* reading end */
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_pid = pid;
tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1;
tcb->p_pid = pid;
/* Make gdb aware of new thread manager */
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;
if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
return &__pthread_manager_thread;
return manager_thread;
h = __pthread_handles + 2;
while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
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. */
if (self == __pthread_main_thread)
{
#ifdef USE_TLS
waitpid(manager_thread->p_pid, NULL, __WCLONE);
#else
waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
#endif
/* Since all threads have been asynchronously terminated
(possibly holding locks), free cannot be used any more. */
/*free (__pthread_manager_thread_bos);*/
@ -850,7 +940,7 @@ static void pthread_handle_sigcancel(int sig)
pthread_descr self = thread_self();
sigjmp_buf * jmpbuf;
if (self == &__pthread_manager_thread)
if (self == manager_thread)
{
#ifdef THREAD_SELF
/* 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
thread. */
pthread_descr real_self = thread_self_stack();
if (real_self == &__pthread_manager_thread)
if (real_self == manager_thread)
{
__pthread_manager_sighandler(sig);
return;
@ -876,8 +966,13 @@ static void pthread_handle_sigcancel(int sig)
if (__builtin_expect (__pthread_exit_requested, 0)) {
/* Main thread should accumulate times for thread manager and its
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);
#endif
}
_exit(__pthread_exit_code);
}
if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)

View file

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

View file

@ -1,5 +1,5 @@
/* 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.
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)
#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
__init_misc (int argc, char **argv, char **envp)
{
@ -48,7 +38,3 @@ __init_misc (int argc, char **argv, char **envp)
__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)
sysdep_routines += set-init
extra-objs += static-start.o
# We need special startup code for statically linked binaries.

View file

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

View file

@ -1,5 +1,5 @@
/* 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.
The GNU C Library is free software; you can redistribute it and/or
@ -27,6 +27,7 @@
extern void __mach_init (void);
extern void __libc_init (int, char **, char **);
extern void __init_misc (int, char **, char **);
#ifdef USE_NONOPTION_FLAGS
extern void __getopt_clean_environment (char **);
#endif
@ -106,6 +107,7 @@ init1 (int argc, char *arg0, ...)
d->portarray, d->portarraysize,
d->intarray, d->intarraysize);
__init_misc (argc, argv, __environ);
__libc_init (argc, argv, __environ);
#ifdef USE_NONOPTION_FLAGS

View file

@ -1,5 +1,5 @@
/* 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.
The GNU C Library is free software; you can redistribute it and/or
@ -29,6 +29,7 @@
extern void __mach_init (void);
extern void __libc_init (int, char **, char **);
extern void __init_misc (int, char **, char **);
#ifdef USE_NONOPTION_FLAGS
extern void __getopt_clean_environment (char **);
#endif
@ -69,6 +70,7 @@ posixland_init (int argc, char **argv, char **envp)
__libc_argv = argv;
__environ = envp;
__init_misc (argc, argv, envp);
__libc_init (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS

View file

@ -33,7 +33,7 @@
# include "dl-osinfo.h"
#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. */
static void init (int, char **, char **) __attribute__ ((unused));
@ -89,7 +89,7 @@ init (int argc, char **argv, char **envp)
__libc_init_secure ();
#endif
__libc_init (argc, argv, envp);
__init_misc (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS
/* This is a hack to make the special getopt in GNU libc working. */