/// released to during unlock and acquired from during
/// locking, and therefore stores the clock of the last
/// thread to release this mutex.
- data_race: VClock
+ data_race: VClock,
}
declare_id!(RwLockId);
/// is stored to the main data_race variable once all
/// readers are finished.
/// Has to be stored separately since reader lock acquires
- /// must load the clock of the last write and must not
+ /// must load the clock of the last write and must not
/// add happens-before orderings between shared reader
/// locks.
data_race_reader: VClock,
mutexes: IndexVec<MutexId, Mutex>,
rwlocks: IndexVec<RwLockId, RwLock>,
condvars: IndexVec<CondvarId, Condvar>,
- futexes: HashMap<Pointer, Futex>,
+ futexes: HashMap<u64, Futex>,
}
// Private extension trait for local helper methods
/// count. If the lock count reaches 0, release the lock and potentially
/// give to a new owner. If the lock was not locked by `expected_owner`,
/// return `None`.
- fn mutex_unlock(
- &mut self,
- id: MutexId,
- expected_owner: ThreadId,
- ) -> Option<usize> {
+ fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option<usize> {
let this = self.eval_context_mut();
let mutex = &mut this.machine.threads.sync.mutexes[id];
if let Some(current_owner) = mutex.owner {
let rwlock = &this.machine.threads.sync.rwlocks[id];
trace!(
"rwlock_is_locked: {:?} writer is {:?} and there are {} reader threads (some of which could hold multiple read locks)",
- id, rwlock.writer, rwlock.readers.len(),
+ id,
+ rwlock.writer,
+ rwlock.readers.len(),
);
- rwlock.writer.is_some()|| rwlock.readers.is_empty().not()
+ rwlock.writer.is_some() || rwlock.readers.is_empty().not()
}
#[inline]
// The thread was a reader. If the lock is not held any more, give it to a writer.
if this.rwlock_is_locked(id).not() {
-
// All the readers are finished, so set the writer data-race handle to the value
// of the union of all reader data race handles, since the set of readers
// happen-before the writers
#[inline]
/// Put the reader in the queue waiting for the lock and block it.
- fn rwlock_enqueue_and_block_reader(
- &mut self,
- id: RwLockId,
- reader: ThreadId,
- ) {
+ fn rwlock_enqueue_and_block_reader(&mut self, id: RwLockId, reader: ThreadId) {
let this = self.eval_context_mut();
assert!(this.rwlock_is_write_locked(id), "read-queueing on not write locked rwlock");
this.machine.threads.sync.rwlocks[id].reader_queue.push_back(reader);
#[inline]
/// Put the writer in the queue waiting for the lock.
- fn rwlock_enqueue_and_block_writer(
- &mut self,
- id: RwLockId,
- writer: ThreadId,
- ) {
+ fn rwlock_enqueue_and_block_writer(&mut self, id: RwLockId, writer: ThreadId) {
let this = self.eval_context_mut();
assert!(this.rwlock_is_locked(id), "write-queueing on unlocked rwlock");
this.machine.threads.sync.rwlocks[id].writer_queue.push_back(writer);
if let Some(data_race) = data_race {
data_race.validate_lock_release(&mut condvar.data_race, current_thread);
}
- condvar.waiters
- .pop_front()
- .map(|waiter| {
- if let Some(data_race) = data_race {
- data_race.validate_lock_acquire(&mut condvar.data_race, waiter.thread);
- }
- (waiter.thread, waiter.mutex)
- })
+ condvar.waiters.pop_front().map(|waiter| {
+ if let Some(data_race) = data_race {
+ data_race.validate_lock_acquire(&mut condvar.data_race, waiter.thread);
+ }
+ (waiter.thread, waiter.mutex)
+ })
}
#[inline]
this.machine.threads.sync.condvars[id].waiters.retain(|waiter| waiter.thread != thread);
}
- fn futex_wait(&mut self, addr: Pointer<stacked_borrows::Tag>, thread: ThreadId) {
+ fn futex_wait(&mut self, addr: u64, thread: ThreadId) {
let this = self.eval_context_mut();
- let futex = &mut this.machine.threads.sync.futexes.entry(addr.erase_tag()).or_default();
+ let futex = &mut this.machine.threads.sync.futexes.entry(addr).or_default();
let waiters = &mut futex.waiters;
assert!(waiters.iter().all(|waiter| waiter.thread != thread), "thread is already waiting");
waiters.push_back(FutexWaiter { thread });
}
- fn futex_wake(&mut self, addr: Pointer<stacked_borrows::Tag>) -> Option<ThreadId> {
+ fn futex_wake(&mut self, addr: u64) -> Option<ThreadId> {
let this = self.eval_context_mut();
let current_thread = this.get_active_thread();
- let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr.erase_tag())?;
- let data_race = &this.memory.extra.data_race;
+ let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?;
+ let data_race = &this.memory.extra.data_race;
// Each futex-wake happens-before the end of the futex wait
if let Some(data_race) = data_race {
}
let res = futex.waiters.pop_front().map(|waiter| {
if let Some(data_race) = data_race {
- data_race.validate_lock_acquire(&futex.data_race, waiter.thread);
+ data_race.validate_lock_acquire(&futex.data_race, waiter.thread);
}
waiter.thread
});
res
}
- fn futex_remove_waiter(&mut self, addr: Pointer<stacked_borrows::Tag>, thread: ThreadId) {
+ fn futex_remove_waiter(&mut self, addr: u64, thread: ThreadId) {
let this = self.eval_context_mut();
- if let Some(futex) = this.machine.threads.sync.futexes.get_mut(&addr.erase_tag()) {
+ if let Some(futex) = this.machine.threads.sync.futexes.get_mut(&addr) {
futex.waiters.retain(|waiter| waiter.thread != thread);
}
}