evmar / retrowin32

windows emulator
https://evmar.github.io/retrowin32/
Apache License 2.0
582 stars 26 forks source link

implement ExitThread #56

Closed LinusU closed 1 month ago

evmar commented 2 months ago

BTW, if you run exe/rust/build.sh it builds a "threads.exe" program that can exercise some of this. https://github.com/evmar/retrowin32/blob/main/exe/rust/README.md

I just added some build setup docs on how to build this: https://github.com/evmar/retrowin32/blob/main/doc/build_setup.md

Not sure it's worth it for you, just FYI in case it helps

LinusU commented 2 months ago

I've added a new Free state, and was going to implement cpu reuse in new_cpu but not sure exactly how to proceed 🤔

diff --git a/x86/src/x86.rs b/x86/src/x86.rs
index 222969de..cfd8f386 100644
--- a/x86/src/x86.rs
+++ b/x86/src/x86.rs
@@ -69,6 +69,14 @@ impl CPU {
         self.state = CPUState::Error(msg);
     }

+    pub fn reset(&mut self) {
+        self.regs = Registers::default();
+        self.flags = Flags::empty();
+        self.fpu = FPU::default();
+        self.state = Default::default();
+        self.futures.clear();
+    }
+
     // /// Check whether reading a T from mem[addr] would cause OOB, and crash() if so.
     // fn check_oob<T>(&mut self, addr: u32) -> bool {
     //     if addr < NULL_POINTER_REGION_SIZE {
@@ -210,6 +218,13 @@ impl X86 {
     }

     pub fn new_cpu(&mut self) -> &mut CPU {
+        for i in 0..self.cpus.len() {
+            if self.cpus[i].state == CPUState::Free {
+                self.cpus[i].reset();
+                return &mut *self.cpus[i];
+            }
+        }
+
         self.cpus.push(Box::pin(CPU::new()));
         self.cpus.last_mut().unwrap()
     }

I started doing something like this, but I realized that I'm not too well versed in what parts should be reset. In particular, with the code I have, it seems like it might be better to just swap_remove the cpu instead of keeping it around as free? 🤔

evmar commented 2 months ago

Oh yeah, swap_remove makes sense to me! I wonder if there's some way you can swap_remove the current CPU such that we don't even need the ::Free state, but I think it's probably hard for a CPU to tear itself down when the code is deep within some call stack involving it...

evmar commented 2 months ago

FYI I dropped CPUStatus::Exit here https://github.com/evmar/retrowin32/commit/c1735a7dba8374dacc04d448ccd6a73dce1832ec

LinusU commented 1 month ago

(rebased on latest main, not made any more progress)

evmar commented 1 month ago

This looks good, I merged it with another commit on top! We can refine the cleanup bits later, I don't imagine there are too many threads starting/exiting in the programs we care about yet. :)