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-03-06 15:31:21 -0800
committerBrian Anderson <banderson@mozilla.com>2012-03-06 17:14:40 -0800
commitdc0b9f44e2731dec413d69997ad093962deb665e (patch)
treed8d676fe83f2eaf241bb9ca291d388b10fb5c019 /src/rt/rust_port.cpp
parente9571850daded0f46ae3b9b8e0834b6be2e5219b (diff)
downloadrust-dc0b9f44e2731dec413d69997ad093962deb665e.tar.gz
rust-dc0b9f44e2731dec413d69997ad093962deb665e.zip
rt: Change the rust_port refcounting scheme to avoid races
Hopefully...
Diffstat (limited to 'src/rt/rust_port.cpp')
-rw-r--r--src/rt/rust_port.cpp30
1 files changed, 17 insertions, 13 deletions
diff --git a/src/rt/rust_port.cpp b/src/rt/rust_port.cpp
index e3b057264a3..e37829f2df2 100644
--- a/src/rt/rust_port.cpp
+++ b/src/rt/rust_port.cpp
@@ -20,12 +20,19 @@ rust_port::~rust_port() {
     task->deref();
 }
 
-void rust_port::delete_this() {
-    scoped_lock with(detach_lock);
+void rust_port::ref() {
+    scoped_lock with(ref_lock);
+    ref_count++;
+}
 
-    if (task->blocked_on(&detach_cond)) {
-        // The port owner is waiting for the port to be detached
-        task->wakeup(&detach_cond);
+void rust_port::deref() {
+    scoped_lock with(ref_lock);
+    ref_count--;
+    if (!ref_count) {
+        if (task->blocked_on(&detach_cond)) {
+            // The port owner is waiting for the port to be detached
+            task->wakeup(&detach_cond);
+        }
     }
 }
 
@@ -34,23 +41,20 @@ void rust_port::begin_detach(uintptr_t *yield) {
 
     task->release_port(id);
 
-    deref();
+    scoped_lock with(ref_lock);
+    ref_count--;
 
-    scoped_lock with(detach_lock);
-    if (get_ref_count() != 0) {
+    if (ref_count != 0) {
         task->block(&detach_cond, "waiting for port detach");
         *yield = true;
     }
 }
 
 void rust_port::end_detach() {
-    // FIXME: For some reason we can sometimes get here without the
-    // refcount decreasing to 0. This is definitely a bug
-    while (get_ref_count() != 0) { }
-
     // Just take the lock to make sure that the thread that signaled
     // the detach_cond isn't still holding it
-    scoped_lock with(detach_lock);
+    scoped_lock with(ref_lock);
+    I(task->thread, ref_count == 0);
 }
 
 void rust_port::send(void *sptr) {