Skip to content

Commit 34e255d

Browse files
committed
futex not catastrophically failing yet
1 parent d8456d6 commit 34e255d

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

library/std/src/sync/rwlock.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod tests;
44
use crate::cell::UnsafeCell;
55
use crate::fmt;
66
use crate::marker::PhantomData;
7-
use crate::mem::ManuallyDrop;
7+
use crate::mem::{forget, ManuallyDrop};
88
use crate::ops::{Deref, DerefMut};
99
use crate::ptr::NonNull;
1010
use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
@@ -969,13 +969,18 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
969969
/// MORE DOCS COMING SOON.
970970
#[unstable(feature = "rwlock_downgrade", issue = "128203")]
971971
pub fn downgrade(s: Self) -> RwLockReadGuard<'a, T> {
972+
let lock = s.lock;
973+
972974
// SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
973975
// mode, satisfying the `downgrade` contract.
974-
unsafe { s.lock.inner.downgrade() };
976+
unsafe { lock.inner.downgrade() };
977+
978+
// We don't want to call the destructor since that calls `write_unlock`.
979+
forget(s);
975980

976981
// SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
977982
unsafe {
978-
RwLockReadGuard::new(s.lock)
983+
RwLockReadGuard::new(lock)
979984
.expect("We had the exclusive lock so we can't have panicked while holding it")
980985
}
981986
}

library/std/src/sync/rwlock/tests.rs

+8
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,11 @@ fn panic_while_mapping_write_unlocked_poison() {
496496

497497
drop(lock);
498498
}
499+
500+
#[test]
501+
fn test_downgrade_basic() {
502+
let r = RwLock::new(());
503+
504+
let write_guard = r.write().unwrap();
505+
let _read_guard = RwLockWriteGuard::downgrade(write_guard);
506+
}

library/std/src/sys/sync/rwlock/futex.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ impl RwLock {
136136
// Wait for the state to change.
137137
futex_wait(&self.state, state | READERS_WAITING, None);
138138

139-
// FIXME this protocol does not work
139+
// FIXME make sure this works
140+
// FIXME this can probably be more elegant
140141
state = self.state.load(Relaxed);
141142
if state & MASK < MAX_READERS && !has_readers_waiting(state) {
142143
match self.state.compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed)
@@ -147,10 +148,10 @@ impl RwLock {
147148
continue;
148149
}
149150
}
150-
} else {
151-
// Otherwise, spin again after waking up.
152-
state = self.spin_read();
153151
}
152+
153+
// Otherwise, spin again after waking up.
154+
state = self.spin_read();
154155
}
155156
}
156157

@@ -179,7 +180,7 @@ impl RwLock {
179180
}
180181
}
181182

182-
// FIXME this does not work
183+
// FIXME make sure this works
183184
#[inline]
184185
pub unsafe fn downgrade(&self) {
185186
// Removes all the write bits and adds a single read bit.

0 commit comments

Comments
 (0)