From 8574a0670bf698b8d2f817098f9d825c4be03a68 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Mon, 1 Dec 2014 22:37:56 -0800 Subject: [PATCH] Use mmap to create the pthread_internal_t. Bug: 16847284 Change-Id: I488fa236f57aa3acb29b4ffbbab2fab51b0653be --- libc/bionic/pthread_create.cpp | 7 +++---- libc/bionic/pthread_exit.cpp | 6 ------ libc/bionic/pthread_internal.h | 2 ++ libc/bionic/pthread_internals.cpp | 25 ++++++++++++++++++++++++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index fc8afa2ff..8bb1be9d9 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -158,9 +158,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, // Inform the rest of the C library that at least one thread was created. __isthreaded = 1; - pthread_internal_t* thread = reinterpret_cast(calloc(sizeof(*thread), 1)); + pthread_internal_t* thread = __create_thread_struct(); if (thread == NULL) { - __libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: couldn't allocate thread"); return EAGAIN; } @@ -179,7 +178,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, // The caller didn't provide a stack, so allocate one. thread->attr.stack_base = __create_thread_stack(thread); if (thread->attr.stack_base == NULL) { - free(thread); + __free_thread_struct(thread); return EAGAIN; } } else { @@ -230,7 +229,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, if (!thread->user_allocated_stack()) { munmap(thread->attr.stack_base, thread->attr.stack_size); } - free(thread); + __free_thread_struct(thread); __libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s", strerror(errno)); return clone_errno; } diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp index 6cd5311ed..a6bb36312 100644 --- a/libc/bionic/pthread_exit.cpp +++ b/libc/bionic/pthread_exit.cpp @@ -112,12 +112,6 @@ void pthread_exit(void* return_value) { } pthread_mutex_unlock(&g_thread_list_lock); - // Perform a second key cleanup. When using jemalloc, a call to free from - // _pthread_internal_remove_locked causes the memory associated with a key - // to be reallocated. - // TODO: When b/16847284 is fixed this call can be removed. - pthread_key_clean_all(); - if (user_allocated_stack) { // Cleaning up this thread's stack is the creator's responsibility, not ours. __exit(0); diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h index 392e781e4..c5136c93c 100644 --- a/libc/bionic/pthread_internal.h +++ b/libc/bionic/pthread_internal.h @@ -94,6 +94,8 @@ struct pthread_internal_t { char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE]; }; +__LIBC_HIDDEN__ pthread_internal_t* __create_thread_struct(); +__LIBC_HIDDEN__ void __free_thread_struct(pthread_internal_t*); __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread, bool add_to_thread_list); __LIBC_HIDDEN__ void __init_tls(pthread_internal_t* thread); __LIBC_HIDDEN__ void __init_alternate_signal_stack(pthread_internal_t*); diff --git a/libc/bionic/pthread_internals.cpp b/libc/bionic/pthread_internals.cpp index 2270d96f3..33cddd74e 100644 --- a/libc/bionic/pthread_internals.cpp +++ b/libc/bionic/pthread_internals.cpp @@ -28,15 +28,38 @@ #include "pthread_internal.h" +#include #include +#include +#include #include "private/bionic_futex.h" #include "private/bionic_tls.h" +#include "private/libc_logging.h" #include "private/ScopedPthreadMutexLocker.h" pthread_internal_t* g_thread_list = NULL; pthread_mutex_t g_thread_list_lock = PTHREAD_MUTEX_INITIALIZER; +pthread_internal_t* __create_thread_struct() { + void* result = mmap(NULL, sizeof(pthread_internal_t), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + if (result == MAP_FAILED) { + __libc_format_log(ANDROID_LOG_WARN, "libc", + "__create_thread_struct() failed: %s", strerror(errno)); + return NULL; + } + return reinterpret_cast(result); +} + +void __free_thread_struct(pthread_internal_t* thread) { + int result = munmap(thread, sizeof(pthread_internal_t)); + if (result != 0) { + __libc_format_log(ANDROID_LOG_WARN, "libc", + "__free_thread_struct() failed: %s", strerror(errno)); + } +} + void _pthread_internal_remove_locked(pthread_internal_t* thread) { if (thread->next != NULL) { thread->next->prev = thread->prev; @@ -50,7 +73,7 @@ void _pthread_internal_remove_locked(pthread_internal_t* thread) { // The main thread is not heap-allocated. See __libc_init_tls for the declaration, // and __libc_init_common for the point where it's added to the thread list. if ((thread->attr.flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) == 0) { - free(thread); + __free_thread_struct(thread); } }