锁
自旋锁(Spinlock)
我们实现的自旋锁的定义如下:
1 2 3 4 5 6 7 #[derive(Debug,Default)] pub struct Spinlock <T: ?Sized >{ locked:AtomicBool, name: &'static str , cpu_id: Cell<isize >, data:UnsafeCell<T>, }
locked
由core::atmoic::AtomicBool
来声明,这是一个原子布尔类型,即这是一个线程安全的值。而data的值则有UnsafeCell
来包裹(wrap),这表明将有一些不安全的操作将作用在内部包裹的值中,使用该类型我们将没有办法获取内部变量的可变引用。我们可以通过.get()
方法获取*mut T
来对其内部进行操作。
对于一个锁变量,我们需要对其实现acquire()
和release()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 pub fn acquire (&self ) -> SpinlockGuard<'_ , T> { push_off(); if self .holding() { panic! ("acquire" ); } while self .locked.swap(true , Ordering::Acquire){ spin_loop(); } fence(Ordering::SeqCst); unsafe { self .cpu_id.set(cpuid() as isize ); } SpinlockGuard{spinlock: &self } } pub fn release (&self ) { if !self .holding() { panic! ("release" ); } self .cpu_id.set(-1 ); fence(Ordering::SeqCst); self .locked.store(false , Ordering::Release); pop_off(); }
在我们的实现中,对于acquire
方法,我们首先需要关闭中断并等待获取锁变量并对其进行原子上锁操作,在对变量上锁之后返回一个SpinlockGuard
变量。
而对于release
方法,我们则首先需要判断当前锁的状态,当锁为acquire
状态时我们将其解锁并进行开启中断。
而SpinlockGuard
的定义如下:
1 2 3 pub struct SpinlockGuard <'a , T>{ spinlock:&'a Spinlock<T> }
锁守卫者返回一个锁变量供获得锁的线程进行操作。同时我们对解引用操作符进行重载,从而能够使得获得锁的线程调用data的方法进行操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 impl <T> Deref for SpinlockGuard<'_ , T>{ type Target = T; fn deref (&self ) -> &Self::Target { unsafe { &*self .spinlock.data.get() } } } impl <T> DerefMut for SpinlockGuard<'_ , T>{ fn deref_mut (&mut self ) -> &mut Self::Target{ unsafe { &mut *self .spinlock.data.get() } } }
睡眠锁(Sleeplock)
待开发…