summary refs log tree commit diff
path: root/src/rt/sync
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-03-30 18:37:30 -0700
committerBrian Anderson <banderson@mozilla.com>2012-03-31 19:51:29 -0700
commitc8dc6fcb4cd29e5fb6c509149871b869b951295d (patch)
tree3556f9f57afa10a2f14c4ff44042b6db174ded2a /src/rt/sync
parent609144f7a6adba552602feb7e50e7c4d6a815fae (diff)
downloadrust-c8dc6fcb4cd29e5fb6c509149871b869b951295d.tar.gz
rust-c8dc6fcb4cd29e5fb6c509149871b869b951295d.zip
Revert "rt: Remove lock_held_by_current_thread"
Adds back the ability to make assertions about locks, but only under the
--enable-debug configuration

This reverts commit b247de64583e2ab527088813ba9192824554e801.

Conflicts:

	src/rt/rust_sched_loop.cpp
Diffstat (limited to 'src/rt/sync')
-rw-r--r--src/rt/sync/lock_and_signal.cpp59
-rw-r--r--src/rt/sync/lock_and_signal.h19
2 files changed, 78 insertions, 0 deletions
diff --git a/src/rt/sync/lock_and_signal.cpp b/src/rt/sync/lock_and_signal.cpp
index 35576f7fd97..1d0842e6c60 100644
--- a/src/rt/sync/lock_and_signal.cpp
+++ b/src/rt/sync/lock_and_signal.cpp
@@ -10,8 +10,15 @@
 
 #include "lock_and_signal.h"
 
+// FIXME: This is not a portable way of specifying an invalid pthread_t
+#define INVALID_THREAD 0
+
+
 #if defined(__WIN32__)
 lock_and_signal::lock_and_signal()
+#if defined(DEBUG_LOCKS)
+    : _holding_thread(INVALID_THREAD)
+#endif
 {
     _event = CreateEvent(NULL, FALSE, FALSE, NULL);
 
@@ -30,6 +37,9 @@ lock_and_signal::lock_and_signal()
 
 #else
 lock_and_signal::lock_and_signal()
+#if defined(DEBUG_LOCKS)
+    : _holding_thread(INVALID_THREAD)
+#endif
 {
     CHECKED(pthread_cond_init(&_cond, NULL));
     CHECKED(pthread_mutex_init(&_mutex, NULL));
@@ -47,14 +57,25 @@ lock_and_signal::~lock_and_signal() {
 }
 
 void lock_and_signal::lock() {
+    must_not_have_lock();
 #if defined(__WIN32__)
     EnterCriticalSection(&_cs);
+#if defined(DEBUG_LOCKS)
+    _holding_thread = GetCurrentThreadId();
+#endif
 #else
     CHECKED(pthread_mutex_lock(&_mutex));
+#if defined(DEBUG_LOCKS)
+    _holding_thread = pthread_self();
+#endif
 #endif
 }
 
 void lock_and_signal::unlock() {
+    must_have_lock();
+#if defined(DEBUG_LOCKS)
+    _holding_thread = INVALID_THREAD;
+#endif
 #if defined(__WIN32__)
     LeaveCriticalSection(&_cs);
 #else
@@ -66,12 +87,24 @@ void lock_and_signal::unlock() {
  * Wait indefinitely until condition is signaled.
  */
 void lock_and_signal::wait() {
+    must_have_lock();
+#if defined(DEBUG_LOCKS)
+    _holding_thread = INVALID_THREAD;
+#endif
 #if defined(__WIN32__)
     LeaveCriticalSection(&_cs);
     WaitForSingleObject(_event, INFINITE);
     EnterCriticalSection(&_cs);
+    must_not_be_locked();
+#if defined(DEBUG_LOCKS)
+    _holding_thread = GetCurrentThreadId();
+#endif
 #else
     CHECKED(pthread_cond_wait(&_cond, &_mutex));
+    must_not_be_locked();
+#if defined(DEBUG_LOCKS)
+    _holding_thread = pthread_self();
+#endif
 #endif
 }
 
@@ -86,6 +119,32 @@ void lock_and_signal::signal() {
 #endif
 }
 
+#if defined(DEBUG_LOCKS)
+bool lock_and_signal::lock_held_by_current_thread()
+{
+#if defined(__WIN32__)
+    return _holding_thread == GetCurrentThreadId();
+#else
+    return pthread_equal(_holding_thread, pthread_self());
+#endif
+}
+#endif
+
+#if defined(DEBUG_LOCKS)
+void lock_and_signal::must_have_lock() {
+    assert(lock_held_by_current_thread() && "must have lock");
+}
+void lock_and_signal::must_not_have_lock() {
+    assert(!lock_held_by_current_thread() && "must not have lock");
+}
+void lock_and_signal::must_not_be_locked() {
+}
+#else
+void lock_and_signal::must_have_lock() { }
+void lock_and_signal::must_not_have_lock() { }
+void lock_and_signal::must_not_be_locked() { }
+#endif
+
 scoped_lock::scoped_lock(lock_and_signal &lock)
     : lock(lock)
 {
diff --git a/src/rt/sync/lock_and_signal.h b/src/rt/sync/lock_and_signal.h
index f4ffcc30a68..fae9b1c24ea 100644
--- a/src/rt/sync/lock_and_signal.h
+++ b/src/rt/sync/lock_and_signal.h
@@ -2,15 +2,31 @@
 #ifndef LOCK_AND_SIGNAL_H
 #define LOCK_AND_SIGNAL_H
 
+#ifndef RUST_NDEBUG
+#define DEBUG_LOCKS
+#endif
+
 class lock_and_signal {
 #if defined(__WIN32__)
     HANDLE _event;
     CRITICAL_SECTION _cs;
+#if defined(DEBUG_LOCKS)
+    DWORD _holding_thread;
+#endif
 #else
     pthread_cond_t _cond;
     pthread_mutex_t _mutex;
+#if defined(DEBUG_LOCKS)
+    pthread_t _holding_thread;
+#endif
 #endif
 
+#if defined(DEBUG_LOCKS)
+    bool lock_held_by_current_thread();
+#endif
+
+    void must_not_be_locked();
+
 public:
     lock_and_signal();
     virtual ~lock_and_signal();
@@ -19,6 +35,9 @@ public:
     void unlock();
     void wait();
     void signal();
+
+    void must_have_lock();
+    void must_not_have_lock();
 };
 
 class scoped_lock {