diff --git a/benchmark/Cargo.toml b/benchmark/Cargo.toml index 63b08938..9cd06cb2 100644 --- a/benchmark/Cargo.toml +++ b/benchmark/Cargo.toml @@ -20,3 +20,6 @@ path = "src/rwlock.rs" [features] nightly = ["parking_lot/nightly"] deadlock_detection = ["parking_lot/deadlock_detection"] + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["synchapi"] } diff --git a/benchmark/src/mutex.rs b/benchmark/src/mutex.rs index c651d029..a511185b 100644 --- a/benchmark/src/mutex.rs +++ b/benchmark/src/mutex.rs @@ -8,7 +8,7 @@ mod args; use crate::args::ArgRange; -#[cfg(unix)] +#[cfg(any(windows, unix))] use std::cell::UnsafeCell; use std::{ sync::{ @@ -57,6 +57,46 @@ impl Mutex for parking_lot::Mutex { } } +#[cfg(not(windows))] +type SrwLock = std::sync::Mutex; + +#[cfg(windows)] +use winapi::um::synchapi; +#[cfg(windows)] +struct SrwLock(UnsafeCell, UnsafeCell); +#[cfg(windows)] +unsafe impl Sync for SrwLock {} +#[cfg(windows)] +unsafe impl Send for SrwLock {} +#[cfg(windows)] +impl Mutex for SrwLock { + fn new(v: T) -> Self { + let mut h: synchapi::SRWLOCK = synchapi::SRWLOCK { Ptr: std::ptr::null_mut() }; + + unsafe { + synchapi::InitializeSRWLock(&mut h); + } + SrwLock( + UnsafeCell::new(v), + UnsafeCell::new(h), + ) + } + fn lock(&self, f: F) -> R + where + F: FnOnce(&mut T) -> R, + { + unsafe { + synchapi::AcquireSRWLockExclusive(self.1.get()); + let res = f(&mut *self.0.get()); + synchapi::ReleaseSRWLockExclusive(self.1.get()); + res + } + } + fn name() -> &'static str { + "winapi_srwlock" + } +} + #[cfg(not(unix))] type PthreadMutex = std::sync::Mutex; @@ -220,6 +260,15 @@ fn run_all( seconds_per_test, test_iterations, ); + if cfg!(windows) { + run_benchmark_iterations::>( + num_threads, + work_per_critical_section, + work_between_critical_sections, + seconds_per_test, + test_iterations, + ); + } if cfg!(unix) { run_benchmark_iterations::>( num_threads, diff --git a/benchmark/src/rwlock.rs b/benchmark/src/rwlock.rs index 4a3998c6..36fa7e85 100644 --- a/benchmark/src/rwlock.rs +++ b/benchmark/src/rwlock.rs @@ -8,7 +8,7 @@ mod args; use crate::args::ArgRange; -#[cfg(unix)] +#[cfg(any(windows, unix))] use std::cell::UnsafeCell; use std::{ sync::{ @@ -93,6 +93,57 @@ impl RwLock for seqlock::SeqLock { } } +#[cfg(not(windows))] +type SrwLock = std::sync::RwLock; + +#[cfg(windows)] +use winapi::um::synchapi; +#[cfg(windows)] +struct SrwLock(UnsafeCell, UnsafeCell); +#[cfg(windows)] +unsafe impl Sync for SrwLock {} +#[cfg(windows)] +unsafe impl Send for SrwLock {} +#[cfg(windows)] +impl RwLock for SrwLock { + fn new(v: T) -> Self { + let mut h: synchapi::SRWLOCK = synchapi::SRWLOCK { Ptr: std::ptr::null_mut() }; + + unsafe { + synchapi::InitializeSRWLock(&mut h); + } + SrwLock( + UnsafeCell::new(v), + UnsafeCell::new(h), + ) + } + fn read(&self, f: F) -> R + where + F: FnOnce(&T) -> R, + { + unsafe { + synchapi::AcquireSRWLockShared(self.1.get()); + let res = f(&*self.0.get()); + synchapi::ReleaseSRWLockShared(self.1.get()); + res + } + } + fn write(&self, f: F) -> R + where + F: FnOnce(&mut T) -> R, + { + unsafe { + synchapi::AcquireSRWLockExclusive(self.1.get()); + let res = f(&mut *self.0.get()); + synchapi::ReleaseSRWLockExclusive(self.1.get()); + res + } + } + fn name() -> &'static str { + "winapi_srwlock" + } +} + #[cfg(not(unix))] type PthreadRwLock = std::sync::RwLock; @@ -304,14 +355,16 @@ fn run_all( seconds_per_test, test_iterations, ); - run_benchmark_iterations::>( - num_writer_threads, - num_reader_threads, - work_per_critical_section, - work_between_critical_sections, - seconds_per_test, - test_iterations, - ); + if cfg!(windows) { + run_benchmark_iterations::>( + num_writer_threads, + num_reader_threads, + work_per_critical_section, + work_between_critical_sections, + seconds_per_test, + test_iterations, + ); + } if cfg!(unix) { run_benchmark_iterations::>( num_writer_threads,