aboutsummaryrefslogtreecommitdiff
path: root/nptl/allocatestack.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@systemhalted.org>2015-08-09 04:17:17 -0400
committerMike Frysinger <vapier@gentoo.org>2016-02-19 12:41:29 -0500
commitd615a47355699d29df01b28a120cef29c8a38091 (patch)
treea60b5cd1dddc6bb30e409601dad08f09a601993b /nptl/allocatestack.c
parent11fca9615fa7b98135d262066db5f4156dd72955 (diff)
downloadglibc-d615a47355699d29df01b28a120cef29c8a38091.tar
glibc-d615a47355699d29df01b28a120cef29c8a38091.tar.gz
glibc-d615a47355699d29df01b28a120cef29c8a38091.tar.bz2
glibc-d615a47355699d29df01b28a120cef29c8a38091.zip
nptl: support thread stacks that grow up
Gentoo has been carrying this for all arches since 2.17. URL: http://bugs.gentoo.org/301642
Diffstat (limited to 'nptl/allocatestack.c')
-rw-r--r--nptl/allocatestack.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index c044b205c8..6b42b11d5a 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -372,6 +372,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
{
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
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. */
#if TLS_TCB_AT_TP
- adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+ adj = ((uintptr_t) 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)
+ adj = ((uintptr_t) stackaddr - __static_tls_size)
& __static_tls_align_m1;
assert (size > adj);
#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
is wanted. */
#if TLS_TCB_AT_TP
- pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+ pd = (struct pthread *) ((uintptr_t) stackaddr
- TLS_TCB_SIZE - adj);
#elif TLS_DTV_AT_TP
- pd = (struct pthread *) (((uintptr_t) attr->stackaddr
+ pd = (struct pthread *) (((uintptr_t) stackaddr
- __static_tls_size - adj)
- TLS_PRE_TCB_SIZE);
#endif
@@ -410,7 +417,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
pd->specific[0] = pd->specific_1stblock;
/* Remember the stack-related values. */
- pd->stackblock = (char *) attr->stackaddr - size;
+ pd->stackblock = (char *) stackaddr - size;
pd->stackblock_size = size;
/* 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);
#elif _STACK_GROWS_DOWN
char *guard = mem;
-# elif _STACK_GROWS_UP
+#elif _STACK_GROWS_UP
char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
#endif
if (mprotect (guard, guardsize, PROT_NONE) != 0)
@@ -734,7 +741,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
# endif
#else
*stack = pd->stackblock;
- assert (*stack > 0);
#endif
return 0;