about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorunknown <Eric@.(none)>2011-08-08 13:38:20 -0700
committerEric Holk <eholk@mozilla.com>2011-08-08 16:55:38 -0700
commit44bef5f2cb175769155d92ec65bd6b16e6708a1e (patch)
treed7524b51e2af0cb191cd93cda3f282ac4ac8f4c6 /src/rt
parentf4f057ced1f4152575571a6e5116e1ad5bb38beb (diff)
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.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/memory_region.cpp2
-rw-r--r--src/rt/rust.cpp4
-rw-r--r--src/rt/rust_builtin.cpp5
-rw-r--r--src/rt/rust_chan.cpp9
-rw-r--r--src/rt/rust_internal.h2
-rw-r--r--src/rt/rust_kernel.cpp26
-rw-r--r--src/rt/rust_kernel.h8
-rw-r--r--src/rt/rust_scheduler.h3
-rw-r--r--src/rt/rust_task.cpp2
-rw-r--r--src/rt/rust_task.h3
-rw-r--r--src/rt/rust_upcall.cpp28
-rw-r--r--src/rt/test/rust_test_runtime.cpp3
-rw-r--r--src/rt/util/hash_map.h1
13 files changed, 69 insertions, 27 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<rust_task_id, rust_task *> 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_scheduler>,
     rust_kernel *kernel;
     int32_t list_index;
 
-    hash_map<rust_task *, rust_task *> _task_proxies;
-    hash_map<rust_port *, rust_port *> _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_task>, rust_cond
 {
@@ -59,6 +58,8 @@ rust_task : public kernel_owned<rust_task>, 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.
  */