about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sys/windows/c.rs116
-rw-r--r--library/std/src/sys/windows/mutex.rs110
2 files changed, 81 insertions, 145 deletions
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 2b1bc92dc84..f43a19d91b6 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -1020,6 +1020,60 @@ extern "system" {
     pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
     pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
     pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinka
+    pub fn CreateSymbolicLinkW(
+        lpSymlinkFileName: LPCWSTR,
+        lpTargetFileName: LPCWSTR,
+        dwFlags: DWORD,
+    ) -> BOOLEAN;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
+    pub fn GetFinalPathNameByHandleW(
+        hFile: HANDLE,
+        lpszFilePath: LPCWSTR,
+        cchFilePath: DWORD,
+        dwFlags: DWORD,
+    ) -> DWORD;
+
+    // >= Vista / Server 2003
+    // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadstackguarantee
+    #[cfg(not(target_vendor = "uwp"))]
+    pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle
+    pub fn SetFileInformationByHandle(
+        hFile: HANDLE,
+        FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
+        lpFileInformation: LPVOID,
+        dwBufferSize: DWORD,
+    ) -> BOOL;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepconditionvariablesrw
+    pub fn SleepConditionVariableSRW(
+        ConditionVariable: PCONDITION_VARIABLE,
+        SRWLock: PSRWLOCK,
+        dwMilliseconds: DWORD,
+        Flags: ULONG,
+    ) -> BOOL;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakeconditionvariable
+    pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
+    pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-acquiresrwlockexclusive
+    pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
+    pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
 }
 
 // Functions that aren't available on every version of Windows that we support,
@@ -1027,70 +1081,26 @@ extern "system" {
 compat_fn! {
     "kernel32":
 
-    pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
-                               _lpTargetFileName: LPCWSTR,
-                               _dwFlags: DWORD) -> BOOLEAN {
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
-    }
-    pub fn GetFinalPathNameByHandleW(_hFile: HANDLE,
-                                     _lpszFilePath: LPCWSTR,
-                                     _cchFilePath: DWORD,
-                                     _dwFlags: DWORD) -> DWORD {
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
-    }
-    #[cfg(not(target_vendor = "uwp"))]
-    pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
-    }
+    // >= Win10 1607
+    // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
     pub fn SetThreadDescription(hThread: HANDLE,
                                 lpThreadDescription: LPCWSTR) -> HRESULT {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
     }
-    pub fn SetFileInformationByHandle(_hFile: HANDLE,
-                    _FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
-                    _lpFileInformation: LPVOID,
-                    _dwBufferSize: DWORD) -> BOOL {
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
-    }
+
+    // >= Win8 / Server 2012
+    // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
     pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
                                           -> () {
         GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
     }
-    pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
-                                     SRWLock: PSRWLOCK,
-                                     dwMilliseconds: DWORD,
-                                     Flags: ULONG) -> BOOL {
-        panic!("condition variables not available")
-    }
-    pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
-                                 -> () {
-        panic!("condition variables not available")
-    }
-    pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
-                                    -> () {
-        panic!("condition variables not available")
-    }
-    pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
-        panic!("rwlocks not available")
-    }
-    pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK) -> () {
-        panic!("rwlocks not available")
-    }
-    pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
-        panic!("rwlocks not available")
-    }
-    pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK) -> () {
-        panic!("rwlocks not available")
-    }
-    pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN {
-        panic!("rwlocks not available")
-    }
-    pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN {
-        panic!("rwlocks not available")
-    }
 }
+
 compat_fn! {
     "api-ms-win-core-synch-l1-2-0":
+
+    // >= Windows 8 / Server 2012
+    // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
     pub fn WaitOnAddress(
         Address: LPVOID,
         CompareAddress: LPVOID,
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index d4cc56d4cb3..72a0993d94d 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -13,20 +13,13 @@
 //!
 //! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
 //!    is that there are no guarantees of fairness.
-//!
-//! The downside of this approach, however, is that SRWLock is not available on
-//! Windows XP, so we continue to have a fallback implementation where
-//! CriticalSection is used and we keep track of who's holding the mutex to
-//! detect recursive locks.
-
-use crate::cell::{Cell, UnsafeCell};
-use crate::mem::{self, MaybeUninit};
-use crate::sync::atomic::{AtomicUsize, Ordering};
+
+use crate::cell::UnsafeCell;
+use crate::mem::MaybeUninit;
 use crate::sys::c;
 
 pub struct Mutex {
-    // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
-    lock: AtomicUsize,
+    srwlock: UnsafeCell<c::SRWLOCK>,
 }
 
 // Windows SRW Locks are movable (while not borrowed).
@@ -37,106 +30,39 @@ pub type MovableMutex = Mutex;
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
-struct Inner {
-    remutex: ReentrantMutex,
-    held: Cell<bool>,
-}
-
-#[derive(Clone, Copy)]
-enum Kind {
-    SRWLock,
-    CriticalSection,
-}
-
 #[inline]
 pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
-    debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
-    &m.lock as *const _ as *mut _
+    m.srwlock.get()
 }
 
 impl Mutex {
     pub const fn new() -> Mutex {
-        Mutex {
-            // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
-            // initializing an SRWLOCK here.
-            lock: AtomicUsize::new(0),
-        }
+        Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
     }
     #[inline]
     pub unsafe fn init(&mut self) {}
+
+    #[inline]
     pub unsafe fn lock(&self) {
-        match kind() {
-            Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
-            Kind::CriticalSection => {
-                let inner = &*self.inner();
-                inner.remutex.lock();
-                if inner.held.replace(true) {
-                    // It was already locked, so we got a recursive lock which we do not want.
-                    inner.remutex.unlock();
-                    panic!("cannot recursively lock a mutex");
-                }
-            }
-        }
+        c::AcquireSRWLockExclusive(raw(self));
     }
+
+    #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        match kind() {
-            Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
-            Kind::CriticalSection => {
-                let inner = &*self.inner();
-                if !inner.remutex.try_lock() {
-                    false
-                } else if inner.held.replace(true) {
-                    // It was already locked, so we got a recursive lock which we do not want.
-                    inner.remutex.unlock();
-                    false
-                } else {
-                    true
-                }
-            }
-        }
+        c::TryAcquireSRWLockExclusive(raw(self)) != 0
     }
+
+    #[inline]
     pub unsafe fn unlock(&self) {
-        match kind() {
-            Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
-            Kind::CriticalSection => {
-                let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
-                inner.held.set(false);
-                inner.remutex.unlock();
-            }
-        }
-    }
-    pub unsafe fn destroy(&self) {
-        match kind() {
-            Kind::SRWLock => {}
-            Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
-                0 => {}
-                n => Box::from_raw(n as *mut Inner).remutex.destroy(),
-            },
-        }
+        c::ReleaseSRWLockExclusive(raw(self));
     }
 
-    unsafe fn inner(&self) -> *const Inner {
-        match self.lock.load(Ordering::SeqCst) {
-            0 => {}
-            n => return n as *const _,
-        }
-        let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
-        inner.remutex.init();
-        let inner = Box::into_raw(inner);
-        match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) {
-            Ok(_) => inner,
-            Err(n) => {
-                Box::from_raw(inner).remutex.destroy();
-                n as *const _
-            }
-        }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        // SRWLock does not need to be destroyed.
     }
 }
 
-fn kind() -> Kind {
-    if c::AcquireSRWLockExclusive::is_available() { Kind::SRWLock } else { Kind::CriticalSection }
-}
-
 pub struct ReentrantMutex {
     inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
 }