Skip to content

Commit 1c6a624

Browse files
saethlinRalfJung
authored andcommitted
Please help, where is this lifetime bound coming from
1 parent a8f8106 commit 1c6a624

File tree

4 files changed

+90
-40
lines changed

4 files changed

+90
-40
lines changed

src/tools/miri/src/concurrency/thread.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ pub enum SchedulingAction {
3232

3333
/// Timeout callbacks can be created by synchronization primitives to tell the
3434
/// scheduler that they should be called once some period of time passes.
35-
type TimeoutCallback<'mir, 'tcx> = Box<
36-
dyn FnOnce(&mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx,
37-
>;
35+
pub trait TimeoutCallback<'mir, 'tcx>: VisitMachineValues + 'tcx {
36+
fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>;
37+
}
3838

3939
/// A thread identifier.
4040
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
@@ -252,7 +252,7 @@ struct TimeoutCallbackInfo<'mir, 'tcx> {
252252
/// The callback should be called no earlier than this time.
253253
call_time: Time,
254254
/// The called function.
255-
callback: TimeoutCallback<'mir, 'tcx>,
255+
callback: Box<dyn TimeoutCallback<'mir, 'tcx>>,
256256
}
257257

258258
impl<'mir, 'tcx> std::fmt::Debug for TimeoutCallbackInfo<'mir, 'tcx> {
@@ -542,7 +542,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
542542
&mut self,
543543
thread: ThreadId,
544544
call_time: Time,
545-
callback: TimeoutCallback<'mir, 'tcx>,
545+
callback: Box<dyn TimeoutCallback<'mir, 'tcx>>,
546546
) {
547547
self.timeout_callbacks
548548
.try_insert(thread, TimeoutCallbackInfo { call_time, callback })
@@ -558,7 +558,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
558558
fn get_ready_callback(
559559
&mut self,
560560
clock: &Clock,
561-
) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx>)> {
561+
) -> Option<(ThreadId, Box<dyn TimeoutCallback<'mir, 'tcx>>)> {
562562
// We iterate over all threads in the order of their indices because
563563
// this allows us to have a deterministic scheduler.
564564
for thread in self.threads.indices() {
@@ -931,7 +931,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
931931
&mut self,
932932
thread: ThreadId,
933933
call_time: Time,
934-
callback: TimeoutCallback<'mir, 'tcx>,
934+
callback: Box<dyn TimeoutCallback<'mir, 'tcx>>,
935935
) {
936936
let this = self.eval_context_mut();
937937
if !this.machine.communicate() && matches!(call_time, Time::RealTime(..)) {
@@ -970,7 +970,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
970970
// 2. Make the scheduler the only place that can change the active
971971
// thread.
972972
let old_thread = this.set_active_thread(thread);
973-
callback(this)?;
973+
callback.call(this)?;
974974
this.set_active_thread(old_thread);
975975
Ok(())
976976
}

src/tools/miri/src/shims/time.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::time::{Duration, SystemTime};
22

3+
use crate::concurrency::thread::TimeoutCallback;
34
use crate::*;
45

56
/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
@@ -218,10 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
218219
this.register_timeout_callback(
219220
active_thread,
220221
Time::Monotonic(timeout_time),
221-
Box::new(move |ecx| {
222-
ecx.unblock_thread(active_thread);
223-
Ok(())
224-
}),
222+
Box::new(Callback { active_thread }),
225223
);
226224

227225
Ok(0)
@@ -244,12 +242,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
244242
this.register_timeout_callback(
245243
active_thread,
246244
Time::Monotonic(timeout_time),
247-
Box::new(move |ecx| {
248-
ecx.unblock_thread(active_thread);
249-
Ok(())
250-
}),
245+
Box::new(Callback { active_thread }),
251246
);
252247

253248
Ok(())
254249
}
255250
}
251+
252+
struct Callback {
253+
active_thread: ThreadId,
254+
}
255+
256+
impl VisitMachineValues for Callback {
257+
fn visit_machine_values(&self, _visit: &mut ProvenanceVisitor) {}
258+
}
259+
260+
impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback {
261+
fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
262+
ecx.unblock_thread(self.active_thread);
263+
Ok(())
264+
}
265+
}

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

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::concurrency::thread::Time;
1+
use crate::concurrency::thread::{Time, TimeoutCallback};
22
use crate::*;
33
use rustc_target::abi::{Align, Size};
44
use std::time::SystemTime;
@@ -193,14 +193,7 @@ pub fn futex<'tcx>(
193193
this.register_timeout_callback(
194194
thread,
195195
timeout_time,
196-
Box::new(move |this| {
197-
this.unblock_thread(thread);
198-
this.futex_remove_waiter(addr_usize, thread);
199-
let etimedout = this.eval_libc("ETIMEDOUT")?;
200-
this.set_last_error(etimedout)?;
201-
this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?;
202-
Ok(())
203-
}),
196+
Box::new(Callback { thread, addr_usize, dest }),
204197
);
205198
}
206199
} else {
@@ -259,3 +252,30 @@ pub fn futex<'tcx>(
259252

260253
Ok(())
261254
}
255+
256+
struct Callback<'tcx> {
257+
thread: ThreadId,
258+
addr_usize: u64,
259+
dest: PlaceTy<'tcx, Provenance>,
260+
}
261+
262+
impl<'tcx> VisitMachineValues for Callback<'tcx> {
263+
fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) {
264+
let Callback { thread: _, addr_usize: _, dest } = self;
265+
if let Place::Ptr(place) = **dest {
266+
visit.visit(place);
267+
}
268+
}
269+
}
270+
271+
impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> {
272+
fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
273+
this.unblock_thread(self.thread);
274+
this.futex_remove_waiter(self.addr_usize, self.thread);
275+
let etimedout = this.eval_libc("ETIMEDOUT")?;
276+
this.set_last_error(etimedout)?;
277+
this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?;
278+
279+
Ok(())
280+
}
281+
}

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

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::time::SystemTime;
33
use rustc_hir::LangItem;
44
use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty};
55

6-
use crate::concurrency::thread::Time;
6+
use crate::concurrency::thread::{Time, TimeoutCallback};
77
use crate::*;
88

99
// pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform.
@@ -856,20 +856,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
856856
this.register_timeout_callback(
857857
active_thread,
858858
timeout_time,
859-
Box::new(move |ecx| {
860-
// We are not waiting for the condvar any more, wait for the
861-
// mutex instead.
862-
reacquire_cond_mutex(ecx, active_thread, mutex_id)?;
863-
864-
// Remove the thread from the conditional variable.
865-
ecx.condvar_remove_waiter(id, active_thread);
866-
867-
// Set the return value: we timed out.
868-
let etimedout = ecx.eval_libc("ETIMEDOUT")?;
869-
ecx.write_scalar(etimedout, &dest)?;
870-
871-
Ok(())
872-
}),
859+
Box::new(Callback { active_thread, mutex_id, id, dest }),
873860
);
874861

875862
Ok(())
@@ -898,6 +885,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
898885
}
899886
}
900887

888+
struct Callback<'tcx> {
889+
active_thread: ThreadId,
890+
mutex_id: MutexId,
891+
id: CondvarId,
892+
dest: PlaceTy<'tcx, Provenance>,
893+
}
894+
895+
impl<'tcx> VisitMachineValues for Callback<'tcx> {
896+
fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) {
897+
let Callback { active_thread: _, mutex_id: _, id: _, dest } = self;
898+
if let Place::Ptr(place) = **dest {
899+
visit.visit(place);
900+
}
901+
}
902+
}
903+
904+
impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> {
905+
fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
906+
// We are not waiting for the condvar any more, wait for the
907+
// mutex instead.
908+
reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?;
909+
910+
// Remove the thread from the conditional variable.
911+
ecx.condvar_remove_waiter(self.id, self.active_thread);
912+
913+
// Set the return value: we timed out.
914+
let etimedout = ecx.eval_libc("ETIMEDOUT")?;
915+
ecx.write_scalar(etimedout, &self.dest)?;
916+
917+
Ok(())
918+
}
919+
}
920+
901921
fn layout_of_maybe_uninit<'tcx>(tcx: TyCtxtAt<'tcx>, param: Ty<'tcx>) -> TyAndLayout<'tcx> {
902922
let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None);
903923
let ty = tcx.bound_type_of(def_id).subst(*tcx, &[param.into()]);

0 commit comments

Comments
 (0)