@@ -134,8 +134,21 @@ impl RwLock {
134
134
// Wait for the state to change.
135
135
futex_wait ( & self . state , state | READERS_WAITING , None ) ;
136
136
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
+ }
139
152
}
140
153
}
141
154
@@ -164,9 +177,26 @@ impl RwLock {
164
177
}
165
178
}
166
179
180
+ // FIXME this does not work
167
181
#[ inline]
168
182
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
+ }
170
200
}
171
201
172
202
#[ cold]
0 commit comments