Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a5db2c3

Browse files
committed
Refactor to hide *_next_id functions
1 parent 1a7f6d5 commit a5db2c3

File tree

3 files changed

+133
-89
lines changed

3 files changed

+133
-89
lines changed

src/shims/posix/sync.rs

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,27 @@ fn mutex_get_or_create_id<'mir, 'tcx: 'mir>(
113113
mutex_op: &OpTy<'tcx, Tag>,
114114
) -> InterpResult<'tcx, MutexId> {
115115
let value_place = ecx.offset_and_layout_to_place(mutex_op, 4, ecx.machine.layouts.u32)?;
116-
let (old, success) = ecx
117-
.atomic_compare_exchange_scalar(
118-
&value_place,
119-
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
120-
ecx.mutex_next_id().to_u32_scalar().into(),
121-
AtomicRwOp::Relaxed,
122-
AtomicReadOp::Relaxed,
123-
false,
124-
)?
125-
.to_scalar_pair()?;
126-
127-
if success.to_bool().expect("compare_exchange's second return value is a bool") {
128-
let id = ecx.mutex_create();
129-
Ok(id)
130-
} else {
131-
Ok(MutexId::from_u32(old.to_u32().expect("layout is u32")))
132-
}
116+
117+
ecx.mutex_get_or_create(|ecx, next_id| {
118+
let (old, success) = ecx
119+
.atomic_compare_exchange_scalar(
120+
&value_place,
121+
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
122+
next_id.to_u32_scalar().into(),
123+
AtomicRwOp::Relaxed,
124+
AtomicReadOp::Relaxed,
125+
false,
126+
)?
127+
.to_scalar_pair()
128+
.expect("compare_exchange returns a scalar pair");
129+
130+
Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
131+
// Caller of the closure needs to allocate next_id
132+
None
133+
} else {
134+
Some(MutexId::from_u32(old.to_u32().expect("layout is u32")))
135+
})
136+
})
133137
}
134138

135139
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@@ -165,23 +169,27 @@ fn rwlock_get_or_create_id<'mir, 'tcx: 'mir>(
165169
rwlock_op: &OpTy<'tcx, Tag>,
166170
) -> InterpResult<'tcx, RwLockId> {
167171
let value_place = ecx.offset_and_layout_to_place(rwlock_op, 4, ecx.machine.layouts.u32)?;
168-
let (old, success) = ecx
169-
.atomic_compare_exchange_scalar(
170-
&value_place,
171-
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
172-
ecx.rwlock_next_id().to_u32_scalar().into(),
173-
AtomicRwOp::Relaxed,
174-
AtomicReadOp::Relaxed,
175-
false,
176-
)?
177-
.to_scalar_pair()?;
178-
179-
if success.to_bool().expect("compare_exchange's second return value is a bool") {
180-
let id = ecx.rwlock_create();
181-
Ok(id)
182-
} else {
183-
Ok(RwLockId::from_u32(old.to_u32().expect("layout is u32")))
184-
}
172+
173+
ecx.rwlock_get_or_create(|ecx, next_id| {
174+
let (old, success) = ecx
175+
.atomic_compare_exchange_scalar(
176+
&value_place,
177+
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
178+
next_id.to_u32_scalar().into(),
179+
AtomicRwOp::Relaxed,
180+
AtomicReadOp::Relaxed,
181+
false,
182+
)?
183+
.to_scalar_pair()
184+
.expect("compare_exchange returns a scalar pair");
185+
186+
Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
187+
// Caller of the closure needs to allocate next_id
188+
None
189+
} else {
190+
Some(RwLockId::from_u32(old.to_u32().expect("layout is u32")))
191+
})
192+
})
185193
}
186194

187195
// pthread_condattr_t
@@ -246,23 +254,26 @@ fn cond_get_or_create_id<'mir, 'tcx: 'mir>(
246254
) -> InterpResult<'tcx, CondvarId> {
247255
let value_place = ecx.offset_and_layout_to_place(cond_op, 4, ecx.machine.layouts.u32)?;
248256

249-
let (old, success) = ecx
250-
.atomic_compare_exchange_scalar(
251-
&value_place,
252-
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
253-
ecx.condvar_next_id().to_u32_scalar().into(),
254-
AtomicRwOp::Relaxed,
255-
AtomicReadOp::Relaxed,
256-
false,
257-
)?
258-
.to_scalar_pair()?;
259-
260-
if success.to_bool().expect("compare_exchange's second return value is a bool") {
261-
let id = ecx.condvar_create();
262-
Ok(id)
263-
} else {
264-
Ok(CondvarId::from_u32(old.to_u32().expect("layout is u32")))
265-
}
257+
ecx.condvar_get_or_create(|ecx, next_id| {
258+
let (old, success) = ecx
259+
.atomic_compare_exchange_scalar(
260+
&value_place,
261+
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
262+
next_id.to_u32_scalar().into(),
263+
AtomicRwOp::Relaxed,
264+
AtomicReadOp::Relaxed,
265+
false,
266+
)?
267+
.to_scalar_pair()
268+
.expect("compare_exchange returns a scalar pair");
269+
270+
Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
271+
// Caller of the closure needs to allocate next_id
272+
None
273+
} else {
274+
Some(CondvarId::from_u32(old.to_u32().expect("layout is u32")))
275+
})
276+
})
266277
}
267278

268279
fn cond_get_clock_id<'mir, 'tcx: 'mir>(

src/shims/windows/sync.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,26 @@ fn srwlock_get_or_create_id<'mir, 'tcx: 'mir>(
99
) -> InterpResult<'tcx, RwLockId> {
1010
let value_place = ecx.offset_and_layout_to_place(lock_op, 0, ecx.machine.layouts.u32)?;
1111

12-
let (old, success) = ecx
13-
.atomic_compare_exchange_scalar(
14-
&value_place,
15-
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
16-
ecx.rwlock_next_id().to_u32_scalar().into(),
17-
AtomicRwOp::AcqRel,
18-
AtomicReadOp::Acquire,
19-
false,
20-
)?
21-
.to_scalar_pair()?;
22-
23-
if success.to_bool().expect("compare_exchange's second return value is a bool") {
24-
let id = ecx.rwlock_create();
25-
Ok(id)
26-
} else {
27-
Ok(RwLockId::from_u32(old.to_u32().expect("layout is u32")))
28-
}
12+
ecx.rwlock_get_or_create(|ecx, next_id| {
13+
let (old, success) = ecx
14+
.atomic_compare_exchange_scalar(
15+
&value_place,
16+
&ImmTy::from_uint(0u32, ecx.machine.layouts.u32),
17+
next_id.to_u32_scalar().into(),
18+
AtomicRwOp::Relaxed,
19+
AtomicReadOp::Relaxed,
20+
false,
21+
)?
22+
.to_scalar_pair()
23+
.expect("compare_exchange returns a scalar pair");
24+
25+
Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
26+
// Caller of the closure needs to allocate next_id
27+
None
28+
} else {
29+
Some(RwLockId::from_u32(old.to_u32().expect("layout is u32")))
30+
})
31+
})
2932
}
3033

3134
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

src/sync.rs

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,28 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
208208
// situations.
209209
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
210210
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
211-
#[inline]
212-
/// Peek the id of the next mutex
213-
fn mutex_next_id(&self) -> MutexId {
214-
let this = self.eval_context_ref();
215-
this.machine.threads.sync.mutexes.next_index()
216-
}
217-
218211
#[inline]
219212
/// Create state for a new mutex.
220213
fn mutex_create(&mut self) -> MutexId {
221214
let this = self.eval_context_mut();
222215
this.machine.threads.sync.mutexes.push(Default::default())
223216
}
224217

218+
#[inline]
219+
/// Provides the closure with the next MutexId. Creates that mutex if the closure returns None,
220+
/// otherwise returns the value from the closure
221+
fn mutex_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, MutexId>
222+
where
223+
F: FnOnce(&mut MiriEvalContext<'mir, 'tcx>, MutexId) -> InterpResult<'tcx, Option<MutexId>>,
224+
{
225+
let this = self.eval_context_mut();
226+
if let Some(old) = existing(this, this.machine.threads.sync.mutexes.next_index())? {
227+
Ok(old)
228+
} else {
229+
Ok(self.mutex_create())
230+
}
231+
}
232+
225233
#[inline]
226234
/// Get the id of the thread that currently owns this lock.
227235
fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId {
@@ -297,20 +305,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
297305
this.block_thread(thread);
298306
}
299307

300-
#[inline]
301-
/// Peek the id of the next read write lock
302-
fn rwlock_next_id(&self) -> RwLockId {
303-
let this = self.eval_context_ref();
304-
this.machine.threads.sync.rwlocks.next_index()
305-
}
306-
307308
#[inline]
308309
/// Create state for a new read write lock.
309310
fn rwlock_create(&mut self) -> RwLockId {
310311
let this = self.eval_context_mut();
311312
this.machine.threads.sync.rwlocks.push(Default::default())
312313
}
313314

315+
#[inline]
316+
/// Provides the closure with the next RwLockId. Creates that RwLock if the closure returns None,
317+
/// otherwise returns the value from the closure
318+
fn rwlock_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, RwLockId>
319+
where
320+
F: FnOnce(
321+
&mut MiriEvalContext<'mir, 'tcx>,
322+
RwLockId,
323+
) -> InterpResult<'tcx, Option<RwLockId>>,
324+
{
325+
let this = self.eval_context_mut();
326+
if let Some(old) = existing(this, this.machine.threads.sync.rwlocks.next_index())? {
327+
Ok(old)
328+
} else {
329+
Ok(self.rwlock_create())
330+
}
331+
}
332+
314333
#[inline]
315334
/// Check if locked.
316335
fn rwlock_is_locked(&self, id: RwLockId) -> bool {
@@ -452,20 +471,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
452471
this.block_thread(writer);
453472
}
454473

455-
#[inline]
456-
/// Peek the id of the next Condvar
457-
fn condvar_next_id(&self) -> CondvarId {
458-
let this = self.eval_context_ref();
459-
this.machine.threads.sync.condvars.next_index()
460-
}
461-
462474
#[inline]
463475
/// Create state for a new conditional variable.
464476
fn condvar_create(&mut self) -> CondvarId {
465477
let this = self.eval_context_mut();
466478
this.machine.threads.sync.condvars.push(Default::default())
467479
}
468480

481+
#[inline]
482+
/// Provides the closure with the next CondvarId. Creates that Condvar if the closure returns None,
483+
/// otherwise returns the value from the closure
484+
fn condvar_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, CondvarId>
485+
where
486+
F: FnOnce(
487+
&mut MiriEvalContext<'mir, 'tcx>,
488+
CondvarId,
489+
) -> InterpResult<'tcx, Option<CondvarId>>,
490+
{
491+
let this = self.eval_context_mut();
492+
if let Some(old) = existing(this, this.machine.threads.sync.condvars.next_index())? {
493+
Ok(old)
494+
} else {
495+
Ok(self.condvar_create())
496+
}
497+
}
498+
469499
#[inline]
470500
/// Is the conditional variable awaited?
471501
fn condvar_is_awaited(&mut self, id: CondvarId) -> bool {

0 commit comments

Comments
 (0)