@@ -87,7 +87,7 @@ pub struct AdditionalMutexData {
87
87
pub kind : MutexKind ,
88
88
89
89
/// The address of the mutex.
90
- pub address : Pointer ,
90
+ pub address : u64 ,
91
91
}
92
92
93
93
/// The mutex state.
@@ -195,14 +195,15 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
195
195
/// Returns `None` if memory stores a non-zero invalid ID.
196
196
///
197
197
/// `get_objs` must return the `IndexVec` that stores all the objects of this type.
198
+ /// `create_obj` must create the new object if initialization is needed.
198
199
#[ inline]
199
- fn get_or_create_id < Id : SyncId + Idx , T : Default > (
200
+ fn get_or_create_id < Id : SyncId + Idx , T > (
200
201
& mut self ,
201
202
lock_op : & OpTy < ' tcx > ,
202
203
lock_layout : TyAndLayout < ' tcx > ,
203
204
offset : u64 ,
204
205
get_objs : impl for < ' a > Fn ( & ' a mut MiriInterpCx < ' tcx > ) -> & ' a mut IndexVec < Id , T > ,
205
- initialize_data : impl FnOnce ( ) -> InterpResult < ' tcx , Option < AdditionalMutexData > > ,
206
+ create_obj : impl for < ' a > FnOnce ( & ' a mut MiriInterpCx < ' tcx > ) -> InterpResult < ' tcx , T > ,
206
207
) -> InterpResult < ' tcx , Option < Id > > {
207
208
let this = self . eval_context_mut ( ) ;
208
209
let value_place =
@@ -224,10 +225,9 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
224
225
Ok ( if success. to_bool ( ) . expect ( "compare_exchange's second return value is a bool" ) {
225
226
// We set the in-memory ID to `next_index`, now also create this object in the machine
226
227
// state.
227
- let new_index = get_objs ( this) . push ( T :: default ( ) ) ;
228
+ let obj = create_obj ( this) ?;
229
+ let new_index = get_objs ( this) . push ( obj) ;
228
230
assert_eq ! ( next_index, new_index) ;
229
- let data = initialize_data ( ) ?;
230
- get_objs ( this) [ new_index] . data = data;
231
231
Some ( new_index)
232
232
} else {
233
233
let id = Id :: from_u32 ( old. to_u32 ( ) . expect ( "layout is u32" ) ) ;
@@ -240,6 +240,32 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
240
240
} )
241
241
}
242
242
243
+ /// Eagerly creates a Miri sync structure.
244
+ ///
245
+ /// `create_id` will store the index of the sync_structure in the memory pointed to by
246
+ /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized.
247
+ /// - `lock_op` must hold a pointer to the sync structure.
248
+ /// - `lock_layout` must be the memory layout of the sync structure.
249
+ /// - `offset` must be the offset inside the sync structure where its miri id will be stored.
250
+ /// - `get_objs` is described in `get_or_create_id`.
251
+ /// - `obj` must be the new sync object.
252
+ fn create_id < Id : SyncId + Idx , T > (
253
+ & mut self ,
254
+ lock_op : & OpTy < ' tcx > ,
255
+ lock_layout : TyAndLayout < ' tcx > ,
256
+ offset : u64 ,
257
+ get_objs : impl for < ' a > Fn ( & ' a mut MiriInterpCx < ' tcx > ) -> & ' a mut IndexVec < Id , T > ,
258
+ obj : T ,
259
+ ) -> InterpResult < ' tcx , Id > {
260
+ let this = self . eval_context_mut ( ) ;
261
+ let value_place =
262
+ this. deref_pointer_and_offset ( lock_op, offset, lock_layout, this. machine . layouts . u32 ) ?;
263
+
264
+ let new_index = get_objs ( this) . push ( obj) ;
265
+ this. write_scalar ( Scalar :: from_u32 ( new_index. to_u32 ( ) ) , & value_place) ?;
266
+ Ok ( new_index)
267
+ }
268
+
243
269
fn condvar_reacquire_mutex (
244
270
& mut self ,
245
271
mutex : MutexId ,
@@ -266,16 +292,44 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
266
292
// situations.
267
293
impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
268
294
pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
295
+ /// Eagerly create and initialize a new mutex.
296
+ fn mutex_create (
297
+ & mut self ,
298
+ lock_op : & OpTy < ' tcx > ,
299
+ lock_layout : TyAndLayout < ' tcx > ,
300
+ offset : u64 ,
301
+ data : Option < AdditionalMutexData > ,
302
+ ) -> InterpResult < ' tcx , MutexId > {
303
+ let this = self . eval_context_mut ( ) ;
304
+ this. create_id (
305
+ lock_op,
306
+ lock_layout,
307
+ offset,
308
+ |ecx| & mut ecx. machine . sync . mutexes ,
309
+ Mutex { data, ..Default :: default ( ) } ,
310
+ )
311
+ }
312
+
313
+ /// Lazily create a new mutex.
314
+ /// `initialize_data` must return any additional data that a user wants to associate with the mutex.
269
315
fn mutex_get_or_create_id (
270
316
& mut self ,
271
317
lock_op : & OpTy < ' tcx > ,
272
318
lock_layout : TyAndLayout < ' tcx > ,
273
319
offset : u64 ,
274
- initialize_data : impl FnOnce ( ) -> InterpResult < ' tcx , Option < AdditionalMutexData > > ,
320
+ initialize_data : impl for < ' a > FnOnce (
321
+ & ' a mut MiriInterpCx < ' tcx > ,
322
+ ) -> InterpResult < ' tcx , Option < AdditionalMutexData > > ,
275
323
) -> InterpResult < ' tcx , MutexId > {
276
324
let this = self . eval_context_mut ( ) ;
277
- this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . mutexes ) ?
278
- . ok_or_else ( || err_ub_format ! ( "mutex has invalid ID" ) . into ( ) , initialize_data)
325
+ this. get_or_create_id (
326
+ lock_op,
327
+ lock_layout,
328
+ offset,
329
+ |ecx| & mut ecx. machine . sync . mutexes ,
330
+ |ecx| initialize_data ( ecx) . map ( |data| Mutex { data, ..Default :: default ( ) } ) ,
331
+ ) ?
332
+ . ok_or_else ( || err_ub_format ! ( "mutex has invalid ID" ) . into ( ) )
279
333
}
280
334
281
335
/// Retrieve the additional data stored for a mutex.
@@ -294,8 +348,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
294
348
offset : u64 ,
295
349
) -> InterpResult < ' tcx , RwLockId > {
296
350
let this = self . eval_context_mut ( ) ;
297
- this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . rwlocks ) ?
298
- . ok_or_else ( || err_ub_format ! ( "rwlock has invalid ID" ) . into ( ) )
351
+ this. get_or_create_id (
352
+ lock_op,
353
+ lock_layout,
354
+ offset,
355
+ |ecx| & mut ecx. machine . sync . rwlocks ,
356
+ |_| Ok ( Default :: default ( ) ) ,
357
+ ) ?
358
+ . ok_or_else ( || err_ub_format ! ( "rwlock has invalid ID" ) . into ( ) )
299
359
}
300
360
301
361
fn condvar_get_or_create_id (
@@ -305,8 +365,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
305
365
offset : u64 ,
306
366
) -> InterpResult < ' tcx , CondvarId > {
307
367
let this = self . eval_context_mut ( ) ;
308
- this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . condvars ) ?
309
- . ok_or_else ( || err_ub_format ! ( "condvar has invalid ID" ) . into ( ) )
368
+ this. get_or_create_id (
369
+ lock_op,
370
+ lock_layout,
371
+ offset,
372
+ |ecx| & mut ecx. machine . sync . condvars ,
373
+ |_| Ok ( Default :: default ( ) ) ,
374
+ ) ?
375
+ . ok_or_else ( || err_ub_format ! ( "condvar has invalid ID" ) . into ( ) )
310
376
}
311
377
312
378
#[ inline]
0 commit comments