mirror of
git://sourceware.org/git/glibc.git
synced 2025-02-17 13:00:43 +08:00
2003-03-11 Jakub Jelinek <jakub@redhat.com>
* sysdeps/pthread/createthread.c (ARCH_CLONE): Define if not defined. (create_thread): Only assert PD->tcb != NULL under [TLS_TCB_AT_TP]. Use ARCH_CLONE. * allocatestack.c (ALLOCATE_STACK_PARMS): New macro. [NEED_SEPARATE_REGISTER_STACK] (STACK_VARIABLES, STACK_VARIABLES_ARGS, STACK_VARIABLES_PARMS, ALLOCATE_STACK_PARMS, ALLOCATE_STACK): New macros. (TLS_TPADJ): New macro. (get_cached_stack, queue_stack, __deallocate_stack): Use TLS_TPADJ. (allocate_stack): Handle TLS_DTV_AT_TP and NEED_SEPARATE_REGISTER_STACK. Use TLS_TPADJ. * pthread_create.c (__pthread_create_2_1) [! TLS_TCB_AT_TP]: Don't set PD->self. * init.c [__ia64__] (__NR_set_tid_address): Define.
This commit is contained in:
parent
d0aacb47f9
commit
5d5d5969b1
@ -29,6 +29,7 @@
|
||||
|
||||
|
||||
|
||||
#ifndef NEED_SEPARATE_REGISTER_STACK
|
||||
|
||||
/* Most architectures have exactly one stack pointer. Some have more. */
|
||||
#define STACK_VARIABLES void *stackaddr
|
||||
@ -39,6 +40,24 @@
|
||||
/* How to declare function which gets there parameters. */
|
||||
#define STACK_VARIABLES_PARMS void *stackaddr
|
||||
|
||||
/* How to declare allocate_stack. */
|
||||
#define ALLOCATE_STACK_PARMS void **stack
|
||||
|
||||
/* This is how the function is called. We do it this way to allow
|
||||
other variants of the function to have more parameters. */
|
||||
#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
|
||||
|
||||
#else
|
||||
|
||||
#define STACK_VARIABLES void *stackaddr; size_t stacksize
|
||||
#define STACK_VARIABLES_ARGS stackaddr, stacksize
|
||||
#define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize
|
||||
#define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize
|
||||
#define ALLOCATE_STACK(attr, pd) \
|
||||
allocate_stack (attr, pd, &stackaddr, &stacksize)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Default alignment of stack. */
|
||||
#ifndef STACK_ALIGN
|
||||
@ -58,6 +77,12 @@
|
||||
# define ARCH_MAP_FLAGS 0
|
||||
#endif
|
||||
|
||||
/* This yields the pointer that TLS support code calls the thread pointer. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# define TLS_TPADJ(pd) (pd)
|
||||
#elif TLS_DTV_AT_TP
|
||||
# define TLS_TPADJ(pd) ((pd) + 1)
|
||||
#endif
|
||||
|
||||
/* Cache handling for not-yet free stacks. */
|
||||
|
||||
@ -162,11 +187,13 @@ get_cached_stack (size_t *sizep, void **memp)
|
||||
result->nextevent = NULL;
|
||||
|
||||
/* Clear the DTV. */
|
||||
dtv_t *dtv = GET_DTV (result);
|
||||
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
|
||||
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
|
||||
|
||||
/* Re-initialize the TLS. */
|
||||
return _dl_allocate_tls_init (result);
|
||||
_dl_allocate_tls_init (TLS_TPADJ (result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -203,7 +230,7 @@ queue_stack (struct pthread *stack)
|
||||
stack_cache_actsize -= curr->stackblock_size;
|
||||
|
||||
/* Free the memory associated with the ELF TLS. */
|
||||
_dl_deallocate_tls (curr, false);
|
||||
_dl_deallocate_tls (TLS_TPADJ (curr), false);
|
||||
|
||||
/* Remove this block. This should never fail. If it
|
||||
does something is really wrong. */
|
||||
@ -222,11 +249,12 @@ queue_stack (struct pthread *stack)
|
||||
|
||||
static int
|
||||
allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
void **stack)
|
||||
ALLOCATE_STACK_PARMS)
|
||||
{
|
||||
struct pthread *pd;
|
||||
size_t size;
|
||||
size_t pagesize_m1 = __getpagesize () - 1;
|
||||
void *stacktop;
|
||||
|
||||
assert (attr != NULL);
|
||||
assert (powerof2 (pagesize_m1 + 1));
|
||||
@ -248,15 +276,27 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
return EINVAL;
|
||||
|
||||
/* Adjust stack size for alignment of the TLS block. */
|
||||
adj = ((uintptr_t) attr->stackaddr) & __static_tls_align_m1;
|
||||
#if TLS_TCB_AT_TP
|
||||
adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
|
||||
& __static_tls_align_m1;
|
||||
assert (size > adj + TLS_TCB_SIZE);
|
||||
#elif TLS_DTV_AT_TP
|
||||
adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
|
||||
& __static_tls_align_m1;
|
||||
assert (size > adj);
|
||||
#endif
|
||||
|
||||
/* The user provided some memory. Let's hope it matches the
|
||||
size... We do not allocate guard pages if the user provided
|
||||
the stack. It is the user's responsibility to do this if it
|
||||
is wanted. */
|
||||
pd = (struct pthread *) (((uintptr_t) attr->stackaddr - adj)
|
||||
& ~(__alignof (struct pthread) - 1)) - 1;
|
||||
#if TLS_TCB_AT_TP
|
||||
pd = (struct pthread *) ((uintptr_t) attr->stackaddr
|
||||
- TLS_TCB_SIZE - adj);
|
||||
#elif TLS_DTV_AT_TP
|
||||
pd = (struct pthread *) ((uintptr_t) attr->stackaddr
|
||||
- __static_tls_size - adj) - 1;
|
||||
#endif
|
||||
|
||||
/* The user provided stack memory needs to be cleared. */
|
||||
memset (pd, '\0', sizeof (struct pthread));
|
||||
@ -290,7 +330,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
#endif
|
||||
|
||||
/* Allocate the DTV for this thread. */
|
||||
if (_dl_allocate_tls (pd) == NULL)
|
||||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||||
/* Something went wrong. */
|
||||
return errno;
|
||||
|
||||
@ -371,7 +411,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
#endif
|
||||
|
||||
/* Place the thread descriptor at the end of the stack. */
|
||||
#if TLS_TCB_AT_TP
|
||||
pd = (struct pthread *) ((char *) mem + size - coloring) - 1;
|
||||
#elif TLS_DTV_AT_TP
|
||||
pd = (struct pthread *) (((uintptr_t) mem + size - coloring
|
||||
- __static_tls_size)
|
||||
& ~__static_tls_align_m1) - 1;
|
||||
#endif
|
||||
|
||||
/* Remember the stack-related values. */
|
||||
pd->stackblock = mem;
|
||||
@ -400,7 +446,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
#endif
|
||||
|
||||
/* Allocate the DTV for this thread. */
|
||||
if (_dl_allocate_tls (pd) == NULL)
|
||||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
int err = errno;
|
||||
@ -432,7 +478,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
/* Create or resize the guard area if necessary. */
|
||||
if (__builtin_expect (guardsize > pd->guardsize, 0))
|
||||
{
|
||||
if (mprotect (mem, guardsize, PROT_NONE) != 0)
|
||||
#ifdef NEED_SEPARATE_REGISTER_STACK
|
||||
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
||||
#else
|
||||
char *guard = mem;
|
||||
#endif
|
||||
if (mprotect (guard, guardsize, PROT_NONE) != 0)
|
||||
{
|
||||
int err;
|
||||
mprot_error:
|
||||
@ -446,7 +497,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
lll_unlock (stack_cache_lock);
|
||||
|
||||
/* Get rid of the TLS block we allocated. */
|
||||
_dl_deallocate_tls (pd, false);
|
||||
_dl_deallocate_tls (TLS_TPADJ (pd), false);
|
||||
|
||||
/* Free the stack memory regardless of whether the size
|
||||
of the cache is over the limit or not. If this piece
|
||||
@ -464,9 +515,25 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
0))
|
||||
{
|
||||
/* The old guard area is too large. */
|
||||
|
||||
#ifdef NEED_SEPARATE_REGISTER_STACK
|
||||
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
||||
char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
|
||||
|
||||
if (oldguard < guard
|
||||
&& mprotect (oldguard, guard - oldguard,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
goto mprot_error;
|
||||
|
||||
if (mprotect (guard + guardsize,
|
||||
oldguard + pd->guardsize - guard - guardsize,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
goto mprot_error;
|
||||
#else
|
||||
if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
goto mprot_error;
|
||||
#endif
|
||||
|
||||
pd->guardsize = guardsize;
|
||||
}
|
||||
@ -477,18 +544,21 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
/* The stack begins before the TCB and the static TLS block. */
|
||||
*stack = ((char *) (pd + 1) - __static_tls_size);
|
||||
stacktop = ((char *) (pd + 1) - __static_tls_size);
|
||||
#elif TLS_DTV_AT_TP
|
||||
stacktop = (char *) (pd - 1);
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SEPARATE_REGISTER_STACK
|
||||
*stack = pd->stackblock;
|
||||
*stacksize = stacktop - *stack;
|
||||
#else
|
||||
# error "Implement me"
|
||||
*stack = stacktop;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is how the function is called. We do it this way to allow
|
||||
other variants of the function to have more parameters. */
|
||||
#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
@ -508,7 +578,7 @@ __deallocate_stack (struct pthread *pd)
|
||||
(void) queue_stack (pd);
|
||||
else
|
||||
/* Free the memory associated with the ELF TLS. */
|
||||
_dl_deallocate_tls (pd, false);
|
||||
_dl_deallocate_tls (TLS_TPADJ (pd), false);
|
||||
|
||||
lll_unlock (stack_cache_lock);
|
||||
}
|
||||
|
@ -37,6 +37,8 @@
|
||||
having the definition remove these lines. */
|
||||
#if defined __s390__
|
||||
# define __NR_set_tid_address 252
|
||||
#elif defined __ia64__
|
||||
# define __NR_set_tid_address 1233
|
||||
#else
|
||||
# define __NR_set_tid_address 258
|
||||
#endif
|
||||
|
@ -344,10 +344,10 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
|
||||
performed in 'get_cached_stack'. This way we avoid doing this if
|
||||
the stack freshly allocated with 'mmap'. */
|
||||
|
||||
#ifdef TLS_TCB_AT_TP
|
||||
/* Reference to the TCB itself. */
|
||||
pd->self = pd;
|
||||
|
||||
#ifdef TLS_TCB_AT_TP
|
||||
/* Self-reference for TLS. */
|
||||
pd->tcb = pd;
|
||||
#endif
|
||||
|
@ -34,6 +34,10 @@
|
||||
# define TLS_VALUE pd
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_CLONE
|
||||
# define ARCH_CLONE __clone
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
|
||||
@ -42,8 +46,9 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
|
||||
PREPARE_CREATE;
|
||||
#endif
|
||||
|
||||
#ifdef TLS_TCB_AT_TP
|
||||
assert (pd->tcb != NULL);
|
||||
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
|
||||
{
|
||||
@ -62,11 +67,11 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
|
||||
lll_lock (pd->lock);
|
||||
|
||||
/* Create the thread. */
|
||||
if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
|
||||
CLONE_SETTLS | CLONE_PARENT_SETTID |
|
||||
CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
|
||||
pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
|
||||
if (ARCH_CLONE (start_thread_debug, STACK_VARIABLES_ARGS,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
|
||||
CLONE_SETTLS | CLONE_PARENT_SETTID |
|
||||
CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
|
||||
pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
|
||||
/* Failed. */
|
||||
return errno;
|
||||
|
||||
@ -135,10 +140,10 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
|
||||
|
||||
The termination signal is chosen to be zero which means no signal
|
||||
is sent. */
|
||||
if (__clone (start_thread, STACK_VARIABLES_ARGS,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
|
||||
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
|
||||
CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
|
||||
if (ARCH_CLONE (start_thread, STACK_VARIABLES_ARGS,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
|
||||
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
|
||||
CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
|
||||
/* Failed. */
|
||||
return errno;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user