aboutsummaryrefslogtreecommitdiff
path: root/nptl/allocatestack.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@systemhalted.org>2013-08-16 14:57:59 -0400
committerMike Frysinger <vapier@gentoo.org>2014-02-08 09:21:06 -0500
commita5760bbb50f3dbfd1e4051a54aae35060cdd639b (patch)
tree87050392c0d80ee6b56edf4e945e144c9521a62a /nptl/allocatestack.c
parent6a714e48586aa7f21d2eeef9195cee57c9ebaa60 (diff)
downloadglibc-a5760bbb50f3dbfd1e4051a54aae35060cdd639b.tar
glibc-a5760bbb50f3dbfd1e4051a54aae35060cdd639b.tar.gz
glibc-a5760bbb50f3dbfd1e4051a54aae35060cdd639b.tar.bz2
glibc-a5760bbb50f3dbfd1e4051a54aae35060cdd639b.zip
nptl: support thread stacks that grow up
http://bugs.gentoo.org/301642
Diffstat (limited to 'nptl/allocatestack.c')
-rw-r--r--nptl/allocatestack.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 13eca47cf2..ad6d8a9f8b 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -371,6 +371,15 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0))
{
uintptr_t adj;
+#if _STACK_GROWS_DOWN
+ char * stackaddr = (char *) attr->stackaddr;
+#else
+ /* 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. */
+ char * stackaddr = (char *) attr->stackaddr + attr->stacksize;
+#endif
/* If the user also specified the size of the stack make sure it
is large enough. */
@@ -380,11 +389,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
@@ -394,10 +403,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
@@ -409,7 +418,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
@@ -635,7 +644,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)
@@ -731,7 +740,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
*stack = stacktop;
#elif _STACK_GROWS_UP
*stack = pd->stackblock;
- assert (*stack > 0);
#endif
return 0;