From 06b09f34ed64a006a80ae8df383e3c8b176f02e0 Mon Sep 17 00:00:00 2001 From: kong <45937622+kkkkkong@users.noreply.github.com> Date: Sat, 14 Jan 2023 22:38:05 +0800 Subject: [PATCH] Patch sched rust (#139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * 添加rt调度器的rust初步实现 * 完善rt调度逻辑 * 调试rt调度器 * 修改sched的返回值 * cargo fmt 格式化 * 删除无用代码,修补rt bug * 删除无用的代码,和重复的逻辑 * 软中断bugfix * 删除一些代码 * 添加kthread_run_rt文档 * 解决sphinix警告_static目录不存在的问题 Co-authored-by: longjin --- docs/_static/.gitkeep | 0 docs/kernel/process_management/kthread.md | 12 ++ kernel/src/arch/x86_64/asm/bitops.rs | 2 +- kernel/src/arch/x86_64/asm/mod.rs | 4 +- kernel/src/arch/x86_64/asm/ptrace.rs | 8 +- kernel/src/arch/x86_64/interrupt/mod.rs | 10 +- kernel/src/arch/x86_64/mm/barrier.rs | 14 +- kernel/src/arch/x86_64/mm/mod.rs | 2 +- kernel/src/arch/x86_64/mod.rs | 4 +- kernel/src/common/kthread.h | 17 +++ kernel/src/driver/mod.rs | 2 +- kernel/src/driver/timers/mod.rs | 2 +- kernel/src/driver/timers/rtc/mod.rs | 2 +- kernel/src/driver/uart/uart.rs | 59 ++++---- kernel/src/exception/softirq.h | 4 +- kernel/src/exception/softirq.rs | 4 +- kernel/src/filesystem/devfs/mod.rs | 1 + kernel/src/filesystem/fat32/mod.rs | 1 + kernel/src/filesystem/procfs/mod.rs | 1 + kernel/src/filesystem/rootfs/mod.rs | 1 + kernel/src/filesystem/vfs/mod.rs | 1 + kernel/src/include/bindings/mod.rs | 2 +- kernel/src/include/mod.rs | 2 +- kernel/src/ipc/mod.rs | 2 +- kernel/src/ipc/signal_types.rs | 2 +- kernel/src/libs/atomic.rs | 4 +- kernel/src/libs/ffi_convert.rs | 22 +-- kernel/src/libs/list.rs | 15 +- kernel/src/libs/lockref.rs | 44 +++--- kernel/src/libs/mod.rs | 6 +- kernel/src/libs/refcount.rs | 30 ++-- kernel/src/libs/wait_queue.rs | 14 +- kernel/src/mm/allocator.rs | 2 +- kernel/src/process/initial_proc.rs | 3 +- kernel/src/process/mod.rs | 8 +- kernel/src/process/pid.rs | 6 +- kernel/src/process/proc-types.h | 1 + kernel/src/process/process.c | 24 ++- kernel/src/process/process.rs | 4 +- kernel/src/sched/cfs.rs | 28 ++-- kernel/src/sched/core.rs | 51 ++++++- kernel/src/sched/mod.rs | 3 +- kernel/src/sched/rt.rs | 173 ++++++++++++++++++++++ kernel/src/smp/mod.rs | 2 +- 44 files changed, 426 insertions(+), 173 deletions(-) create mode 100644 docs/_static/.gitkeep create mode 100644 kernel/src/sched/rt.rs diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/kernel/process_management/kthread.md b/docs/kernel/process_management/kthread.md index 270bf4e5..58042e80 100644 --- a/docs/kernel/process_management/kthread.md +++ b/docs/kernel/process_management/kthread.md @@ -62,6 +62,18 @@   该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。 +### kthread_run_rt() + +#### 原型 + +  `kthread_run_rt(thread_fn, data, name_fmt, ...)` + +#### 简介 + +  创建内核实时线程并加入调度队列。 + +  类似`kthread_run()`,该宏定义也是`kthread_create()`的简单封装,提供创建了内核实时线程后,在设置实时进程的参数后,立即运行的功能。 + ## 停止内核线程 ### kthread_stop() diff --git a/kernel/src/arch/x86_64/asm/bitops.rs b/kernel/src/arch/x86_64/asm/bitops.rs index 9368db25..7eb7c06c 100644 --- a/kernel/src/arch/x86_64/asm/bitops.rs +++ b/kernel/src/arch/x86_64/asm/bitops.rs @@ -2,7 +2,7 @@ use core::arch::x86_64::_popcnt64; /// @brief ffz - 寻找u64中的第一个0所在的位(从第0位开始寻找) /// 请注意,如果x中没有0,那么结果将是未定义的。请确保传入的x至少存在1个0 -/// +/// /// @param x 目标u64 /// @return i32 bit-number(0..63) of the first (least significant) zero bit. #[inline] diff --git a/kernel/src/arch/x86_64/asm/mod.rs b/kernel/src/arch/x86_64/asm/mod.rs index 84c2473a..dae9eda1 100644 --- a/kernel/src/arch/x86_64/asm/mod.rs +++ b/kernel/src/arch/x86_64/asm/mod.rs @@ -1,6 +1,6 @@ pub mod irqflags; #[macro_use] pub mod current; -pub mod ptrace; pub mod bitops; -pub mod cmpxchg; \ No newline at end of file +pub mod cmpxchg; +pub mod ptrace; diff --git a/kernel/src/arch/x86_64/asm/ptrace.rs b/kernel/src/arch/x86_64/asm/ptrace.rs index d5faba63..1a9fed17 100644 --- a/kernel/src/arch/x86_64/asm/ptrace.rs +++ b/kernel/src/arch/x86_64/asm/ptrace.rs @@ -3,10 +3,10 @@ use crate::include::bindings::bindings::pt_regs; /// @brief 判断给定的栈帧是否来自用户态 /// 判断方法为:根据代码段选择子是否具有ring3的访问权限(低2bit均为1) -pub fn user_mode(regs: *const pt_regs)->bool{ - if (unsafe{(*regs).cs} & 0x3) != 0{ +pub fn user_mode(regs: *const pt_regs) -> bool { + if (unsafe { (*regs).cs } & 0x3) != 0 { return true; - }else { + } else { return false; } -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/interrupt/mod.rs b/kernel/src/arch/x86_64/interrupt/mod.rs index 909948f0..88ec1abf 100644 --- a/kernel/src/arch/x86_64/interrupt/mod.rs +++ b/kernel/src/arch/x86_64/interrupt/mod.rs @@ -3,16 +3,16 @@ use core::arch::asm; /// @brief 关闭中断 #[inline] -pub fn cli(){ - unsafe{ +pub fn cli() { + unsafe { asm!("cli"); } } /// @brief 开启中断 #[inline] -pub fn sti(){ - unsafe{ +pub fn sti() { + unsafe { asm!("sti"); } -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/mm/barrier.rs b/kernel/src/arch/x86_64/mm/barrier.rs index bd211435..2ef11a9d 100644 --- a/kernel/src/arch/x86_64/mm/barrier.rs +++ b/kernel/src/arch/x86_64/mm/barrier.rs @@ -2,22 +2,22 @@ use core::arch::asm; #[inline(always)] -pub fn mfence(){ - unsafe{ +pub fn mfence() { + unsafe { asm!("mfence"); } } #[inline(always)] -pub fn lfence(){ - unsafe{ +pub fn lfence() { + unsafe { asm!("lfence"); } } #[inline(always)] -pub fn sfence(){ - unsafe{ +pub fn sfence() { + unsafe { asm!("sfence"); } -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index ee97f2e3..bda00b3f 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -19,7 +19,7 @@ pub fn switch_mm( mfence(); // kdebug!("to get pml4t"); let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) }; - + unsafe { asm!("mov cr3, {}", in(reg) pml4t); } diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 3c028dd8..0df59e68 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,7 +1,7 @@ #[macro_use] pub mod asm; +pub mod context; pub mod cpu; pub mod interrupt; pub mod mm; -pub mod context; -pub mod sched; \ No newline at end of file +pub mod sched; diff --git a/kernel/src/common/kthread.h b/kernel/src/common/kthread.h index 440066f6..30dba8ca 100644 --- a/kernel/src/common/kthread.h +++ b/kernel/src/common/kthread.h @@ -54,6 +54,23 @@ struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data __kt; \ }) +/** + * @brief 创建内核实时线程,并将其唤醒 + * + * @param thread_fn 该内核线程要执行的函数 + * @param data 传递给 thread_fn 的参数数据 + * @param name_fmt printf-style format string for the thread name + * @param arg name_fmt的参数 + */ +#define kthread_run_rt(thread_fn, data, name_fmt, ...) \ + ({ \ + struct process_control_block *__kt = kthread_create(thread_fn, data, name_fmt, ##__VA_ARGS__); \ + __kt=process_init_rt_pcb(__kt); \ + if (!IS_ERR(__kt)){ \ + process_wakeup(__kt);} \ + __kt; \ + }) + /** * @brief 向kthread发送停止信号,请求其结束 * diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index e15146ed..4b1cb990 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,2 +1,2 @@ -pub mod uart; pub mod timers; +pub mod uart; diff --git a/kernel/src/driver/timers/mod.rs b/kernel/src/driver/timers/mod.rs index db221127..2f5f4717 100644 --- a/kernel/src/driver/timers/mod.rs +++ b/kernel/src/driver/timers/mod.rs @@ -1 +1 @@ -pub mod rtc; \ No newline at end of file +pub mod rtc; diff --git a/kernel/src/driver/timers/rtc/mod.rs b/kernel/src/driver/timers/rtc/mod.rs index db221127..2f5f4717 100644 --- a/kernel/src/driver/timers/rtc/mod.rs +++ b/kernel/src/driver/timers/rtc/mod.rs @@ -1 +1 @@ -pub mod rtc; \ No newline at end of file +pub mod rtc; diff --git a/kernel/src/driver/uart/uart.rs b/kernel/src/driver/uart/uart.rs index db6afae7..95e7de36 100644 --- a/kernel/src/driver/uart/uart.rs +++ b/kernel/src/driver/uart/uart.rs @@ -1,5 +1,5 @@ use crate::include::bindings::bindings::{io_in8, io_out8}; -use core::{str, char, intrinsics::offset}; +use core::{char, intrinsics::offset, str}; const UART_SUCCESS: i32 = 0; const E_UART_BITS_RATE_ERROR: i32 = 1; @@ -63,7 +63,7 @@ impl UartPort { struct UartRegister { reg_data: u8, reg_interrupt_enable: u8, - reg_ii_fifo: u8, // Interrupt Identification and FIFO control registers + reg_ii_fifo: u8, // Interrupt Identification and FIFO control registers reg_line_config: u8, reg_modem_config: u8, reg_line_status: u8, @@ -79,7 +79,10 @@ pub struct UartDriver { impl Default for UartDriver { fn default() -> Self { - Self {port: UartPort::COM1, baud_rate: 115200} + Self { + port: UartPort::COM1, + baud_rate: 115200, + } } } @@ -96,26 +99,26 @@ impl UartDriver { if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 { return Err("uart init error."); } - + unsafe { io_out8(port + 1, 0x00); // Disable all interrupts io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) - + let divisor = UART_MAX_BITS_RATE / baud_rate; - - io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) + + io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte) - io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit - io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit + io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR) io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) - + // Check if serial is faulty (i.e: not same byte as sent) if io_in8(port + 0) != 0xAE { return Err("uart faulty"); } - + // If serial is not faulty set it in normal operation mode // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) io_out8(port + 4, 0x08); @@ -133,15 +136,15 @@ impl UartDriver { } fn serial_received(offset: u16) -> bool { - if unsafe{ io_in8(offset + 5) } & 1 != 0 { + if unsafe { io_in8(offset + 5) } & 1 != 0 { true } else { false } } - + fn is_transmit_empty(offset: u16) -> bool { - if unsafe{ io_in8(offset + 5) } & 0x20 != 0 { + if unsafe { io_in8(offset + 5) } & 0x20 != 0 { true } else { false @@ -157,11 +160,13 @@ impl UartDriver { let port = uart_port.to_u16(); while UartDriver::is_transmit_empty(port) == false { for c in str.bytes() { - unsafe { io_out8(port, c); } + unsafe { + io_out8(port, c); + } } } //TODO:pause } - + /// @brief 串口接收一个字节 /// @param uart_port 端口号 /// @return 接收的字节 @@ -171,7 +176,6 @@ impl UartDriver { while UartDriver::serial_received(port) == false {} //TODO:pause unsafe { io_in8(port) as char } } - } ///@brief 发送数据 @@ -180,7 +184,9 @@ impl UartDriver { #[no_mangle] pub extern "C" fn c_uart_send(port: u16, c: u8) { while UartDriver::is_transmit_empty(port) == false {} //TODO:pause - unsafe { io_out8(port, c); } + unsafe { + io_out8(port, c); + } } ///@brief 从uart接收数据 @@ -196,8 +202,7 @@ pub extern "C" fn c_uart_read(port: u16) -> u8 { ///@param port 串口端口 ///@param str 字符串S #[no_mangle] -pub extern "C" fn c_uart_send_str(port: u16, str: *const u8) -{ +pub extern "C" fn c_uart_send_str(port: u16, str: *const u8) { unsafe { let mut i = 0; while *offset(str, i) != '\0' as u8 { @@ -222,22 +227,22 @@ pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 { unsafe { io_out8(port + 1, 0x00); // Disable all interrupts io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) - + let divisor = UART_MAX_BITS_RATE / baud_rate; - - io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) + + io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor (lo byte) io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte) - io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit - io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit + io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR) io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) - + // Check if serial is faulty (i.e: not same byte as sent) if io_in8(port + 0) != 0xAE { return -E_UART_SERIAL_FAULT; } - + // If serial is not faulty set it in normal operation mode // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) io_out8(port + 4, 0x08); diff --git a/kernel/src/exception/softirq.h b/kernel/src/exception/softirq.h index 2932674a..5f811260 100644 --- a/kernel/src/exception/softirq.h +++ b/kernel/src/exception/softirq.h @@ -14,11 +14,9 @@ // ==================implementation with rust=================== extern void softirq_init(); -extern void raise_softirq(uint64_t sirq_num); +extern void raise_softirq(uint32_t sirq_num); extern int register_softirq(uint32_t irq_num, void (*action)(void *data), void *data); extern int unregister_softirq(uint32_t irq_num); -extern void set_softirq_pending(uint64_t status); -extern void clear_softirq_pending(uint32_t irq_num); extern void do_softirq(); // for temporary diff --git a/kernel/src/exception/softirq.rs b/kernel/src/exception/softirq.rs index e211cd49..791a7d4c 100644 --- a/kernel/src/exception/softirq.rs +++ b/kernel/src/exception/softirq.rs @@ -66,9 +66,9 @@ pub fn __get_softirq_handler_mut() -> &'static mut Softirq { #[no_mangle] #[allow(dead_code)] -pub extern "C" fn raise_softirq(sirq_num: u64) { +pub extern "C" fn raise_softirq(sirq_num: u32) { let softirq_handler = __get_softirq_handler_mut(); - softirq_handler.set_softirq_pending(1 << sirq_num); + softirq_handler.set_softirq_pending(sirq_num); } /// @brief 软中断注册函数 diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index e69de29b..8b137891 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -0,0 +1 @@ + diff --git a/kernel/src/filesystem/fat32/mod.rs b/kernel/src/filesystem/fat32/mod.rs index e69de29b..8b137891 100644 --- a/kernel/src/filesystem/fat32/mod.rs +++ b/kernel/src/filesystem/fat32/mod.rs @@ -0,0 +1 @@ + diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index e69de29b..8b137891 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -0,0 +1 @@ + diff --git a/kernel/src/filesystem/rootfs/mod.rs b/kernel/src/filesystem/rootfs/mod.rs index e69de29b..8b137891 100644 --- a/kernel/src/filesystem/rootfs/mod.rs +++ b/kernel/src/filesystem/rootfs/mod.rs @@ -0,0 +1 @@ + diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index e69de29b..8b137891 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -0,0 +1 @@ + diff --git a/kernel/src/include/bindings/mod.rs b/kernel/src/include/bindings/mod.rs index 44946577..90c70dcc 100644 --- a/kernel/src/include/bindings/mod.rs +++ b/kernel/src/include/bindings/mod.rs @@ -1 +1 @@ -pub mod bindings; \ No newline at end of file +pub mod bindings; diff --git a/kernel/src/include/mod.rs b/kernel/src/include/mod.rs index b9da6e6e..c94bf0a6 100644 --- a/kernel/src/include/mod.rs +++ b/kernel/src/include/mod.rs @@ -1,2 +1,2 @@ #![allow(non_snake_case)] -pub mod bindings; \ No newline at end of file +pub mod bindings; diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 00f0754e..40bec6c3 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,2 +1,2 @@ pub mod signal; -pub mod signal_types; \ No newline at end of file +pub mod signal_types; diff --git a/kernel/src/ipc/signal_types.rs b/kernel/src/ipc/signal_types.rs index 2c1d0490..6f29980e 100644 --- a/kernel/src/ipc/signal_types.rs +++ b/kernel/src/ipc/signal_types.rs @@ -546,7 +546,7 @@ impl SigQueue { } /// @brief 从C的void*指针转换为static生命周期的可变引用 - pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue{ + pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue { let sq = p as *mut SigQueue; let sq = unsafe { sq.as_mut::<'static>() }.unwrap(); return sq; diff --git a/kernel/src/libs/atomic.rs b/kernel/src/libs/atomic.rs index ac5eb5b4..6e942167 100644 --- a/kernel/src/libs/atomic.rs +++ b/kernel/src/libs/atomic.rs @@ -13,8 +13,8 @@ pub fn atomic_read(ato: *const atomic_t) -> i64 { /// @brief 原子的设置原子变量的值 #[inline] -pub fn atomic_set(ato: *mut atomic_t, value:i64) { - unsafe{ +pub fn atomic_set(ato: *mut atomic_t, value: i64) { + unsafe { write_volatile(&mut (*ato).value, value); } } diff --git a/kernel/src/libs/ffi_convert.rs b/kernel/src/libs/ffi_convert.rs index 97f13f40..4e39d51a 100644 --- a/kernel/src/libs/ffi_convert.rs +++ b/kernel/src/libs/ffi_convert.rs @@ -6,24 +6,10 @@ pub trait FFIBind2Rust { fn convert_mut(src: *mut T) -> Option<&'static mut Self>; } - - -pub fn __convert_mut<'a, S, D>(src:*mut S) ->Option<&'a mut D>{ - return unsafe { - core::mem::transmute::< - *mut S, - *mut D, - >(src) - .as_mut() - }; +pub fn __convert_mut<'a, S, D>(src: *mut S) -> Option<&'a mut D> { + return unsafe { core::mem::transmute::<*mut S, *mut D>(src).as_mut() }; } -pub fn __convert_ref<'a, S, D>(src:*const S) ->Option<&'a D>{ - return unsafe { - core::mem::transmute::< - *const S, - *const D, - >(src) - .as_ref() - }; +pub fn __convert_ref<'a, S, D>(src: *const S) -> Option<&'a D> { + return unsafe { core::mem::transmute::<*const S, *const D>(src).as_ref() }; } diff --git a/kernel/src/libs/list.rs b/kernel/src/libs/list.rs index 6f324e6d..b39c38d9 100644 --- a/kernel/src/libs/list.rs +++ b/kernel/src/libs/list.rs @@ -3,13 +3,16 @@ use crate::include::bindings::bindings::List; /// @brief 初始化链表 #[inline] pub fn list_init(list: *mut List) { - unsafe{*list}.prev = list; - unsafe{*list}.next = list; + unsafe { *list }.prev = list; + unsafe { *list }.next = list; } -impl Default for List{ +impl Default for List { fn default() -> Self { - let x= Self { prev: 0 as *mut List, next: 0 as *mut List }; - return x; + let x = Self { + prev: 0 as *mut List, + next: 0 as *mut List, + }; + return x; } -} \ No newline at end of file +} diff --git a/kernel/src/libs/lockref.rs b/kernel/src/libs/lockref.rs index d1c36169..81b8950f 100644 --- a/kernel/src/libs/lockref.rs +++ b/kernel/src/libs/lockref.rs @@ -324,32 +324,32 @@ impl LockRef { } /* - * 您可以使用以下代码测试lockref +* 您可以使用以下代码测试lockref - let mut lockref = LockRef::new(); - kdebug!("lockref={:?}", lockref); - lockref.inc(); - assert_eq!(lockref.count, 1); - kdebug!("lockref={:?}", lockref); - assert!(lockref.dec().is_ok()); - assert_eq!(lockref.count, 0); + let mut lockref = LockRef::new(); + kdebug!("lockref={:?}", lockref); + lockref.inc(); + assert_eq!(lockref.count, 1); + kdebug!("lockref={:?}", lockref); + assert!(lockref.dec().is_ok()); + assert_eq!(lockref.count, 0); - assert!(lockref.dec().is_err()); - assert_eq!(lockref.count, 0); + assert!(lockref.dec().is_err()); + assert_eq!(lockref.count, 0); - lockref.inc(); - assert_eq!(lockref.count, 1); + lockref.inc(); + assert_eq!(lockref.count, 1); - assert!(lockref.dec_not_zero().is_err()); + assert!(lockref.dec_not_zero().is_err()); - lockref.inc(); - assert_eq!(lockref.count, 2); + lockref.inc(); + assert_eq!(lockref.count, 2); - assert!(lockref.dec_not_zero().is_ok()); + assert!(lockref.dec_not_zero().is_ok()); - lockref.mark_dead(); - assert!(lockref.count < 0); - - assert!(lockref.inc_not_dead().is_err()); - kdebug!("lockref={:?}", lockref); - */ \ No newline at end of file + lockref.mark_dead(); + assert!(lockref.count < 0); + + assert!(lockref.inc_not_dead().is_err()); + kdebug!("lockref={:?}", lockref); +*/ diff --git a/kernel/src/libs/mod.rs b/kernel/src/libs/mod.rs index 620fa802..4e948958 100644 --- a/kernel/src/libs/mod.rs +++ b/kernel/src/libs/mod.rs @@ -1,9 +1,9 @@ +pub mod ffi_convert; pub mod printk; pub mod spinlock; -pub mod ffi_convert; #[macro_use] pub mod refcount; pub mod atomic; -pub mod wait_queue; pub mod list; -pub mod lockref; \ No newline at end of file +pub mod lockref; +pub mod wait_queue; diff --git a/kernel/src/libs/refcount.rs b/kernel/src/libs/refcount.rs index 7f63e8f9..8e83939e 100644 --- a/kernel/src/libs/refcount.rs +++ b/kernel/src/libs/refcount.rs @@ -1,20 +1,28 @@ -use crate::{include::bindings::bindings::{atomic_inc, atomic_t, atomic_dec}, kwarn}; +use crate::{ + include::bindings::bindings::{atomic_dec, atomic_inc, atomic_t}, + kwarn, +}; -use super::{ffi_convert::{FFIBind2Rust, __convert_mut, __convert_ref}, atomic::atomic_read}; +use super::{ + atomic::atomic_read, + ffi_convert::{FFIBind2Rust, __convert_mut, __convert_ref}, +}; #[derive(Debug, Copy, Clone)] pub struct RefCount { pub refs: atomic_t, } -impl Default for RefCount{ +impl Default for RefCount { fn default() -> Self { - Self { refs: atomic_t { value: 1 }} + Self { + refs: atomic_t { value: 1 }, + } } } /// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用 -impl FFIBind2Rust for RefCount{ +impl FFIBind2Rust for RefCount { fn convert_mut( src: *mut crate::include::bindings::bindings::refcount_struct, ) -> Option<&'static mut Self> { @@ -23,7 +31,7 @@ impl FFIBind2Rust for RefCo fn convert_ref( src: *const crate::include::bindings::bindings::refcount_struct, ) -> Option<&'static Self> { - return __convert_ref(src) + return __convert_ref(src); } } @@ -40,10 +48,10 @@ macro_rules! REFCOUNT_INIT { #[allow(dead_code)] #[inline] pub fn refcount_inc(r: &mut RefCount) { - if atomic_read(&r.refs) == 0{ + if atomic_read(&r.refs) == 0 { kwarn!("Refcount increased from 0, may be use-after free"); } - + unsafe { atomic_inc(&mut r.refs); } @@ -52,10 +60,8 @@ pub fn refcount_inc(r: &mut RefCount) { /// @brief 引用计数自减1 #[allow(dead_code)] #[inline] -pub fn refcount_dec(r: &mut RefCount){ - unsafe{ +pub fn refcount_dec(r: &mut RefCount) { + unsafe { atomic_dec(&mut r.refs); } } - - diff --git a/kernel/src/libs/wait_queue.rs b/kernel/src/libs/wait_queue.rs index 230c235c..2f308288 100644 --- a/kernel/src/libs/wait_queue.rs +++ b/kernel/src/libs/wait_queue.rs @@ -1,12 +1,14 @@ -use crate::include::bindings::bindings::{wait_queue_head_t}; +use crate::include::bindings::bindings::wait_queue_head_t; -use super::{list::list_init}; +use super::list::list_init; - -impl Default for wait_queue_head_t{ +impl Default for wait_queue_head_t { fn default() -> Self { - let mut x = Self { wait_list: Default::default(), lock: Default::default() }; + let mut x = Self { + wait_list: Default::default(), + lock: Default::default(), + }; list_init(&mut x.wait_list); return x; } -} \ No newline at end of file +} diff --git a/kernel/src/mm/allocator.rs b/kernel/src/mm/allocator.rs index 1078812b..4bee32b7 100644 --- a/kernel/src/mm/allocator.rs +++ b/kernel/src/mm/allocator.rs @@ -1,5 +1,5 @@ -use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE}; use super::gfp::__GFP_ZERO; +use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE}; use core::alloc::{GlobalAlloc, Layout}; diff --git a/kernel/src/process/initial_proc.rs b/kernel/src/process/initial_proc.rs index 1f76be7f..ecfedf07 100644 --- a/kernel/src/process/initial_proc.rs +++ b/kernel/src/process/initial_proc.rs @@ -26,10 +26,9 @@ pub static mut INITIAL_SIGHAND: sighand_struct = sighand_struct { /// @brief 初始化pid=0的进程的信号相关的信息 #[no_mangle] pub extern "C" fn initial_proc_init_signal(pcb: *mut process_control_block) { - // 所设置的pcb的pid一定为0 assert_eq!(unsafe { (*pcb).pid }, 0); - + // 设置init进程的sighand和signal unsafe { (*pcb).sighand = &mut INITIAL_SIGHAND as *mut sighand_struct as usize diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 1b7c5b40..04005642 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -1,5 +1,5 @@ -pub mod pid; -pub mod process; -pub mod preempt; +pub mod fork; pub mod initial_proc; -pub mod fork; \ No newline at end of file +pub mod pid; +pub mod preempt; +pub mod process; diff --git a/kernel/src/process/pid.rs b/kernel/src/process/pid.rs index 245adb87..8cbb1771 100644 --- a/kernel/src/process/pid.rs +++ b/kernel/src/process/pid.rs @@ -1,4 +1,4 @@ -use crate::{include::bindings::bindings::pt_regs, arch::asm::current::current_pcb}; +use crate::{arch::asm::current::current_pcb, include::bindings::bindings::pt_regs}; #[allow(dead_code)] #[derive(Debug, Clone, Copy)] @@ -23,6 +23,6 @@ impl PartialEq for PidType { * @brief 获取当前进程的pid */ #[no_mangle] -pub extern "C" fn sys_getpid(_regs: &pt_regs)->u64{ +pub extern "C" fn sys_getpid(_regs: &pt_regs) -> u64 { return current_pcb().pid as u64; -} \ No newline at end of file +} diff --git a/kernel/src/process/proc-types.h b/kernel/src/process/proc-types.h index d6c4ba11..0d6f4a99 100644 --- a/kernel/src/process/proc-types.h +++ b/kernel/src/process/proc-types.h @@ -105,6 +105,7 @@ struct process_control_block long pid; long priority; // 优先级 int64_t virtual_runtime; // 虚拟运行时间 + int64_t rt_time_slice; // 由实时调度器管理的时间片 // 进程拥有的文件描述符的指针数组 // todo: 改用动态指针数组 diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c index b795f55e..81ae4bc9 100644 --- a/kernel/src/process/process.c +++ b/kernel/src/process/process.c @@ -409,7 +409,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]) // 关闭之前的文件描述符 process_exit_files(current_pcb); - + process_open_stdio(current_pcb); // 清除进程的vfork标志位 @@ -469,6 +469,22 @@ exec_failed:; } #pragma GCC pop_options +/** + * @brief 初始化实时进程rt_pcb + * + * @return 初始化后的进程 + * + */ +struct process_control_block *process_init_rt_pcb(struct process_control_block *rt_pcb) +{ + // 暂时将实时进程的优先级设置为10 + rt_pcb->priority = 10; + rt_pcb->policy = SCHED_RR; + rt_pcb->rt_time_slice = 80; + rt_pcb->virtual_runtime = 0x7fffffffffffffff; + return rt_pcb; +} + /** * @brief 内核init进程 * @@ -508,6 +524,12 @@ ul initial_kernel_thread(ul arg) // waitpid(tpid[i], NULL, NULL); // kinfo("All test done."); + // 测试实时进程 + + // struct process_control_block *test_rt1 = kthread_run_rt(&test, NULL, "test rt"); + // kdebug("process:rt test kthread is created!!!!"); + + // 准备切换到用户态 struct pt_regs *regs; diff --git a/kernel/src/process/process.rs b/kernel/src/process/process.rs index 8fbcd248..c3722da6 100644 --- a/kernel/src/process/process.rs +++ b/kernel/src/process/process.rs @@ -2,9 +2,7 @@ use core::ptr::{read_volatile, write_volatile}; use crate::{ arch::asm::current::current_pcb, - include::bindings::bindings::{ - process_control_block, PROC_RUNNING, PROC_STOPPED, - }, + include::bindings::bindings::{process_control_block, PROC_RUNNING, PROC_STOPPED}, sched::core::{cpu_executing, sched_enqueue}, smp::core::{smp_get_processor_id, smp_send_reschedule}, }; diff --git a/kernel/src/sched/cfs.rs b/kernel/src/sched/cfs.rs index 399e9c77..91d5871f 100644 --- a/kernel/src/sched/cfs.rs +++ b/kernel/src/sched/cfs.rs @@ -1,24 +1,17 @@ -use core::{ - ptr::null_mut, - sync::atomic::compiler_fence, -}; +use core::{ptr::null_mut, sync::atomic::compiler_fence}; use alloc::{boxed::Box, vec::Vec}; use crate::{ - arch::{ - asm::current::current_pcb, - context::switch_process, - }, + arch::asm::current::current_pcb, include::bindings::bindings::{ - initial_proc_union, process_control_block, MAX_CPU_NUM, PF_NEED_SCHED, - PROC_RUNNING, + initial_proc_union, process_control_block, MAX_CPU_NUM, PF_NEED_SCHED, PROC_RUNNING, }, kBUG, libs::spinlock::RawSpinlock, }; -use super::core::Scheduler; +use super::core::{sched_enqueue, Scheduler}; /// 声明全局的cfs调度器实例 @@ -149,8 +142,7 @@ impl SchedulerCFS { impl Scheduler for SchedulerCFS { /// @brief 在当前cpu上进行调度。 /// 请注意,进入该函数之前,需要关中断 - fn sched(&mut self) { - // kdebug!("cfs:sched"); + fn sched(&mut self) -> Option<&'static mut process_control_block> { current_pcb().flags &= !(PF_NEED_SCHED as u64); let current_cpu_id = current_pcb().cpu_id as usize; let current_cpu_queue: &mut CFSQueue = self.cpu_queue[current_cpu_id]; @@ -163,8 +155,7 @@ impl Scheduler for SchedulerCFS { compiler_fence(core::sync::atomic::Ordering::SeqCst); // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 if current_pcb().state & (PROC_RUNNING as u64) != 0 { - // kdebug!("cfs:sched->enqueue"); - current_cpu_queue.enqueue(current_pcb()); + sched_enqueue(current_pcb()); compiler_fence(core::sync::atomic::Ordering::SeqCst); } @@ -175,9 +166,7 @@ impl Scheduler for SchedulerCFS { } compiler_fence(core::sync::atomic::Ordering::SeqCst); - - switch_process(current_pcb(), proc); - compiler_fence(core::sync::atomic::Ordering::SeqCst); + return Some(proc); } else { // 不进行切换 @@ -188,10 +177,11 @@ impl Scheduler for SchedulerCFS { } compiler_fence(core::sync::atomic::Ordering::SeqCst); - current_cpu_queue.enqueue(proc); + sched_enqueue(proc); compiler_fence(core::sync::atomic::Ordering::SeqCst); } compiler_fence(core::sync::atomic::Ordering::SeqCst); + return None; } fn enqueue(&mut self, pcb: &'static mut process_control_block) { diff --git a/kernel/src/sched/core.rs b/kernel/src/sched/core.rs index 2d805999..b96bb99f 100644 --- a/kernel/src/sched/core.rs +++ b/kernel/src/sched/core.rs @@ -2,11 +2,16 @@ use core::sync::atomic::compiler_fence; use crate::{ arch::asm::{current::current_pcb, ptrace::user_mode}, - include::bindings::bindings::{process_control_block, pt_regs, EPERM, SCHED_NORMAL}, + arch::context::switch_process, + include::bindings::bindings::{ + process_control_block, pt_regs, EPERM, PROC_RUNNING, SCHED_FIFO, SCHED_NORMAL, SCHED_RR, + }, + kdebug, process::process::process_cpu, }; use super::cfs::{sched_cfs_init, SchedulerCFS, __get_cfs_scheduler}; +use super::rt::{sched_rt_init, SchedulerRT, __get_rt_scheduler}; /// @brief 获取指定的cpu上正在执行的进程的pcb #[inline] @@ -23,28 +28,50 @@ pub fn cpu_executing(cpu_id: u32) -> &'static mut process_control_block { /// @brief 具体的调度器应当实现的trait pub trait Scheduler { /// @brief 使用该调度器发起调度的时候,要调用的函数 - fn sched(&mut self); + fn sched(&mut self) -> Option<&'static mut process_control_block>; /// @brief 将pcb加入这个调度器的调度队列 fn enqueue(&mut self, pcb: &'static mut process_control_block); } -fn __sched() { +fn __sched() -> Option<&'static mut process_control_block> { compiler_fence(core::sync::atomic::Ordering::SeqCst); let cfs_scheduler: &mut SchedulerCFS = __get_cfs_scheduler(); + let rt_scheduler: &mut SchedulerRT = __get_rt_scheduler(); compiler_fence(core::sync::atomic::Ordering::SeqCst); - cfs_scheduler.sched(); - - compiler_fence(core::sync::atomic::Ordering::SeqCst); + let next: &'static mut process_control_block; + match rt_scheduler.pick_next_task_rt() { + Some(p) => { + next = p; + // kdebug!("next pcb is {}",next.pid); + // rt_scheduler.enqueue_task_rt(next.priority as usize, next); + sched_enqueue(next); + return rt_scheduler.sched(); + } + None => { + return cfs_scheduler.sched(); + } + } } /// @brief 将进程加入调度队列 #[allow(dead_code)] #[no_mangle] pub extern "C" fn sched_enqueue(pcb: &'static mut process_control_block) { + // 调度器不处理running位为0的进程 + if pcb.state & (PROC_RUNNING as u64) == 0 { + return; + } let cfs_scheduler = __get_cfs_scheduler(); - cfs_scheduler.enqueue(pcb); + let rt_scheduler = __get_rt_scheduler(); + if pcb.policy == SCHED_NORMAL { + cfs_scheduler.enqueue(pcb); + } else if pcb.policy == SCHED_FIFO || pcb.policy == SCHED_RR { + rt_scheduler.enqueue(pcb); + } else { + panic!("This policy is not supported at this time"); + } } /// @brief 初始化进程调度器模块 @@ -53,6 +80,7 @@ pub extern "C" fn sched_enqueue(pcb: &'static mut process_control_block) { pub extern "C" fn sched_init() { unsafe { sched_cfs_init(); + sched_rt_init(); } } @@ -65,6 +93,9 @@ pub extern "C" fn sched_update_jiffies() { SCHED_NORMAL => { __get_cfs_scheduler().timer_update_jiffies(); } + SCHED_FIFO | SCHED_RR => { + current_pcb().rt_time_slice -= 1; + } _ => { todo!() } @@ -80,6 +111,10 @@ pub extern "C" fn sys_sched(regs: &'static mut pt_regs) -> u64 { if user_mode(regs) { return (-(EPERM as i64)) as u64; } - __sched(); + // 根据调度结果统一进行切换 + let pcb = __sched(); + if pcb.is_some() { + switch_process(current_pcb(), pcb.unwrap()); + } 0 } diff --git a/kernel/src/sched/mod.rs b/kernel/src/sched/mod.rs index f714a594..9851454a 100644 --- a/kernel/src/sched/mod.rs +++ b/kernel/src/sched/mod.rs @@ -1,2 +1,3 @@ +pub mod cfs; pub mod core; -pub mod cfs; \ No newline at end of file +pub mod rt; diff --git a/kernel/src/sched/rt.rs b/kernel/src/sched/rt.rs new file mode 100644 index 00000000..08e7484e --- /dev/null +++ b/kernel/src/sched/rt.rs @@ -0,0 +1,173 @@ +use core::{ptr::null_mut, sync::atomic::compiler_fence}; + +use alloc::{boxed::Box, vec::Vec}; + +use crate::{ + arch::asm::current::current_pcb, + include::bindings::bindings::{ + initial_proc_union, process_control_block, PF_NEED_SCHED, SCHED_FIFO, SCHED_NORMAL, + SCHED_RR, + }, + kBUG, kdebug, + libs::spinlock::RawSpinlock, +}; + +use super::core::{sched_enqueue, Scheduler}; + +/// 声明全局的rt调度器实例 + +pub static mut RT_SCHEDULER_PTR: *mut SchedulerRT = null_mut(); + +/// @brief 获取rt调度器实例的可变引用 +#[inline] +pub fn __get_rt_scheduler() -> &'static mut SchedulerRT { + return unsafe { RT_SCHEDULER_PTR.as_mut().unwrap() }; +} + +/// @brief 初始化rt调度器 +pub unsafe fn sched_rt_init() { + kdebug!("test rt init"); + if RT_SCHEDULER_PTR.is_null() { + RT_SCHEDULER_PTR = Box::leak(Box::new(SchedulerRT::new())); + } else { + kBUG!("Try to init RT Scheduler twice."); + panic!("Try to init RT Scheduler twice."); + } +} + +/// @brief RT队列(per-cpu的) +#[derive(Debug)] +struct RTQueue { + /// 队列的锁 + lock: RawSpinlock, + /// 进程的队列 + queue: Vec<&'static mut process_control_block>, +} + +impl RTQueue { + pub fn new() -> RTQueue { + RTQueue { + queue: Vec::new(), + lock: RawSpinlock::INIT, + } + } + /// @brief 将pcb加入队列 + pub fn enqueue(&mut self, pcb: &'static mut process_control_block) { + self.lock.lock(); + + // 如果进程是IDLE进程,那么就不加入队列 + if pcb.pid == 0 { + self.lock.unlock(); + return; + } + self.queue.push(pcb); + self.lock.unlock(); + } + + /// @brief 将pcb从调度队列中弹出,若队列为空,则返回None + pub fn dequeue(&mut self) -> Option<&'static mut process_control_block> { + let res: Option<&'static mut process_control_block>; + self.lock.lock(); + if self.queue.len() > 0 { + // 队列不为空,返回下一个要执行的pcb + res = Some(self.queue.pop().unwrap()); + } else { + // 如果队列为空,则返回None + res=None; + } + self.lock.unlock(); + return res; + } + +} + +/// @brief RT调度器类 +pub struct SchedulerRT { + cpu_queue: Vec<&'static mut RTQueue>, +} + +impl SchedulerRT { + const RR_TIMESLICE: i64 = 100; + const MAX_RT_PRIO: i64 = 100; + + pub fn new() -> SchedulerRT { + // 暂时手动指定核心数目 + // todo: 从cpu模块来获取核心的数目 + let mut result = SchedulerRT { + cpu_queue: Default::default(), + }; + + // 为每个cpu核心创建队列 + for _ in 0..SchedulerRT::MAX_RT_PRIO { + result.cpu_queue.push(Box::leak(Box::new(RTQueue::new()))); + } + return result; + } + /// @brief 挑选下一个可执行的rt进程 + pub fn pick_next_task_rt(&mut self) -> Option<&'static mut process_control_block> { + // 循环查找,直到找到 + // 这里应该是优先级数量,而不是CPU数量,需要修改 + for i in 0..SchedulerRT::MAX_RT_PRIO { + let cpu_queue_i: &mut RTQueue = self.cpu_queue[i as usize]; + let proc: Option<&'static mut process_control_block> = cpu_queue_i.dequeue(); + if proc.is_some(){ + return proc; + } + } + // return 一个空值 + None + } +} + +impl Scheduler for SchedulerRT { + /// @brief 在当前cpu上进行调度。 + /// 请注意,进入该函数之前,需要关中断 + fn sched(&mut self) -> Option<&'static mut process_control_block> { + current_pcb().flags &= !(PF_NEED_SCHED as u64); + // 正常流程下,这里一定是会pick到next的pcb的,如果是None的话,要抛出错误 + let proc: &'static mut process_control_block = + self.pick_next_task_rt().expect("No RT process found"); + + // 如果是fifo策略,则可以一直占有cpu直到有优先级更高的任务就绪(即使优先级相同也不行)或者主动放弃(等待资源) + if proc.policy == SCHED_FIFO { + // 如果挑选的进程优先级小于当前进程,则不进行切换 + if proc.priority <= current_pcb().priority { + sched_enqueue(proc); + } else { + // 将当前的进程加进队列 + sched_enqueue(current_pcb()); + compiler_fence(core::sync::atomic::Ordering::SeqCst); + return Some(proc); + } + } + // RR调度策略需要考虑时间片 + else if proc.policy == SCHED_RR { + // 同等优先级的,考虑切换 + if proc.priority >= current_pcb().priority { + // 判断这个进程时间片是否耗尽,若耗尽则将其时间片赋初值然后入队 + if proc.rt_time_slice <= 0 { + proc.rt_time_slice = SchedulerRT::RR_TIMESLICE; + proc.flags |= !(PF_NEED_SCHED as u64); + sched_enqueue(proc); + } + // 目标进程时间片未耗尽,切换到目标进程 + else { + // 将当前进程加进队列 + sched_enqueue(current_pcb()); + compiler_fence(core::sync::atomic::Ordering::SeqCst); + return Some(proc); + } + } + // curr优先级更大,说明一定是实时进程,将所选进程入队列 + else { + sched_enqueue(proc); + } + } + return None; + } + + fn enqueue(&mut self, pcb: &'static mut process_control_block) { + let cpu_queue = &mut self.cpu_queue[pcb.cpu_id as usize]; + cpu_queue.enqueue(pcb); + } +} diff --git a/kernel/src/smp/mod.rs b/kernel/src/smp/mod.rs index 689cad34..5a7ca06a 100644 --- a/kernel/src/smp/mod.rs +++ b/kernel/src/smp/mod.rs @@ -1 +1 @@ -pub mod core; \ No newline at end of file +pub mod core;