Skip to content

Commit e607b36

Browse files
authored
Merge pull request #4411 from LorrensP-2158466/remove-leaky-syncobj
Remove leaky synchronisation objects.
2 parents 9044174 + 68b842c commit e607b36

File tree

8 files changed

+148
-184
lines changed

8 files changed

+148
-184
lines changed

src/concurrency/init_once.rs

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
use std::cell::RefCell;
12
use std::collections::VecDeque;
2-
3-
use rustc_index::Idx;
3+
use std::rc::Rc;
44

55
use super::thread::DynUnblockCallback;
66
use super::vector_clock::VClock;
77
use crate::*;
88

9-
super::sync::declare_id!(InitOnceId);
10-
119
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1210
/// The current status of a one time initialization.
1311
pub enum InitOnceStatus {
@@ -25,44 +23,70 @@ pub(super) struct InitOnce {
2523
clock: VClock,
2624
}
2725

28-
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
29-
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
26+
impl InitOnce {
3027
#[inline]
31-
fn init_once_status(&mut self, id: InitOnceId) -> InitOnceStatus {
32-
let this = self.eval_context_ref();
33-
this.machine.sync.init_onces[id].status
34-
}
35-
36-
/// Put the thread into the queue waiting for the initialization.
37-
#[inline]
38-
fn init_once_enqueue_and_block(&mut self, id: InitOnceId, callback: DynUnblockCallback<'tcx>) {
39-
let this = self.eval_context_mut();
40-
let thread = this.active_thread();
41-
let init_once = &mut this.machine.sync.init_onces[id];
42-
assert_ne!(init_once.status, InitOnceStatus::Complete, "queueing on complete init once");
43-
init_once.waiters.push_back(thread);
44-
this.block_thread(BlockReason::InitOnce(id), None, callback);
28+
pub fn status(&self) -> InitOnceStatus {
29+
self.status
4530
}
4631

4732
/// Begin initializing this InitOnce. Must only be called after checking that it is currently
4833
/// uninitialized.
4934
#[inline]
50-
fn init_once_begin(&mut self, id: InitOnceId) {
51-
let this = self.eval_context_mut();
52-
let init_once = &mut this.machine.sync.init_onces[id];
35+
pub fn begin(&mut self) {
5336
assert_eq!(
54-
init_once.status,
37+
self.status(),
5538
InitOnceStatus::Uninitialized,
5639
"beginning already begun or complete init once"
5740
);
58-
init_once.status = InitOnceStatus::Begun;
41+
self.status = InitOnceStatus::Begun;
5942
}
43+
}
6044

45+
#[derive(Default, Clone, Debug)]
46+
pub struct InitOnceRef(Rc<RefCell<InitOnce>>);
47+
48+
impl InitOnceRef {
49+
pub fn new() -> Self {
50+
Self(Default::default())
51+
}
52+
53+
pub fn status(&self) -> InitOnceStatus {
54+
self.0.borrow().status()
55+
}
56+
57+
pub fn begin(&self) {
58+
self.0.borrow_mut().begin();
59+
}
60+
}
61+
62+
impl VisitProvenance for InitOnceRef {
63+
// InitOnce contains no provenance.
64+
fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {}
65+
}
66+
67+
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
68+
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
69+
/// Put the thread into the queue waiting for the initialization.
6170
#[inline]
62-
fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
71+
fn init_once_enqueue_and_block(
72+
&mut self,
73+
init_once_ref: InitOnceRef,
74+
callback: DynUnblockCallback<'tcx>,
75+
) {
6376
let this = self.eval_context_mut();
64-
let init_once = &mut this.machine.sync.init_onces[id];
77+
let thread = this.active_thread();
78+
let mut init_once = init_once_ref.0.borrow_mut();
79+
assert_ne!(init_once.status, InitOnceStatus::Complete, "queueing on complete init once");
80+
81+
init_once.waiters.push_back(thread);
82+
this.block_thread(BlockReason::InitOnce, None, callback);
83+
}
6584

85+
#[inline]
86+
fn init_once_complete(&mut self, init_once_ref: &InitOnceRef) -> InterpResult<'tcx> {
87+
let this = self.eval_context_mut();
88+
89+
let mut init_once = init_once_ref.0.borrow_mut();
6690
assert_eq!(
6791
init_once.status,
6892
InitOnceStatus::Begun,
@@ -79,17 +103,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
79103

80104
// Wake up everyone.
81105
// need to take the queue to avoid having `this` be borrowed multiple times
82-
for waiter in std::mem::take(&mut init_once.waiters) {
83-
this.unblock_thread(waiter, BlockReason::InitOnce(id))?;
106+
let waiters = std::mem::take(&mut init_once.waiters);
107+
drop(init_once);
108+
for waiter in waiters {
109+
this.unblock_thread(waiter, BlockReason::InitOnce)?;
84110
}
85111

86112
interp_ok(())
87113
}
88114

89115
#[inline]
90-
fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
116+
fn init_once_fail(&mut self, init_once_ref: &InitOnceRef) -> InterpResult<'tcx> {
91117
let this = self.eval_context_mut();
92-
let init_once = &mut this.machine.sync.init_onces[id];
118+
let mut init_once = init_once_ref.0.borrow_mut();
93119
assert_eq!(
94120
init_once.status,
95121
InitOnceStatus::Begun,
@@ -106,7 +132,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
106132

107133
// Wake up one waiting thread, so they can go ahead and try to init this.
108134
if let Some(waiter) = init_once.waiters.pop_front() {
109-
this.unblock_thread(waiter, BlockReason::InitOnce(id))?;
135+
drop(init_once);
136+
this.unblock_thread(waiter, BlockReason::InitOnce)?;
110137
}
111138

112139
interp_ok(())
@@ -115,15 +142,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
115142
/// Synchronize with the previous completion of an InitOnce.
116143
/// Must only be called after checking that it is complete.
117144
#[inline]
118-
fn init_once_observe_completed(&mut self, id: InitOnceId) {
145+
fn init_once_observe_completed(&mut self, init_once_ref: &InitOnceRef) {
119146
let this = self.eval_context_mut();
147+
let init_once = init_once_ref.0.borrow();
120148

121149
assert_eq!(
122-
this.init_once_status(id),
150+
init_once.status,
123151
InitOnceStatus::Complete,
124152
"observing the completion of incomplete init once"
125153
);
126154

127-
this.acquire_clock(&this.machine.sync.init_onces[id].clock);
155+
this.acquire_clock(&init_once.clock);
128156
}
129157
}

0 commit comments

Comments
 (0)