about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorMichael Bebenita <mbebenita@mozilla.com>2010-09-15 11:56:45 -0700
committerMichael Bebenita <mbebenita@mozilla.com>2010-09-16 00:51:03 -0700
commit1bd331b7aaa24245f86868305ab64600683a41e1 (patch)
tree1b088c433bc95ee416eefe502b0dca866b5dead6 /src/rt
parent91b4a0c9f8ba7be56fc098ffc6182a888e3970bf (diff)
Fixed deadlock caused by the message pump not being notified of new message sends.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_dom.cpp2
-rw-r--r--src/rt/rust_kernel.cpp21
-rw-r--r--src/rt/rust_kernel.h11
-rw-r--r--src/rt/rust_message.h5
-rw-r--r--src/rt/sync/lock_free_queue.h2
5 files changed, 36 insertions, 5 deletions
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index d3b5d2cee89..4527955176c 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -314,7 +314,7 @@ rust_dom::start_main_loop() {
             }
             log(rust_log::TASK,
                 "all tasks are blocked, scheduler yielding ...");
-            sync::yield();
+            sync::sleep(100);
             log(rust_log::TASK,
                 "scheduler resuming ...");
             continue;
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index ef4220f9129..0dc1369dca6 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -164,9 +164,7 @@ void
 rust_kernel::terminate_kernel_loop() {
     log(rust_log::KERN, "terminating kernel loop");
     _interrupt_kernel_loop = true;
-    _kernel_lock.lock();
-    _kernel_lock.signal_all();
-    _kernel_lock.unlock();
+    signal_kernel_lock();
     join();
 }
 
@@ -217,6 +215,23 @@ rust_kernel::free_handles(hash_map<T*, rust_handle<T>* > &map) {
     }
 }
 
+void
+rust_kernel::notify_message_enqueued(rust_message_queue *queue,
+                                     rust_message *message) {
+    // The message pump needs to handle this message if the queue is not
+    // associated with a domain, therefore signal the message pump.
+    if (queue->is_associated() == false) {
+        signal_kernel_lock();
+    }
+}
+
+void
+rust_kernel::signal_kernel_lock() {
+    _kernel_lock.lock();
+    _kernel_lock.signal_all();
+    _kernel_lock.unlock();
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h
index f85d55ac201..3ad7b396575 100644
--- a/src/rt/rust_kernel.h
+++ b/src/rt/rust_kernel.h
@@ -9,6 +9,7 @@
  */
 
 class rust_kernel;
+class rust_message;
 
 template <typename T> class
 rust_handle :
@@ -90,6 +91,16 @@ public:
 
     bool is_deadlocked();
 
+    void signal_kernel_lock();
+
+    /**
+     * Notifies the kernel whenever a message has been enqueued . This gives
+     * the kernel the opportunity to wake up the message pump thread if the
+     * message queue is not associated.
+     */
+    void
+    notify_message_enqueued(rust_message_queue *queue, rust_message *message);
+
     /**
      * Blocks until all domains have terminated.
      */
diff --git a/src/rt/rust_message.h b/src/rt/rust_message.h
index c342e3e411a..e9ce94bfa9e 100644
--- a/src/rt/rust_message.h
+++ b/src/rt/rust_message.h
@@ -114,6 +114,11 @@ public:
     bool is_associated() {
         return this->dom_handle != NULL;
     }
+
+    void enqueue(rust_message* message) {
+        lock_free_queue<rust_message*>::enqueue(message);
+        kernel->notify_message_enqueued(this, message);
+    }
 };
 
 //
diff --git a/src/rt/sync/lock_free_queue.h b/src/rt/sync/lock_free_queue.h
index ac0c5b046a0..1c760bff9d4 100644
--- a/src/rt/sync/lock_free_queue.h
+++ b/src/rt/sync/lock_free_queue.h
@@ -120,7 +120,7 @@ public:
         return head.node == tail.node;
     }
 
-    void enqueue(T value) {
+    virtual void enqueue(T value) {
 
         // Create a new node to be inserted in the linked list, and set the
         // next node to NULL.