From 44bef5f2cb175769155d92ec65bd6b16e6708a1e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2011 13:38:20 -0700 Subject: [PATCH] Introduced task handles. This is the new way to refer to tasks in rust-land. Currently all they do is serve as a key to look up the old rust_task structure. Ideally they won't be ref counted, but baby steps. --- src/rt/memory_region.cpp | 2 +- src/rt/rust.cpp | 4 +++- src/rt/rust_builtin.cpp | 5 ++++- src/rt/rust_chan.cpp | 9 +++++---- src/rt/rust_internal.h | 2 ++ src/rt/rust_kernel.cpp | 26 ++++++++++++++++++++++++-- src/rt/rust_kernel.h | 8 ++++++-- src/rt/rust_scheduler.h | 3 --- src/rt/rust_task.cpp | 2 ++ src/rt/rust_task.h | 3 ++- src/rt/rust_upcall.cpp | 28 +++++++++++++++++----------- src/rt/test/rust_test_runtime.cpp | 3 ++- src/rt/util/hash_map.h | 1 + src/test/run-pass/task-comm-10.rs | 17 ++++++----------- 14 files changed, 75 insertions(+), 38 deletions(-) diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index 021375d8ef0..4ef3eb05ce1 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -4,7 +4,7 @@ // NB: please do not commit code with this uncommented. It's // hugely expensive and should only be used as a last resort. // -// #define TRACK_ALLOCATIONS +#define TRACK_ALLOCATIONS #define MAGIC 0xbadc0ffe diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 42deca7b2cd..a94eb6c1a24 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -93,7 +93,9 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) { rust_srv *srv = new rust_srv(env); rust_kernel *kernel = new rust_kernel(srv, env->num_sched_threads); - rust_task *root_task = kernel->create_task(NULL, "main"); + rust_task_id root_id = kernel->create_task(NULL, "main"); + rust_task *root_task = kernel->get_task_by_id(root_id); + I(kernel, root_task != NULL); rust_scheduler *sched = root_task->sched; command_line_args *args = new (kernel, "main command line args") diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 862373e07dd..7653bc35ee2 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -408,8 +408,11 @@ task_yield(rust_task *task) { } extern "C" CDECL intptr_t -task_join(rust_task *task, rust_task *join_task) { +task_join(rust_task *task, rust_task_id tid) { // If the other task is already dying, we don't have to wait for it. + rust_task *join_task = task->kernel->get_task_by_id(tid); + // FIXME: find task exit status and return that. + if(!join_task) return 0; join_task->lock.lock(); if (join_task->dead() == false) { join_task->tasks_waiting_to_join.push(task); diff --git a/src/rt/rust_chan.cpp b/src/rt/rust_chan.cpp index 045694eee61..12a199f685d 100644 --- a/src/rt/rust_chan.cpp +++ b/src/rt/rust_chan.cpp @@ -73,16 +73,17 @@ void rust_chan::disassociate() { * Attempt to send data to the associated port. */ void rust_chan::send(void *sptr) { - scoped_lock with(port->lock); - - buffer.enqueue(sptr); - if (!is_associated()) { W(kernel, is_associated(), "rust_chan::transmit with no associated port."); return; } + I(kernel, port != NULL); + scoped_lock with(port->lock); + + buffer.enqueue(sptr); + A(kernel, !buffer.is_empty(), "rust_chan::transmit with nothing to send."); diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 3ad9afa7fbf..798087a9d54 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -64,6 +64,8 @@ struct stk_seg; struct type_desc; struct frame_glue_fns; +typedef intptr_t rust_task_id; + #ifndef __i386__ #error "Target CPU not supported." #endif diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index 24db485dd9d..4197f5dea89 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -9,6 +9,7 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) : _region(srv, true), _log(srv, NULL), srv(srv), + max_id(0), num_threads(num_threads), rval(0), live_tasks(0), @@ -133,10 +134,31 @@ int rust_kernel::start_task_threads() return rval; } -rust_task * +rust_task_id rust_kernel::create_task(rust_task *spawner, const char *name) { rust_scheduler *thread = threads[rand(&rctx) % num_threads]; - return thread->create_task(spawner, name); + rust_task *t = thread->create_task(spawner, name); + { + scoped_lock with(_kernel_lock); + t->id = max_id++; + task_table.put(t->id, t); + } + return t->id; +} + +rust_task * +rust_kernel::get_task_by_id(rust_task_id id) { + scoped_lock with(_kernel_lock); + rust_task *task = NULL; + // get leaves task unchanged if not found. + task_table.get(id, &task); + return task; +} + +void +rust_kernel::release_task_id(rust_task_id id) { + scoped_lock with(_kernel_lock); + task_table.remove(id); } void rust_kernel::wakeup_schedulers() { diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index 45624765a8e..ff5b100445e 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -26,8 +26,10 @@ private: void create_schedulers(); void destroy_schedulers(); -public: + rust_task_id max_id; + hash_map task_table; +public: const size_t num_threads; int rval; @@ -56,7 +58,9 @@ public: void win32_require(LPCTSTR fn, BOOL ok); #endif - rust_task *create_task(rust_task *spawner, const char *name); + rust_task_id create_task(rust_task *spawner, const char *name); + rust_task *get_task_by_id(rust_task_id id); + void release_task_id(rust_task_id tid); }; #endif /* RUST_KERNEL_H */ diff --git a/src/rt/rust_scheduler.h b/src/rt/rust_scheduler.h index 87ee1f1b206..28669169512 100644 --- a/src/rt/rust_scheduler.h +++ b/src/rt/rust_scheduler.h @@ -51,9 +51,6 @@ struct rust_scheduler : public kernel_owned, rust_kernel *kernel; int32_t list_index; - hash_map _task_proxies; - hash_map _port_proxies; - const int id; lock_and_signal lock; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 37a5e64172e..fbee8896590 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -95,6 +95,8 @@ rust_task::~rust_task() DLOG(sched, task, "~rust_task %s @0x%" PRIxPTR ", refcnt=%d", name, (uintptr_t)this, ref_count); + kernel->release_task_id(id); + /* FIXME: tighten this up, there are some more assertions that hold at task-lifecycle events. */ I(sched, ref_count == 0); // || diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 66d03d19b62..be7a774db92 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -34,7 +34,6 @@ struct gc_alloc { } }; - struct rust_task : public kernel_owned, rust_cond { @@ -59,6 +58,8 @@ rust_task : public kernel_owned, rust_cond size_t gc_alloc_thresh; size_t gc_alloc_accum; + rust_task_id id; + // Keeps track of the last time this task yielded. timer yield_timer; diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 2190ec7b49f..5feffe600c3 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -140,9 +140,11 @@ void upcall_del_chan(rust_task *task, rust_chan *chan) { * has its own copy of the channel. */ extern "C" CDECL rust_chan * -upcall_clone_chan(rust_task *task, rust_task *target, +upcall_clone_chan(rust_task *task, rust_task_id tid, rust_chan *chan) { + // FIXME: This should be removed. LOG_UPCALL_ENTRY(task); + rust_task *target = task->kernel->get_task_by_id(tid); return chan->clone(target); } @@ -203,9 +205,9 @@ upcall_fail(rust_task *task, * Called whenever a task's ref count drops to zero. */ extern "C" CDECL void -upcall_kill(rust_task *task, rust_task *target) { +upcall_kill(rust_task *task, rust_task_id tid) { LOG_UPCALL_ENTRY(task); - + rust_task *target = task->kernel->get_task_by_id(tid); target->kill(); } @@ -322,9 +324,9 @@ upcall_new_str(rust_task *task, char const *s, size_t fill) { } extern "C" CDECL rust_str * -upcall_dup_str(rust_task *task, rust_task *target, rust_str *str) { +upcall_dup_str(rust_task *task, rust_task_id tid, rust_str *str) { LOG_UPCALL_ENTRY(task); - + rust_task *target = task->kernel->get_task_by_id(tid); return make_str(target, (char const *)str->data, str->fill); } @@ -482,27 +484,30 @@ upcall_get_type_desc(rust_task *task, return td; } -extern "C" CDECL rust_task * +extern "C" CDECL rust_task_id upcall_new_task(rust_task *spawner, rust_vec *name) { // name is a rust string structure. LOG_UPCALL_ENTRY(spawner); - rust_task *task = + rust_task_id tid = spawner->kernel->create_task(spawner, (const char *)name->data); + rust_task *task = spawner->kernel->get_task_by_id(tid); task->ref(); - return task; + return tid; } extern "C" CDECL void -upcall_take_task(rust_task *task, rust_task *target) { +upcall_take_task(rust_task *task, rust_task_id tid) { LOG_UPCALL_ENTRY(task); + rust_task *target = task->kernel->get_task_by_id(tid); if(target) { target->ref(); } } extern "C" CDECL void -upcall_drop_task(rust_task *task, rust_task *target) { +upcall_drop_task(rust_task *task, rust_task_id tid) { LOG_UPCALL_ENTRY(task); + rust_task *target = task->kernel->get_task_by_id(tid); if(target) { target->deref(); } @@ -526,13 +531,14 @@ upcall_drop_chan(rust_task *task, rust_chan *target) { extern "C" CDECL rust_task * upcall_start_task(rust_task *spawner, - rust_task *task, + rust_task_id tid, uintptr_t spawnee_fn, uintptr_t args, size_t args_sz) { LOG_UPCALL_ENTRY(spawner); rust_scheduler *sched = spawner->sched; + rust_task *task = spawner->kernel->get_task_by_id(tid); DLOG(sched, task, "upcall start_task(task %s @0x%" PRIxPTR ", spawnee 0x%" PRIxPTR ")", diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp index ad5a018eec8..520426eb256 100644 --- a/src/rt/test/rust_test_runtime.cpp +++ b/src/rt/test/rust_test_runtime.cpp @@ -45,7 +45,8 @@ void task_entry() { void rust_task_test::worker::run() { - rust_task *root_task = kernel->create_task(NULL, "main"); + rust_task_id root_id = kernel->create_task(NULL, "main"); + rust_task *root_task = kernel->get_task_by_id(root_id); root_task->start((uintptr_t)&task_entry, (uintptr_t)NULL); root_task->sched->start_main_loop(); } diff --git a/src/rt/util/hash_map.h b/src/rt/util/hash_map.h index 08d308370ed..0ff6ed190d3 100644 --- a/src/rt/util/hash_map.h +++ b/src/rt/util/hash_map.h @@ -1,3 +1,4 @@ +// -*- c++ -*- /** * A C++ wrapper around uthash. */ diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index cdd18478dbc..b1f825aa372 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -4,12 +4,11 @@ import std::comm; fn start(pcc: *u8) { let c = comm::chan_from_unsafe_ptr(pcc); - let p; + let p = comm::mk_port[str](); + c.send(p.mk_chan().unsafe_ptr()); let a; let b; - p = comm::mk_port[str](); - c.send(p.mk_chan().unsafe_ptr()); a = p.recv(); log_err a; b = p.recv(); @@ -17,15 +16,11 @@ fn start(pcc: *u8) { } fn main() { - let p : comm::_port[*u8]; - let child; + let p = comm::mk_port[*u8](); + let child = spawn start(p.mk_chan().unsafe_ptr()); - p = comm::mk_port(); - child = spawn start(p.mk_chan().unsafe_ptr()); - let pc; let c; - - pc = p.recv(); - c = comm::chan_from_unsafe_ptr(pc); + let pc = p.recv(); + let c = comm::chan_from_unsafe_ptr(pc); c.send("A"); c.send("B"); task::yield();