diff options
author | Elliott Hughes <enh@google.com> | 2014-08-25 17:26:50 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2014-08-26 10:36:38 -0700 |
commit | 57b7a6110e7e8b446fc23cce4765ff625ee0a105 (patch) | |
tree | e2578675ae1435988a645a32182ced476f802ec5 /libc/bionic/pthread_attr.cpp | |
parent | a4a8c4feb8cf3cebf8aceace70e699e128095b5c (diff) | |
download | android_bionic-57b7a6110e7e8b446fc23cce4765ff625ee0a105.tar.gz android_bionic-57b7a6110e7e8b446fc23cce4765ff625ee0a105.tar.bz2 android_bionic-57b7a6110e7e8b446fc23cce4765ff625ee0a105.zip |
Fix pthread_getattr_np for the main thread.
On most architectures the kernel subtracts a random offset to the stack
pointer in create_elf_tables by calling arch_align_stack before writing
the auxval table and so on. On all but x86 this doesn't cause a problem
because the random offset is less than a page, but on x86 it's up to two
pages. This means that our old technique of rounding the stack pointer
doesn't work. (Our old implementation of that technique was wrong too.)
It's also incorrect to assume that the main thread's stack base and size
are constant. Likewise to assume that the main thread has a guard page.
The main thread is not like other threads.
This patch switches to reading /proc/self/maps (and checking RLIMIT_STACK)
whenever we're asked.
Bug: 17111575
Signed-off-by: Fengwei Yin <fengwei.yin@intel.com>
Change-Id: I1d4dbffe7bc7bda1d353c3a295dbf68d29f63158
Diffstat (limited to 'libc/bionic/pthread_attr.cpp')
-rw-r--r-- | libc/bionic/pthread_attr.cpp | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp index e1cd85365..8df3bffac 100644 --- a/libc/bionic/pthread_attr.cpp +++ b/libc/bionic/pthread_attr.cpp @@ -28,6 +28,13 @@ #include <pthread.h> +#include <inttypes.h> +#include <stdio.h> +#include <sys/resource.h> + +#include "private/bionic_string_utils.h" +#include "private/ErrnoRestorer.h" +#include "private/libc_logging.h" #include "pthread_internal.h" int pthread_attr_init(pthread_attr_t* attr) { @@ -90,8 +97,8 @@ int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stack_size) { } int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) { - *stack_size = attr->stack_size; - return 0; + void* unused; + return pthread_attr_getstack(attr, &unused, stack_size); } int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) { @@ -106,7 +113,42 @@ int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_s return 0; } +static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) { + ErrnoRestorer errno_restorer; + + // It doesn't matter which thread we are; we're just looking for "[stack]". + FILE* fp = fopen("/proc/self/maps", "re"); + if (fp == NULL) { + return errno; + } + char line[BUFSIZ]; + while (fgets(line, sizeof(line), fp) != NULL) { + if (ends_with(line, " [stack]\n")) { + uintptr_t lo, hi; + if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) { + *stack_base = reinterpret_cast<void*>(lo); + *stack_size = hi - lo; + + // Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises? + rlimit stack_limit; + if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) { + if (*stack_size > stack_limit.rlim_cur) { + *stack_size = stack_limit.rlim_cur; + } + } + + fclose(fp); + return 0; + } + } + } + __libc_fatal("No [stack] line found in /proc/self/maps!"); +} + int pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) { + if ((attr->flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) != 0) { + return __pthread_attr_getstack_main_thread(stack_base, stack_size); + } *stack_base = attr->stack_base; *stack_size = attr->stack_size; return 0; @@ -122,9 +164,8 @@ int pthread_attr_getguardsize(const pthread_attr_t* attr, size_t* guard_size) { return 0; } -int pthread_getattr_np(pthread_t thid, pthread_attr_t* attr) { - pthread_internal_t* thread = (pthread_internal_t*) thid; - *attr = thread->attr; +int pthread_getattr_np(pthread_t t, pthread_attr_t* attr) { + *attr = reinterpret_cast<pthread_internal_t*>(t)->attr; return 0; } |