Skip to content
This repository was archived by the owner on Feb 13, 2024. It is now read-only.

Commit 5e25f3d

Browse files
bors[bot]toku-sa-n
andauthored
Merge #621
621: feat: implement `exit` system call r=toku-sa-n a=toku-sa-n - feat: implement `exit` system call - test: add a process to test `exit` system call Fixes: #620 bors r+ Co-authored-by: toku-sa-n <[email protected]>
2 parents e087cc8 + 17fa282 commit 5e25f3d

File tree

9 files changed

+97
-23
lines changed

9 files changed

+97
-23
lines changed

kernel/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,14 @@ fn initialize_in_user_mode(boot_info: &mut kernelboot::Info) {
111111
ustar.list();
112112
ustar.content("build/bootx64.efi");
113113

114-
process::init();
114+
process::manager::init();
115115

116116
process::manager::add(run_tasks, Privilege::User);
117117

118118
if cfg!(feature = "qemu_test") {
119119
process::manager::add(tests::main, Privilege::User);
120120
process::manager::add(tests::process::kernel_privilege_test, Privilege::Kernel);
121+
process::manager::add(tests::process::exit_test, Privilege::User);
121122
}
122123
}
123124

kernel/src/process/collections/process.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ where
3939
f(p)
4040
}
4141

42+
pub(in crate::process) fn remove(id: process::Id) {
43+
lock_processes().remove(&id).expect("No such process.");
44+
}
45+
4246
fn lock_processes() -> SpinlockGuard<'static, BTreeMap<process::Id, Process>> {
4347
PROCESSES
4448
.try_lock()

kernel/src/process/collections/woken_pid.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ pub(super) fn active_pid() -> process::Id {
2020
lock_queue()[0]
2121
}
2222

23+
pub(in crate::process) fn pop() -> process::Id {
24+
lock_queue()
25+
.pop_front()
26+
.expect("All processes are terminated.")
27+
}
28+
2329
fn lock_queue() -> SpinlockGuard<'static, VecDeque<process::Id>> {
2430
WOKEN_PIDS
2531
.try_lock()

kernel/src/process/exit.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
use super::{
4+
collections,
5+
manager::{self, Message},
6+
};
7+
use common::constant::INTERRUPT_STACK;
8+
9+
// Do not define this as a function as the function cannot return.
10+
macro_rules! change_stack {
11+
() => {
12+
const RSP: u64 = INTERRUPT_STACK.as_u64();
13+
unsafe {
14+
asm!("
15+
mov rsp, {}
16+
", const RSP);
17+
}
18+
};
19+
}
20+
21+
pub fn exit() -> ! {
22+
change_stack!();
23+
free_stack();
24+
manager::set_temporary_stack_frame();
25+
send_exit_message();
26+
cause_timer_interrupt();
27+
}
28+
29+
fn free_stack() {
30+
collections::process::handle_running_mut(|p| {
31+
p.stack = None;
32+
p.stack_frame = None;
33+
});
34+
}
35+
36+
fn send_exit_message() {
37+
let id = collections::woken_pid::pop();
38+
manager::send_message(Message::Exit(id));
39+
}
40+
41+
fn cause_timer_interrupt() -> ! {
42+
unsafe { asm!("int 0x20", options(noreturn)) }
43+
}

kernel/src/process/manager.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,52 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

33
use super::{collections, collections::woken_pid, switch, Privilege, Process};
4+
use crate::tss::TSS;
45
use alloc::collections::VecDeque;
6+
use common::constant::INTERRUPT_STACK;
57
use conquer_once::spin::Lazy;
68
use spinning_top::Spinlock;
9+
10+
pub use super::exit::exit;
711
pub use switch::switch;
812

913
static MESSAGE: Lazy<Spinlock<VecDeque<Message>>> = Lazy::new(|| Spinlock::new(VecDeque::new()));
1014

1115
pub fn main() -> ! {
1216
loop {
13-
while let Some(Message::Add(f, p)) = MESSAGE.lock().pop_front() {
14-
match p {
15-
Privilege::Kernel => push_process_to_queue(Process::kernel(f)),
16-
Privilege::User => push_process_to_queue(Process::user(f)),
17+
while let Some(m) = MESSAGE.lock().pop_front() {
18+
match m {
19+
Message::Add(f, p) => match p {
20+
Privilege::Kernel => push_process_to_queue(Process::kernel(f)),
21+
Privilege::User => push_process_to_queue(Process::user(f)),
22+
},
23+
Message::Exit(id) => collections::process::remove(id),
1724
}
1825
}
1926
}
2027
}
2128

2229
pub fn init() {
30+
set_temporary_stack_frame();
2331
push_process_to_queue(Process::user(main));
2432
}
2533

2634
pub fn add(f: fn() -> !, p: Privilege) {
27-
MESSAGE.lock().push_back(Message::Add(f, p));
35+
send_message(Message::Add(f, p));
2836
}
2937

3038
pub fn getpid() -> i32 {
3139
collections::process::handle_running(|p| p.id.as_i32())
3240
}
3341

42+
pub(super) fn send_message(m: Message) {
43+
MESSAGE.lock().push_back(m);
44+
}
45+
46+
pub(super) fn set_temporary_stack_frame() {
47+
TSS.lock().interrupt_stack_table[0] = INTERRUPT_STACK;
48+
}
49+
3450
fn push_process_to_queue(p: Process) {
3551
add_pid(p.id());
3652
add_process(p);
@@ -48,6 +64,7 @@ pub(super) fn loader(f: fn() -> !) -> ! {
4864
f()
4965
}
5066

51-
enum Message {
67+
pub(super) enum Message {
5268
Add(fn() -> !, Privilege),
69+
Exit(super::Id),
5370
}

kernel/src/process/mod.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,19 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

33
mod collections;
4+
mod exit;
45
pub mod manager;
56
mod stack_frame;
67
mod switch;
78

8-
use crate::{
9-
mem::{allocator::page_box::PageBox, paging::pml4::PML4},
10-
tss::TSS,
11-
};
12-
use common::constant::INTERRUPT_STACK;
9+
use crate::mem::{allocator::page_box::PageBox, paging::pml4::PML4};
1310
use core::sync::atomic::{AtomicI32, Ordering};
1411
use stack_frame::StackFrame;
1512
use x86_64::{
1613
structures::paging::{PageTable, PageTableFlags},
1714
PhysAddr, VirtAddr,
1815
};
1916

20-
pub fn init() {
21-
register_initial_interrupt_stack_table_addr();
22-
manager::init();
23-
}
24-
25-
fn register_initial_interrupt_stack_table_addr() {
26-
TSS.lock().interrupt_stack_table[0] = INTERRUPT_STACK;
27-
}
28-
2917
#[derive(Debug)]
3018
pub struct Process {
3119
id: Id,

kernel/src/syscall.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use x86_64::{
1313
PhysAddr, VirtAddr,
1414
};
1515

16-
use crate::mem::allocator;
16+
use crate::{mem::allocator, process};
1717

1818
pub fn init() {
1919
enable();
@@ -94,6 +94,7 @@ unsafe fn select_proper_syscall(idx: u64, a1: u64, a2: u64) -> u64 {
9494
sys_unmap_pages(VirtAddr::new(a1), Bytes::new(a2.try_into().unwrap()))
9595
}
9696
syscalls::Ty::GetPid => sys_getpid().try_into().unwrap(),
97+
syscalls::Ty::Exit => sys_exit(),
9798
},
9899
None => panic!("Unsupported syscall index: {}", idx),
99100
}
@@ -168,5 +169,9 @@ fn sys_unmap_pages(start: VirtAddr, bytes: Bytes) -> u64 {
168169
}
169170

170171
fn sys_getpid() -> i32 {
171-
crate::process::manager::getpid()
172+
process::manager::getpid()
173+
}
174+
175+
fn sys_exit() -> ! {
176+
process::manager::exit();
172177
}

kernel/src/tests/process.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ pub fn kernel_privilege_test() -> ! {
1919
x86_64::instructions::hlt()
2020
}
2121
}
22+
23+
pub fn exit_test() -> ! {
24+
syscalls::exit();
25+
}

syscalls/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ pub fn getpid() -> i32 {
9292
unsafe { general_syscall(Ty::GetPid, 0, 0).try_into().unwrap() }
9393
}
9494

95+
pub fn exit() -> ! {
96+
let ty = Ty::Exit as u64;
97+
unsafe { asm!("syscall", in("rax") ty, options(noreturn)) }
98+
}
99+
95100
/// SAFETY: This function is unsafe if arguments are invalid.
96101
unsafe fn general_syscall(ty: Ty, a1: u64, a2: u64) -> u64 {
97102
let ty = ty as u64;
@@ -117,4 +122,5 @@ pub enum Ty {
117122
MapPages,
118123
UnmapPages,
119124
GetPid,
125+
Exit,
120126
}

0 commit comments

Comments
 (0)