about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-18 21:51:31 -0800
committerbors <bors@rust-lang.org>2013-11-18 21:51:31 -0800
commitf5f5d5aac762a554850d291165536ba752260303 (patch)
tree56afc4b9b834d4496c175a3ab701823dbba72e15 /src/libstd
parentab7fe9dd06e93986f6b11512031c891059474653 (diff)
parent508b7b996e5d557ec1c49e1d11563ecf4fc9d287 (diff)
auto merge of #10479 : alexcrichton/rust/native-mutex.rs, r=cmr
This adds a new `std::unstable::mutex` module which contains bindings to the platform-provided mutexes. This module is pretty much entirely unsafe to use, but is critical for the runtime and dropping our C++ dependency.

The actual implementation is to do a compare-and-swap on an initially uninitialized pointer. Pthreads does allow for static initialization, so this wouldn't be necessary if we had all the proper headers and whatnot, but windows it looks like will always require some sort of compare-and-swap operation. For now, I didn't want to have to define all the pthreads headers, so I continue to just malloc the pthreads lock/cvar.

After this, there's only one remaining C++ component of rust, and that's unwinding.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/os.rs12
-rw-r--r--src/libstd/rt/args.rs54
-rw-r--r--src/libstd/rt/local_ptr.rs12
-rw-r--r--src/libstd/rt/test.rs20
-rw-r--r--src/libstd/task/mod.rs34
-rw-r--r--src/libstd/unstable/dynamic_lib.rs12
-rw-r--r--src/libstd/unstable/mod.rs1
-rw-r--r--src/libstd/unstable/mutex.rs336
-rw-r--r--src/libstd/unstable/sync.rs41
9 files changed, 428 insertions, 94 deletions
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 213cf5dc07c..3ea6e18f942 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -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
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index 48e58879026..0d32d2d7dba 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -21,46 +21,60 @@
 //! 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")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
 mod imp {
+    use cast;
     use libc;
     use option::{Option, Some, None};
     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 +108,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 +133,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};
diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs
index f35b657d9dd..d5d1931a217 100644
--- a/src/libstd/rt/local_ptr.rs
+++ b/src/libstd/rt/local_ptr.rs
@@ -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();
     }
 }
 
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index 19ab36a6ac4..c1a7893f5a5 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -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),
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 51c11b69972..5a2251eaa46 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -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();
         }
     }
 }
diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs
index 1ce228250c9..e0d284a32df 100644
--- a/src/libstd/unstable/dynamic_lib.rs
+++ b/src/libstd/unstable/dynamic_lib.rs
@@ -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;
diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs
index ea03ea6f551..9b8c81979a9 100644
--- a/src/libstd/unstable/mod.rs
+++ b/src/libstd/unstable/mod.rs
@@ -24,6 +24,7 @@ pub mod simd;
 #[cfg(not(test))]
 pub mod lang;
 pub mod sync;
+pub mod mutex;
 pub mod atomics;
 pub mod raw;
 
diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs
new file mode 100644
index 00000000000..5be9be7bf8a
--- /dev/null
+++ b/src/libstd/unstable/mutex.rs
@@ -0,0 +1,336 @@
+// Copyright 2013 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.
+
+//! A native mutex and condition variable type
+//!
+//! This module contains bindings to the platform's native mutex/condition
+//! variable primitives. It provides a single type, `Mutex`, which can be
+//! statically initialized via the `MUTEX_INIT` value. This object serves as both a
+//! mutex and a condition variable simultaneously.
+//!
+//! The lock is lazily initialized, but it can only be unsafely destroyed. A
+//! statically initialized lock doesn't necessarily have a time at which it can
+//! get deallocated. For this reason, there is no `Drop` implementation of the
+//! mutex, but rather the `destroy()` method must be invoked manually if
+//! destruction of the mutex is desired.
+//!
+//! It is not recommended to use this type for idiomatic rust use. This type is
+//! appropriate where no other options are available, but other rust concurrency
+//! primitives should be used before this type.
+//!
+//! # Example
+//!
+//!     use std::unstable::mutex::{Mutex, MUTEX_INIT};
+//!
+//!     // Use a statically initialized mutex
+//!     static mut lock: Mutex = MUTEX_INIT;
+//!
+//!     unsafe {
+//!         lock.lock();
+//!         lock.unlock();
+//!     }
+//!
+//!     // Use a normally initialied mutex
+//!     let mut lock = Mutex::new();
+//!     unsafe {
+//!         lock.lock();
+//!         lock.unlock();
+//!         lock.destroy();
+//!     }
+
+#[allow(non_camel_case_types)];
+
+use libc::c_void;
+use unstable::atomics;
+
+pub struct Mutex {
+    // pointers for the lock/cond handles, atomically updated
+    priv lock: atomics::AtomicUint,
+    priv cond: atomics::AtomicUint,
+}
+
+pub static MUTEX_INIT: Mutex = Mutex {
+    lock: atomics::INIT_ATOMIC_UINT,
+    cond: atomics::INIT_ATOMIC_UINT,
+};
+
+impl Mutex {
+    /// Creates a new mutex, with the lock/condition variable pre-initialized
+    pub unsafe fn new() -> Mutex {
+        Mutex {
+            lock: atomics::AtomicUint::new(imp::init_lock() as uint),
+            cond: atomics::AtomicUint::new(imp::init_cond() as uint),
+        }
+    }
+
+    /// Creates a new copy of this mutex. This is an unsafe operation because
+    /// there is no reference counting performed on this type.
+    ///
+    /// This function may only be called on mutexes which have had both the
+    /// internal condition variable and lock initialized. This means that the
+    /// mutex must have been created via `new`, or usage of it has already
+    /// initialized the internal handles.
+    ///
+    /// This is a dangerous function to call as both this mutex and the returned
+    /// mutex will share the same handles to the underlying mutex/condition
+    /// variable. Care must be taken to ensure that deallocation happens
+    /// accordingly.
+    pub unsafe fn clone(&self) -> Mutex {
+        let lock = self.lock.load(atomics::Relaxed);
+        let cond = self.cond.load(atomics::Relaxed);
+        assert!(lock != 0);
+        assert!(cond != 0);
+        Mutex {
+            lock: atomics::AtomicUint::new(lock),
+            cond: atomics::AtomicUint::new(cond),
+        }
+    }
+
+    /// Acquires this lock. This assumes that the current thread does not
+    /// already hold the lock.
+    pub unsafe fn lock(&mut self) { imp::lock(self.getlock()) }
+
+    /// Attempts to acquire the lock. The value returned is whether the lock was
+    /// acquired or not
+    pub unsafe fn trylock(&mut self) -> bool { imp::trylock(self.getlock()) }
+
+    /// Unlocks the lock. This assumes that the current thread already holds the
+    /// lock.
+    pub unsafe fn unlock(&mut self) { imp::unlock(self.getlock()) }
+
+    /// Block on the internal condition variable.
+    ///
+    /// This function assumes that the lock is already held
+    pub unsafe fn wait(&mut self) { imp::wait(self.getcond(), self.getlock()) }
+
+    /// Signals a thread in `wait` to wake up
+    pub unsafe fn signal(&mut self) { imp::signal(self.getcond()) }
+
+    /// This function is especially unsafe because there are no guarantees made
+    /// that no other thread is currently holding the lock or waiting on the
+    /// condition variable contained inside.
+    pub unsafe fn destroy(&mut self) {
+        imp::free_lock(self.lock.swap(0, atomics::Relaxed));
+        imp::free_cond(self.cond.swap(0, atomics::Relaxed));
+    }
+
+    unsafe fn getlock(&mut self) -> *c_void {
+        match self.lock.load(atomics::Relaxed) {
+            0 => {}
+            n => return n as *c_void
+        }
+        let lock = imp::init_lock();
+        match self.lock.compare_and_swap(0, lock, atomics::SeqCst) {
+            0 => return lock as *c_void,
+            _ => {}
+        }
+        imp::free_lock(lock);
+        return self.lock.load(atomics::Relaxed) as *c_void;
+    }
+
+    unsafe fn getcond(&mut self) -> *c_void {
+        match self.cond.load(atomics::Relaxed) {
+            0 => {}
+            n => return n as *c_void
+        }
+        let cond = imp::init_cond();
+        match self.cond.compare_and_swap(0, cond, atomics::SeqCst) {
+            0 => return cond as *c_void,
+            _ => {}
+        }
+        imp::free_cond(cond);
+        return self.cond.load(atomics::Relaxed) as *c_void;
+    }
+}
+
+#[cfg(unix)]
+mod imp {
+    use libc::c_void;
+    use libc;
+    use ptr;
+
+    type pthread_mutex_t = libc::c_void;
+    type pthread_mutexattr_t = libc::c_void;
+    type pthread_cond_t = libc::c_void;
+    type pthread_condattr_t = libc::c_void;
+
+    pub unsafe fn init_lock() -> uint {
+        let block = libc::malloc(rust_pthread_mutex_t_size() as libc::size_t);
+        assert!(!block.is_null());
+        let n = pthread_mutex_init(block, ptr::null());
+        assert_eq!(n, 0);
+        return block as uint;
+    }
+
+    pub unsafe fn init_cond() -> uint {
+        let block = libc::malloc(rust_pthread_cond_t_size() as libc::size_t);
+        assert!(!block.is_null());
+        let n = pthread_cond_init(block, ptr::null());
+        assert_eq!(n, 0);
+        return block as uint;
+    }
+
+    pub unsafe fn free_lock(h: uint) {
+        let block = h as *c_void;
+        assert_eq!(pthread_mutex_destroy(block), 0);
+        libc::free(block);
+    }
+
+    pub unsafe fn free_cond(h: uint) {
+        let block = h as *c_void;
+        assert_eq!(pthread_cond_destroy(block), 0);
+        libc::free(block);
+    }
+
+    pub unsafe fn lock(l: *pthread_mutex_t) {
+        assert_eq!(pthread_mutex_lock(l), 0);
+    }
+
+    pub unsafe fn trylock(l: *c_void) -> bool {
+        pthread_mutex_trylock(l) == 0
+    }
+
+    pub unsafe fn unlock(l: *pthread_mutex_t) {
+        assert_eq!(pthread_mutex_unlock(l), 0);
+    }
+
+    pub unsafe fn wait(cond: *pthread_cond_t, m: *pthread_mutex_t) {
+        assert_eq!(pthread_cond_wait(cond, m), 0);
+    }
+
+    pub unsafe fn signal(cond: *pthread_cond_t) {
+        assert_eq!(pthread_cond_signal(cond), 0);
+    }
+
+    extern {
+        fn rust_pthread_mutex_t_size() -> libc::c_int;
+        fn rust_pthread_cond_t_size() -> libc::c_int;
+    }
+
+    extern {
+        fn pthread_mutex_init(lock: *pthread_mutex_t,
+                              attr: *pthread_mutexattr_t) -> libc::c_int;
+        fn pthread_mutex_destroy(lock: *pthread_mutex_t) -> libc::c_int;
+        fn pthread_cond_init(cond: *pthread_cond_t,
+                              attr: *pthread_condattr_t) -> libc::c_int;
+        fn pthread_cond_destroy(cond: *pthread_cond_t) -> libc::c_int;
+        fn pthread_mutex_lock(lock: *pthread_mutex_t) -> libc::c_int;
+        fn pthread_mutex_trylock(lock: *pthread_mutex_t) -> libc::c_int;
+        fn pthread_mutex_unlock(lock: *pthread_mutex_t) -> libc::c_int;
+
+        fn pthread_cond_wait(cond: *pthread_cond_t,
+                             lock: *pthread_mutex_t) -> libc::c_int;
+        fn pthread_cond_signal(cond: *pthread_cond_t) -> libc::c_int;
+    }
+}
+
+#[cfg(windows)]
+mod imp {
+    use libc;
+    use libc::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES, c_void, DWORD, LPCSTR};
+    use ptr;
+    type LPCRITICAL_SECTION = *c_void;
+    static SPIN_COUNT: DWORD = 4000;
+
+    pub unsafe fn init_lock() -> uint {
+        let block = libc::malloc(rust_crit_section_size() as libc::size_t);
+        assert!(!block.is_null());
+        InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
+        return block as uint;
+    }
+
+    pub unsafe fn init_cond() -> uint {
+        return CreateEventA(ptr::mut_null(), libc::FALSE, libc::FALSE,
+                            ptr::null()) as uint;
+    }
+
+    pub unsafe fn free_lock(h: uint) {
+        DeleteCriticalSection(h as LPCRITICAL_SECTION);
+        libc::free(h as *c_void);
+    }
+
+    pub unsafe fn free_cond(h: uint) {
+        let block = h as HANDLE;
+        libc::CloseHandle(block);
+    }
+
+    pub unsafe fn lock(l: *c_void) {
+        EnterCriticalSection(l as LPCRITICAL_SECTION)
+    }
+
+    pub unsafe fn trylock(l: *c_void) -> bool {
+        TryEnterCriticalSection(l as LPCRITICAL_SECTION) != 0
+    }
+
+    pub unsafe fn unlock(l: *c_void) {
+        LeaveCriticalSection(l as LPCRITICAL_SECTION)
+    }
+
+    pub unsafe fn wait(cond: *c_void, m: *c_void) {
+        unlock(m);
+        WaitForSingleObject(cond as HANDLE, 0);
+        lock(m);
+    }
+
+    pub unsafe fn signal(cond: *c_void) {
+        assert!(SetEvent(cond as HANDLE) != 0);
+    }
+
+    extern {
+        fn rust_crit_section_size() -> libc::c_int;
+    }
+
+    extern "system" {
+        fn CreateEventA(lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
+                        bManualReset: BOOL,
+                        bInitialState: BOOL,
+                        lpName: LPCSTR) -> HANDLE;
+        fn InitializeCriticalSectionAndSpinCount(
+                        lpCriticalSection: LPCRITICAL_SECTION,
+                        dwSpinCount: DWORD) -> BOOL;
+        fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+        fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+        fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+        fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL;
+        fn SetEvent(hEvent: HANDLE) -> BOOL;
+        fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::{Mutex, MUTEX_INIT};
+    use rt::thread::Thread;
+
+    #[test]
+    fn somke_lock() {
+        static mut lock: Mutex = MUTEX_INIT;
+        unsafe {
+            lock.lock();
+            lock.unlock();
+        }
+    }
+
+    #[test]
+    fn somke_cond() {
+        static mut lock: Mutex = MUTEX_INIT;
+        unsafe {
+            let t = do Thread::start {
+                lock.lock();
+                lock.signal();
+                lock.unlock();
+            };
+            lock.lock();
+            lock.wait();
+            lock.unlock();
+            t.join();
+        }
+    }
+}
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index 0e1f5fc1bdc..3423b995fda 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -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;