mirror of
https://github.com/sgmarz/osblog.git
synced 2024-11-27 20:03:32 +04:00
Added locking to the scheduler. Since this is invoked so often, it causes a race with the test_elf process.
This commit is contained in:
parent
ef0997be74
commit
532b246f7b
@ -8,8 +8,8 @@ use crate::syscall::syscall_sleep;
|
|||||||
pub const DEFAULT_LOCK_SLEEP: usize = 10000;
|
pub const DEFAULT_LOCK_SLEEP: usize = 10000;
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum MutexState {
|
pub enum MutexState {
|
||||||
Locked = 0,
|
Unlocked = 0,
|
||||||
Unlocked = 1,
|
Locked = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -44,14 +44,14 @@ impl<'a> Mutex {
|
|||||||
/// Never use a sleep lock for the process list. Sleeping requires
|
/// Never use a sleep lock for the process list. Sleeping requires
|
||||||
/// the process list to function, so you'll deadlock if you do.
|
/// the process list to function, so you'll deadlock if you do.
|
||||||
pub fn sleep_lock(&mut self) {
|
pub fn sleep_lock(&mut self) {
|
||||||
while self.lock() == false {
|
while !self.lock() {
|
||||||
syscall_sleep(DEFAULT_LOCK_SLEEP);
|
syscall_sleep(DEFAULT_LOCK_SLEEP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Can safely be used inside of an interrupt context.
|
/// Can safely be used inside of an interrupt context.
|
||||||
pub fn spin_lock(&mut self) {
|
pub fn spin_lock(&mut self) {
|
||||||
while self.lock() == false {}
|
while !self.lock() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unlock(&mut self) {
|
pub fn unlock(&mut self) {
|
||||||
|
@ -59,7 +59,6 @@ pub fn set_running(pid: u16) -> bool {
|
|||||||
// of process pointers.
|
// of process pointers.
|
||||||
let mut retval = false;
|
let mut retval = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
for proc in pl.iter_mut() {
|
for proc in pl.iter_mut() {
|
||||||
if proc.pid == pid {
|
if proc.pid == pid {
|
||||||
@ -73,7 +72,6 @@ pub fn set_running(pid: u16) -> bool {
|
|||||||
// Some(pl).
|
// Some(pl).
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
}
|
}
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
}
|
||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
@ -86,7 +84,6 @@ pub fn set_waiting(pid: u16) -> bool {
|
|||||||
// of process pointers.
|
// of process pointers.
|
||||||
let mut retval = false;
|
let mut retval = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
for proc in pl.iter_mut() {
|
for proc in pl.iter_mut() {
|
||||||
if proc.pid == pid {
|
if proc.pid == pid {
|
||||||
@ -100,7 +97,6 @@ pub fn set_waiting(pid: u16) -> bool {
|
|||||||
// Some(pl).
|
// Some(pl).
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
}
|
}
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
}
|
||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
@ -111,7 +107,6 @@ pub fn set_sleeping(pid: u16, duration: usize) -> bool {
|
|||||||
// of process pointers.
|
// of process pointers.
|
||||||
let mut retval = false;
|
let mut retval = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
for proc in pl.iter_mut() {
|
for proc in pl.iter_mut() {
|
||||||
if proc.pid == pid {
|
if proc.pid == pid {
|
||||||
@ -129,7 +124,6 @@ pub fn set_sleeping(pid: u16, duration: usize) -> bool {
|
|||||||
// Some(pl).
|
// Some(pl).
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
}
|
}
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
}
|
||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
@ -138,7 +132,6 @@ pub fn set_sleeping(pid: u16, duration: usize) -> bool {
|
|||||||
/// this function does nothing.
|
/// this function does nothing.
|
||||||
pub fn delete_process(pid: u16) {
|
pub fn delete_process(pid: u16) {
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
for i in 0..pl.len() {
|
for i in 0..pl.len() {
|
||||||
let p = pl.get_mut(i).unwrap();
|
let p = pl.get_mut(i).unwrap();
|
||||||
@ -154,7 +147,6 @@ pub fn delete_process(pid: u16) {
|
|||||||
// Some(pl).
|
// Some(pl).
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
}
|
}
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +154,6 @@ pub fn delete_process(pid: u16) {
|
|||||||
/// unsafe since the process can be deleted and we'll still have a pointer.
|
/// unsafe since the process can be deleted and we'll still have a pointer.
|
||||||
pub unsafe fn get_by_pid(pid: u16) -> *mut Process {
|
pub unsafe fn get_by_pid(pid: u16) -> *mut Process {
|
||||||
let mut ret = null_mut();
|
let mut ret = null_mut();
|
||||||
PROCESS_LIST_MUTEX.spin_lock();
|
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
for i in pl.iter_mut() {
|
for i in pl.iter_mut() {
|
||||||
if i.get_pid() == pid {
|
if i.get_pid() == pid {
|
||||||
@ -172,7 +163,6 @@ pub unsafe fn get_by_pid(pid: u16) -> *mut Process {
|
|||||||
}
|
}
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
}
|
}
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,58 +233,57 @@ pub fn add_kernel_process(func: fn()) -> u16 {
|
|||||||
// then move ownership back to the PROCESS_LIST.
|
// then move ownership back to the PROCESS_LIST.
|
||||||
// This allows mutual exclusion as anyone else trying to grab
|
// This allows mutual exclusion as anyone else trying to grab
|
||||||
// the process list will get None rather than the Deque.
|
// the process list will get None rather than the Deque.
|
||||||
unsafe { PROCESS_LIST_MUTEX.spin_lock(); }
|
// .take() will replace PROCESS_LIST with None and give
|
||||||
|
// us the only copy of the Deque.
|
||||||
|
let func_addr = func as usize;
|
||||||
|
let func_vaddr = func_addr; //- 0x6000_0000;
|
||||||
|
// println!("func_addr = {:x} -> {:x}", func_addr, func_vaddr);
|
||||||
|
// We will convert NEXT_PID below into an atomic increment when
|
||||||
|
// we start getting into multi-hart processing. For now, we want
|
||||||
|
// a process. Get it to work, then improve it!
|
||||||
|
let my_pid = unsafe { NEXT_PID };
|
||||||
|
let mut ret_proc =
|
||||||
|
Process { frame: zalloc(1) as *mut TrapFrame,
|
||||||
|
stack: zalloc(STACK_PAGES),
|
||||||
|
pid: my_pid,
|
||||||
|
root: zalloc(1) as *mut Table,
|
||||||
|
state: ProcessState::Running,
|
||||||
|
data: ProcessData::zero(),
|
||||||
|
sleep_until: 0,
|
||||||
|
program: null_mut()
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
NEXT_PID += 1;
|
||||||
|
}
|
||||||
|
// Now we move the stack pointer to the bottom of the
|
||||||
|
// allocation. The spec shows that register x2 (2) is the stack
|
||||||
|
// pointer.
|
||||||
|
// We could use ret_proc.stack.add, but that's an unsafe
|
||||||
|
// function which would require an unsafe block. So, convert it
|
||||||
|
// to usize first and then add PAGE_SIZE is better.
|
||||||
|
// We also need to set the stack adjustment so that it is at the
|
||||||
|
// bottom of the memory and far away from heap allocations.
|
||||||
|
unsafe {
|
||||||
|
(*ret_proc.frame).pc = func_vaddr;
|
||||||
|
// 1 is the return address register. This makes it so we
|
||||||
|
// don't have to do syscall_exit() when a kernel process
|
||||||
|
// finishes.
|
||||||
|
(*ret_proc.frame).regs[1] = ra_delete_proc as usize;
|
||||||
|
(*ret_proc.frame).regs[2] =
|
||||||
|
ret_proc.stack as usize + STACK_PAGES * 4096;
|
||||||
|
(*ret_proc.frame).mode = CpuMode::Machine as usize;
|
||||||
|
(*ret_proc.frame).pid = ret_proc.pid as usize;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(mut pl) = unsafe { PROCESS_LIST.take() } {
|
if let Some(mut pl) = unsafe { PROCESS_LIST.take() } {
|
||||||
// .take() will replace PROCESS_LIST with None and give
|
|
||||||
// us the only copy of the Deque.
|
|
||||||
let func_addr = func as usize;
|
|
||||||
let func_vaddr = func_addr; //- 0x6000_0000;
|
|
||||||
// println!("func_addr = {:x} -> {:x}", func_addr, func_vaddr);
|
|
||||||
// We will convert NEXT_PID below into an atomic increment when
|
|
||||||
// we start getting into multi-hart processing. For now, we want
|
|
||||||
// a process. Get it to work, then improve it!
|
|
||||||
let my_pid = unsafe { NEXT_PID };
|
|
||||||
let mut ret_proc =
|
|
||||||
Process { frame: zalloc(1) as *mut TrapFrame,
|
|
||||||
stack: zalloc(STACK_PAGES),
|
|
||||||
pid: my_pid,
|
|
||||||
root: zalloc(1) as *mut Table,
|
|
||||||
state: ProcessState::Running,
|
|
||||||
data: ProcessData::zero(),
|
|
||||||
sleep_until: 0,
|
|
||||||
program: null_mut()
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
NEXT_PID += 1;
|
|
||||||
}
|
|
||||||
// Now we move the stack pointer to the bottom of the
|
|
||||||
// allocation. The spec shows that register x2 (2) is the stack
|
|
||||||
// pointer.
|
|
||||||
// We could use ret_proc.stack.add, but that's an unsafe
|
|
||||||
// function which would require an unsafe block. So, convert it
|
|
||||||
// to usize first and then add PAGE_SIZE is better.
|
|
||||||
// We also need to set the stack adjustment so that it is at the
|
|
||||||
// bottom of the memory and far away from heap allocations.
|
|
||||||
unsafe {
|
|
||||||
(*ret_proc.frame).pc = func_vaddr;
|
|
||||||
// 1 is the return address register. This makes it so we
|
|
||||||
// don't have to do syscall_exit() when a kernel process
|
|
||||||
// finishes.
|
|
||||||
(*ret_proc.frame).regs[1] = ra_delete_proc as usize;
|
|
||||||
(*ret_proc.frame).regs[2] =
|
|
||||||
ret_proc.stack as usize + STACK_PAGES * 4096;
|
|
||||||
(*ret_proc.frame).mode = CpuMode::Machine as usize;
|
|
||||||
(*ret_proc.frame).pid = ret_proc.pid as usize;
|
|
||||||
}
|
|
||||||
pl.push_back(ret_proc);
|
pl.push_back(ret_proc);
|
||||||
// Now, we no longer need the owned Deque, so we hand it
|
// Now, we no longer need the owned Deque, so we hand it
|
||||||
// back by replacing the PROCESS_LIST's None with the
|
// back by replacing the PROCESS_LIST's None with the
|
||||||
// Some(pl).
|
// Some(pl).
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
PROCESS_LIST_MUTEX.unlock();
|
|
||||||
}
|
}
|
||||||
return my_pid;
|
my_pid
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsafe { PROCESS_LIST_MUTEX.unlock(); }
|
unsafe { PROCESS_LIST_MUTEX.unlock(); }
|
||||||
@ -398,6 +387,7 @@ pub fn add_kernel_process_args(func: fn(args_ptr: usize), args: usize) -> u16 {
|
|||||||
/// but later, it should call the shell.
|
/// but later, it should call the shell.
|
||||||
pub fn init() -> usize {
|
pub fn init() -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
PROCESS_LIST_MUTEX.spin_lock();
|
||||||
PROCESS_LIST = Some(VecDeque::with_capacity(15));
|
PROCESS_LIST = Some(VecDeque::with_capacity(15));
|
||||||
// add_process_default(init_process);
|
// add_process_default(init_process);
|
||||||
add_kernel_process(init_process);
|
add_kernel_process(init_process);
|
||||||
@ -412,6 +402,7 @@ pub fn init() -> usize {
|
|||||||
// println!("Init's frame is at 0x{:08x}", frame);
|
// println!("Init's frame is at 0x{:08x}", frame);
|
||||||
// Put the process list back in the global.
|
// Put the process list back in the global.
|
||||||
PROCESS_LIST.replace(pl);
|
PROCESS_LIST.replace(pl);
|
||||||
|
PROCESS_LIST_MUTEX.unlock();
|
||||||
// Return the first instruction's address to execute.
|
// Return the first instruction's address to execute.
|
||||||
// Since we use the MMU, all start here.
|
// Since we use the MMU, all start here.
|
||||||
(*p).pc
|
(*p).pc
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
// Stephen Marz
|
// Stephen Marz
|
||||||
// 27 Dec 2019
|
// 27 Dec 2019
|
||||||
|
|
||||||
use crate::process::{ProcessState, PROCESS_LIST};
|
use crate::process::{ProcessState, PROCESS_LIST, PROCESS_LIST_MUTEX};
|
||||||
use crate::cpu::get_mtime;
|
use crate::cpu::get_mtime;
|
||||||
|
|
||||||
pub fn schedule() -> usize {
|
pub fn schedule() -> usize {
|
||||||
let mut frame_addr: usize = 0x1111;
|
let mut frame_addr: usize = 0x1111;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
PROCESS_LIST_MUTEX.spin_lock();
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
// Rust allows us to label loops so that break statements can be
|
// Rust allows us to label loops so that break statements can be
|
||||||
// targeted.
|
// targeted.
|
||||||
@ -39,6 +40,7 @@ pub fn schedule() -> usize {
|
|||||||
else {
|
else {
|
||||||
println!("could not take process list");
|
println!("could not take process list");
|
||||||
}
|
}
|
||||||
|
PROCESS_LIST_MUTEX.unlock();
|
||||||
}
|
}
|
||||||
frame_addr
|
frame_addr
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user