Fixed a few concurrency bugs. Still not perfect, but overall it seems much more reliable.

This commit is contained in:
Eric Holk 2011-06-21 18:08:34 -07:00 committed by Graydon Hoare
parent 4d99bf9af2
commit 6367bcf427
5 changed files with 20 additions and 11 deletions

View File

@ -166,9 +166,11 @@ rust_dom::number_of_live_tasks() {
*/
void
rust_dom::reap_dead_tasks() {
I(this, scheduler_lock.lock_held_by_current_thread());
for (size_t i = 0; i < dead_tasks.length(); ) {
rust_task *task = dead_tasks[i];
if (task->ref_count == 0) {
// Make sure this task isn't still running somewhere else...
if (task->ref_count == 0 && task->can_schedule()) {
I(this, task->tasks_waiting_to_join.is_empty());
dead_tasks.remove(task);
DLOG(this, task,
@ -315,13 +317,14 @@ rust_dom::start_main_loop(int id) {
DLOG(this, task,
"Running task %p on worker %d",
scheduled_task, id);
I(this, !scheduled_task->active);
scheduled_task->active = true;
activate(scheduled_task);
scheduled_task->active = false;
DLOG(this, task,
"returned from task %s @0x%" PRIxPTR
" in state '%s', sp=0x%, worker id=%d" PRIxPTR,
" in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
scheduled_task->name,
(uintptr_t)scheduled_task,
scheduled_task->state->name,
@ -349,7 +352,9 @@ rust_dom::start_main_loop(int id) {
"scheduler yielding ...",
dead_tasks.length());
log_state();
scheduler_lock.unlock();
sync::yield();
scheduler_lock.lock();
} else {
drain_incoming_message_queue(true);
}

View File

@ -54,7 +54,8 @@ rust_srv::fatal(const char *expression,
"fatal, '%s' failed, %s:%d %s",
expression, file, (int)line, buf);
log(msg);
exit(1);
abort();
//exit(1);
}
void

View File

@ -53,7 +53,7 @@ rust_task : public maybe_proxy<rust_task>,
// This flag indicates that a worker is either currently running the task
// or is about to run this task.
bool active;
volatile bool active;
// Only a pointer to 'name' is kept, so it must live as long as this task.
rust_task(rust_dom *dom,

View File

@ -223,9 +223,12 @@ upcall_recv(rust_task *task, uintptr_t *dptr, rust_port *port) {
// on the port. Remember the rendezvous location so that any sender
// task can write to it before waking up this task.
LOG(task, comm, "<=== waiting for rendezvous data ===");
task->rendezvous_ptr = dptr;
task->block(port, "waiting for rendezvous data");
{
scoped_lock sync(port->lock);
LOG(task, comm, "<=== waiting for rendezvous data ===");
task->rendezvous_ptr = dptr;
task->block(port, "waiting for rendezvous data");
}
task->yield(3);
}

View File

@ -34,8 +34,8 @@ fn fib(int n) -> int {
}
fn main() {
assert (fib(8) == 21);
assert (fib(15) == 610);
log fib(8);
log fib(15);
assert (fib(8) == 21);
assert (fib(15) == 610);
log fib(8);
log fib(15);
}