about summary refs log tree commit diff
path: root/src/rt/rust_kernel.cpp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-04-06 17:03:00 -0700
committerBrian Anderson <banderson@mozilla.com>2012-04-07 19:56:41 -0700
commit01dc4a8b26d722d306a00e44a5b1ed5cf3fd24b1 (patch)
tree7bebe6c918cd108943cd8d07b0203b25256d063f /src/rt/rust_kernel.cpp
parenta6e748a1d9795f59f9ca954dbf1ad82d238c3990 (diff)
downloadrust-01dc4a8b26d722d306a00e44a5b1ed5cf3fd24b1.tar.gz
rust-01dc4a8b26d722d306a00e44a5b1ed5cf3fd24b1.zip
core: Add priv::weaken_task
Diffstat (limited to 'src/rt/rust_kernel.cpp')
-rw-r--r--src/rt/rust_kernel.cpp81
1 files changed, 80 insertions, 1 deletions
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index ff6b0e1056c..21422646f0d 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -1,11 +1,11 @@
 
 
-
 #include "rust_kernel.h"
 #include "rust_port.h"
 #include "rust_util.h"
 #include "rust_scheduler.h"
 #include "rust_sched_launcher.h"
+#include <algorithm>
 
 #define KLOG_(...)                              \
     KLOG(this, kern, __VA_ARGS__)
@@ -21,6 +21,7 @@ rust_kernel::rust_kernel(rust_env *env) :
     max_sched_id(0),
     sched_reaper(this),
     osmain_driver(NULL),
+    non_weak_tasks(0),
     env(env)
 {
     // Create the single threaded scheduler that will run on the platform's
@@ -286,6 +287,84 @@ rust_kernel::set_exit_status(int code) {
     }
 }
 
+void
+rust_kernel::register_task() {
+    KLOG_("Registering task");
+    uintptr_t new_non_weak_tasks = sync::increment(non_weak_tasks);
+    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+}
+
+void
+rust_kernel::unregister_task() {
+    KLOG_("Unregistering task");
+    uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
+    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+    if (new_non_weak_tasks == 0) {
+        end_weak_tasks();
+    }
+}
+
+void
+rust_kernel::weaken_task(rust_port_id chan) {
+    {
+        scoped_lock with(weak_task_lock);
+        KLOG_("Weakening task with channel %" PRIdPTR, chan);
+        weak_task_chans.push_back(chan);
+    }
+    uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
+    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+    if (new_non_weak_tasks == 0) {
+        end_weak_tasks();
+    }
+}
+
+void
+rust_kernel::unweaken_task(rust_port_id chan) {
+    uintptr_t new_non_weak_tasks = sync::increment(non_weak_tasks);
+    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+    {
+        scoped_lock with(weak_task_lock);
+        KLOG_("Unweakening task with channel %" PRIdPTR, chan);
+        std::vector<rust_port_id>::iterator iter =
+            std::find(weak_task_chans.begin(), weak_task_chans.end(), chan);
+        if (iter != weak_task_chans.end()) {
+            weak_task_chans.erase(iter);
+        }
+    }
+}
+
+void
+rust_kernel::end_weak_tasks() {
+    std::vector<rust_port_id> chancopies;
+    {
+        //scoped_lock with(weak_task_lock);
+        chancopies = weak_task_chans;
+        weak_task_chans.clear();
+    }
+    while (!chancopies.empty()) {
+        rust_port_id chan = chancopies.back();
+        chancopies.pop_back();
+        KLOG_("Notifying weak task " PRIdPTR, chan);
+        uintptr_t token = 0;
+        send_to_port(chan, &token);
+    }
+}
+
+bool
+rust_kernel::send_to_port(rust_port_id chan, void *sptr) {
+    KLOG_("rust_port_id*_send port: 0x%" PRIxPTR, (uintptr_t) chan);
+
+    rust_port *port = get_port_by_id(chan);
+    if(port) {
+        port->send(sptr);
+        port->deref();
+        return true;
+    } else {
+        KLOG_("didn't get the port");
+        return false;
+    }
+}
+
 //
 // Local Variables:
 // mode: C++