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;
}
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();
}
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 {
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) {
}
}
+extern "C" void upcall_shared_free(void* ptr);
+
// This runs on the Rust stack
extern "C" CDECL
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);
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);
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);
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;
~rust_task();
void start(spawn_fn spawnee_fn,
- uintptr_t args);
+ rust_boxed_closure *env,
+ void *args);
void start();
bool running();
bool blocked();
return true;
}
-void task_entry(uintptr_t retptr, uintptr_t env) {
+void task_entry(void *, rust_boxed_closure *, void *) {
printf("task entry\n");
}
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();
}
#[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" }
}
}
#[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);}
}