summaryrefslogtreecommitdiff
path: root/evthread.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-11-27 17:22:19 -0500
committerNick Mathewson <nickm@torproject.org>2009-11-27 17:36:51 -0500
commit0cd3bb9f3a53cce9a64ce1536d6e171848e8da59 (patch)
tree6597c900dc2b4cb3ee0018cde1b84fe2499f322c /evthread.c
parent2df1f82bfa1b432a277b0e1f8fc65aed7898f5e5 (diff)
downloadlibevent-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.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/evthread.c b/evthread.c
index 8222ad27..66d7a3dd 100644
--- a/evthread.c
+++ b/evthread.c
@@ -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