diff --git a/libc/Android.mk b/libc/Android.mk index ed7d055e7..c0da9b2a1 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -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 \ diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 3d98861df..659cf398a 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -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 index be89b4612..000000000 --- a/libc/bionic/pthread_debug.cpp +++ /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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#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 -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(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(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(count); - memcpy(stack->addrs, addrs, count * sizeof(uintptr_t)); -} - -/****************************************************************************/ - -static int historyListHas( - const MutexInfoList* list, MutexInfo const * obj) { - int i; - for (i=0; icount; 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 ; iparents.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(); - 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(); - 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(); - 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 -} diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp index c4cd9e0e4..9fd5d32dd 100644 --- a/libc/bionic/pthread_mutex.cpp +++ b/libc/bionic/pthread_mutex.cpp @@ -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; + int error = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC); + if (error == ETIMEDOUT) { + error = EBUSY; } - if (PTHREAD_DEBUG_ENABLED) { - if (!err) { - pthread_debug_mutex_lock_check(mutex); - } - } - 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; }