From 343e9de8ef4ee9727f027c896ce99f09611b9603 Mon Sep 17 00:00:00 2001 From: Ben Blum Date: Wed, 11 Jul 2012 20:00:58 -0400 Subject: Proper locking with blocked_on()/wakeup() in rust_port. Closes #2787. Closes #1923. --- src/rt/rust_port.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src/rt/rust_port.cpp') 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); } } -- cgit 1.4.1-3-g733a5