about summary refs log tree commit diff
path: root/src/rt/rust_timer.cpp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
commitd6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch)
treeb425187e232966063ffc2f0d14c04a55d8f004ef /src/rt/rust_timer.cpp
parentc01efc669f09508b55eced32d3c88702578a7c3e (diff)
downloadrust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.gz
rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip
Populate tree.
Diffstat (limited to 'src/rt/rust_timer.cpp')
-rw-r--r--src/rt/rust_timer.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/rt/rust_timer.cpp b/src/rt/rust_timer.cpp
new file mode 100644
index 00000000000..897b7730182
--- /dev/null
+++ b/src/rt/rust_timer.cpp
@@ -0,0 +1,97 @@
+
+#include "rust_internal.h"
+
+// The mechanism in this file is very crude; every domain (thread) spawns its
+// own secondary timer thread, and that timer thread *never idles*. It
+// sleep-loops interrupting the domain.
+//
+// This will need replacement, particularly in order to achieve an actual
+// state of idling when we're waiting on the outside world.  Though that might
+// be as simple as making a secondary waitable start/stop-timer signalling
+// system between the domain and its timer thread. We'll see.
+//
+// On the other hand, we don't presently have the ability to idle domains *at
+// all*, and without the timer thread we're unable to otherwise preempt rust
+// tasks. So ... one step at a time.
+//
+// The implementation here is "lockless" in the sense that it only involves
+// one-directional signaling of one-shot events, so the event initiator just
+// writes a nonzero word to a prederermined location and waits for the
+// receiver to see it show up in their memory.
+
+#if defined(__WIN32__)
+static DWORD WINAPI
+win32_timer_loop(void *ptr)
+{
+    // We were handed the rust_timer that owns us.
+    rust_timer *timer = (rust_timer *)ptr;
+    rust_dom &dom = timer->dom;
+    dom.log(LOG_TIMER, "in timer 0x%" PRIxPTR, (uintptr_t)timer);
+    while (!timer->exit_flag) {
+        Sleep(TIME_SLICE_IN_MS);
+        dom.log(LOG_TIMER,
+                "timer 0x%" PRIxPTR
+                " interrupting domain 0x%" PRIxPTR,
+                (uintptr_t)timer,
+                (uintptr_t)&dom);
+        dom.interrupt_flag = 1;
+    }
+    ExitThread(0);
+    return 0;
+}
+
+#elif defined(__GNUC__)
+static void *
+pthread_timer_loop(void *ptr)
+{
+    // We were handed the rust_timer that owns us.
+    rust_timer *timer = (rust_timer *)ptr;
+    rust_dom &dom(timer->dom);
+    while (!timer->exit_flag) {
+        usleep(TIME_SLICE_IN_MS * 1000);
+        dom.interrupt_flag = 1;
+    }
+    pthread_exit(NULL);
+    return 0;
+
+}
+#else
+#error "Platform not supported"
+#endif
+
+
+rust_timer::rust_timer(rust_dom &dom) : dom(dom), exit_flag(0)
+{
+    dom.log(rust_log::TIMER, "creating timer for domain 0x%" PRIxPTR, &dom);
+#if defined(__WIN32__)
+    thread = CreateThread(NULL, 0, win32_timer_loop, this, 0, NULL);
+    dom.win32_require("CreateThread", thread != NULL);
+#else
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    pthread_create(&thread, &attr, pthread_timer_loop, (void *)this);
+#endif
+}
+
+rust_timer::~rust_timer()
+{
+    exit_flag = 1;
+#if defined(__WIN32__)
+    dom.win32_require("WaitForSingleObject",
+                      WaitForSingleObject(thread, INFINITE)
+                      == WAIT_OBJECT_0);
+#else
+    pthread_join(thread, NULL);
+#endif
+}
+
+//
+// Local Variables:
+// mode: C++
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//