about summary refs log tree commit diff
path: root/src/rt/rust_port.cpp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-02-14 22:23:16 -0800
committerBrian Anderson <banderson@mozilla.com>2012-02-16 11:12:22 -0800
commitb2cfb7ef8262ebe47514f016f59054ebcfe15d61 (patch)
tree871bc0980b26b11d700761cad9a8ac245f5fcedc /src/rt/rust_port.cpp
parente62ddf48988087d19934e1fdc6abb6de5f7a6a02 (diff)
downloadrust-b2cfb7ef8262ebe47514f016f59054ebcfe15d61.tar.gz
rust-b2cfb7ef8262ebe47514f016f59054ebcfe15d61.zip
rt: Add rust_port_select function
Diffstat (limited to 'src/rt/rust_port.cpp')
-rw-r--r--src/rt/rust_port.cpp34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/rt/rust_port.cpp b/src/rt/rust_port.cpp
index a917c12e151..5f46b9c4ca0 100644
--- a/src/rt/rust_port.cpp
+++ b/src/rt/rust_port.cpp
@@ -30,18 +30,34 @@ void rust_port::detach() {
 
 void rust_port::send(void *sptr) {
     I(task->thread, !lock.lock_held_by_current_thread());
-    scoped_lock with(lock);
+    bool did_rendezvous = false;
+    {
+        scoped_lock with(lock);
+
+        buffer.enqueue(sptr);
 
-    buffer.enqueue(sptr);
+        A(kernel, !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;
+        }
+    }
 
-    A(kernel, !buffer.is_empty(),
-      "rust_chan::transmit with nothing to send.");
+    if (!did_rendezvous) {
+        // If the task wasn't waiting specifically on this port,
+        // it may be waiting on a group of ports
 
-    if (task->blocked_on(this)) {
-        KLOG(kernel, comm, "dequeued in rendezvous_ptr");
-        buffer.dequeue(task->rendezvous_ptr);
-        task->rendezvous_ptr = 0;
-        task->wakeup(this);
+        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);
+        }
     }
 }