OSDN Git Service

Remove the broken pthread deadlock prediction.
authorElliott Hughes <enh@google.com>
Wed, 14 May 2014 18:35:49 +0000 (11:35 -0700)
committerElliott Hughes <enh@google.com>
Wed, 14 May 2014 18:38:22 +0000 (11:38 -0700)
This hasn't built in over one release cycle and no one even noticed.
art does this the right way and other projects should do the same.

Change-Id: I7d1fb84c4080e008f329ee73e209ce85a36e6d55

libc/Android.mk
libc/bionic/libc_init_dynamic.cpp
libc/bionic/pthread_debug.cpp [deleted file]
libc/bionic/pthread_mutex.cpp

index ed7d055..c0da9b2 100644 (file)
@@ -747,10 +747,6 @@ LOCAL_MODULE := libc_bionic
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
-# Set -DPTHREAD_DEBUG_ENABLED=true to enable support for pthread deadlock prediction.
-# Since this code is experimental it is disabled by default.
-LOCAL_CFLAGS += -DPTHREAD_DEBUG_ENABLED=false
-
 ifneq ($(TARGET_USES_LOGD),false)
 LOCAL_CFLAGS += -DTARGET_USES_LOGD
 endif
@@ -889,7 +885,6 @@ LOCAL_SRC_FILES := \
     bionic/malloc_debug_common.cpp \
     bionic/debug_mapinfo.cpp \
     bionic/debug_stacktrace.cpp \
-    bionic/pthread_debug.cpp \
     bionic/libc_init_dynamic.cpp \
     bionic/NetdClient.cpp \
 
index 3d98861..659cf39 100644 (file)
@@ -55,7 +55,6 @@
 #include "private/KernelArgumentBlock.h"
 
 extern "C" {
-  extern void pthread_debug_init(void);
   extern void malloc_debug_init(void);
   extern void malloc_debug_fini(void);
   extern void netdClientInit(void);
@@ -77,11 +76,8 @@ __attribute__((constructor)) static void __libc_preinit() {
 
   __libc_init_common(*args);
 
-  // Hooks for the debug malloc and pthread libraries to let them know that we're starting up.
-  pthread_debug_init();
+  // Hooks for various libraries to let them know that we're starting up.
   malloc_debug_init();
-
-  // Hook for the netd client library to let it know that we're starting up.
   netdClientInit();
 }
 
diff --git a/libc/bionic/pthread_debug.cpp b/libc/bionic/pthread_debug.cpp
deleted file mode 100644 (file)
index be89b46..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/atomics.h>
-#include <sys/system_properties.h>
-#include <sys/mman.h>
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <pthread.h>
-#include <unwind.h>
-#include <unistd.h>
-
-#include "private/bionic_tls.h"
-#include "debug_mapinfo.h"
-#include "debug_stacktrace.h"
-#include "private/libc_logging.h"
-
-/*
- * ===========================================================================
- *      Deadlock prediction
- * ===========================================================================
- */
-/*
-The idea is to predict the possibility of deadlock by recording the order
-in which locks are acquired.  If we see an attempt to acquire a lock
-out of order, we can identify the locks and offending code.
-
-To make this work, we need to keep track of the locks held by each thread,
-and create history trees for each lock.  When a thread tries to acquire
-a new lock, we walk through the "history children" of the lock, looking
-for a match with locks the thread already holds.  If we find a match,
-it means the thread has made a request that could result in a deadlock.
-
-To support recursive locks, we always allow re-locking a currently-held
-lock, and maintain a recursion depth count.
-
-An ASCII-art example, where letters represent locks:
-
-        A
-       /|\
-      / | \
-     B  |  D
-      \ |
-       \|
-        C
-
-The above is the tree we'd have after handling lock synchronization
-sequences "ABC", "AC", "AD".  A has three children, {B, C, D}.  C is also
-a child of B.  (The lines represent pointers between parent and child.
-Every node can have multiple parents and multiple children.)
-
-If we hold AC, and want to lock B, we recursively search through B's
-children to see if A or C appears.  It does, so we reject the attempt.
-(A straightforward way to implement it: add a link from C to B, then
-determine whether the graph starting at B contains a cycle.)
-
-If we hold AC and want to lock D, we would succeed, creating a new link
-from C to D.
-
-Updates to MutexInfo structs are only allowed for the thread that holds
-the lock, so we actually do most of our deadlock prediction work after
-the lock has been acquired.
-*/
-
-#if PTHREAD_DEBUG_ENABLED
-
-// =============================================================================
-// log functions
-// =============================================================================
-
-#define LOGD(format, ...)  \
-    __libc_format_log(ANDROID_LOG_DEBUG, "pthread_debug", (format), ##__VA_ARGS__ )
-
-#define LOGW(format, ...)  \
-    __libc_format_log(ANDROID_LOG_WARN, "pthread_debug", (format), ##__VA_ARGS__ )
-
-#define LOGE(format, ...)  \
-    __libc_format_log(ANDROID_LOG_ERROR, "pthread_debug", (format), ##__VA_ARGS__ )
-
-#define LOGI(format, ...)  \
-    __libc_format_log(ANDROID_LOG_INFO, "pthread_debug", (format), ##__VA_ARGS__ )
-
-static const char* const kStartBanner =
-        "===============================================================";
-
-static const char* const kEndBanner =
-        "===============================================================";
-
-extern const char* __progname;
-
-#define STACK_TRACE_DEPTH 16
-
-/****************************************************************************/
-
-/*
- * level <= 0 : deadlock prediction disabled
- * level    1 : deadlock prediction enabled, w/o call stacks
- * level    2 : deadlock prediction enabled w/ call stacks
- */
-#define CAPTURE_CALLSTACK 2
-static int g_pthread_debug_level = 0;
-static pid_t g_pthread_debug_disabled_thread = -1;
-static pthread_mutex_t g_dbg_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/****************************************************************************/
-
-/* some simple/lame malloc replacement
- * NOT thread-safe and leaks everything
- */
-
-#define DBG_ALLOC_BLOCK_SIZE PAGESIZE
-static size_t g_dbg_alloc_offset = DBG_ALLOC_BLOCK_SIZE;
-static char* g_dbg_alloc_ptr = NULL;
-
-template <typename T>
-static T* DbgAllocLocked(size_t count = 1) {
-    size_t size = sizeof(T) * count;
-    if ((g_dbg_alloc_offset + size) > DBG_ALLOC_BLOCK_SIZE) {
-        g_dbg_alloc_offset = 0;
-        g_dbg_alloc_ptr = reinterpret_cast<char*>(mmap(NULL, DBG_ALLOC_BLOCK_SIZE,
-                                                    PROT_READ|PROT_WRITE,
-                                                    MAP_ANON | MAP_PRIVATE, 0, 0));
-        if (g_dbg_alloc_ptr == MAP_FAILED) {
-            return NULL;
-        }
-    }
-    void* addr = g_dbg_alloc_ptr + g_dbg_alloc_offset;
-    g_dbg_alloc_offset += size;
-    return reinterpret_cast<T*>(addr);
-}
-
-static void* debug_realloc(void *ptr, size_t size, size_t old_size) {
-    void* addr = mmap(NULL, size, PROT_READ|PROT_WRITE,
-            MAP_ANON | MAP_PRIVATE, 0, 0);
-    if (addr != MAP_FAILED) {
-        if (ptr) {
-            memcpy(addr, ptr, old_size);
-            munmap(ptr, old_size);
-        }
-    } else {
-        addr = NULL;
-    }
-    return addr;
-}
-
-/*****************************************************************************/
-
-struct MutexInfo;
-
-typedef struct CallStack {
-    uintptr_t    depth;
-    uintptr_t*   addrs;
-} CallStack;
-
-typedef struct MutexInfo* MutexInfoListEntry;
-typedef struct CallStack  CallStackListEntry;
-
-typedef struct GrowingList {
-    int alloc;
-    int count;
-    union {
-        void*               data;
-        MutexInfoListEntry* list;
-        CallStackListEntry* stack;
-    };
-} GrowingList;
-
-typedef GrowingList MutexInfoList;
-typedef GrowingList CallStackList;
-
-typedef struct MutexInfo {
-    // thread currently holding the lock or 0
-    pid_t               owner;
-
-    // most-recently-locked doubly-linked list
-    struct MutexInfo*   prev;
-    struct MutexInfo*   next;
-
-    // for reentrant locks
-    int                 lockCount;
-    // when looking for loops in the graph, marks visited nodes
-    int                 historyMark;
-    // the actual mutex
-    pthread_mutex_t*    mutex;
-    // list of locks directly acquired AFTER this one in the same thread
-    MutexInfoList       children;
-    // list of locks directly acquired BEFORE this one in the same thread
-    MutexInfoList       parents;
-    // list of call stacks when a new link is established to this lock form its parent
-    CallStackList       stacks;
-    // call stack when this lock was acquired last
-    int                 stackDepth;
-    uintptr_t           stackTrace[STACK_TRACE_DEPTH];
-} MutexInfo;
-
-static void growingListInit(GrowingList* list) {
-    list->alloc = 0;
-    list->count = 0;
-    list->data = NULL;
-}
-
-static void growingListAdd(GrowingList* pList, size_t objSize) {
-    if (pList->count == pList->alloc) {
-        size_t oldsize = pList->alloc * objSize;
-        pList->alloc += PAGESIZE / objSize;
-        size_t size = pList->alloc * objSize;
-        pList->data = debug_realloc(pList->data, size, oldsize);
-    }
-    pList->count++;
-}
-
-static void initMutexInfo(MutexInfo* object, pthread_mutex_t* mutex) {
-    object->owner = 0;
-    object->prev = 0;
-    object->next = 0;
-    object->lockCount = 0;
-    object->historyMark = 0;
-    object->mutex = mutex;
-    growingListInit(&object->children);
-    growingListInit(&object->parents);
-    growingListInit(&object->stacks);
-    object->stackDepth = 0;
-}
-
-typedef struct ThreadInfo {
-    pid_t       pid;
-    MutexInfo*  mrl;
-} ThreadInfo;
-
-static void initThreadInfo(ThreadInfo* object, pid_t pid) {
-    object->pid = pid;
-    object->mrl = NULL;
-}
-
-/****************************************************************************/
-
-static MutexInfo* get_mutex_info(pthread_mutex_t *mutex);
-static void mutex_lock_checked(MutexInfo* mrl, MutexInfo* object);
-static void mutex_unlock_checked(MutexInfo* object);
-
-/****************************************************************************/
-
-extern "C" int pthread_mutex_lock_impl(pthread_mutex_t *mutex);
-extern "C" int pthread_mutex_unlock_impl(pthread_mutex_t *mutex);
-
-static int pthread_mutex_lock_unchecked(pthread_mutex_t *mutex) {
-    return pthread_mutex_lock_impl(mutex);
-}
-
-static int pthread_mutex_unlock_unchecked(pthread_mutex_t *mutex) {
-    return pthread_mutex_unlock_impl(mutex);
-}
-
-/****************************************************************************/
-
-static void dup_backtrace(CallStack* stack, size_t count, uintptr_t const* addrs) {
-    stack->depth = count;
-    stack->addrs = DbgAllocLocked<uintptr_t>(count);
-    memcpy(stack->addrs, addrs, count * sizeof(uintptr_t));
-}
-
-/****************************************************************************/
-
-static int historyListHas(
-        const MutexInfoList* list, MutexInfo const * obj) {
-    int i;
-    for (i=0; i<list->count; i++) {
-        if (list->list[i] == obj) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-static void historyListAdd(MutexInfoList* pList, MutexInfo* obj) {
-    growingListAdd(pList, sizeof(MutexInfoListEntry));
-    pList->list[pList->count - 1] = obj;
-}
-
-static int historyListRemove(MutexInfoList* pList, MutexInfo* obj) {
-    int i;
-    for (i = pList->count-1; i >= 0; i--) {
-        if (pList->list[i] == obj) {
-            break;
-        }
-    }
-    if (i < 0) {
-        // not found!
-        return 0;
-    }
-
-    if (i != pList->count-1) {
-        // copy the last entry to the new free slot
-        pList->list[i] = pList->list[pList->count-1];
-    }
-    pList->count--;
-    memset(&pList->list[pList->count], 0, sizeof(MutexInfoListEntry));
-    return 1;
-}
-
-static void linkParentToChild(MutexInfo* parent, MutexInfo* child) {
-    historyListAdd(&parent->children, child);
-    historyListAdd(&child->parents, parent);
-}
-
-static void unlinkParentFromChild(MutexInfo* parent, MutexInfo* child) {
-    historyListRemove(&parent->children, child);
-    historyListRemove(&child->parents, parent);
-}
-
-/****************************************************************************/
-
-static void callstackListAdd(CallStackList* pList,
-        int count, uintptr_t const* addrs) {
-    growingListAdd(pList, sizeof(CallStackListEntry));
-    dup_backtrace(&pList->stack[pList->count - 1], count, addrs);
-}
-
-/****************************************************************************/
-
-/*
- * Recursively traverse the object hierarchy starting at "obj".  We mark
- * ourselves on entry and clear the mark on exit.  If we ever encounter
- * a marked object, we have a cycle.
- *
- * Returns "true" if all is well, "false" if we found a cycle.
- */
-
-static int traverseTree(MutexInfo* obj, MutexInfo const* objParent)
-{
-    /*
-     * Have we been here before?
-     */
-    if (obj->historyMark) {
-        int stackDepth;
-        uintptr_t addrs[STACK_TRACE_DEPTH];
-
-        /* Turn off prediction temporarily in this thread while logging */
-        g_pthread_debug_disabled_thread = gettid();
-
-        backtrace_startup();
-
-        LOGW("%s\n", kStartBanner);
-        LOGW("pid: %d, tid: %d >>> %s <<<", getpid(), gettid(), __progname);
-        LOGW("Illegal lock attempt:\n");
-        LOGW("--- pthread_mutex_t at %p\n", obj->mutex);
-        stackDepth = get_backtrace(addrs, STACK_TRACE_DEPTH);
-        log_backtrace(addrs, stackDepth);
-
-        LOGW("+++ Currently held locks in this thread (in reverse order):");
-        MutexInfo* cur = obj;
-        pid_t ourtid = gettid();
-        int i;
-        for (i=0 ; i<cur->parents.count ; i++) {
-            MutexInfo* parent = cur->parents.list[i];
-            if (parent->owner == ourtid) {
-                LOGW("--- pthread_mutex_t at %p\n", parent->mutex);
-                if (g_pthread_debug_level >= CAPTURE_CALLSTACK) {
-                    log_backtrace(parent->stackTrace, parent->stackDepth);
-                }
-                cur = parent;
-                break;
-            }
-        }
-
-        LOGW("+++ Earlier, the following lock order (from last to first) was established\n");
-        return 0;
-    }
-
-    obj->historyMark = 1;
-
-    MutexInfoList* pList = &obj->children;
-    int result = 1;
-    int i;
-    for (i = pList->count-1; i >= 0; i--) {
-        MutexInfo* child = pList->list[i];
-        if (!traverseTree(child,  obj)) {
-            LOGW("--- pthread_mutex_t at %p\n", obj->mutex);
-            if (g_pthread_debug_level >= CAPTURE_CALLSTACK) {
-                int index = historyListHas(&obj->parents, objParent);
-                if ((size_t)index < (size_t)obj->stacks.count) {
-                    log_backtrace(obj->stacks.stack[index].addrs, obj->stacks.stack[index].depth);
-                } else {
-                    log_backtrace(obj->stackTrace, obj->stackDepth);
-                }
-            }
-            result = 0;
-            break;
-        }
-    }
-
-    obj->historyMark = 0;
-    return result;
-}
-
-/****************************************************************************/
-
-static void mutex_lock_checked(MutexInfo* mrl, MutexInfo* object)
-{
-    pid_t tid = gettid();
-    if (object->owner == tid) {
-        object->lockCount++;
-        return;
-    }
-
-    object->owner = tid;
-    object->lockCount = 0;
-
-    if (g_pthread_debug_level >= CAPTURE_CALLSTACK) {
-        // always record the call stack when acquiring a lock.
-        // it's not efficient, but is useful during diagnostics
-        object->stackDepth = get_backtrace(object->stackTrace, STACK_TRACE_DEPTH);
-    }
-
-    // no other locks held in this thread -- no deadlock possible!
-    if (mrl == NULL)
-        return;
-
-    // check if the lock we're trying to acquire is a direct descendant of
-    // the most recently locked mutex in this thread, in which case we're
-    // in a good situation -- no deadlock possible
-    if (historyListHas(&mrl->children, object) >= 0)
-        return;
-
-    pthread_mutex_lock_unchecked(&g_dbg_lock);
-
-    linkParentToChild(mrl, object);
-    if (!traverseTree(object, mrl)) {
-        backtrace_shutdown();
-        LOGW("%s\n", kEndBanner);
-        unlinkParentFromChild(mrl, object);
-        // reenable pthread debugging for this thread
-        g_pthread_debug_disabled_thread = -1;
-    } else {
-        // record the call stack for this link
-        // NOTE: the call stack is added at the same index
-        // as mrl in object->parents[]
-        // ie: object->parents.count == object->stacks.count, which is
-        // also the index.
-        if (g_pthread_debug_level >= CAPTURE_CALLSTACK) {
-            callstackListAdd(&object->stacks,
-                    object->stackDepth, object->stackTrace);
-        }
-    }
-
-    pthread_mutex_unlock_unchecked(&g_dbg_lock);
-}
-
-static void mutex_unlock_checked(MutexInfo* object)
-{
-    pid_t tid = gettid();
-    if (object->owner == tid) {
-        if (object->lockCount == 0) {
-            object->owner = 0;
-        } else {
-            object->lockCount--;
-        }
-    }
-}
-
-
-// =============================================================================
-// Hash Table functions
-// =============================================================================
-
-/****************************************************************************/
-
-#define HASHTABLE_SIZE      256
-
-typedef struct HashEntry HashEntry;
-struct HashEntry {
-    size_t slot;
-    HashEntry* prev;
-    HashEntry* next;
-    void* data;
-};
-
-typedef struct HashTable HashTable;
-struct HashTable {
-    HashEntry* slots[HASHTABLE_SIZE];
-};
-
-static HashTable g_mutex_map;
-static HashTable g_thread_map;
-
-/****************************************************************************/
-
-static uint32_t get_hashcode(void const * key, size_t keySize)
-{
-    uint32_t h = keySize;
-    char const* data = (char const*)key;
-    size_t i;
-    for (i = 0; i < keySize; i++) {
-        h = h * 31 + *data;
-        data++;
-    }
-    return (uint32_t)h;
-}
-
-static size_t get_index(uint32_t h)
-{
-    // We apply this secondary hashing discovered by Doug Lea to defend
-    // against bad hashes.
-    h += ~(h << 9);
-    h ^= (((unsigned int) h) >> 14);
-    h += (h << 4);
-    h ^= (((unsigned int) h) >> 10);
-    return (size_t)h & (HASHTABLE_SIZE - 1);
-}
-
-/****************************************************************************/
-
-static void hashmap_init(HashTable* table) {
-    memset(table, 0, sizeof(HashTable));
-}
-
-static void hashmap_removeEntry(HashTable* table, HashEntry* entry)
-{
-    HashEntry* prev = entry->prev;
-    HashEntry* next = entry->next;
-    if (prev != NULL) entry->prev->next = next;
-    if (next != NULL) entry->next->prev = prev;
-    if (prev == NULL) {
-        // we are the head of the list. set the head to be next
-        table->slots[entry->slot] = entry->next;
-    }
-}
-
-static HashEntry* hashmap_lookup(HashTable* table,
-        void const* key, size_t ksize,
-        int (*equals)(void const* data, void const* key))
-{
-    const uint32_t hash = get_hashcode(key, ksize);
-    const size_t slot = get_index(hash);
-
-    HashEntry* entry = table->slots[slot];
-    while (entry) {
-        if (equals(entry->data, key)) {
-            break;
-        }
-        entry = entry->next;
-    }
-
-    if (entry == NULL) {
-        // create a new entry
-        entry = DbgAllocLocked<HashEntry>();
-        entry->data = NULL;
-        entry->slot = slot;
-        entry->prev = NULL;
-        entry->next = table->slots[slot];
-        if (entry->next != NULL) {
-            entry->next->prev = entry;
-        }
-        table->slots[slot] = entry;
-    }
-    return entry;
-}
-
-/****************************************************************************/
-
-static int MutexInfo_equals(void const* data, void const* key) {
-    return ((MutexInfo const *)data)->mutex == *(pthread_mutex_t **)key;
-}
-
-static MutexInfo* get_mutex_info(pthread_mutex_t *mutex)
-{
-    pthread_mutex_lock_unchecked(&g_dbg_lock);
-
-    HashEntry* entry = hashmap_lookup(&g_mutex_map,
-            &mutex, sizeof(mutex),
-            &MutexInfo_equals);
-    if (entry->data == NULL) {
-        MutexInfo* mutex_info = DbgAllocLocked<MutexInfo>();
-        entry->data = mutex_info;
-        initMutexInfo(mutex_info, mutex);
-    }
-
-    pthread_mutex_unlock_unchecked(&g_dbg_lock);
-
-    return (MutexInfo *)entry->data;
-}
-
-/****************************************************************************/
-
-static int ThreadInfo_equals(void const* data, void const* key) {
-    return ((ThreadInfo const *)data)->pid == *(pid_t *)key;
-}
-
-static ThreadInfo* get_thread_info(pid_t pid)
-{
-    pthread_mutex_lock_unchecked(&g_dbg_lock);
-
-    HashEntry* entry = hashmap_lookup(&g_thread_map,
-            &pid, sizeof(pid),
-            &ThreadInfo_equals);
-    if (entry->data == NULL) {
-        ThreadInfo* thread_info = DbgAllocLocked<ThreadInfo>();
-        entry->data = thread_info;
-        initThreadInfo(thread_info, pid);
-    }
-
-    pthread_mutex_unlock_unchecked(&g_dbg_lock);
-
-    return (ThreadInfo *)entry->data;
-}
-
-static void push_most_recently_locked(MutexInfo* mrl) {
-    ThreadInfo* tinfo = get_thread_info(gettid());
-    mrl->next = NULL;
-    mrl->prev = tinfo->mrl;
-    tinfo->mrl = mrl;
-}
-
-static void remove_most_recently_locked(MutexInfo* mrl) {
-    ThreadInfo* tinfo = get_thread_info(gettid());
-    if (mrl->next) {
-        (mrl->next)->prev = mrl->prev;
-    }
-    if (mrl->prev) {
-        (mrl->prev)->next = mrl->next;
-    }
-    if (tinfo->mrl == mrl) {
-        tinfo->mrl = mrl->next;
-    }
-}
-
-static MutexInfo* get_most_recently_locked() {
-    ThreadInfo* tinfo = get_thread_info(gettid());
-    return tinfo->mrl;
-}
-
-/****************************************************************************/
-
-/*
- * See if we were allowed to grab the lock at this time.  We do it
- * *after* acquiring the lock, rather than before, so that we can
- * freely update the MutexInfo struct.  This seems counter-intuitive,
- * but our goal is deadlock *prediction* not deadlock *prevention*.
- * (If we actually deadlock, the situation is easy to diagnose from
- * a thread dump, so there's no point making a special effort to do
- * the checks before the lock is held.)
- */
-
-extern "C" __LIBC_HIDDEN__ void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex)
-{
-    if (g_pthread_debug_level == 0) return;
-    // prediction disabled for this thread
-    if (g_pthread_debug_disabled_thread == gettid())
-        return;
-    MutexInfo* object = get_mutex_info(mutex);
-    MutexInfo* mrl = get_most_recently_locked();
-    mutex_lock_checked(mrl, object);
-    push_most_recently_locked(object);
-}
-
-/*
- * pthread_debug_mutex_unlock_check() must be called with the mutex
- * still held (ie: before calling the real unlock)
- */
-
-extern "C" __LIBC_HIDDEN__ void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex)
-{
-    if (g_pthread_debug_level == 0) return;
-    // prediction disabled for this thread
-    if (g_pthread_debug_disabled_thread == gettid())
-        return;
-    MutexInfo* object = get_mutex_info(mutex);
-    remove_most_recently_locked(object);
-    mutex_unlock_checked(object);
-}
-
-#endif // PTHREAD_DEBUG_ENABLED
-
-// Called from libc_init_dynamic() just after system properties have been initialized.
-extern "C" __LIBC_HIDDEN__ void pthread_debug_init() {
-#if PTHREAD_DEBUG_ENABLED
-    char env[PROP_VALUE_MAX];
-    if (__system_property_get("debug.libc.pthread", env)) {
-        int level = atoi(env);
-        if (level) {
-            LOGI("pthread deadlock detection level %d enabled for pid %d (%s)",
-                    level, getpid(), __progname);
-            hashmap_init(&g_mutex_map);
-            g_pthread_debug_level = level;
-        }
-    }
-#endif
-}
index c4cd9e0..9fd5d32 100644 (file)
@@ -445,9 +445,7 @@ _recursive_increment(pthread_mutex_t* mutex, int mvalue, int mtype)
     }
 }
 
-__LIBC_HIDDEN__
-int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
-{
+int pthread_mutex_lock(pthread_mutex_t* mutex) {
     int mvalue, mtype, tid, shared;
 
     mvalue = mutex->value;
@@ -523,20 +521,7 @@ int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
     /* NOTREACHED */
 }
 
-int pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-    int err = pthread_mutex_lock_impl(mutex);
-    if (PTHREAD_DEBUG_ENABLED) {
-        if (!err) {
-            pthread_debug_mutex_lock_check(mutex);
-        }
-    }
-    return err;
-}
-
-__LIBC_HIDDEN__
-int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
-{
+int pthread_mutex_unlock(pthread_mutex_t* mutex) {
     int mvalue, mtype, tid, shared;
 
     mvalue = mutex->value;
@@ -588,17 +573,7 @@ int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
     return 0;
 }
 
-int pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-    if (PTHREAD_DEBUG_ENABLED) {
-        pthread_debug_mutex_unlock_check(mutex);
-    }
-    return pthread_mutex_unlock_impl(mutex);
-}
-
-__LIBC_HIDDEN__
-int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
-{
+int pthread_mutex_trylock(pthread_mutex_t* mutex) {
     int mvalue, mtype, tid, shared;
 
     mvalue = mutex->value;
@@ -638,17 +613,6 @@ int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
     return EBUSY;
 }
 
-int pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
-    int err = pthread_mutex_trylock_impl(mutex);
-    if (PTHREAD_DEBUG_ENABLED) {
-        if (!err) {
-            pthread_debug_mutex_lock_check(mutex);
-        }
-    }
-    return err;
-}
-
 static int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout, clockid_t clock) {
   timespec ts;
 
@@ -761,16 +725,11 @@ extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex, unsigned ms
     abs_timeout.tv_nsec -= 1000000000;
   }
 
-  int err = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC);
-  if (err == ETIMEDOUT) {
-    err = EBUSY;
-  }
-  if (PTHREAD_DEBUG_ENABLED) {
-    if (!err) {
-      pthread_debug_mutex_lock_check(mutex);
-    }
+  int error = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC);
+  if (error == ETIMEDOUT) {
+    error = EBUSY;
   }
-  return err;
+  return error;
 }
 #endif
 
@@ -778,16 +737,12 @@ int pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout)
   return __pthread_mutex_timedlock(mutex, abs_timeout, CLOCK_REALTIME);
 }
 
-int pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-    int ret;
-
-    /* use trylock to ensure that the mutex value is
-     * valid and is not already locked. */
-    ret = pthread_mutex_trylock_impl(mutex);
-    if (ret != 0)
-        return ret;
-
-    mutex->value = 0xdead10cc;
-    return 0;
+int pthread_mutex_destroy(pthread_mutex_t* mutex) {
+  // Use trylock to ensure that the mutex is valid and not already locked.
+  int error = pthread_mutex_trylock(mutex);
+  if (error != 0) {
+    return error;
+  }
+  mutex->value = 0xdead10cc;
+  return 0;
 }