]> git.lizzy.rs Git - rust.git/commitdiff
refactor into private functions
authorDrMeepster <19316085+DrMeepster@users.noreply.github.com>
Fri, 4 Nov 2022 01:13:53 +0000 (18:13 -0700)
committerDrMeepster <19316085+DrMeepster@users.noreply.github.com>
Fri, 4 Nov 2022 01:13:53 +0000 (18:13 -0700)
src/tools/miri/src/concurrency/init_once.rs
src/tools/miri/src/shims/windows/sync.rs

index b1443662e2b7fdc7be6b8f336e224a336994c9da..eb42cdf80abbeb5de883a9dc009948fc5777f2df 100644 (file)
@@ -3,7 +3,7 @@
 
 use rustc_index::vec::Idx;
 
-use super::sync::EvalContextExtPriv;
+use super::sync::EvalContextExtPriv as _;
 use super::thread::MachineCallback;
 use super::vector_clock::VClock;
 use crate::*;
@@ -52,6 +52,43 @@ fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
     }
 }
 
+impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// Synchronize with the previous initialization attempt of an InitOnce.
+    #[inline]
+    fn init_once_observe_attempt(&mut self, id: InitOnceId) {
+        let this = self.eval_context_mut();
+        let current_thread = this.get_active_thread();
+
+        if let Some(data_race) = &this.machine.data_race {
+            data_race.validate_lock_acquire(
+                &this.machine.threads.sync.init_onces[id].data_race,
+                current_thread,
+            );
+        }
+    }
+
+    #[inline]
+    fn init_once_wake_waiter(
+        &mut self,
+        id: InitOnceId,
+        waiter: InitOnceWaiter<'mir, 'tcx>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let current_thread = this.get_active_thread();
+
+        this.unblock_thread(waiter.thread);
+
+        // Call callback, with the woken-up thread as `current`.
+        this.set_active_thread(waiter.thread);
+        this.init_once_observe_attempt(id);
+        waiter.callback.call(this)?;
+        this.set_active_thread(current_thread);
+
+        Ok(())
+    }
+}
+
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn init_once_get_or_create_id(
@@ -141,13 +178,7 @@ fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         // Wake up everyone.
         // need to take the queue to avoid having `this` be borrowed multiple times
         for waiter in std::mem::take(&mut init_once.waiters) {
-            this.unblock_thread(waiter.thread);
-
-            // Call callback, with the woken-up thread as `current`.
-            this.set_active_thread(waiter.thread);
-            this.init_once_acquire(id);
-            waiter.callback.call(this)?;
-            this.set_active_thread(current_thread);
+            this.init_once_wake_waiter(id, waiter)?;
         }
 
         Ok(())
@@ -171,13 +202,7 @@ fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
 
         // Wake up one waiting thread, so they can go ahead and try to init this.
         if let Some(waiter) = init_once.waiters.pop_front() {
-            this.unblock_thread(waiter.thread);
-
-            // Call callback, with the woken-up thread as `current`.
-            this.set_active_thread(waiter.thread);
-            this.init_once_acquire(id);
-            waiter.callback.call(this)?;
-            this.set_active_thread(current_thread);
+            this.init_once_wake_waiter(id, waiter)?;
         } else {
             // Nobody there to take this, so go back to 'uninit'
             init_once.status = InitOnceStatus::Uninitialized;
@@ -186,18 +211,18 @@ fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         Ok(())
     }
 
-    /// Synchronize with the previous completion or failure of an InitOnce.
-    /// This is required to prevent data races.
+    /// Synchronize with the previous completion of an InitOnce.
+    /// Must only be called after checking that it is complete.
     #[inline]
-    fn init_once_acquire(&mut self, id: InitOnceId) {
+    fn init_once_observe_completed(&mut self, id: InitOnceId) {
         let this = self.eval_context_mut();
-        let current_thread = this.get_active_thread();
 
-        if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_acquire(
-                &this.machine.threads.sync.init_onces[id].data_race,
-                current_thread,
-            );
-        }
+        assert_eq!(
+            this.init_once_status(id),
+            InitOnceStatus::Complete,
+            "observing the completion of incomplete init once"
+        );
+
+        this.init_once_observe_attempt(id);
     }
 }
index f8980e188b45b303efd1b447930b9ba8e2c90440..098804626f2f956f9e5f574fe64f675cdf18320c 100644 (file)
@@ -178,7 +178,7 @@ fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
                 )
             }
             InitOnceStatus::Complete => {
-                this.init_once_acquire(id);
+                this.init_once_observe_completed(id);
                 this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?;
             }
         }