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: \ private: \
intptr_t ref_count; \ intptr_t ref_count; \
public: \ 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; } } void deref() { if(0 == sync::decrement(ref_count)) { delete this; } }
template <typename T> struct rc_base { 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; rust_task *task = NULL;
// get leaves task unchanged if not found. // get leaves task unchanged if not found.
task_table.get(id, &task); 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; 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); rust_port_id register_port(rust_port *port);
void release_port(rust_port_id id); void release_port(rust_port_id id);
rust_port *get_port_by_id(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; }
}; };
// //