Adding a lock/condition variable to libcore.
This commit is contained in:
parent
9ee1480fd1
commit
dc718d97a6
6 changed files with 156 additions and 0 deletions
1
mk/rt.mk
1
mk/rt.mk
|
@ -71,6 +71,7 @@ RUNTIME_CS_$(1) := \
|
||||||
rt/rust_cc.cpp \
|
rt/rust_cc.cpp \
|
||||||
rt/rust_debug.cpp \
|
rt/rust_debug.cpp \
|
||||||
rt/rust_box_annihilator.cpp \
|
rt/rust_box_annihilator.cpp \
|
||||||
|
rt/rust_cond_lock.cpp \
|
||||||
rt/memory_region.cpp \
|
rt/memory_region.cpp \
|
||||||
rt/boxed_region.cpp \
|
rt/boxed_region.cpp \
|
||||||
rt/arch/$$(HOST_$(1))/context.cpp \
|
rt/arch/$$(HOST_$(1))/context.cpp \
|
||||||
|
|
|
@ -7,6 +7,7 @@ export min_align_of;
|
||||||
export pref_align_of;
|
export pref_align_of;
|
||||||
export refcount;
|
export refcount;
|
||||||
export log_str;
|
export log_str;
|
||||||
|
export lock_and_signal, condition, methods;
|
||||||
|
|
||||||
enum type_desc = {
|
enum type_desc = {
|
||||||
first_param: **libc::c_int,
|
first_param: **libc::c_int,
|
||||||
|
@ -15,11 +16,20 @@ enum type_desc = {
|
||||||
// Remaining fields not listed
|
// Remaining fields not listed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type rust_cond_lock = *libc::c_void;
|
||||||
|
|
||||||
#[abi = "cdecl"]
|
#[abi = "cdecl"]
|
||||||
native mod rustrt {
|
native mod rustrt {
|
||||||
pure fn refcount(t: *()) -> libc::intptr_t;
|
pure fn refcount(t: *()) -> libc::intptr_t;
|
||||||
fn unsupervise();
|
fn unsupervise();
|
||||||
pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
|
pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
|
||||||
|
|
||||||
|
fn rust_create_cond_lock() -> rust_cond_lock;
|
||||||
|
fn rust_destroy_cond_lock(lock: rust_cond_lock);
|
||||||
|
fn rust_lock_cond_lock(lock: rust_cond_lock);
|
||||||
|
fn rust_unlock_cond_lock(lock: rust_cond_lock);
|
||||||
|
fn rust_wait_cond_lock(lock: rust_cond_lock);
|
||||||
|
fn rust_signal_cond_lock(lock: rust_cond_lock) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[abi = "rust-intrinsic"]
|
#[abi = "rust-intrinsic"]
|
||||||
|
@ -74,8 +84,50 @@ pure fn log_str<T>(t: T) -> str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource lock_and_signal(lock: rust_cond_lock) {
|
||||||
|
rustrt::rust_destroy_cond_lock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum condition {
|
||||||
|
condition_(rust_cond_lock)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource unlock(lock: rust_cond_lock) {
|
||||||
|
rustrt::rust_unlock_cond_lock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_lock() -> lock_and_signal {
|
||||||
|
lock_and_signal(rustrt::rust_create_cond_lock())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl methods for lock_and_signal {
|
||||||
|
fn lock<T>(f: fn() -> T) -> T {
|
||||||
|
rustrt::rust_lock_cond_lock(*self);
|
||||||
|
let _r = unlock(*self);
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock_cond<T>(f: fn(condition) -> T) -> T {
|
||||||
|
rustrt::rust_lock_cond_lock(*self);
|
||||||
|
let _r = unlock(*self);
|
||||||
|
f(condition_(*self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl methods for condition {
|
||||||
|
fn wait() {
|
||||||
|
rustrt::rust_wait_cond_lock(*self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signal() -> bool {
|
||||||
|
rustrt::rust_signal_cond_lock(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std;
|
||||||
|
import std::arc;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn size_of_basic() {
|
fn size_of_basic() {
|
||||||
|
@ -121,6 +173,26 @@ mod tests {
|
||||||
assert pref_align_of::<uint>() == 8u;
|
assert pref_align_of::<uint>() == 8u;
|
||||||
assert pref_align_of::<*uint>() == 8u;
|
assert pref_align_of::<*uint>() == 8u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn condition_variable() {
|
||||||
|
let lock = arc::arc(create_lock());
|
||||||
|
let lock2 = arc::clone(&lock);
|
||||||
|
|
||||||
|
task::spawn {|move lock2|
|
||||||
|
let lock = arc::get(&lock2);
|
||||||
|
(*lock).lock_cond {|c|
|
||||||
|
c.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut signaled = false;
|
||||||
|
while !signaled {
|
||||||
|
(*arc::get(&lock)).lock_cond {|c|
|
||||||
|
signaled = c.signal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "sync/timer.h"
|
#include "sync/timer.h"
|
||||||
#include "rust_abi.h"
|
#include "rust_abi.h"
|
||||||
#include "rust_port.h"
|
#include "rust_port.h"
|
||||||
|
#include "rust_cond_lock.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -861,6 +862,61 @@ rust_task_allow_kill() {
|
||||||
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;
|
||||||
|
task->block(lock, "waiting for signal");
|
||||||
|
lock->lock.unlock();
|
||||||
|
task->yield(false);
|
||||||
|
lock->lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
lock->waiting = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: C++
|
// mode: C++
|
||||||
|
|
6
src/rt/rust_cond_lock.cpp
Normal file
6
src/rt/rust_cond_lock.cpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "rust_cond_lock.h"
|
||||||
|
|
||||||
|
rust_cond_lock::rust_cond_lock()
|
||||||
|
: waiting(NULL)
|
||||||
|
{
|
||||||
|
}
|
15
src/rt/rust_cond_lock.h
Normal file
15
src/rt/rust_cond_lock.h
Normal file
|
@ -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;
|
||||||
|
};
|
|
@ -163,3 +163,9 @@ rust_port_drop
|
||||||
rust_port_task
|
rust_port_task
|
||||||
rust_task_inhibit_kill
|
rust_task_inhibit_kill
|
||||||
rust_task_allow_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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue