@@ -136,8 +136,21 @@ impl RwLock {
136
136
// Wait for the state to change.
137
137
futex_wait ( & self . state , state | READERS_WAITING , None ) ;
138
138
139
- // Spin again after waking up.
140
- state = self . spin_read ( ) ;
139
+ // FIXME this protocol does not work
140
+ state = self . state . load ( Relaxed ) ;
141
+ if state & MASK < MAX_READERS && !has_readers_waiting ( state) {
142
+ match self . state . compare_exchange_weak ( state, state + READ_LOCKED , Acquire , Relaxed )
143
+ {
144
+ Ok ( _) => return , // Locked!
145
+ Err ( s) => {
146
+ state = s;
147
+ continue ;
148
+ }
149
+ }
150
+ } else {
151
+ // Otherwise, spin again after waking up.
152
+ state = self . spin_read ( ) ;
153
+ }
141
154
}
142
155
}
143
156
@@ -166,9 +179,26 @@ impl RwLock {
166
179
}
167
180
}
168
181
182
+ // FIXME this does not work
169
183
#[ inline]
170
184
pub unsafe fn downgrade ( & self ) {
171
- todo ! ( )
185
+ // Removes all the write bits and adds a single read bit.
186
+ let old_state = self . state . fetch_sub ( WRITE_LOCKED - READ_LOCKED , Relaxed ) ;
187
+ debug_assert ! (
188
+ is_write_locked( old_state) ,
189
+ "RwLock must be write locked to call `downgrade`"
190
+ ) ;
191
+
192
+ let state = old_state - WRITE_LOCKED + READ_LOCKED ;
193
+ debug_assert ! (
194
+ !is_unlocked( state) && !is_write_locked( state) ,
195
+ "RwLock is somehow not in read mode after `downgrade`"
196
+ ) ;
197
+
198
+ if has_readers_waiting ( state) {
199
+ self . state . fetch_sub ( READERS_WAITING , Relaxed ) ;
200
+ futex_wake_all ( & self . state ) ;
201
+ }
172
202
}
173
203
174
204
#[ cold]
0 commit comments