about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2015-04-04 00:46:54 +0300
committerSimonas Kazlauskas <git@kazlauskas.me>2015-04-08 19:42:16 +0300
commit45aa6c8d1bc2f7863c92da6643de4642bb2d83bf (patch)
tree53f8648a696dc49072ceef53c36974f6fc599515 /src/libstd/sys/windows
parent80def6c2447d23a624e611417f24cf0ab2a5a676 (diff)
downloadrust-45aa6c8d1bc2f7863c92da6643de4642bb2d83bf.tar.gz
rust-45aa6c8d1bc2f7863c92da6643de4642bb2d83bf.zip
Implement reentrant mutexes and make stdio use them
write_fmt calls write for each formatted field. The default implementation of write_fmt is used,
which will call write on not-yet-locked stdout (and write locking after), therefore making print!
in multithreaded environment still interleave contents of two separate prints.

This patch implements reentrant mutexes, changes stdio handles to use these mutexes and overrides
write_fmt to lock the stdio handle for the whole duration of the call.
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/mutex.rs31
-rw-r--r--src/libstd/sys/windows/sync.rs18
2 files changed, 48 insertions, 1 deletions
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 0847f3b52bf..ca20858bb5b 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -12,6 +12,7 @@ use prelude::v1::*;
 
 use cell::UnsafeCell;
 use sys::sync as ffi;
+use mem;
 
 pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
 
@@ -57,3 +58,33 @@ impl Mutex {
         // ...
     }
 }
+
+pub struct ReentrantMutex { inner: Box<UnsafeCell<ffi::CRITICAL_SECTION>> }
+
+unsafe impl Send for ReentrantMutex {}
+unsafe impl Sync for ReentrantMutex {}
+
+impl ReentrantMutex {
+    pub unsafe fn new() -> ReentrantMutex {
+        let mutex = ReentrantMutex { inner: box mem::uninitialized() };
+        ffi::InitializeCriticalSection(mutex.inner.get());
+        mutex
+    }
+
+    pub unsafe fn lock(&self) {
+        ffi::EnterCriticalSection(self.inner.get());
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        ffi::TryEnterCriticalSection(self.inner.get()) != 0
+    }
+
+    pub unsafe fn unlock(&self) {
+        ffi::LeaveCriticalSection(self.inner.get());
+    }
+
+    pub unsafe fn destroy(&self) {
+        ffi::DeleteCriticalSection(self.inner.get());
+    }
+}
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
index 7614104c98b..5410259540e 100644
--- a/src/libstd/sys/windows/sync.rs
+++ b/src/libstd/sys/windows/sync.rs
@@ -8,17 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{BOOL, DWORD, LPVOID, c_ulong};
+use libc::{BOOL, DWORD, LPVOID, LONG, HANDLE, c_ulong};
 use libc::types::os::arch::extra::BOOLEAN;
 
 pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
 pub type PSRWLOCK = *mut SRWLOCK;
 pub type ULONG = c_ulong;
+pub type ULONG_PTR = c_ulong;
 
 #[repr(C)]
 pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
 #[repr(C)]
 pub struct SRWLOCK { pub ptr: LPVOID }
+#[repr(C)]
+pub struct CRITICAL_SECTION {
+    CriticalSectionDebug: LPVOID,
+    LockCount: LONG,
+    RecursionCount: LONG,
+    OwningThread: HANDLE,
+    LockSemaphore: HANDLE,
+    SpinCount: ULONG_PTR
+}
 
 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE {
     ptr: 0 as *mut _,
@@ -41,4 +51,10 @@ extern "system" {
     pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
     pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
     pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
+
+    pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
+    pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
+    pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN;
+    pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
+    pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 }