summary refs log tree commit diff
path: root/src/rt/rust_scheduler.cpp
diff options
context:
space:
mode:
authorPhilipp Brüschweiler <blei42@gmail.com>2012-09-14 15:01:17 +0200
committerBrian Anderson <banderson@mozilla.com>2012-09-19 14:01:53 -0700
commit68e755b1c26db09cf8e121bbbea2075f6116e279 (patch)
tree8d48dc089bb9effd2090117fd6033c4ca81470d1 /src/rt/rust_scheduler.cpp
parent35a935377483823ca1fbaede5a87406b494b0488 (diff)
downloadrust-68e755b1c26db09cf8e121bbbea2075f6116e279.tar.gz
rust-68e755b1c26db09cf8e121bbbea2075f6116e279.zip
core: Allocate threads on demand, not on scheduler startup
API change: rust_kernel::create_scheduler() or
rust_scheduler::rust_scheduler() respecitevly now take ownership of the
launch factory argument, it is needed to create new threads on demand.

Also renames rustrt::sched_threads() to rustrt::rust_sched_threads() for
consistency. Added rustrt::rust_max_sched_threads() to return the
maximal number of scheduled threads of the current scheduler.

Fixes #3493.
Diffstat (limited to 'src/rt/rust_scheduler.cpp')
-rw-r--r--src/rt/rust_scheduler.cpp75
1 files changed, 47 insertions, 28 deletions
diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp
index 5dd1a261c0e..aa288cf3b94 100644
--- a/src/rt/rust_scheduler.cpp
+++ b/src/rt/rust_scheduler.cpp
@@ -6,34 +6,39 @@
 #include "rust_sched_launcher.h"
 
 rust_scheduler::rust_scheduler(rust_kernel *kernel,
-                               size_t num_threads,
+                               size_t max_num_threads,
                                rust_sched_id id,
                                bool allow_exit,
                                bool killed,
                                rust_sched_launcher_factory *launchfac) :
     ref_count(1),
     kernel(kernel),
-    live_threads(num_threads),
+    live_threads(0),
     live_tasks(0),
     cur_thread(0),
     may_exit(allow_exit),
-    num_threads(num_threads),
+    killed(killed),
+    launchfac(launchfac),
+    max_num_threads(max_num_threads),
     id(id)
 {
-    create_task_threads(launchfac, killed);
+    // Create the first thread
+    threads.push(create_task_thread(0));
 }
 
 void rust_scheduler::delete_this() {
     destroy_task_threads();
+    delete launchfac;
     delete this;
 }
 
 rust_sched_launcher *
-rust_scheduler::create_task_thread(rust_sched_launcher_factory *launchfac,
-                                   int id, bool killed) {
+rust_scheduler::create_task_thread(int id) {
+    live_threads++;
     rust_sched_launcher *thread = launchfac->create(this, id, killed);
-    KLOG(kernel, kern, "created task thread: " PTR ", id: %d",
-          thread, id);
+    KLOG(kernel, kern, "created task thread: " PTR
+         ", id: %d, live_threads: %d",
+         thread, id, live_threads);
     return thread;
 }
 
@@ -44,18 +49,8 @@ rust_scheduler::destroy_task_thread(rust_sched_launcher *thread) {
 }
 
 void
-rust_scheduler::create_task_threads(rust_sched_launcher_factory *launchfac,
-                                    bool killed) {
-    KLOG(kernel, kern, "Using %d scheduler threads.", num_threads);
-
-    for(size_t i = 0; i < num_threads; ++i) {
-        threads.push(create_task_thread(launchfac, i, killed));
-    }
-}
-
-void
 rust_scheduler::destroy_task_threads() {
-    for(size_t i = 0; i < num_threads; ++i) {
+    for(size_t i = 0; i < threads.size(); ++i) {
         destroy_task_thread(threads[i]);
     }
 }
@@ -63,7 +58,7 @@ rust_scheduler::destroy_task_threads() {
 void
 rust_scheduler::start_task_threads()
 {
-    for(size_t i = 0; i < num_threads; ++i) {
+    for(size_t i = 0; i < threads.size(); ++i) {
         rust_sched_launcher *thread = threads[i];
         thread->start();
     }
@@ -72,7 +67,7 @@ rust_scheduler::start_task_threads()
 void
 rust_scheduler::join_task_threads()
 {
-    for(size_t i = 0; i < num_threads; ++i) {
+    for(size_t i = 0; i < threads.size(); ++i) {
         rust_sched_launcher *thread = threads[i];
         thread->join();
     }
@@ -80,7 +75,7 @@ rust_scheduler::join_task_threads()
 
 void
 rust_scheduler::kill_all_tasks() {
-    for(size_t i = 0; i < num_threads; ++i) {
+    for(size_t i = 0; i < threads.size(); ++i) {
         rust_sched_launcher *thread = threads[i];
         thread->get_loop()->kill_all_tasks();
     }
@@ -92,10 +87,29 @@ rust_scheduler::create_task(rust_task *spawner, const char *name) {
     {
         scoped_lock with(lock);
         live_tasks++;
-        thread_no = cur_thread++;
-        if (cur_thread >= num_threads)
-            cur_thread = 0;
+
+        // Find unoccupied thread
+        for (thread_no = 0; thread_no < threads.size(); ++thread_no) {
+            if (threads[thread_no]->get_loop()->number_of_live_tasks() == 0)
+                break;
+        }
+
+        if (thread_no == threads.size()) {
+            if (threads.size() < max_num_threads) {
+                // Else create new thread
+                thread_no = threads.size();
+                rust_sched_launcher *thread = create_task_thread(thread_no);
+                thread->start();
+                threads.push(thread);
+            } else {
+                // Or use round robin allocation
+                thread_no = cur_thread++;
+                if (cur_thread >= max_num_threads)
+                    cur_thread = 0;
+            }
+        }
     }
+    KLOG(kernel, kern, "Creating task %s, on thread %d.", name, thread_no);
     kernel->register_task();
     rust_sched_launcher *thread = threads[thread_no];
     return thread->get_loop()->create_task(spawner, name);
@@ -119,17 +133,22 @@ rust_scheduler::release_task() {
 
 void
 rust_scheduler::exit() {
-    // Take a copy of num_threads. After the last thread exits this
+    // Take a copy of the number of 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;
+    size_t current_num_threads = threads.size();
     for(size_t i = 0; i < current_num_threads; ++i) {
         threads[i]->get_loop()->exit();
     }
 }
 
 size_t
+rust_scheduler::max_number_of_threads() {
+    return max_num_threads;
+}
+
+size_t
 rust_scheduler::number_of_threads() {
-    return num_threads;
+    return threads.size();
 }
 
 void