about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@gmail.com>2010-08-08 19:24:35 -0700
committerJeffrey Yasskin <jyasskin@gmail.com>2010-08-09 11:43:16 +0200
commitb71340552fa0caa870877f87a1273e8d4c91efe6 (patch)
treea1a1883cded2c8541a817d41d91c2002a926207b /src
parentdf75a968c56935cca1c1482a8703eca82c607c62 (diff)
downloadrust-b71340552fa0caa870877f87a1273e8d4c91efe6.tar.gz
rust-b71340552fa0caa870877f87a1273e8d4c91efe6.zip
Add names to tasks and domains. These can either be an explicit literal string
after the "spawn" keyword, or implicitly the call expression used to start the
spawn.
Diffstat (limited to 'src')
-rw-r--r--src/boot/fe/ast.ml5
-rw-r--r--src/boot/fe/pexp.ml29
-rw-r--r--src/boot/me/alias.ml2
-rw-r--r--src/boot/me/effect.ml2
-rw-r--r--src/boot/me/layout.ml2
-rw-r--r--src/boot/me/trans.ml11
-rw-r--r--src/boot/me/type.ml2
-rw-r--r--src/boot/me/typestate.ml4
-rw-r--r--src/boot/me/walk.ml2
-rw-r--r--src/rt/rust.cpp2
-rw-r--r--src/rt/rust_dom.cpp66
-rw-r--r--src/rt/rust_dom.h5
-rw-r--r--src/rt/rust_task.cpp43
-rw-r--r--src/rt/rust_task.h5
-rw-r--r--src/rt/rust_upcall.cpp50
15 files changed, 141 insertions, 89 deletions
diff --git a/src/boot/fe/ast.ml b/src/boot/fe/ast.ml
index efbd62ae202..8fc952a5150 100644
--- a/src/boot/fe/ast.ml
+++ b/src/boot/fe/ast.ml
@@ -199,7 +199,7 @@ and tup_input = (mutability * atom)
 and stmt' =
 
   (* 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_tup of (lval * (tup_input 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 ";"
           end
 
-      | STMT_spawn (dst, domain, fn, args) ->
+      | STMT_spawn (dst, domain, name, fn, args) ->
           fmt_lval ff dst;
           fmt ff " = spawn ";
           fmt_domain ff domain;
+          fmt_str ff ("\"" ^ name ^ "\"");
           fmt_lval ff fn;
           fmt_atoms ff args;
           fmt ff ";";
diff --git a/src/boot/fe/pexp.ml b/src/boot/fe/pexp.ml
index 3e17e0e49e7..75983c7f837 100644
--- a/src/boot/fe/pexp.ml
+++ b/src/boot/fe/pexp.ml
@@ -18,7 +18,7 @@ open Parser;;
 
 type pexp' =
     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_rec of ((Ast.ident * Ast.mutability * pexp) array * pexp option)
   | PEXP_tup of ((Ast.mutability * pexp) array)
@@ -558,9 +558,27 @@ and parse_bottom_pexp (ps:pstate) : pexp =
               THREAD -> bump ps; Ast.DOMAIN_thread
             | _ -> Ast.DOMAIN_local
         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
-          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 ->
         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
             ac [ fn_stmts; arg_stmts; [| bind_stmt |] ]
 
-      | PEXP_spawn (domain, sub) ->
+      | PEXP_spawn (domain, name, sub) ->
           begin
             match sub.node with
                 PEXP_call (fn, args) ->
@@ -1191,7 +1209,8 @@ and desugar_expr_init
                   let (arg_stmts, arg_atoms) = desugar_expr_atoms ps args in
                   let fn_lval = atom_lval ps fn_atom in
                   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
                     ac [ fn_stmts; arg_stmts; [| spawn_stmt |] ]
               | _ -> raise (err "non-call spawn" ps)
diff --git a/src/boot/me/alias.ml b/src/boot/me/alias.ml
index 94d34fb2df0..27575324171 100644
--- a/src/boot/me/alias.ml
+++ b/src/boot/me/alias.ml
@@ -59,7 +59,7 @@ let alias_analysis_visitor
              * survive 'into' a sub-block (those formed during iteration)
              * need to be handled in this module.  *)
             Ast.STMT_call (dst, callee, args)
-          | Ast.STMT_spawn (dst, _, callee, args)
+          | Ast.STMT_spawn (dst, _, _, callee, args)
             -> alias_call_args dst callee args
 
           | Ast.STMT_send (_, src) -> alias src
diff --git a/src/boot/me/effect.ml b/src/boot/me/effect.ml
index 79868defa41..73797409d31 100644
--- a/src/boot/me/effect.ml
+++ b/src/boot/me/effect.ml
@@ -62,7 +62,7 @@ let mutability_checking_visitor
       match s.node with
             Ast.STMT_copy (lv_dst, _)
           | Ast.STMT_call (lv_dst, _, _)
-          | Ast.STMT_spawn (lv_dst, _, _, _)
+          | Ast.STMT_spawn (lv_dst, _, _, _, _)
           | Ast.STMT_recv (lv_dst, _)
           | Ast.STMT_bind (lv_dst, _, _)
           | Ast.STMT_new_rec (lv_dst, _, _)
diff --git a/src/boot/me/layout.ml b/src/boot/me/layout.ml
index a9358795ed3..1df37f0f9e2 100644
--- a/src/boot/me/layout.ml
+++ b/src/boot/me/layout.ml
@@ -400,7 +400,7 @@ let layout_visitor
       let callees =
         match s.node with
             Ast.STMT_call (_, lv, _)
-          | Ast.STMT_spawn (_, _, lv, _) -> [| lv |]
+          | Ast.STMT_spawn (_, _, _, lv, _) -> [| lv |]
           | Ast.STMT_check (_, calls) -> Array.map (fun (lv, _) -> lv) calls
           | _ -> [| |]
       in
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index b708bb268ff..01a89c56588 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -2128,10 +2128,12 @@ let trans_visitor
       ((*initializing*)_:bool)
       (dst:Ast.lval)
       (domain:Ast.domain)
+      (name:string)
       (fn_lval:Ast.lval)
       (args:Ast.atom array)
       : unit =
     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 fn_ty_params = [| |] in*)
     let _ =
@@ -2165,7 +2167,7 @@ let trans_visitor
         match domain with
             Ast.DOMAIN_thread ->
               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;
                 trans_upcall "upcall_start_thread" task_cell
                   [|
@@ -2177,7 +2179,7 @@ let trans_visitor
             end
          | _ ->
              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;
                  trans_upcall "upcall_start_task" task_cell
                    [|
@@ -4496,8 +4498,9 @@ let trans_visitor
       | Ast.STMT_send (chan,src) ->
           trans_send chan src
 
-      | Ast.STMT_spawn (dst, domain, plv, args) ->
-          trans_spawn (maybe_init stmt.id "spawn" dst) dst domain plv args
+      | Ast.STMT_spawn (dst, domain, name, plv, args) ->
+          trans_spawn (maybe_init stmt.id "spawn" dst) dst
+            domain name plv args
 
       | Ast.STMT_recv (dst, chan) ->
           trans_recv (maybe_init stmt.id "recv" dst) dst chan
diff --git a/src/boot/me/type.ml b/src/boot/me/type.ml
index 23210ea1ff8..b2d5a6221d0 100644
--- a/src/boot/me/type.ml
+++ b/src/boot/me/type.ml
@@ -692,7 +692,7 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
     and check_stmt (stmt:Ast.stmt) : unit =
       check_ret stmt;
       match stmt.Common.node with
-          Ast.STMT_spawn (dst, _, callee, args) ->
+          Ast.STMT_spawn (dst, _, _, callee, args) ->
             infer_lval Ast.TY_task dst;
             demand Ast.TY_nil (check_fn callee args)
 
diff --git a/src/boot/me/typestate.ml b/src/boot/me/typestate.ml
index baf4a54398c..207029909de 100644
--- a/src/boot/me/typestate.ml
+++ b/src/boot/me/typestate.ml
@@ -664,7 +664,7 @@ let condition_assigning_visitor
             let precond = Array.append dst_init src_init in
               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) ->
             raise_dst_init_precond_if_writing_through s.id dst;
             visit_callable_pre s.id (lval_slots cx dst) lv args
@@ -1350,7 +1350,7 @@ let lifecycle_visitor
         match s.node with
             Ast.STMT_copy (lv_dst, _)
           | Ast.STMT_call (lv_dst, _, _)
-          | Ast.STMT_spawn (lv_dst, _, _, _)
+          | Ast.STMT_spawn (lv_dst, _, _, _, _)
           | Ast.STMT_recv (lv_dst, _)
           | Ast.STMT_bind (lv_dst, _, _)
           | Ast.STMT_new_rec (lv_dst, _, _)
diff --git a/src/boot/me/walk.ml b/src/boot/me/walk.ml
index 0e65406aec3..cadfd66b967 100644
--- a/src/boot/me/walk.ml
+++ b/src/boot/me/walk.ml
@@ -451,7 +451,7 @@ and walk_stmt
           walk_lval v f;
           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 p;
           Array.iter (walk_atom v) az
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 9cc2fe4188a..82a19cbcd84 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -182,7 +182,7 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, char **argv)
     int ret;
     {
         rust_srv srv;
-        rust_dom dom(&srv, crate);
+        rust_dom dom(&srv, crate, "main");
         command_line_args args(dom, argc, argv);
 
         dom.log(rust_log::DOM, "startup: %d args", args.argc);
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index 99aaddb2b15..004a10275e4 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -5,11 +5,13 @@
 template class ptr_vec<rust_task>;
 
 
-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),
     root_crate(root_crate),
     _log(srv, this),
     srv(srv),
+    name(name),
     running_tasks(this),
     blocked_tasks(this),
     dead_tasks(this),
@@ -25,7 +27,7 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate) :
     pthread_attr_setstacksize(&attr, 1024 * 1024);
     pthread_attr_setdetachstate(&attr, true);
 #endif
-    root_task = new (this) rust_task(this, NULL);
+    root_task = new (this) rust_task(this, NULL, name);
 }
 
 static void
@@ -42,23 +44,25 @@ rust_dom::delete_proxies() {
     rust_task *task;
     rust_proxy<rust_task> *task_proxy;
     while (_task_proxies.pop(&task, &task_proxy)) {
-        log(rust_log::TASK, "deleting proxy %" PRIxPTR
-                            " in dom %" PRIxPTR, task_proxy, task_proxy->dom);
+        log(rust_log::TASK,
+            "deleting proxy %" PRIxPTR " in dom %s @0x%" PRIxPTR,
+            task_proxy, task_proxy->dom->name, task_proxy->dom);
         delete task_proxy;
     }
 
     rust_port *port;
     rust_proxy<rust_port> *port_proxy;
     while (_port_proxies.pop(&port, &port_proxy)) {
-        log(rust_log::TASK, "deleting proxy %" PRIxPTR
-                            " in dom %" PRIxPTR, port_proxy, port_proxy->dom);
+        log(rust_log::TASK,
+            "deleting proxy %" PRIxPTR " in dom %s @0x%" PRIxPTR,
+            port_proxy, port_proxy->dom->name, port_proxy->dom);
         delete port_proxy;
     }
 }
 
 rust_dom::~rust_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");
     delete_proxies();
@@ -124,7 +128,8 @@ rust_dom::logptr(char const *msg, T* ptrval) {
 
 void
 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);
     rval = 1;
 }
@@ -133,8 +138,9 @@ void *
 rust_dom::malloc(size_t sz) {
     void *p = srv->malloc(sz);
     I(this, p);
-    log(rust_log::MEM, "0x%" PRIxPTR " rust_dom::malloc(%d) -> 0x%" PRIxPTR,
-        (uintptr_t) this, sz, p);
+    log(rust_log::MEM,
+        "%s @0x%" PRIxPTR " rust_dom::malloc(%d) -> 0x%" PRIxPTR,
+        name, (uintptr_t) this, sz, p);
     return p;
 }
 
@@ -190,8 +196,8 @@ void
 rust_dom::add_task_to_state_vec(ptr_vec<rust_task> *v, rust_task *task)
 {
     log(rust_log::MEM|rust_log::TASK,
-        "adding task 0x%" PRIxPTR " in state '%s' to vec 0x%" PRIxPTR,
-        (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
+        "adding task %s @0x%" PRIxPTR " in state '%s' to vec 0x%" PRIxPTR,
+        task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
     v->push(task);
 }
 
@@ -200,8 +206,8 @@ void
 rust_dom::remove_task_from_state_vec(ptr_vec<rust_task> *v, rust_task *task)
 {
     log(rust_log::MEM|rust_log::TASK,
-        "removing task 0x%" PRIxPTR " in state '%s' from vec 0x%" PRIxPTR,
-        (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
+        "removing task %s @0x%" PRIxPTR " in state '%s' from vec 0x%" PRIxPTR,
+        task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
     I(this, (*v)[task->idx] == task);
     v->swap_delete(task);
 }
@@ -229,7 +235,8 @@ rust_dom::reap_dead_tasks() {
 
             dead_tasks.swap_delete(task);
             log(rust_log::TASK,
-                "deleting unreferenced dead task 0x%" PRIxPTR, task);
+                "deleting unreferenced dead task %s @0x%" PRIxPTR,
+                task->name, task);
             delete task;
             continue;
         }
@@ -272,7 +279,7 @@ rust_dom::get_task_proxy(rust_task *task) {
     if (_task_proxies.get(task, &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);
     _task_proxies.put(task, proxy);
     return proxy;
@@ -327,7 +334,8 @@ rust_dom::log_state() {
         log(rust_log::TASK, "running tasks:");
         for (size_t i = 0; i < running_tasks.length(); i++) {
             log(rust_log::TASK,
-                "\t task: 0x%" PRIxPTR, running_tasks[i]);
+                "\t task: %s @0x%" PRIxPTR,
+                running_tasks[i]->name, running_tasks[i]);
         }
     }
 
@@ -335,15 +343,17 @@ rust_dom::log_state() {
         log(rust_log::TASK, "blocked tasks:");
         for (size_t i = 0; i < blocked_tasks.length(); i++) {
             log(rust_log::TASK,
-                "\t task: 0x%" PRIxPTR ", blocked on: 0x%" PRIxPTR,
-                blocked_tasks[i], blocked_tasks[i]->cond);
+                "\t task: %s @0x%" PRIxPTR ", blocked on: 0x%" PRIxPTR,
+                blocked_tasks[i]->name, blocked_tasks[i],
+                blocked_tasks[i]->cond);
         }
     }
 
     if (!dead_tasks.is_empty()) {
         log(rust_log::TASK, "dead tasks:");
         for (size_t i = 0; i < dead_tasks.length(); i++) {
-            log(rust_log::TASK, "\t task: 0x%" PRIxPTR, dead_tasks[i]);
+            log(rust_log::TASK, "\t task: %s @0x%" PRIxPTR,
+                dead_tasks[i]->name, dead_tasks[i]);
         }
     }
 }
@@ -360,7 +370,8 @@ rust_dom::start_main_loop()
     // Make sure someone is watching, to pull us out of infinite loops.
     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());
 
     while (n_live_tasks() > 0) {
@@ -386,16 +397,18 @@ rust_dom::start_main_loop()
         I(this, scheduled_task->running());
 
         log(rust_log::TASK,
-                 "activating task 0x%" PRIxPTR ", sp=0x%" PRIxPTR,
-                 (uintptr_t)scheduled_task, scheduled_task->rust_sp);
+                 "activating task %s @0x%" PRIxPTR ", sp=0x%" PRIxPTR,
+            scheduled_task->name, (uintptr_t)scheduled_task,
+            scheduled_task->rust_sp);
 
         interrupt_flag = 0;
 
         activate(scheduled_task);
 
         log(rust_log::TASK,
-                 "returned from task 0x%" PRIxPTR
+                 "returned from task %s @0x%" PRIxPTR
                  " in state '%s', sp=0x%" PRIxPTR,
+                 scheduled_task->name,
                  (uintptr_t)scheduled_task,
                  state_vec_name(scheduled_task->state),
                  scheduled_task->rust_sp);
@@ -417,8 +430,9 @@ rust_dom::start_main_loop()
         if (_log.is_tracing(rust_log::DOM)) {
             for (size_t i = 0; i < dead_tasks.length(); i++) {
                 log(rust_log::DOM,
-                    "task: 0x%" PRIxPTR ", index: %d, ref_count: %d",
-                    dead_tasks[i], i, dead_tasks[i]->ref_count);
+                    "task: %s @0x%" PRIxPTR ", index: %d, ref_count: %d",
+                    dead_tasks[i]->name, dead_tasks[i], i,
+                    dead_tasks[i]->ref_count);
             }
         }
 
diff --git a/src/rt/rust_dom.h b/src/rt/rust_dom.h
index 528790d56cc..abf10cefe00 100644
--- a/src/rt/rust_dom.h
+++ b/src/rt/rust_dom.h
@@ -25,6 +25,7 @@ struct rust_dom
     rust_crate const *root_crate;
     rust_log _log;
     rust_srv *srv;
+    const char *const name;
     ptr_vec<rust_task> running_tasks;
     ptr_vec<rust_task> blocked_tasks;
     ptr_vec<rust_task> dead_tasks;
@@ -47,7 +48,9 @@ struct rust_dom
     pthread_attr_t attr;
 #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();
 
     void activate(rust_task *task);
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 9f4fa611a95..279850cb0f8 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -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),
     stk(new_stk(dom, 0)),
     runtime_sp(0),
@@ -60,6 +60,7 @@ rust_task::rust_task(rust_dom *dom, rust_task *spawner) :
     gc_alloc_chain(0),
     dom(dom),
     cache(NULL),
+    name(name),
     state(&dom->running_tasks),
     cond(NULL),
     supervisor(spawner),
@@ -77,8 +78,8 @@ rust_task::rust_task(rust_dom *dom, rust_task *spawner) :
 rust_task::~rust_task()
 {
     dom->log(rust_log::MEM|rust_log::TASK,
-             "~rust_task 0x%" PRIxPTR ", refcnt=%d",
-             (uintptr_t)this, ref_count);
+             "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
+             name, (uintptr_t)this, ref_count);
 
     /*
       for (uintptr_t fp = get_fp(); fp; fp = get_previous_fp(fp)) {
@@ -311,7 +312,7 @@ void
 rust_task::yield(size_t nargs)
 {
     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());
 }
 
@@ -326,7 +327,7 @@ rust_task::kill() {
     // 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().
     // 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();
 
@@ -339,7 +340,7 @@ rust_task::kill() {
 void
 rust_task::fail(size_t nargs) {
     // 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();
     if (this == dom->root_task)
@@ -347,9 +348,9 @@ rust_task::fail(size_t nargs) {
     run_after_return(nargs, dom->root_crate->get_unwind_glue());
     if (supervisor) {
         dom->log(rust_log::TASK,
-                 "task 0x%" PRIxPTR
-                 " propagating failure to supervisor 0x%" PRIxPTR,
-                 this, supervisor);
+                 "task %s @0x%" PRIxPTR
+                 " propagating failure to supervisor %s @0x%" PRIxPTR,
+                 name, this, supervisor->name, supervisor);
         supervisor->kill();
     }
 }
@@ -358,7 +359,7 @@ void
 rust_task::gc(size_t nargs)
 {
     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());
 }
 
@@ -366,8 +367,9 @@ void
 rust_task::unsupervise()
 {
     dom->log(rust_log::TASK,
-             "task 0x%" PRIxPTR " disconnecting from supervisor 0x%" PRIxPTR,
-             this, supervisor);
+             "task %s @0x%" PRIxPTR
+             " disconnecting from supervisor %s @0x%" PRIxPTR,
+             name, this, supervisor->name, supervisor);
     supervisor = NULL;
 }
 
@@ -468,8 +470,9 @@ rust_task::malloc(size_t sz, type_desc *td)
     if (td) {
         gc_alloc *gcm = (gc_alloc*) mem;
         dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
-                 "task 0x%" PRIxPTR " allocated %d GC bytes = 0x%" PRIxPTR,
-                 (uintptr_t)this, sz, gcm);
+                 "task %s @0x%" PRIxPTR
+                 " allocated %d GC bytes = 0x%" PRIxPTR,
+                 name, (uintptr_t)this, sz, gcm);
         memset((void*) gcm, 0, sizeof(gc_alloc));
         link_gc(gcm);
         gcm->ctrl_word = (uintptr_t)td;
@@ -488,8 +491,9 @@ rust_task::realloc(void *data, size_t sz, bool is_gc)
         sz += sizeof(gc_alloc);
         gcm = (gc_alloc*) dom->realloc((void*)gcm, sz);
         dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
-                 "task 0x%" PRIxPTR " reallocated %d GC bytes = 0x%" PRIxPTR,
-                 (uintptr_t)this, sz, gcm);
+                 "task %s @0x%" PRIxPTR
+                 " reallocated %d GC bytes = 0x%" PRIxPTR,
+                 name, (uintptr_t)this, sz, gcm);
         if (!gcm)
             return gcm;
         link_gc(gcm);
@@ -507,8 +511,8 @@ rust_task::free(void *p, bool is_gc)
         gc_alloc *gcm = (gc_alloc*)(((char *)p) - sizeof(gc_alloc));
         unlink_gc(gcm);
         dom->log(rust_log::TASK|rust_log::MEM|rust_log::GC,
-                 "task 0x%" PRIxPTR " freeing GC memory = 0x%" PRIxPTR,
-                 (uintptr_t)this, gcm);
+                 "task %s @0x%" PRIxPTR " freeing GC memory = 0x%" PRIxPTR,
+                 name, (uintptr_t)this, gcm);
         dom->free(gcm);
     } else {
         dom->free(p);
@@ -521,7 +525,8 @@ rust_task::transition(ptr_vec<rust_task> *src, ptr_vec<rust_task> *dst)
 {
     I(dom, state == src);
     dom->log(rust_log::TASK,
-             "task 0x%" PRIxPTR " state change '%s' -> '%s'",
+             "task %s @0x%" PRIxPTR " state change '%s' -> '%s'",
+             name,
              (uintptr_t)this,
              dom->state_vec_name(src),
              dom->state_vec_name(dst));
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index b657592a5ef..27495e2c1ad 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -21,6 +21,7 @@ rust_task : public maybe_proxy<rust_task>,
     rust_crate_cache *cache;
 
     // Fields known only to the runtime.
+    const char *const name;
     ptr_vec<rust_task> *state;
     rust_cond *cond;
     rust_task *supervisor;     // Parent-link for failure propagation.
@@ -41,8 +42,10 @@ rust_task : public maybe_proxy<rust_task>,
 
     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 *spawner);
+              rust_task *spawner,
+              const char *name);
     ~rust_task();
 
     void start(uintptr_t exit_task_glue,
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 574cb703a1f..b0757e29e42 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -6,16 +6,18 @@
 #define LOG_UPCALL_ENTRY(task)                              \
     (task)->dom->get_log().reset_indent(0);                 \
     (task)->log(rust_log::UPCALL,                           \
-                "> UPCALL %s - task: 0x%" PRIxPTR           \
+                "> UPCALL %s - task: %s @0x%" PRIxPTR       \
                 " retpc: x%" PRIxPTR,                       \
                 __FUNCTION__,                               \
-                (task), __builtin_return_address(0));       \
+                (task)->name, (task),                       \
+                __builtin_return_address(0));               \
     (task)->dom->get_log().indent();
 #else
 #define LOG_UPCALL_ENTRY(task)                              \
     (task)->dom->get_log().reset_indent(0);                 \
     (task)->log(rust_log::UPCALL,                           \
-                "> UPCALL task: x%" PRIxPTR (task));        \
+                "> UPCALL task: %s @x%" PRIxPTR,            \
+                (task)->name, (task));                      \
     (task)->dom->get_log().indent();
 #endif
 
@@ -55,8 +57,8 @@ upcall_new_port(rust_task *task, size_t unit_sz) {
     LOG_UPCALL_ENTRY(task);
     rust_dom *dom = task->dom;
     task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
-              "upcall_new_port(task=0x%" PRIxPTR ", unit_sz=%d)",
-              (uintptr_t) task, unit_sz);
+              "upcall_new_port(task=0x%" PRIxPTR " (%s), unit_sz=%d)",
+              (uintptr_t) task, task->name, unit_sz);
     return new (dom) rust_port(task, unit_sz);
 }
 
@@ -76,8 +78,9 @@ upcall_new_chan(rust_task *task, rust_port *port) {
     LOG_UPCALL_ENTRY(task);
     rust_dom *dom = task->dom;
     task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
-              "upcall_new_chan(task=0x%" PRIxPTR ", port=0x%" PRIxPTR ")",
-              (uintptr_t) task, port);
+              "upcall_new_chan("
+              "task=0x%" PRIxPTR " (%s), port=0x%" PRIxPTR ")",
+              (uintptr_t) task, task->name, port);
     I(dom, port);
     return new (dom) rust_chan(task, port);
 }
@@ -136,11 +139,11 @@ extern "C" CDECL void upcall_yield(rust_task *task) {
 extern "C" CDECL void
 upcall_join(rust_task *task, maybe_proxy<rust_task> *target) {
     LOG_UPCALL_ENTRY(task);
+    rust_task *target_task = target->delegate();
     task->log(rust_log::UPCALL | rust_log::COMM,
-              "target: 0x%" PRIxPTR ", task: 0x%" PRIxPTR,
-              target, target->delegate());
+              "target: 0x%" PRIxPTR ", task: %s @0x%" PRIxPTR,
+              target, target_task->name, target_task);
 
-    rust_task *target_task = target->delegate();
     if (target->is_proxy()) {
         notify_message::
         send(notify_message::JOIN, "join", task, target->as_proxy());
@@ -222,8 +225,8 @@ upcall_kill(rust_task *task, maybe_proxy<rust_task> *target) {
     rust_task *target_task = target->delegate();
 
     task->log(rust_log::UPCALL | rust_log::TASK,
-              "kill task 0x%" PRIxPTR ", ref count %d",
-              target_task,
+              "kill task %s @0x%" PRIxPTR ", ref count %d",
+              target_task->name, target_task,
               target_task->ref_count);
 
     if (target->is_proxy()) {
@@ -498,14 +501,14 @@ static void *rust_thread_start(void *ptr)
 }
 
 extern "C" CDECL rust_task *
-upcall_new_task(rust_task *spawner) {
+upcall_new_task(rust_task *spawner, const char *name) {
     LOG_UPCALL_ENTRY(spawner);
 
     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,
-             "upcall new_task(spawner 0x%" PRIxPTR ") = 0x%" PRIxPTR,
-             spawner, task);
+             "upcall new_task(spawner %s @0x%" PRIxPTR ", %s) = 0x%" PRIxPTR,
+             spawner->name, spawner, name, task);
     return task;
 }
 
@@ -516,26 +519,27 @@ upcall_start_task(rust_task *spawner, rust_task *task,
 
     rust_dom *dom = spawner->dom;
     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
              ", spawnee 0x%" PRIxPTR
-             ", callsz %" PRIdPTR ")", task, exit_task_glue, spawnee_fn,
-             callsz);
+             ", callsz %" PRIdPTR ")", task->name, task, exit_task_glue,
+             spawnee_fn, callsz);
     task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
     return 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);
 
     rust_dom *old_dom = task->dom;
     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,
-              "upcall new_thread() = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
-              new_dom, new_dom->root_task);
+              "upcall new_thread(%s) = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
+              name, new_dom, new_dom->root_task);
     rust_proxy<rust_task> *proxy =
         new (old_dom) rust_proxy<rust_task>(old_dom,
                                             new_dom->root_task, true);