fix: use try_lock in data accessors to prevent component mutex deadlock
This commit is contained in:
parent
d1cc176cc7
commit
14060e15e5
1 changed files with 77 additions and 44 deletions
|
|
@ -700,24 +700,35 @@ impl ConfigurableSystem {
|
||||||
|
|
||||||
/// Get CPU register data from Intel 4004 CPU
|
/// Get CPU register data from Intel 4004 CPU
|
||||||
/// Returns: CpuRegisterData if Intel 4004 CPU is found, None otherwise
|
/// Returns: CpuRegisterData if Intel 4004 CPU is found, None otherwise
|
||||||
|
/// Uses try_lock() to avoid blocking when component is busy
|
||||||
pub fn get_cpu_register_data(&self) -> Option<CpuRegisterData> {
|
pub fn get_cpu_register_data(&self) -> Option<CpuRegisterData> {
|
||||||
// Look for Intel 4004 CPU components
|
// Look for Intel 4004 CPU components
|
||||||
for (_name, component) in &self.components {
|
for (_name, component) in &self.components {
|
||||||
if let Ok(comp) = component.lock() {
|
match component.try_lock() {
|
||||||
// Try to downcast to Intel4004
|
Ok(comp) => {
|
||||||
if let Some(cpu) = comp.as_any().downcast_ref::<Intel4004>() {
|
// Try to downcast to Intel4004
|
||||||
let mut index_registers = [0u8; 16];
|
if let Some(cpu) = comp.as_any().downcast_ref::<Intel4004>() {
|
||||||
for i in 0..16 {
|
let mut index_registers = [0u8; 16];
|
||||||
index_registers[i] = cpu.get_register(i as u8).unwrap_or(0);
|
for i in 0..16 {
|
||||||
}
|
index_registers[i] = cpu.get_register(i as u8).unwrap_or(0);
|
||||||
|
}
|
||||||
|
|
||||||
return Some(CpuRegisterData {
|
return Some(CpuRegisterData {
|
||||||
program_counter: cpu.get_program_counter(),
|
program_counter: cpu.get_program_counter(),
|
||||||
accumulator: cpu.get_accumulator(),
|
accumulator: cpu.get_accumulator(),
|
||||||
carry: cpu.get_carry(),
|
carry: cpu.get_carry(),
|
||||||
stack_pointer: cpu.get_stack_pointer(),
|
stack_pointer: cpu.get_stack_pointer(),
|
||||||
index_registers,
|
index_registers,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(std::sync::TryLockError::WouldBlock) => {
|
||||||
|
// Component is busy, continue to next component
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(std::sync::TryLockError::Poisoned(_)) => {
|
||||||
|
// Handle poisoned mutex - continue to next component
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -727,33 +738,44 @@ impl ConfigurableSystem {
|
||||||
/// Get RAM data from Intel 4002 RAM chips
|
/// Get RAM data from Intel 4002 RAM chips
|
||||||
/// Parameters: max_rows - Maximum number of rows to return per bank
|
/// Parameters: max_rows - Maximum number of rows to return per bank
|
||||||
/// Returns: Vector of (chip_name, banks) where each bank is a vector of nibbles
|
/// Returns: Vector of (chip_name, banks) where each bank is a vector of nibbles
|
||||||
|
/// Uses try_lock() to avoid blocking when component is busy
|
||||||
pub fn get_ram_data(&self, max_rows: usize) -> RamData {
|
pub fn get_ram_data(&self, max_rows: usize) -> RamData {
|
||||||
let mut ram_data = Vec::new();
|
let mut ram_data = Vec::new();
|
||||||
|
|
||||||
for (name, component) in &self.components {
|
for (name, component) in &self.components {
|
||||||
if let Ok(comp) = component.lock() {
|
match component.try_lock() {
|
||||||
// Try to downcast to Intel4002
|
Ok(comp) => {
|
||||||
if let Some(ram) = comp.as_any().downcast_ref::<Intel4002>() {
|
// Try to downcast to Intel4002
|
||||||
let mut banks = Vec::new();
|
if let Some(ram) = comp.as_any().downcast_ref::<Intel4002>() {
|
||||||
|
let mut banks = Vec::new();
|
||||||
|
|
||||||
// Intel 4002 has 4 banks of 16 4-bit words each (64 nibbles total per chip)
|
// Intel 4002 has 4 banks of 16 4-bit words each (64 nibbles total per chip)
|
||||||
// But actually it has 4 main memory registers, each with 16 4-bit characters
|
// But actually it has 4 main memory registers, each with 16 4-bit characters
|
||||||
// and 4 status characters = 4 x 20 = 80 nibbles
|
// and 4 status characters = 4 x 20 = 80 nibbles
|
||||||
for bank in 0..4 {
|
for bank in 0..4 {
|
||||||
let mut bank_data = Vec::new();
|
let mut bank_data = Vec::new();
|
||||||
// Read up to max_rows * 4 nibbles per bank
|
// Read up to max_rows * 4 nibbles per bank
|
||||||
// The read_ram_direct takes a single address parameter
|
// The read_ram_direct takes a single address parameter
|
||||||
for addr in 0..(max_rows * 4).min(20) {
|
for addr in 0..(max_rows * 4).min(20) {
|
||||||
// Calculate the combined address for this bank and offset
|
// Calculate the combined address for this bank and offset
|
||||||
let full_addr = (bank * 20 + addr) as u8;
|
let full_addr = (bank * 20 + addr) as u8;
|
||||||
// Use read_ram_direct to get the nibble at this address
|
// Use read_ram_direct to get the nibble at this address
|
||||||
let value = ram.read_ram_direct(full_addr).unwrap_or(0);
|
let value = ram.read_ram_direct(full_addr).unwrap_or(0);
|
||||||
bank_data.push(value);
|
bank_data.push(value);
|
||||||
|
}
|
||||||
|
banks.push(bank_data);
|
||||||
}
|
}
|
||||||
banks.push(bank_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
ram_data.push((name.clone(), banks));
|
ram_data.push((name.clone(), banks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(std::sync::TryLockError::WouldBlock) => {
|
||||||
|
// Component is busy, skip to next component
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(std::sync::TryLockError::Poisoned(_)) => {
|
||||||
|
// Handle poisoned mutex - skip to next component
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -764,22 +786,33 @@ impl ConfigurableSystem {
|
||||||
/// Get ROM data from Intel 4001 ROM chips
|
/// Get ROM data from Intel 4001 ROM chips
|
||||||
/// Parameters: max_rows - Maximum number of bytes to return per chip
|
/// Parameters: max_rows - Maximum number of bytes to return per chip
|
||||||
/// Returns: Vector of (chip_name, bytes)
|
/// Returns: Vector of (chip_name, bytes)
|
||||||
|
/// Uses try_lock() to avoid blocking when component is busy
|
||||||
pub fn get_rom_data(&self, max_rows: usize) -> RomData {
|
pub fn get_rom_data(&self, max_rows: usize) -> RomData {
|
||||||
let mut rom_data = Vec::new();
|
let mut rom_data = Vec::new();
|
||||||
|
|
||||||
for (name, component) in &self.components {
|
for (name, component) in &self.components {
|
||||||
if let Ok(comp) = component.lock() {
|
match component.try_lock() {
|
||||||
// Try to downcast to Intel4001
|
Ok(comp) => {
|
||||||
if let Some(rom) = comp.as_any().downcast_ref::<Intel4001>() {
|
// Try to downcast to Intel4001
|
||||||
let mut data = Vec::new();
|
if let Some(rom) = comp.as_any().downcast_ref::<Intel4001>() {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
|
||||||
// Intel 4001 has 256 bytes of ROM
|
// Intel 4001 has 256 bytes of ROM
|
||||||
for addr in 0..max_rows.min(256) {
|
for addr in 0..max_rows.min(256) {
|
||||||
let value = rom.read_rom(addr as u8).unwrap_or(0);
|
let value = rom.read_rom(addr as u8).unwrap_or(0);
|
||||||
data.push(value);
|
data.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_data.push((name.clone(), data));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
rom_data.push((name.clone(), data));
|
Err(std::sync::TryLockError::WouldBlock) => {
|
||||||
|
// Component is busy, skip to next component
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(std::sync::TryLockError::Poisoned(_)) => {
|
||||||
|
// Handle poisoned mutex - skip to next component
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue