Fixed deadlock in the scheduler caused by condition variables.
This commit is contained in:
parent
4641fcef61
commit
5917ca3519
4 changed files with 13 additions and 11 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue