@@ -13,37 +13,13 @@ use macros::pin_data;
1313pub mod mutex;
1414pub mod spinlock;
1515
16- /// The "backend" of a lock.
17- ///
18- /// It is the actual implementation of the lock, without the need to repeat patterns used in all
19- /// locks.
20- ///
21- /// # Safety
22- ///
23- /// - Implementers must ensure that only one thread/CPU may access the protected data once the lock
24- /// is owned, that is, between calls to `lock` and `unlock`.
25- /// - Implementers must also ensure that `relock` uses the same locking method as the original
26- /// lock operation. For example, it should disable interrupts if [`IrqSaveBackend::lock_irqsave`]
27- /// is used.
28- pub unsafe trait Backend {
16+ pub unsafe trait EffectiveBackend {
2917 /// The state required by the lock.
3018 type State ;
3119
3220 /// The state required to be kept between lock and unlock.
3321 type GuardState ;
3422
35- /// Initialises the lock.
36- ///
37- /// # Safety
38- ///
39- /// `ptr` must be valid for write for the duration of the call, while `name` and `key` must
40- /// remain valid for read indefinitely.
41- unsafe fn init (
42- ptr : * mut Self :: State ,
43- name : * const core:: ffi:: c_char ,
44- key : * mut bindings:: lock_class_key ,
45- ) ;
46-
4723 /// Acquires the lock, making the caller its owner.
4824 ///
4925 /// # Safety
@@ -71,6 +47,32 @@ pub unsafe trait Backend {
7147 }
7248}
7349
50+ /// The "backend" of a lock.
51+ ///
52+ /// It is the actual implementation of the lock, without the need to repeat patterns used in all
53+ /// locks.
54+ ///
55+ /// # Safety
56+ ///
57+ /// - Implementers must ensure that only one thread/CPU may access the protected data once the lock
58+ /// is owned, that is, between calls to `lock` and `unlock`.
59+ /// - Implementers must also ensure that `relock` uses the same locking method as the original
60+ /// lock operation. For example, it should disable interrupts if [`IrqSaveBackend::lock_irqsave`]
61+ /// is used.
62+ pub unsafe trait Backend : EffectiveBackend {
63+ /// Initialises the lock.
64+ ///
65+ /// # Safety
66+ ///
67+ /// `ptr` must be valid for write for the duration of the call, while `name` and `key` must
68+ /// remain valid for read indefinitely.
69+ unsafe fn init (
70+ ptr : * mut Self :: State ,
71+ name : * const core:: ffi:: c_char ,
72+ key : * mut bindings:: lock_class_key ,
73+ ) ;
74+ }
75+
7476/// The "backend" of a lock that supports the irq-save variant.
7577///
7678/// # Safety
@@ -82,16 +84,7 @@ pub unsafe trait Backend {
8284/// must disable interrupts on lock, and restore interrupt state on unlock. Implementers may use
8385/// [`Backend::GuardState`] to store state needed to keep track of the interrupt state.
8486pub unsafe trait IrqSaveBackend : Backend {
85- /// Acquires the lock, making the caller its owner.
86- ///
87- /// Before acquiring the lock, it disables interrupts, and returns the previous interrupt state
88- /// as its guard state so that the guard can restore it when it is dropped.
89- ///
90- /// # Safety
91- ///
92- /// Callers must ensure that [`Backend::init`] has been previously called.
93- #[ must_use]
94- unsafe fn lock_irqsave ( ptr : * mut Self :: State ) -> Self :: GuardState ;
87+ type IrqSaveBackend : EffectiveBackend < State = Self :: State > ;
9588}
9689
9790/// A mutual exclusion primitive.
@@ -154,10 +147,10 @@ impl<T: ?Sized, B: IrqSaveBackend> Lock<T, B> {
154147 /// Before acquiring the lock, it disables interrupts. When the guard is dropped, the interrupt
155148 /// state (either enabled or disabled) is restored to its state before
156149 /// [`lock_irqsave`](Self::lock_irqsave) was called.
157- pub fn lock_irqsave ( & self ) -> Guard < ' _ , T , B > {
150+ pub fn lock_irqsave ( & self ) -> Guard < ' _ , T , B , B :: IrqSaveBackend > {
158151 // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
159152 // that `init` was called.
160- let state = unsafe { B :: lock_irqsave ( self . state . get ( ) ) } ;
153+ let state = unsafe { B :: IrqSaveBackend :: lock ( self . state . get ( ) ) } ;
161154 // SAFETY: The lock was just acquired.
162155 unsafe { Guard :: new ( self , state) }
163156 }
@@ -169,29 +162,29 @@ impl<T: ?Sized, B: IrqSaveBackend> Lock<T, B> {
169162/// when a guard goes out of scope. It also provides a safe and convenient way to access the data
170163/// protected by the lock.
171164#[ must_use = "the lock unlocks immediately when the guard is unused" ]
172- pub struct Guard < ' a , T : ?Sized , B : Backend > {
165+ pub struct Guard < ' a , T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > = B > {
173166 pub ( crate ) lock : & ' a Lock < T , B > ,
174- pub ( crate ) state : B :: GuardState ,
167+ pub ( crate ) state : E :: GuardState ,
175168 _not_send : PhantomData < * mut ( ) > ,
176169}
177170
178171// SAFETY: `Guard` is sync when the data protected by the lock is also sync.
179- unsafe impl < T : Sync + ?Sized , B : Backend > Sync for Guard < ' _ , T , B > { }
172+ unsafe impl < T : Sync + ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > Sync for Guard < ' _ , T , B , E > { }
180173
181- impl < T : ?Sized , B : Backend > Guard < ' _ , T , B > {
174+ impl < T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > Guard < ' _ , T , B , E > {
182175 pub ( crate ) fn do_unlocked ( & mut self , cb : impl FnOnce ( ) ) {
183176 // SAFETY: The caller owns the lock, so it is safe to unlock it.
184- unsafe { B :: unlock ( self . lock . state . get ( ) , & self . state ) } ;
177+ unsafe { E :: unlock ( self . lock . state . get ( ) , & self . state ) } ;
185178
186179 // SAFETY: The lock was just unlocked above and is being relocked now.
187180 let _relock =
188- ScopeGuard :: new ( || unsafe { B :: relock ( self . lock . state . get ( ) , & mut self . state ) } ) ;
181+ ScopeGuard :: new ( || unsafe { E :: relock ( self . lock . state . get ( ) , & mut self . state ) } ) ;
189182
190183 cb ( ) ;
191184 }
192185}
193186
194- impl < T : ?Sized , B : Backend > core:: ops:: Deref for Guard < ' _ , T , B > {
187+ impl < T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > core:: ops:: Deref for Guard < ' _ , T , B , E > {
195188 type Target = T ;
196189
197190 fn deref ( & self ) -> & Self :: Target {
@@ -200,27 +193,27 @@ impl<T: ?Sized, B: Backend> core::ops::Deref for Guard<'_, T, B> {
200193 }
201194}
202195
203- impl < T : ?Sized , B : Backend > core:: ops:: DerefMut for Guard < ' _ , T , B > {
196+ impl < T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > core:: ops:: DerefMut for Guard < ' _ , T , B , E > {
204197 fn deref_mut ( & mut self ) -> & mut Self :: Target {
205198 // SAFETY: The caller owns the lock, so it is safe to deref the protected data.
206199 unsafe { & mut * self . lock . data . get ( ) }
207200 }
208201}
209202
210- impl < T : ?Sized , B : Backend > Drop for Guard < ' _ , T , B > {
203+ impl < T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > Drop for Guard < ' _ , T , B , E > {
211204 fn drop ( & mut self ) {
212205 // SAFETY: The caller owns the lock, so it is safe to unlock it.
213- unsafe { B :: unlock ( self . lock . state . get ( ) , & self . state ) } ;
206+ unsafe { E :: unlock ( self . lock . state . get ( ) , & self . state ) } ;
214207 }
215208}
216209
217- impl < ' a , T : ?Sized , B : Backend > Guard < ' a , T , B > {
210+ impl < ' a , T : ?Sized , B : Backend , E : EffectiveBackend < State = B :: State > > Guard < ' a , T , B , E > {
218211 /// Constructs a new immutable lock guard.
219212 ///
220213 /// # Safety
221214 ///
222215 /// The caller must ensure that it owns the lock.
223- pub ( crate ) unsafe fn new ( lock : & ' a Lock < T , B > , state : B :: GuardState ) -> Self {
216+ pub ( crate ) unsafe fn new ( lock : & ' a Lock < T , B > , state : E :: GuardState ) -> Self {
224217 Self {
225218 lock,
226219 state,
0 commit comments