about summary refs log tree commit diff
path: root/src/rt/rust_scheduler.cpp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-02-06 23:38:22 -0800
committerBrian Anderson <banderson@mozilla.com>2012-02-08 15:42:51 -0800
commit028af5cb6c588a33b0bf5cbf451236407f5ba110 (patch)
tree611d6a90a411b1917d75994604784f9248c7433c /src/rt/rust_scheduler.cpp
parentebc3646c39e2a24fe6eec778fb7ca5862d95acf7 (diff)
downloadrust-028af5cb6c588a33b0bf5cbf451236407f5ba110.tar.gz
rust-028af5cb6c588a33b0bf5cbf451236407f5ba110.zip
rt: Change the lifecycle of tasks and schedulers for various reasons
This is in preparation for giving schedulers their own life cycle separate
from the kernel.

Tasks must be deleted before their scheduler thread, so we can't let the
scheduler exit before all its tasks have been cleaned up. In this scheme,
the scheduler will unregister tasks with the kernel when they are reaped,
then drop their ref on the task (there may still be others). When the task
ref count hits zero, the task will request to be unregistered from the
scheduler, which is responsible for deleting the task.

Instead of having the kernel tell the scheduler to exit, let the scheduler
decide when to exit. For now it will exit when all of its tasks are
unregistered.
Diffstat (limited to 'src/rt/rust_scheduler.cpp')
-rw-r--r--src/rt/rust_scheduler.cpp23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp
index e2389906d86..629df420bd1 100644
--- a/src/rt/rust_scheduler.cpp
+++ b/src/rt/rust_scheduler.cpp
@@ -9,6 +9,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
     srv(srv),
     env(srv->env),
     live_threads(num_threads),
+    live_tasks(0),
     num_threads(num_threads),
     id(id)
 {
@@ -84,6 +85,7 @@ rust_scheduler::create_task(rust_task *spawner, const char *name,
     {
 	scoped_lock with(lock);
 	thread_no = isaac_rand(&rctx) % num_threads;
+	live_tasks++;
     }
     rust_task_thread *thread = threads[thread_no];
     return thread->create_task(spawner, name, init_stack_sz);
@@ -95,8 +97,27 @@ rust_scheduler::create_task(rust_task *spawner, const char *name) {
 }
 
 void
+rust_scheduler::release_task() {
+    bool need_exit = false;
+    {
+	scoped_lock with(lock);
+	live_tasks--;
+	if (live_tasks == 0) {
+	    need_exit = true;
+	}
+    }
+    if (need_exit) {
+	// There are no more tasks on this scheduler. Time to leave
+	exit();
+    }
+}
+
+void
 rust_scheduler::exit() {
-    for(size_t i = 0; i < num_threads; ++i) {
+    // Take a copy of num_threads. After the last thread exits this
+    // scheduler will get destroyed, and our fields will cease to exist.
+    size_t current_num_threads = num_threads;
+    for(size_t i = 0; i < current_num_threads; ++i) {
         threads[i]->exit();
     }
 }