fixed a deadlock

This commit is contained in:
2025-06-15 16:51:20 +01:00
parent aca73589de
commit 5d1ea86cdd
5 changed files with 49 additions and 29 deletions
+27 -17
View File
@@ -1,6 +1,6 @@
use std::{ use std::{
sync::{ sync::{
Arc, Mutex, Arc, Mutex, MutexGuard,
mpsc::{self, Receiver, Sender}, mpsc::{self, Receiver, Sender},
}, },
thread, thread,
@@ -15,27 +15,39 @@ use crate::{
}, },
}; };
pub fn run_emulator( pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: Processor) {
cmd_rx: &Receiver<Command>, println!("starting");
state_tx: &Sender<State>,
cpu: &Arc<Mutex<Processor>>,
) {
let mut running = Running::Paused; let mut running = Running::Paused;
let mut addr = 0u32; let mut addr = 0u32;
let size = 256; let size = 256;
// Send initial state. // Send initial state.
let Ok(mut cpu_lock) = cpu.lock() else { // let Ok(mut cpu_lock) = cpu.lock() else {
panic!("Failed to lock CPU.") // panic!("Failed to lock CPU.")
}; // };
let mut cpu_lock = cpu;
cpu_lock.get_stack(32);
println!("got stack");
cpu_lock.display();
println!("got display");
let memory_view = cpu_lock.memory.read_range(addr, size); let memory_view = cpu_lock.memory.read_range(addr, size);
let initial_state = state(cpu, running, 0, memory_view); println!("got view");
let initial_state = state(&mut cpu_lock, running, 0, memory_view);
println!("got state");
let _ = state_tx.send(initial_state); let _ = state_tx.send(initial_state);
println!("sent state");
let mut instruction_count = 0; let mut instruction_count = 0;
loop { loop {
println!("looping");
let cmd = if running == Running::Running { let cmd = if running == Running::Running {
match cmd_rx.try_recv() { match cmd_rx.try_recv() {
Ok(cmd) => Some(cmd), Ok(cmd) => Some(cmd),
@@ -50,6 +62,8 @@ pub fn run_emulator(
}; };
if let Some(cmd) = cmd { if let Some(cmd) = cmd {
println!("Received command: {:?}", cmd);
match cmd { match cmd {
Command::Start => { Command::Start => {
running = Running::Running; running = Running::Running;
@@ -95,7 +109,7 @@ pub fn run_emulator(
} }
let memory_view = cpu_lock.memory.read_range(addr, size); let memory_view = cpu_lock.memory.read_range(addr, size);
let state = state(cpu, running, instruction_count, memory_view); let state = state(&mut cpu_lock, running, instruction_count, memory_view);
let _ = state_tx.send(state); let _ = state_tx.send(state);
} }
@@ -129,7 +143,7 @@ pub fn run_emulator(
if update { if update {
let memory_view = cpu_lock.memory.read_range(addr, size); let memory_view = cpu_lock.memory.read_range(addr, size);
let state = state(cpu, running, instruction_count, memory_view); let state = state(&mut cpu_lock, running, instruction_count, memory_view);
let _ = state_tx.send(state); let _ = state_tx.send(state);
} }
} else { } else {
@@ -139,15 +153,11 @@ pub fn run_emulator(
} }
fn state( fn state(
cpu: &Arc<Mutex<Processor>>, cpu_lock: &mut Processor,
running: Running, running: Running,
instruction_count: usize, instruction_count: usize,
memory_view: Vec<u8>, memory_view: Vec<u8>,
) -> State { ) -> State {
let Ok(mut cpu_lock) = cpu.lock() else {
panic!("Could not lock CPU.")
};
State { State {
// TODO: Replace with actual register access from your CPU. // TODO: Replace with actual register access from your CPU.
reg_file: cpu_lock.registers, reg_file: cpu_lock.registers,
+8
View File
@@ -7,6 +7,14 @@ pub enum Running {
Halted, Halted,
} }
pub trait IODevice: Send + Sync {
fn read_byte(&mut self, addr: u32) -> u8;
fn write_byte(&mut self, addr: u32, value: u8);
fn read_range(&mut self, addr: u32, size: u32) -> Vec<u8>;
fn write_range(&mut self, addr: u32, value: Vec<u8>);
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Command { pub enum Command {
Start, Start,
Stop, Stop,
+11 -5
View File
@@ -1,27 +1,33 @@
use std::cmp::{max, min}; use std::{
cmp::{max, min},
sync::Arc,
};
use crate::{ use crate::{
common::instructions::{Instruction, Interrupt, Register, errors::InstructionDecodeError}, common::instructions::{Instruction, Interrupt, Register, errors::InstructionDecodeError},
emulator::system::{memory::MemoryUnit, model::RegFile}, emulator::system::{
memory::MemoryUnit,
model::{IODevice, RegFile},
},
}; };
pub struct Processor { pub struct Processor {
pub memory: Box<dyn MemoryUnit>, pub memory: Box<dyn MemoryUnit>,
pub registers: RegFile, pub registers: RegFile,
pub halted: bool, pub halted: bool,
// pub io_devices: Vec<Arc<dyn IODevice>>, pub io_devices: Vec<Arc<dyn IODevice>>,
} }
#[allow(clippy::needless_pass_by_ref_mut)] #[allow(clippy::needless_pass_by_ref_mut)]
impl Processor { impl Processor {
// io_devices: Vec<Arc<dyn IODevice>>
#[must_use] #[must_use]
pub fn new(memory: Box<dyn MemoryUnit>) -> Self { pub fn new(memory: Box<dyn MemoryUnit>, io_devices: Vec<Arc<dyn IODevice>>) -> Self {
Self { Self {
// io_devices, // io_devices,
memory, memory,
registers: RegFile::default(), registers: RegFile::default(),
halted: false, halted: false,
io_devices,
} }
} }
+1 -1
View File
@@ -9,7 +9,7 @@ use crate::{
fn create_test_processor() -> Processor { fn create_test_processor() -> Processor {
let memory = Box::new(MainStore::new()); let memory = Box::new(MainStore::new());
Processor::new(memory) Processor::new(memory, Vec::new())
} }
#[test] #[test]
+2 -6
View File
@@ -17,14 +17,10 @@ fn main() -> Result<(), eframe::Error> {
let (state_sender, state_receiver) = std::sync::mpsc::channel(); let (state_sender, state_receiver) = std::sync::mpsc::channel();
let mainstore = MainStore::new(); let mainstore = MainStore::new();
let processor = Processor::new(Box::new(mainstore)); let processor = Processor::new(Box::new(mainstore), vec![]);
thread::spawn(move || { thread::spawn(move || {
run_emulator( run_emulator(&cmd_receiver, &state_sender, processor);
&cmd_receiver,
&state_sender,
&Arc::new(Mutex::new(processor)),
);
}); });
// Create UI // Create UI