diff options
| author | Eric Holk <eholk@mozilla.com> | 2011-06-15 18:16:17 -0700 |
|---|---|---|
| committer | Eric Holk <eholk@mozilla.com> | 2011-06-15 18:16:59 -0700 |
| commit | 67360ae61808453d308496f90e0b3faa3e8efee3 (patch) | |
| tree | 7df5f198272c57aeebf35e9a22aa03cd12f33e0b | |
| parent | c4f9bd94700188678893659580f3b7aa80da3b7d (diff) | |
| download | rust-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.cpp | 6 | ||||
| -rw-r--r-- | src/rt/arch/i386/context.h | 8 | ||||
| -rw-r--r-- | src/rt/rust.cpp | 3 | ||||
| -rw-r--r-- | src/rt/rust_task.cpp | 10 | ||||
| -rw-r--r-- | src/rt/rust_task.h | 3 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 23 | ||||
| -rw-r--r-- | src/rt/test/rust_test_runtime.cpp | 2 | ||||
| -rw-r--r-- | src/test/run-pass/comm.rs | 5 | ||||
| -rw-r--r-- | src/test/run-pass/spawn.rs | 18 | ||||
| -rw-r--r-- | src/test/run-pass/spawn2.rs | 14 |
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: |
