Skip to content

Commit 2720cf5

Browse files
committed
scheduler: Refactor
The scheduler needed some love for a long time now.
1 parent 866d554 commit 2720cf5

File tree

12 files changed

+311
-280
lines changed

12 files changed

+311
-280
lines changed

kernel/src/debugging/mod.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use crate::{
2-
info,
3-
klibc::sizes::MiB,
4-
processes::{process_table, scheduler::get_current_process},
5-
};
1+
use crate::{info, klibc::sizes::MiB, processes::scheduler};
62

73
pub mod backtrace;
84
mod eh_frame_parser;
@@ -24,16 +20,14 @@ pub fn dump_current_state() {
2420
used_heap_pages, total_heap_pages
2521
);
2622

27-
process_table::THE.lock().dump();
28-
29-
let current_process = get_current_process();
30-
if let Some(process) = current_process {
31-
let process = process.lock();
23+
scheduler::THE.with_lock(|s| {
24+
s.dump();
25+
let current_process = s.get_current_process().lock();
3226
info!(
3327
"Current Process: PID={} NAME={} STATE={:?}",
34-
process.get_pid(),
35-
process.get_name(),
36-
process.get_state()
28+
current_process.get_pid(),
29+
current_process.get_name(),
30+
current_process.get_state()
3731
);
38-
}
32+
});
3933
}

kernel/src/interrupts/trap.rs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,17 @@ use crate::{
77
memory::linker_information::LinkerInformation,
88
processes::{
99
process::ProcessState,
10-
scheduler::{self, get_current_process, schedule},
10+
scheduler::{self},
1111
},
1212
syscalls::{self},
1313
warn,
1414
};
15-
use alloc::string::ToString;
1615
use common::syscalls::trap_frame::{Register, TrapFrame};
1716
use core::panic;
1817

1918
#[no_mangle]
2019
extern "C" fn handle_timer_interrupt() {
21-
scheduler::schedule();
20+
scheduler::THE.lock().schedule();
2221
}
2322

2423
#[no_mangle]
@@ -35,7 +34,7 @@ fn handle_external_interrupt() {
3534
plic::complete_interrupt(plic_interrupt);
3635

3736
match input {
38-
3 => crate::processes::scheduler::send_ctrl_c(),
37+
3 => scheduler::THE.lock().send_ctrl_c(),
3938
4 => crate::debugging::dump_current_state(),
4039
_ => STDIN_BUFFER.lock().push(input),
4140
}
@@ -53,11 +52,11 @@ fn handle_syscall(sepc: usize, trap_frame: &mut TrapFrame) {
5352
cpu::write_sepc(sepc + 4); // Skip the ecall instruction
5453
}
5554
// In case our current process was set to waiting state we need to reschedule
56-
if let Some(process) = get_current_process()
57-
&& process.lock().get_state() == ProcessState::Waiting
58-
{
59-
schedule();
60-
}
55+
scheduler::THE.with_lock(|mut s| {
56+
if s.get_current_process().lock().get_state() == ProcessState::Waiting {
57+
s.schedule();
58+
}
59+
});
6160
}
6261

6362
fn warn_on_stackoverflow(cause: InterruptCause, stval: usize) {
@@ -77,27 +76,19 @@ fn handle_unhandled_exception(
7776
sepc: usize,
7877
trap_frame: &mut TrapFrame,
7978
) {
80-
let current_process = get_current_process();
81-
let mut is_userspace_address = "NO ACTIVE PROCESS".to_string();
82-
let mut process_name = is_userspace_address.clone();
83-
if let Some(current_process) = current_process {
84-
let current_process = current_process.lock();
85-
is_userspace_address = format!(
86-
"{}",
87-
current_process.get_page_table().is_userspace_address(sepc)
88-
);
89-
process_name = current_process.get_name().to_string();
90-
}
91-
panic!(
79+
let message= scheduler::THE.lock().get_current_process().with_lock(|p| {
80+
format!(
9281
"Unhandled exception!\nName: {}\nException code: {}\nstval: 0x{:x}\nsepc: 0x{:x}\nFrom Userspace: {}\nProcess name: {}\nTrap Frame: {:?}",
9382
cause.get_reason(),
9483
cause.get_exception_code(),
9584
stval,
9685
sepc,
97-
is_userspace_address,
98-
process_name,
86+
p.get_page_table().is_userspace_address(sepc),
87+
p.get_name(),
9988
trap_frame
100-
);
89+
)
90+
});
91+
panic!("{}", message);
10192
}
10293

10394
#[no_mangle]

kernel/src/io/stdin_buf.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
cpu,
33
processes::{
44
process::{Pid, ProcessState},
5-
process_table, timer,
5+
scheduler, timer,
66
},
77
};
88
use alloc::collections::{BTreeSet, VecDeque};
@@ -29,9 +29,9 @@ impl StdinBuffer {
2929

3030
pub fn push(&mut self, byte: u8) {
3131
let notified = !self.wakeup_queue.is_empty();
32-
process_table::THE.with_lock(|pt| {
32+
scheduler::THE.with_lock(|s| {
3333
for pid in &self.wakeup_queue {
34-
if let Some(process) = pt.get_process(*pid) {
34+
if let Some(process) = s.get_process(*pid) {
3535
process.with_lock(|mut p| {
3636
p.set_state(ProcessState::Runnable);
3737
p.set_syscall_return_code(byte as usize);

kernel/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ extern "C" fn kernel_init(hart_id: usize, device_tree_pointer: *const ()) {
118118

119119
plic::init_uart_interrupt();
120120

121-
scheduler::initialize();
121+
scheduler::init();
122122

123123
let mut pci_devices = enumerate_devices(&pci_information);
124124

kernel/src/memory/page_tables.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ impl RootPageTableHolder {
163163
}
164164
}
165165

166+
pub const fn invalid() -> Self {
167+
Self {
168+
root_table: null_mut(),
169+
already_mapped: Vec::new(),
170+
}
171+
}
172+
166173
fn table(&self) -> &PageTable {
167174
// SAFETY: It is always allocated
168175
unsafe { &*self.root_table }

kernel/src/panic.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ static PANIC_COUNTER: AtomicU8 = AtomicU8::new(0);
1010
#[cfg(not(miri))]
1111
#[panic_handler]
1212
fn panic(info: &PanicInfo) -> ! {
13-
use crate::processes::scheduler::disarm_current_process;
14-
1513
unsafe {
1614
crate::cpu::disable_global_interrupts();
1715
}
@@ -22,7 +20,6 @@ fn panic(info: &PanicInfo) -> ! {
2220
// output some data
2321
unsafe {
2422
QEMU_UART.disarm();
25-
disarm_current_process();
2623
}
2724

2825
println!("");

kernel/src/processes/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub mod loader;
1+
mod loader;
22
pub mod process;
33
pub mod process_table;
44
pub mod scheduler;

kernel/src/processes/process.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
};
88
use alloc::{
99
collections::{BTreeMap, BTreeSet},
10-
string::String,
10+
string::{String, ToString},
1111
vec::Vec,
1212
};
1313
use common::{
@@ -21,6 +21,8 @@ use core::{
2121

2222
pub type Pid = u64;
2323

24+
pub const NEVER_PID: Pid = 0;
25+
2426
const FREE_MMAP_START_ADDRESS: usize = 0x2000000000;
2527

2628
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -30,6 +32,8 @@ pub enum ProcessState {
3032
}
3133

3234
fn get_next_pid() -> Pid {
35+
// PIDs will start from 1
36+
// 0 is reserved for the never process which will be never scheduled
3337
static PID_COUNTER: AtomicU64 = AtomicU64::new(1);
3438
let next_pid = PID_COUNTER.fetch_add(1, Ordering::Relaxed);
3539
assert_ne!(next_pid, u64::MAX, "We ran out of process pids");
@@ -76,6 +80,23 @@ impl Debug for Process {
7680
}
7781

7882
impl Process {
83+
pub fn never() -> Self {
84+
Self {
85+
name: "never".to_string(),
86+
pid: NEVER_PID,
87+
register_state: TrapFrame::zero(),
88+
page_table: RootPageTableHolder::invalid(),
89+
program_counter: 0,
90+
allocated_pages: Vec::new(),
91+
state: ProcessState::Waiting,
92+
free_mmap_address: FREE_MMAP_START_ADDRESS,
93+
next_free_descriptor: 0,
94+
open_udp_sockets: BTreeMap::new(),
95+
in_kernel_mode: false,
96+
notify_on_die: BTreeSet::new(),
97+
}
98+
}
99+
79100
pub fn get_notifies_on_die(&self) -> impl Iterator<Item = &Pid> {
80101
self.notify_on_die.iter()
81102
}

kernel/src/processes/process_table.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use common::mutex::Mutex;
33

44
use crate::{debug, info};
55

6-
use super::process::{Pid, Process, ProcessState};
7-
8-
pub static THE: Mutex<ProcessTable> = Mutex::new(ProcessTable::new());
6+
use super::process::{Pid, Process, ProcessState, NEVER_PID};
97

108
pub type ProcessRef = Arc<Mutex<Process>>;
119

@@ -14,10 +12,12 @@ pub struct ProcessTable {
1412
}
1513

1614
impl ProcessTable {
17-
const fn new() -> Self {
18-
Self {
15+
pub fn new() -> Self {
16+
let mut self_ = Self {
1917
processes: BTreeMap::new(),
20-
}
18+
};
19+
self_.add_process(Process::never());
20+
self_
2121
}
2222

2323
pub fn add_process(&mut self, process: Process) {
@@ -26,13 +26,18 @@ impl ProcessTable {
2626
}
2727

2828
pub fn is_empty(&self) -> bool {
29-
self.processes.is_empty()
29+
// If only the never process is left
30+
// we know the process table is empty
31+
self.processes.len() == 1
3032
}
3133

32-
pub fn get_highest_pid_without_yash(&self) -> Option<Pid> {
34+
pub fn get_highest_pid_without(&self, process_names: &[&str]) -> Option<Pid> {
3335
self.processes
3436
.iter()
35-
.filter(|(_, p)| p.lock().get_name() != "yash")
37+
.filter(|(_, p)| {
38+
let p = p.lock();
39+
!process_names.iter().any(|n| p.get_name() == *n) && p.get_pid() != NEVER_PID
40+
})
3641
.max_by_key(|(pid, _)| *pid)
3742
.map(|(pid, _)| *pid)
3843
}
@@ -50,6 +55,10 @@ impl ProcessTable {
5055
}
5156

5257
pub fn kill(&mut self, pid: Pid) {
58+
assert!(
59+
pid != NEVER_PID,
60+
"We are not allowed to kill the never process"
61+
);
5362
debug!("Removing pid={pid} from process table");
5463
if let Some(process) = self.processes.remove(&pid) {
5564
assert_eq!(
@@ -93,8 +102,11 @@ impl ProcessTable {
93102
self.processes.get(&pid)
94103
}
95104

96-
pub fn does_pid_exist(&self, pid: Pid) -> bool {
97-
self.processes.contains_key(&pid)
105+
pub fn get_dummy_process(&self) -> ProcessRef {
106+
self.processes
107+
.get(&NEVER_PID)
108+
.expect("The dummy process must always exist")
109+
.clone()
98110
}
99111

100112
pub fn wake_process_up(&self, pid: Pid) {

0 commit comments

Comments
 (0)