about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2022-09-26 21:48:18 -0400
committerRalf Jung <post@ralfj.de>2022-10-04 15:32:10 +0200
commit1c6a6244c10173f0ae8e4e675e613de74f359484 (patch)
treeb085d1f20aa5a82edad6d8f11175a47bff2fcfb2
parenta8f8106cec59550322e46e33a79ada673c2f13f6 (diff)
downloadrust-1c6a6244c10173f0ae8e4e675e613de74f359484.tar.gz
rust-1c6a6244c10173f0ae8e4e675e613de74f359484.zip
Please help, where is this lifetime bound coming from
-rw-r--r--src/tools/miri/src/concurrency/thread.rs16
-rw-r--r--src/tools/miri/src/shims/time.rs26
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs38
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs50
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()]);