diff options
| -rw-r--r-- | src/rt/rust.cpp | 2 | ||||
| -rw-r--r-- | src/rt/rust_builtin.cpp | 6 | ||||
| -rw-r--r-- | src/rt/rust_task.cpp | 43 | ||||
| -rw-r--r-- | src/rt/rust_task.h | 15 | ||||
| -rw-r--r-- | src/rt/test/rust_test_runtime.cpp | 4 | ||||
| -rw-r--r-- | src/test/stdtest/task.rs | 52 |
6 files changed, 55 insertions, 67 deletions
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index a3b30c26e5b..03acdaa91e0 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -98,7 +98,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) { DLOG(sched, dom, "startup: arg[%d] = '%s'", i, args->argv[i]); } - root_task->start((spawn_fn)main_fn, (uintptr_t)args->args); + root_task->start((spawn_fn)main_fn, NULL, args->args); root_task->deref(); root_task = NULL; diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index b387078a75a..4f951a7faf0 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -421,15 +421,15 @@ rust_get_task() { } struct fn_env_pair { - intptr_t f; - intptr_t env; + spawn_fn f; + rust_boxed_closure *env; }; extern "C" CDECL void start_task(rust_task_id id, fn_env_pair *f) { rust_task *task = rust_scheduler::get_task(); rust_task *target = task->kernel->get_task_by_id(id); - target->start((spawn_fn)f->f, f->env); + target->start(f->f, f->env, NULL); target->deref(); } diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index f63e8d8d4c0..cade11e372d 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -292,18 +292,9 @@ rust_task::~rust_task() struct spawn_args { rust_task *task; - uintptr_t envptr; spawn_fn f; -}; - -struct rust_closure { - const type_desc *td; - // ... see trans_closure.rs for full description ... -}; - -struct rust_boxed_closure { - intptr_t ref_count; - rust_closure closure; + rust_boxed_closure *envptr; + void *argptr; }; struct cleanup_args { @@ -319,14 +310,6 @@ cleanup_task(cleanup_args *args) { cc::do_cc(task); - rust_boxed_closure* boxed_env = (rust_boxed_closure*)a->envptr; - if(boxed_env) { - // free the environment. - rust_closure *env = &boxed_env->closure; - env->td->drop_glue(NULL, NULL, &env->td, env); - env->td->free_glue(NULL, NULL, &env->td, env); - } - task->die(); if (task->killed && !failed) { @@ -345,6 +328,8 @@ cleanup_task(cleanup_args *args) { } } +extern "C" void upcall_shared_free(void* ptr); + // This runs on the Rust stack extern "C" CDECL void task_start_wrapper(spawn_args *a) @@ -355,16 +340,23 @@ void task_start_wrapper(spawn_args *a) try { // The first argument is the return pointer; as the task fn // must have void return type, we can safely pass 0. - a->f(0, a->envptr); + a->f(0, a->envptr, a->argptr); } catch (rust_task *ex) { A(task->sched, ex == task, "Expected this task to be thrown for unwinding"); failed = true; } - cleanup_args ca = {a, failed}; + rust_boxed_closure* boxed_env = (rust_boxed_closure*)a->envptr; + if(boxed_env) { + // free the environment. + const type_desc *td = boxed_env->closure.td; + td->drop_glue(NULL, NULL, td->first_param, &boxed_env->closure); + upcall_shared_free(boxed_env); + } // The cleanup work needs lots of stack + cleanup_args ca = {a, failed}; task->sched->c_context.call_shim_on_c_stack(&ca, (void*)cleanup_task); task->ctx.next->swap(task->ctx); @@ -372,10 +364,12 @@ void task_start_wrapper(spawn_args *a) void rust_task::start(spawn_fn spawnee_fn, - uintptr_t env) + rust_boxed_closure *envptr, + void *argptr) { LOG(this, task, "starting task from fn 0x%" PRIxPTR - " with env 0x%" PRIxPTR, spawnee_fn, env); + " with env 0x%" PRIxPTR " and arg 0x%" PRIxPTR, + spawnee_fn, envptr, argptr); I(sched, stk->data != NULL); @@ -386,7 +380,8 @@ rust_task::start(spawn_fn spawnee_fn, spawn_args *a = (spawn_args *)sp; a->task = this; - a->envptr = env; + a->envptr = envptr; + a->argptr = argptr; a->f = spawnee_fn; ctx.call((void *)task_start_wrapper, a, sp); diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 2c8e9809c7a..6be28f41574 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -21,7 +21,17 @@ struct chan_handle { rust_port_id port; }; -typedef void (*CDECL spawn_fn)(uintptr_t, uintptr_t); +struct rust_closure { + const type_desc *td; + // ... see trans_closure.rs for full description ... +}; + +struct rust_boxed_closure { + intptr_t ref_count; + rust_closure closure; +}; + +typedef void (*CDECL spawn_fn)(void*, rust_boxed_closure*, void *); struct rust_box; @@ -135,7 +145,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond ~rust_task(); void start(spawn_fn spawnee_fn, - uintptr_t args); + rust_boxed_closure *env, + void *args); void start(); bool running(); bool blocked(); diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp index 644a23f28b1..7bfa06fdc99 100644 --- a/src/rt/test/rust_test_runtime.cpp +++ b/src/rt/test/rust_test_runtime.cpp @@ -39,7 +39,7 @@ rust_domain_test::run() { return true; } -void task_entry(uintptr_t retptr, uintptr_t env) { +void task_entry(void *, rust_boxed_closure *, void *) { printf("task entry\n"); } @@ -47,7 +47,7 @@ void rust_task_test::worker::run() { rust_task_id root_id = kernel->create_task(NULL, "main"); rust_task *root_task = kernel->get_task_by_id(root_id); - root_task->start(&task_entry, (uintptr_t)NULL); + root_task->start(&task_entry, NULL, NULL); root_task->sched->start_main_loop(); } diff --git a/src/test/stdtest/task.rs b/src/test/stdtest/task.rs index 3a08606f47e..500189a0bc6 100644 --- a/src/test/stdtest/task.rs +++ b/src/test/stdtest/task.rs @@ -11,33 +11,29 @@ fn test_sleep() { task::sleep(1000000u); } #[test] #[ignore(cfg(target_os = "win32"))] fn test_unsupervise() { - fn f(&&_i: ()) { task::unsupervise(); fail; } - task::spawn((), f); + fn f() { task::unsupervise(); fail; } + task::spawn {|| f}; } #[test] fn test_lib_spawn() { - fn foo(&&_i: ()) { #error("Hello, World!"); } - task::spawn((), foo); + fn foo() { #error("Hello, World!"); } + task::spawn {|| foo}; } #[test] fn test_lib_spawn2() { - fn foo(&&x: int) { assert (x == 42); } - task::spawn(42, foo); + fn foo(x: int) { assert (x == 42); } + task::spawn {|| foo(42);}; } #[test] fn test_join_chan() { - fn winner(&&_i: ()) { } + fn winner() { } - let p = comm::port(); - task::spawn_notify((), winner, comm::chan(p)); - let s = comm::recv(p); - #error("received task status message"); - log(error, s); - alt s { - task::exit(_, task::tr_success.) {/* yay! */ } + let t = task::spawn_joinable {|| winner();}; + alt task::join(t) { + task::tr_success. {/* yay! */ } _ { fail "invalid task status received" } } } @@ -46,32 +42,18 @@ fn test_join_chan() { #[test] #[ignore(cfg(target_os = "win32"))] fn test_join_chan_fail() { - fn failer(&&_i: ()) { task::unsupervise(); fail } + fn failer() { task::unsupervise(); fail } - let p = comm::port(); - task::spawn_notify((), failer, comm::chan(p)); - let s = comm::recv(p); - #error("received task status message"); - log(error, s); - alt s { - task::exit(_, task::tr_failure.) {/* yay! */ } + let t = task::spawn_joinable {|| failer();}; + alt task::join(t) { + task::tr_failure. {/* yay! */ } _ { fail "invalid task status received" } } } #[test] -fn test_join_convenient() { - fn winner(&&_i: ()) { } - let handle = task::spawn_joinable((), winner); - assert (task::tr_success == task::join(handle)); -} - -#[test] -#[ignore] fn spawn_polymorphic() { - // FIXME #1038: Can't spawn palymorphic functions - /*fn foo<T: send>(x: T) { log(error, x); } - - task::spawn(true, foo); - task::spawn(42, foo);*/ + fn foo<send T>(x: T) { log(error, x); } + task::spawn {|| foo(true);} + task::spawn {|| foo(42);} } |
