diff options
| author | Brian Anderson <banderson@mozilla.com> | 2012-03-06 15:31:21 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-03-06 17:14:40 -0800 |
| commit | dc0b9f44e2731dec413d69997ad093962deb665e (patch) | |
| tree | d8d676fe83f2eaf241bb9ca291d388b10fb5c019 /src/rt/rust_port.cpp | |
| parent | e9571850daded0f46ae3b9b8e0834b6be2e5219b (diff) | |
| download | rust-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.cpp | 30 |
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) { |
