b513a5a500
I was still having issues with the build system somehow getting confused as to which set of valgrind headers to use when compiling rt. This commit moves all the valgrind headers into their own directory under rt and makes the usage more consistent. The compiler is now passed the -DNVALGRIND flag when valgrind is not installed, as opposed to passing -DHAVE_VALGRIND. We also pass -I src/rt to the compiler when building rt so you can more easily import what you want. I also cleaned up some erroneous #includes along the way. It should be safe to always just import the local valgrind headers and use them without question. NVALGRIND turns the operations to no-ops when it is active, and the build and tests run cleanly with or without.
91 lines
2.8 KiB
C++
91 lines
2.8 KiB
C++
#include "rust_internal.h"
|
|
#include "vg/valgrind.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
|
|
#elif defined(__GNUC__)
|
|
static void *
|
|
#else
|
|
#error "Platform not supported"
|
|
#endif
|
|
timer_loop(void *ptr) {
|
|
// We were handed the rust_timer that owns us.
|
|
rust_timer *timer = (rust_timer *)ptr;
|
|
rust_scheduler *sched = timer->sched;
|
|
DLOG(sched, timer, "in timer 0x%" PRIxPTR, (uintptr_t)timer);
|
|
size_t ms = TIME_SLICE_IN_MS;
|
|
|
|
while (!timer->exit_flag) {
|
|
#if defined(__WIN32__)
|
|
Sleep(ms);
|
|
#else
|
|
usleep(ms * 1000);
|
|
#endif
|
|
DLOG(sched, timer, "timer 0x%" PRIxPTR
|
|
" interrupting schedain 0x%" PRIxPTR, (uintptr_t) timer,
|
|
(uintptr_t) sched);
|
|
sched->interrupt_flag = 1;
|
|
}
|
|
#if defined(__WIN32__)
|
|
ExitThread(0);
|
|
#else
|
|
pthread_exit(NULL);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
rust_timer::rust_timer(rust_scheduler *sched) :
|
|
sched(sched), exit_flag(0) {
|
|
DLOG(sched, timer, "creating timer for domain 0x%" PRIxPTR, sched);
|
|
#if defined(__WIN32__)
|
|
thread = CreateThread(NULL, 0, timer_loop, this, 0, NULL);
|
|
sched->kernel->win32_require("CreateThread", thread != NULL);
|
|
if (RUNNING_ON_VALGRIND)
|
|
Sleep(10);
|
|
#else
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
pthread_create(&thread, &attr, timer_loop, (void *)this);
|
|
#endif
|
|
}
|
|
|
|
rust_timer::~rust_timer() {
|
|
exit_flag = 1;
|
|
#if defined(__WIN32__)
|
|
sched->kernel->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 $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
|
// End:
|
|
//
|