From bfb36e35b98c9649005fc65fd92d690bdbbc7406 Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 29 Oct 2024 00:20:45 +0800 Subject: [PATCH] Remove MutexID list --- src/tools/miri/src/concurrency/sync.rs | 100 ++++++++++++-------- src/tools/miri/src/concurrency/thread.rs | 2 +- src/tools/miri/src/lib.rs | 2 +- src/tools/miri/src/shims/unix/macos/sync.rs | 44 +++++---- src/tools/miri/src/shims/unix/sync.rs | 49 +++++----- 5 files changed, 111 insertions(+), 86 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 199aedfa6d237..43950495fb91d 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -1,6 +1,9 @@ +use std::cell::RefCell; use std::collections::VecDeque; use std::collections::hash_map::Entry; +use std::default::Default; use std::ops::Not; +use std::rc::Rc; use std::time::Duration; use rustc_data_structures::fx::FxHashMap; @@ -44,8 +47,6 @@ macro_rules! declare_id { } pub(super) use declare_id; -declare_id!(MutexId); - /// The mutex state. #[derive(Default, Debug)] struct Mutex { @@ -59,6 +60,21 @@ struct Mutex { clock: VClock, } +#[derive(Default, Clone, Debug)] +pub struct MutexRef(Rc>); + +impl MutexRef { + fn new() -> Self { + MutexRef(Rc::new(RefCell::new(Mutex::default()))) + } +} + +impl VisitProvenance for MutexRef { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { + // Mutex contains no provenance. + } +} + declare_id!(RwLockId); /// The read-write lock state. @@ -133,7 +149,6 @@ struct FutexWaiter { /// The state of all synchronization objects. #[derive(Default, Debug)] pub struct SynchronizationObjects { - mutexes: IndexVec, rwlocks: IndexVec, condvars: IndexVec, pub(super) init_onces: IndexVec, @@ -147,17 +162,17 @@ impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn condvar_reacquire_mutex( &mut self, - mutex: MutexId, + mutex_ref: &MutexRef, retval: Scalar, dest: MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - if this.mutex_is_locked(mutex) { - assert_ne!(this.mutex_get_owner(mutex), this.active_thread()); - this.mutex_enqueue_and_block(mutex, Some((retval, dest))); + if this.mutex_is_locked(mutex_ref) { + assert_ne!(this.mutex_get_owner(mutex_ref), this.active_thread()); + this.mutex_enqueue_and_block(mutex_ref, Some((retval, dest))); } else { // We can have it right now! - this.mutex_lock(mutex); + this.mutex_lock(mutex_ref); // Don't forget to write the return value. this.write_scalar(retval, &dest)?; } @@ -166,10 +181,9 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } impl SynchronizationObjects { - pub fn mutex_create(&mut self) -> MutexId { - self.mutexes.push(Default::default()) + pub fn mutex_create(&mut self) -> MutexRef { + MutexRef::new() } - pub fn rwlock_create(&mut self) -> RwLockId { self.rwlocks.push(Default::default()) } @@ -201,7 +215,7 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Helper for lazily initialized `alloc_extra.sync` data: /// this forces an immediate init. - fn lazy_sync_init( + fn lazy_sync_init( &mut self, primitive: &MPlaceTy<'tcx>, init_offset: Size, @@ -227,7 +241,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// - If yes, fetches the data from `alloc_extra.sync`, or calls `missing_data` if that fails /// and stores that in `alloc_extra.sync`. /// - Otherwise, calls `new_data` to initialize the primitive. - fn lazy_sync_get_data( + /// + /// The return value is a *clone* of the stored data, so if you intend to mutate it + /// better wrap everything into an `Rc`. + fn lazy_sync_get_data( &mut self, primitive: &MPlaceTy<'tcx>, init_offset: Size, @@ -258,15 +275,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; if let Some(data) = alloc_extra.get_sync::(offset) { - interp_ok(*data) + interp_ok(data.clone()) } else { let data = missing_data()?; - alloc_extra.sync.insert(offset, Box::new(data)); + alloc_extra.sync.insert(offset, Box::new(data.clone())); interp_ok(data) } } else { let data = new_data(this)?; - this.lazy_sync_init(primitive, init_offset, data)?; + this.lazy_sync_init(primitive, init_offset, data.clone())?; interp_ok(data) } } @@ -298,23 +315,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { #[inline] /// Get the id of the thread that currently owns this lock. - fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId { - let this = self.eval_context_ref(); - this.machine.sync.mutexes[id].owner.unwrap() + fn mutex_get_owner(&mut self, mutex_ref: &MutexRef) -> ThreadId { + mutex_ref.0.borrow().owner.unwrap() } #[inline] /// Check if locked. - fn mutex_is_locked(&self, id: MutexId) -> bool { - let this = self.eval_context_ref(); - this.machine.sync.mutexes[id].owner.is_some() + fn mutex_is_locked(&self, mutex_ref: &MutexRef) -> bool { + mutex_ref.0.borrow().owner.is_some() } /// Lock by setting the mutex owner and increasing the lock count. - fn mutex_lock(&mut self, id: MutexId) { + fn mutex_lock(&mut self, mutex_ref: &MutexRef) { let this = self.eval_context_mut(); let thread = this.active_thread(); - let mutex = &mut this.machine.sync.mutexes[id]; + let mut mutex = mutex_ref.0.borrow_mut(); if let Some(current_owner) = mutex.owner { assert_eq!(thread, current_owner, "mutex already locked by another thread"); assert!( @@ -334,9 +349,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// count. If the lock count reaches 0, release the lock and potentially /// give to a new owner. If the lock was not locked by the current thread, /// return `None`. - fn mutex_unlock(&mut self, id: MutexId) -> InterpResult<'tcx, Option> { + fn mutex_unlock(&mut self, mutex_ref: &MutexRef) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); - let mutex = &mut this.machine.sync.mutexes[id]; + let mut mutex = mutex_ref.0.borrow_mut(); interp_ok(if let Some(current_owner) = mutex.owner { // Mutex is locked. if current_owner != this.machine.threads.active_thread() { @@ -354,8 +369,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutex.clock.clone_from(clock) }); } - if let Some(thread) = this.machine.sync.mutexes[id].queue.pop_front() { - this.unblock_thread(thread, BlockReason::Mutex(id))?; + let thread_id = mutex.queue.pop_front(); + // We need to drop our mutex borrow before unblock_thread + // because it will be borrowed again in the unblock callback. + drop(mutex); + if thread_id.is_some() { + this.unblock_thread(thread_id.unwrap(), BlockReason::Mutex)?; } } Some(old_lock_count) @@ -372,24 +391,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { #[inline] fn mutex_enqueue_and_block( &mut self, - id: MutexId, + mutex_ref: &MutexRef, retval_dest: Option<(Scalar, MPlaceTy<'tcx>)>, ) { let this = self.eval_context_mut(); - assert!(this.mutex_is_locked(id), "queing on unlocked mutex"); + assert!(this.mutex_is_locked(mutex_ref), "queuing on unlocked mutex"); let thread = this.active_thread(); - this.machine.sync.mutexes[id].queue.push_back(thread); + mutex_ref.0.borrow_mut().queue.push_back(thread); + let mutex_ref = mutex_ref.clone(); this.block_thread( - BlockReason::Mutex(id), + BlockReason::Mutex, None, callback!( @capture<'tcx> { - id: MutexId, + mutex_ref: MutexRef, retval_dest: Option<(Scalar, MPlaceTy<'tcx>)>, } @unblock = |this| { - assert!(!this.mutex_is_locked(id)); - this.mutex_lock(id); + assert!(!this.mutex_is_locked(&mutex_ref)); + this.mutex_lock(&mutex_ref); if let Some((retval, dest)) = retval_dest { this.write_scalar(retval, &dest)?; @@ -610,14 +630,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn condvar_wait( &mut self, condvar: CondvarId, - mutex: MutexId, + mutex_ref: MutexRef, timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>, retval_succ: Scalar, retval_timeout: Scalar, dest: MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - if let Some(old_locked_count) = this.mutex_unlock(mutex)? { + if let Some(old_locked_count) = this.mutex_unlock(&mutex_ref)? { if old_locked_count != 1 { throw_unsup_format!( "awaiting a condvar on a mutex acquired multiple times is not supported" @@ -637,7 +657,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { callback!( @capture<'tcx> { condvar: CondvarId, - mutex: MutexId, + mutex_ref: MutexRef, retval_succ: Scalar, retval_timeout: Scalar, dest: MPlaceTy<'tcx>, @@ -652,7 +672,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Try to acquire the mutex. // The timeout only applies to the first wait (until the signal), not for mutex acquisition. - this.condvar_reacquire_mutex(mutex, retval_succ, dest) + this.condvar_reacquire_mutex(&mutex_ref, retval_succ, dest) } @timeout = |this| { // We have to remove the waiter from the queue again. @@ -660,7 +680,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let waiters = &mut this.machine.sync.condvars[condvar].waiters; waiters.retain(|waiter| *waiter != thread); // Now get back the lock. - this.condvar_reacquire_mutex(mutex, retval_timeout, dest) + this.condvar_reacquire_mutex(&mutex_ref, retval_timeout, dest) } ), ); diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 3946cb5ee5431..596aaeca87ae6 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -162,7 +162,7 @@ pub enum BlockReason { /// Waiting for time to pass. Sleep, /// Blocked on a mutex. - Mutex(MutexId), + Mutex, /// Blocked on a condition variable. Condvar(CondvarId), /// Blocked on a reader-writer lock. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 938d1ca319e0f..e8451dc5e5008 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -121,7 +121,7 @@ pub use crate::concurrency::data_race::{ }; pub use crate::concurrency::init_once::{EvalContextExt as _, InitOnceId}; pub use crate::concurrency::sync::{ - CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects, + CondvarId, EvalContextExt as _, MutexRef, RwLockId, SynchronizationObjects, }; pub use crate::concurrency::thread::{ BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, TimeoutAnchor, diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 1df1202442a86..431fd34e78f9d 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -14,10 +14,10 @@ use rustc_target::abi::Size; use crate::*; -#[derive(Copy, Clone)] +#[derive(Clone)] enum MacOsUnfairLock { Poisoned, - Active { id: MutexId }, + Active { mutex_ref: MutexRef }, } impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -42,8 +42,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(MacOsUnfairLock::Poisoned) }, |ecx| { - let id = ecx.machine.sync.mutex_create(); - interp_ok(MacOsUnfairLock::Active { id }) + let mutex_ref = ecx.machine.sync.mutex_create(); + interp_ok(MacOsUnfairLock::Active { mutex_ref }) }, ) } @@ -54,7 +54,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_lock(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { // Trying to get a poisoned lock. Just block forever... this.block_thread( BlockReason::Sleep, @@ -69,17 +69,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(()); }; - if this.mutex_is_locked(id) { - if this.mutex_get_owner(id) == this.active_thread() { + if this.mutex_is_locked(&mutex_ref) { + if this.mutex_get_owner(&mutex_ref) == this.active_thread() { // Matching the current macOS implementation: abort on reentrant locking. throw_machine_stop!(TerminationInfo::Abort( "attempted to lock an os_unfair_lock that is already locked by the current thread".to_owned() )); } - this.mutex_enqueue_and_block(id, None); + this.mutex_enqueue_and_block(&mutex_ref, None); } else { - this.mutex_lock(id); + this.mutex_lock(&mutex_ref); } interp_ok(()) @@ -92,18 +92,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { // Trying to get a poisoned lock. That never works. this.write_scalar(Scalar::from_bool(false), dest)?; return interp_ok(()); }; - if this.mutex_is_locked(id) { + if this.mutex_is_locked(&mutex_ref) { // Contrary to the blocking lock function, this does not check for // reentrancy. this.write_scalar(Scalar::from_bool(false), dest)?; } else { - this.mutex_lock(id); + this.mutex_lock(&mutex_ref); this.write_scalar(Scalar::from_bool(true), dest)?; } @@ -113,7 +113,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_unlock(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { // The lock is poisoned, who knows who owns it... we'll pretend: someone else. throw_machine_stop!(TerminationInfo::Abort( "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned() @@ -121,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; // Now, unlock. - if this.mutex_unlock(id)?.is_none() { + if this.mutex_unlock(&mutex_ref)?.is_none() { // Matching the current macOS implementation: abort. throw_machine_stop!(TerminationInfo::Abort( "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned() @@ -130,7 +130,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the lock is not locked by anyone now, it went quer. // Reset to zero so that it can be moved and initialized again for the next phase. - if !this.mutex_is_locked(id) { + if !this.mutex_is_locked(&mutex_ref) { let lock_place = this.deref_pointer_as(lock_op, this.machine.layouts.u32)?; this.write_scalar_atomic(Scalar::from_u32(0), &lock_place, AtomicWriteOrd::Relaxed)?; } @@ -141,13 +141,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_assert_owner(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { // The lock is poisoned, who knows who owns it... we'll pretend: someone else. throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() )); }; - if !this.mutex_is_locked(id) || this.mutex_get_owner(id) != this.active_thread() { + if !this.mutex_is_locked(&mutex_ref) + || this.mutex_get_owner(&mutex_ref) != this.active_thread() + { throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() )); @@ -161,11 +163,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_assert_not_owner(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { // The lock is poisoned, who knows who owns it... we'll pretend: someone else. return interp_ok(()); }; - if this.mutex_is_locked(id) && this.mutex_get_owner(id) == this.active_thread() { + if this.mutex_is_locked(&mutex_ref) + && this.mutex_get_owner(&mutex_ref) == this.active_thread() + { throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_not_owner on an os_unfair_lock owned by the current thread".to_owned() )); @@ -173,7 +177,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the lock is not locked by anyone now, it went quer. // Reset to zero so that it can be moved and initialized again for the next phase. - if !this.mutex_is_locked(id) { + if !this.mutex_is_locked(&mutex_ref) { let lock_place = this.deref_pointer_as(lock_op, this.machine.layouts.u32)?; this.write_scalar_atomic(Scalar::from_u32(0), &lock_place, AtomicWriteOrd::Relaxed)?; } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index a4beaa47baa4f..8760246e4388e 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -116,9 +116,9 @@ enum MutexKind { ErrorCheck, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] struct PthreadMutex { - id: MutexId, + mutex_ref: MutexRef, kind: MutexKind, } @@ -175,15 +175,13 @@ fn mutex_create<'tcx>( ) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer(mutex_ptr)?; let id = ecx.machine.sync.mutex_create(); - let data = PthreadMutex { id, kind }; - ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data)?; + let data = PthreadMutex { mutex_ref: id, kind }; + ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data.clone())?; interp_ok(data) } -/// Returns the `MutexId` of the mutex stored at `mutex_op`. -/// -/// `mutex_get_id` will also check if the mutex has been moved since its first use and -/// return an error if it has. +/// Returns the mutex data stored at the address that `mutex_ptr` points to. +/// Will raise an error if the mutex has been moved since its first use. fn mutex_get_data<'tcx, 'a>( ecx: &'a mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, @@ -196,7 +194,7 @@ fn mutex_get_data<'tcx, 'a>( |ecx| { let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; let id = ecx.machine.sync.mutex_create(); - interp_ok(PthreadMutex { id, kind }) + interp_ok(PthreadMutex { mutex_ref: id, kind }) }, ) } @@ -502,10 +500,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mutex = mutex_get_data(this, mutex_op)?; - let ret = if this.mutex_is_locked(mutex.id) { - let owner_thread = this.mutex_get_owner(mutex.id); + let ret = if this.mutex_is_locked(&mutex.mutex_ref) { + let owner_thread = this.mutex_get_owner(&mutex.mutex_ref); if owner_thread != this.active_thread() { - this.mutex_enqueue_and_block(mutex.id, Some((Scalar::from_i32(0), dest.clone()))); + this.mutex_enqueue_and_block( + &mutex.mutex_ref, + Some((Scalar::from_i32(0), dest.clone())), + ); return interp_ok(()); } else { // Trying to acquire the same mutex again. @@ -517,14 +518,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), MutexKind::Recursive => { - this.mutex_lock(mutex.id); + this.mutex_lock(&mutex.mutex_ref); 0 } } } } else { // The mutex is unlocked. Let's lock it. - this.mutex_lock(mutex.id); + this.mutex_lock(&mutex.mutex_ref); 0 }; this.write_scalar(Scalar::from_i32(ret), dest)?; @@ -536,8 +537,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mutex = mutex_get_data(this, mutex_op)?; - interp_ok(Scalar::from_i32(if this.mutex_is_locked(mutex.id) { - let owner_thread = this.mutex_get_owner(mutex.id); + interp_ok(Scalar::from_i32(if this.mutex_is_locked(&mutex.mutex_ref) { + let owner_thread = this.mutex_get_owner(&mutex.mutex_ref); if owner_thread != this.active_thread() { this.eval_libc_i32("EBUSY") } else { @@ -545,14 +546,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => this.eval_libc_i32("EBUSY"), MutexKind::Recursive => { - this.mutex_lock(mutex.id); + this.mutex_lock(&mutex.mutex_ref); 0 } } } } else { // The mutex is unlocked. Let's lock it. - this.mutex_lock(mutex.id); + this.mutex_lock(&mutex.mutex_ref); 0 })) } @@ -562,7 +563,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mutex = mutex_get_data(this, mutex_op)?; - if let Some(_old_locked_count) = this.mutex_unlock(mutex.id)? { + if let Some(_old_locked_count) = this.mutex_unlock(&mutex.mutex_ref)? { // The mutex was locked by the current thread. interp_ok(Scalar::from_i32(0)) } else { @@ -591,7 +592,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // since we make the field unint below. let mutex = mutex_get_data(this, mutex_op)?; - if this.mutex_is_locked(mutex.id) { + if this.mutex_is_locked(&mutex.mutex_ref) { throw_ub_format!("destroyed a locked mutex"); } @@ -823,11 +824,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let data = cond_get_data(this, cond_op)?; - let mutex_id = mutex_get_data(this, mutex_op)?.id; + let mutex_ref = mutex_get_data(this, mutex_op)?.mutex_ref; this.condvar_wait( data.id, - mutex_id, + mutex_ref, None, // no timeout Scalar::from_i32(0), Scalar::from_i32(0), // retval_timeout -- unused @@ -847,7 +848,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let data = cond_get_data(this, cond_op)?; - let mutex_id = mutex_get_data(this, mutex_op)?.id; + let mutex_ref = mutex_get_data(this, mutex_op)?.mutex_ref; // Extract the timeout. let duration = match this @@ -870,7 +871,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.condvar_wait( data.id, - mutex_id, + mutex_ref, Some((timeout_clock, TimeoutAnchor::Absolute, duration)), Scalar::from_i32(0), this.eval_libc("ETIMEDOUT"), // retval_timeout