Skip to content

Commit affcc2d

Browse files
committed
sched: Refactor scheduler
1 parent 277e1fb commit affcc2d

11 files changed

Lines changed: 555 additions & 198 deletions

File tree

kernel/src/arch/executor.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use super::internal;
2+
use crate::{memory::stack::KernelStack, posix::errno::EResult, process::task::Task};
3+
4+
pub use internal::executor::{Executor, ForkedImage, FrameImage};
5+
6+
pub fn new_kernel(
7+
entry: extern "C" fn(usize, usize),
8+
arg1: usize,
9+
arg2: usize,
10+
stack: &KernelStack,
11+
) -> EResult<Executor> {
12+
internal::executor::Executor::new_kernel(entry, arg1, arg2, stack)
13+
}
14+
15+
/// Switches the current CPU context from one task executor to another.
16+
///
17+
/// # Safety
18+
/// The caller must ensure that `from` and `to` are valid, distinct live tasks.
19+
pub unsafe fn switch(from: *const Task, to: *const Task) -> *mut Task {
20+
unsafe { internal::executor::switch(from, to) }
21+
}
22+
23+
pub fn fork_current(entry: extern "C" fn(*const ForkedImage, usize) -> !, arg: usize) {
24+
internal::executor::fork_current(entry, arg)
25+
}
26+
27+
pub fn run_on_stack_raw(
28+
stack_top: usize,
29+
entry: extern "C" fn(usize, usize) -> !,
30+
arg: usize,
31+
) -> ! {
32+
internal::executor::run_on_stack_raw(stack_top, entry, arg)
33+
}

kernel/src/arch/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mod internal {
2222
}
2323

2424
pub mod cpu;
25+
pub mod executor;
2526
pub mod irq;
2627
pub mod sched;
2728
pub mod virt;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use super::sched;
2+
use crate::{memory::stack::KernelStack, posix::errno::EResult, process::task::Task};
3+
4+
pub type Executor = sched::TaskContext;
5+
6+
#[repr(C)]
7+
pub struct ForkedImage;
8+
9+
pub struct FrameImage;
10+
11+
impl Executor {
12+
pub fn new_kernel(
13+
entry: extern "C" fn(usize, usize),
14+
arg1: usize,
15+
arg2: usize,
16+
stack: &KernelStack,
17+
) -> EResult<Self> {
18+
let mut this = Self::default();
19+
sched::init_task(&mut this, entry, arg1, arg2, stack, false)?;
20+
Ok(this)
21+
}
22+
}
23+
24+
pub unsafe fn switch(from: *const Task, to: *const Task) -> *mut Task {
25+
unsafe { sched::switch(from, to) }
26+
}
27+
28+
pub fn fork_current(_entry: extern "C" fn(*const ForkedImage, usize) -> !, _arg: usize) {
29+
todo!("riscv64 executor forking is not implemented yet")
30+
}
31+
32+
pub fn run_on_stack_raw(
33+
stack_top: usize,
34+
entry: extern "C" fn(usize, usize) -> !,
35+
arg: usize,
36+
) -> ! {
37+
sched::run_on_stack_raw(stack_top, entry, arg)
38+
}

kernel/src/arch/riscv64/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod cpu;
2+
pub mod executor;
23
pub mod irq;
34
pub mod sched;
45
pub mod system;

kernel/src/arch/sched.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ use crate::{
77
use core::{fmt::Debug, mem::MaybeUninit};
88

99
pub use internal::sched::{Context, SyscallRestart};
10-
assert_trait_impl!(TaskContext, Debug);
10+
assert_trait_impl!(Context, Debug);
1111
assert_trait_impl!(Context, Default);
1212
assert_trait_impl!(Context, Clone);
1313
assert_trait_impl!(Context, Copy);
1414

15-
pub use internal::sched::TaskContext;
16-
assert_trait_impl!(TaskContext, Debug);
17-
assert_trait_impl!(TaskContext, Default);
18-
assert_trait_impl!(TaskContext, Clone);
15+
pub use crate::arch::executor::Executor;
16+
assert_trait_impl!(Executor, Debug);
17+
assert_trait_impl!(Executor, Default);
18+
assert_trait_impl!(Executor, Clone);
1919

2020
/// Disables preemption.
2121
/// # Safety
@@ -55,7 +55,7 @@ pub fn broadcast_shootdown() {
5555

5656
/// Initializes a new task.
5757
pub fn init_task(
58-
task: &mut TaskContext,
58+
task: &mut Executor,
5959
entry: extern "C" fn(usize, usize),
6060
arg1: usize,
6161
arg2: usize,

kernel/src/arch/x86_64/executor.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use super::{sched, sched::Context};
2+
use crate::{memory::stack::KernelStack, posix::errno::EResult, process::task::Task};
3+
use alloc::boxed::Box;
4+
use core::{arch::asm, mem::offset_of};
5+
6+
#[repr(C)]
7+
#[derive(Default, Debug, Clone)]
8+
pub struct Executor {
9+
pub rsp: u64,
10+
pub fpu_region: Box<[u8]>,
11+
pub ds: u16,
12+
pub es: u16,
13+
pub fs: u16,
14+
pub gs: u16,
15+
pub fsbase: u64,
16+
pub gsbase: u64,
17+
pub restarted: bool,
18+
}
19+
20+
impl Executor {
21+
pub fn new_kernel(
22+
entry: extern "C" fn(usize, usize),
23+
arg1: usize,
24+
arg2: usize,
25+
stack: &KernelStack,
26+
) -> EResult<Self> {
27+
let mut this = Self::default();
28+
sched::init_task(&mut this, entry, arg1, arg2, stack, false)?;
29+
Ok(this)
30+
}
31+
}
32+
33+
#[repr(C)]
34+
pub struct ForkedImage {
35+
rbx: usize,
36+
rbp: usize,
37+
r12: usize,
38+
r13: usize,
39+
r14: usize,
40+
r15: usize,
41+
rsp: usize,
42+
rip: usize,
43+
rflags: usize,
44+
}
45+
46+
impl ForkedImage {
47+
pub const fn ip(&self) -> usize {
48+
self.rip
49+
}
50+
51+
pub const fn sp(&self) -> usize {
52+
self.rsp
53+
}
54+
55+
pub const fn flags(&self) -> usize {
56+
self.rflags
57+
}
58+
}
59+
60+
pub struct FrameImage<'a> {
61+
frame: &'a mut Context,
62+
}
63+
64+
impl<'a> FrameImage<'a> {
65+
pub fn new(frame: &'a mut Context) -> Self {
66+
Self { frame }
67+
}
68+
69+
pub const fn frame(&self) -> &Context {
70+
self.frame
71+
}
72+
73+
pub fn frame_mut(&mut self) -> &mut Context {
74+
self.frame
75+
}
76+
77+
pub const fn ip(&self) -> usize {
78+
self.frame.rip as usize
79+
}
80+
81+
pub const fn sp(&self) -> usize {
82+
self.frame.rsp as usize
83+
}
84+
85+
pub const fn flags(&self) -> usize {
86+
self.frame.rflags as usize
87+
}
88+
}
89+
90+
pub unsafe fn switch(from: *const Task, to: *const Task) -> *mut Task {
91+
unsafe { sched::switch(from, to) }
92+
}
93+
94+
pub fn run_on_stack_raw(
95+
stack_top: usize,
96+
entry: extern "C" fn(usize, usize) -> !,
97+
arg: usize,
98+
) -> ! {
99+
sched::run_on_stack_raw(stack_top, entry, arg)
100+
}
101+
102+
pub fn fork_current(entry: extern "C" fn(*const ForkedImage, usize) -> !, arg: usize) {
103+
let mut image = ForkedImage {
104+
rbx: 0,
105+
rbp: 0,
106+
r12: 0,
107+
r13: 0,
108+
r14: 0,
109+
r15: 0,
110+
rsp: 0,
111+
rip: 0,
112+
rflags: 0,
113+
};
114+
115+
unsafe {
116+
asm!(
117+
"mov [{image} + {rbx}], rbx",
118+
"mov [{image} + {rbp}], rbp",
119+
"mov [{image} + {r12}], r12",
120+
"mov [{image} + {r13}], r13",
121+
"mov [{image} + {r14}], r14",
122+
"mov [{image} + {r15}], r15",
123+
"mov [{image} + {rsp}], rsp",
124+
"lea rax, [rip + 2f]",
125+
"mov [{image} + {rip}], rax",
126+
"pushfq",
127+
"pop [{image} + {rflags}]",
128+
"mov rdi, {image}",
129+
"mov rsi, {arg}",
130+
"call {entry}",
131+
"ud2",
132+
"2:",
133+
image = in(reg) &mut image,
134+
arg = in(reg) arg,
135+
entry = in(reg) entry,
136+
rbx = const offset_of!(ForkedImage, rbx),
137+
rbp = const offset_of!(ForkedImage, rbp),
138+
r12 = const offset_of!(ForkedImage, r12),
139+
r13 = const offset_of!(ForkedImage, r13),
140+
r14 = const offset_of!(ForkedImage, r14),
141+
r15 = const offset_of!(ForkedImage, r15),
142+
rsp = const offset_of!(ForkedImage, rsp),
143+
rip = const offset_of!(ForkedImage, rip),
144+
rflags = const offset_of!(ForkedImage, rflags),
145+
out("rax") _,
146+
out("rdi") _,
147+
out("rsi") _,
148+
out("rdx") _,
149+
out("rcx") _,
150+
out("r8") _,
151+
out("r9") _,
152+
out("r10") _,
153+
out("r11") _,
154+
);
155+
}
156+
}

kernel/src/arch/x86_64/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::util::once::Once;
33
mod asm;
44
mod consts;
55
pub mod cpu;
6+
pub mod executor;
67
pub mod irq;
78
pub mod sched;
89
pub mod system;

kernel/src/arch/x86_64/sched.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::{
77
system::{apic::LAPIC, gdt::TSS},
88
};
99
use crate::{
10+
arch::sched::Executor,
1011
irq::lock::IrqLock,
1112
memory::{UserPtr, VirtAddr, stack::KernelStack},
1213
percpu::CpuData,
@@ -19,27 +20,12 @@ use crate::{
1920
sched::Scheduler,
2021
uapi::signal::{SA_ONSTACK, siginfo_t},
2122
};
22-
use alloc::boxed::Box;
2323
use core::{
2424
arch::{asm, naked_asm},
2525
fmt::Write,
2626
mem::offset_of,
2727
};
2828

29-
#[repr(C)]
30-
#[derive(Default, Debug, Clone)]
31-
pub struct TaskContext {
32-
pub rsp: u64,
33-
pub fpu_region: Box<[u8]>,
34-
pub ds: u16,
35-
pub es: u16,
36-
pub fs: u16,
37-
pub gs: u16,
38-
pub fsbase: u64,
39-
pub gsbase: u64,
40-
pub restarted: bool,
41-
}
42-
4329
#[repr(C)]
4430
#[derive(Default, Clone, Copy)]
4531
pub struct Context {
@@ -187,8 +173,8 @@ pub(in crate::arch) unsafe fn switch(from: *const Task, to: *const Task) -> *mut
187173
let from = from.as_ref().unwrap();
188174
let to = to.as_ref().unwrap();
189175

190-
let from_context = &mut *from.task_context.get();
191-
let to_context = &mut *to.task_context.get();
176+
let from_context = &mut *from.executor.get();
177+
let to_context = &mut *to.executor.get();
192178

193179
let cpu = ARCH_DATA.get();
194180
TSS.get().lock().rsp0 = to.kernel_stack.top().into();
@@ -279,7 +265,7 @@ pub(in crate::arch) extern "C" fn run_on_stack_raw(
279265
}
280266

281267
pub(in crate::arch) fn init_task(
282-
context: &mut TaskContext,
268+
context: &mut Executor,
283269
entry: extern "C" fn(usize, usize),
284270
arg1: usize,
285271
arg2: usize,

kernel/src/arch/x86_64/system/smp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ extern "C" fn ap_entry(info: PhysAddr) -> ! {
219219

220220
let reaper_task =
221221
Arc::new(Task::new(sched::reaper_fn, 0, 0, Process::get_kernel(), false).unwrap());
222+
reaper_task.bound.store(true, Ordering::Release);
222223
cpu_ctx.scheduler.set_reaper_task(reaper_task);
223224

224225
// Create a dummy task to drop right after the first reschedule.

0 commit comments

Comments
 (0)