1
Fork 0

Merge commit 'jyasskin/work'

Conflicts:
	src/rt/rust_dom.cpp
	src/rt/rust_upcall.cpp
This commit is contained in:
Graydon Hoare 2010-08-10 13:26:00 -07:00
commit dbe8760af3
17 changed files with 156 additions and 104 deletions

View file

@ -2822,12 +2822,15 @@ x.y = z + 2;
@c * Ref.Stmt.Spawn:: Statements creating new tasks. @c * Ref.Stmt.Spawn:: Statements creating new tasks.
@cindex Spawn statement @cindex Spawn statement
A @code{spawn} statement consists of keyword @code{spawn}, followed by a A @code{spawn} statement consists of keyword @code{spawn}, followed by
normal @emph{call} statement (@pxref{Ref.Stmt.Call}). A @code{spawn} an optional literal string naming the new task and then a normal
statement causes the runtime to construct a new task executing the called @emph{call} statement (@pxref{Ref.Stmt.Call}). A @code{spawn}
function. The called function is referred to as the @dfn{entry function} for statement causes the runtime to construct a new task executing the
the spawned task, and its arguments are copied from the spawning task to the called function with the given name. The called function is referred
spawned task before the spawned task begins execution. to as the @dfn{entry function} for the spawned task, and its arguments
are copied from the spawning task to the spawned task before the
spawned task begins execution. If no explicit name is present, the
task is implicitly named with the string of the call statement.
Functions taking alias-slot arguments, or returning non-nil values, cannot be Functions taking alias-slot arguments, or returning non-nil values, cannot be
spawned. Iterators cannot be spawned. spawned. Iterators cannot be spawned.
@ -2843,6 +2846,7 @@ fn helper(chan[u8] out) @{
let port[u8] out; let port[u8] out;
let task p = spawn helper(chan(out)); let task p = spawn helper(chan(out));
let task p2 = spawn "my_helper" helper(chan(out));
// let task run, do other things. // let task run, do other things.
auto result <- out; auto result <- out;

View file

@ -472,7 +472,6 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
i32-sub.rs \ i32-sub.rs \
i8-incr.rs \ i8-incr.rs \
import.rs \ import.rs \
inner-module.rs \
integral-indexing.rs \ integral-indexing.rs \
int-lib.rs \ int-lib.rs \
iter-range.rs \ iter-range.rs \

View file

@ -199,7 +199,7 @@ and tup_input = (mutability * atom)
and stmt' = and stmt' =
(* lval-assigning stmts. *) (* lval-assigning stmts. *)
STMT_spawn of (lval * domain * lval * (atom array)) STMT_spawn of (lval * domain * string * lval * (atom array))
| STMT_new_rec of (lval * (rec_input array) * lval option) | STMT_new_rec of (lval * (rec_input array) * lval option)
| STMT_new_tup of (lval * (tup_input array)) | STMT_new_tup of (lval * (tup_input array))
| STMT_new_vec of (lval * mutability * atom array) | STMT_new_vec of (lval * mutability * atom array)
@ -936,10 +936,11 @@ and fmt_stmt_body (ff:Format.formatter) (s:stmt) : unit =
fmt ff ";" fmt ff ";"
end end
| STMT_spawn (dst, domain, fn, args) -> | STMT_spawn (dst, domain, name, fn, args) ->
fmt_lval ff dst; fmt_lval ff dst;
fmt ff " = spawn "; fmt ff " = spawn ";
fmt_domain ff domain; fmt_domain ff domain;
fmt_str ff ("\"" ^ name ^ "\"");
fmt_lval ff fn; fmt_lval ff fn;
fmt_atoms ff args; fmt_atoms ff args;
fmt ff ";"; fmt ff ";";

View file

@ -18,7 +18,7 @@ open Parser;;
type pexp' = type pexp' =
PEXP_call of (pexp * pexp array) PEXP_call of (pexp * pexp array)
| PEXP_spawn of (Ast.domain * pexp) | PEXP_spawn of (Ast.domain * string * pexp)
| PEXP_bind of (pexp * pexp option array) | PEXP_bind of (pexp * pexp option array)
| PEXP_rec of ((Ast.ident * Ast.mutability * pexp) array * pexp option) | PEXP_rec of ((Ast.ident * Ast.mutability * pexp) array * pexp option)
| PEXP_tup of ((Ast.mutability * pexp) array) | PEXP_tup of ((Ast.mutability * pexp) array)
@ -558,9 +558,27 @@ and parse_bottom_pexp (ps:pstate) : pexp =
THREAD -> bump ps; Ast.DOMAIN_thread THREAD -> bump ps; Ast.DOMAIN_thread
| _ -> Ast.DOMAIN_local | _ -> Ast.DOMAIN_local
in in
let pexp = ctxt "spawn [domain] pexp: init call" parse_pexp ps in (* Spawns either have an explicit literal string for the spawned
task's name, or the task is named as the entry call
expression. *)
let explicit_name =
match peek ps with
LIT_STR s -> bump ps; Some s
| _ -> None
in
let pexp =
ctxt "spawn [domain] [name] pexp: init call" parse_pexp ps
in
let bpos = lexpos ps in let bpos = lexpos ps in
span ps apos bpos (PEXP_spawn (domain, pexp)) let name =
match explicit_name with
Some s -> s
(* FIXME: string_of_span returns a string like
"./driver.rs:10:16 - 11:52", not the actual text at those
characters *)
| None -> Session.string_of_span { lo = apos; hi = bpos }
in
span ps apos bpos (PEXP_spawn (domain, name, pexp))
| BIND -> | BIND ->
let apos = lexpos ps in let apos = lexpos ps in
@ -1183,7 +1201,7 @@ and desugar_expr_init
let bind_stmt = ss (Ast.STMT_bind (dst_lval, fn_lval, arg_atoms)) in let bind_stmt = ss (Ast.STMT_bind (dst_lval, fn_lval, arg_atoms)) in
ac [ fn_stmts; arg_stmts; [| bind_stmt |] ] ac [ fn_stmts; arg_stmts; [| bind_stmt |] ]
| PEXP_spawn (domain, sub) -> | PEXP_spawn (domain, name, sub) ->
begin begin
match sub.node with match sub.node with
PEXP_call (fn, args) -> PEXP_call (fn, args) ->
@ -1191,7 +1209,8 @@ and desugar_expr_init
let (arg_stmts, arg_atoms) = desugar_expr_atoms ps args in let (arg_stmts, arg_atoms) = desugar_expr_atoms ps args in
let fn_lval = atom_lval ps fn_atom in let fn_lval = atom_lval ps fn_atom in
let spawn_stmt = let spawn_stmt =
ss (Ast.STMT_spawn (dst_lval, domain, fn_lval, arg_atoms)) ss (Ast.STMT_spawn
(dst_lval, domain, name, fn_lval, arg_atoms))
in in
ac [ fn_stmts; arg_stmts; [| spawn_stmt |] ] ac [ fn_stmts; arg_stmts; [| spawn_stmt |] ]
| _ -> raise (err "non-call spawn" ps) | _ -> raise (err "non-call spawn" ps)

View file

@ -59,7 +59,7 @@ let alias_analysis_visitor
* survive 'into' a sub-block (those formed during iteration) * survive 'into' a sub-block (those formed during iteration)
* need to be handled in this module. *) * need to be handled in this module. *)
Ast.STMT_call (dst, callee, args) Ast.STMT_call (dst, callee, args)
| Ast.STMT_spawn (dst, _, callee, args) | Ast.STMT_spawn (dst, _, _, callee, args)
-> alias_call_args dst callee args -> alias_call_args dst callee args
| Ast.STMT_send (_, src) -> alias src | Ast.STMT_send (_, src) -> alias src

View file

@ -62,7 +62,7 @@ let mutability_checking_visitor
match s.node with match s.node with
Ast.STMT_copy (lv_dst, _) Ast.STMT_copy (lv_dst, _)
| Ast.STMT_call (lv_dst, _, _) | Ast.STMT_call (lv_dst, _, _)
| Ast.STMT_spawn (lv_dst, _, _, _) | Ast.STMT_spawn (lv_dst, _, _, _, _)
| Ast.STMT_recv (lv_dst, _) | Ast.STMT_recv (lv_dst, _)
| Ast.STMT_bind (lv_dst, _, _) | Ast.STMT_bind (lv_dst, _, _)
| Ast.STMT_new_rec (lv_dst, _, _) | Ast.STMT_new_rec (lv_dst, _, _)

View file

@ -402,7 +402,7 @@ let layout_visitor
let callees = let callees =
match s.node with match s.node with
Ast.STMT_call (_, lv, _) Ast.STMT_call (_, lv, _)
| Ast.STMT_spawn (_, _, lv, _) -> [| lv |] | Ast.STMT_spawn (_, _, _, lv, _) -> [| lv |]
| Ast.STMT_check (_, calls) -> Array.map (fun (lv, _) -> lv) calls | Ast.STMT_check (_, calls) -> Array.map (fun (lv, _) -> lv) calls
| _ -> [| |] | _ -> [| |]
in in

View file

@ -2141,10 +2141,12 @@ let trans_visitor
((*initializing*)_:bool) ((*initializing*)_:bool)
(dst:Ast.lval) (dst:Ast.lval)
(domain:Ast.domain) (domain:Ast.domain)
(name:string)
(fn_lval:Ast.lval) (fn_lval:Ast.lval)
(args:Ast.atom array) (args:Ast.atom array)
: unit = : unit =
let (task_cell, _) = trans_lval_init dst in let (task_cell, _) = trans_lval_init dst in
let runtime_name = trans_static_string name in
let (fptr_operand, fn_ty) = trans_callee fn_lval in let (fptr_operand, fn_ty) = trans_callee fn_lval in
(*let fn_ty_params = [| |] in*) (*let fn_ty_params = [| |] in*)
let _ = let _ =
@ -2178,7 +2180,7 @@ let trans_visitor
match domain with match domain with
Ast.DOMAIN_thread -> Ast.DOMAIN_thread ->
begin begin
trans_upcall "upcall_new_thread" new_task [| |]; trans_upcall "upcall_new_thread" new_task [| runtime_name |];
copy_fn_args false true (CLONE_all new_task) call; copy_fn_args false true (CLONE_all new_task) call;
trans_upcall "upcall_start_thread" task_cell trans_upcall "upcall_start_thread" task_cell
[| [|
@ -2190,7 +2192,7 @@ let trans_visitor
end end
| _ -> | _ ->
begin begin
trans_upcall "upcall_new_task" new_task [| |]; trans_upcall "upcall_new_task" new_task [| runtime_name |];
copy_fn_args false true (CLONE_chan new_task) call; copy_fn_args false true (CLONE_chan new_task) call;
trans_upcall "upcall_start_task" task_cell trans_upcall "upcall_start_task" task_cell
[| [|
@ -4529,8 +4531,9 @@ let trans_visitor
| Ast.STMT_send (chan,src) -> | Ast.STMT_send (chan,src) ->
trans_send chan src trans_send chan src
| Ast.STMT_spawn (dst, domain, plv, args) -> | Ast.STMT_spawn (dst, domain, name, plv, args) ->
trans_spawn (maybe_init stmt.id "spawn" dst) dst domain plv args trans_spawn (maybe_init stmt.id "spawn" dst) dst
domain name plv args
| Ast.STMT_recv (dst, chan) -> | Ast.STMT_recv (dst, chan) ->
trans_recv (maybe_init stmt.id "recv" dst) dst chan trans_recv (maybe_init stmt.id "recv" dst) dst chan

View file

@ -692,7 +692,7 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
and check_stmt (stmt:Ast.stmt) : unit = and check_stmt (stmt:Ast.stmt) : unit =
check_ret stmt; check_ret stmt;
match stmt.Common.node with match stmt.Common.node with
Ast.STMT_spawn (dst, _, callee, args) -> Ast.STMT_spawn (dst, _, _, callee, args) ->
infer_lval Ast.TY_task dst; infer_lval Ast.TY_task dst;
demand Ast.TY_nil (check_fn callee args) demand Ast.TY_nil (check_fn callee args)

View file

@ -664,7 +664,7 @@ let condition_assigning_visitor
let precond = Array.append dst_init src_init in let precond = Array.append dst_init src_init in
raise_pre_post_cond s.id precond; raise_pre_post_cond s.id precond;
| Ast.STMT_spawn (dst, _, lv, args) | Ast.STMT_spawn (dst, _, _, lv, args)
| Ast.STMT_call (dst, lv, args) -> | Ast.STMT_call (dst, lv, args) ->
raise_dst_init_precond_if_writing_through s.id dst; raise_dst_init_precond_if_writing_through s.id dst;
visit_callable_pre s.id (lval_slots cx dst) lv args visit_callable_pre s.id (lval_slots cx dst) lv args
@ -1350,7 +1350,7 @@ let lifecycle_visitor
match s.node with match s.node with
Ast.STMT_copy (lv_dst, _) Ast.STMT_copy (lv_dst, _)
| Ast.STMT_call (lv_dst, _, _) | Ast.STMT_call (lv_dst, _, _)
| Ast.STMT_spawn (lv_dst, _, _, _) | Ast.STMT_spawn (lv_dst, _, _, _, _)
| Ast.STMT_recv (lv_dst, _) | Ast.STMT_recv (lv_dst, _)
| Ast.STMT_bind (lv_dst, _, _) | Ast.STMT_bind (lv_dst, _, _)
| Ast.STMT_new_rec (lv_dst, _, _) | Ast.STMT_new_rec (lv_dst, _, _)

View file

@ -451,7 +451,7 @@ and walk_stmt
walk_lval v f; walk_lval v f;
Array.iter (walk_opt_atom v) az Array.iter (walk_opt_atom v) az
| Ast.STMT_spawn (dst,_,p,az) -> | Ast.STMT_spawn (dst,_,_,p,az) ->
walk_lval v dst; walk_lval v dst;
walk_lval v p; walk_lval v p;
Array.iter (walk_atom v) az Array.iter (walk_atom v) az

View file

@ -184,7 +184,7 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, char **argv)
int ret; int ret;
{ {
rust_srv srv; rust_srv srv;
rust_dom dom(&srv, crate); rust_dom dom(&srv, crate, "main");
command_line_args args(dom, argc, argv); command_line_args args(dom, argc, argv);
dom.log(rust_log::DOM, "startup: %d args", args.argc); dom.log(rust_log::DOM, "startup: %d args", args.argc);

View file

@ -7,11 +7,13 @@ template class ptr_vec<rust_task>;
// Keeps track of all live domains, for debugging purposes. // Keeps track of all live domains, for debugging purposes.
array_list<rust_dom*> _live_domains; array_list<rust_dom*> _live_domains;
rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate) : rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
const char *name) :
interrupt_flag(0), interrupt_flag(0),
root_crate(root_crate), root_crate(root_crate),
_log(srv, this), _log(srv, this),
srv(srv), srv(srv),
name(name),
running_tasks(this), running_tasks(this),
blocked_tasks(this), blocked_tasks(this),
dead_tasks(this), dead_tasks(this),
@ -27,7 +29,7 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate) :
pthread_attr_setstacksize(&attr, 1024 * 1024); pthread_attr_setstacksize(&attr, 1024 * 1024);
pthread_attr_setdetachstate(&attr, true); pthread_attr_setdetachstate(&attr, true);
#endif #endif
root_task = new (this) rust_task(this, NULL); root_task = new (this) rust_task(this, NULL, name);
if (_live_domains.replace(NULL, this) == false) { if (_live_domains.replace(NULL, this) == false) {
_live_domains.append(this); _live_domains.append(this);
@ -49,25 +51,25 @@ rust_dom::delete_proxies() {
rust_task *task; rust_task *task;
rust_proxy<rust_task> *task_proxy; rust_proxy<rust_task> *task_proxy;
while (_task_proxies.pop(&task, &task_proxy)) { while (_task_proxies.pop(&task, &task_proxy)) {
log(rust_log::TASK, "deleting proxy 0x%" PRIxPTR log(rust_log::TASK,
" in dom 0x%" PRIxPTR, "deleting proxy 0x%" PRIxPTR " in dom %s 0x%" PRIxPTR,
task_proxy, task_proxy->dom); task_proxy, task_proxy->dom->name, task_proxy->dom);
delete task_proxy; delete task_proxy;
} }
rust_port *port; rust_port *port;
rust_proxy<rust_port> *port_proxy; rust_proxy<rust_port> *port_proxy;
while (_port_proxies.pop(&port, &port_proxy)) { while (_port_proxies.pop(&port, &port_proxy)) {
log(rust_log::TASK, "deleting proxy 0x%" PRIxPTR log(rust_log::TASK,
" in dom 0x%" PRIxPTR, "deleting proxy 0x%" PRIxPTR " in dom %s 0x%" PRIxPTR,
port_proxy, port_proxy->dom); port_proxy, port_proxy->dom->name, port_proxy->dom);
delete port_proxy; delete port_proxy;
} }
} }
rust_dom::~rust_dom() { rust_dom::~rust_dom() {
log(rust_log::MEM | rust_log::DOM, log(rust_log::MEM | rust_log::DOM,
"~rust_dom 0x%" PRIxPTR, (uintptr_t)this); "~rust_dom %s @0x%" PRIxPTR, name, (uintptr_t)this);
log(rust_log::TASK, "deleting all proxies"); log(rust_log::TASK, "deleting all proxies");
delete_proxies(); delete_proxies();
@ -135,7 +137,8 @@ rust_dom::logptr(char const *msg, T* ptrval) {
void void
rust_dom::fail() { rust_dom::fail() {
log(rust_log::DOM, "domain 0x%" PRIxPTR " root task failed", this); log(rust_log::DOM, "domain %s @0x%" PRIxPTR " root task failed",
name, this);
I(this, rval == 0); I(this, rval == 0);
rval = 1; rval = 1;
} }
@ -144,8 +147,9 @@ void *
rust_dom::malloc(size_t sz) { rust_dom::malloc(size_t sz) {
void *p = srv->malloc(sz); void *p = srv->malloc(sz);
I(this, p); I(this, p);
log(rust_log::MEM, "0x%" PRIxPTR " rust_dom::malloc(%d) -> 0x%" PRIxPTR, log(rust_log::MEM,
(uintptr_t) this, sz, p); "%s @0x%" PRIxPTR " rust_dom::malloc(%d) -> 0x%" PRIxPTR,
name, (uintptr_t) this, sz, p);
return p; return p;
} }
@ -201,8 +205,8 @@ void
rust_dom::add_task_to_state_vec(ptr_vec<rust_task> *v, rust_task *task) rust_dom::add_task_to_state_vec(ptr_vec<rust_task> *v, rust_task *task)
{ {
log(rust_log::MEM|rust_log::TASK, log(rust_log::MEM|rust_log::TASK,
"adding task 0x%" PRIxPTR " in state '%s' to vec 0x%" PRIxPTR, "adding task %s @0x%" PRIxPTR " in state '%s' to vec 0x%" PRIxPTR,
(uintptr_t)task, state_vec_name(v), (uintptr_t)v); task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
v->push(task); v->push(task);
} }
@ -211,8 +215,8 @@ void
rust_dom::remove_task_from_state_vec(ptr_vec<rust_task> *v, rust_task *task) rust_dom::remove_task_from_state_vec(ptr_vec<rust_task> *v, rust_task *task)
{ {
log(rust_log::MEM|rust_log::TASK, log(rust_log::MEM|rust_log::TASK,
"removing task 0x%" PRIxPTR " in state '%s' from vec 0x%" PRIxPTR, "removing task %s @0x%" PRIxPTR " in state '%s' from vec 0x%" PRIxPTR,
(uintptr_t)task, state_vec_name(v), (uintptr_t)v); task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
I(this, (*v)[task->idx] == task); I(this, (*v)[task->idx] == task);
v->swap_delete(task); v->swap_delete(task);
} }
@ -239,7 +243,8 @@ rust_dom::reap_dead_tasks() {
I(this, task->tasks_waiting_to_join.is_empty()); I(this, task->tasks_waiting_to_join.is_empty());
dead_tasks.swap_delete(task); dead_tasks.swap_delete(task);
log(rust_log::TASK, log(rust_log::TASK,
"deleting unreferenced dead task 0x%" PRIxPTR, task); "deleting unreferenced dead task %s @0x%" PRIxPTR,
task->name, task);
delete task; delete task;
continue; continue;
} }
@ -282,7 +287,7 @@ rust_dom::get_task_proxy(rust_task *task) {
if (_task_proxies.get(task, &proxy)) { if (_task_proxies.get(task, &proxy)) {
return proxy; return proxy;
} }
log(rust_log::COMM, "no proxy for 0x%" PRIxPTR, task); log(rust_log::COMM, "no proxy for %s @0x%" PRIxPTR, task->name, task);
proxy = new (this) rust_proxy<rust_task> (this, task, false); proxy = new (this) rust_proxy<rust_task> (this, task, false);
_task_proxies.put(task, proxy); _task_proxies.put(task, proxy);
return proxy; return proxy;
@ -344,7 +349,8 @@ rust_dom::log_state() {
log(rust_log::TASK, "running tasks:"); log(rust_log::TASK, "running tasks:");
for (size_t i = 0; i < running_tasks.length(); i++) { for (size_t i = 0; i < running_tasks.length(); i++) {
log(rust_log::TASK, log(rust_log::TASK,
"\t task: 0x%" PRIxPTR, running_tasks[i]); "\t task: %s @0x%" PRIxPTR,
running_tasks[i]->name, running_tasks[i]);
} }
} }
@ -352,16 +358,18 @@ rust_dom::log_state() {
log(rust_log::TASK, "blocked tasks:"); log(rust_log::TASK, "blocked tasks:");
for (size_t i = 0; i < blocked_tasks.length(); i++) { for (size_t i = 0; i < blocked_tasks.length(); i++) {
log(rust_log::TASK, log(rust_log::TASK,
"\t task: 0x%" PRIxPTR ", blocked on: 0x%" PRIxPTR, "\t task: %s @0x%" PRIxPTR ", blocked on: 0x%" PRIxPTR,
blocked_tasks[i], blocked_tasks[i]->cond); blocked_tasks[i]->name, blocked_tasks[i],
blocked_tasks[i]->cond);
} }
} }
if (!dead_tasks.is_empty()) { if (!dead_tasks.is_empty()) {
log(rust_log::TASK, "dead tasks:"); log(rust_log::TASK, "dead tasks:");
for (size_t i = 0; i < dead_tasks.length(); i++) { for (size_t i = 0; i < dead_tasks.length(); i++) {
log(rust_log::TASK, "\t task: 0x%" PRIxPTR ", ref_count: %d", log(rust_log::TASK, "\t task: %s 0x%" PRIxPTR ", ref_count: %d",
dead_tasks[i], dead_tasks[i]->ref_count); dead_tasks[i], dead_tasks[i]->name,
dead_tasks[i]->ref_count);
} }
} }
} }
@ -378,7 +386,8 @@ rust_dom::start_main_loop()
// Make sure someone is watching, to pull us out of infinite loops. // Make sure someone is watching, to pull us out of infinite loops.
rust_timer timer(this); rust_timer timer(this);
log(rust_log::DOM, "running main-loop on domain 0x%" PRIxPTR, this); log(rust_log::DOM, "running main-loop on domain %s @0x%" PRIxPTR,
name, this);
logptr("exit-task glue", root_crate->get_exit_task_glue()); logptr("exit-task glue", root_crate->get_exit_task_glue());
while (n_live_tasks() > 0) { while (n_live_tasks() > 0) {
@ -405,22 +414,24 @@ rust_dom::start_main_loop()
I(this, scheduled_task->running()); I(this, scheduled_task->running());
log(rust_log::TASK, log(rust_log::TASK,
"activating task 0x%" PRIxPTR "activating task %s 0x%" PRIxPTR
", sp=0x%" PRIxPTR ", sp=0x%" PRIxPTR
", ref_count=%d" ", ref_count=%d"
", state: %s", ", state: %s",
(uintptr_t)scheduled_task, scheduled_task->name,
scheduled_task->rust_sp, (uintptr_t)scheduled_task,
scheduled_task->ref_count, scheduled_task->rust_sp,
scheduled_task->state_str()); scheduled_task->ref_count,
scheduled_task->state_str());
interrupt_flag = 0; interrupt_flag = 0;
activate(scheduled_task); activate(scheduled_task);
log(rust_log::TASK, log(rust_log::TASK,
"returned from task 0x%" PRIxPTR "returned from task %s @0x%" PRIxPTR
" in state '%s', sp=0x%" PRIxPTR, " in state '%s', sp=0x%" PRIxPTR,
scheduled_task->name,
(uintptr_t)scheduled_task, (uintptr_t)scheduled_task,
state_vec_name(scheduled_task->state), state_vec_name(scheduled_task->state),
scheduled_task->rust_sp); scheduled_task->rust_sp);

View file

@ -25,6 +25,7 @@ struct rust_dom
rust_crate const *root_crate; rust_crate const *root_crate;
rust_log _log; rust_log _log;
rust_srv *srv; rust_srv *srv;
const char *const name;
ptr_vec<rust_task> running_tasks; ptr_vec<rust_task> running_tasks;
ptr_vec<rust_task> blocked_tasks; ptr_vec<rust_task> blocked_tasks;
ptr_vec<rust_task> dead_tasks; ptr_vec<rust_task> dead_tasks;
@ -44,7 +45,9 @@ struct rust_dom
pthread_attr_t attr; pthread_attr_t attr;
#endif #endif
rust_dom(rust_srv *srv, rust_crate const *root_crate); // Only a pointer to 'name' is kept, so it must live as long as this
// domain.
rust_dom(rust_srv *srv, rust_crate const *root_crate, const char *name);
~rust_dom(); ~rust_dom();
void activate(rust_task *task); void activate(rust_task *task);

View file

@ -52,7 +52,7 @@ align_down(uintptr_t sp)
} }
rust_task::rust_task(rust_dom *dom, rust_task *spawner) : rust_task::rust_task(rust_dom *dom, rust_task *spawner, const char *name) :
maybe_proxy<rust_task>(this), maybe_proxy<rust_task>(this),
stk(new_stk(dom, 0)), stk(new_stk(dom, 0)),
runtime_sp(0), runtime_sp(0),
@ -60,6 +60,7 @@ rust_task::rust_task(rust_dom *dom, rust_task *spawner) :
gc_alloc_chain(0), gc_alloc_chain(0),
dom(dom), dom(dom),
cache(NULL), cache(NULL),
name(name),
state(&dom->running_tasks), state(&dom->running_tasks),
cond(NULL), cond(NULL),
supervisor(spawner), supervisor(spawner),
@ -77,8 +78,8 @@ rust_task::rust_task(rust_dom *dom, rust_task *spawner) :
rust_task::~rust_task() rust_task::~rust_task()
{ {
dom->log(rust_log::MEM|rust_log::TASK, dom->log(rust_log::MEM|rust_log::TASK,
"~rust_task 0x%" PRIxPTR ", refcnt=%d", "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
(uintptr_t)this, ref_count); name, (uintptr_t)this, ref_count);
/* /*
for (uintptr_t fp = get_fp(); fp; fp = get_previous_fp(fp)) { for (uintptr_t fp = get_fp(); fp; fp = get_previous_fp(fp)) {
@ -311,7 +312,7 @@ void
rust_task::yield(size_t nargs) rust_task::yield(size_t nargs)
{ {
log(rust_log::TASK, log(rust_log::TASK,
"task 0x%" PRIxPTR " yielding", this); "task %s @0x%" PRIxPTR " yielding", name, this);
run_after_return(nargs, dom->root_crate->get_yield_glue()); run_after_return(nargs, dom->root_crate->get_yield_glue());
} }
@ -331,7 +332,7 @@ rust_task::kill() {
// Note the distinction here: kill() is when you're in an upcall // Note the distinction here: kill() is when you're in an upcall
// from task A and want to force-fail task B, you do B->kill(). // from task A and want to force-fail task B, you do B->kill().
// If you want to fail yourself you do self->fail(upcall_nargs). // If you want to fail yourself you do self->fail(upcall_nargs).
log(rust_log::TASK, "killing task 0x%" PRIxPTR, this); log(rust_log::TASK, "killing task %s @0x%" PRIxPTR, name, this);
// Unblock the task so it can unwind. // Unblock the task so it can unwind.
unblock(); unblock();
@ -345,7 +346,7 @@ rust_task::kill() {
void void
rust_task::fail(size_t nargs) { rust_task::fail(size_t nargs) {
// See note in ::kill() regarding who should call this. // See note in ::kill() regarding who should call this.
dom->log(rust_log::TASK, "task 0x%" PRIxPTR " failing", this); dom->log(rust_log::TASK, "task %s @0x%" PRIxPTR " failing", name, this);
// Unblock the task so it can unwind. // Unblock the task so it can unwind.
unblock(); unblock();
if (this == dom->root_task) if (this == dom->root_task)
@ -353,9 +354,9 @@ rust_task::fail(size_t nargs) {
run_after_return(nargs, dom->root_crate->get_unwind_glue()); run_after_return(nargs, dom->root_crate->get_unwind_glue());
if (supervisor) { if (supervisor) {
dom->log(rust_log::TASK, dom->log(rust_log::TASK,
"task 0x%" PRIxPTR "task %s @0x%" PRIxPTR
" propagating failure to supervisor 0x%" PRIxPTR, " propagating failure to supervisor %s @0x%" PRIxPTR,
this, supervisor); name, this, supervisor->name, supervisor);
supervisor->kill(); supervisor->kill();
} }
} }
@ -364,7 +365,7 @@ void
rust_task::gc(size_t nargs) rust_task::gc(size_t nargs)
{ {
dom->log(rust_log::TASK|rust_log::MEM, dom->log(rust_log::TASK|rust_log::MEM,
"task 0x%" PRIxPTR " garbage collecting", this); "task %s @0x%" PRIxPTR " garbage collecting", name, this);
run_after_return(nargs, dom->root_crate->get_gc_glue()); run_after_return(nargs, dom->root_crate->get_gc_glue());
} }
@ -372,8 +373,9 @@ void
rust_task::unsupervise() rust_task::unsupervise()
{ {
dom->log(rust_log::TASK, dom->log(rust_log::TASK,
"task 0x%" PRIxPTR " disconnecting from supervisor 0x%" PRIxPTR, "task %s @0x%" PRIxPTR
this, supervisor); " disconnecting from supervisor %s @0x%" PRIxPTR,
name, this, supervisor->name, supervisor);
supervisor = NULL; supervisor = NULL;
} }
@ -474,8 +476,9 @@ rust_task::malloc(size_t sz, type_desc *td)
if (td) { if (td) {
gc_alloc *gcm = (gc_alloc*) mem; gc_alloc *gcm = (gc_alloc*) mem;
dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC, dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
"task 0x%" PRIxPTR " allocated %d GC bytes = 0x%" PRIxPTR, "task %s @0x%" PRIxPTR
(uintptr_t)this, sz, gcm); " allocated %d GC bytes = 0x%" PRIxPTR,
name, (uintptr_t)this, sz, gcm);
memset((void*) gcm, 0, sizeof(gc_alloc)); memset((void*) gcm, 0, sizeof(gc_alloc));
link_gc(gcm); link_gc(gcm);
gcm->ctrl_word = (uintptr_t)td; gcm->ctrl_word = (uintptr_t)td;
@ -494,8 +497,9 @@ rust_task::realloc(void *data, size_t sz, bool is_gc)
sz += sizeof(gc_alloc); sz += sizeof(gc_alloc);
gcm = (gc_alloc*) dom->realloc((void*)gcm, sz); gcm = (gc_alloc*) dom->realloc((void*)gcm, sz);
dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC, dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
"task 0x%" PRIxPTR " reallocated %d GC bytes = 0x%" PRIxPTR, "task %s @0x%" PRIxPTR
(uintptr_t)this, sz, gcm); " reallocated %d GC bytes = 0x%" PRIxPTR,
name, (uintptr_t)this, sz, gcm);
if (!gcm) if (!gcm)
return gcm; return gcm;
link_gc(gcm); link_gc(gcm);
@ -513,8 +517,8 @@ rust_task::free(void *p, bool is_gc)
gc_alloc *gcm = (gc_alloc*)(((char *)p) - sizeof(gc_alloc)); gc_alloc *gcm = (gc_alloc*)(((char *)p) - sizeof(gc_alloc));
unlink_gc(gcm); unlink_gc(gcm);
dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC, dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
"task 0x%" PRIxPTR " freeing GC memory = 0x%" PRIxPTR, "task %s @0x%" PRIxPTR " freeing GC memory = 0x%" PRIxPTR,
(uintptr_t)this, gcm); name, (uintptr_t)this, gcm);
dom->free(gcm); dom->free(gcm);
} else { } else {
dom->free(p); dom->free(p);
@ -531,7 +535,8 @@ rust_task::transition(ptr_vec<rust_task> *src, ptr_vec<rust_task> *dst)
{ {
I(dom, state == src); I(dom, state == src);
dom->log(rust_log::TASK, dom->log(rust_log::TASK,
"task 0x%" PRIxPTR " state change '%s' -> '%s'", "task %s @0x%" PRIxPTR " state change '%s' -> '%s'",
name,
(uintptr_t)this, (uintptr_t)this,
dom->state_vec_name(src), dom->state_vec_name(src),
dom->state_vec_name(dst)); dom->state_vec_name(dst));

View file

@ -21,6 +21,7 @@ rust_task : public maybe_proxy<rust_task>,
rust_crate_cache *cache; rust_crate_cache *cache;
// Fields known only to the runtime. // Fields known only to the runtime.
const char *const name;
ptr_vec<rust_task> *state; ptr_vec<rust_task> *state;
rust_cond *cond; rust_cond *cond;
rust_task *supervisor; // Parent-link for failure propagation. rust_task *supervisor; // Parent-link for failure propagation.
@ -41,8 +42,10 @@ rust_task : public maybe_proxy<rust_task>,
rust_alarm alarm; rust_alarm alarm;
// Only a pointer to 'name' is kept, so it must live as long as this task.
rust_task(rust_dom *dom, rust_task(rust_dom *dom,
rust_task *spawner); rust_task *spawner,
const char *name);
~rust_task(); ~rust_task();
void start(uintptr_t exit_task_glue, void start(uintptr_t exit_task_glue,

View file

@ -6,18 +6,20 @@
#define LOG_UPCALL_ENTRY(task) \ #define LOG_UPCALL_ENTRY(task) \
(task)->dom->get_log().reset_indent(0); \ (task)->dom->get_log().reset_indent(0); \
(task)->log(rust_log::UPCALL, \ (task)->log(rust_log::UPCALL, \
"> UPCALL %s - task: 0x%" PRIxPTR \ "> UPCALL %s - task: %s 0x%" PRIxPTR \
" retpc: x%" PRIxPTR \ " retpc: x%" PRIxPTR \
" ref_count: %d", \ " ref_count: %d", \
__FUNCTION__, \ __FUNCTION__, \
(task), __builtin_return_address(0), \ (task)->name, (task), \
__builtin_return_address(0), \
(task->ref_count)); \ (task->ref_count)); \
(task)->dom->get_log().indent(); (task)->dom->get_log().indent();
#else #else
#define LOG_UPCALL_ENTRY(task) \ #define LOG_UPCALL_ENTRY(task) \
(task)->dom->get_log().reset_indent(0); \ (task)->dom->get_log().reset_indent(0); \
(task)->log(rust_log::UPCALL, \ (task)->log(rust_log::UPCALL, \
"> UPCALL task: x%" PRIxPTR (task)); \ "> UPCALL task: %s @x%" PRIxPTR, \
(task)->name, (task)); \
(task)->dom->get_log().indent(); (task)->dom->get_log().indent();
#endif #endif
@ -70,8 +72,8 @@ upcall_new_port(rust_task *task, size_t unit_sz) {
LOG_UPCALL_ENTRY(task); LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom; rust_dom *dom = task->dom;
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM, task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
"upcall_new_port(task=0x%" PRIxPTR ", unit_sz=%d)", "upcall_new_port(task=0x%" PRIxPTR " (%s), unit_sz=%d)",
(uintptr_t) task, unit_sz); (uintptr_t) task, task->name, unit_sz);
return new (dom) rust_port(task, unit_sz); return new (dom) rust_port(task, unit_sz);
} }
@ -91,8 +93,9 @@ upcall_new_chan(rust_task *task, rust_port *port) {
LOG_UPCALL_ENTRY(task); LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom; rust_dom *dom = task->dom;
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM, task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
"upcall_new_chan(task=0x%" PRIxPTR ", port=0x%" PRIxPTR ")", "upcall_new_chan("
(uintptr_t) task, port); "task=0x%" PRIxPTR " (%s), port=0x%" PRIxPTR ")",
(uintptr_t) task, task->name, port);
I(dom, port); I(dom, port);
return new (dom) rust_chan(task, port); return new (dom) rust_chan(task, port);
} }
@ -175,11 +178,11 @@ extern "C" CDECL void upcall_yield(rust_task *task) {
extern "C" CDECL void extern "C" CDECL void
upcall_join(rust_task *task, maybe_proxy<rust_task> *target) { upcall_join(rust_task *task, maybe_proxy<rust_task> *target) {
LOG_UPCALL_ENTRY(task); LOG_UPCALL_ENTRY(task);
task->log(rust_log::UPCALL | rust_log::COMM,
"target: 0x%" PRIxPTR ", task: 0x%" PRIxPTR,
target, target->delegate());
rust_task *target_task = target->delegate(); rust_task *target_task = target->delegate();
task->log(rust_log::UPCALL | rust_log::COMM,
"target: 0x%" PRIxPTR ", task: %s @0x%" PRIxPTR,
target, target_task->name, target_task);
if (target->is_proxy()) { if (target->is_proxy()) {
notify_message:: notify_message::
send(notify_message::JOIN, "join", task, target->as_proxy()); send(notify_message::JOIN, "join", task, target->as_proxy());
@ -252,8 +255,8 @@ upcall_kill(rust_task *task, maybe_proxy<rust_task> *target) {
rust_task *target_task = target->delegate(); rust_task *target_task = target->delegate();
task->log(rust_log::UPCALL | rust_log::TASK, task->log(rust_log::UPCALL | rust_log::TASK,
"kill task 0x%" PRIxPTR ", ref count %d", "kill task %s @0x%" PRIxPTR ", ref count %d",
target_task, target_task->name, target_task,
target_task->ref_count); target_task->ref_count);
if (target->is_proxy()) { if (target->is_proxy()) {
@ -530,14 +533,14 @@ static void *rust_thread_start(void *ptr)
} }
extern "C" CDECL rust_task * extern "C" CDECL rust_task *
upcall_new_task(rust_task *spawner) { upcall_new_task(rust_task *spawner, const char *name) {
LOG_UPCALL_ENTRY(spawner); LOG_UPCALL_ENTRY(spawner);
rust_dom *dom = spawner->dom; rust_dom *dom = spawner->dom;
rust_task *task = new (dom) rust_task(dom, spawner); rust_task *task = new (dom) rust_task(dom, spawner, name);
dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK, dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
"upcall new_task(spawner 0x%" PRIxPTR ") = 0x%" PRIxPTR, "upcall new_task(spawner %s @0x%" PRIxPTR ", %s) = 0x%" PRIxPTR,
spawner, task); spawner->name, spawner, name, task);
return task; return task;
} }
@ -548,26 +551,27 @@ upcall_start_task(rust_task *spawner, rust_task *task,
rust_dom *dom = spawner->dom; rust_dom *dom = spawner->dom;
dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK, dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
"upcall start_task(task 0x%" PRIxPTR "upcall start_task(task %s @0x%" PRIxPTR
" exit_task_glue 0x%" PRIxPTR " exit_task_glue 0x%" PRIxPTR
", spawnee 0x%" PRIxPTR ", spawnee 0x%" PRIxPTR
", callsz %" PRIdPTR ")", task, exit_task_glue, spawnee_fn, ", callsz %" PRIdPTR ")", task->name, task, exit_task_glue,
callsz); spawnee_fn, callsz);
task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz); task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
return task; return task;
} }
extern "C" CDECL maybe_proxy<rust_task> * extern "C" CDECL maybe_proxy<rust_task> *
upcall_new_thread(rust_task *task) { upcall_new_thread(rust_task *task, const char *name) {
LOG_UPCALL_ENTRY(task); LOG_UPCALL_ENTRY(task);
rust_dom *old_dom = task->dom; rust_dom *old_dom = task->dom;
rust_dom *new_dom = new rust_dom(old_dom->srv->clone(), rust_dom *new_dom = new rust_dom(old_dom->srv->clone(),
old_dom->root_crate); old_dom->root_crate,
name);
task->log(rust_log::UPCALL | rust_log::MEM, task->log(rust_log::UPCALL | rust_log::MEM,
"upcall new_thread() = dom 0x%" PRIxPTR " task 0x%" PRIxPTR, "upcall new_thread(%s) = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
new_dom, new_dom->root_task); name, new_dom, new_dom->root_task);
rust_proxy<rust_task> *proxy = rust_proxy<rust_task> *proxy =
new (old_dom) rust_proxy<rust_task>(old_dom, new (old_dom) rust_proxy<rust_task>(old_dom,
new_dom->root_task, true); new_dom->root_task, true);