@@ -134,8 +134,21 @@ impl RwLock {
134134 // Wait for the state to change.
135135 futex_wait ( & self . state , state | READERS_WAITING , None ) ;
136136
137- // Spin again after waking up.
138- state = self . spin_read ( ) ;
137+ // FIXME this protocol does not work
138+ state = self . state . load ( Relaxed ) ;
139+ if state & MASK < MAX_READERS && !has_readers_waiting ( state) {
140+ match self . state . compare_exchange_weak ( state, state + READ_LOCKED , Acquire , Relaxed )
141+ {
142+ Ok ( _) => return , // Locked!
143+ Err ( s) => {
144+ state = s;
145+ continue ;
146+ }
147+ }
148+ } else {
149+ // Otherwise, spin again after waking up.
150+ state = self . spin_read ( ) ;
151+ }
139152 }
140153 }
141154
@@ -164,9 +177,26 @@ impl RwLock {
164177 }
165178 }
166179
180+ // FIXME this does not work
167181 #[ inline]
168182 pub unsafe fn downgrade ( & self ) {
169- todo ! ( )
183+ // Removes all the write bits and adds a single read bit.
184+ let old_state = self . state . fetch_sub ( WRITE_LOCKED - READ_LOCKED , Relaxed ) ;
185+ debug_assert ! (
186+ is_write_locked( old_state) ,
187+ "RwLock must be write locked to call `downgrade`"
188+ ) ;
189+
190+ let state = old_state - WRITE_LOCKED + READ_LOCKED ;
191+ debug_assert ! (
192+ !is_unlocked( state) && !is_write_locked( state) ,
193+ "RwLock is somehow not in read mode after `downgrade`"
194+ ) ;
195+
196+ if has_readers_waiting ( state) {
197+ self . state . fetch_sub ( READERS_WAITING , Relaxed ) ;
198+ futex_wake_all ( & self . state ) ;
199+ }
170200 }
171201
172202 #[ cold]
0 commit comments