diff options
author | Carlos O'Donell <carlos@systemhalted.org> | 2015-08-09 04:17:17 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2016-02-19 12:41:29 -0500 |
commit | d615a47355699d29df01b28a120cef29c8a38091 (patch) | |
tree | a60b5cd1dddc6bb30e409601dad08f09a601993b /nptl/allocatestack.c | |
parent | 11fca9615fa7b98135d262066db5f4156dd72955 (diff) | |
download | glibc-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.c | 20 |
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; |