diff options
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/rust_kernel.cpp | 6 | ||||
| -rw-r--r-- | src/rt/rust_kernel.h | 2 | ||||
| -rw-r--r-- | src/rt/rust_scheduler.cpp | 21 | ||||
| -rw-r--r-- | src/rt/rust_scheduler.h | 5 |
4 files changed, 25 insertions, 9 deletions
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index a52c2d48eed..aaf19f240c8 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -189,11 +189,9 @@ rust_kernel::release_task_id(rust_task_id id) { task_table.remove(id); } -void rust_kernel::wakeup_schedulers() { +void rust_kernel::exit_schedulers() { for(size_t i = 0; i < num_threads; ++i) { - rust_scheduler *sched = threads[i]; - scoped_lock with(sched->lock); - sched->lock.signal_all(); + threads[i]->exit(); } } diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index 3d64e57d9f9..b82119cc5ad 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -47,7 +47,7 @@ public: bool is_deadlocked(); void signal_kernel_lock(); - void wakeup_schedulers(); + void exit_schedulers(); void log_all_scheduler_state(); void log(uint32_t level, char const *fmt, ...); diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index 5a6cbd241ae..9005680dcc6 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -32,7 +32,8 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel, kernel(kernel), id(id), min_stack_size(kernel->env->min_stack_size), - env(kernel->env) + env(kernel->env), + should_exit(false) { LOGPTR(this, "new dom", (uintptr_t)this); isaac_init(this, &rctx); @@ -160,8 +161,12 @@ rust_scheduler::reap_dead_tasks(int id) { rust_task *task = dead_tasks_copy[i]; if (task) { task->deref(); - sync::decrement(kernel->live_tasks); - kernel->wakeup_schedulers(); + int live_tasks = sync::decrement(kernel->live_tasks); + if (live_tasks == 0) { + // There are no more tasks and there never will be. + // Tell all the schedulers to exit. + kernel->exit_schedulers(); + } } } srv->free(dead_tasks_copy); @@ -236,7 +241,7 @@ rust_scheduler::start_main_loop() { DLOG(this, dom, "started domain loop %d", id); - while (kernel->live_tasks > 0) { + while (!should_exit) { A(this, kernel->is_deadlocked() == false, "deadlock"); DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d", @@ -375,6 +380,14 @@ rust_scheduler::get_task() { } #endif +void +rust_scheduler::exit() { + A(this, !lock.lock_held_by_current_thread(), "Shouldn't have lock"); + scoped_lock with(lock); + should_exit = true; + lock.signal_all(); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rust_scheduler.h b/src/rt/rust_scheduler.h index b5bd92efaaa..ee69af5479e 100644 --- a/src/rt/rust_scheduler.h +++ b/src/rt/rust_scheduler.h @@ -91,6 +91,8 @@ struct rust_scheduler : public kernel_owned<rust_scheduler>, rust_env *env; context c_context; + bool should_exit; + // Only a pointer to 'name' is kept, so it must live as long as this // domain. rust_scheduler(rust_kernel *kernel, rust_srv *srv, int id); @@ -127,6 +129,9 @@ struct rust_scheduler : public kernel_owned<rust_scheduler>, void place_task_in_tls(rust_task *task); static rust_task *get_task(); + + // Tells the scheduler to exit it's scheduling loop and thread + void exit(); }; inline rust_log & |
