mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 00:10:10 +00:00
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.
This commit is contained in:
parent
e413826144
commit
557fab43bd
15
ChangeLog
15
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>
|
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.
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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, ¶m);
|
__sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, ¶m);
|
||||||
__pthread_manager_thread.p_priority = thread_prio;
|
manager_thread->p_priority = thread_prio;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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" \
|
||||||
|
@ -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
|
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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. */
|
||||||
|
Loading…
Reference in New Issue
Block a user