瀏覽代碼

rwlock: rename rwsem to rwlock and reimpl the lock

greatbridf 10 月之前
父節點
當前提交
525eee2872

+ 23 - 5
crates/eonix_sync/src/guard.rs

@@ -35,7 +35,9 @@ where
 {
     #[must_use = "The returned `UnlockedGuard` must be used to relock the lock."]
     pub fn unlock(mut self) -> UnlockedGuard<'a, T, S, L, W> {
-        unsafe { S::do_temporary_unlock(&self.strategy_data, &mut self.context) }
+        unsafe {
+            self.force_unlock();
+        }
 
         UnlockedGuard {
             lock: self.lock,
@@ -53,13 +55,21 @@ where
     /// dropping the guard. Using the guard after calling this function is
     /// undefined behavior.
     pub unsafe fn force_unlock(&mut self) {
-        unsafe { S::do_temporary_unlock(&self.strategy_data, &mut self.context) }
+        if W {
+            unsafe { S::do_temporary_unlock(&self.strategy_data, &mut self.context) }
+        } else {
+            unsafe { S::do_temporary_unlock_shared(&self.strategy_data, &mut self.context) }
+        }
     }
 
     /// # Safety
     /// Calling this function twice on a force unlocked guard will cause deadlocks.
     pub unsafe fn force_relock(&mut self) {
-        unsafe { S::do_relock(&self.strategy_data, &mut self.context) }
+        if W {
+            unsafe { S::do_relock(&self.strategy_data, &mut self.context) }
+        } else {
+            unsafe { S::do_relock_shared(&self.strategy_data, &mut self.context) }
+        }
     }
 }
 
@@ -71,7 +81,11 @@ where
 {
     #[must_use = "Throwing away the relocked guard is pointless."]
     pub fn relock(mut self) -> Guard<'a, T, S, L, W> {
-        unsafe { S::do_relock(&self.strategy_data, &mut self.context) }
+        if W {
+            unsafe { S::do_relock(&self.strategy_data, &mut self.context) }
+        } else {
+            unsafe { S::do_relock_shared(&self.strategy_data, &mut self.context) }
+        }
 
         Guard {
             lock: self.lock,
@@ -154,6 +168,10 @@ where
     L: LockStrategy,
 {
     fn drop(&mut self) {
-        unsafe { S::do_unlock(&self.strategy_data, &mut self.context) }
+        if WRITE {
+            unsafe { S::do_unlock(&self.strategy_data, &mut self.context) }
+        } else {
+            unsafe { S::do_unlock_shared(&self.strategy_data, &mut self.context) }
+        }
     }
 }

+ 4 - 1
crates/eonix_sync/src/lib.rs

@@ -3,13 +3,16 @@
 mod guard;
 mod lock;
 mod locked;
+mod rwlock;
 mod spin;
 mod strategy;
 
 pub use guard::Guard;
 pub use lock::Lock;
 pub use locked::{AsProof, AsProofMut, Locked, Proof, ProofMut};
+pub use rwlock::RwLockStrategy;
 pub use spin::{IrqStrategy, SpinStrategy};
-pub use strategy::LockStrategy;
+pub use strategy::{LockStrategy, WaitStrategy};
 
 pub type Spin<T> = Lock<T, SpinStrategy>;
+pub type RwLock<T, W> = Lock<T, RwLockStrategy<W>>;

+ 1 - 2
crates/eonix_sync/src/lock.rs

@@ -33,7 +33,6 @@ impl<T, S> Lock<T, S>
 where
     S: LockStrategy,
 {
-    #[inline(always)]
     pub fn new(value: T) -> Self {
         Self {
             strategy_data: S::new_data(),
@@ -91,7 +90,7 @@ where
         Guard {
             lock: self,
             strategy_data: &self.strategy_data,
-            context: unsafe { IrqStrategy::<S>::do_lock(&self.strategy_data) },
+            context: unsafe { IrqStrategy::<S>::do_lock_shared(&self.strategy_data) },
         }
     }
 

+ 154 - 0
crates/eonix_sync/src/rwlock.rs

@@ -0,0 +1,154 @@
+use crate::{LockStrategy, WaitStrategy};
+use core::{
+    marker::PhantomData,
+    sync::atomic::{AtomicIsize, Ordering},
+};
+
+pub struct RwLockStrategy<W>(PhantomData<W>)
+where
+    W: WaitStrategy;
+
+pub struct RwLockData<W>
+where
+    W: WaitStrategy,
+{
+    counter: AtomicIsize,
+    wait_data: W::Data,
+}
+
+impl<W> RwLockStrategy<W>
+where
+    W: WaitStrategy,
+{
+    #[cold]
+    fn lock_slow_path(
+        data: &<Self as LockStrategy>::StrategyData,
+    ) -> <Self as LockStrategy>::GuardContext {
+        loop {
+            if let Ok(_) =
+                data.counter
+                    .compare_exchange_weak(0, -1, Ordering::Acquire, Ordering::Relaxed)
+            {
+                return ();
+            }
+
+            W::write_wait(&data.wait_data, || {
+                data.counter.load(Ordering::Relaxed) == 0
+            });
+        }
+    }
+
+    #[cold]
+    fn lock_shared_slow_path(
+        data: &<Self as LockStrategy>::StrategyData,
+    ) -> <Self as LockStrategy>::GuardContext {
+        loop {
+            let mut counter = data.counter.load(Ordering::Relaxed);
+            while !W::has_write_waiting(&data.wait_data) && counter >= 0 {
+                match data.counter.compare_exchange_weak(
+                    counter,
+                    counter + 1,
+                    Ordering::Acquire,
+                    Ordering::Relaxed,
+                ) {
+                    Ok(_) => return (),
+                    Err(previous) => counter = previous,
+                }
+            }
+
+            W::read_wait(&data.wait_data, || {
+                !W::has_write_waiting(&data.wait_data) && data.counter.load(Ordering::Relaxed) >= 0
+            });
+        }
+    }
+}
+
+unsafe impl<W> LockStrategy for RwLockStrategy<W>
+where
+    W: WaitStrategy,
+{
+    type StrategyData = RwLockData<W>;
+    type GuardContext = ();
+
+    fn new_data() -> Self::StrategyData {
+        Self::StrategyData {
+            counter: AtomicIsize::new(0),
+            wait_data: W::new_data(),
+        }
+    }
+
+    unsafe fn is_locked(data: &Self::StrategyData) -> bool {
+        data.counter.load(Ordering::Relaxed) == 1
+    }
+
+    unsafe fn try_lock(data: &Self::StrategyData) -> Option<Self::GuardContext> {
+        data.counter
+            .compare_exchange(0, -1, Ordering::Acquire, Ordering::Relaxed)
+            .map(|_| ())
+            .ok()
+    }
+
+    unsafe fn try_lock_shared(data: &Self::StrategyData) -> Option<Self::GuardContext>
+    where
+        Self: Sized,
+    {
+        if W::has_write_waiting(&data.wait_data) {
+            return None;
+        }
+
+        let counter = data.counter.load(Ordering::Relaxed);
+        match counter {
+            0.. => data
+                .counter
+                .compare_exchange(counter, counter + 1, Ordering::Acquire, Ordering::Relaxed)
+                .ok()
+                .map(|_| ()),
+            _ => None,
+        }
+    }
+
+    unsafe fn do_lock(data: &Self::StrategyData) -> Self::GuardContext {
+        if let Some(context) = unsafe { Self::try_lock(data) } {
+            // Quick path
+            context
+        } else {
+            Self::lock_slow_path(data)
+        }
+    }
+
+    unsafe fn do_lock_shared(data: &Self::StrategyData) -> Self::GuardContext {
+        if let Some(context) = unsafe { Self::try_lock_shared(data) } {
+            // Quick path
+            context
+        } else {
+            Self::lock_shared_slow_path(data)
+        }
+    }
+
+    unsafe fn do_unlock(data: &Self::StrategyData, _: &mut Self::GuardContext)
+    where
+        Self: Sized,
+    {
+        let old = data.counter.fetch_add(1, Ordering::Release);
+        assert_eq!(
+            old, -1,
+            "RwLockStrategy::do_unlock: erroneous counter value: {}",
+            old
+        );
+        W::write_notify(&data.wait_data);
+    }
+
+    unsafe fn do_unlock_shared(data: &Self::StrategyData, _: &mut Self::GuardContext)
+    where
+        Self: Sized,
+    {
+        match data.counter.fetch_sub(1, Ordering::Release) {
+            2.. => {}
+            1 => W::read_notify(&data.wait_data),
+            val => unreachable!(
+                "RwLockStrategy::do_unlock_shared: erroneous counter value: {}",
+                val
+            ),
+        }
+    }
+}

+ 5 - 8
crates/eonix_sync/src/spin.rs

@@ -27,22 +27,19 @@ unsafe impl LockStrategy for SpinStrategy {
     }
 
     unsafe fn try_lock(data: &Self::StrategyData) -> Option<Self::GuardContext> {
-        use Ordering::{Acquire, Relaxed};
         eonix_preempt::disable();
 
-        if data.compare_exchange(false, true, Acquire, Relaxed).is_ok() {
-            Some(())
-        } else {
-            None
-        }
+        data.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
+            .map(|_| ())
+            .inspect_err(|_| eonix_preempt::enable())
+            .ok()
     }
 
     unsafe fn do_lock(data: &Self::StrategyData) -> Self::GuardContext {
-        use Ordering::{Acquire, Relaxed};
         eonix_preempt::disable();
 
         while data
-            .compare_exchange_weak(false, true, Acquire, Relaxed)
+            .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
             .is_err()
         {
             while Self::is_locked(data) {

+ 62 - 0
crates/eonix_sync/src/strategy.rs

@@ -22,6 +22,13 @@ pub unsafe trait LockStrategy {
     where
         Self: Sized;
 
+    unsafe fn try_lock_shared(data: &Self::StrategyData) -> Option<Self::GuardContext>
+    where
+        Self: Sized,
+    {
+        unsafe { Self::try_lock(data) }
+    }
+
     unsafe fn do_lock_shared(data: &Self::StrategyData) -> Self::GuardContext
     where
         Self: Sized,
@@ -29,6 +36,13 @@ pub unsafe trait LockStrategy {
         unsafe { Self::do_lock(data) }
     }
 
+    unsafe fn do_unlock_shared(data: &Self::StrategyData, context: &mut Self::GuardContext)
+    where
+        Self: Sized,
+    {
+        unsafe { Self::do_unlock(data, context) }
+    }
+
     unsafe fn do_temporary_unlock(data: &Self::StrategyData, context: &mut Self::GuardContext)
     where
         Self: Sized,
@@ -36,10 +50,58 @@ pub unsafe trait LockStrategy {
         unsafe { Self::do_unlock(data, context) }
     }
 
+    unsafe fn do_temporary_unlock_shared(
+        data: &Self::StrategyData,
+        context: &mut Self::GuardContext,
+    ) where
+        Self: Sized,
+    {
+        unsafe { Self::do_unlock_shared(data, context) }
+    }
+
     unsafe fn do_relock(data: &Self::StrategyData, context: &mut Self::GuardContext)
     where
         Self: Sized,
     {
         *context = unsafe { Self::do_lock(data) };
     }
+
+    unsafe fn do_relock_shared(data: &Self::StrategyData, context: &mut Self::GuardContext)
+    where
+        Self: Sized,
+    {
+        *context = unsafe { Self::do_lock_shared(data) };
+    }
+}
+
+pub trait WaitStrategy {
+    type Data;
+
+    fn new_data() -> Self::Data
+    where
+        Self: Sized;
+
+    fn has_write_waiting(data: &Self::Data) -> bool
+    where
+        Self: Sized;
+
+    fn has_read_waiting(data: &Self::Data) -> bool
+    where
+        Self: Sized;
+
+    fn write_wait(data: &Self::Data, check: impl Fn() -> bool)
+    where
+        Self: Sized;
+
+    fn read_wait(data: &Self::Data, check: impl Fn() -> bool)
+    where
+        Self: Sized;
+
+    fn write_notify(data: &Self::Data)
+    where
+        Self: Sized;
+
+    fn read_notify(data: &Self::Data)
+    where
+        Self: Sized;
 }

+ 2 - 2
src/fs/fat32.rs

@@ -79,7 +79,7 @@ struct FatFs {
     volume_label: [u8; 11],
 
     device: Arc<BlockDevice>,
-    fat: RwSemaphore<Vec<ClusterNo>>,
+    fat: RwLock<Vec<ClusterNo>>,
     weak: Weak<FatFs>,
     icache: BTreeMap<Ino, FatInode>,
 }
@@ -135,7 +135,7 @@ impl FatFs {
             sectors_per_cluster: 0,
             rootdir_cluster: 0,
             data_start: 0,
-            fat: RwSemaphore::new(Vec::new()),
+            fat: RwLock::new(Vec::new()),
             weak: weak.clone(),
             icache: BTreeMap::new(),
             volume_label: [0; 11],

+ 2 - 2
src/kernel/task/process.rs

@@ -6,7 +6,7 @@ use crate::{
     kernel::mem::MMList,
     prelude::*,
     rcu::{rcu_sync, RCUPointer, RCUReadGuard},
-    sync::{CondVar, RwSemReadGuard, SpinGuard},
+    sync::{CondVar, RwLockReadGuard, SpinGuard},
 };
 use alloc::{
     collections::{btree_map::BTreeMap, vec_deque::VecDeque},
@@ -79,7 +79,7 @@ pub struct NotifyBatch<'waitlist, 'process, 'cv> {
 
 pub struct Entry<'waitlist, 'proclist, 'cv> {
     wait_procs: SpinGuard<'waitlist, VecDeque<WaitObject>>,
-    process_list: RwSemReadGuard<'proclist, ProcessList>,
+    process_list: RwLockReadGuard<'proclist, ProcessList>,
     cv: &'cv CondVar,
     want_stop: bool,
     want_continue: bool,

+ 3 - 3
src/kernel/task/process_list.rs

@@ -22,8 +22,8 @@ pub struct ProcessList {
 }
 
 lazy_static! {
-    static ref GLOBAL_PROC_LIST: RwSemaphore<ProcessList> = {
-        RwSemaphore::new(ProcessList {
+    static ref GLOBAL_PROC_LIST: RwLock<ProcessList> = {
+        RwLock::new(ProcessList {
             init: None,
             threads: BTreeMap::new(),
             processes: BTreeMap::new(),
@@ -34,7 +34,7 @@ lazy_static! {
 }
 
 impl ProcessList {
-    pub fn get() -> &'static RwSemaphore<Self> {
+    pub fn get() -> &'static RwLock<Self> {
         &GLOBAL_PROC_LIST
     }
 

+ 2 - 2
src/kernel/task/session.rs

@@ -19,7 +19,7 @@ struct SessionJobControl {
 pub struct Session {
     pub sid: u32,
     pub leader: Weak<Process>,
-    job_control: RwSemaphore<SessionJobControl>,
+    job_control: RwLock<SessionJobControl>,
 
     groups: Locked<BTreeMap<u32, Weak<ProcessGroup>>, ProcessList>,
 }
@@ -30,7 +30,7 @@ impl Session {
         let session = Arc::new(Self {
             sid: leader.pid,
             leader: Arc::downgrade(leader),
-            job_control: RwSemaphore::new(SessionJobControl {
+            job_control: RwLock::new(SessionJobControl {
                 foreground: Weak::new(),
                 control_terminal: None,
             }),

+ 2 - 2
src/kernel/vfs/inode.rs

@@ -44,7 +44,7 @@ pub struct InodeData {
     pub ctime: Spin<TimeSpec>,
     pub mtime: Spin<TimeSpec>,
 
-    pub rwsem: RwSemaphore<()>,
+    pub rwsem: RwLock<()>,
 
     pub vfs: Weak<dyn Vfs>,
 }
@@ -57,7 +57,7 @@ impl InodeData {
             atime: Spin::new(TimeSpec::default()),
             ctime: Spin::new(TimeSpec::default()),
             mtime: Spin::new(TimeSpec::default()),
-            rwsem: RwSemaphore::new(()),
+            rwsem: RwLock::new(()),
             size: Default::default(),
             nlink: Default::default(),
             uid: Default::default(),

+ 1 - 1
src/prelude.rs

@@ -22,7 +22,7 @@ pub(crate) use alloc::{boxed::Box, string::String, vec, vec::Vec};
 
 pub(crate) use core::{any::Any, fmt::Write, marker::PhantomData, str};
 
-pub use crate::sync::{Mutex, RwSemaphore, Spin};
+pub use crate::sync::{Mutex, RwLock, Spin};
 
 #[allow(dead_code)]
 pub trait AsAny: Send + Sync {

+ 6 - 6
src/rcu.rs

@@ -1,4 +1,4 @@
-use crate::{prelude::*, sync::RwSemReadGuard};
+use crate::{prelude::*, sync::RwLockReadGuard};
 use alloc::sync::Arc;
 use core::{
     ops::Deref,
@@ -10,12 +10,12 @@ use pointers::BorrowedArc;
 
 pub struct RCUReadGuard<'data, T: 'data> {
     value: T,
-    guard: RwSemReadGuard<'data, ()>,
+    guard: RwLockReadGuard<'data, ()>,
     _phantom: PhantomData<&'data T>,
 }
 
 lazy_static! {
-    static ref GLOBAL_RCU_SEM: RwSemaphore<()> = RwSemaphore::new(());
+    static ref GLOBAL_RCU_SEM: RwLock<()> = RwLock::new(());
 }
 
 impl<'data, T: 'data> RCUReadGuard<'data, T> {
@@ -48,7 +48,7 @@ pub trait RCUNode<MySelf> {
 pub struct RCUList<T: RCUNode<T>> {
     head: AtomicPtr<T>,
 
-    reader_lock: RwSemaphore<()>,
+    reader_lock: RwLock<()>,
     update_lock: Mutex<()>,
 }
 
@@ -56,7 +56,7 @@ impl<T: RCUNode<T>> RCUList<T> {
     pub fn new() -> Self {
         Self {
             head: AtomicPtr::new(core::ptr::null_mut()),
-            reader_lock: RwSemaphore::new(()),
+            reader_lock: RwLock::new(()),
             update_lock: Mutex::new(()),
         }
     }
@@ -158,7 +158,7 @@ impl<T: RCUNode<T>> RCUList<T> {
 
 pub struct RCUIterator<'lt, T: RCUNode<T>> {
     cur: Option<NonNull<T>>,
-    _lock: RwSemReadGuard<'lt, ()>,
+    _lock: RwLockReadGuard<'lt, ()>,
 }
 
 impl<'lt, T: RCUNode<T>> Iterator for RCUIterator<'lt, T> {

+ 73 - 3
src/sync.rs

@@ -2,14 +2,84 @@ mod arcswap;
 mod condvar;
 pub mod semaphore;
 
+use eonix_sync::WaitStrategy;
+
 pub use eonix_sync::{Guard, Lock, Spin, SpinStrategy};
 
+#[doc(hidden)]
+pub struct Wait {
+    lock: Spin<()>,
+    cv_read: UCondVar,
+    cv_write: UCondVar,
+}
+
+impl WaitStrategy for Wait {
+    type Data = Self;
+
+    fn new_data() -> Self::Data {
+        Self {
+            lock: Spin::new(()),
+            cv_read: UCondVar::new(),
+            cv_write: UCondVar::new(),
+        }
+    }
+
+    fn has_write_waiting(data: &Self::Data) -> bool {
+        data.cv_write.has_waiters()
+    }
+
+    fn has_read_waiting(data: &Self::Data) -> bool {
+        data.cv_read.has_waiters()
+    }
+
+    fn write_wait(data: &Self::Data, check: impl Fn() -> bool) {
+        let mut lock = data.lock.lock();
+
+        loop {
+            if check() {
+                break;
+            }
+            data.cv_write.wait(&mut lock);
+        }
+    }
+
+    fn read_wait(data: &Self::Data, check: impl Fn() -> bool) {
+        let mut lock = data.lock.lock();
+        loop {
+            if check() {
+                break;
+            }
+            data.cv_read.wait(&mut lock);
+        }
+    }
+
+    fn write_notify(data: &Self::Data) {
+        let _lock = data.lock.lock();
+        if Self::has_write_waiting(data) {
+            data.cv_write.notify_one();
+        }
+        if Self::has_read_waiting(data) {
+            data.cv_read.notify_all();
+        }
+    }
+
+    fn read_notify(data: &Self::Data) {
+        let _lock = data.lock.lock();
+        if Self::has_write_waiting(data) {
+            data.cv_write.notify_one();
+        }
+        if Self::has_read_waiting(data) {
+            data.cv_read.notify_all();
+        }
+    }
+}
+
 pub type Mutex<T> = Lock<T, semaphore::SemaphoreStrategy<1>>;
-pub type RwSemaphore<T> = Lock<T, semaphore::RwSemaphoreStrategy>;
+pub type RwLock<T> = eonix_sync::RwLock<T, Wait>;
 
 pub type SpinGuard<'lock, T> = Guard<'lock, T, SpinStrategy, SpinStrategy, true>;
-pub type RwSemReadGuard<'lock, T> =
-    Guard<'lock, T, semaphore::RwSemaphoreStrategy, semaphore::RwSemaphoreStrategy, false>;
+pub type RwLockReadGuard<'lock, T> =
+    Guard<'lock, T, eonix_sync::RwLockStrategy<Wait>, eonix_sync::RwLockStrategy<Wait>, false>;
 
 pub type CondVar = condvar::CondVar<true>;
 pub type UCondVar = condvar::CondVar<false>;

+ 4 - 0
src/sync/condvar.rs

@@ -26,6 +26,10 @@ impl<const I: bool> CondVar<I> {
         }
     }
 
+    pub fn has_waiters(&self) -> bool {
+        !self.waiters.lock().is_empty()
+    }
+
     fn wake(waker: Waker) {
         println_trace!("trace_condvar", "tid({}) is trying to wake", thread.tid);
         waker.wake();

+ 0 - 120
src/sync/semaphore.rs

@@ -3,15 +3,6 @@ use eonix_sync::LockStrategy;
 
 pub struct SemaphoreStrategy<const MAX: usize = { core::usize::MAX }>;
 
-#[allow(dead_code)]
-impl<const MAX: usize> SemaphoreStrategy<MAX> {
-    #[inline(always)]
-    fn is_locked(data: &<Self as LockStrategy>::StrategyData) -> bool {
-        let counter = data.counter.lock();
-        *counter > 0
-    }
-}
-
 pub struct SemaphoreData {
     counter: Spin<usize>,
     cv: UCondVar,
@@ -78,114 +69,3 @@ unsafe impl<const MAX: usize> LockStrategy for SemaphoreStrategy<MAX> {
         }
     }
 }
-
-pub struct RwSemaphoreStrategy<const READ_MAX: isize = { core::isize::MAX }>;
-
-#[allow(dead_code)]
-impl<const READ_MAX: isize> RwSemaphoreStrategy<READ_MAX> {
-    #[inline(always)]
-    fn is_read_locked(data: &<Self as LockStrategy>::StrategyData) -> bool {
-        let counter = data.counter.lock();
-        *counter > 0
-    }
-
-    #[inline(always)]
-    fn is_write_locked(data: &<Self as LockStrategy>::StrategyData) -> bool {
-        let counter = data.counter.lock();
-        *counter < 0
-    }
-}
-
-pub struct RwSemaphoreData {
-    counter: Spin<isize>,
-    read_cv: UCondVar,
-    write_cv: UCondVar,
-}
-
-unsafe impl<const READ_MAX: isize> LockStrategy for RwSemaphoreStrategy<READ_MAX> {
-    type StrategyData = RwSemaphoreData;
-    type GuardContext = ();
-
-    #[inline(always)]
-    unsafe fn is_locked(data: &Self::StrategyData) -> bool {
-        *data.counter.lock() != 0
-    }
-
-    #[inline(always)]
-    unsafe fn try_lock(data: &Self::StrategyData) -> Option<Self::GuardContext> {
-        let mut counter = data.counter.lock();
-        assert!(*counter >= -1 && *counter <= READ_MAX);
-        if *counter == 0 {
-            *counter -= 1;
-            Some(())
-        } else {
-            None
-        }
-    }
-
-    #[inline(always)]
-    fn new_data() -> Self::StrategyData {
-        RwSemaphoreData {
-            counter: Spin::new(0),
-            read_cv: UCondVar::new(),
-            write_cv: UCondVar::new(),
-        }
-    }
-
-    #[inline(always)]
-    /// Acquire the semaphore in write mode
-    ///
-    /// # Might Sleep
-    unsafe fn do_lock(data: &Self::StrategyData) -> Self::GuardContext {
-        loop {
-            let mut counter = data.counter.lock();
-            assert!(*counter >= -1 && *counter <= READ_MAX);
-
-            if *counter == 0 {
-                *counter -= 1;
-                return;
-            }
-
-            data.write_cv.wait(&mut counter);
-        }
-    }
-
-    #[inline(always)]
-    /// Acquire the semaphore in read mode
-    ///
-    /// # Might Sleep
-    unsafe fn do_lock_shared(data: &Self::StrategyData) -> Self::GuardContext {
-        loop {
-            let mut counter = data.counter.lock();
-            assert!(*counter >= -1 && *counter <= READ_MAX);
-
-            if *counter >= 0 && *counter < READ_MAX {
-                *counter += 1;
-                return;
-            }
-
-            data.read_cv.wait(&mut counter);
-        }
-    }
-
-    #[inline(always)]
-    unsafe fn do_unlock(data: &Self::StrategyData, _: &mut Self::GuardContext) {
-        let mut counter = data.counter.lock();
-        assert!(*counter >= -1 && *counter <= READ_MAX);
-
-        match *counter {
-            -1 => {
-                *counter = 0;
-                data.read_cv.notify_all();
-                data.write_cv.notify_one();
-            }
-            n if n > 0 => {
-                *counter -= 1;
-                if *counter == 0 {
-                    data.write_cv.notify_one();
-                }
-            }
-            _ => panic!("Semaphore in inconsistent state"),
-        }
-    }
-}