mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
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:
parent
ec53d23ed0
commit
06b09f34ed
0
docs/_static/.gitkeep
vendored
Normal file
0
docs/_static/.gitkeep
vendored
Normal file
@ -62,6 +62,18 @@
|
|||||||
|
|
||||||
  该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。
|
  该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。
|
||||||
|
|
||||||
|
### kthread_run_rt()
|
||||||
|
|
||||||
|
#### 原型
|
||||||
|
|
||||||
|
  `kthread_run_rt(thread_fn, data, name_fmt, ...)`
|
||||||
|
|
||||||
|
#### 简介
|
||||||
|
|
||||||
|
  创建内核实时线程并加入调度队列。
|
||||||
|
|
||||||
|
  类似`kthread_run()`,该宏定义也是`kthread_create()`的简单封装,提供创建了内核实时线程后,在设置实时进程的参数后,立即运行的功能。
|
||||||
|
|
||||||
## 停止内核线程
|
## 停止内核线程
|
||||||
|
|
||||||
### kthread_stop()
|
### kthread_stop()
|
||||||
|
@ -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]
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
|
@ -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发送停止信号,请求其结束
|
||||||
*
|
*
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
pub mod uart;
|
|
||||||
pub mod timers;
|
pub mod timers;
|
||||||
|
pub mod uart;
|
||||||
|
@ -1 +1 @@
|
|||||||
pub mod rtc;
|
pub mod rtc;
|
||||||
|
@ -1 +1 @@
|
|||||||
pub mod rtc;
|
pub mod rtc;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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 软中断注册函数
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -1 +1 @@
|
|||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
pub mod signal;
|
pub mod signal;
|
||||||
pub mod signal_types;
|
pub mod signal_types;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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: 改用动态指针数组
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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},
|
||||||
};
|
};
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
173
kernel/src/sched/rt.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user