about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Holk <eholk@mozilla.com>2011-06-15 18:16:17 -0700
committerEric Holk <eholk@mozilla.com>2011-06-15 18:16:59 -0700
commit67360ae61808453d308496f90e0b3faa3e8efee3 (patch)
tree7df5f198272c57aeebf35e9a22aa03cd12f33e0b
parentc4f9bd94700188678893659580f3b7aa80da3b7d (diff)
downloadrust-67360ae61808453d308496f90e0b3faa3e8efee3.tar.gz
rust-67360ae61808453d308496f90e0b3faa3e8efee3.zip
Fixed a problem where spawn arguments were getting lost again. Also, fixed up stack alignment, which closes #496
-rw-r--r--src/rt/arch/i386/context.cpp6
-rw-r--r--src/rt/arch/i386/context.h8
-rw-r--r--src/rt/rust.cpp3
-rw-r--r--src/rt/rust_task.cpp10
-rw-r--r--src/rt/rust_task.h3
-rw-r--r--src/rt/rust_upcall.cpp23
-rw-r--r--src/rt/test/rust_test_runtime.cpp2
-rw-r--r--src/test/run-pass/comm.rs5
-rw-r--r--src/test/run-pass/spawn.rs18
-rw-r--r--src/test/run-pass/spawn2.rs14
10 files changed, 54 insertions, 38 deletions
diff --git a/src/rt/arch/i386/context.cpp b/src/rt/arch/i386/context.cpp
index 8f5dbacbcf4..c1c8ba2167b 100644
--- a/src/rt/arch/i386/context.cpp
+++ b/src/rt/arch/i386/context.cpp
@@ -36,10 +36,14 @@ void context::swap(context &out)
 void context::call(void *f, void *arg, void *stack) {
   // set up the trampoline frame
   uint32_t *sp = (uint32_t *)stack;
+
+  // Shift the stack pointer so the alignment works out right.
+  sp = align_down(sp) - 2;
+
   *--sp = (uint32_t)this;
   *--sp = (uint32_t)arg;
-  *--sp = 0xdeadbeef; //(uint32_t)ctx_trampoline1;
   *--sp = 0xdeadbeef;
+  *--sp = 0xca11ab1e;
 
   regs.esp = (uint32_t)sp;
   regs.eip = (uint32_t)f;
diff --git a/src/rt/arch/i386/context.h b/src/rt/arch/i386/context.h
index 0ddbee6988f..5329016450a 100644
--- a/src/rt/arch/i386/context.h
+++ b/src/rt/arch/i386/context.h
@@ -32,4 +32,12 @@ public:
   void call(void *f, void *arg, void *sp);
 };
 
+template<typename T>
+T align_down(T sp)
+{
+    // There is no platform we care about that needs more than a
+    // 16-byte alignment.
+    return (T)((int)sp & ~(16 - 1));
+}
+
 #endif
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 166c0002533..c7cece2ef81 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -93,8 +93,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
         DLOG(dom, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
     }
 
-    dom->root_task->start(main_fn, 
-                          (uintptr_t)args->args, sizeof(args->args));
+    dom->root_task->start(main_fn, (uintptr_t)args->args);
 
     int ret = dom->start_main_loop();
     delete args;
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index bae6f221a95..bb8261bb78a 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -17,6 +17,7 @@
 static size_t const min_stk_bytes = 0x300000;
 // static size_t const min_stk_bytes = 0x10000;
 
+
 // Task stack segments. Heap allocated and chained together.
 
 static stk_seg*
@@ -152,25 +153,24 @@ void task_start_wrapper(spawn_args *a)
 
 void
 rust_task::start(uintptr_t spawnee_fn,
-                 uintptr_t args,
-                 size_t callsz)
+                 uintptr_t args)
 {
     LOGPTR(dom, "from spawnee", spawnee_fn);
 
     I(dom, stk->data != NULL);
 
-    char *sp = (char *)stk->limit;
+    char *sp = (char *)rust_sp;
 
     sp -= sizeof(spawn_args);
 
     spawn_args *a = (spawn_args *)sp;
 
     a->task = this;
-    a->a3 = 0xca11ab1e;
+    a->a3 = 0;
     a->a4 = args;
     void **f = (void **)&a->f;
     *f = (void *)spawnee_fn;
-
+    
     ctx.call((void *)task_start_wrapper, a, sp);
 
     yield_timer.reset(0);
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index 82792c1e1e5..a022a348667 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -60,8 +60,7 @@ rust_task : public maybe_proxy<rust_task>,
     ~rust_task();
 
     void start(uintptr_t spawnee_fn,
-               uintptr_t args,
-               size_t callsz);
+               uintptr_t args);
     void grow(size_t n_frame_bytes);
     bool running();
     bool blocked();
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 68a15e3b3a3..e8c8e45e1c6 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -509,14 +509,6 @@ upcall_new_task(rust_task *spawner, rust_vec *name) {
     return task;
 }
 
-static uintptr_t
-align_down(uintptr_t sp)
-{
-    // There is no platform we care about that needs more than a
-    // 16-byte alignment.
-    return sp & ~(16 - 1);
-}
-
 extern "C" CDECL rust_task *
 upcall_start_task(rust_task *spawner,
                   rust_task *task,
@@ -538,12 +530,11 @@ upcall_start_task(rust_task *spawner,
     // The args tuple is stack-allocated. We need to move it over to the new
     // stack.
     task->rust_sp -= args_sz;
+    uintptr_t child_arg = (uintptr_t)task->rust_sp;
+
     memcpy((void*)task->rust_sp, (void*)args, args_sz);
-    uintptr_t start_args[] = {0, 0, 0, task->rust_sp};
-    
-    task->rust_sp = align_down(task->rust_sp);
-    
-    task->start(spawnee_fn, (uintptr_t)start_args, sizeof(start_args));
+
+    task->start(spawnee_fn, child_arg);
     return task;
 }
 
@@ -567,6 +558,8 @@ upcall_new_thread(rust_task *task, const char *name) {
     return child_task_proxy;
 }
 
+#if 0 /* TODO: this code will be re-enabled once we have multithreading. */
+
 #if defined(__WIN32__)
 static DWORD WINAPI rust_thread_start(void *ptr)
 #elif defined(__GNUC__)
@@ -587,6 +580,8 @@ static void *rust_thread_start(void *ptr)
     return 0;
 }
 
+#endif
+
 /**
  * Called after a new domain is created. Here we create a new thread and
  * and start the domain main loop.
@@ -597,6 +592,7 @@ upcall_start_thread(rust_task *task,
                     uintptr_t spawnee_fn,
                     size_t callsz) {
     LOG_UPCALL_ENTRY(task);
+#if 0
     rust_dom *parenet_dom = task->dom;
     rust_handle<rust_task> *child_task_handle = child_task_proxy->handle();
     LOG(task, task,
@@ -616,6 +612,7 @@ upcall_start_thread(rust_task *task,
     pthread_create(&thread, &parenet_dom->attr, rust_thread_start,
                    (void *) child_task->dom);
 #endif
+#endif // 0
     return child_task_proxy;
 }
 
diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp
index c683302dec2..0fed35dad82 100644
--- a/src/rt/test/rust_test_runtime.cpp
+++ b/src/rt/test/rust_test_runtime.cpp
@@ -52,7 +52,7 @@ rust_task_test::worker::run() {
     rust_handle<rust_dom> *handle =
         kernel->create_domain("test");
     rust_dom *domain = handle->referent();
-    domain->root_task->start((uintptr_t)&task_entry, (uintptr_t)NULL, 0);
+    domain->root_task->start((uintptr_t)&task_entry, (uintptr_t)NULL);
     domain->start_main_loop();
     kernel->destroy_domain(domain);
 }
diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs
index 844f3ee3bfa..5b249e03041 100644
--- a/src/test/run-pass/comm.rs
+++ b/src/test/run-pass/comm.rs
@@ -5,12 +5,12 @@
 
 fn main() {
   let port[int] p = port();
-  spawn child(chan(p));
+  let task t = spawn child(chan(p));
   let int y;
   p |> y;
   log_err "received";
   log_err y;
-  //assert (y == 10);
+  assert (y == 10);
 }
 
 fn child(chan[int] c) {
@@ -18,4 +18,3 @@ fn child(chan[int] c) {
   c <| 10;
   log_err "value sent"
 }
-
diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs
index 719258ecd9f..db695a1dd8b 100644
--- a/src/test/run-pass/spawn.rs
+++ b/src/test/run-pass/spawn.rs
@@ -1,14 +1,18 @@
+// xfail-stage0
+// -*- rust -*-
 
+use std;
 
+fn main() {
+    auto t = spawn child(10);
+    std::task::join(t)
+}
 
-// xfail-stage0
-// xfail-stage1
-// xfail-stage2
-// xfail-stage3
-// -*- rust -*-
-fn main() { auto t = spawn child(10); }
+fn child(int i) {
+    log_err i;
+    assert(i == 10);
+}
 
-fn child(int i) { log_err i; }
 // Local Variables:
 // mode: rust;
 // fill-column: 78;
diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs
index 1739cfee8dc..3d2690e34e5 100644
--- a/src/test/run-pass/spawn2.rs
+++ b/src/test/run-pass/spawn2.rs
@@ -1,11 +1,8 @@
 // xfail-stage0
-// xfail-stage1
-// xfail-stage2
-// xfail-stage3
 // -*- rust -*-
 
 fn main() {
-  spawn child(10, 20, 30, 40, 50, 60, 70, 80, 90);
+    spawn child(10, 20, 30, 40, 50, 60, 70, 80, 90);
 }
 
 fn child(int i1,
@@ -27,6 +24,15 @@ fn child(int i1,
   log_err i7;
   log_err i8;
   log_err i9;
+  assert(i1 == 10);
+  assert(i2 == 20);
+  assert(i3 == 30);
+  assert(i4 == 40);
+  assert(i5 == 50);
+  assert(i6 == 60);
+  assert(i7 == 70);
+  assert(i8 == 80);
+  assert(i9 == 90);
 }
 
 // Local Variables: