Add suuport for sleeping processes and a syscall to sleep waiting for IPC
This commit is contained in:
parent
8bbc165e58
commit
1376aa5f44
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bootinfo::BOOTINFO, dbg, print, println, virtual_memory::{ASpaceMutex, AddressSpace, ACTIVE_SPACE, KERNEL_SPACE}, TASKING
|
bootinfo::BOOTINFO, dbg, print, println, tasking::SleepReason, virtual_memory::{ASpaceMutex, AddressSpace, ACTIVE_SPACE, KERNEL_SPACE}, TASKING
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
use core::{arch::asm, ptr::{addr_of, slice_from_raw_parts_mut}, slice, str};
|
use core::{arch::asm, ptr::{addr_of, slice_from_raw_parts_mut}, slice, str};
|
||||||
@ -312,16 +312,20 @@ extern "C" fn syscall_handler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
11 => {
|
11 => {
|
||||||
|
let pid = regs.rcx as usize;
|
||||||
if let Some(buffer) = get_buffer(regs.rdx) {
|
if let Some(buffer) = get_buffer(regs.rdx) {
|
||||||
assert!(regs.rsi as usize <= buffer.len());
|
assert!(regs.rsi as usize <= buffer.len());
|
||||||
let mut tasking = TASKING.lock();
|
let mut tasking = TASKING.lock();
|
||||||
if let Some(_queue) = tasking.message_queue_mut(regs.rcx as usize) {
|
if let Some(_queue) = tasking.message_queue_mut(pid) {
|
||||||
let len = regs.rsi as usize;
|
let len = regs.rsi as usize;
|
||||||
let buffer = Box::into_raw(buffer);
|
let buffer = Box::into_raw(buffer);
|
||||||
let new_buffer_key =
|
let new_buffer_key =
|
||||||
tasking.proc_data_buffers_mut(regs.rcx as usize).insert(buffer);
|
tasking.proc_data_buffers_mut(pid).insert(buffer);
|
||||||
let queue = tasking.message_queue_mut(regs.rcx as usize).unwrap();
|
let queue = tasking.message_queue_mut(pid).unwrap();
|
||||||
queue.push((new_buffer_key, len));
|
queue.push((new_buffer_key, len));
|
||||||
|
if tasking.proc_sleeping(pid) == Some(SleepReason::WaitingForIPC) {
|
||||||
|
tasking.wake(pid);
|
||||||
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
} else {
|
} else {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
@ -380,9 +384,16 @@ extern "C" fn syscall_handler() {
|
|||||||
let space = tasking.address_spaces_mut().get_mut((regs.rcx - 1) as usize).unwrap();
|
let space = tasking.address_spaces_mut().get_mut((regs.rcx - 1) as usize).unwrap();
|
||||||
space.run(|| unsafe { slice::from_raw_parts_mut(regs.rdx as *mut u8, regs.rsi as usize).fill(0) });
|
space.run(|| unsafe { slice::from_raw_parts_mut(regs.rdx as *mut u8, regs.rsi as usize).fill(0) });
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
},
|
||||||
|
18 => {
|
||||||
|
let mut tasking = TASKING.lock();
|
||||||
|
if tasking.current_message_queue_mut().is_empty() {
|
||||||
|
tasking.sleep(SleepReason::WaitingForIPC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
unsafe { SYSCALL_REGS = regs };
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"mov rbx, [rip+SYSCALL_REGS+8]",
|
"mov rbx, [rip+SYSCALL_REGS+8]",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
gdt, println, qemu_exit,
|
dbg, gdt, println, qemu_exit, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, KERNEL_SPACE}
|
||||||
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, KERNEL_SPACE},
|
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
use core::{arch::asm, ptr::addr_of};
|
use core::{arch::asm, ptr::addr_of};
|
||||||
@ -77,6 +76,11 @@ extern "C" fn task_force_unlock() {
|
|||||||
interrupts::enable();
|
interrupts::enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum SleepReason {
|
||||||
|
WaitingForIPC,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Process {
|
struct Process {
|
||||||
kernel_stack: Box<[usize], &'static ASpaceMutex>,
|
kernel_stack: Box<[usize], &'static ASpaceMutex>,
|
||||||
@ -86,6 +90,7 @@ struct Process {
|
|||||||
address_spaces: Slab<AddressSpace>,
|
address_spaces: Slab<AddressSpace>,
|
||||||
data_buffers: Slab<*mut [u8]>,
|
data_buffers: Slab<*mut [u8]>,
|
||||||
message_queue: SegQueue<(usize, usize)>,
|
message_queue: SegQueue<(usize, usize)>,
|
||||||
|
sleeping: Option<SleepReason>
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Process {}
|
unsafe impl Send for Process {}
|
||||||
@ -129,6 +134,7 @@ impl Tasking {
|
|||||||
address_spaces: Slab::new(),
|
address_spaces: Slab::new(),
|
||||||
data_buffers: Slab::new(),
|
data_buffers: Slab::new(),
|
||||||
message_queue: SegQueue::new(),
|
message_queue: SegQueue::new(),
|
||||||
|
sleeping: None,
|
||||||
});
|
});
|
||||||
self.ready_to_run.push(pid);
|
self.ready_to_run.push(pid);
|
||||||
Ok(pid)
|
Ok(pid)
|
||||||
@ -149,10 +155,14 @@ impl Tasking {
|
|||||||
self.processes[current_process].address_space = Some(current_address_space);
|
self.processes[current_process].address_space = Some(current_address_space);
|
||||||
let next_process = &self.processes[next_process_pid];
|
let next_process = &self.processes[next_process_pid];
|
||||||
gdt::set_tss_stack(next_process.kernel_esp_top);
|
gdt::set_tss_stack(next_process.kernel_esp_top);
|
||||||
|
if self.processes[current_process].sleeping.is_none() {
|
||||||
self.ready_to_run.push(current_process);
|
self.ready_to_run.push(current_process);
|
||||||
|
}
|
||||||
let kernel_esp = next_process.kernel_esp;
|
let kernel_esp = next_process.kernel_esp;
|
||||||
let previous_process = self.current_process.replace(next_process_pid).unwrap();
|
let previous_process = self.current_process.replace(next_process_pid).unwrap();
|
||||||
switch_to_asm(&mut (self.processes[previous_process].kernel_esp), kernel_esp);
|
switch_to_asm(&mut (self.processes[previous_process].kernel_esp), kernel_esp);
|
||||||
|
} else if self.processes[current_process].sleeping.is_some() {
|
||||||
|
qemu_exit::exit_qemu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +187,7 @@ impl Tasking {
|
|||||||
switch_to_asm_exit(kernel_esp);
|
switch_to_asm_exit(kernel_esp);
|
||||||
unreachable!()
|
unreachable!()
|
||||||
} else {
|
} else {
|
||||||
println!("Last process exited, exiting QEMU");
|
println!("Last non-sleeping process exited, exiting QEMU");
|
||||||
qemu_exit::exit_qemu();
|
qemu_exit::exit_qemu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,4 +211,20 @@ impl Tasking {
|
|||||||
pub fn message_queue_mut(&mut self, pid: usize) -> Option<&mut SegQueue<(usize, usize)>> {
|
pub fn message_queue_mut(&mut self, pid: usize) -> Option<&mut SegQueue<(usize, usize)>> {
|
||||||
Some(&mut self.processes.get_mut(pid)?.message_queue)
|
Some(&mut self.processes.get_mut(pid)?.message_queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn proc_sleeping(&mut self, pid: usize) -> Option<SleepReason> {
|
||||||
|
self.processes[pid].sleeping
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sleep(&mut self, reason: SleepReason) {
|
||||||
|
self.processes[self.current_process.unwrap()].sleeping = Some(reason);
|
||||||
|
self.task_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wake(&mut self, pid: usize) {
|
||||||
|
if self.processes[pid].sleeping.is_some() {
|
||||||
|
self.processes[pid].sleeping = None;
|
||||||
|
self.ready_to_run.push(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user