diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-11-27 17:22:19 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2009-11-27 17:36:51 -0500 |
commit | 0cd3bb9f3a53cce9a64ce1536d6e171848e8da59 (patch) | |
tree | 6597c900dc2b4cb3ee0018cde1b84fe2499f322c /evthread.c | |
parent | 2df1f82bfa1b432a277b0e1f8fc65aed7898f5e5 (diff) | |
download | libevent-0cd3bb9f3a53cce9a64ce1536d6e171848e8da59.tar.gz |
Improved optional lock debugging.
There were a couple of places in the code where we manually kept lock
counts to make sure we never accessed resources without holding a
lock, and that we never released a lock we didn't have. The
lock-debugging code already puts counts on _every_ lock when lock
debugging is enabled, so there is no need to keep these counts around
otherwise. This patch rewrites the ASSERT_FOO_LOCKED macros to all
use a common EVLOCK_ASSERT_LOCKED().
We also teach the lock debugging code to keep track of who exactly
holds each lock, so that EVLOCK_ASSERT_LOCKED() means "locked by this
thread."
Diffstat (limited to 'evthread.c')
-rw-r--r-- | evthread.c | 30 |
1 files changed, 30 insertions, 0 deletions
@@ -36,6 +36,7 @@ #include "log-internal.h" #include "mm-internal.h" #include "util-internal.h" +#include "evthread-internal.h" /* globals */ int _evthread_lock_debugging_enabled = 0; @@ -150,6 +151,7 @@ evthread_set_lock_create_callbacks(void *(*alloc_fn)(void), struct debug_lock { unsigned locktype; + unsigned long held_by; /* XXXX if we ever use read-write locks, we will need a separate * lock to protect count. */ int count; @@ -171,6 +173,7 @@ debug_lock_alloc(unsigned locktype) } result->locktype = locktype; result->count = 0; + result->held_by = 0; return result; } @@ -204,6 +207,13 @@ debug_lock_lock(unsigned mode, void *lock_) ++lock->count; if (!(lock->locktype & EVTHREAD_LOCKTYPE_RECURSIVE)) EVUTIL_ASSERT(lock->count == 1); + if (_evthread_id_fn) { + unsigned long me; + me = _evthread_id_fn(); + if (lock->count > 1) + EVUTIL_ASSERT(lock->held_by == me); + lock->held_by = me; + } } return res; } @@ -217,6 +227,12 @@ debug_lock_unlock(unsigned mode, void *lock_) EVUTIL_ASSERT(mode & (EVTHREAD_READ|EVTHREAD_WRITE)); else EVUTIL_ASSERT((mode & (EVTHREAD_READ|EVTHREAD_WRITE)) == 0); + if (_evthread_id_fn) { + unsigned long me = _evthread_id_fn(); + EVUTIL_ASSERT(lock->held_by == me); + if (lock->count == 1) + lock->held_by = 0; + } --lock->count; EVUTIL_ASSERT(lock->count >= 0); if (_original_lock_fns.unlock) @@ -244,4 +260,18 @@ evthread_enable_lock_debuging(void) _evthread_lock_debugging_enabled = 1; } +int +_evthread_is_debug_lock_held(void *lock_) +{ + struct debug_lock *lock = lock_; + if (! lock->count) + return 0; + if (_evthread_id_fn) { + unsigned long me = _evthread_id_fn(); + if (lock->held_by != me) + return 0; + } + return 1; +} + #endif |