use sys::os;
use os::windows::prelude::*;
use ptr;
- use sys::c::compat::kernel32::SetThreadErrorMode;
+ use sys::c::SetThreadErrorMode;
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
// disable "dll load failed" error dialog.
#![allow(bad_style, dead_code, overflowing_literals)]
use libc;
+use libc::{c_uint, c_ulong};
+use libc::{DWORD, BOOL, BOOLEAN, ERROR_CALL_NOT_IMPLEMENTED, LPVOID, HANDLE};
+use libc::{LPCWSTR, LONG};
pub use self::GET_FILEEX_INFO_LEVELS::*;
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub PathBuffer: libc::WCHAR,
}
+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 _,
+};
+pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
+
#[link(name = "ws2_32")]
+#[link(name = "userenv")]
extern "system" {
pub fn WSAStartup(wVersionRequested: libc::WORD,
lpWSAData: LPWSADATA) -> libc::c_int;
pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
pub fn CancelIoEx(hFile: libc::HANDLE,
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
-}
-
-pub mod compat {
- use prelude::v1::*;
- use ffi::CString;
- use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
- use sync::atomic::{AtomicUsize, Ordering};
+ 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);
- extern "system" {
- fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
- fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
- }
-
- fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
- fallback: usize) -> usize {
- let mut module: Vec<u16> = module.utf16_units().collect();
- module.push(0);
- let symbol = CString::new(symbol).unwrap();
- let func = unsafe {
- let handle = GetModuleHandleW(module.as_ptr());
- GetProcAddress(handle, symbol.as_ptr()) as usize
- };
- let value = if func == 0 {fallback} else {func};
- ptr.store(value, Ordering::SeqCst);
- value
- }
-
- /// Macro for creating a compatibility fallback for a Windows function
- ///
- /// # Examples
- /// ```
- /// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) {
- /// // Fallback implementation
- /// })
- /// ```
- ///
- /// Note that arguments unused by the fallback implementation should not be
- /// called `_` as they are used to be passed to the real function if
- /// available.
- macro_rules! compat_fn {
- ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
- -> $rettype:ty { $fallback:expr }) => (
- #[inline(always)]
- pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
- use sync::atomic::{AtomicUsize, Ordering};
- use mem;
-
- static PTR: AtomicUsize = AtomicUsize::new(0);
-
- fn load() -> usize {
- ::sys::c::compat::store_func(&PTR,
- stringify!($module),
- stringify!($symbol),
- fallback as usize)
- }
-
- extern "system" fn fallback($($argname: $argtype),*)
- -> $rettype { $fallback }
-
- let addr = match PTR.load(Ordering::SeqCst) {
- 0 => load(),
- n => n,
- };
- let f: extern "system" fn($($argtype),*) -> $rettype =
- mem::transmute(addr);
- f($($argname),*)
- }
- )
- }
-
- /// Compatibility layer for functions in `kernel32.dll`
- ///
- /// Latest versions of Windows this is needed for:
- ///
- /// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
- /// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
- pub mod kernel32 {
- use libc::c_uint;
- use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
- use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
- use sys::c::SetLastError;
-
- compat_fn! {
- kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
- _lpTargetFileName: LPCWSTR,
- _dwFlags: DWORD) -> BOOLEAN {
- unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
- }
- }
-
- compat_fn! {
- kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
- _lpszFilePath: LPCWSTR,
- _cchFilePath: DWORD,
- _dwFlags: DWORD) -> DWORD {
- unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
- }
- }
-
- compat_fn! {
- kernel32::SetThreadErrorMode(_dwNewMode: DWORD, _lpOldMode: *mut DWORD) -> c_uint {
- unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
- }
- }
- }
-}
-
-extern "system" {
// FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
pub fn ReadConsoleW(hConsoleInput: libc::HANDLE,
lpBuffer: libc::LPVOID,
lpCreationTime: *const libc::FILETIME,
lpLastAccessTime: *const libc::FILETIME,
lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL;
- pub fn SetFileInformationByHandle(hFile: libc::HANDLE,
- FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
- lpFileInformation: libc::LPVOID,
- dwBufferSize: libc::DWORD) -> libc::BOOL;
pub fn GetTempPathW(nBufferLength: libc::DWORD,
lpBuffer: libc::LPCWSTR) -> libc::DWORD;
pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
pub fn SwitchToThread() -> libc::BOOL;
pub fn Sleep(dwMilliseconds: libc::DWORD);
pub fn GetProcessId(handle: libc::HANDLE) -> libc::DWORD;
-}
-
-#[link(name = "userenv")]
-extern "system" {
pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
lpProfileDir: libc::LPCWSTR,
lpcchSize: *mut libc::DWORD) -> libc::BOOL;
}
+
+// Functions that aren't available on Windows XP, but we still use them and just
+// provide some form of a fallback implementation.
+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
+ }
+ pub fn SetThreadErrorMode(_dwNewMode: DWORD,
+ _lpOldMode: *mut DWORD) -> c_uint {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
+ }
+ pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
+ }
+ pub fn SetFileInformationByHandle(_hFile: HANDLE,
+ _FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
+ _lpFileInformation: LPVOID,
+ _dwBufferSize: DWORD) -> BOOL {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
+ }
+ 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")
+ }
+}
--- /dev/null
+// Copyright 2014 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 "compatibility layer" for spanning XP and Windows 7
+//!
+//! The standard library currently binds many functions that are not available
+//! on Windows XP, but we would also like to support building executables that
+//! run on XP. To do this we specify all non-XP APIs as having a fallback
+//! implementation to do something reasonable.
+//!
+//! This dynamic runtime detection of whether a function is available is
+//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
+//! static-per-function which caches the result of the first check. In this
+//! manner we pay a semi-large one-time cost up front for detecting whether a
+//! function is available but afterwards it's just a load and a jump.
+
+use prelude::v1::*;
+
+use ffi::CString;
+use libc::{LPVOID, LPCWSTR, HMODULE, LPCSTR};
+use sync::atomic::{AtomicUsize, Ordering};
+
+extern "system" {
+ fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
+ fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
+}
+
+pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
+ let mut module: Vec<u16> = module.utf16_units().collect();
+ module.push(0);
+ let symbol = CString::new(symbol).unwrap();
+ unsafe {
+ let handle = GetModuleHandleW(module.as_ptr());
+ match GetProcAddress(handle, symbol.as_ptr()) as usize {
+ 0 => None,
+ n => Some(n),
+ }
+ }
+}
+
+pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
+ fallback: usize) -> usize {
+ let value = lookup(module, symbol).unwrap_or(fallback);
+ ptr.store(value, Ordering::SeqCst);
+ value
+}
+
+macro_rules! compat_fn {
+ ($module:ident: $(
+ pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
+ -> $rettype:ty {
+ $($body:expr);*
+ }
+ )*) => ($(
+ #[allow(unused_variables)]
+ pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
+ use sync::atomic::{AtomicUsize, Ordering};
+ use mem;
+ type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
+
+ static PTR: AtomicUsize = AtomicUsize::new(0);
+
+ fn load() -> usize {
+ ::sys::compat::store_func(&PTR,
+ stringify!($module),
+ stringify!($symbol),
+ fallback as usize)
+ }
+ unsafe extern "system" fn fallback($($argname: $argtype),*)
+ -> $rettype {
+ $($body);*
+ }
+
+ let addr = match PTR.load(Ordering::SeqCst) {
+ 0 => load(),
+ n => n,
+ };
+ mem::transmute::<usize, F>(addr)($($argname),*)
+ }
+ )*)
+}
use cell::UnsafeCell;
use libc::{self, DWORD};
-use sys::os;
+use sys::c;
use sys::mutex::{self, Mutex};
-use sys::sync as ffi;
+use sys::os;
use time::Duration;
-pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
+pub struct Condvar { inner: UnsafeCell<c::CONDITION_VARIABLE> }
unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}
impl Condvar {
pub const fn new() -> Condvar {
- Condvar { inner: UnsafeCell::new(ffi::CONDITION_VARIABLE_INIT) }
+ Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) }
}
#[inline]
pub unsafe fn wait(&self, mutex: &Mutex) {
- let r = ffi::SleepConditionVariableSRW(self.inner.get(),
- mutex::raw(mutex),
- libc::INFINITE,
- 0);
+ let r = c::SleepConditionVariableSRW(self.inner.get(),
+ mutex::raw(mutex),
+ libc::INFINITE,
+ 0);
debug_assert!(r != 0);
}
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- let r = ffi::SleepConditionVariableSRW(self.inner.get(),
- mutex::raw(mutex),
- super::dur2timeout(dur),
- 0);
+ let r = c::SleepConditionVariableSRW(self.inner.get(),
+ mutex::raw(mutex),
+ super::dur2timeout(dur),
+ 0);
if r == 0 {
const ERROR_TIMEOUT: DWORD = 0x5B4;
debug_assert_eq!(os::errno() as usize, ERROR_TIMEOUT as usize);
#[inline]
pub unsafe fn notify_one(&self) {
- ffi::WakeConditionVariable(self.inner.get())
+ c::WakeConditionVariable(self.inner.get())
}
#[inline]
pub unsafe fn notify_all(&self) {
- ffi::WakeAllConditionVariable(self.inner.get())
+ c::WakeAllConditionVariable(self.inner.get())
}
pub unsafe fn destroy(&self) {
}
pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
- use sys::c::compat::kernel32::CreateSymbolicLinkW;
let src = to_utf16(src);
let dst = to_utf16(dst);
let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
try!(cvt(unsafe {
- CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL
+ c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL
}));
Ok(())
}
}
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
- use sys::c::compat::kernel32::GetFinalPathNameByHandleW;
let mut opts = OpenOptions::new();
opts.read(true);
let f = try!(File::open(p, &opts));
super::fill_utf16_buf(|buf, sz| unsafe {
- GetFinalPathNameByHandleW(f.handle.raw(), buf, sz,
- libc::VOLUME_NAME_DOS)
+ c::GetFinalPathNameByHandleW(f.handle.raw(), buf, sz,
+ libc::VOLUME_NAME_DOS)
}, |buf| {
PathBuf::from(OsString::from_wide(buf))
})
use path::PathBuf;
use time::Duration;
+#[macro_use] pub mod compat;
+
pub mod backtrace;
pub mod c;
pub mod condvar;
pub mod process;
pub mod rwlock;
pub mod stack_overflow;
-pub mod sync;
pub mod thread;
pub mod thread_local;
pub mod time;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+//! System Mutexes
+//!
+//! The Windows implementation of mutexes is a little odd and it may not be
+//! immediately obvious what's going on. The primary oddness is that SRWLock is
+//! used instead of CriticalSection, and this is done because:
+//!
+//! 1. SRWLock is several times faster than CriticalSection according to
+//! benchmarks performed on both Windows 8 and Windows 7.
+//!
+//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
+//! Unix implementation deadlocks so consistency is preferred. See #19962 for
+//! more details.
+//!
+//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
+//! is there 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 prelude::v1::*;
use cell::UnsafeCell;
-use sys::sync as ffi;
use mem;
+use sync::atomic::{AtomicUsize, Ordering};
+use sys::c;
+use sys::compat;
-pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
+pub struct Mutex {
+ lock: AtomicUsize,
+ held: UnsafeCell<bool>,
+}
unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}
-#[inline]
-pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
- m.inner.get()
+#[derive(Clone, Copy)]
+enum Kind {
+ SRWLock = 1,
+ CriticalSection = 2,
}
-// So you might be asking why we're using SRWLock instead of CriticalSection?
-//
-// 1. SRWLock is several times faster than CriticalSection according to
-// benchmarks performed on both Windows 8 and Windows 7.
-//
-// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix
-// implementation deadlocks so consistency is preferred. See #19962 for more
-// details.
-//
-// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
-// is there there are no guarantees of fairness.
+#[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 _
+}
impl Mutex {
pub const fn new() -> Mutex {
- Mutex { inner: UnsafeCell::new(ffi::SRWLOCK_INIT) }
+ Mutex {
+ lock: AtomicUsize::new(0),
+ held: UnsafeCell::new(false),
+ }
}
- #[inline]
pub unsafe fn lock(&self) {
- ffi::AcquireSRWLockExclusive(self.inner.get())
+ match kind() {
+ Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
+ Kind::CriticalSection => {
+ let re = self.remutex();
+ (*re).lock();
+ if !self.flag_locked() {
+ (*re).unlock();
+ panic!("cannot recursively lock a mutex");
+ }
+ }
+ }
}
- #[inline]
pub unsafe fn try_lock(&self) -> bool {
- ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
+ match kind() {
+ Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
+ Kind::CriticalSection => {
+ let re = self.remutex();
+ if !(*re).try_lock() {
+ false
+ } else if self.flag_locked() {
+ true
+ } else {
+ (*re).unlock();
+ false
+ }
+ }
+ }
}
- #[inline]
pub unsafe fn unlock(&self) {
- ffi::ReleaseSRWLockExclusive(self.inner.get())
+ *self.held.get() = false;
+ match kind() {
+ Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
+ Kind::CriticalSection => (*self.remutex()).unlock(),
+ }
}
- #[inline]
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 ReentrantMutex).destroy(); }
+ }
+ }
+ }
+ }
+
+ unsafe fn remutex(&self) -> *mut ReentrantMutex {
+ match self.lock.load(Ordering::SeqCst) {
+ 0 => {}
+ n => return n as *mut _,
+ }
+ let mut re = Box::new(ReentrantMutex::uninitialized());
+ re.init();
+ let re = Box::into_raw(re);
+ match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
+ 0 => re,
+ n => { Box::from_raw(re).destroy(); n as *mut _ }
+ }
+ }
+
+ unsafe fn flag_locked(&self) -> bool {
+ if *self.held.get() {
+ false
+ } else {
+ *self.held.get() = true;
+ true
+ }
+
}
}
-pub struct ReentrantMutex { inner: UnsafeCell<ffi::CRITICAL_SECTION> }
+fn kind() -> Kind {
+ static KIND: AtomicUsize = AtomicUsize::new(0);
+
+ let val = KIND.load(Ordering::SeqCst);
+ if val == Kind::SRWLock as usize {
+ return Kind::SRWLock
+ } else if val == Kind::CriticalSection as usize {
+ return Kind::CriticalSection
+ }
+
+ let ret = match compat::lookup("kernel32", "AcquireSRWLockExclusive") {
+ None => Kind::CriticalSection,
+ Some(..) => Kind::SRWLock,
+ };
+ KIND.store(ret as usize, Ordering::SeqCst);
+ return ret;
+}
+
+pub struct ReentrantMutex { inner: UnsafeCell<c::CRITICAL_SECTION> }
unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}
}
pub unsafe fn init(&mut self) {
- ffi::InitializeCriticalSection(self.inner.get());
+ c::InitializeCriticalSection(self.inner.get());
}
pub unsafe fn lock(&self) {
- ffi::EnterCriticalSection(self.inner.get());
+ c::EnterCriticalSection(self.inner.get());
}
#[inline]
pub unsafe fn try_lock(&self) -> bool {
- ffi::TryEnterCriticalSection(self.inner.get()) != 0
+ c::TryEnterCriticalSection(self.inner.get()) != 0
}
pub unsafe fn unlock(&self) {
- ffi::LeaveCriticalSection(self.inner.get());
+ c::LeaveCriticalSection(self.inner.get());
}
pub unsafe fn destroy(&self) {
- ffi::DeleteCriticalSection(self.inner.get());
+ c::DeleteCriticalSection(self.inner.get());
}
}
use prelude::v1::*;
use cell::UnsafeCell;
-use sys::sync as ffi;
+use sys::c;
-pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
+pub struct RWLock { inner: UnsafeCell<c::SRWLOCK> }
unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}
impl RWLock {
pub const fn new() -> RWLock {
- RWLock { inner: UnsafeCell::new(ffi::SRWLOCK_INIT) }
+ RWLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) }
}
#[inline]
pub unsafe fn read(&self) {
- ffi::AcquireSRWLockShared(self.inner.get())
+ c::AcquireSRWLockShared(self.inner.get())
}
#[inline]
pub unsafe fn try_read(&self) -> bool {
- ffi::TryAcquireSRWLockShared(self.inner.get()) != 0
+ c::TryAcquireSRWLockShared(self.inner.get()) != 0
}
#[inline]
pub unsafe fn write(&self) {
- ffi::AcquireSRWLockExclusive(self.inner.get())
+ c::AcquireSRWLockExclusive(self.inner.get())
}
#[inline]
pub unsafe fn try_write(&self) -> bool {
- ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
+ c::TryAcquireSRWLockExclusive(self.inner.get()) != 0
}
#[inline]
pub unsafe fn read_unlock(&self) {
- ffi::ReleaseSRWLockShared(self.inner.get())
+ c::ReleaseSRWLockShared(self.inner.get())
}
#[inline]
pub unsafe fn write_unlock(&self) {
- ffi::ReleaseSRWLockExclusive(self.inner.get())
+ c::ReleaseSRWLockExclusive(self.inner.get())
}
#[inline]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rt::util::report_overflow;
use core::prelude::*;
-use ptr;
-use mem;
+
+use libc::types::os::arch::extra::{LPVOID, DWORD, LONG};
use libc;
-use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
+use mem;
+use ptr;
+use rt::util::report_overflow;
+use sys::c;
use sys_common::stack;
pub struct Handler {
}
pub unsafe fn make_handler() -> Handler {
- if SetThreadStackGuarantee(&mut 0x5000) == 0 {
- panic!("failed to reserve stack space for exception handling");
+ // This API isn't available on XP, so don't panic in that case and just pray
+ // it works out ok.
+ if c::SetThreadStackGuarantee(&mut 0x5000) == 0 {
+ if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 {
+ panic!("failed to reserve stack space for exception handling");
+ }
}
Handler { _data: 0 as *mut libc::c_void }
fn AddVectoredExceptionHandler(FirstHandler: ULONG,
VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
-> LPVOID;
- fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
}
+++ /dev/null
-// Copyright 2014 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.
-
-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 _,
-};
-pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
-
-extern "system" {
- // condition variables
- pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
- SRWLock: PSRWLOCK,
- dwMilliseconds: DWORD,
- Flags: ULONG) -> BOOL;
- pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
- pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
-
- // slim rwlocks
- 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;
-
- 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);
-}