@@ -11,33 +11,86 @@ mod imp {
11
11
12
12
#[ cfg( any( target_arch = "arm" , target_arch = "mips" , target_arch = "powerpc" ) ) ]
13
13
mod imp {
14
- use std:: sync:: atomic:: Ordering ;
15
- use std:: sync:: Mutex ;
14
+ use std:: cell:: UnsafeCell ;
15
+ use std:: ops:: { Deref , DerefMut } ;
16
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
16
17
17
- #[ derive( Debug ) ]
18
- pub ( crate ) struct AtomicU64 ( Mutex < u64 > ) ;
18
+ use crossbeam_utils:: Backoff ;
19
+
20
+ pub ( crate ) struct AtomicU64 ( Spinlock < u64 > ) ;
19
21
20
22
impl AtomicU64 {
21
- pub ( crate ) fn new ( val : u64 ) -> Self {
22
- Self ( Mutex :: new ( val) )
23
+ pub ( crate ) const fn new ( val : u64 ) -> Self {
24
+ Self ( Spinlock :: new ( val) )
23
25
}
24
26
25
27
pub ( crate ) fn load ( & self , _: Ordering ) -> u64 {
26
- * self . 0 . lock ( ) . unwrap ( )
28
+ * self . 0 . lock ( )
27
29
}
28
30
29
31
pub ( crate ) fn fetch_add ( & self , val : u64 , _: Ordering ) -> u64 {
30
- let mut lock = self . 0 . lock ( ) . unwrap ( ) ;
32
+ let mut lock = self . 0 . lock ( ) ;
31
33
let prev = * lock;
32
34
* lock = prev + val;
33
35
prev
34
36
}
35
37
36
38
pub ( crate ) fn fetch_sub ( & self , val : u64 , _: Ordering ) -> u64 {
37
- let mut lock = self . 0 . lock ( ) . unwrap ( ) ;
39
+ let mut lock = self . 0 . lock ( ) ;
38
40
let prev = * lock;
39
41
* lock = prev - val;
40
42
prev
41
43
}
42
44
}
45
+
46
+ /// A simple spinlock.
47
+ pub ( crate ) struct Spinlock < T > {
48
+ flag : AtomicBool ,
49
+ value : UnsafeCell < T > ,
50
+ }
51
+
52
+ unsafe impl < T : Send > Send for Spinlock < T > { }
53
+ unsafe impl < T : Send > Sync for Spinlock < T > { }
54
+
55
+ impl < T > Spinlock < T > {
56
+ /// Returns a new spinlock initialized with `value`.
57
+ pub ( crate ) const fn new ( value : T ) -> Self {
58
+ Self {
59
+ flag : AtomicBool :: new ( false ) ,
60
+ value : UnsafeCell :: new ( value) ,
61
+ }
62
+ }
63
+
64
+ /// Locks the spinlock.
65
+ pub ( crate ) fn lock ( & self ) -> SpinlockGuard < ' _ , T > {
66
+ let backoff = Backoff :: new ( ) ;
67
+ while self . flag . swap ( true , Ordering :: Acquire ) {
68
+ backoff. snooze ( ) ;
69
+ }
70
+ SpinlockGuard ( self )
71
+ }
72
+ }
73
+
74
+ /// A guard holding a spinlock locked.
75
+ pub ( crate ) struct SpinlockGuard < ' a , T > ( & ' a Spinlock < T > ) ;
76
+
77
+ impl < T > Drop for SpinlockGuard < ' _ , T > {
78
+ fn drop ( & mut self ) {
79
+ self . 0 . flag . store ( false , Ordering :: Release ) ;
80
+ }
81
+ }
82
+
83
+ impl < T > Deref for SpinlockGuard < ' _ , T > {
84
+ type Target = T ;
85
+
86
+ fn deref ( & self ) -> & T {
87
+ unsafe { & * self . 0 . value . get ( ) }
88
+ }
89
+ }
90
+
91
+ impl < T > DerefMut for SpinlockGuard < ' _ , T > {
92
+ fn deref_mut ( & mut self ) -> & mut T {
93
+ unsafe { & mut * self . 0 . value . get ( ) }
94
+ }
95
+ }
43
96
}
0 commit comments