about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-03-30 13:54:37 -0700
committerBrian Anderson <banderson@mozilla.com>2012-03-31 19:51:29 -0700
commit218dd084697ed2ce58812ef9e69cdc86cb83bcf2 (patch)
tree171eaf77a6e1d8c4af168bcb17d2ba02d9f41f83 /src
parent771c1be6a64225d416ad99a860f1c8d34ce3a18b (diff)
downloadrust-218dd084697ed2ce58812ef9e69cdc86cb83bcf2.tar.gz
rust-218dd084697ed2ce58812ef9e69cdc86cb83bcf2.zip
rt: Introduce rust_sched_reaper
This just moves the responsibility for joining with scheduler threads
off to a worker thread. This will be needed when we allow tasks to be
scheduled on the main thread.
Diffstat (limited to 'src')
-rw-r--r--src/rt/rust.cpp2
-rw-r--r--src/rt/rust_kernel.cpp23
-rw-r--r--src/rt/rust_kernel.h6
-rw-r--r--src/rt/rust_sched_reaper.cpp15
-rw-r--r--src/rt/rust_sched_reaper.h17
5 files changed, 56 insertions, 7 deletions
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index d1adf41118f..00657f8ec0a 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -93,7 +93,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
     root_task->start((spawn_fn)main_fn, NULL, args->args);
     root_task = NULL;
 
-    int ret = kernel->wait_for_schedulers();
+    int ret = kernel->wait_for_exit();
     delete args;
     delete kernel;
     delete srv;
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index e74819ab318..0c7ec5c64b6 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -17,6 +17,7 @@ rust_kernel::rust_kernel(rust_srv *srv) :
     max_port_id(0),
     rval(0),
     max_sched_id(0),
+    sched_reaper(this),
     env(srv->env)
 {
 }
@@ -62,6 +63,9 @@ rust_kernel::create_scheduler(size_t num_threads) {
     rust_scheduler *sched;
     {
         scoped_lock with(sched_lock);
+        // If this is the first scheduler then we need to launch
+        // the scheduler reaper.
+        bool start_reaper = sched_table.empty();
         id = max_sched_id++;
         K(srv, id != INTPTR_MAX, "Hit the maximum scheduler id");
         sched = new (this, "rust_scheduler")
@@ -69,6 +73,9 @@ rust_kernel::create_scheduler(size_t num_threads) {
         bool is_new = sched_table
             .insert(std::pair<rust_sched_id, rust_scheduler*>(id, sched)).second;
         A(this, is_new, "Reusing a sched id?");
+        if (start_reaper) {
+            sched_reaper.start();
+        }
     }
     sched->start_task_threads();
     return id;
@@ -96,12 +103,12 @@ rust_kernel::release_scheduler_id(rust_sched_id id) {
 }
 
 /*
-Called on the main thread to wait for the kernel to exit. This function is
-also used to join on every terminating scheduler thread, so that we can be
-sure they have completely exited before the process exits.  If we don't join
-them then we can see valgrind errors due to un-freed pthread memory.
+Called by rust_sched_reaper to join every every terminating scheduler thread,
+so that we can be sure they have completely exited before the process exits.
+If we don't join them then we can see valgrind errors due to un-freed pthread
+memory.
  */
-int
+void
 rust_kernel::wait_for_schedulers()
 {
     scoped_lock with(sched_lock);
@@ -120,6 +127,12 @@ rust_kernel::wait_for_schedulers()
             sched_lock.wait();
         }
     }
+}
+
+/* Called on the main thread to wait for the kernel to exit */
+int
+rust_kernel::wait_for_exit() {
+    sched_reaper.join();
     return rval;
 }
 
diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h
index f97303cae0f..78548917ee5 100644
--- a/src/rt/rust_kernel.h
+++ b/src/rt/rust_kernel.h
@@ -6,6 +6,7 @@
 #include <vector>
 #include "memory_region.h"
 #include "rust_log.h"
+#include "rust_sched_reaper.h"
 
 struct rust_task_thread;
 class rust_scheduler;
@@ -46,6 +47,8 @@ private:
     // A list of scheduler ids that are ready to exit
     std::vector<rust_sched_id> join_list;
 
+    rust_sched_reaper sched_reaper;
+
 public:
 
     struct rust_env *env;
@@ -66,7 +69,8 @@ public:
     rust_scheduler* get_scheduler_by_id(rust_sched_id id);
     // Called by a scheduler to indicate that it is terminating
     void release_scheduler_id(rust_sched_id id);
-    int wait_for_schedulers();
+    void wait_for_schedulers();
+    int wait_for_exit();
 
 #ifdef __WIN32__
     void win32_require(LPCTSTR fn, BOOL ok);
diff --git a/src/rt/rust_sched_reaper.cpp b/src/rt/rust_sched_reaper.cpp
new file mode 100644
index 00000000000..f2897859f23
--- /dev/null
+++ b/src/rt/rust_sched_reaper.cpp
@@ -0,0 +1,15 @@
+#include "rust_internal.h"
+#include "rust_kernel.h"
+#include "rust_sched_reaper.h"
+
+// NB: We're using a very small stack here
+const size_t STACK_SIZE = 1024*20;
+
+rust_sched_reaper::rust_sched_reaper(rust_kernel *kernel)
+    : rust_thread(STACK_SIZE), kernel(kernel) {
+}
+
+void
+rust_sched_reaper::run() {
+    kernel->wait_for_schedulers();
+}
diff --git a/src/rt/rust_sched_reaper.h b/src/rt/rust_sched_reaper.h
new file mode 100644
index 00000000000..6b43038312d
--- /dev/null
+++ b/src/rt/rust_sched_reaper.h
@@ -0,0 +1,17 @@
+#ifndef RUST_SCHED_REAPER_H
+#define RUST_SCHED_REAPER_H
+
+#include "sync/rust_thread.h"
+
+class rust_kernel;
+
+/* Responsible for joining with rust_schedulers */
+class rust_sched_reaper : public rust_thread {
+private:
+    rust_kernel *kernel;
+public:
+    rust_sched_reaper(rust_kernel *kernel);
+    virtual void run();
+};
+
+#endif /* RUST_SCHED_REAPER_H */