2010-06-23 23:03:09 -05:00
|
|
|
|
|
|
|
#include "rust_internal.h"
|
2010-07-04 23:18:47 -05:00
|
|
|
#include "valgrind.h"
|
2010-06-23 23:03:09 -05:00
|
|
|
|
|
|
|
// 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
|
2010-06-24 10:52:52 -05:00
|
|
|
#elif defined(__GNUC__)
|
|
|
|
static void *
|
|
|
|
#else
|
|
|
|
#error "Platform not supported"
|
|
|
|
#endif
|
|
|
|
timer_loop(void *ptr)
|
2010-06-23 23:03:09 -05:00
|
|
|
{
|
|
|
|
// We were handed the rust_timer that owns us.
|
|
|
|
rust_timer *timer = (rust_timer *)ptr;
|
|
|
|
rust_dom &dom = timer->dom;
|
2010-06-24 10:52:52 -05:00
|
|
|
dom.log(rust_log::TIMER, "in timer 0x%" PRIxPTR, (uintptr_t)timer);
|
2010-07-04 23:18:47 -05:00
|
|
|
size_t ms = TIME_SLICE_IN_MS;
|
|
|
|
if (!RUNNING_ON_VALGRIND)
|
|
|
|
ms = 1;
|
|
|
|
|
2010-06-23 23:03:09 -05:00
|
|
|
while (!timer->exit_flag) {
|
2010-06-24 10:52:52 -05:00
|
|
|
#if defined(__WIN32__)
|
2010-07-04 23:18:47 -05:00
|
|
|
Sleep(ms);
|
2010-06-24 10:52:52 -05:00
|
|
|
#else
|
2010-07-04 23:18:47 -05:00
|
|
|
usleep(ms * 1000);
|
2010-06-24 10:52:52 -05:00
|
|
|
#endif
|
|
|
|
dom.log(rust_log::TIMER,
|
2010-06-23 23:03:09 -05:00
|
|
|
"timer 0x%" PRIxPTR
|
|
|
|
" interrupting domain 0x%" PRIxPTR,
|
|
|
|
(uintptr_t)timer,
|
|
|
|
(uintptr_t)&dom);
|
|
|
|
dom.interrupt_flag = 1;
|
|
|
|
}
|
2010-06-24 10:52:52 -05:00
|
|
|
#if defined(__WIN32__)
|
2010-06-23 23:03:09 -05:00
|
|
|
ExitThread(0);
|
2010-06-24 10:52:52 -05:00
|
|
|
#else
|
2010-06-23 23:03:09 -05:00
|
|
|
pthread_exit(NULL);
|
2010-06-24 10:52:52 -05:00
|
|
|
#endif
|
2010-06-23 23:03:09 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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__)
|
2010-06-24 10:52:52 -05:00
|
|
|
thread = CreateThread(NULL, 0, timer_loop, this, 0, NULL);
|
2010-06-23 23:03:09 -05:00
|
|
|
dom.win32_require("CreateThread", thread != NULL);
|
2010-07-05 00:41:42 -05:00
|
|
|
if (RUNNING_ON_VALGRIND)
|
|
|
|
Sleep(10);
|
2010-06-23 23:03:09 -05:00
|
|
|
#else
|
|
|
|
pthread_attr_init(&attr);
|
|
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
2010-06-24 10:52:52 -05:00
|
|
|
pthread_create(&thread, &attr, timer_loop, (void *)this);
|
2010-07-05 00:41:42 -05:00
|
|
|
if (RUNNING_ON_VALGRIND)
|
2010-07-04 23:18:47 -05:00
|
|
|
usleep(10000);
|
2010-07-05 00:41:42 -05:00
|
|
|
#endif
|
2010-06-23 23:03:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
|
|
|
//
|