]> git.lizzy.rs Git - rust.git/blobdiff - src/thread.rs
remove no longer needed imports
[rust.git] / src / thread.rs
index 3418e8c7d2bfdf9ce63522b418c86bbee05e689e..96131dba3ca6a0e0399e94515ff8425fe614876d 100644 (file)
@@ -2,7 +2,6 @@
 
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
-use std::convert::TryFrom;
 use std::num::TryFromIntError;
 use std::time::{Duration, Instant, SystemTime};
 
@@ -218,7 +217,7 @@ pub struct ThreadManager<'mir, 'tcx> {
     pub(crate) sync: SynchronizationState,
     /// A mapping from a thread-local static to an allocation id of a thread
     /// specific allocation.
-    thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), AllocId>>,
+    thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), Pointer<Tag>>>,
     /// A flag that indicates that we should change the active thread.
     yield_active_thread: bool,
     /// Callbacks that are called once the specified time passes.
@@ -247,18 +246,18 @@ fn default() -> Self {
 impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     /// Check if we have an allocation for the given thread local static for the
     /// active thread.
-    fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<AllocId> {
+    fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Tag>> {
         self.thread_local_alloc_ids.borrow().get(&(def_id, self.active_thread)).cloned()
     }
 
-    /// Set the allocation id as the allocation id of the given thread local
+    /// Set the pointer for the allocation of the given thread local
     /// static for the active thread.
     ///
     /// Panics if a thread local is initialized twice for the same thread.
-    fn set_thread_local_alloc_id(&self, def_id: DefId, new_alloc_id: AllocId) {
+    fn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Tag>) {
         self.thread_local_alloc_ids
             .borrow_mut()
-            .try_insert((def_id, self.active_thread), new_alloc_id)
+            .try_insert((def_id, self.active_thread), ptr)
             .unwrap();
     }
 
@@ -302,6 +301,11 @@ fn has_terminated(&self, thread_id: ThreadId) -> bool {
         self.threads[thread_id].state == ThreadState::Terminated
     }
 
+    /// Have all threads terminated?
+    fn have_all_terminated(&self) -> bool {
+        self.threads.iter().all(|thread| thread.state == ThreadState::Terminated)
+    }
+
     /// Enable the thread for execution. The thread must be terminated.
     fn enable_thread(&mut self, thread_id: ThreadId) {
         assert!(self.has_terminated(thread_id));
@@ -332,7 +336,7 @@ fn detach_thread(&mut self, id: ThreadId) -> InterpResult<'tcx> {
     fn join_thread(
         &mut self,
         joined_thread_id: ThreadId,
-        data_race: &Option<data_race::GlobalState>,
+        data_race: Option<&mut data_race::GlobalState>,
     ) -> InterpResult<'tcx> {
         if self.threads[joined_thread_id].join_status != ThreadJoinStatus::Joinable {
             throw_ub_format!("trying to join a detached or already joined thread");
@@ -435,8 +439,11 @@ fn get_ready_callback(&mut self) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx
     }
 
     /// Wakes up threads joining on the active one and deallocates thread-local statics.
-    /// The `AllocId` that can now be freed is returned.
-    fn thread_terminated(&mut self, data_race: &Option<data_race::GlobalState>) -> Vec<AllocId> {
+    /// The `AllocId` that can now be freed are returned.
+    fn thread_terminated(
+        &mut self,
+        mut data_race: Option<&mut data_race::GlobalState>,
+    ) -> Vec<Pointer<Tag>> {
         let mut free_tls_statics = Vec::new();
         {
             let mut thread_local_statics = self.thread_local_alloc_ids.borrow_mut();
@@ -452,14 +459,14 @@ fn thread_terminated(&mut self, data_race: &Option<data_race::GlobalState>) -> V
             });
         }
         // Set the thread into a terminated state in the data-race detector
-        if let Some(data_race) = data_race {
+        if let Some(ref mut data_race) = data_race {
             data_race.thread_terminated();
         }
         // Check if we need to unblock any threads.
         for (i, thread) in self.threads.iter_enumerated_mut() {
             if thread.state == ThreadState::BlockedOnJoin(self.active_thread) {
                 // The thread has terminated, mark happens-before edge to joining thread
-                if let Some(data_race) = data_race {
+                if let Some(ref mut data_race) = data_race {
                     data_race.thread_joined(i, self.active_thread);
                 }
                 trace!("unblocking {:?} because {:?} terminated", i, self.active_thread);
@@ -488,15 +495,7 @@ fn schedule(
         // If we get here again and the thread is *still* terminated, there are no more dtors to run.
         if self.threads[MAIN_THREAD].state == ThreadState::Terminated {
             // The main thread terminated; stop the program.
-            if self.threads.iter().any(|thread| thread.state != ThreadState::Terminated) {
-                // FIXME: This check should be either configurable or just emit
-                // a warning. For example, it seems normal for a program to
-                // terminate without waiting for its detached threads to
-                // terminate. However, this case is not trivial to support
-                // because we also probably do not want to consider the memory
-                // owned by these threads as leaked.
-                throw_unsup_format!("the main thread terminated without waiting for other threads");
-            }
+            // We do *not* run TLS dtors of remaining threads, which seems to match rustc behavior.
             return Ok(SchedulingAction::Stop);
         }
         // This thread and the program can keep going.
@@ -554,16 +553,16 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
     /// Get a thread-specific allocation id for the given thread-local static.
     /// If needed, allocate a new one.
-    fn get_or_create_thread_local_alloc_id(
+    fn get_or_create_thread_local_alloc(
         &mut self,
         def_id: DefId,
-    ) -> InterpResult<'tcx, AllocId> {
+    ) -> InterpResult<'tcx, Pointer<Tag>> {
         let this = self.eval_context_mut();
         let tcx = this.tcx;
-        if let Some(new_alloc_id) = this.machine.threads.get_thread_local_alloc_id(def_id) {
+        if let Some(old_alloc) = this.machine.threads.get_thread_local_alloc_id(def_id) {
             // We already have a thread-specific allocation id for this
             // thread-local static.
-            Ok(new_alloc_id)
+            Ok(old_alloc)
         } else {
             // We need to allocate a thread-specific allocation id for this
             // thread-local static.
@@ -573,10 +572,10 @@ fn get_or_create_thread_local_alloc_id(
             }
             let allocation = tcx.eval_static_initializer(def_id)?;
             // Create a fresh allocation with this content.
-            let new_alloc_id =
-                this.memory.allocate_with(allocation.clone(), MiriMemoryKind::Tls.into()).alloc_id;
-            this.machine.threads.set_thread_local_alloc_id(def_id, new_alloc_id);
-            Ok(new_alloc_id)
+            let new_alloc =
+                this.allocate_raw_ptr(allocation.inner().clone(), MiriMemoryKind::Tls.into());
+            this.machine.threads.set_thread_local_alloc(def_id, new_alloc);
+            Ok(new_alloc)
         }
     }
 
@@ -584,7 +583,7 @@ fn get_or_create_thread_local_alloc_id(
     fn create_thread(&mut self) -> ThreadId {
         let this = self.eval_context_mut();
         let id = this.machine.threads.create_thread();
-        if let Some(data_race) = &this.memory.extra.data_race {
+        if let Some(data_race) = &mut this.machine.data_race {
             data_race.thread_created(id);
         }
         id
@@ -599,15 +598,14 @@ fn detach_thread(&mut self, thread_id: ThreadId) -> InterpResult<'tcx> {
     #[inline]
     fn join_thread(&mut self, joined_thread_id: ThreadId) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let data_race = &this.memory.extra.data_race;
-        this.machine.threads.join_thread(joined_thread_id, data_race)?;
+        this.machine.threads.join_thread(joined_thread_id, this.machine.data_race.as_mut())?;
         Ok(())
     }
 
     #[inline]
     fn set_active_thread(&mut self, thread_id: ThreadId) -> ThreadId {
         let this = self.eval_context_mut();
-        if let Some(data_race) = &this.memory.extra.data_race {
+        if let Some(data_race) = &this.machine.data_race {
             data_race.thread_set_active(thread_id);
         }
         this.machine.threads.set_active_thread_id(thread_id)
@@ -643,6 +641,12 @@ fn has_terminated(&self, thread_id: ThreadId) -> bool {
         this.machine.threads.has_terminated(thread_id)
     }
 
+    #[inline]
+    fn have_all_terminated(&self) -> bool {
+        let this = self.eval_context_ref();
+        this.machine.threads.have_all_terminated()
+    }
+
     #[inline]
     fn enable_thread(&mut self, thread_id: ThreadId) {
         let this = self.eval_context_mut();
@@ -664,7 +668,7 @@ fn active_thread_stack_mut(&mut self) -> &mut Vec<Frame<'mir, 'tcx, Tag, FrameDa
     #[inline]
     fn set_active_thread_name(&mut self, new_thread_name: Vec<u8>) {
         let this = self.eval_context_mut();
-        if let Some(data_race) = &this.memory.extra.data_race {
+        if let Some(data_race) = &mut this.machine.data_race {
             if let Ok(string) = String::from_utf8(new_thread_name.clone()) {
                 data_race.thread_set_name(this.machine.threads.active_thread, string);
             }
@@ -748,7 +752,7 @@ fn run_timeout_callback(&mut self) -> InterpResult<'tcx> {
     #[inline]
     fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction> {
         let this = self.eval_context_mut();
-        let data_race = &this.memory.extra.data_race;
+        let data_race = &this.machine.data_race;
         this.machine.threads.schedule(data_race)
     }
 
@@ -759,10 +763,8 @@ fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction> {
     #[inline]
     fn thread_terminated(&mut self) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let data_race = &this.memory.extra.data_race;
-        for alloc_id in this.machine.threads.thread_terminated(data_race) {
-            let ptr = this.memory.global_base_pointer(alloc_id.into())?;
-            this.memory.deallocate(ptr, None, MiriMemoryKind::Tls.into())?;
+        for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) {
+            this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
         }
         Ok(())
     }