@@ -136,8 +136,21 @@ impl RwLock {
136136 // Wait for the state to change.
137137 futex_wait ( & self . state , state | READERS_WAITING , None ) ;
138138
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+ }
141154 }
142155 }
143156
@@ -166,9 +179,26 @@ impl RwLock {
166179 }
167180 }
168181
182+ // FIXME this does not work
169183 #[ inline]
170184 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+ }
172202 }
173203
174204 #[ cold]
0 commit comments