Track kernel buffers per-process

This commit is contained in:
pjht 2024-08-16 20:03:00 -05:00
parent 75814f3589
commit 4d908f1335
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
2 changed files with 53 additions and 18 deletions

View File

@ -332,7 +332,7 @@ extern "C" fn syscall_handler() {
retval = 1; retval = 1;
} }
}); });
TASKING.record_buf_dealloc(buffer.len()); TASKING.record_curr_buf_dealloc(buffer.len());
} else { } else {
retval = 1; retval = 1;
} }
@ -420,6 +420,12 @@ extern "C" fn syscall_handler() {
SECOND_PORT.write_u32s(&[ SECOND_PORT.write_u32s(&[
total_len, // Total block length total_len, // Total block length
]); ]);
TASKING.record_curr_buf_dealloc(buffer.len());
#[expect(
clippy::unwrap_used,
reason = "The PID is known valid due to using it in message_queue_mut in the if-let condition"
)]
TASKING.record_buf_alloc(pid, buffer.len()).unwrap();
let buffer = Box::into_raw(buffer); let buffer = Box::into_raw(buffer);
#[expect( #[expect(
clippy::unwrap_used, clippy::unwrap_used,
@ -503,7 +509,7 @@ extern "C" fn syscall_handler() {
} }
15 => { 15 => {
if let Some(buf) = get_buffer(regs.rcx) { if let Some(buf) = get_buffer(regs.rcx) {
TASKING.record_buf_dealloc(buf.len()); TASKING.record_curr_buf_dealloc(buf.len());
} }
} }
16 => { 16 => {
@ -511,7 +517,7 @@ extern "C" fn syscall_handler() {
let rounded_size = size.next_multiple_of(4096); let rounded_size = size.next_multiple_of(4096);
KERNEL_SPACE.lock().alloc_force_user = true; KERNEL_SPACE.lock().alloc_force_user = true;
let mut buffer = Vec::with_capacity_in(rounded_size, &*KERNEL_SPACE); let mut buffer = Vec::with_capacity_in(rounded_size, &*KERNEL_SPACE);
TASKING.record_buf_alloc(rounded_size); TASKING.record_curr_buf_alloc(rounded_size);
buffer.resize(rounded_size, 0); buffer.resize(rounded_size, 0);
let buffer = buffer.into_boxed_slice(); let buffer = buffer.into_boxed_slice();
let buffer = Box::into_raw(buffer); let buffer = Box::into_raw(buffer);

View File

@ -101,6 +101,7 @@ struct Process {
data_buffers: Mutex<Slab<*mut [u8]>>, data_buffers: Mutex<Slab<*mut [u8]>>,
message_queue: Mutex<SegQueue<(usize, usize)>>, message_queue: Mutex<SegQueue<(usize, usize)>>,
sleeping: RwLock<Option<SleepReason>>, sleeping: RwLock<Option<SleepReason>>,
buf_allocated: AtomicUsize,
} }
unsafe impl Send for Process {} unsafe impl Send for Process {}
@ -114,7 +115,6 @@ pub static TASKING: Lazy<Tasking> = Lazy::new(|| Tasking {
ready_to_run: Mutex::new(VecDeque::new()), ready_to_run: Mutex::new(VecDeque::new()),
current_pid: RwLock::new(None), current_pid: RwLock::new(None),
freeable_kstacks: Mutex::new(Vec::new()), freeable_kstacks: Mutex::new(Vec::new()),
buf_allocated: AtomicUsize::new(0),
}); });
#[derive(Debug)] #[derive(Debug)]
@ -123,7 +123,6 @@ pub struct Tasking {
ready_to_run: Mutex<VecDeque<usize>>, ready_to_run: Mutex<VecDeque<usize>>,
current_pid: RwLock<Option<usize>>, current_pid: RwLock<Option<usize>>,
freeable_kstacks: Mutex<Vec<Box<[usize], &'static ASpaceMutex>>>, freeable_kstacks: Mutex<Vec<Box<[usize], &'static ASpaceMutex>>>,
buf_allocated: AtomicUsize,
} }
pub const KSTACK_SIZE: usize = 0x1_0000 / 8; pub const KSTACK_SIZE: usize = 0x1_0000 / 8;
@ -211,6 +210,7 @@ impl Tasking {
message_queue: Mutex::new(SegQueue::new()), message_queue: Mutex::new(SegQueue::new()),
sleeping: RwLock::new(None), sleeping: RwLock::new(None),
arguments: (user_arg_mem.cast(), arguments.len()), arguments: (user_arg_mem.cast(), arguments.len()),
buf_allocated: AtomicUsize::new(0),
}); });
self.ready_to_run.lock().push_back(pid); self.ready_to_run.lock().push_back(pid);
Ok(pid) Ok(pid)
@ -291,10 +291,13 @@ impl Tasking {
|| ACTIVE_SPACE.lock().get_bytes_allocated(), || ACTIVE_SPACE.lock().get_bytes_allocated(),
|space| space.get_bytes_allocated(), |space| space.get_bytes_allocated(),
); );
let buf_bytes_used = current_process.buf_allocated.load(Ordering::Relaxed);
println!( println!(
"[TASKING] PID {current_pid} exiting, used {} ({}), this is being leaked.", "[TASKING] PID {current_pid} exiting, used {} ({}) + {} ({}) of kernel buffers, this is being leaked.",
SizeFormatter::new(bytes_used, BINARY), SizeFormatter::new(bytes_used, BINARY),
bytes_used / 4096 bytes_used / 4096,
SizeFormatter::new(buf_bytes_used, BINARY),
buf_bytes_used / 4096,
); );
self.freeable_kstacks.lock().push(processes.remove(current_pid).kernel_stack); self.freeable_kstacks.lock().push(processes.remove(current_pid).kernel_stack);
} }
@ -392,32 +395,58 @@ impl Tasking {
self.processes.read()[self.current_pid.read().unwrap()].arguments self.processes.read()[self.current_pid.read().unwrap()].arguments
} }
pub fn record_buf_alloc(&self, size: usize) { pub fn record_curr_buf_alloc(&self, size: usize) {
self.buf_allocated.fetch_add(size, Ordering::Relaxed); #[warn(clippy::unwrap_used, reason = "FIXME")]
#[warn(clippy::indexing_slicing, reason = "FIXME(?)")]
self.processes.read()[self.current_pid.read().unwrap()]
.buf_allocated
.fetch_add(size, Ordering::Relaxed);
} }
pub fn record_buf_dealloc(&self, size: usize) { pub fn record_curr_buf_dealloc(&self, size: usize) {
self.buf_allocated.fetch_sub(size, Ordering::Relaxed); #[warn(clippy::unwrap_used, reason = "FIXME")]
#[warn(clippy::indexing_slicing, reason = "FIXME(?)")]
self.processes.read()[self.current_pid.read().unwrap()]
.buf_allocated
.fetch_sub(size, Ordering::Relaxed);
}
pub fn record_buf_alloc(&self, pid: usize, size: usize) -> Result<(), InvalidPid> {
self.processes
.read()
.get(pid)
.ok_or(InvalidPid)?
.buf_allocated
.fetch_add(size, Ordering::Relaxed);
Ok(())
}
pub fn record_buf_dealloc(&self, pid: usize, size: usize) -> Result<(), InvalidPid> {
self.processes
.read()
.get(pid)
.ok_or(InvalidPid)?
.buf_allocated
.fetch_sub(size, Ordering::Relaxed);
Ok(())
} }
pub fn print_stats(&self) { pub fn print_stats(&self) {
let mut total = let mut total =
KERNEL_SPACE.lock().get_bytes_allocated() + self.buf_allocated.load(Ordering::Relaxed); KERNEL_SPACE.lock().get_bytes_allocated();
println!( println!(
"[TASKING] Kernel misc used {}", "[TASKING] Kernel used {}",
SizeFormatter::new(KERNEL_SPACE.lock().get_bytes_allocated(), BINARY) SizeFormatter::new(KERNEL_SPACE.lock().get_bytes_allocated(), BINARY)
); );
println!(
"[TASKING] Kernel buffers used {}",
SizeFormatter::new(self.buf_allocated.load(Ordering::Relaxed), BINARY)
);
for (i, process) in self.processes.read().iter() { for (i, process) in self.processes.read().iter() {
let bytes_used = process.address_space.as_ref().map_or_else( let bytes_used = process.address_space.as_ref().map_or_else(
|| ACTIVE_SPACE.lock().get_bytes_allocated(), || ACTIVE_SPACE.lock().get_bytes_allocated(),
|space| space.get_bytes_allocated(), |space| space.get_bytes_allocated(),
); );
let buf_bytes_used = process.buf_allocated.load(Ordering::Relaxed);
total += bytes_used; total += bytes_used;
println!("[TASKING] PID {} used {}", i, SizeFormatter::new(bytes_used, BINARY)); total += buf_bytes_used;
println!("[TASKING] PID {} used {} + {} of kernel buffers", i, SizeFormatter::new(bytes_used, BINARY), SizeFormatter::new(buf_bytes_used, BINARY));
} }
println!("[TASKING] Total used {} ({})", SizeFormatter::new(total, BINARY), total / 4096); println!("[TASKING] Total used {} ({})", SizeFormatter::new(total, BINARY), total / 4096);
} }