about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-06-06 15:06:24 -0700
committerEric Holk <eric.holk@gmail.com>2012-06-15 22:00:24 -0400
commite394ebda37bf6bbe4c516e2b9381aac8bd964dcc (patch)
tree58128171af062efa394ee0d0697bcb52c29bb21e /src/rt
parent5c9f414a85ae8f3448a27f56274afc861974cffe (diff)
downloadrust-e394ebda37bf6bbe4c516e2b9381aac8bd964dcc.tar.gz
rust-e394ebda37bf6bbe4c516e2b9381aac8bd964dcc.zip
Adding a lock/condition variable to libcore.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_builtin.cpp55
-rw-r--r--src/rt/rust_cond_lock.cpp6
-rw-r--r--src/rt/rust_cond_lock.h15
-rw-r--r--src/rt/rustrt.def.in6
4 files changed, 82 insertions, 0 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 2a65012b52a..25da500cb23 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -7,6 +7,7 @@
 #include "sync/timer.h"
 #include "rust_abi.h"
 #include "rust_port.h"
+#include "rust_cond_lock.h"
 
 #include <time.h>
 
@@ -862,6 +863,60 @@ rust_task_allow_kill() {
     task->allow_kill();
 }
 
+extern "C" rust_cond_lock*
+rust_create_cond_lock() {
+    return new rust_cond_lock();
+}
+
+extern "C" void
+rust_destroy_cond_lock(rust_cond_lock *lock) {
+    delete lock;
+}
+
+extern "C" void
+rust_lock_cond_lock(rust_cond_lock *lock) {
+    lock->lock.lock();
+}
+
+extern "C" void
+rust_unlock_cond_lock(rust_cond_lock *lock) {
+    lock->lock.unlock();
+}
+
+// The next two functions do not use the built in condition variable features
+// because the Rust schedule is not aware of them, and they can block the
+// scheduler thread.
+
+extern "C" void
+rust_wait_cond_lock(rust_cond_lock *lock) {
+    rust_task *task = rust_get_current_task();
+#ifdef DEBUG_LOCKS
+    assert(lock->lock.lock_held_by_current_thread());
+#endif
+    assert(NULL == lock->waiting);
+    lock->waiting = task;
+    lock->lock.unlock();
+    task->block(lock, "waiting for signal");
+    lock->lock.lock();
+    lock->waiting = NULL;
+}
+
+extern "C" bool
+rust_signal_cond_lock(rust_cond_lock *lock) {
+#ifdef DEBUG_LOCKS
+    assert(lock->lock.lock_held_by_current_thread());
+#endif
+    if(NULL == lock->waiting) {
+        return false;
+    }
+    else {
+        lock->waiting->wakeup(lock);
+        return true;
+    }
+}
+
+
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_cond_lock.cpp b/src/rt/rust_cond_lock.cpp
new file mode 100644
index 00000000000..cdeccfdc26c
--- /dev/null
+++ b/src/rt/rust_cond_lock.cpp
@@ -0,0 +1,6 @@
+#include "rust_cond_lock.h"
+
+rust_cond_lock::rust_cond_lock()
+    : waiting(NULL)
+{
+}
diff --git a/src/rt/rust_cond_lock.h b/src/rt/rust_cond_lock.h
new file mode 100644
index 00000000000..0adafd59678
--- /dev/null
+++ b/src/rt/rust_cond_lock.h
@@ -0,0 +1,15 @@
+// -*- c++ -*-
+// A lock and condition variable pair that is useable from Rust.
+
+#pragma once
+
+#include "sync/lock_and_signal.h"
+#include "rust_globals.h"
+#include "rust_task.h"
+
+struct rust_cond_lock : public rust_cond {
+    rust_cond_lock();
+
+    lock_and_signal lock;
+    rust_task *waiting;
+};
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 7977c42cfa4..5cf6ee61773 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -163,3 +163,9 @@ rust_port_drop
 rust_port_task
 rust_task_inhibit_kill
 rust_task_allow_kill
+rust_create_cond_lock
+rust_destroy_cond_lock
+rust_lock_cond_lock
+rust_unlock_cond_lock
+rust_wait_cond_lock
+rust_signal_cond_lock