about summary refs log tree commit diff
path: root/src/rt/rust_port.cpp
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2012-07-11 20:00:58 -0400
committerBen Blum <bblum@andrew.cmu.edu>2012-07-12 18:08:36 -0400
commit343e9de8ef4ee9727f027c896ce99f09611b9603 (patch)
tree203e9084453699cb8b7175a75438cfd5c9ed8d00 /src/rt/rust_port.cpp
parentb897696a3abde84e57cda3f6e4267be3b647835c (diff)
downloadrust-343e9de8ef4ee9727f027c896ce99f09611b9603.tar.gz
rust-343e9de8ef4ee9727f027c896ce99f09611b9603.zip
Proper locking with blocked_on()/wakeup() in rust_port. Closes #2787. Closes #1923.
Diffstat (limited to 'src/rt/rust_port.cpp')
-rw-r--r--src/rt/rust_port.cpp28
1 files changed, 15 insertions, 13 deletions
diff --git a/src/rt/rust_port.cpp b/src/rt/rust_port.cpp
index f1a40508aca..919dadd4044 100644
--- a/src/rt/rust_port.cpp
+++ b/src/rt/rust_port.cpp
@@ -26,9 +26,11 @@ void rust_port::deref() {
     scoped_lock with(ref_lock);
     ref_count--;
     if (!ref_count) {
+        // The port owner is waiting for the port to be detached (if it
+        // hasn't already been killed)
+        scoped_lock with(task->lifecycle_lock);
         if (task->blocked_on(&detach_cond)) {
-            // The port owner is waiting for the port to be detached
-            task->wakeup(&detach_cond);
+            task->wakeup_inner(&detach_cond);
         }
     }
 }
@@ -64,12 +66,15 @@ void rust_port::send(void *sptr) {
         assert(!buffer.is_empty() &&
                "rust_chan::transmit with nothing to send.");
 
-        if (task->blocked_on(this)) {
-            KLOG(kernel, comm, "dequeued in rendezvous_ptr");
-            buffer.dequeue(task->rendezvous_ptr);
-            task->rendezvous_ptr = 0;
-            task->wakeup(this);
-            did_rendezvous = true;
+        {
+            scoped_lock with(task->lifecycle_lock);
+            if (task->blocked_on(this)) {
+                KLOG(kernel, comm, "dequeued in rendezvous_ptr");
+                buffer.dequeue(task->rendezvous_ptr);
+                task->rendezvous_ptr = 0;
+                task->wakeup_inner(this);
+                did_rendezvous = true;
+            }
         }
     }
 
@@ -78,11 +83,8 @@ void rust_port::send(void *sptr) {
         // it may be waiting on a group of ports
 
         rust_port_selector *port_selector = task->get_port_selector();
-        // This check is not definitive. The port selector will take a lock
-        // and check again whether the task is still blocked.
-        if (task->blocked_on(port_selector)) {
-            port_selector->msg_sent_on(this);
-        }
+        // The port selector will check if the task is blocked, not us.
+        port_selector->msg_sent_on(this);
     }
 }