@@ -78,6 +78,7 @@ struct RawLockFuture<'a> {
78
78
79
79
impl < ' a > RawLockFuture < ' a > {
80
80
/// Remove waker registration. This should be called upon successful acqusition of the lock.
81
+ #[ cold]
81
82
fn deregister_waker ( & mut self , acquired : bool ) {
82
83
if let Some ( key) = self . opt_key . take ( ) {
83
84
let mut blocked = self . mutex . blocked . lock ( ) ;
@@ -94,6 +95,57 @@ impl<'a> RawLockFuture<'a> {
94
95
}
95
96
}
96
97
98
+ /// The cold path where the first poll of a mutex will cause the mutex to block.
99
+ #[ cold]
100
+ fn poll_would_block ( & mut self , cx : & mut Context < ' _ > ) -> Poll < ( ) > {
101
+ let mut blocked = self . mutex . blocked . lock ( ) ;
102
+
103
+ // Try locking again because it's possible the mutex got unlocked before
104
+ // we acquire the lock of `blocked`.
105
+ let state = self . mutex . state . fetch_or ( LOCK | BLOCKED , Ordering :: Relaxed ) ;
106
+ if state & LOCK == 0 {
107
+ return Poll :: Ready ( ( ) ) ;
108
+ }
109
+
110
+ // Register the current task.
111
+ // Insert a new entry into the list of blocked tasks.
112
+ let w = cx. waker ( ) . clone ( ) ;
113
+ let key = blocked. insert ( Some ( w) ) ;
114
+ self . opt_key = Some ( key) ;
115
+
116
+ Poll :: Pending
117
+ }
118
+
119
+ /// The cold path where we are polling an already-blocked mutex
120
+ #[ cold]
121
+ fn poll_blocked ( & mut self , cx : & mut Context < ' _ > ) -> Poll < ( ) > {
122
+ if self . mutex . try_lock ( ) {
123
+ self . deregister_waker ( true ) ;
124
+ Poll :: Ready ( ( ) )
125
+ } else {
126
+ let mut blocked = self . mutex . blocked . lock ( ) ;
127
+
128
+ // Try locking again because it's possible the mutex got unlocked before
129
+ // we acquire the lock of `blocked`. On this path we know we have BLOCKED
130
+ // set, so don't bother to set it again.
131
+ if self . mutex . try_lock ( ) {
132
+ std:: mem:: drop ( blocked) ;
133
+ self . deregister_waker ( true ) ;
134
+ return Poll :: Ready ( ( ) ) ;
135
+ }
136
+
137
+ // There is already an entry in the list of blocked tasks. Just
138
+ // reset the waker if it was removed.
139
+ let opt_waker = unsafe { blocked. get ( self . opt_key . unwrap ( ) ) } ;
140
+ if opt_waker. is_none ( ) {
141
+ let w = cx. waker ( ) . clone ( ) ;
142
+ * opt_waker = Some ( w) ;
143
+ }
144
+
145
+ Poll :: Pending
146
+ }
147
+ }
148
+
97
149
/// Cold path of drop. Only to be hit when locking is cancelled.
98
150
#[ cold]
99
151
fn drop_slow ( & mut self ) {
@@ -104,57 +156,17 @@ impl<'a> RawLockFuture<'a> {
104
156
impl < ' a > Future for RawLockFuture < ' a > {
105
157
type Output = ( ) ;
106
158
159
+ #[ inline]
107
160
fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
108
161
match self . opt_key {
109
162
None => {
110
163
if self . mutex . try_lock ( ) {
111
164
Poll :: Ready ( ( ) )
112
165
} else {
113
- let mut blocked = self . mutex . blocked . lock ( ) ;
114
-
115
- // Try locking again because it's possible the mutex got unlocked before
116
- // we acquire the lock of `blocked`.
117
- let state = self . mutex . state . fetch_or ( LOCK | BLOCKED , Ordering :: Relaxed ) ;
118
- if state & LOCK == 0 {
119
- return Poll :: Ready ( ( ) ) ;
120
- }
121
-
122
- // Register the current task.
123
- // Insert a new entry into the list of blocked tasks.
124
- let w = cx. waker ( ) . clone ( ) ;
125
- let key = blocked. insert ( Some ( w) ) ;
126
- self . opt_key = Some ( key) ;
127
-
128
- Poll :: Pending
129
- }
130
- }
131
- Some ( key) => {
132
- if self . mutex . try_lock ( ) {
133
- self . deregister_waker ( true ) ;
134
- Poll :: Ready ( ( ) )
135
- } else {
136
- let mut blocked = self . mutex . blocked . lock ( ) ;
137
-
138
- // Try locking again because it's possible the mutex got unlocked before
139
- // we acquire the lock of `blocked`. On this path we know we have BLOCKED
140
- // set, so don't bother to set it again.
141
- if self . mutex . try_lock ( ) {
142
- std:: mem:: drop ( blocked) ;
143
- self . deregister_waker ( true ) ;
144
- return Poll :: Ready ( ( ) ) ;
145
- }
146
-
147
- // There is already an entry in the list of blocked tasks. Just
148
- // reset the waker if it was removed.
149
- let opt_waker = unsafe { blocked. get ( key) } ;
150
- if opt_waker. is_none ( ) {
151
- let w = cx. waker ( ) . clone ( ) ;
152
- * opt_waker = Some ( w) ;
153
- }
154
-
155
- Poll :: Pending
166
+ self . poll_would_block ( cx)
156
167
}
157
168
}
169
+ Some ( _) => self . poll_blocked ( cx) ,
158
170
}
159
171
}
160
172
}
0 commit comments