5
5
// Author: Joerg Roedel <[email protected] >
6
6
7
7
use super :: common:: * ;
8
+ use crate :: types:: TPR_LOCK ;
8
9
use core:: cell:: UnsafeCell ;
9
10
use core:: marker:: PhantomData ;
10
11
use core:: ops:: { Deref , DerefMut } ;
@@ -41,7 +42,9 @@ impl<T, I> Deref for RawReadLockGuard<'_, T, I> {
41
42
}
42
43
43
44
pub type ReadLockGuard < ' a , T > = RawReadLockGuard < ' a , T , IrqUnsafeLocking > ;
44
- pub type ReadLockGuardIrqSafe < ' a , T > = RawReadLockGuard < ' a , T , IrqSafeLocking > ;
45
+ pub type ReadLockGuardIrqSafe < ' a , T > = RawReadLockGuard < ' a , T , IrqGuardLocking > ;
46
+ pub type ReadLockGuardAnyTpr < ' a , T , const TPR : usize > =
47
+ RawReadLockGuard < ' a , T , TprGuardLocking < TPR > > ;
45
48
46
49
/// A guard that provides exclusive write access to the data protected by [`RWLock`]
47
50
#[ derive( Debug ) ]
@@ -81,7 +84,9 @@ impl<T, I> DerefMut for RawWriteLockGuard<'_, T, I> {
81
84
}
82
85
83
86
pub type WriteLockGuard < ' a , T > = RawWriteLockGuard < ' a , T , IrqUnsafeLocking > ;
84
- pub type WriteLockGuardIrqSafe < ' a , T > = RawWriteLockGuard < ' a , T , IrqSafeLocking > ;
87
+ pub type WriteLockGuardIrqSafe < ' a , T > = RawWriteLockGuard < ' a , T , IrqGuardLocking > ;
88
+ pub type WriteLockGuardAnyTpr < ' a , T , const TPR : usize > =
89
+ RawWriteLockGuard < ' a , T , TprGuardLocking < TPR > > ;
85
90
86
91
/// A simple Read-Write Lock (RWLock) that allows multiple readers or
87
92
/// one exclusive writer.
@@ -216,7 +221,7 @@ impl<T, I: IrqLocking> RawRWLock<T, I> {
216
221
///
217
222
/// A [`ReadLockGuard`] that provides read access to the protected data.
218
223
pub fn lock_read ( & self ) -> RawReadLockGuard < ' _ , T , I > {
219
- let irq_state = I :: irqs_disable ( ) ;
224
+ let irq_state = I :: acquire_lock ( ) ;
220
225
loop {
221
226
let val = self . wait_for_writers ( ) ;
222
227
let ( readers, _) = split_val ( val) ;
@@ -246,7 +251,7 @@ impl<T, I: IrqLocking> RawRWLock<T, I> {
246
251
///
247
252
/// A [`WriteLockGuard`] that provides write access to the protected data.
248
253
pub fn lock_write ( & self ) -> RawWriteLockGuard < ' _ , T , I > {
249
- let irq_state = I :: irqs_disable ( ) ;
254
+ let irq_state = I :: acquire_lock ( ) ;
250
255
251
256
// Waiting for current writer to finish
252
257
loop {
@@ -277,7 +282,9 @@ impl<T, I: IrqLocking> RawRWLock<T, I> {
277
282
}
278
283
279
284
pub type RWLock < T > = RawRWLock < T , IrqUnsafeLocking > ;
280
- pub type RWLockIrqSafe < T > = RawRWLock < T , IrqSafeLocking > ;
285
+ pub type RWLockIrqSafe < T > = RawRWLock < T , IrqGuardLocking > ;
286
+ pub type RWLockAnyTpr < T , const TPR : usize > = RawRWLock < T , TprGuardLocking < TPR > > ;
287
+ pub type RWLockTpr < T > = RWLockAnyTpr < T , { TPR_LOCK } > ;
281
288
282
289
mod tests {
283
290
#[ test]
@@ -380,7 +387,7 @@ mod tests {
380
387
381
388
// Lock for read
382
389
let guard = lock. lock_read ( ) ;
383
- // IRQs must still be enabled;
390
+ // IRQs must be disabled
384
391
assert ! ( irqs_disabled( ) ) ;
385
392
// Unlock
386
393
drop ( guard) ;
@@ -391,4 +398,33 @@ mod tests {
391
398
raw_irqs_disable ( ) ;
392
399
}
393
400
}
401
+
402
+ #[ test]
403
+ #[ cfg_attr( not( test_in_svsm) , ignore = "Can only be run inside guest" ) ]
404
+ fn rw_lock_tpr ( ) {
405
+ use crate :: cpu:: irq_state:: raw_get_tpr;
406
+ use crate :: locking:: * ;
407
+ use crate :: types:: TPR_LOCK ;
408
+
409
+ assert_eq ! ( raw_get_tpr( ) , 0 ) ;
410
+ let lock = RWLockTpr :: new ( 0 ) ;
411
+
412
+ // Lock for write
413
+ let guard = lock. lock_write ( ) ;
414
+ // TPR must be raised
415
+ assert_eq ! ( raw_get_tpr( ) , TPR_LOCK ) ;
416
+ // Unlock
417
+ drop ( guard) ;
418
+ // TPR must be restored
419
+ assert_eq ! ( raw_get_tpr( ) , 0 ) ;
420
+
421
+ // Lock for read
422
+ let guard = lock. lock_read ( ) ;
423
+ // TPR must be raised
424
+ assert_eq ! ( raw_get_tpr( ) , TPR_LOCK ) ;
425
+ // Unlock
426
+ drop ( guard) ;
427
+ // TPR must be restored
428
+ assert_eq ! ( raw_get_tpr( ) , 0 ) ;
429
+ }
394
430
}
0 commit comments