pthread_internal.cpp revision 4bc739a54c4ba9063e91bef06ff226dab118792d
19d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes/*
29d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * Copyright (C) 2008 The Android Open Source Project
39d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * All rights reserved.
49d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *
59d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * Redistribution and use in source and binary forms, with or without
69d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * modification, are permitted provided that the following conditions
79d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * are met:
89d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *  * Redistributions of source code must retain the above copyright
99d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *    notice, this list of conditions and the following disclaimer.
109d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *  * Redistributions in binary form must reproduce the above copyright
119d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *    notice, this list of conditions and the following disclaimer in
129d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *    the documentation and/or other materials provided with the
139d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *    distribution.
149d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes *
159d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
169d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
179d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
189d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
199d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
209d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
219d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
229d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
239d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
249d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
259d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes * SUCH DAMAGE.
279d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes */
289d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
299d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes#include "pthread_internal.h"
309d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
318574a0670bf698b8d2f817098f9d825c4be03a68Yabin Cui#include <errno.h>
3275ef63d6cf83787233d1c45489c4ec03b0a67d16Dan Albert#include <stdlib.h>
338574a0670bf698b8d2f817098f9d825c4be03a68Yabin Cui#include <string.h>
348574a0670bf698b8d2f817098f9d825c4be03a68Yabin Cui#include <sys/mman.h>
3575ef63d6cf83787233d1c45489c4ec03b0a67d16Dan Albert
36c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes#include "private/bionic_futex.h"
37eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_tls.h"
388574a0670bf698b8d2f817098f9d825c4be03a68Yabin Cui#include "private/libc_logging.h"
39eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/ScopedPthreadMutexLocker.h"
409d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
41673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuistatic pthread_internal_t* g_thread_list = NULL;
42673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuistatic pthread_mutex_t g_thread_list_lock = PTHREAD_MUTEX_INITIALIZER;
43673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui
44673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuipthread_t __pthread_internal_add(pthread_internal_t* thread) {
45673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  ScopedPthreadMutexLocker locker(&g_thread_list_lock);
46673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui
47673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  // We insert at the head.
48673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  thread->next = g_thread_list;
49673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  thread->prev = NULL;
50673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  if (thread->next != NULL) {
51673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui    thread->next->prev = thread;
52673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  }
53673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  g_thread_list = thread;
54673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  return reinterpret_cast<pthread_t>(thread);
55673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui}
56673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui
57673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuivoid __pthread_internal_remove(pthread_internal_t* thread) {
58673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  ScopedPthreadMutexLocker locker(&g_thread_list_lock);
599d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
609d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  if (thread->next != NULL) {
619d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes    thread->next->prev = thread->prev;
629d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  }
639d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  if (thread->prev != NULL) {
649d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes    thread->prev->next = thread->next;
659d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  } else {
661728b2396591853345507a063ed6075dfd251706Elliott Hughes    g_thread_list = thread->next;
679d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  }
68673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui}
699d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
70673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuistatic void __pthread_internal_free(pthread_internal_t* thread) {
71673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  if (thread->mmap_size != 0) {
72ba8dfc2669d658dc340eb8f9c9b40ca074f05047Yabin Cui    // Free mapped space, including thread stack and pthread_internal_t.
73ba8dfc2669d658dc340eb8f9c9b40ca074f05047Yabin Cui    munmap(thread->attr.stack_base, thread->mmap_size);
749d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  }
759d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes}
769d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
77673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuivoid __pthread_internal_remove_and_free(pthread_internal_t* thread) {
78673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  __pthread_internal_remove(thread);
79673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  __pthread_internal_free(thread);
80673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui}
81673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui
82673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cuipthread_internal_t* __pthread_internal_find(pthread_t thread_id) {
83673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(thread_id);
844bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov
854bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov  // check if thread is pthread_self() before acquiring the lock
864bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov  if (thread == __get_thread()) {
874bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov    return thread;
884bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov  }
894bc739a54c4ba9063e91bef06ff226dab118792dDimitry Ivanov
90220b99bdc1c5f51825ac2a87062bc05fe3e0d722Yabin Cui  ScopedPthreadMutexLocker locker(&g_thread_list_lock);
919d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes
92220b99bdc1c5f51825ac2a87062bc05fe3e0d722Yabin Cui  for (pthread_internal_t* t = g_thread_list; t != NULL; t = t->next) {
93220b99bdc1c5f51825ac2a87062bc05fe3e0d722Yabin Cui    if (t == thread) {
94220b99bdc1c5f51825ac2a87062bc05fe3e0d722Yabin Cui      return thread;
95673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui    }
969d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes  }
97673b15e4ee2c6d99b150aedddc0f389e29f98e1bYabin Cui  return NULL;
989d23e04c43dbb8480bea8be28b8a2f37423bec49Elliott Hughes}
99