about summary refs log tree commit diff
path: root/src/rt/rust_task.cpp
diff options
context:
space:
mode:
authorEric Holk <eholk@mozilla.com>2011-06-20 17:19:50 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-06-27 09:58:39 -0700
commit4bc773465fe95da37b8c867979786b190de6197c (patch)
tree668f9398ab5f977a5dfac6c9e9b807540fe745d1 /src/rt/rust_task.cpp
parent91eadfd1ea1544513258fc30bf94ef384db2ad90 (diff)
downloadrust-4bc773465fe95da37b8c867979786b190de6197c.tar.gz
rust-4bc773465fe95da37b8c867979786b190de6197c.zip
Basic multithreading support. The infinite loops test successfully maxes out the CPU.
Diffstat (limited to 'src/rt/rust_task.cpp')
-rw-r--r--src/rt/rust_task.cpp29
1 files changed, 20 insertions, 9 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index bb8261bb78a..f42f40510bd 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -70,7 +70,8 @@ rust_task::rust_task(rust_dom *dom, rust_task_list *state,
     list_index(-1),
     rendezvous_ptr(0),
     alarm(this),
-    handle(NULL)
+    handle(NULL),
+    active(false)
 {
     LOGPTR(dom, "new task", (uintptr_t)this);
     DLOG(dom, task, "sizeof(task) = %d (0x%x)", sizeof *this, sizeof *this);
@@ -123,17 +124,12 @@ struct spawn_args {
                        uintptr_t, uintptr_t);
 };
 
-// TODO: rewrite this in LLVM assembly so we can be sure the calling
-// conventions will match.
 extern "C" CDECL
 void task_start_wrapper(spawn_args *a)
 {
     rust_task *task = a->task;
     int rval = 42;
     
-    // This is used by the context switching code. LLVM generates fastcall
-    // functions, but ucontext needs cdecl functions. This massages the
-    // calling conventions into the right form.
     a->f(&rval, task, a->a3, a->a4);
 
     LOG(task, task, "task exited with value %d", rval);
@@ -174,7 +170,10 @@ rust_task::start(uintptr_t spawnee_fn,
     ctx.call((void *)task_start_wrapper, a, sp);
 
     yield_timer.reset(0);
-    transition(&dom->newborn_tasks, &dom->running_tasks);
+    {
+        scoped_lock sync(dom->scheduler_lock);
+        transition(&dom->newborn_tasks, &dom->running_tasks);
+    }
 }
 
 void
@@ -425,7 +424,10 @@ rust_task::block(rust_cond *on, const char* name) {
     A(dom, cond == NULL, "Cannot block an already blocked task.");
     A(dom, on != NULL, "Cannot block on a NULL object.");
 
-    transition(&dom->running_tasks, &dom->blocked_tasks);
+    {
+        scoped_lock sync(dom->scheduler_lock);
+        transition(&dom->running_tasks, &dom->blocked_tasks);
+    }
     cond = on;
     cond_name = name;
 }
@@ -437,7 +439,10 @@ rust_task::wakeup(rust_cond *from) {
                         (uintptr_t) cond, (uintptr_t) from);
     A(dom, cond == from, "Cannot wake up blocked task on wrong condition.");
 
-    transition(&dom->blocked_tasks, &dom->running_tasks);
+    {
+        scoped_lock sync(dom->scheduler_lock);
+        transition(&dom->blocked_tasks, &dom->running_tasks);
+    }
     I(dom, cond == from);
     cond = NULL;
     cond_name = "none";
@@ -445,6 +450,7 @@ rust_task::wakeup(rust_cond *from) {
 
 void
 rust_task::die() {
+    scoped_lock sync(dom->scheduler_lock);
     transition(&dom->running_tasks, &dom->dead_tasks);
 }
 
@@ -482,6 +488,11 @@ rust_task::get_handle() {
     return handle;
 }
 
+bool rust_task::can_schedule()
+{
+    return yield_timer.has_timed_out() && !active;
+}
+
 //
 // Local Variables:
 // mode: C++