diff options
| author | Ben Kimock <kimockb@gmail.com> | 2022-09-26 21:48:18 -0400 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-10-04 15:32:10 +0200 |
| commit | 1c6a6244c10173f0ae8e4e675e613de74f359484 (patch) | |
| tree | b085d1f20aa5a82edad6d8f11175a47bff2fcfb2 | |
| parent | a8f8106cec59550322e46e33a79ada673c2f13f6 (diff) | |
| download | rust-1c6a6244c10173f0ae8e4e675e613de74f359484.tar.gz rust-1c6a6244c10173f0ae8e4e675e613de74f359484.zip | |
Please help, where is this lifetime bound coming from
| -rw-r--r-- | src/tools/miri/src/concurrency/thread.rs | 16 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/time.rs | 26 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/unix/linux/sync.rs | 38 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/unix/sync.rs | 50 |
4 files changed, 90 insertions, 40 deletions
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 01ae4320f3b..3c5a6786bd1 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -32,9 +32,9 @@ pub enum SchedulingAction { /// Timeout callbacks can be created by synchronization primitives to tell the /// scheduler that they should be called once some period of time passes. -type TimeoutCallback<'mir, 'tcx> = Box< - dyn FnOnce(&mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx, ->; +pub trait TimeoutCallback<'mir, 'tcx>: VisitMachineValues + 'tcx { + fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; +} /// A thread identifier. #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -252,7 +252,7 @@ struct TimeoutCallbackInfo<'mir, 'tcx> { /// The callback should be called no earlier than this time. call_time: Time, /// The called function. - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box<dyn TimeoutCallback<'mir, 'tcx>>, } impl<'mir, 'tcx> std::fmt::Debug for TimeoutCallbackInfo<'mir, 'tcx> { @@ -542,7 +542,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box<dyn TimeoutCallback<'mir, 'tcx>>, ) { self.timeout_callbacks .try_insert(thread, TimeoutCallbackInfo { call_time, callback }) @@ -558,7 +558,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { fn get_ready_callback( &mut self, clock: &Clock, - ) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx>)> { + ) -> Option<(ThreadId, Box<dyn TimeoutCallback<'mir, 'tcx>>)> { // We iterate over all threads in the order of their indices because // this allows us to have a deterministic scheduler. for thread in self.threads.indices() { @@ -931,7 +931,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box<dyn TimeoutCallback<'mir, 'tcx>>, ) { let this = self.eval_context_mut(); if !this.machine.communicate() && matches!(call_time, Time::RealTime(..)) { @@ -970,7 +970,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // 2. Make the scheduler the only place that can change the active // thread. let old_thread = this.set_active_thread(thread); - callback(this)?; + callback.call(this)?; this.set_active_thread(old_thread); Ok(()) } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 24fe5245393..43792024e2c 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -1,5 +1,6 @@ use std::time::{Duration, SystemTime}; +use crate::concurrency::thread::TimeoutCallback; use crate::*; /// 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> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(Callback { active_thread }), ); Ok(0) @@ -244,12 +242,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(Callback { active_thread }), ); Ok(()) } } + +struct Callback { + active_thread: ThreadId, +} + +impl VisitMachineValues for Callback { + fn visit_machine_values(&self, _visit: &mut ProvenanceVisitor) {} +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + ecx.unblock_thread(self.active_thread); + Ok(()) + } +} diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 5a6ce28d25c..784fa12d18a 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -1,4 +1,4 @@ -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{Time, TimeoutCallback}; use crate::*; use rustc_target::abi::{Align, Size}; use std::time::SystemTime; @@ -193,14 +193,7 @@ pub fn futex<'tcx>( this.register_timeout_callback( thread, timeout_time, - Box::new(move |this| { - this.unblock_thread(thread); - this.futex_remove_waiter(addr_usize, thread); - let etimedout = this.eval_libc("ETIMEDOUT")?; - this.set_last_error(etimedout)?; - this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?; - Ok(()) - }), + Box::new(Callback { thread, addr_usize, dest }), ); } } else { @@ -259,3 +252,30 @@ pub fn futex<'tcx>( Ok(()) } + +struct Callback<'tcx> { + thread: ThreadId, + addr_usize: u64, + dest: PlaceTy<'tcx, Provenance>, +} + +impl<'tcx> VisitMachineValues for Callback<'tcx> { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + let Callback { thread: _, addr_usize: _, dest } = self; + if let Place::Ptr(place) = **dest { + visit.visit(place); + } + } +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + this.unblock_thread(self.thread); + this.futex_remove_waiter(self.addr_usize, self.thread); + let etimedout = this.eval_libc("ETIMEDOUT")?; + this.set_last_error(etimedout)?; + this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; + + Ok(()) + } +} diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 2e972a27ffe..cdb3cdc4b9a 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -3,7 +3,7 @@ use std::time::SystemTime; use rustc_hir::LangItem; use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty}; -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{Time, TimeoutCallback}; use crate::*; // 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> { this.register_timeout_callback( active_thread, timeout_time, - Box::new(move |ecx| { - // We are not waiting for the condvar any more, wait for the - // mutex instead. - reacquire_cond_mutex(ecx, active_thread, mutex_id)?; - - // Remove the thread from the conditional variable. - ecx.condvar_remove_waiter(id, active_thread); - - // Set the return value: we timed out. - let etimedout = ecx.eval_libc("ETIMEDOUT")?; - ecx.write_scalar(etimedout, &dest)?; - - Ok(()) - }), + Box::new(Callback { active_thread, mutex_id, id, dest }), ); Ok(()) @@ -898,6 +885,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } +struct Callback<'tcx> { + active_thread: ThreadId, + mutex_id: MutexId, + id: CondvarId, + dest: PlaceTy<'tcx, Provenance>, +} + +impl<'tcx> VisitMachineValues for Callback<'tcx> { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; + if let Place::Ptr(place) = **dest { + visit.visit(place); + } + } +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + // We are not waiting for the condvar any more, wait for the + // mutex instead. + reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?; + + // Remove the thread from the conditional variable. + ecx.condvar_remove_waiter(self.id, self.active_thread); + + // Set the return value: we timed out. + let etimedout = ecx.eval_libc("ETIMEDOUT")?; + ecx.write_scalar(etimedout, &self.dest)?; + + Ok(()) + } +} + fn layout_of_maybe_uninit<'tcx>(tcx: TyCtxtAt<'tcx>, param: Ty<'tcx>) -> TyAndLayout<'tcx> { let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); let ty = tcx.bound_type_of(def_id).subst(*tcx, &[param.into()]); |
