Skip to content

Commit 4268d51

Browse files
committed
processes: Let bet waken up by subcomponents
Don't store the reason why a process is sleeping. Let the process be waken up by the timer or input on the keyboard.
1 parent 1e73d4b commit 4268d51

File tree

6 files changed

+79
-55
lines changed

6 files changed

+79
-55
lines changed

kernel/src/cpu.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ use core::arch::asm;
22

33
use common::syscalls::trap_frame::TrapFrame;
44

5-
use crate::assert::assert_unreachable;
6-
75
pub fn write_sscratch_register(value: *const TrapFrame) {
86
unsafe {
97
asm!("csrw sscratch, {}", in(reg) value);
@@ -64,18 +62,6 @@ pub fn wait_for_interrupt() {
6462
}
6563
}
6664

67-
pub fn sret_to_kernel() -> ! {
68-
unsafe {
69-
asm!(
70-
"
71-
csrs sstatus, {}
72-
sret
73-
", in(reg) (1<<8)
74-
)
75-
}
76-
assert_unreachable();
77-
}
78-
7965
const SIE_STIE: usize = 5;
8066
const SSTATUS_SPP: usize = 8;
8167

kernel/src/interrupts/trap.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use crate::{
55
interrupts::plic::{self, InterruptSource},
66
io::{stdin_buf::STDIN_BUFFER, uart},
77
memory::linker_information::LinkerInformation,
8-
processes::scheduler::{self, get_current_process, schedule},
8+
processes::{
9+
process::ProcessState,
10+
scheduler::{self, get_current_process, schedule},
11+
},
912
syscalls::{self},
1013
warn,
1114
};
@@ -51,7 +54,7 @@ fn handle_syscall(sepc: usize, trap_frame: &mut TrapFrame) {
5154
}
5255
// In case our current process was set to waiting state we need to reschedule
5356
if let Some(process) = get_current_process()
54-
&& process.lock().get_state().is_waiting()
57+
&& process.lock().get_state() == ProcessState::Waiting
5558
{
5659
schedule();
5760
}

kernel/src/io/stdin_buf.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
1-
use crate::processes::process_list;
2-
use alloc::collections::VecDeque;
1+
use crate::processes::{process::Pid, process_list};
2+
use alloc::collections::{BTreeSet, VecDeque};
33
use common::mutex::Mutex;
44

55
pub static STDIN_BUFFER: Mutex<StdinBuffer> = Mutex::new(StdinBuffer::new());
66

77
pub struct StdinBuffer {
88
data: VecDeque<u8>,
9+
wakeup_queue: BTreeSet<Pid>,
910
}
1011

1112
impl StdinBuffer {
1213
const fn new() -> Self {
1314
StdinBuffer {
1415
data: VecDeque::new(),
16+
wakeup_queue: BTreeSet::new(),
1517
}
1618
}
1719

20+
pub fn register_wakeup(&mut self, pid: Pid) {
21+
self.wakeup_queue.insert(pid);
22+
}
23+
1824
pub fn push(&mut self, byte: u8) {
19-
if process_list::notify_input(byte) {
20-
// We already delivered the byte to the processes waiting for it
25+
let mut notified = false;
26+
for pid in &self.wakeup_queue {
27+
if process_list::notify_input(*pid, byte) {
28+
notified = true;
29+
}
30+
}
31+
self.wakeup_queue.clear();
32+
if notified {
2133
return;
2234
}
2335
self.data.push_back(byte);

kernel/src/processes/process.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@ use crate::{
33
klibc::elf::ElfFile,
44
memory::{page::PinnedHeapPages, page_tables::RootPageTableHolder, PAGE_SIZE},
55
net::sockets::SharedAssignedSocket,
6-
processes::loader::{self, LoadedElf},
6+
processes::{
7+
loader::{self, LoadedElf},
8+
process_list,
9+
},
10+
};
11+
use alloc::{
12+
collections::{BTreeMap, BTreeSet},
13+
string::String,
14+
vec::Vec,
715
};
8-
use alloc::{collections::BTreeMap, string::String, vec::Vec};
916
use common::{
1017
net::UDPDescriptor,
1118
syscalls::trap_frame::{Register, TrapFrame},
@@ -22,17 +29,7 @@ const FREE_MMAP_START_ADDRESS: usize = 0x2000000000;
2229
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2330
pub enum ProcessState {
2431
Runnable,
25-
WaitingFor(Pid),
26-
WaitingForInput,
27-
}
28-
29-
impl ProcessState {
30-
pub fn is_waiting(&self) -> bool {
31-
matches!(
32-
self,
33-
ProcessState::WaitingFor(_) | ProcessState::WaitingForInput
34-
)
35-
}
32+
Waiting,
3633
}
3734

3835
fn get_next_pid() -> Pid {
@@ -54,6 +51,7 @@ pub struct Process {
5451
next_free_descriptor: u64,
5552
open_udp_sockets: BTreeMap<UDPDescriptor, SharedAssignedSocket>,
5653
in_kernel_mode: bool,
54+
notify_on_die: BTreeSet<Pid>,
5755
}
5856

5957
impl Debug for Process {
@@ -96,6 +94,10 @@ impl Process {
9694
ptr
9795
}
9896

97+
pub fn add_notify_on_die(&mut self, pid: Pid) {
98+
self.notify_on_die.insert(pid);
99+
}
100+
99101
pub fn get_register_state(&self) -> &TrapFrame {
100102
&self.register_state
101103
}
@@ -168,6 +170,7 @@ impl Process {
168170
next_free_descriptor: 0,
169171
open_udp_sockets: BTreeMap::new(),
170172
in_kernel_mode: false,
173+
notify_on_die: BTreeSet::new(),
171174
}
172175
}
173176

@@ -193,6 +196,9 @@ impl Process {
193196

194197
impl Drop for Process {
195198
fn drop(&mut self) {
199+
for pid in &self.notify_on_die {
200+
process_list::wake_up(*pid);
201+
}
196202
debug!(
197203
"Drop process (PID: {}) (Allocated pages: {:?})",
198204
self.pid, self.allocated_pages

kernel/src/processes/process_list.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ pub fn kill(pid: Pid) {
5353
);
5454
// Drop process lock
5555
drop(processes);
56-
notify_died(pid);
5756
}
5857
}
5958

@@ -87,26 +86,33 @@ pub fn does_pid_exits(pid: Pid) -> bool {
8786
.any(|process| process.lock().get_pid() == pid)
8887
}
8988

90-
pub fn notify_died(pid: Pid) {
91-
let processes = PROCESSES.lock();
92-
for process in processes.iter() {
93-
if process.lock().get_state() == ProcessState::WaitingFor(pid) {
94-
process.lock().set_state(ProcessState::Runnable);
95-
}
89+
pub fn get_process(pid: Pid) -> Option<Arc<Mutex<Process>>> {
90+
PROCESSES
91+
.lock()
92+
.iter()
93+
.find(|process| process.lock().get_pid() == pid)
94+
.cloned()
95+
}
96+
97+
pub fn wake_up(pid: Pid) {
98+
let mut processes = PROCESSES.lock();
99+
let process = processes.iter_mut().find(|p| p.lock().get_pid() == pid);
100+
101+
if let Some(process) = process {
102+
process.lock().set_state(ProcessState::Runnable);
96103
}
97104
}
98105

99-
pub fn notify_input(byte: u8) -> bool {
106+
pub fn notify_input(pid: Pid, byte: u8) -> bool {
100107
let processes = PROCESSES.lock();
101108
let mut notified = false;
102-
for process in processes.iter() {
109+
if let Some(process) = processes.iter().find(|p| p.lock().get_pid() == pid) {
103110
let mut process = process.lock();
104-
if process.get_state() == ProcessState::WaitingForInput {
105-
process.set_state(ProcessState::Runnable);
106-
process.set_syscall_return_code(byte as usize);
107-
notified = true;
108-
}
111+
process.set_state(ProcessState::Runnable);
112+
process.set_syscall_return_code(byte as usize);
113+
notified = true;
109114
}
115+
110116
if notified {
111117
// Let's schedule a new process which can process the input
112118
timer::set_timer(0);

kernel/src/processes/scheduler.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ use super::{
44
};
55
use crate::{
66
autogenerated::userspace_programs::{INIT, PROGRAMS},
7-
cpu::{self, sret_to_kernel},
7+
cpu::{self},
88
debug, info,
99
interrupts::{read_trap_frame, set_sscratch_to_kernel_trap_frame, write_trap_frame},
10+
io::stdin_buf::STDIN_BUFFER,
1011
klibc::elf::ElfFile,
1112
memory::page_tables::{activate_page_table, KERNEL_PAGE_TABLES},
1213
processes::{
13-
process_list::{self, notify_died},
14+
process_list::{self},
1415
timer,
1516
},
1617
test::qemu_exit,
@@ -52,17 +53,20 @@ pub fn schedule() {
5253
let addr = cpu::wfi_loop as *const () as usize;
5354
debug!("setting sepc={addr:#x}");
5455
cpu::write_sepc(addr);
56+
cpu::set_ret_to_kernel_mode(true);
5557
set_sscratch_to_kernel_trap_frame();
56-
sret_to_kernel()
5758
}
5859

5960
pub fn kill_current_process() {
60-
debug!("Killing current process");
6161
let current_process = CURRENT_PROCESS.lock().take();
6262
if let Some(current_process) = current_process {
63+
assert_eq!(
64+
Arc::strong_count(&current_process),
65+
1,
66+
"We should have the last handle of this process"
67+
);
6368
activate_page_table(&KERNEL_PAGE_TABLES);
64-
notify_died(current_process.lock().get_pid());
65-
debug!("{:?}", current_process);
69+
debug!("Killing {:?}", *current_process.lock());
6670
}
6771
schedule();
6872
}
@@ -77,8 +81,12 @@ pub fn let_current_process_wait_for(pid: Pid) -> bool {
7781
.expect("There should be a process.");
7882

7983
let mut current_process = current_process.lock();
80-
current_process.set_state(ProcessState::WaitingFor(pid));
84+
current_process.set_state(ProcessState::Waiting);
8185
current_process.set_syscall_return_code(0);
86+
87+
let wait_for = process_list::get_process(pid).expect("This process must exist");
88+
wait_for.lock().add_notify_on_die(current_process.get_pid());
89+
8290
true
8391
}
8492

@@ -89,7 +97,10 @@ pub fn let_current_process_wait_for_input() {
8997
.expect("There should be a process.");
9098

9199
let mut current_process = current_process.lock();
92-
current_process.set_state(ProcessState::WaitingForInput);
100+
STDIN_BUFFER
101+
.lock()
102+
.register_wakeup(current_process.get_pid());
103+
current_process.set_state(ProcessState::Waiting);
93104
}
94105

95106
pub fn send_ctrl_c() {

0 commit comments

Comments
 (0)