mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +03:00
nptl: support thread stacks that grow up
Gentoo has been carrying this for all arches since 2.17. URL: http://bugs.gentoo.org/301642
This commit is contained in:
committed by
Mike Frysinger
parent
11fca9615f
commit
d615a47355
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2016-02-19 Carlos O'Donell <carlos@systemhalted.org>
|
||||||
|
|
||||||
|
* nptl/allocatestack.c (allocate_stack): Declare new stackaddr,
|
||||||
|
assign attr->stackaddr to it, and adjust it down when
|
||||||
|
_STACK_GROWS_UP. Change all attr->stackaddr to stackaddr.
|
||||||
|
[_STACK_GROWS_UP]: Delete assert.
|
||||||
|
* nptl/pthread_create.c (START_THREAD_DEFN) [!_STACK_GROWS_DOWN]:
|
||||||
|
Implement stack grows up logic.
|
||||||
|
* nptl/pthread_getattr_np.c (pthread_getattr_np): Implement
|
||||||
|
stack grows up logic.
|
||||||
|
|
||||||
2016-02-19 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
2016-02-19 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
* NEWS: Update with 2.24 template.
|
* NEWS: Update with 2.24 template.
|
||||||
|
@ -372,6 +372,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
|
if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
|
||||||
{
|
{
|
||||||
uintptr_t adj;
|
uintptr_t adj;
|
||||||
|
char *stackaddr = (char *) attr->stackaddr;
|
||||||
|
|
||||||
|
/* Assume the same layout as the _STACK_GROWS_DOWN case, with struct
|
||||||
|
pthread at the top of the stack block. Later we adjust the guard
|
||||||
|
location and stack address to match the _STACK_GROWS_UP case. */
|
||||||
|
if (_STACK_GROWS_UP)
|
||||||
|
stackaddr += attr->stacksize;
|
||||||
|
|
||||||
/* If the user also specified the size of the stack make sure it
|
/* If the user also specified the size of the stack make sure it
|
||||||
is large enough. */
|
is large enough. */
|
||||||
@ -381,11 +388,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
|
|
||||||
/* Adjust stack size for alignment of the TLS block. */
|
/* Adjust stack size for alignment of the TLS block. */
|
||||||
#if TLS_TCB_AT_TP
|
#if TLS_TCB_AT_TP
|
||||||
adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
|
adj = ((uintptr_t) stackaddr - TLS_TCB_SIZE)
|
||||||
& __static_tls_align_m1;
|
& __static_tls_align_m1;
|
||||||
assert (size > adj + TLS_TCB_SIZE);
|
assert (size > adj + TLS_TCB_SIZE);
|
||||||
#elif TLS_DTV_AT_TP
|
#elif TLS_DTV_AT_TP
|
||||||
adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
|
adj = ((uintptr_t) stackaddr - __static_tls_size)
|
||||||
& __static_tls_align_m1;
|
& __static_tls_align_m1;
|
||||||
assert (size > adj);
|
assert (size > adj);
|
||||||
#endif
|
#endif
|
||||||
@ -395,10 +402,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
the stack. It is the user's responsibility to do this if it
|
the stack. It is the user's responsibility to do this if it
|
||||||
is wanted. */
|
is wanted. */
|
||||||
#if TLS_TCB_AT_TP
|
#if TLS_TCB_AT_TP
|
||||||
pd = (struct pthread *) ((uintptr_t) attr->stackaddr
|
pd = (struct pthread *) ((uintptr_t) stackaddr
|
||||||
- TLS_TCB_SIZE - adj);
|
- TLS_TCB_SIZE - adj);
|
||||||
#elif TLS_DTV_AT_TP
|
#elif TLS_DTV_AT_TP
|
||||||
pd = (struct pthread *) (((uintptr_t) attr->stackaddr
|
pd = (struct pthread *) (((uintptr_t) stackaddr
|
||||||
- __static_tls_size - adj)
|
- __static_tls_size - adj)
|
||||||
- TLS_PRE_TCB_SIZE);
|
- TLS_PRE_TCB_SIZE);
|
||||||
#endif
|
#endif
|
||||||
@ -410,7 +417,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
pd->specific[0] = pd->specific_1stblock;
|
pd->specific[0] = pd->specific_1stblock;
|
||||||
|
|
||||||
/* Remember the stack-related values. */
|
/* Remember the stack-related values. */
|
||||||
pd->stackblock = (char *) attr->stackaddr - size;
|
pd->stackblock = (char *) stackaddr - size;
|
||||||
pd->stackblock_size = size;
|
pd->stackblock_size = size;
|
||||||
|
|
||||||
/* This is a user-provided stack. It will not be queued in the
|
/* This is a user-provided stack. It will not be queued in the
|
||||||
@ -634,7 +641,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
||||||
#elif _STACK_GROWS_DOWN
|
#elif _STACK_GROWS_DOWN
|
||||||
char *guard = mem;
|
char *guard = mem;
|
||||||
# elif _STACK_GROWS_UP
|
#elif _STACK_GROWS_UP
|
||||||
char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
|
char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
|
||||||
#endif
|
#endif
|
||||||
if (mprotect (guard, guardsize, PROT_NONE) != 0)
|
if (mprotect (guard, guardsize, PROT_NONE) != 0)
|
||||||
@ -734,7 +741,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
*stack = pd->stackblock;
|
*stack = pd->stackblock;
|
||||||
assert (*stack > 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -427,12 +427,25 @@ START_THREAD_DEFN
|
|||||||
#ifdef _STACK_GROWS_DOWN
|
#ifdef _STACK_GROWS_DOWN
|
||||||
char *sp = CURRENT_STACK_FRAME;
|
char *sp = CURRENT_STACK_FRAME;
|
||||||
size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
|
size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
|
||||||
#else
|
|
||||||
# error "to do"
|
|
||||||
#endif
|
|
||||||
assert (freesize < pd->stackblock_size);
|
assert (freesize < pd->stackblock_size);
|
||||||
if (freesize > PTHREAD_STACK_MIN)
|
if (freesize > PTHREAD_STACK_MIN)
|
||||||
__madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
|
__madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
|
||||||
|
#else
|
||||||
|
/* Page aligned start of memory to free (higher than or equal
|
||||||
|
to current sp plus the minimum stack size). */
|
||||||
|
void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME
|
||||||
|
+ PTHREAD_STACK_MIN
|
||||||
|
+ pagesize_m1)
|
||||||
|
& ~pagesize_m1);
|
||||||
|
char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
|
||||||
|
/* Is there any space to free? */
|
||||||
|
if (free_end > (char *)freeblock)
|
||||||
|
{
|
||||||
|
size_t freesize = (size_t)(free_end - (char *)freeblock);
|
||||||
|
assert (freesize < pd->stackblock_size);
|
||||||
|
__madvise (freeblock, freesize, MADV_DONTNEED);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If the thread is detached free the TCB. */
|
/* If the thread is detached free the TCB. */
|
||||||
if (IS_DETACHED (pd))
|
if (IS_DETACHED (pd))
|
||||||
|
@ -58,7 +58,11 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
|||||||
if (__glibc_likely (thread->stackblock != NULL))
|
if (__glibc_likely (thread->stackblock != NULL))
|
||||||
{
|
{
|
||||||
iattr->stacksize = thread->stackblock_size;
|
iattr->stacksize = thread->stackblock_size;
|
||||||
|
#if _STACK_GROWS_DOWN
|
||||||
iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
|
iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
|
||||||
|
#else
|
||||||
|
iattr->stackaddr = (char *) thread->stackblock;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -103,7 +107,9 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
|||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t linelen = 0;
|
size_t linelen = 0;
|
||||||
|
#if _STACK_GROWS_DOWN
|
||||||
uintptr_t last_to = 0;
|
uintptr_t last_to = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (! feof_unlocked (fp))
|
while (! feof_unlocked (fp))
|
||||||
{
|
{
|
||||||
@ -127,17 +133,24 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
|||||||
stack extension request. */
|
stack extension request. */
|
||||||
iattr->stacksize = (iattr->stacksize
|
iattr->stacksize = (iattr->stacksize
|
||||||
& -(intptr_t) GLRO(dl_pagesize));
|
& -(intptr_t) GLRO(dl_pagesize));
|
||||||
|
#if _STACK_GROWS_DOWN
|
||||||
/* The limit might be too high. */
|
/* The limit might be too high. */
|
||||||
if ((size_t) iattr->stacksize
|
if ((size_t) iattr->stacksize
|
||||||
> (size_t) iattr->stackaddr - last_to)
|
> (size_t) iattr->stackaddr - last_to)
|
||||||
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
|
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
|
||||||
|
#else
|
||||||
|
/* The limit might be too high. */
|
||||||
|
if ((size_t) iattr->stacksize
|
||||||
|
> to - (size_t) iattr->stackaddr)
|
||||||
|
iattr->stacksize = to - (size_t) iattr->stackaddr;
|
||||||
|
#endif
|
||||||
/* We succeed and no need to look further. */
|
/* We succeed and no need to look further. */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if _STACK_GROWS_DOWN
|
||||||
last_to = to;
|
last_to = to;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
free (line);
|
free (line);
|
||||||
|
Reference in New Issue
Block a user