aboutsummaryrefslogtreecommitdiff
path: root/src/rt/sync
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/sync')
-rw-r--r--src/rt/sync/condition_variable.cpp28
-rw-r--r--src/rt/sync/condition_variable.h1
-rw-r--r--src/rt/sync/lock_free_queue.cpp4
-rw-r--r--src/rt/sync/lock_free_queue.h3
-rw-r--r--src/rt/sync/sync.cpp12
-rw-r--r--src/rt/sync/sync.h9
-rw-r--r--src/rt/sync/timer.cpp61
-rw-r--r--src/rt/sync/timer.h25
8 files changed, 138 insertions, 5 deletions
diff --git a/src/rt/sync/condition_variable.cpp b/src/rt/sync/condition_variable.cpp
index d4032572..c34ab7f4 100644
--- a/src/rt/sync/condition_variable.cpp
+++ b/src/rt/sync/condition_variable.cpp
@@ -9,14 +9,16 @@
// #define TRACE
-condition_variable::condition_variable() {
#if defined(__WIN32__)
+condition_variable::condition_variable() {
_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
#else
+condition_variable::condition_variable() {
pthread_cond_init(&_cond, NULL);
pthread_mutex_init(&_mutex, NULL);
-#endif
}
+#endif
condition_variable::~condition_variable() {
#if defined(__WIN32__)
@@ -31,15 +33,31 @@ condition_variable::~condition_variable() {
* Wait indefinitely until condition is signaled.
*/
void condition_variable::wait() {
+ timed_wait(0);
+}
+
+void condition_variable::timed_wait(size_t timeout_in_ns) {
#ifdef TRACE
- printf("waiting on condition_variable: 0x%" PRIxPTR "\n",
- (uintptr_t)this);
+ printf("waiting on condition_variable: 0x%" PRIxPTR " for %d ns. \n",
+ (uintptr_t) this, (int) timeout_in_ns);
#endif
#if defined(__WIN32__)
WaitForSingleObject(_event, INFINITE);
#else
pthread_mutex_lock(&_mutex);
- pthread_cond_wait(&_cond, &_mutex);
+ // wait() automatically releases the mutex while it waits, and acquires
+ // it right before exiting. This allows signal() to acquire the mutex
+ // when signaling.)
+ if (timeout_in_ns == 0) {
+ pthread_cond_wait(&_cond, &_mutex);
+ } else {
+ timeval time_val;
+ gettimeofday(&time_val, NULL);
+ timespec time_spec;
+ time_spec.tv_sec = time_val.tv_sec + 0;
+ time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns;
+ pthread_cond_timedwait(&_cond, &_mutex, &time_spec);
+ }
pthread_mutex_unlock(&_mutex);
#endif
#ifdef TRACE
diff --git a/src/rt/sync/condition_variable.h b/src/rt/sync/condition_variable.h
index f847ef99..f336a7f2 100644
--- a/src/rt/sync/condition_variable.h
+++ b/src/rt/sync/condition_variable.h
@@ -13,6 +13,7 @@ public:
virtual ~condition_variable();
void wait();
+ void timed_wait(size_t timeout_in_ns);
void signal();
};
diff --git a/src/rt/sync/lock_free_queue.cpp b/src/rt/sync/lock_free_queue.cpp
index 69241ece..3f859862 100644
--- a/src/rt/sync/lock_free_queue.cpp
+++ b/src/rt/sync/lock_free_queue.cpp
@@ -18,6 +18,7 @@ lock_free_queue::lock_free_queue() : _tail(this) {
void
lock_free_queue::enqueue(lock_free_queue_node *item) {
+ lock.lock();
item->next = (lock_free_queue_node *) NULL;
lock_free_queue_node *last = _tail;
_tail = item;
@@ -25,10 +26,12 @@ lock_free_queue::enqueue(lock_free_queue_node *item) {
last = last->next;
}
last->next = item;
+ lock.unlock();
}
lock_free_queue_node *
lock_free_queue::dequeue() {
+ lock.lock();
lock_free_queue_node *item = next;
if (item && !(next = item->next)) {
_tail = (lock_free_queue_node *) this;
@@ -41,6 +44,7 @@ lock_free_queue::dequeue() {
} while ((lost = help) != (lock_free_queue_node *) NULL);
}
}
+ lock.unlock();
return item;
}
diff --git a/src/rt/sync/lock_free_queue.h b/src/rt/sync/lock_free_queue.h
index 1f09ec52..c1a309b8 100644
--- a/src/rt/sync/lock_free_queue.h
+++ b/src/rt/sync/lock_free_queue.h
@@ -1,6 +1,8 @@
#ifndef LOCK_FREE_QUEUE_H
#define LOCK_FREE_QUEUE_H
+#include "spin_lock.h"
+
class lock_free_queue_node {
public:
lock_free_queue_node *next;
@@ -8,6 +10,7 @@ public:
};
class lock_free_queue : lock_free_queue_node {
+ spin_lock lock;
lock_free_queue_node *_tail;
public:
lock_free_queue();
diff --git a/src/rt/sync/sync.cpp b/src/rt/sync/sync.cpp
new file mode 100644
index 00000000..09a6f291
--- /dev/null
+++ b/src/rt/sync/sync.cpp
@@ -0,0 +1,12 @@
+#include "../globals.h"
+#include "sync.h"
+
+void sync::yield() {
+#ifdef __APPLE__
+ pthread_yield_np();
+#elif __WIN32__
+ Sleep(1);
+#else
+ pthread_yield();
+#endif
+}
diff --git a/src/rt/sync/sync.h b/src/rt/sync/sync.h
new file mode 100644
index 00000000..902b5661
--- /dev/null
+++ b/src/rt/sync/sync.h
@@ -0,0 +1,9 @@
+#ifndef SYNC_H
+#define SYNC_H
+
+class sync {
+public:
+ static void yield();
+};
+
+#endif /* SYNC_H */
diff --git a/src/rt/sync/timer.cpp b/src/rt/sync/timer.cpp
new file mode 100644
index 00000000..0487b397
--- /dev/null
+++ b/src/rt/sync/timer.cpp
@@ -0,0 +1,61 @@
+#include "../globals.h"
+#include "timer.h"
+
+#if defined(__APPLE__)
+#include <mach/mach_time.h>
+#endif
+
+timer::timer() {
+#if __WIN32__
+ uint64_t ticks_per_second;
+ QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second);
+ _ticks_per_us = ticks_per_second / 1000000;
+#endif
+ reset(0);
+}
+
+void
+timer::reset(uint64_t timeout) {
+ _start = get_time();
+ _timeout = timeout;
+}
+
+uint64_t
+timer::get_elapsed_time() {
+ return get_time() - _start;
+}
+
+int64_t
+timer::get_timeout() {
+ return _timeout - get_elapsed_time();
+}
+
+bool
+timer::has_timed_out() {
+ return get_timeout() <= 0;
+}
+
+uint64_t
+timer::get_time() {
+#ifdef __APPLE__
+ uint64_t time = mach_absolute_time();
+ mach_timebase_info_data_t info = {0, 0};
+ if (info.denom == 0) {
+ mach_timebase_info(&info);
+ }
+ uint64_t time_nano = time * (info.numer / info.denom);
+ return time_nano / 1000;
+#elif __WIN32__
+ uint64_t ticks;
+ QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
+ return ticks / _ticks_per_us;
+#else
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (ts.tv_sec * 1000000000LL + ts.tv_nsec) / 1000;
+#endif
+}
+
+timer::~timer() {
+ // Nop.
+}
diff --git a/src/rt/sync/timer.h b/src/rt/sync/timer.h
new file mode 100644
index 00000000..509fd22c
--- /dev/null
+++ b/src/rt/sync/timer.h
@@ -0,0 +1,25 @@
+/*
+ * Utility class to measure time in a platform independent way.
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+class timer {
+private:
+ uint64_t _start;
+ uint64_t _timeout;
+ uint64_t get_time();
+#if __WIN32__
+ uint64_t _ticks_per_us;
+#endif
+public:
+ timer();
+ void reset(uint64_t timeout);
+ uint64_t get_elapsed_time();
+ int64_t get_timeout();
+ bool has_timed_out();
+ virtual ~timer();
+};
+
+#endif /* TIMER_H */