about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-03-30 17:10:02 -0700
committerBrian Anderson <banderson@mozilla.com>2012-03-31 19:51:29 -0700
commit609144f7a6adba552602feb7e50e7c4d6a815fae (patch)
treea0281e219c6d944dbffcd408e7291d14ae08e21e
parent218dd084697ed2ce58812ef9e69cdc86cb83bcf2 (diff)
downloadrust-609144f7a6adba552602feb7e50e7c4d6a815fae.tar.gz
rust-609144f7a6adba552602feb7e50e7c4d6a815fae.zip
rt: Extract start_main_loop from rust_sched_loop to rust_sched_driver
-rw-r--r--mk/rt.mk1
-rw-r--r--src/rt/rust_sched_driver.cpp46
-rw-r--r--src/rt/rust_sched_driver.h23
-rw-r--r--src/rt/rust_sched_launcher.cpp5
-rw-r--r--src/rt/rust_sched_launcher.h8
-rw-r--r--src/rt/rust_sched_loop.cpp37
-rw-r--r--src/rt/rust_sched_loop.h10
-rw-r--r--src/rt/rust_signal.h10
8 files changed, 108 insertions, 32 deletions
diff --git a/mk/rt.mk b/mk/rt.mk
index 5e01c158d7d..eee3f9cf3ea 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -52,6 +52,7 @@ RUNTIME_CS_$(1) := \
               rt/rust_env.cpp \
               rt/rust_sched_loop.cpp \
               rt/rust_sched_launcher.cpp \
+              rt/rust_sched_driver.cpp \
               rt/rust_scheduler.cpp \
               rt/rust_sched_reaper.cpp \
               rt/rust_task.cpp \
diff --git a/src/rt/rust_sched_driver.cpp b/src/rt/rust_sched_driver.cpp
new file mode 100644
index 00000000000..dd9ca9e7f10
--- /dev/null
+++ b/src/rt/rust_sched_driver.cpp
@@ -0,0 +1,46 @@
+#include <assert.h>
+#include "rust_internal.h"
+#include "rust_sched_driver.h"
+#include "rust_sched_loop.h"
+
+rust_sched_driver::rust_sched_driver(rust_sched_loop *sched_loop)
+    : sched_loop(sched_loop),
+      signalled(false) {
+
+    assert(sched_loop != NULL);
+    sched_loop->on_pump_loop(this);
+}
+
+/**
+ * Starts the main scheduler loop which performs task scheduling for this
+ * domain.
+ *
+ * Returns once no more tasks can be scheduled and all task ref_counts
+ * drop to zero.
+ */
+void
+rust_sched_driver::start_main_loop() {
+    assert(sched_loop != NULL);
+
+    rust_sched_loop_state state = sched_loop_state_keep_going;
+    while (state != sched_loop_state_exit) {
+        DLOG(sched_loop, dom, "pumping scheduler");
+        state = sched_loop->run_single_turn();
+
+        if (state == sched_loop_state_block) {
+            scoped_lock with(lock);
+            if (!signalled) {
+                DLOG(sched_loop, dom, "blocking scheduler");
+                lock.wait();
+            }
+            signalled = false;
+        }
+    }
+}
+
+void
+rust_sched_driver::signal() {
+    scoped_lock with(lock);
+    signalled = true;
+    lock.signal();
+}
diff --git a/src/rt/rust_sched_driver.h b/src/rt/rust_sched_driver.h
new file mode 100644
index 00000000000..c8dae9ca7b8
--- /dev/null
+++ b/src/rt/rust_sched_driver.h
@@ -0,0 +1,23 @@
+#ifndef RUST_SCHED_DRIVER_H
+#define RUST_SCHED_DRIVER_H
+
+#include "sync/lock_and_signal.h"
+#include "rust_signal.h"
+
+struct rust_sched_loop;
+
+class rust_sched_driver : public rust_signal {
+private:
+    rust_sched_loop *sched_loop;
+    lock_and_signal lock;
+    bool signalled;
+
+public:
+    rust_sched_driver(rust_sched_loop *sched_loop);
+
+    void start_main_loop();
+
+    virtual void signal();
+};
+
+#endif /* RUST_SCHED_DRIVER_H */
diff --git a/src/rt/rust_sched_launcher.cpp b/src/rt/rust_sched_launcher.cpp
index 08a5ff47f3f..2a001a619fa 100644
--- a/src/rt/rust_sched_launcher.cpp
+++ b/src/rt/rust_sched_launcher.cpp
@@ -7,10 +7,11 @@ rust_sched_launcher::rust_sched_launcher(rust_scheduler *sched,
                                          rust_srv *srv, int id)
     : rust_thread(SCHED_STACK_SIZE),
       kernel(sched->kernel),
-      sched_loop(sched, srv, id) {
+      sched_loop(sched, srv, id),
+      driver(&sched_loop) {
 }
 
 void
 rust_sched_launcher::run() {
-    sched_loop.start_main_loop();
+    driver.start_main_loop();
 }
diff --git a/src/rt/rust_sched_launcher.h b/src/rt/rust_sched_launcher.h
index 38d46042bcf..1baf1724341 100644
--- a/src/rt/rust_sched_launcher.h
+++ b/src/rt/rust_sched_launcher.h
@@ -3,12 +3,7 @@
 
 #include "rust_internal.h"
 #include "sync/rust_thread.h"
-
-#ifndef _WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#endif
+#include "rust_sched_driver.h"
 
 class rust_sched_launcher
   : public kernel_owned<rust_sched_launcher>,
@@ -18,6 +13,7 @@ public:
 
 private:
     rust_sched_loop sched_loop;
+    rust_sched_driver driver;
 
 public:
     rust_sched_launcher(rust_scheduler *sched, rust_srv *srv, int id);
diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp
index 3ddf23cd9a1..ce549db5236 100644
--- a/src/rt/rust_sched_loop.cpp
+++ b/src/rt/rust_sched_loop.cpp
@@ -25,6 +25,7 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched,
     should_exit(false),
     cached_c_stack(NULL),
     dead_task(NULL),
+    pump_signal(NULL),
     kernel(sched->kernel),
     sched(sched),
     srv(srv),
@@ -183,32 +184,24 @@ rust_sched_loop::log_state() {
     }
 }
 
-/**
- * Starts the main scheduler loop which performs task scheduling for this
- * domain.
- *
- * Returns once no more tasks can be scheduled and all task ref_counts
- * drop to zero.
- */
 void
-rust_sched_loop::start_main_loop() {
-    DLOG(this, dom, "started domain loop %d", id);
-
-    rust_sched_loop_state state = sched_loop_state_keep_going;
-    while (state != sched_loop_state_exit) {
-        state = run_single_turn();
+rust_sched_loop::on_pump_loop(rust_signal *signal) {
+    I(this, pump_signal == NULL);
+    I(this, signal != NULL);
+    pump_signal = signal;
+}
 
-        scoped_lock with(lock);
-        if (!should_exit && running_tasks.length() == 0) {
-            lock.wait();
-        }
-        DLOG(this, task,
-             "scheduler %d resuming ...", id);
-    }
+void
+rust_sched_loop::pump_loop() {
+    I(this, pump_signal != NULL);
+    pump_signal->signal();
 }
 
 rust_sched_loop_state
 rust_sched_loop::run_single_turn() {
+    DLOG(this, task,
+         "scheduler %d resuming ...", id);
+
     lock.lock();
 
     if (!should_exit) {
@@ -344,7 +337,7 @@ rust_sched_loop::transition(rust_task *task,
     }
     task->set_state(dst, cond, cond_name);
 
-    lock.signal();
+    pump_loop();
 }
 
 #ifndef _WIN32
@@ -382,7 +375,7 @@ rust_sched_loop::exit() {
     scoped_lock with(lock);
     DLOG(this, dom, "Requesting exit for thread %d", id);
     should_exit = true;
-    lock.signal();
+    pump_loop();
 }
 
 // Before activating each task, make sure we have a C stack available.
diff --git a/src/rt/rust_sched_loop.h b/src/rt/rust_sched_loop.h
index c21dc9b0c34..e89e9a6313b 100644
--- a/src/rt/rust_sched_loop.h
+++ b/src/rt/rust_sched_loop.h
@@ -3,6 +3,7 @@
 
 #include "rust_internal.h"
 #include "rust_stack.h"
+#include "rust_signal.h"
 #include "context.h"
 
 enum rust_task_state {
@@ -22,6 +23,8 @@ enum rust_sched_loop_state {
     sched_loop_state_exit
 };
 
+struct rust_task;
+
 typedef indexed_list<rust_task> rust_task_list;
 
 struct rust_sched_loop
@@ -53,13 +56,15 @@ private:
     rust_task_list blocked_tasks;
     rust_task *dead_task;
 
+    rust_signal *pump_signal;
+
     void prepare_c_stack(rust_task *task);
     void unprepare_c_stack();
 
     rust_task_list *state_list(rust_task_state state);
     const char *state_name(rust_task_state state);
 
-    rust_sched_loop_state run_single_turn();
+    void pump_loop();
 
 public:
     rust_kernel *kernel;
@@ -96,7 +101,8 @@ public:
     void reap_dead_tasks();
     rust_task *schedule_task();
 
-    void start_main_loop();
+    void on_pump_loop(rust_signal *signal);
+    rust_sched_loop_state run_single_turn();
 
     void log_state();
 
diff --git a/src/rt/rust_signal.h b/src/rt/rust_signal.h
new file mode 100644
index 00000000000..3f27f1fad97
--- /dev/null
+++ b/src/rt/rust_signal.h
@@ -0,0 +1,10 @@
+#ifndef RUST_SIGNAL_H
+#define RUST_SIGNAL_H
+
+// Just an abstrict class that reperesents something that can be signalled
+class rust_signal {
+public:
+    virtual void signal() = 0;
+};
+
+#endif /* RUST_SIGNAL_H */