Fixed deadlock in the scheduler caused by condition variables.

This commit is contained in:
Michael Bebenita 2010-08-09 08:06:08 -07:00
parent 4641fcef61
commit 5917ca3519
4 changed files with 13 additions and 11 deletions

View file

@ -262,8 +262,6 @@ void rust_dom::send_message(rust_message *message) {
this); this);
A(this, message->dom == this, "Message owned by non-local domain."); A(this, message->dom == this, "Message owned by non-local domain.");
_incoming_message_queue.enqueue(message); _incoming_message_queue.enqueue(message);
_incoming_message_pending.signal();
_progress.signal();
} }
/** /**
@ -398,9 +396,11 @@ rust_dom::start_main_loop()
"all tasks are blocked, waiting for progress ..."); "all tasks are blocked, waiting for progress ...");
if (_log.is_tracing(rust_log::TASK)) if (_log.is_tracing(rust_log::TASK))
log_state(); log_state();
_progress.wait();
log(rust_log::TASK, log(rust_log::TASK,
"progress made, resuming ..."); "all tasks are blocked, scheduler yielding ...");
sync::yield();
log(rust_log::TASK,
"scheduler resuming ...");
continue; continue;
} }
@ -450,7 +450,14 @@ rust_dom::start_main_loop()
} }
if (_incoming_message_queue.is_empty()) { if (_incoming_message_queue.is_empty()) {
_incoming_message_pending.wait(); log(rust_log::DOM,
"waiting for %d dead tasks to become dereferenced, "
"scheduler yielding ...",
dead_tasks.length());
if (_log.is_tracing(rust_log::TASK)) {
log_state();
}
sync::yield();
} else { } else {
drain_incoming_message_queue(); drain_incoming_message_queue();
} }

View file

@ -34,13 +34,10 @@ struct rust_dom
rust_task *curr_task; rust_task *curr_task;
int rval; int rval;
condition_variable _progress;
hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies; hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies;
hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies; hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies;
// Incoming messages from other domains. // Incoming messages from other domains.
condition_variable _incoming_message_pending;
lock_free_queue _incoming_message_queue; lock_free_queue _incoming_message_queue;
#ifndef __WIN32__ #ifndef __WIN32__

View file

@ -38,6 +38,7 @@ extern "C" {
#error "Platform not supported." #error "Platform not supported."
#endif #endif
#include "sync/sync.h"
#include "sync/condition_variable.h" #include "sync/condition_variable.h"
#ifndef __i386__ #ifndef __i386__

View file

@ -556,9 +556,6 @@ rust_task::wakeup(rust_cond *from)
A(dom, cond == from, "Cannot wake up blocked task on wrong condition."); A(dom, cond == from, "Cannot wake up blocked task on wrong condition.");
transition(&dom->blocked_tasks, &dom->running_tasks); transition(&dom->blocked_tasks, &dom->running_tasks);
// TODO: Signaling every time the task is awaken is kind of silly,
// do this a nicer way.
dom->_progress.signal();
I(dom, cond == from); I(dom, cond == from);
cond = NULL; cond = NULL;
} }