Skip to content

Commit 2489dde

Browse files
committed
Clean up Mutex lock (un)blocking code.
1 parent 093381e commit 2489dde

File tree

2 files changed

+26
-37
lines changed

2 files changed

+26
-37
lines changed

genmc-sys/cpp/src/MiriInterface/Mutex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ auto MiriGenmcShim::handle_mutex_lock(ThreadId thread_id, uint64_t address, uint
8080
// We did not acquire the mutex, so we tell GenMC to block the thread until we can acquire
8181
// it. GenMC determines this based on the annotation we pass with the load further up in
8282
// this function, namely when that load will read a value other than `MUTEX_LOCKED`.
83-
// NOTE: The blocking happens on the Miri side.
83+
GenMCDriver::handleAssume(inc_pos(thread_id), AssumeType::Spinloop);
8484
}
8585
return MutexLockResultExt::ok(is_lock_acquired);
8686
}

src/concurrency/genmc/intercept.rs

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -91,54 +91,43 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
9191
// FIXME(genmc): improve error handling.
9292
throw_ub_format!("{}", error.to_string_lossy());
9393
}
94-
debug!(
95-
"GenMC: Mutex::lock(): is_reset: {}, is_lock_acquired: {}",
96-
result.is_reset, result.is_lock_acquired
97-
);
98-
if result.is_lock_acquired {
99-
// NOTE: We don't write anything back to Miri's memory, the Mutex state is handled only by GenMC.
100-
return interp_ok(());
101-
}
102-
// We either did not acquire the mutex, or GenMC informed us to reset and try the lock again later, so we block the current thread.
103-
if !result.is_reset {
104-
// GenMC expects us to block the thread if we did get a `reset`.
105-
genmc_ctx.handle_assume_block(&this.machine, AssumeType::Spinloop)?;
106-
}
107-
// Block the thread on the Miri side.
108-
this.block_thread(
94+
if result.is_reset {
95+
debug!("GenMC: Mutex::lock: Reset");
96+
// GenMC informed us to reset and try the lock again later.
97+
// We block the current thread until GenMC schedules it again.
98+
this.block_thread(
10999
crate::BlockReason::Genmc,
110100
None,
111101
crate::callback!(
112102
@capture<'tcx> {
113103
mutex: MPlaceTy<'tcx>,
114104
}
115105
|this, unblock: crate::UnblockKind| {
116-
debug!("GenMC: handling Mutex::lock: unblocking callback called.");
106+
debug!("GenMC: Mutex::lock: unblocking callback called, attempting to lock the Mutex again.");
117107
assert_eq!(unblock, crate::UnblockKind::Ready);
118-
let genmc_ctx = this.machine.data_race.as_genmc_ref().unwrap();
119-
let result = genmc_ctx.handle
120-
.borrow_mut()
121-
.pin_mut()
122-
.handle_mutex_lock(
123-
genmc_ctx.active_thread_genmc_tid(&this.machine),
124-
mutex.ptr().addr().bytes(),
125-
mutex.layout.size.bytes(),
126-
);
127-
if let Some(error) = result.error.as_ref() {
128-
// FIXME(genmc): improve error handling.
129-
throw_ub_format!("{}", error.to_string_lossy());
130-
}
131-
assert!(!result.is_reset, "We should not get a reset on the second lock attempt.");
132-
// If we did not acquire the mutex and GenMC did not tell us to reset and try again, we block this thread for the remainder of the current execution.
133-
if !result.is_lock_acquired {
134-
debug!("GenMC: Mutex::lock failed to acquire the Mutex twice, permanently blocking thread.");
135-
// This is equivalent to a user inserted `assume(false)`.
136-
this.handle_user_assume_block()?;
137-
}
108+
this.intercept_mutex_lock(mutex)?;
138109
interp_ok(())
139110
}
140111
),
141112
);
113+
} else if result.is_lock_acquired {
114+
debug!("GenMC: Mutex::lock successfully acquired the Mutex.");
115+
} else {
116+
debug!("GenMC: Mutex::lock failed to acquire the Mutex, permanently blocking thread.");
117+
// NOTE: `handle_mutex_lock` already blocked the current thread on the GenMC side.
118+
this.block_thread(
119+
crate::BlockReason::Genmc,
120+
None,
121+
crate::callback!(
122+
@capture<'tcx> {
123+
mutex: MPlaceTy<'tcx>,
124+
}
125+
|this, _unblock: crate::UnblockKind| {
126+
unreachable!("A thread blocked on `Mutex::lock` should not be unblocked again.");
127+
}
128+
),
129+
);
130+
}
142131
// NOTE: We don't write anything back to Miri's memory where the Mutex is located, that state is handled only by GenMC.
143132
interp_ok(())
144133
}

0 commit comments

Comments
 (0)