Skip to content

Commit 08fa421

Browse files
committed
squash! SelfContainedFutex: avoid live-lock in lock
Use a single condvar per futex word.
1 parent ccaed69 commit 08fa421

1 file changed

Lines changed: 13 additions & 16 deletions

File tree

src/lib/shadow-shim-helper-rs/src/scmutex.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ mod sync {
2727
use std::collections::HashMap;
2828
#[cfg(loom)]
2929
loom::lazy_static! {
30-
pub static ref FUTEXES: Mutex<HashMap<usize, Vec<Arc<Condvar>>>> = Mutex::new(HashMap::new());
30+
pub static ref FUTEXES: Mutex<HashMap<usize, Arc<Condvar>>> = Mutex::new(HashMap::new());
3131
}
3232

3333
#[cfg(not(loom))]
@@ -68,19 +68,18 @@ mod sync {
6868
if futex_word_val != val {
6969
return Err(nix::errno::Errno::EAGAIN);
7070
}
71-
let waiters = hashmap
71+
let condvar = hashmap
7272
.entry(futex_word as *const _ as usize)
73-
.or_insert(Vec::new());
74-
let condvar = Arc::new(Condvar::new());
75-
waiters.push(condvar.clone());
73+
.or_insert(Arc::new(Condvar::new()))
74+
.clone();
7675
// We could get a spurious wakeup here, but that's ok.
7776
// Futexes are subject to spurious wakeups too.
7877
condvar.wait(hashmap).unwrap();
7978
Ok(0)
8079
}
8180

8281
#[cfg(not(loom))]
83-
pub(super) unsafe fn futex_wake(futex_word: &super::AtomicFutexWord) -> nix::Result<i64> {
82+
pub(super) unsafe fn futex_wake(futex_word: &super::AtomicFutexWord) -> nix::Result<()> {
8483
// The kernel just checks for equality of the value at this pointer.
8584
// Just validate that it's the right size and alignment.
8685
assert_eq!(
@@ -103,19 +102,17 @@ mod sync {
103102
std::ptr::null_mut() as *mut u32,
104103
032,
105104
)
106-
})
105+
})?;
106+
Ok(())
107107
}
108108
#[cfg(loom)]
109-
pub(super) unsafe fn futex_wake(futex_word: &super::AtomicFutexWord) -> nix::Result<i64> {
110-
let mut hashmap = FUTEXES.lock().unwrap();
111-
let Some(waiters) = hashmap.get_mut(&(futex_word as *const _ as usize)) else {
112-
return Ok(0);
113-
};
114-
let Some(condvar) = waiters.pop() else {
115-
return Ok(0);
109+
pub(super) unsafe fn futex_wake(futex_word: &super::AtomicFutexWord) -> nix::Result<()> {
110+
let hashmap = FUTEXES.lock().unwrap();
111+
let Some(condvar) = hashmap.get(&(futex_word as *const _ as usize)) else {
112+
return Ok(());
116113
};
117-
condvar.notify_all();
118-
Ok(1)
114+
condvar.notify_one();
115+
Ok(())
119116
}
120117

121118
#[cfg(not(loom))]

0 commit comments

Comments
 (0)