Patch sched rust (#139)

* update

* 添加rt调度器的rust初步实现

* 完善rt调度逻辑

* 调试rt调度器

* 修改sched的返回值

* cargo fmt 格式化

* 删除无用代码,修补rt bug

* 删除无用的代码,和重复的逻辑

* 软中断bugfix

* 删除一些代码

* 添加kthread_run_rt文档

* 解决sphinix警告_static目录不存在的问题

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
kong 2023-01-14 22:38:05 +08:00 committed by GitHub
parent ec53d23ed0
commit 06b09f34ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 426 additions and 173 deletions

0
docs/_static/.gitkeep vendored Normal file
View File

View File

@ -62,6 +62,18 @@
&emsp;&emsp;该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。 &emsp;&emsp;该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。
### kthread_run_rt()
#### 原型
&emsp;&emsp;`kthread_run_rt(thread_fn, data, name_fmt, ...)`
#### 简介
&emsp;&emsp;创建内核实时线程并加入调度队列。
&emsp;&emsp;类似`kthread_run()`,该宏定义也是`kthread_create()`的简单封装,提供创建了内核实时线程后,在设置实时进程的参数后,立即运行的功能。
## 停止内核线程 ## 停止内核线程
### kthread_stop() ### kthread_stop()

View File

@ -2,7 +2,7 @@ use core::arch::x86_64::_popcnt64;
/// @brief ffz - 寻找u64中的第一个0所在的位从第0位开始寻找 /// @brief ffz - 寻找u64中的第一个0所在的位从第0位开始寻找
/// 请注意如果x中没有0,那么结果将是未定义的。请确保传入的x至少存在1个0 /// 请注意如果x中没有0,那么结果将是未定义的。请确保传入的x至少存在1个0
/// ///
/// @param x 目标u64 /// @param x 目标u64
/// @return i32 bit-number(0..63) of the first (least significant) zero bit. /// @return i32 bit-number(0..63) of the first (least significant) zero bit.
#[inline] #[inline]

View File

@ -1,6 +1,6 @@
pub mod irqflags; pub mod irqflags;
#[macro_use] #[macro_use]
pub mod current; pub mod current;
pub mod ptrace;
pub mod bitops; pub mod bitops;
pub mod cmpxchg; pub mod cmpxchg;
pub mod ptrace;

View File

@ -3,10 +3,10 @@ use crate::include::bindings::bindings::pt_regs;
/// @brief 判断给定的栈帧是否来自用户态 /// @brief 判断给定的栈帧是否来自用户态
/// 判断方法为根据代码段选择子是否具有ring3的访问权限低2bit均为1 /// 判断方法为根据代码段选择子是否具有ring3的访问权限低2bit均为1
pub fn user_mode(regs: *const pt_regs)->bool{ pub fn user_mode(regs: *const pt_regs) -> bool {
if (unsafe{(*regs).cs} & 0x3) != 0{ if (unsafe { (*regs).cs } & 0x3) != 0 {
return true; return true;
}else { } else {
return false; return false;
} }
} }

View File

@ -3,16 +3,16 @@ use core::arch::asm;
/// @brief 关闭中断 /// @brief 关闭中断
#[inline] #[inline]
pub fn cli(){ pub fn cli() {
unsafe{ unsafe {
asm!("cli"); asm!("cli");
} }
} }
/// @brief 开启中断 /// @brief 开启中断
#[inline] #[inline]
pub fn sti(){ pub fn sti() {
unsafe{ unsafe {
asm!("sti"); asm!("sti");
} }
} }

View File

@ -2,22 +2,22 @@
use core::arch::asm; use core::arch::asm;
#[inline(always)] #[inline(always)]
pub fn mfence(){ pub fn mfence() {
unsafe{ unsafe {
asm!("mfence"); asm!("mfence");
} }
} }
#[inline(always)] #[inline(always)]
pub fn lfence(){ pub fn lfence() {
unsafe{ unsafe {
asm!("lfence"); asm!("lfence");
} }
} }
#[inline(always)] #[inline(always)]
pub fn sfence(){ pub fn sfence() {
unsafe{ unsafe {
asm!("sfence"); asm!("sfence");
} }
} }

View File

@ -19,7 +19,7 @@ pub fn switch_mm(
mfence(); mfence();
// kdebug!("to get pml4t"); // kdebug!("to get pml4t");
let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) }; let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) };
unsafe { unsafe {
asm!("mov cr3, {}", in(reg) pml4t); asm!("mov cr3, {}", in(reg) pml4t);
} }

View File

@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
pub mod asm; pub mod asm;
pub mod context;
pub mod cpu; pub mod cpu;
pub mod interrupt; pub mod interrupt;
pub mod mm; pub mod mm;
pub mod context; pub mod sched;
pub mod sched;

View File

@ -54,6 +54,23 @@ struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data
__kt; \ __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发送停止信号 * @brief kthread发送停止信号
* *

View File

@ -1,2 +1,2 @@
pub mod uart;
pub mod timers; pub mod timers;
pub mod uart;

View File

@ -1 +1 @@
pub mod rtc; pub mod rtc;

View File

@ -1 +1 @@
pub mod rtc; pub mod rtc;

View File

@ -1,5 +1,5 @@
use crate::include::bindings::bindings::{io_in8, io_out8}; 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 UART_SUCCESS: i32 = 0;
const E_UART_BITS_RATE_ERROR: i32 = 1; const E_UART_BITS_RATE_ERROR: i32 = 1;
@ -63,7 +63,7 @@ impl UartPort {
struct UartRegister { struct UartRegister {
reg_data: u8, reg_data: u8,
reg_interrupt_enable: 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_line_config: u8,
reg_modem_config: u8, reg_modem_config: u8,
reg_line_status: u8, reg_line_status: u8,
@ -79,7 +79,10 @@ pub struct UartDriver {
impl Default for UartDriver { impl Default for UartDriver {
fn default() -> Self { 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 { if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
return Err("uart init error."); return Err("uart init error.");
} }
unsafe { unsafe {
io_out8(port + 1, 0x00); // Disable all interrupts io_out8(port + 1, 0x00); // Disable all interrupts
io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
let divisor = UART_MAX_BITS_RATE / baud_rate; 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 + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit 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 + 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, 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 + 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) 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) // Check if serial is faulty (i.e: not same byte as sent)
if io_in8(port + 0) != 0xAE { if io_in8(port + 0) != 0xAE {
return Err("uart faulty"); return Err("uart faulty");
} }
// If serial is not faulty set it in normal operation mode // If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
io_out8(port + 4, 0x08); io_out8(port + 4, 0x08);
@ -133,15 +136,15 @@ impl UartDriver {
} }
fn serial_received(offset: u16) -> bool { fn serial_received(offset: u16) -> bool {
if unsafe{ io_in8(offset + 5) } & 1 != 0 { if unsafe { io_in8(offset + 5) } & 1 != 0 {
true true
} else { } else {
false false
} }
} }
fn is_transmit_empty(offset: u16) -> bool { fn is_transmit_empty(offset: u16) -> bool {
if unsafe{ io_in8(offset + 5) } & 0x20 != 0 { if unsafe { io_in8(offset + 5) } & 0x20 != 0 {
true true
} else { } else {
false false
@ -157,11 +160,13 @@ impl UartDriver {
let port = uart_port.to_u16(); let port = uart_port.to_u16();
while UartDriver::is_transmit_empty(port) == false { while UartDriver::is_transmit_empty(port) == false {
for c in str.bytes() { for c in str.bytes() {
unsafe { io_out8(port, c); } unsafe {
io_out8(port, c);
}
} }
} //TODO:pause } //TODO:pause
} }
/// @brief 串口接收一个字节 /// @brief 串口接收一个字节
/// @param uart_port 端口号 /// @param uart_port 端口号
/// @return 接收的字节 /// @return 接收的字节
@ -171,7 +176,6 @@ impl UartDriver {
while UartDriver::serial_received(port) == false {} //TODO:pause while UartDriver::serial_received(port) == false {} //TODO:pause
unsafe { io_in8(port) as char } unsafe { io_in8(port) as char }
} }
} }
///@brief 发送数据 ///@brief 发送数据
@ -180,7 +184,9 @@ impl UartDriver {
#[no_mangle] #[no_mangle]
pub extern "C" fn c_uart_send(port: u16, c: u8) { pub extern "C" fn c_uart_send(port: u16, c: u8) {
while UartDriver::is_transmit_empty(port) == false {} //TODO:pause while UartDriver::is_transmit_empty(port) == false {} //TODO:pause
unsafe { io_out8(port, c); } unsafe {
io_out8(port, c);
}
} }
///@brief 从uart接收数据 ///@brief 从uart接收数据
@ -196,8 +202,7 @@ pub extern "C" fn c_uart_read(port: u16) -> u8 {
///@param port 串口端口 ///@param port 串口端口
///@param str 字符串S ///@param str 字符串S
#[no_mangle] #[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 { unsafe {
let mut i = 0; let mut i = 0;
while *offset(str, i) != '\0' as u8 { 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 { unsafe {
io_out8(port + 1, 0x00); // Disable all interrupts io_out8(port + 1, 0x00); // Disable all interrupts
io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor) io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
let divisor = UART_MAX_BITS_RATE / baud_rate; 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 + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit 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 + 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, 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 + 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) 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) // Check if serial is faulty (i.e: not same byte as sent)
if io_in8(port + 0) != 0xAE { if io_in8(port + 0) != 0xAE {
return -E_UART_SERIAL_FAULT; return -E_UART_SERIAL_FAULT;
} }
// If serial is not faulty set it in normal operation mode // If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
io_out8(port + 4, 0x08); io_out8(port + 4, 0x08);

View File

@ -14,11 +14,9 @@
// ==================implementation with rust=================== // ==================implementation with rust===================
extern void softirq_init(); 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 register_softirq(uint32_t irq_num, void (*action)(void *data), void *data);
extern int unregister_softirq(uint32_t irq_num); 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(); extern void do_softirq();
// for temporary // for temporary

View File

@ -66,9 +66,9 @@ pub fn __get_softirq_handler_mut() -> &'static mut Softirq {
#[no_mangle] #[no_mangle]
#[allow(dead_code)] #[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(); let softirq_handler = __get_softirq_handler_mut();
softirq_handler.set_softirq_pending(1 << sirq_num); softirq_handler.set_softirq_pending(sirq_num);
} }
/// @brief 软中断注册函数 /// @brief 软中断注册函数

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -1 +1 @@
pub mod bindings; pub mod bindings;

View File

@ -1,2 +1,2 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
pub mod bindings; pub mod bindings;

View File

@ -1,2 +1,2 @@
pub mod signal; pub mod signal;
pub mod signal_types; pub mod signal_types;

View File

@ -546,7 +546,7 @@ impl SigQueue {
} }
/// @brief 从C的void*指针转换为static生命周期的可变引用 /// @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 = p as *mut SigQueue;
let sq = unsafe { sq.as_mut::<'static>() }.unwrap(); let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
return sq; return sq;

View File

@ -13,8 +13,8 @@ pub fn atomic_read(ato: *const atomic_t) -> i64 {
/// @brief 原子的设置原子变量的值 /// @brief 原子的设置原子变量的值
#[inline] #[inline]
pub fn atomic_set(ato: *mut atomic_t, value:i64) { pub fn atomic_set(ato: *mut atomic_t, value: i64) {
unsafe{ unsafe {
write_volatile(&mut (*ato).value, value); write_volatile(&mut (*ato).value, value);
} }
} }

View File

@ -6,24 +6,10 @@ pub trait FFIBind2Rust<T> {
fn convert_mut(src: *mut T) -> Option<&'static mut Self>; 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>{ pub fn __convert_ref<'a, S, D>(src: *const S) -> Option<&'a D> {
return unsafe { return unsafe { core::mem::transmute::<*const S, *const D>(src).as_ref() };
core::mem::transmute::<
*const S,
*const D,
>(src)
.as_ref()
};
} }

View File

@ -3,13 +3,16 @@ use crate::include::bindings::bindings::List;
/// @brief 初始化链表 /// @brief 初始化链表
#[inline] #[inline]
pub fn list_init(list: *mut List) { pub fn list_init(list: *mut List) {
unsafe{*list}.prev = list; unsafe { *list }.prev = list;
unsafe{*list}.next = list; unsafe { *list }.next = list;
} }
impl Default for List{ impl Default for List {
fn default() -> Self { fn default() -> Self {
let x= Self { prev: 0 as *mut List, next: 0 as *mut List }; let x = Self {
return x; prev: 0 as *mut List,
next: 0 as *mut List,
};
return x;
} }
} }

View File

@ -324,32 +324,32 @@ impl LockRef {
} }
/* /*
* 使lockref * 使lockref
let mut lockref = LockRef::new(); let mut lockref = LockRef::new();
kdebug!("lockref={:?}", lockref); kdebug!("lockref={:?}", lockref);
lockref.inc(); lockref.inc();
assert_eq!(lockref.count, 1); assert_eq!(lockref.count, 1);
kdebug!("lockref={:?}", lockref); kdebug!("lockref={:?}", lockref);
assert!(lockref.dec().is_ok()); assert!(lockref.dec().is_ok());
assert_eq!(lockref.count, 0); assert_eq!(lockref.count, 0);
assert!(lockref.dec().is_err()); assert!(lockref.dec().is_err());
assert_eq!(lockref.count, 0); assert_eq!(lockref.count, 0);
lockref.inc(); lockref.inc();
assert_eq!(lockref.count, 1); assert_eq!(lockref.count, 1);
assert!(lockref.dec_not_zero().is_err()); assert!(lockref.dec_not_zero().is_err());
lockref.inc(); lockref.inc();
assert_eq!(lockref.count, 2); assert_eq!(lockref.count, 2);
assert!(lockref.dec_not_zero().is_ok()); assert!(lockref.dec_not_zero().is_ok());
lockref.mark_dead(); lockref.mark_dead();
assert!(lockref.count < 0); assert!(lockref.count < 0);
assert!(lockref.inc_not_dead().is_err()); assert!(lockref.inc_not_dead().is_err());
kdebug!("lockref={:?}", lockref); kdebug!("lockref={:?}", lockref);
*/ */

View File

@ -1,9 +1,9 @@
pub mod ffi_convert;
pub mod printk; pub mod printk;
pub mod spinlock; pub mod spinlock;
pub mod ffi_convert;
#[macro_use] #[macro_use]
pub mod refcount; pub mod refcount;
pub mod atomic; pub mod atomic;
pub mod wait_queue;
pub mod list; pub mod list;
pub mod lockref; pub mod lockref;
pub mod wait_queue;

View File

@ -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)] #[derive(Debug, Copy, Clone)]
pub struct RefCount { pub struct RefCount {
pub refs: atomic_t, pub refs: atomic_t,
} }
impl Default for RefCount{ impl Default for RefCount {
fn default() -> Self { fn default() -> Self {
Self { refs: atomic_t { value: 1 }} Self {
refs: atomic_t { value: 1 },
}
} }
} }
/// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用 /// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用
impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCount{ impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCount {
fn convert_mut( fn convert_mut(
src: *mut crate::include::bindings::bindings::refcount_struct, src: *mut crate::include::bindings::bindings::refcount_struct,
) -> Option<&'static mut Self> { ) -> Option<&'static mut Self> {
@ -23,7 +31,7 @@ impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCo
fn convert_ref( fn convert_ref(
src: *const crate::include::bindings::bindings::refcount_struct, src: *const crate::include::bindings::bindings::refcount_struct,
) -> Option<&'static Self> { ) -> Option<&'static Self> {
return __convert_ref(src) return __convert_ref(src);
} }
} }
@ -40,10 +48,10 @@ macro_rules! REFCOUNT_INIT {
#[allow(dead_code)] #[allow(dead_code)]
#[inline] #[inline]
pub fn refcount_inc(r: &mut RefCount) { 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"); kwarn!("Refcount increased from 0, may be use-after free");
} }
unsafe { unsafe {
atomic_inc(&mut r.refs); atomic_inc(&mut r.refs);
} }
@ -52,10 +60,8 @@ pub fn refcount_inc(r: &mut RefCount) {
/// @brief 引用计数自减1 /// @brief 引用计数自减1
#[allow(dead_code)] #[allow(dead_code)]
#[inline] #[inline]
pub fn refcount_dec(r: &mut RefCount){ pub fn refcount_dec(r: &mut RefCount) {
unsafe{ unsafe {
atomic_dec(&mut r.refs); atomic_dec(&mut r.refs);
} }
} }

View File

@ -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 { 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); list_init(&mut x.wait_list);
return x; return x;
} }
} }

View File

@ -1,5 +1,5 @@
use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE};
use super::gfp::__GFP_ZERO; use super::gfp::__GFP_ZERO;
use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE};
use core::alloc::{GlobalAlloc, Layout}; use core::alloc::{GlobalAlloc, Layout};

View File

@ -26,10 +26,9 @@ pub static mut INITIAL_SIGHAND: sighand_struct = sighand_struct {
/// @brief 初始化pid=0的进程的信号相关的信息 /// @brief 初始化pid=0的进程的信号相关的信息
#[no_mangle] #[no_mangle]
pub extern "C" fn initial_proc_init_signal(pcb: *mut process_control_block) { pub extern "C" fn initial_proc_init_signal(pcb: *mut process_control_block) {
// 所设置的pcb的pid一定为0 // 所设置的pcb的pid一定为0
assert_eq!(unsafe { (*pcb).pid }, 0); assert_eq!(unsafe { (*pcb).pid }, 0);
// 设置init进程的sighand和signal // 设置init进程的sighand和signal
unsafe { unsafe {
(*pcb).sighand = &mut INITIAL_SIGHAND as *mut sighand_struct as usize (*pcb).sighand = &mut INITIAL_SIGHAND as *mut sighand_struct as usize

View File

@ -1,5 +1,5 @@
pub mod pid; pub mod fork;
pub mod process;
pub mod preempt;
pub mod initial_proc; pub mod initial_proc;
pub mod fork; pub mod pid;
pub mod preempt;
pub mod process;

View File

@ -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)] #[allow(dead_code)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -23,6 +23,6 @@ impl PartialEq for PidType {
* @brief pid * @brief pid
*/ */
#[no_mangle] #[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; return current_pcb().pid as u64;
} }

View File

@ -105,6 +105,7 @@ struct process_control_block
long pid; long pid;
long priority; // 优先级 long priority; // 优先级
int64_t virtual_runtime; // 虚拟运行时间 int64_t virtual_runtime; // 虚拟运行时间
int64_t rt_time_slice; // 由实时调度器管理的时间片
// 进程拥有的文件描述符的指针数组 // 进程拥有的文件描述符的指针数组
// todo: 改用动态指针数组 // todo: 改用动态指针数组

View File

@ -409,7 +409,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
// 关闭之前的文件描述符 // 关闭之前的文件描述符
process_exit_files(current_pcb); process_exit_files(current_pcb);
process_open_stdio(current_pcb); process_open_stdio(current_pcb);
// 清除进程的vfork标志位 // 清除进程的vfork标志位
@ -469,6 +469,22 @@ exec_failed:;
} }
#pragma GCC pop_options #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进程 * @brief init进程
* *
@ -508,6 +524,12 @@ ul initial_kernel_thread(ul arg)
// waitpid(tpid[i], NULL, NULL); // waitpid(tpid[i], NULL, NULL);
// kinfo("All test done."); // 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; struct pt_regs *regs;

View File

@ -2,9 +2,7 @@ use core::ptr::{read_volatile, write_volatile};
use crate::{ use crate::{
arch::asm::current::current_pcb, arch::asm::current::current_pcb,
include::bindings::bindings::{ include::bindings::bindings::{process_control_block, PROC_RUNNING, PROC_STOPPED},
process_control_block, PROC_RUNNING, PROC_STOPPED,
},
sched::core::{cpu_executing, sched_enqueue}, sched::core::{cpu_executing, sched_enqueue},
smp::core::{smp_get_processor_id, smp_send_reschedule}, smp::core::{smp_get_processor_id, smp_send_reschedule},
}; };

View File

@ -1,24 +1,17 @@
use core::{ use core::{ptr::null_mut, sync::atomic::compiler_fence};
ptr::null_mut,
sync::atomic::compiler_fence,
};
use alloc::{boxed::Box, vec::Vec}; use alloc::{boxed::Box, vec::Vec};
use crate::{ use crate::{
arch::{ arch::asm::current::current_pcb,
asm::current::current_pcb,
context::switch_process,
},
include::bindings::bindings::{ include::bindings::bindings::{
initial_proc_union, process_control_block, MAX_CPU_NUM, PF_NEED_SCHED, initial_proc_union, process_control_block, MAX_CPU_NUM, PF_NEED_SCHED, PROC_RUNNING,
PROC_RUNNING,
}, },
kBUG, kBUG,
libs::spinlock::RawSpinlock, libs::spinlock::RawSpinlock,
}; };
use super::core::Scheduler; use super::core::{sched_enqueue, Scheduler};
/// 声明全局的cfs调度器实例 /// 声明全局的cfs调度器实例
@ -149,8 +142,7 @@ impl SchedulerCFS {
impl Scheduler for SchedulerCFS { impl Scheduler for SchedulerCFS {
/// @brief 在当前cpu上进行调度。 /// @brief 在当前cpu上进行调度。
/// 请注意,进入该函数之前,需要关中断 /// 请注意,进入该函数之前,需要关中断
fn sched(&mut self) { fn sched(&mut self) -> Option<&'static mut process_control_block> {
// kdebug!("cfs:sched");
current_pcb().flags &= !(PF_NEED_SCHED as u64); current_pcb().flags &= !(PF_NEED_SCHED as u64);
let current_cpu_id = current_pcb().cpu_id as usize; let current_cpu_id = current_pcb().cpu_id as usize;
let current_cpu_queue: &mut CFSQueue = self.cpu_queue[current_cpu_id]; 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); compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
if current_pcb().state & (PROC_RUNNING as u64) != 0 { if current_pcb().state & (PROC_RUNNING as u64) != 0 {
// kdebug!("cfs:sched->enqueue"); sched_enqueue(current_pcb());
current_cpu_queue.enqueue(current_pcb());
compiler_fence(core::sync::atomic::Ordering::SeqCst); compiler_fence(core::sync::atomic::Ordering::SeqCst);
} }
@ -175,9 +166,7 @@ impl Scheduler for SchedulerCFS {
} }
compiler_fence(core::sync::atomic::Ordering::SeqCst); compiler_fence(core::sync::atomic::Ordering::SeqCst);
return Some(proc);
switch_process(current_pcb(), proc);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
} else { } else {
// 不进行切换 // 不进行切换
@ -188,10 +177,11 @@ impl Scheduler for SchedulerCFS {
} }
compiler_fence(core::sync::atomic::Ordering::SeqCst); 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);
} }
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) { fn enqueue(&mut self, pcb: &'static mut process_control_block) {

View File

@ -2,11 +2,16 @@ use core::sync::atomic::compiler_fence;
use crate::{ use crate::{
arch::asm::{current::current_pcb, ptrace::user_mode}, 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, process::process::process_cpu,
}; };
use super::cfs::{sched_cfs_init, SchedulerCFS, __get_cfs_scheduler}; use super::cfs::{sched_cfs_init, SchedulerCFS, __get_cfs_scheduler};
use super::rt::{sched_rt_init, SchedulerRT, __get_rt_scheduler};
/// @brief 获取指定的cpu上正在执行的进程的pcb /// @brief 获取指定的cpu上正在执行的进程的pcb
#[inline] #[inline]
@ -23,28 +28,50 @@ pub fn cpu_executing(cpu_id: u32) -> &'static mut process_control_block {
/// @brief 具体的调度器应当实现的trait /// @brief 具体的调度器应当实现的trait
pub trait Scheduler { pub trait Scheduler {
/// @brief 使用该调度器发起调度的时候,要调用的函数 /// @brief 使用该调度器发起调度的时候,要调用的函数
fn sched(&mut self); fn sched(&mut self) -> Option<&'static mut process_control_block>;
/// @brief 将pcb加入这个调度器的调度队列 /// @brief 将pcb加入这个调度器的调度队列
fn enqueue(&mut self, pcb: &'static mut process_control_block); 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); compiler_fence(core::sync::atomic::Ordering::SeqCst);
let cfs_scheduler: &mut SchedulerCFS = __get_cfs_scheduler(); let cfs_scheduler: &mut SchedulerCFS = __get_cfs_scheduler();
let rt_scheduler: &mut SchedulerRT = __get_rt_scheduler();
compiler_fence(core::sync::atomic::Ordering::SeqCst); compiler_fence(core::sync::atomic::Ordering::SeqCst);
cfs_scheduler.sched(); let next: &'static mut process_control_block;
match rt_scheduler.pick_next_task_rt() {
compiler_fence(core::sync::atomic::Ordering::SeqCst); 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 将进程加入调度队列 /// @brief 将进程加入调度队列
#[allow(dead_code)] #[allow(dead_code)]
#[no_mangle] #[no_mangle]
pub extern "C" fn sched_enqueue(pcb: &'static mut process_control_block) { 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(); 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 初始化进程调度器模块 /// @brief 初始化进程调度器模块
@ -53,6 +80,7 @@ pub extern "C" fn sched_enqueue(pcb: &'static mut process_control_block) {
pub extern "C" fn sched_init() { pub extern "C" fn sched_init() {
unsafe { unsafe {
sched_cfs_init(); sched_cfs_init();
sched_rt_init();
} }
} }
@ -65,6 +93,9 @@ pub extern "C" fn sched_update_jiffies() {
SCHED_NORMAL => { SCHED_NORMAL => {
__get_cfs_scheduler().timer_update_jiffies(); __get_cfs_scheduler().timer_update_jiffies();
} }
SCHED_FIFO | SCHED_RR => {
current_pcb().rt_time_slice -= 1;
}
_ => { _ => {
todo!() todo!()
} }
@ -80,6 +111,10 @@ pub extern "C" fn sys_sched(regs: &'static mut pt_regs) -> u64 {
if user_mode(regs) { if user_mode(regs) {
return (-(EPERM as i64)) as u64; return (-(EPERM as i64)) as u64;
} }
__sched(); // 根据调度结果统一进行切换
let pcb = __sched();
if pcb.is_some() {
switch_process(current_pcb(), pcb.unwrap());
}
0 0
} }

View File

@ -1,2 +1,3 @@
pub mod cfs;
pub mod core; pub mod core;
pub mod cfs; pub mod rt;

173
kernel/src/sched/rt.rs Normal file
View File

@ -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);
}
}

View File

@ -1 +1 @@
pub mod core; pub mod core;