mirror of
https://github.com/sgmarz/osblog.git
synced 2024-11-24 02:16:19 +04:00
Create a system call to add a process to prevent data race with the process list.
This commit is contained in:
parent
30fcd7894a
commit
fe5a909335
@ -7,7 +7,9 @@ use crate::{block::block_op,
|
|||||||
cpu::{dump_registers, TrapFrame},
|
cpu::{dump_registers, TrapFrame},
|
||||||
minixfs,
|
minixfs,
|
||||||
page::{virt_to_phys, Table},
|
page::{virt_to_phys, Table},
|
||||||
process::{delete_process, get_by_pid, set_sleeping, set_waiting}};
|
process::{delete_process, get_by_pid, set_sleeping, set_waiting}};
|
||||||
|
|
||||||
|
use crate::process::{PROCESS_LIST_MUTEX, PROCESS_LIST, Process};
|
||||||
|
|
||||||
/// do_syscall is called from trap.rs to invoke a system call. No discernment is
|
/// do_syscall is called from trap.rs to invoke a system call. No discernment is
|
||||||
/// made here whether this is a U-mode, S-mode, or M-mode system call.
|
/// made here whether this is a U-mode, S-mode, or M-mode system call.
|
||||||
@ -41,6 +43,20 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
|||||||
set_sleeping((*frame).pid as u16, (*frame).regs[10]);
|
set_sleeping((*frame).pid as u16, (*frame).regs[10]);
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
11 => {
|
||||||
|
// Add process to the scheduler. This is obviously insecure and
|
||||||
|
// we wouldn't do this realistically.
|
||||||
|
let my_proc = (*frame).regs[10] as *const Process;
|
||||||
|
PROCESS_LIST_MUTEX.spin_lock();
|
||||||
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
|
// As soon as we push this process on the list, it'll be
|
||||||
|
// schedule-able.
|
||||||
|
pl.push_back(my_proc.read());
|
||||||
|
PROCESS_LIST.replace(pl);
|
||||||
|
}
|
||||||
|
PROCESS_LIST_MUTEX.unlock();
|
||||||
|
mepc + 4
|
||||||
|
},
|
||||||
63 => {
|
63 => {
|
||||||
// Read system call
|
// Read system call
|
||||||
// This is an asynchronous call. This will get the
|
// This is an asynchronous call. This will get the
|
||||||
@ -184,6 +200,10 @@ pub fn syscall_sleep(duration: usize)
|
|||||||
{
|
{
|
||||||
let _ = do_make_syscall(10, duration, 0, 0, 0, 0, 0);
|
let _ = do_make_syscall(10, duration, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn syscall_add_process(process: Process) {
|
||||||
|
let _ = do_make_syscall(11, &process as *const Process as usize, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
// These system call numbers come from libgloss so that we can use newlib
|
// These system call numbers come from libgloss so that we can use newlib
|
||||||
// for our system calls.
|
// for our system calls.
|
||||||
// Libgloss wants the system call number in A7 and arguments in A0..A6
|
// Libgloss wants the system call number in A7 and arguments in A0..A6
|
||||||
|
@ -13,11 +13,9 @@ use crate::{cpu::{build_satp,
|
|||||||
ProcessData,
|
ProcessData,
|
||||||
ProcessState,
|
ProcessState,
|
||||||
NEXT_PID,
|
NEXT_PID,
|
||||||
PROCESS_LIST,
|
|
||||||
PROCESS_LIST_MUTEX,
|
|
||||||
STACK_ADDR,
|
STACK_ADDR,
|
||||||
STACK_PAGES},
|
STACK_PAGES},
|
||||||
syscall::syscall_fs_read};
|
syscall::{syscall_add_process, syscall_fs_read}};
|
||||||
|
|
||||||
/// Test block will load raw binaries into memory to execute them. This function
|
/// Test block will load raw binaries into memory to execute them. This function
|
||||||
/// will load ELF files and try to execute them.
|
/// will load ELF files and try to execute them.
|
||||||
@ -187,33 +185,13 @@ pub fn test_elf() {
|
|||||||
// now. Since we don't reuse PIDs, this means that we can only spawn
|
// now. Since we don't reuse PIDs, this means that we can only spawn
|
||||||
// 65534 processes.
|
// 65534 processes.
|
||||||
satp_fence_asid(my_pid as usize);
|
satp_fence_asid(my_pid as usize);
|
||||||
// I took a different tact here than in process.rs. In there I created
|
|
||||||
// the process while holding onto the process list. It might
|
// We will get a data race if we don't use the add process system call. This
|
||||||
// matter since this is asynchronous--it is being ran as a kernel process.
|
// test process is being ran as a kernel process, which then competes with
|
||||||
unsafe {
|
// the scheduler due to the context switch timer. When we use a system call,
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
// it goes into an interrupt context so that the scheduler can safely
|
||||||
}
|
// receive our new process without preemption.
|
||||||
if let Some(mut pl) = unsafe { PROCESS_LIST.take() } {
|
syscall_add_process(my_proc);
|
||||||
// As soon as we push this process on the list, it'll be
|
|
||||||
// schedule-able.
|
|
||||||
println!(
|
|
||||||
"Added user process to the scheduler...get ready \
|
|
||||||
for take-off!"
|
|
||||||
);
|
|
||||||
pl.push_back(my_proc);
|
|
||||||
unsafe {
|
|
||||||
PROCESS_LIST.replace(pl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println!("Unable to spawn process.");
|
|
||||||
// Since my_proc couldn't enter the process list, it
|
|
||||||
// will be dropped and all of the associated allocations
|
|
||||||
// will be deallocated through the process' Drop trait.
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user