aboutsummaryrefslogtreecommitdiffstats
path: root/libc/bionic/pthread_exit.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2015-03-17 18:12:58 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-03-17 18:12:59 +0000
commit94babaee1b6598b15bd807461055d4dcaaa52f10 (patch)
tree0efa7df548f74df352be643bc640202606ce0347 /libc/bionic/pthread_exit.cpp
parent5490bebd7cdd4406780358f590391b75ab8a7d84 (diff)
parent58cf31b50699ed9f523de38c8e943f3bbd1ced9e (diff)
downloadandroid_bionic-94babaee1b6598b15bd807461055d4dcaaa52f10.tar.gz
android_bionic-94babaee1b6598b15bd807461055d4dcaaa52f10.tar.bz2
android_bionic-94babaee1b6598b15bd807461055d4dcaaa52f10.zip
Merge "Make pthread join_state not protected by g_thread_list_lock."
Diffstat (limited to 'libc/bionic/pthread_exit.cpp')
-rw-r--r--libc/bionic/pthread_exit.cpp50
1 files changed, 25 insertions, 25 deletions
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index d0d64b0ec..81cc67be9 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -87,9 +87,12 @@ void pthread_exit(void* return_value) {
thread->alternate_signal_stack = NULL;
}
- bool free_mapped_space = false;
- pthread_mutex_lock(&g_thread_list_lock);
- if ((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) != 0) {
+ ThreadJoinState old_state = THREAD_NOT_JOINED;
+ while (old_state == THREAD_NOT_JOINED &&
+ !atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
+ }
+
+ if (old_state == THREAD_DETACHED) {
// The thread is detached, no one will use pthread_internal_t after pthread_exit.
// So we can free mapped space, which includes pthread_internal_t and thread stack.
// First make sure that the kernel does not try to clear the tid field
@@ -97,28 +100,25 @@ void pthread_exit(void* return_value) {
__set_tid_address(NULL);
// pthread_internal_t is freed below with stack, not here.
+ pthread_mutex_lock(&g_thread_list_lock);
_pthread_internal_remove_locked(thread, false);
- free_mapped_space = true;
- } else {
- // Mark the thread as exiting without freeing pthread_internal_t.
- thread->attr.flags |= PTHREAD_ATTR_FLAG_ZOMBIE;
- }
- pthread_mutex_unlock(&g_thread_list_lock);
-
- if (free_mapped_space && thread->mmap_size != 0) {
- // We need to free mapped space for detached threads when they exit.
- // That's not something we can do in C.
-
- // We don't want to take a signal after we've unmapped the stack.
- // That's one last thing we can handle in C.
- sigset_t mask;
- sigfillset(&mask);
- sigprocmask(SIG_SETMASK, &mask, NULL);
-
- _exit_with_stack_teardown(thread->attr.stack_base, thread->mmap_size);
- } else {
- // No need to free mapped space. Either there was no space mapped, or it is left for
- // the pthread_join caller to clean up.
- __exit(0);
+ pthread_mutex_unlock(&g_thread_list_lock);
+
+ if (thread->mmap_size != 0) {
+ // We need to free mapped space for detached threads when they exit.
+ // That's not something we can do in C.
+
+ // We don't want to take a signal after we've unmapped the stack.
+ // That's one last thing we can handle in C.
+ sigset_t mask;
+ sigfillset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+
+ _exit_with_stack_teardown(thread->attr.stack_base, thread->mmap_size);
+ }
}
+
+ // No need to free mapped space. Either there was no space mapped, or it is left for
+ // the pthread_join caller to clean up.
+ __exit(0);
}