From 7e620c574ea1e31fa729b181881c56c392e72ef8 Mon Sep 17 00:00:00 2001 From: pjht Date: Sun, 3 Nov 2024 11:04:47 -0600 Subject: [PATCH] Integrate with proc_man - report new processes and keep zombie PIDs --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/interrupts.rs | 107 +++++++++++++++++++++++++++++++++------------- src/tasking.rs | 47 ++++++++++++++++++-- 4 files changed, 128 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59c6299..ba46d04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,7 @@ dependencies = [ "tap", "tar-no-std", "uart_16550", + "unsigned-varint", "unwinding", "x86_64", ] @@ -391,6 +392,12 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" + [[package]] name = "unwinding" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index c07c795..f801226 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,4 @@ saturating_cast = "0.1.0" humansize = "2.1.3" cast = "0.3.0" az = "1.2.1" +unsigned-varint = "0.8.0" diff --git a/src/interrupts.rs b/src/interrupts.rs index 52222a3..c2cd42c 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -126,31 +126,45 @@ impl Drop for EoiGuard { } } -#[expect(clippy::needless_pass_by_value, reason = "Signature dictated by external crate")] -fn irq_handler(_stack_frame: InterruptStackFrame, index: u8, _error_code: Option) { - #[expect( - clippy::arithmetic_side_effects, - reason = "This function is only called for irqs, which are always above the base index." - )] - let irq_num = index - IRQ_BASE; - let eoi_guard = EoiGuard(index); - #[expect( - clippy::indexing_slicing, - reason = "This function is only called for 16 irqs, which are all valid indexes" - )] - if let Some(handler) = IRQ_HANDLERS.read()[usize(irq_num)] { - handler(irq_num, eoi_guard); - } else if let Some(handler_task) = IRQ_TASKS.read()[usize(irq_num)] { - let pid = handler_task; - let len: usize = 11; - let rounded_size = len.next_multiple_of(4096); - let mut buffer = Vec::with_capacity_in(rounded_size, &*ACTIVE_SPACE); - buffer.resize(rounded_size, 0); - let mut buffer = buffer.into_boxed_slice(); - buffer[0..8].copy_from_slice(&u64::MAX.to_le_bytes()); - buffer[8..10].copy_from_slice(&2u16.to_le_bytes()); - buffer[10] = irq_num; - assert!(len <= buffer.len()); +pub fn send_ipc_to(pid: usize, buffer: Box<[u8], &'static ASpaceMutex>, len: usize) { + //#[expect( + // clippy::unwrap_used, + // reason = "The min call guarantees that the value is in the range of a u32 before the cast" + //)] + //let trunc_len: u32 = usize::min(len, 4096).try_into().unwrap(); + //#[expect( + // clippy::arithmetic_side_effects, + // reason = "Can't underflow, as x % 4 < 4 no matter the x" + //)] + //let padding = if (trunc_len % 4) != 0 { 4 - (trunc_len % 4) } else { 0 }; + //#[expect( + // clippy::arithmetic_side_effects, + // reason = "Can't overflow, as padding is no more than 4 and trunc_len is no more than 4096." + //)] + //let padded_len = trunc_len + padding; + //#[expect( + // clippy::arithmetic_side_effects, + // reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX" + //)] + //let total_len = padded_len + 8 + (4 * 4); + //SECOND_PORT.write_u32s(&[ + // 0x3, // SPB type + // total_len, // Total block length + // len.saturating_cast::().saturating_add(8), // Packet length + //]); + //SECOND_PORT.write_bytes(&pid.to_ne_bytes()); + //#[expect( + // clippy::indexing_slicing, + // reason = "The truncated length is always <= the buffer's length" + //)] + //SECOND_PORT.write_bytes(&buffer[0..usize(trunc_len)]); + //for _ in 0..padding { + // SECOND_PORT.write_bytes(&[0]); + //} + //SECOND_PORT.write_u32s(&[ + // total_len, // Total block length + //]); + //assert!(len <= buffer.len()); if TASKING.message_queue_mut(pid, |_| ()).is_ok() { let buf_num_pages = buffer.len() / 4096; let buffer = Box::into_raw(buffer); @@ -188,14 +202,39 @@ fn irq_handler(_stack_frame: InterruptStackFrame, index: u8, _error_code: Option clippy::unwrap_used, reason = "The PID is known valid due to using it in message_queue_mut in the if-let condition" )] - #[expect( - clippy::unwrap_used, - reason = "The PID is known valid due to using it in message_queue_mut in the if-let condition" - )] TASKING.wake(pid, SleepReason::WaitingForIPC).unwrap(); } else { println!("irq 1 msg: Bad PID ({})", pid); } + +} + + +#[expect(clippy::needless_pass_by_value, reason = "Signature dictated by external crate")] +fn irq_handler(_stack_frame: InterruptStackFrame, index: u8, _error_code: Option) { + #[expect( + clippy::arithmetic_side_effects, + reason = "This function is only called for irqs, which are always above the base index." + )] + let irq_num = index - IRQ_BASE; + let eoi_guard = EoiGuard(index); + #[expect( + clippy::indexing_slicing, + reason = "This function is only called for 16 irqs, which are all valid indexes" + )] + if let Some(handler) = IRQ_HANDLERS.read()[usize(irq_num)] { + handler(irq_num, eoi_guard); + } else if let Some(handler_task) = IRQ_TASKS.read()[usize(irq_num)] { + let pid = handler_task; + let len: usize = 11; + let rounded_size = len.next_multiple_of(4096); + let mut buffer = Vec::with_capacity_in(rounded_size, &*ACTIVE_SPACE); + buffer.resize(rounded_size, 0); + let mut buffer = buffer.into_boxed_slice(); + buffer[0..8].copy_from_slice(&u64::MAX.to_le_bytes()); + buffer[8..10].copy_from_slice(&2u16.to_le_bytes()); + buffer[10] = irq_num; + send_ipc_to(pid, buffer, len); } } @@ -272,7 +311,7 @@ fn get_buffer(id: u64) -> Option> { }) } -static REGISTERD_PIDS: Lazy>> = Lazy::new(|| RwLock::new(HashMap::new())); +pub static REGISTERD_PIDS: Lazy>> = Lazy::new(|| RwLock::new(HashMap::new())); static INITRD_BUF: Lazy<&'static [u8]> = Lazy::new(|| { #[warn(clippy::expect_used, reason = "FIXME")] @@ -754,6 +793,14 @@ extern "C" fn syscall_handler() { retval = 0; } } + 25 => { + let pid = usize(regs.rcx); + if TASKING.clear_exited_pid(pid).is_err() { + retval = 1; + } else { + retval = 0; + } + } _ => (), }; unsafe { SYSCALL_REGS = regs }; diff --git a/src/tasking.rs b/src/tasking.rs index 30a95e3..5826b0d 100644 --- a/src/tasking.rs +++ b/src/tasking.rs @@ -1,6 +1,5 @@ use crate::{ - gdt, println, qemu_exit, - virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE}, + gdt, interrupts::{send_ipc_to, REGISTERD_PIDS}, println, qemu_exit, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE} }; use alloc::{ borrow::ToOwned, boxed::Box, collections::VecDeque, ffi::CString, string::ToString, vec::Vec, @@ -20,6 +19,7 @@ use x86_64::{ structures::paging::{Page, PageTableFlags}, VirtAddr, }; +use cast::{u64, usize}; #[naked] extern "C" fn switch_to_asm(current_stack: *mut *mut usize, next_stack: *mut usize) { @@ -86,6 +86,7 @@ extern "C" fn task_init() { pub enum SleepReason { WaitingForIPC, NewProcess, + Exited, } #[derive(Debug)] @@ -207,7 +208,33 @@ impl Tasking { sleeping: RwLock::new(Some(SleepReason::NewProcess)), arguments: (user_arg_mem.cast(), arguments.len()), }); - //self.ready_to_run.lock().push_back(pid); + if let Some(&proc_man_pid) = REGISTERD_PIDS.read().get(&3) { + let mut len: usize; + let rounded_size = 32usize.next_multiple_of(4096); + let mut buffer = Vec::with_capacity_in(rounded_size, &*ACTIVE_SPACE); + buffer.resize(rounded_size, 0); + let mut buffer = buffer.into_boxed_slice(); + buffer[0..8].copy_from_slice(&u64::MAX.to_le_bytes()); + buffer[8..10].copy_from_slice(&0u16.to_le_bytes()); + buffer[10] = 0; + buffer[11..19].copy_from_slice(&0u64.to_le_bytes()); + buffer[19..21].copy_from_slice(&8u16.to_le_bytes()); + buffer[21..23].copy_from_slice(&6u16.to_le_bytes()); + len = 23; + len += unsigned_varint::encode::u64(u64(pid), (&mut buffer[len..len+10]).try_into().unwrap()).len(); + if let Some(current_pid) = *(self.current_pid.read()) { + buffer[len] = 1; + len+=1; + len += unsigned_varint::encode::u64(u64(current_pid), (&mut buffer[len..len+10]).try_into().unwrap()).len(); + } else { + buffer[len] = 0; + len+=1; + } + send_ipc_to(usize(proc_man_pid), buffer, len); + } else { + println!("[TASKING] No process manager when creating PID {pid}"); + } + self.ready_to_run.lock().push_back(pid); Ok(pid) } @@ -298,7 +325,8 @@ impl Tasking { #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] let mut processes = self.processes.write(); if let Some(current_pid) = *self.current_pid.read() { - self.freeable_kstacks.lock().push(processes.remove(current_pid).kernel_stack); + //self.freeable_kstacks.lock().push(processes.remove(current_pid).kernel_stack); + *processes[current_pid].sleeping.write() = Some(SleepReason::Exited); } #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] let next_process = &mut processes[next_process_pid]; @@ -327,6 +355,17 @@ impl Tasking { } } + + pub fn clear_exited_pid(&self, pid: usize) -> Result<(), ()> { + let mut processes = self.processes.write(); + let process = processes.get(pid).ok_or(())?; + if *process.sleeping.read() != Some(SleepReason::Exited) { + return Err(()); + } + self.freeable_kstacks.lock().push(processes.remove(pid).kernel_stack); + Ok(()) + } + pub fn address_spaces_mut) -> T, T>(&self, func: F) -> T { let processes = self.processes.read(); #[warn(clippy::unwrap_used, reason = "FIXME")]