extract scheduler functions into new module
This commit is contained in:
parent
71f9a49704
commit
87b00c924f
@ -13,7 +13,10 @@ pub mod uart;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::file::{devsw, CONSOLE},
|
fs::file::{devsw, CONSOLE},
|
||||||
proc::process::{procdump, wakeup, Process},
|
proc::{
|
||||||
|
process::{procdump, Process},
|
||||||
|
scheduler::wakeup,
|
||||||
|
},
|
||||||
sync::mutex::Mutex,
|
sync::mutex::Mutex,
|
||||||
};
|
};
|
||||||
use core::{ffi::c_void, ptr::addr_of_mut};
|
use core::{ffi::c_void, ptr::addr_of_mut};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
console::consoleintr, proc::process::wakeup, queue::Queue, sync::mutex::Mutex,
|
console::consoleintr, proc::scheduler::wakeup, queue::Queue, sync::mutex::Mutex,
|
||||||
trap::InterruptBlocker,
|
trap::InterruptBlocker,
|
||||||
};
|
};
|
||||||
use core::ptr::addr_of;
|
use core::ptr::addr_of;
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
kalloc::{kalloc, kfree},
|
kalloc::{kalloc, kfree},
|
||||||
virtual_memory::{copyin, copyout},
|
virtual_memory::{copyin, copyout},
|
||||||
},
|
},
|
||||||
proc::process::{wakeup, Process},
|
proc::{process::Process, scheduler::wakeup},
|
||||||
sync::spinlock::Spinlock,
|
sync::spinlock::Spinlock,
|
||||||
};
|
};
|
||||||
use core::ptr::{addr_of, addr_of_mut};
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
@ -82,7 +82,7 @@ pub unsafe fn main() -> ! {
|
|||||||
arch::riscv::plic::plicinithart();
|
arch::riscv::plic::plicinithart();
|
||||||
}
|
}
|
||||||
|
|
||||||
proc::process::scheduler();
|
proc::scheduler::scheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
pub mod scheduler;
|
||||||
pub mod trapframe;
|
pub mod trapframe;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#![allow(clippy::comparison_chain)]
|
#![allow(clippy::comparison_chain)]
|
||||||
|
|
||||||
use super::{context::Context, cpu::Cpu, trapframe::Trapframe};
|
use super::{context::Context, cpu::Cpu, scheduler::wakeup, trapframe::Trapframe};
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::riscv::{intr_get, Pagetable, PTE_W},
|
arch::riscv::{Pagetable, PTE_W},
|
||||||
fs::file::{File, Inode},
|
fs::file::{File, Inode},
|
||||||
mem::kalloc::kfree,
|
mem::kalloc::kfree,
|
||||||
sync::spinlock::{Spinlock, SpinlockGuard},
|
sync::spinlock::Spinlock,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::{c_char, c_void},
|
ffi::{c_char, c_void},
|
||||||
@ -36,14 +36,9 @@ extern "C" {
|
|||||||
pub fn proc_mapstacks(kpgtbl: Pagetable);
|
pub fn proc_mapstacks(kpgtbl: Pagetable);
|
||||||
pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
||||||
pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
||||||
pub fn wakeup(chan: *const c_void);
|
|
||||||
pub fn allocproc() -> *mut Process;
|
pub fn allocproc() -> *mut Process;
|
||||||
// pub fn freeproc(p: *mut Process);
|
|
||||||
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
|
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
|
||||||
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
|
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
|
||||||
// pub fn sched();
|
|
||||||
pub fn scheduler() -> !;
|
|
||||||
pub fn swtch(a: *mut Context, b: *mut Context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static NEXT_PID: AtomicI32 = AtomicI32::new(1);
|
pub static NEXT_PID: AtomicI32 = AtomicI32::new(1);
|
||||||
@ -238,64 +233,6 @@ pub unsafe fn growproc(n: i32) -> i32 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Give up the CPU for one scheduling round.
|
|
||||||
pub unsafe fn r#yield() {
|
|
||||||
let p = Process::current().unwrap();
|
|
||||||
let _guard = p.lock.lock();
|
|
||||||
p.state = ProcessState::Runnable;
|
|
||||||
sched();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Switch to scheduler. Must hold only p->lock
|
|
||||||
/// and have changed proc->state. Saves and restores
|
|
||||||
/// previous_interrupts_enabled because previous_interrupts_enabled is a property of this
|
|
||||||
/// kernel thread, not this CPU. It should
|
|
||||||
/// be proc->previous_interrupts_enabled and proc->interrupt_disable_layers, but that would
|
|
||||||
/// break in the few places where a lock is held but
|
|
||||||
/// there's no process.
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn sched() {
|
|
||||||
let p = Process::current().unwrap();
|
|
||||||
let cpu = Cpu::current();
|
|
||||||
|
|
||||||
if cpu.interrupt_disable_layers != 1 {
|
|
||||||
panic!("sched locks");
|
|
||||||
} else if p.state == ProcessState::Running {
|
|
||||||
panic!("sched running");
|
|
||||||
} else if intr_get() > 0 {
|
|
||||||
panic!("sched interruptible");
|
|
||||||
}
|
|
||||||
|
|
||||||
let previous_interrupts_enabled = cpu.previous_interrupts_enabled;
|
|
||||||
swtch(addr_of_mut!(p.context), addr_of_mut!(cpu.context));
|
|
||||||
cpu.previous_interrupts_enabled = previous_interrupts_enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The lock should already be locked.
|
|
||||||
/// Unsafely create a new guard for it so that we can call SpinlockGuard.sleep().
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) {
|
|
||||||
let lock: &Spinlock = &*lock;
|
|
||||||
let guard = SpinlockGuard { lock };
|
|
||||||
guard.sleep(chan);
|
|
||||||
core::mem::forget(guard);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sleep until `wakeup(chan)` is called somewhere else.
|
|
||||||
pub unsafe fn sleep(chan: *mut c_void) {
|
|
||||||
let p = Process::current().unwrap();
|
|
||||||
let _guard = p.lock.lock();
|
|
||||||
|
|
||||||
// Go to sleep.
|
|
||||||
p.chan = chan;
|
|
||||||
p.state = ProcessState::Sleeping;
|
|
||||||
|
|
||||||
sched();
|
|
||||||
|
|
||||||
// Tidy up.
|
|
||||||
p.chan = null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Kill the process with the given pid.
|
/// Kill the process with the given pid.
|
||||||
/// The victim won't exit until it tries to return
|
/// The victim won't exit until it tries to return
|
||||||
/// to user space (see usertrap() in trap.c).
|
/// to user space (see usertrap() in trap.c).
|
||||||
|
77
kernel/rustkernel/src/proc/scheduler.rs
Normal file
77
kernel/rustkernel/src/proc/scheduler.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use super::{
|
||||||
|
context::Context,
|
||||||
|
cpu::Cpu,
|
||||||
|
process::{Process, ProcessState},
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
arch::riscv::intr_get,
|
||||||
|
sync::spinlock::{Spinlock, SpinlockGuard},
|
||||||
|
};
|
||||||
|
use core::{
|
||||||
|
ffi::c_void,
|
||||||
|
ptr::{addr_of_mut, null_mut},
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn wakeup(chan: *const c_void);
|
||||||
|
pub fn scheduler() -> !;
|
||||||
|
pub fn swtch(a: *mut Context, b: *mut Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Give up the CPU for one scheduling round.
|
||||||
|
pub unsafe fn r#yield() {
|
||||||
|
let p = Process::current().unwrap();
|
||||||
|
let _guard = p.lock.lock();
|
||||||
|
p.state = ProcessState::Runnable;
|
||||||
|
sched();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Switch to scheduler. Must hold only p->lock
|
||||||
|
/// and have changed proc->state. Saves and restores
|
||||||
|
/// previous_interrupts_enabled because previous_interrupts_enabled is a property of this
|
||||||
|
/// kernel thread, not this CPU. It should
|
||||||
|
/// be proc->previous_interrupts_enabled and proc->interrupt_disable_layers, but that would
|
||||||
|
/// break in the few places where a lock is held but
|
||||||
|
/// there's no process.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn sched() {
|
||||||
|
let p = Process::current().unwrap();
|
||||||
|
let cpu = Cpu::current();
|
||||||
|
|
||||||
|
if cpu.interrupt_disable_layers != 1 {
|
||||||
|
panic!("sched locks");
|
||||||
|
} else if p.state == ProcessState::Running {
|
||||||
|
panic!("sched running");
|
||||||
|
} else if intr_get() > 0 {
|
||||||
|
panic!("sched interruptible");
|
||||||
|
}
|
||||||
|
|
||||||
|
let previous_interrupts_enabled = cpu.previous_interrupts_enabled;
|
||||||
|
swtch(addr_of_mut!(p.context), addr_of_mut!(cpu.context));
|
||||||
|
cpu.previous_interrupts_enabled = previous_interrupts_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The lock should already be locked.
|
||||||
|
/// Unsafely create a new guard for it so that we can call SpinlockGuard.sleep().
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) {
|
||||||
|
let lock: &Spinlock = &*lock;
|
||||||
|
let guard = SpinlockGuard { lock };
|
||||||
|
guard.sleep(chan);
|
||||||
|
core::mem::forget(guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sleep until `wakeup(chan)` is called somewhere else.
|
||||||
|
pub unsafe fn sleep(chan: *mut c_void) {
|
||||||
|
let p = Process::current().unwrap();
|
||||||
|
let _guard = p.lock.lock();
|
||||||
|
|
||||||
|
// Go to sleep.
|
||||||
|
p.chan = chan;
|
||||||
|
p.state = ProcessState::Sleeping;
|
||||||
|
|
||||||
|
sched();
|
||||||
|
|
||||||
|
// Tidy up.
|
||||||
|
p.chan = null_mut();
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
use super::LockStrategy;
|
use super::LockStrategy;
|
||||||
use crate::proc::process::{sched, sleep, wakeup, Process, ProcessState};
|
use crate::proc::{
|
||||||
|
process::{Process, ProcessState},
|
||||||
|
scheduler::{sched, sleep, wakeup},
|
||||||
|
};
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
ops::Drop,
|
ops::Drop,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::proc::process::{sleep, wakeup};
|
use crate::proc::scheduler::{sleep, wakeup};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::c_char,
|
ffi::c_char,
|
||||||
ptr::addr_of,
|
ptr::addr_of,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
proc::process::{sched, Process, ProcessState},
|
proc::{
|
||||||
|
process::{Process, ProcessState},
|
||||||
|
scheduler::sched,
|
||||||
|
},
|
||||||
trap::{pop_intr_off, push_intr_off},
|
trap::{pop_intr_off, push_intr_off},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
|
@ -3,7 +3,8 @@ use crate::{
|
|||||||
println,
|
println,
|
||||||
proc::{
|
proc::{
|
||||||
cpu::Cpu,
|
cpu::Cpu,
|
||||||
process::{exit, r#yield, wakeup, Process, ProcessState},
|
process::{exit, Process, ProcessState},
|
||||||
|
scheduler::{r#yield, wakeup},
|
||||||
},
|
},
|
||||||
sync::mutex::Mutex,
|
sync::mutex::Mutex,
|
||||||
syscall::syscall,
|
syscall::syscall,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user