mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Remove the C++ lock_and_signal type
A the same time this purges all runtime support needed for statically initialized mutexes, moving all users over to the new Mutex type instead.
This commit is contained in:
parent
24eb1b445d
commit
e8bf078802
1
mk/rt.mk
1
mk/rt.mk
@ -90,7 +90,6 @@ endif
|
||||
endif
|
||||
|
||||
RUNTIME_CXXS_$(1)_$(2) := \
|
||||
rt/sync/lock_and_signal.cpp \
|
||||
rt/rust_builtin.cpp \
|
||||
rt/rust_upcall.cpp \
|
||||
rt/miniz.cpp \
|
||||
|
@ -138,21 +138,19 @@ Accessing environment variables is not generally threadsafe.
|
||||
Serialize access through a global lock.
|
||||
*/
|
||||
fn with_env_lock<T>(f: &fn() -> T) -> T {
|
||||
use unstable::mutex::{Mutex, MUTEX_INIT};
|
||||
use unstable::finally::Finally;
|
||||
|
||||
static mut lock: Mutex = MUTEX_INIT;
|
||||
|
||||
unsafe {
|
||||
return do (|| {
|
||||
rust_take_env_lock();
|
||||
lock.lock();
|
||||
f()
|
||||
}).finally {
|
||||
rust_drop_env_lock();
|
||||
lock.unlock();
|
||||
};
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_take_env_lock();
|
||||
fn rust_drop_env_lock();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) pairs for all the environment
|
||||
|
@ -21,32 +21,42 @@
|
||||
//! FIXME #7756: This has a lot of C glue for lack of globals.
|
||||
|
||||
use option::Option;
|
||||
#[cfg(test)] use option::{Some, None};
|
||||
#[cfg(test)] use realstd;
|
||||
#[cfg(test)] use realargs = realstd::rt::args;
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: int, argv: **u8) {
|
||||
imp::init(argc, argv)
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
pub unsafe fn init(argc: int, argv: **u8) { imp::init(argc, argv) }
|
||||
#[cfg(test)]
|
||||
pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) }
|
||||
|
||||
/// One-time global cleanup.
|
||||
pub fn cleanup() {
|
||||
imp::cleanup()
|
||||
}
|
||||
#[cfg(not(test))] pub fn cleanup() { imp::cleanup() }
|
||||
#[cfg(test)] pub fn cleanup() { realargs::cleanup() }
|
||||
|
||||
/// Take the global arguments from global storage.
|
||||
pub fn take() -> Option<~[~str]> {
|
||||
imp::take()
|
||||
#[cfg(not(test))] pub fn take() -> Option<~[~str]> { imp::take() }
|
||||
#[cfg(test)] pub fn take() -> Option<~[~str]> {
|
||||
match realargs::take() {
|
||||
realstd::option::Some(a) => Some(a),
|
||||
realstd::option::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Give the global arguments to global storage.
|
||||
///
|
||||
/// It is an error if the arguments already exist.
|
||||
pub fn put(args: ~[~str]) {
|
||||
imp::put(args)
|
||||
}
|
||||
#[cfg(not(test))] pub fn put(args: ~[~str]) { imp::put(args) }
|
||||
#[cfg(test)] pub fn put(args: ~[~str]) { realargs::put(args) }
|
||||
|
||||
/// Make a clone of the global arguments.
|
||||
pub fn clone() -> Option<~[~str]> {
|
||||
imp::clone()
|
||||
#[cfg(not(test))] pub fn clone() -> Option<~[~str]> { imp::clone() }
|
||||
#[cfg(test)] pub fn clone() -> Option<~[~str]> {
|
||||
match realargs::clone() {
|
||||
realstd::option::Some(a) => Some(a),
|
||||
realstd::option::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -58,9 +68,12 @@ mod imp {
|
||||
use iter::Iterator;
|
||||
use str;
|
||||
use unstable::finally::Finally;
|
||||
use unstable::mutex::{Mutex, MUTEX_INIT};
|
||||
use util;
|
||||
use vec;
|
||||
|
||||
static mut global_args_ptr: uint = 0;
|
||||
|
||||
pub unsafe fn init(argc: int, argv: **u8) {
|
||||
let args = load_argc_and_argv(argc, argv);
|
||||
put(args);
|
||||
@ -94,20 +107,22 @@ mod imp {
|
||||
}
|
||||
|
||||
fn with_lock<T>(f: &fn() -> T) -> T {
|
||||
static mut lock: Mutex = MUTEX_INIT;
|
||||
|
||||
do (|| {
|
||||
unsafe {
|
||||
rust_take_global_args_lock();
|
||||
lock.lock();
|
||||
f()
|
||||
}
|
||||
}).finally {
|
||||
unsafe {
|
||||
rust_drop_global_args_lock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_global_ptr() -> *mut Option<~~[~str]> {
|
||||
unsafe { rust_get_global_args_ptr() }
|
||||
unsafe { cast::transmute(&global_args_ptr) }
|
||||
}
|
||||
|
||||
// Copied from `os`.
|
||||
@ -117,12 +132,6 @@ mod imp {
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_take_global_args_lock();
|
||||
fn rust_drop_global_args_lock();
|
||||
fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use option::{Some, None};
|
||||
|
@ -21,17 +21,23 @@ use ptr;
|
||||
use cell::Cell;
|
||||
use option::{Option, Some, None};
|
||||
use unstable::finally::Finally;
|
||||
use unstable::mutex::{Mutex, MUTEX_INIT};
|
||||
use tls = rt::thread_local_storage;
|
||||
|
||||
static mut RT_TLS_KEY: tls::Key = -1;
|
||||
|
||||
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
|
||||
pub fn init_tls_key() {
|
||||
static mut lock: Mutex = MUTEX_INIT;
|
||||
static mut initialized: bool = false;
|
||||
|
||||
unsafe {
|
||||
rust_initialize_rt_tls_key(&mut RT_TLS_KEY);
|
||||
extern {
|
||||
fn rust_initialize_rt_tls_key(key: *mut tls::Key);
|
||||
lock.lock();
|
||||
if !initialized {
|
||||
tls::create(&mut RT_TLS_KEY);
|
||||
initialized = true;
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ use cell::Cell;
|
||||
use clone::Clone;
|
||||
use container::Container;
|
||||
use iter::{Iterator, range};
|
||||
use libc;
|
||||
use option::{Some, None};
|
||||
use os;
|
||||
use path::GenericPath;
|
||||
@ -361,11 +360,16 @@ pub fn cleanup_task(mut task: ~Task) {
|
||||
|
||||
/// Get a port number, starting at 9600, for use in tests
|
||||
pub fn next_test_port() -> u16 {
|
||||
use unstable::mutex::{Mutex, MUTEX_INIT};
|
||||
static mut lock: Mutex = MUTEX_INIT;
|
||||
static mut next_offset: u16 = 0;
|
||||
unsafe {
|
||||
return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
|
||||
}
|
||||
extern {
|
||||
fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t;
|
||||
let base = base_port();
|
||||
lock.lock();
|
||||
let ret = base + next_offset;
|
||||
next_offset += 1;
|
||||
lock.unlock();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,13 +399,13 @@ The bots run multiple builds at the same time, and these builds
|
||||
all want to use ports. This function figures out which workspace
|
||||
it is running in and assigns a port range based on it.
|
||||
*/
|
||||
fn base_port() -> uint {
|
||||
fn base_port() -> u16 {
|
||||
use os;
|
||||
use str::StrSlice;
|
||||
use vec::ImmutableVector;
|
||||
|
||||
let base = 9600u;
|
||||
let range = 1000;
|
||||
let base = 9600u16;
|
||||
let range = 1000u16;
|
||||
|
||||
let bases = [
|
||||
("32-opt", base + range * 1),
|
||||
|
@ -1141,22 +1141,10 @@ fn test_spawn_sched_childs_on_default_sched() {
|
||||
po.recv();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod testrt {
|
||||
use libc;
|
||||
|
||||
extern {
|
||||
pub fn rust_dbg_lock_create() -> *libc::c_void;
|
||||
pub fn rust_dbg_lock_destroy(lock: *libc::c_void);
|
||||
pub fn rust_dbg_lock_lock(lock: *libc::c_void);
|
||||
pub fn rust_dbg_lock_unlock(lock: *libc::c_void);
|
||||
pub fn rust_dbg_lock_wait(lock: *libc::c_void);
|
||||
pub fn rust_dbg_lock_signal(lock: *libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spawn_sched_blocking() {
|
||||
use unstable::mutex::Mutex;
|
||||
|
||||
unsafe {
|
||||
|
||||
// Testing that a task in one scheduler can block in foreign code
|
||||
@ -1165,16 +1153,18 @@ fn test_spawn_sched_blocking() {
|
||||
let (start_po, start_ch) = stream();
|
||||
let (fin_po, fin_ch) = stream();
|
||||
|
||||
let lock = testrt::rust_dbg_lock_create();
|
||||
let mut lock = Mutex::new();
|
||||
let lock2 = Cell::new(lock.clone());
|
||||
|
||||
do spawn_sched(SingleThreaded) {
|
||||
testrt::rust_dbg_lock_lock(lock);
|
||||
let mut lock = lock2.take();
|
||||
lock.lock();
|
||||
|
||||
start_ch.send(());
|
||||
|
||||
// Block the scheduler thread
|
||||
testrt::rust_dbg_lock_wait(lock);
|
||||
testrt::rust_dbg_lock_unlock(lock);
|
||||
lock.wait();
|
||||
lock.unlock();
|
||||
|
||||
fin_ch.send(());
|
||||
};
|
||||
@ -1201,11 +1191,11 @@ fn test_spawn_sched_blocking() {
|
||||
let child_ch = setup_po.recv();
|
||||
child_ch.send(20);
|
||||
pingpong(&parent_po, &child_ch);
|
||||
testrt::rust_dbg_lock_lock(lock);
|
||||
testrt::rust_dbg_lock_signal(lock);
|
||||
testrt::rust_dbg_lock_unlock(lock);
|
||||
lock.lock();
|
||||
lock.signal();
|
||||
lock.unlock();
|
||||
fin_po.recv();
|
||||
testrt::rust_dbg_lock_destroy(lock);
|
||||
lock.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +154,9 @@ pub mod dl {
|
||||
}
|
||||
|
||||
pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
|
||||
use unstable::mutex::{Mutex, MUTEX_INIT};
|
||||
static mut lock: Mutex = MUTEX_INIT;
|
||||
|
||||
unsafe {
|
||||
// dlerror isn't thread safe, so we need to lock around this entire
|
||||
// sequence. `atomically` asserts that we don't do anything that
|
||||
@ -161,7 +164,7 @@ pub mod dl {
|
||||
// the scheduler if it happens while the lock is held.
|
||||
// FIXME #9105 use a Rust mutex instead of C++ mutexes.
|
||||
do atomically {
|
||||
rust_take_dlerror_lock();
|
||||
lock.lock();
|
||||
let _old_error = dlerror();
|
||||
|
||||
let result = f();
|
||||
@ -172,7 +175,7 @@ pub mod dl {
|
||||
} else {
|
||||
Err(str::raw::from_c_str(last_error))
|
||||
};
|
||||
rust_drop_dlerror_lock();
|
||||
lock.unlock();
|
||||
ret
|
||||
}
|
||||
}
|
||||
@ -192,11 +195,6 @@ pub mod dl {
|
||||
Local = 0,
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_take_dlerror_lock();
|
||||
fn rust_drop_dlerror_lock();
|
||||
}
|
||||
|
||||
#[link_name = "dl"]
|
||||
extern {
|
||||
fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
|
||||
|
@ -11,12 +11,12 @@
|
||||
use cast;
|
||||
use cell::Cell;
|
||||
use comm;
|
||||
use libc;
|
||||
use ptr;
|
||||
use option::{Option,Some,None};
|
||||
use task;
|
||||
use unstable::atomics::{AtomicOption,AtomicUint,Acquire,Release,Relaxed,SeqCst};
|
||||
use unstable::finally::Finally;
|
||||
use unstable::mutex::Mutex;
|
||||
use ops::Drop;
|
||||
use clone::Clone;
|
||||
use kinds::Send;
|
||||
@ -319,17 +319,14 @@ pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
type rust_little_lock = *libc::c_void;
|
||||
|
||||
pub struct LittleLock {
|
||||
priv l: rust_little_lock,
|
||||
priv l: Mutex,
|
||||
}
|
||||
|
||||
impl Drop for LittleLock {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
rust_destroy_little_lock(self.l);
|
||||
self.l.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,29 +335,31 @@ impl LittleLock {
|
||||
pub fn new() -> LittleLock {
|
||||
unsafe {
|
||||
LittleLock {
|
||||
l: rust_create_little_lock()
|
||||
l: Mutex::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn lock<T>(&self, f: &fn() -> T) -> T {
|
||||
let this = cast::transmute_mut(self);
|
||||
do atomically {
|
||||
rust_lock_little_lock(self.l);
|
||||
this.l.lock();
|
||||
do (|| {
|
||||
f()
|
||||
}).finally {
|
||||
rust_unlock_little_lock(self.l);
|
||||
this.l.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn try_lock<T>(&self, f: &fn() -> T) -> Option<T> {
|
||||
let this = cast::transmute_mut(self);
|
||||
do atomically {
|
||||
if rust_trylock_little_lock(self.l) {
|
||||
if this.l.trylock() {
|
||||
Some(do (|| {
|
||||
f()
|
||||
}).finally {
|
||||
rust_unlock_little_lock(self.l);
|
||||
this.l.unlock();
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -369,18 +368,20 @@ impl LittleLock {
|
||||
}
|
||||
|
||||
pub unsafe fn signal(&self) {
|
||||
rust_signal_little_lock(self.l);
|
||||
let this = cast::transmute_mut(self);
|
||||
this.l.signal();
|
||||
}
|
||||
|
||||
pub unsafe fn lock_and_wait(&self, f: &fn() -> bool) {
|
||||
let this = cast::transmute_mut(self);
|
||||
do atomically {
|
||||
rust_lock_little_lock(self.l);
|
||||
this.l.lock();
|
||||
do (|| {
|
||||
if f() {
|
||||
rust_wait_little_lock(self.l);
|
||||
this.l.wait();
|
||||
}
|
||||
}).finally {
|
||||
rust_unlock_little_lock(self.l);
|
||||
this.l.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,16 +490,6 @@ impl<T:Send> Exclusive<T> {
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_create_little_lock() -> rust_little_lock;
|
||||
fn rust_destroy_little_lock(lock: rust_little_lock);
|
||||
fn rust_trylock_little_lock(lock: rust_little_lock) -> bool;
|
||||
fn rust_lock_little_lock(lock: rust_little_lock);
|
||||
fn rust_unlock_little_lock(lock: rust_little_lock);
|
||||
fn rust_signal_little_lock(lock: rust_little_lock);
|
||||
fn rust_wait_little_lock(lock: rust_little_lock);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use cell::Cell;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
/* Foreign builtins. */
|
||||
|
||||
#include "sync/lock_and_signal.h"
|
||||
#include "rust_globals.h"
|
||||
#include "vg/valgrind.h"
|
||||
|
||||
#include <time.h>
|
||||
@ -379,41 +379,6 @@ rust_mktime(rust_tm* timeptr) {
|
||||
return mktime(&t);
|
||||
}
|
||||
|
||||
extern "C" lock_and_signal*
|
||||
rust_create_little_lock() {
|
||||
return new lock_and_signal();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_destroy_little_lock(lock_and_signal *lock) {
|
||||
delete lock;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_lock_little_lock(lock_and_signal *lock) {
|
||||
lock->lock();
|
||||
}
|
||||
|
||||
extern "C" bool
|
||||
rust_trylock_little_lock(lock_and_signal *lock) {
|
||||
return lock->try_lock();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_unlock_little_lock(lock_and_signal *lock) {
|
||||
lock->unlock();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_wait_little_lock(lock_and_signal *lock) {
|
||||
lock->wait();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_signal_little_lock(lock_and_signal *lock) {
|
||||
lock->signal();
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
@ -440,34 +405,6 @@ rust_readdir() {
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef pthread_key_t tls_key;
|
||||
#else
|
||||
typedef DWORD tls_key;
|
||||
#endif
|
||||
|
||||
// Initialize the TLS key used by the new scheduler
|
||||
extern "C" CDECL void
|
||||
rust_initialize_rt_tls_key(tls_key *key) {
|
||||
|
||||
static lock_and_signal init_lock;
|
||||
static bool initialized = false;
|
||||
|
||||
scoped_lock with(init_lock);
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
#ifndef _WIN32
|
||||
assert(!pthread_key_create(key, NULL));
|
||||
#else
|
||||
*key = TlsAlloc();
|
||||
assert(*key != TLS_OUT_OF_INDEXES);
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void *(rust_try_fn)(void*, void*);
|
||||
|
||||
extern "C" CDECL uintptr_t
|
||||
@ -538,48 +475,6 @@ rust_get_num_cpus() {
|
||||
return get_num_cpus();
|
||||
}
|
||||
|
||||
static lock_and_signal global_args_lock;
|
||||
static uintptr_t global_args_ptr = 0;
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_take_global_args_lock() {
|
||||
global_args_lock.lock();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_drop_global_args_lock() {
|
||||
global_args_lock.unlock();
|
||||
}
|
||||
|
||||
extern "C" CDECL uintptr_t*
|
||||
rust_get_global_args_ptr() {
|
||||
return &global_args_ptr;
|
||||
}
|
||||
|
||||
static lock_and_signal env_lock;
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_take_env_lock() {
|
||||
env_lock.lock();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_drop_env_lock() {
|
||||
env_lock.unlock();
|
||||
}
|
||||
|
||||
static lock_and_signal dlerror_lock;
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_take_dlerror_lock() {
|
||||
dlerror_lock.lock();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_drop_dlerror_lock() {
|
||||
dlerror_lock.unlock();
|
||||
}
|
||||
|
||||
extern "C" CDECL unsigned int
|
||||
rust_valgrind_stack_register(void *start, void *end) {
|
||||
return VALGRIND_STACK_REGISTER(start, end);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// Helper functions used only in tests
|
||||
|
||||
#include "sync/lock_and_signal.h"
|
||||
#include "rust_globals.h"
|
||||
|
||||
// These functions are used in the unit tests for C ABI calls.
|
||||
|
||||
@ -34,41 +34,6 @@ rust_dbg_extern_identity_u8(char u) {
|
||||
return u;
|
||||
}
|
||||
|
||||
extern "C" CDECL lock_and_signal *
|
||||
rust_dbg_lock_create() {
|
||||
return new lock_and_signal();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_dbg_lock_destroy(lock_and_signal *lock) {
|
||||
assert(lock);
|
||||
delete lock;
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_dbg_lock_lock(lock_and_signal *lock) {
|
||||
assert(lock);
|
||||
lock->lock();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_dbg_lock_unlock(lock_and_signal *lock) {
|
||||
assert(lock);
|
||||
lock->unlock();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_dbg_lock_wait(lock_and_signal *lock) {
|
||||
assert(lock);
|
||||
lock->wait();
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_dbg_lock_signal(lock_and_signal *lock) {
|
||||
assert(lock);
|
||||
lock->signal();
|
||||
}
|
||||
|
||||
typedef void *(*dbg_callback)(void*);
|
||||
|
||||
extern "C" CDECL void *
|
||||
@ -160,17 +125,6 @@ rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) {
|
||||
return u;
|
||||
}
|
||||
|
||||
// Generates increasing port numbers for network testing
|
||||
extern "C" CDECL uintptr_t
|
||||
rust_dbg_next_port(uintptr_t base_port) {
|
||||
static lock_and_signal dbg_port_lock;
|
||||
static uintptr_t next_offset = 0;
|
||||
scoped_lock with(dbg_port_lock);
|
||||
uintptr_t this_port = base_port + next_offset;
|
||||
next_offset += 1;
|
||||
return this_port;
|
||||
}
|
||||
|
||||
extern "C" CDECL intptr_t
|
||||
rust_get_test_int() {
|
||||
return 1;
|
||||
|
@ -26,21 +26,8 @@ rust_win32_rand_gen
|
||||
rust_win32_rand_release
|
||||
upcall_rust_personality
|
||||
upcall_reset_stack_limit
|
||||
rust_dbg_lock_create
|
||||
rust_dbg_lock_destroy
|
||||
rust_dbg_lock_lock
|
||||
rust_dbg_lock_unlock
|
||||
rust_dbg_lock_wait
|
||||
rust_dbg_lock_signal
|
||||
rust_dbg_call
|
||||
rust_dbg_do_nothing
|
||||
rust_create_little_lock
|
||||
rust_destroy_little_lock
|
||||
rust_lock_little_lock
|
||||
rust_trylock_little_lock
|
||||
rust_unlock_little_lock
|
||||
rust_signal_little_lock
|
||||
rust_wait_little_lock
|
||||
tdefl_compress_mem_to_heap
|
||||
tinfl_decompress_mem_to_heap
|
||||
rust_swap_registers
|
||||
@ -59,19 +46,12 @@ rust_dbg_extern_return_TwoU32s
|
||||
rust_dbg_extern_return_TwoU64s
|
||||
rust_dbg_extern_identity_double
|
||||
rust_dbg_extern_identity_u8
|
||||
rust_initialize_rt_tls_key
|
||||
rust_dbg_next_port
|
||||
rust_try
|
||||
rust_begin_unwind
|
||||
rust_valgrind_stack_register
|
||||
rust_valgrind_stack_deregister
|
||||
rust_take_env_lock
|
||||
rust_drop_env_lock
|
||||
rust_running_on_valgrind
|
||||
rust_get_num_cpus
|
||||
rust_get_global_args_ptr
|
||||
rust_take_global_args_lock
|
||||
rust_drop_global_args_lock
|
||||
rust_get_test_int
|
||||
rust_pthread_mutex_t_size
|
||||
rust_pthread_cond_t_size
|
||||
|
@ -1,205 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#include "../rust_globals.h"
|
||||
#include "lock_and_signal.h"
|
||||
|
||||
/*
|
||||
* A "lock-and-signal" pair. These are necessarily coupled on pthreads
|
||||
* systems, and artificially coupled (by this file) on win32. Put
|
||||
* together here to minimize ifdefs elsewhere; you must use them as
|
||||
* if you're using a pthreads cvar+mutex pair.
|
||||
*/
|
||||
|
||||
// FIXME (#2683): This is not a portable way of specifying an invalid
|
||||
// pthread_t
|
||||
#define INVALID_THREAD 0
|
||||
|
||||
|
||||
#if defined(__WIN32__)
|
||||
lock_and_signal::lock_and_signal()
|
||||
#if defined(DEBUG_LOCKS)
|
||||
: _holding_thread(INVALID_THREAD)
|
||||
#endif
|
||||
{
|
||||
_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
// If a CRITICAL_SECTION is not initialized with a spin count, it will
|
||||
// default to 0, even on multi-processor systems. MSDN suggests using
|
||||
// 4000. On single-processor systems, the spin count parameter is ignored
|
||||
// and the critical section's spin count defaults to 0.
|
||||
const DWORD SPIN_COUNT = 4000;
|
||||
CHECKED(!InitializeCriticalSectionAndSpinCount(&_cs, SPIN_COUNT));
|
||||
|
||||
// FIXME #2893 Consider checking
|
||||
// GetProcAddress("InitializeCriticalSectionEx")
|
||||
// so Windows >= Vista we can use CRITICAL_SECTION_NO_DEBUG_INFO to avoid
|
||||
// allocating CRITICAL_SECTION debug info that is never released. See:
|
||||
// http://stackoverflow.com/questions/804848/
|
||||
// critical-sections-leaking-memory-on-vista-win2008#889853
|
||||
}
|
||||
|
||||
#else
|
||||
lock_and_signal::lock_and_signal()
|
||||
#if defined(DEBUG_LOCKS)
|
||||
: _holding_thread(INVALID_THREAD)
|
||||
#endif
|
||||
{
|
||||
CHECKED(pthread_cond_init(&_cond, NULL));
|
||||
CHECKED(pthread_mutex_init(&_mutex, NULL));
|
||||
}
|
||||
#endif
|
||||
|
||||
lock_and_signal::~lock_and_signal() {
|
||||
#if defined(__WIN32__)
|
||||
CloseHandle(_event);
|
||||
DeleteCriticalSection(&_cs);
|
||||
#else
|
||||
CHECKED(pthread_cond_destroy(&_cond));
|
||||
CHECKED(pthread_mutex_destroy(&_mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock_and_signal::lock() {
|
||||
must_not_have_lock();
|
||||
#if defined(__WIN32__)
|
||||
EnterCriticalSection(&_cs);
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = GetCurrentThreadId();
|
||||
#endif
|
||||
#else
|
||||
CHECKED(pthread_mutex_lock(&_mutex));
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = pthread_self();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lock_and_signal::try_lock() {
|
||||
must_not_have_lock();
|
||||
#if defined(__WIN32__)
|
||||
if (TryEnterCriticalSection(&_cs)) {
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = GetCurrentThreadId();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#else // non-windows
|
||||
int trylock = pthread_mutex_trylock(&_mutex);
|
||||
if (trylock == 0) {
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = pthread_self();
|
||||
#endif
|
||||
return true;
|
||||
} else if (trylock == EBUSY) {
|
||||
// EBUSY means lock was already held by someone else
|
||||
return false;
|
||||
}
|
||||
// abort on all other errors
|
||||
CHECKED(trylock);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void lock_and_signal::unlock() {
|
||||
must_have_lock();
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = INVALID_THREAD;
|
||||
#endif
|
||||
#if defined(__WIN32__)
|
||||
LeaveCriticalSection(&_cs);
|
||||
#else
|
||||
CHECKED(pthread_mutex_unlock(&_mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait indefinitely until condition is signaled.
|
||||
*/
|
||||
void lock_and_signal::wait() {
|
||||
must_have_lock();
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = INVALID_THREAD;
|
||||
#endif
|
||||
#if defined(__WIN32__)
|
||||
LeaveCriticalSection(&_cs);
|
||||
WaitForSingleObject(_event, INFINITE);
|
||||
EnterCriticalSection(&_cs);
|
||||
must_not_be_locked();
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = GetCurrentThreadId();
|
||||
#endif
|
||||
#else
|
||||
CHECKED(pthread_cond_wait(&_cond, &_mutex));
|
||||
must_not_be_locked();
|
||||
#if defined(DEBUG_LOCKS)
|
||||
_holding_thread = pthread_self();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal condition, and resume the waiting thread.
|
||||
*/
|
||||
void lock_and_signal::signal() {
|
||||
#if defined(__WIN32__)
|
||||
SetEvent(_event);
|
||||
#else
|
||||
CHECKED(pthread_cond_signal(&_cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEBUG_LOCKS)
|
||||
bool lock_and_signal::lock_held_by_current_thread()
|
||||
{
|
||||
#if defined(__WIN32__)
|
||||
return _holding_thread == GetCurrentThreadId();
|
||||
#else
|
||||
return pthread_equal(_holding_thread, pthread_self());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_LOCKS)
|
||||
void lock_and_signal::must_have_lock() {
|
||||
assert(lock_held_by_current_thread() && "must have lock");
|
||||
}
|
||||
void lock_and_signal::must_not_have_lock() {
|
||||
assert(!lock_held_by_current_thread() && "must not have lock");
|
||||
}
|
||||
void lock_and_signal::must_not_be_locked() {
|
||||
}
|
||||
#else
|
||||
void lock_and_signal::must_have_lock() { }
|
||||
void lock_and_signal::must_not_have_lock() { }
|
||||
void lock_and_signal::must_not_be_locked() { }
|
||||
#endif
|
||||
|
||||
scoped_lock::scoped_lock(lock_and_signal &lock)
|
||||
: lock(lock)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
scoped_lock::~scoped_lock()
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
//
|
||||
// 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:
|
@ -1,63 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#ifndef LOCK_AND_SIGNAL_H
|
||||
#define LOCK_AND_SIGNAL_H
|
||||
|
||||
#include "rust_globals.h"
|
||||
|
||||
#ifndef RUST_NDEBUG
|
||||
#define DEBUG_LOCKS
|
||||
#endif
|
||||
|
||||
class lock_and_signal {
|
||||
#if defined(__WIN32__)
|
||||
HANDLE _event;
|
||||
CRITICAL_SECTION _cs;
|
||||
#if defined(DEBUG_LOCKS)
|
||||
DWORD _holding_thread;
|
||||
#endif
|
||||
#else
|
||||
pthread_cond_t _cond;
|
||||
pthread_mutex_t _mutex;
|
||||
#if defined(DEBUG_LOCKS)
|
||||
pthread_t _holding_thread;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_LOCKS)
|
||||
bool lock_held_by_current_thread();
|
||||
#endif
|
||||
|
||||
void must_not_be_locked();
|
||||
|
||||
public:
|
||||
lock_and_signal();
|
||||
virtual ~lock_and_signal();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
void wait();
|
||||
void signal();
|
||||
|
||||
void must_have_lock();
|
||||
void must_not_have_lock();
|
||||
};
|
||||
|
||||
class scoped_lock {
|
||||
lock_and_signal &lock;
|
||||
|
||||
public:
|
||||
scoped_lock(lock_and_signal &lock);
|
||||
~scoped_lock();
|
||||
};
|
||||
|
||||
#endif /* LOCK_AND_SIGNAL_H */
|
Loading…
Reference in New Issue
Block a user