Skip to content

Commit 0225309

Browse files
committed
Auto merge of rust-lang#3874 - RalfJung:sync, r=RalfJung
a bit of refactoring in "sync" - Use `Box<dyn Any>` to keep the "extra data" local to the module implementing the primitive - Pass around places, not pointers Cc `@Mandragorian` -- sorry I couldn't resist and did the `Any` thing ;)
2 parents 0aa3fd4 + 218057c commit 0225309

File tree

6 files changed

+125
-158
lines changed

6 files changed

+125
-158
lines changed

src/tools/miri/src/concurrency/init_once.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::collections::VecDeque;
22

33
use rustc_index::Idx;
4-
use rustc_middle::ty::layout::TyAndLayout;
54

65
use super::sync::EvalContextExtPriv as _;
76
use super::vector_clock::VClock;
@@ -30,14 +29,12 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
3029
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
3130
fn init_once_get_or_create_id(
3231
&mut self,
33-
lock_op: &OpTy<'tcx>,
34-
lock_layout: TyAndLayout<'tcx>,
32+
lock: &MPlaceTy<'tcx>,
3533
offset: u64,
3634
) -> InterpResult<'tcx, InitOnceId> {
3735
let this = self.eval_context_mut();
3836
this.get_or_create_id(
39-
lock_op,
40-
lock_layout,
37+
lock,
4138
offset,
4239
|ecx| &mut ecx.machine.sync.init_onces,
4340
|_| Ok(Default::default()),

src/tools/miri/src/concurrency/sync.rs

+29-65
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
use std::any::Any;
12
use std::collections::{hash_map::Entry, VecDeque};
23
use std::ops::Not;
34
use std::time::Duration;
45

56
use rustc_data_structures::fx::FxHashMap;
67
use rustc_index::{Idx, IndexVec};
7-
use rustc_middle::ty::layout::TyAndLayout;
8+
use rustc_target::abi::Size;
89

910
use super::init_once::InitOnce;
1011
use super::vector_clock::VClock;
@@ -66,27 +67,6 @@ pub(super) use declare_id;
6667

6768
declare_id!(MutexId);
6869

69-
/// The mutex kind.
70-
#[derive(Debug, Clone, Copy)]
71-
#[non_exhaustive]
72-
pub enum MutexKind {
73-
Invalid,
74-
Normal,
75-
Default,
76-
Recursive,
77-
ErrorCheck,
78-
}
79-
80-
#[derive(Debug)]
81-
/// Additional data that may be used by shim implementations.
82-
pub struct AdditionalMutexData {
83-
/// The mutex kind, used by some mutex implementations like pthreads mutexes.
84-
pub kind: MutexKind,
85-
86-
/// The address of the mutex.
87-
pub address: u64,
88-
}
89-
9070
/// The mutex state.
9171
#[derive(Default, Debug)]
9272
struct Mutex {
@@ -100,18 +80,11 @@ struct Mutex {
10080
clock: VClock,
10181

10282
/// Additional data that can be set by shim implementations.
103-
data: Option<AdditionalMutexData>,
83+
data: Option<Box<dyn Any>>,
10484
}
10585

10686
declare_id!(RwLockId);
10787

108-
#[derive(Debug)]
109-
/// Additional data that may be used by shim implementations.
110-
pub struct AdditionalRwLockData {
111-
/// The address of the rwlock.
112-
pub address: u64,
113-
}
114-
11588
/// The read-write lock state.
11689
#[derive(Default, Debug)]
11790
struct RwLock {
@@ -146,7 +119,7 @@ struct RwLock {
146119
clock_current_readers: VClock,
147120

148121
/// Additional data that can be set by shim implementations.
149-
data: Option<AdditionalRwLockData>,
122+
data: Option<Box<dyn Any>>,
150123
}
151124

152125
declare_id!(CondvarId);
@@ -206,21 +179,21 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
206179
#[inline]
207180
fn get_or_create_id<Id: SyncId + Idx, T>(
208181
&mut self,
209-
lock_op: &OpTy<'tcx>,
210-
lock_layout: TyAndLayout<'tcx>,
182+
lock: &MPlaceTy<'tcx>,
211183
offset: u64,
212184
get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
213185
create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>,
214186
) -> InterpResult<'tcx, Option<Id>> {
215187
let this = self.eval_context_mut();
216-
let value_place =
217-
this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?;
188+
let offset = Size::from_bytes(offset);
189+
assert!(lock.layout.size >= offset + this.machine.layouts.u32.size);
190+
let id_place = lock.offset(offset, this.machine.layouts.u32, this)?;
218191
let next_index = get_objs(this).next_index();
219192

220193
// Since we are lazy, this update has to be atomic.
221194
let (old, success) = this
222195
.atomic_compare_exchange_scalar(
223-
&value_place,
196+
&id_place,
224197
&ImmTy::from_uint(0u32, this.machine.layouts.u32),
225198
Scalar::from_u32(next_index.to_u32()),
226199
AtomicRwOrd::Relaxed, // deliberately *no* synchronization
@@ -258,18 +231,18 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
258231
/// - `obj` must be the new sync object.
259232
fn create_id<Id: SyncId + Idx, T>(
260233
&mut self,
261-
lock_op: &OpTy<'tcx>,
262-
lock_layout: TyAndLayout<'tcx>,
234+
lock: &MPlaceTy<'tcx>,
263235
offset: u64,
264236
get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
265237
obj: T,
266238
) -> InterpResult<'tcx, Id> {
267239
let this = self.eval_context_mut();
268-
let value_place =
269-
this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?;
240+
let offset = Size::from_bytes(offset);
241+
assert!(lock.layout.size >= offset + this.machine.layouts.u32.size);
242+
let id_place = lock.offset(offset, this.machine.layouts.u32, this)?;
270243

271244
let new_index = get_objs(this).push(obj);
272-
this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?;
245+
this.write_scalar(Scalar::from_u32(new_index.to_u32()), &id_place)?;
273246
Ok(new_index)
274247
}
275248

@@ -302,15 +275,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
302275
/// Eagerly create and initialize a new mutex.
303276
fn mutex_create(
304277
&mut self,
305-
lock_op: &OpTy<'tcx>,
306-
lock_layout: TyAndLayout<'tcx>,
278+
lock: &MPlaceTy<'tcx>,
307279
offset: u64,
308-
data: Option<AdditionalMutexData>,
280+
data: Option<Box<dyn Any>>,
309281
) -> InterpResult<'tcx, MutexId> {
310282
let this = self.eval_context_mut();
311283
this.create_id(
312-
lock_op,
313-
lock_layout,
284+
lock,
314285
offset,
315286
|ecx| &mut ecx.machine.sync.mutexes,
316287
Mutex { data, ..Default::default() },
@@ -321,17 +292,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
321292
/// `initialize_data` must return any additional data that a user wants to associate with the mutex.
322293
fn mutex_get_or_create_id(
323294
&mut self,
324-
lock_op: &OpTy<'tcx>,
325-
lock_layout: TyAndLayout<'tcx>,
295+
lock: &MPlaceTy<'tcx>,
326296
offset: u64,
327297
initialize_data: impl for<'a> FnOnce(
328298
&'a mut MiriInterpCx<'tcx>,
329-
) -> InterpResult<'tcx, Option<AdditionalMutexData>>,
299+
) -> InterpResult<'tcx, Option<Box<dyn Any>>>,
330300
) -> InterpResult<'tcx, MutexId> {
331301
let this = self.eval_context_mut();
332302
this.get_or_create_id(
333-
lock_op,
334-
lock_layout,
303+
lock,
335304
offset,
336305
|ecx| &mut ecx.machine.sync.mutexes,
337306
|ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }),
@@ -340,28 +309,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
340309
}
341310

342311
/// Retrieve the additional data stored for a mutex.
343-
fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData>
312+
fn mutex_get_data<'a, T: 'static>(&'a mut self, id: MutexId) -> Option<&'a T>
344313
where
345314
'tcx: 'a,
346315
{
347316
let this = self.eval_context_ref();
348-
this.machine.sync.mutexes[id].data.as_ref()
317+
this.machine.sync.mutexes[id].data.as_deref().and_then(|p| p.downcast_ref::<T>())
349318
}
350319

351320
fn rwlock_get_or_create_id(
352321
&mut self,
353-
lock_op: &OpTy<'tcx>,
354-
lock_layout: TyAndLayout<'tcx>,
322+
lock: &MPlaceTy<'tcx>,
355323
offset: u64,
356324
initialize_data: impl for<'a> FnOnce(
357325
&'a mut MiriInterpCx<'tcx>,
358-
)
359-
-> InterpResult<'tcx, Option<AdditionalRwLockData>>,
326+
) -> InterpResult<'tcx, Option<Box<dyn Any>>>,
360327
) -> InterpResult<'tcx, RwLockId> {
361328
let this = self.eval_context_mut();
362329
this.get_or_create_id(
363-
lock_op,
364-
lock_layout,
330+
lock,
365331
offset,
366332
|ecx| &mut ecx.machine.sync.rwlocks,
367333
|ecx| initialize_data(ecx).map(|data| RwLock { data, ..Default::default() }),
@@ -370,24 +336,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
370336
}
371337

372338
/// Retrieve the additional data stored for a rwlock.
373-
fn rwlock_get_data<'a>(&'a mut self, id: RwLockId) -> Option<&'a AdditionalRwLockData>
339+
fn rwlock_get_data<'a, T: 'static>(&'a mut self, id: RwLockId) -> Option<&'a T>
374340
where
375341
'tcx: 'a,
376342
{
377343
let this = self.eval_context_ref();
378-
this.machine.sync.rwlocks[id].data.as_ref()
344+
this.machine.sync.rwlocks[id].data.as_deref().and_then(|p| p.downcast_ref::<T>())
379345
}
380346

381347
fn condvar_get_or_create_id(
382348
&mut self,
383-
lock_op: &OpTy<'tcx>,
384-
lock_layout: TyAndLayout<'tcx>,
349+
lock: &MPlaceTy<'tcx>,
385350
offset: u64,
386351
) -> InterpResult<'tcx, CondvarId> {
387352
let this = self.eval_context_mut();
388353
this.get_or_create_id(
389-
lock_op,
390-
lock_layout,
354+
lock,
391355
offset,
392356
|ecx| &mut ecx.machine.sync.condvars,
393357
|_| Ok(Default::default()),

src/tools/miri/src/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,7 @@ pub use crate::concurrency::{
133133
cpu_affinity::MAX_CPUS,
134134
data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _},
135135
init_once::{EvalContextExt as _, InitOnceId},
136-
sync::{
137-
AdditionalMutexData, AdditionalRwLockData, CondvarId, EvalContextExt as _, MutexId,
138-
MutexKind, RwLockId, SynchronizationObjects,
139-
},
136+
sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects},
140137
thread::{
141138
BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager,
142139
TimeoutAnchor, TimeoutClock, UnblockCallback,

src/tools/miri/src/shims/unix/macos/sync.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ use crate::*;
1414

1515
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
1616
trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
17-
fn os_unfair_lock_getid(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> {
17+
fn os_unfair_lock_getid(&mut self, lock_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> {
1818
let this = self.eval_context_mut();
19+
let lock = this.deref_pointer(lock_ptr)?;
1920
// os_unfair_lock holds a 32-bit value, is initialized with zero and
2021
// must be assumed to be opaque. Therefore, we can just store our
2122
// internal mutex ID in the structure without anyone noticing.
22-
this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None))
23+
this.mutex_get_or_create_id(&lock, 0, |_| Ok(None))
2324
}
2425
}
2526

0 commit comments

Comments
 (0)