Reducing the chances for race conditions in join.

This commit is contained in:
Eric Holk 2011-08-15 11:34:12 -07:00
parent 55c9842e7d
commit 5c6790519b
4 changed files with 20 additions and 3 deletions

View File

@ -115,7 +115,10 @@ static size_t const BUF_BYTES = 2048;
private: \
intptr_t ref_count; \
public: \
void ref() { sync::increment(ref_count); } \
void ref() { \
intptr_t old = sync::increment(ref_count); \
assert(old > 0); \
} \
void deref() { if(0 == sync::decrement(ref_count)) { delete this; } }
template <typename T> struct rc_base {

View File

@ -160,7 +160,17 @@ rust_kernel::get_task_by_id(rust_task_id id) {
rust_task *task = NULL;
// get leaves task unchanged if not found.
task_table.get(id, &task);
if(task) task->ref();
if(task) {
if(task->get_ref_count() == 0) {
// this means the destructor is running, since the destructor
// grabs the kernel lock to unregister the task. Pretend this
// doesn't actually exist.
return NULL;
}
else {
task->ref();
}
}
return task;
}

View File

@ -169,6 +169,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
rust_port_id register_port(rust_port *port);
void release_port(rust_port_id id);
rust_port *get_port_by_id(rust_port_id id);
// Use this function sparingly. Depending on the ref count is generally
// not at all safe.
intptr_t get_ref_count() const { return ref_count; }
};
//

View File

@ -27,4 +27,4 @@ fn main(args: vec[str]) {
task::_spawn(bind f(n));
i += 1u;
}
}
}