mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
进程管理模块重构完成 (#380)
* 添加新版pcb的数据结构 (#273) * 将pcb中的内容分类,分别加锁 (#305) * 进程管理重构:完成fork的主体逻辑 (#309) 1.完成fork的主体逻辑 2.将文件系统接到新的pcb上 3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了 * chdir getcwd pid pgid ppid (#310) --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * 删除旧的fork以及signal的代码,并调整fork/vfork/execve系统调用 (#325) 1.删除旧的fork 2.删除signal相关代码,等进程管理重构结束之后,再重新写. 3.调整了fork/vfork/execve系统调用 * 实现切换进程的代码 (#331) * 实现切换进程的代码 * Patch modify preempt (#332) * 修改设置preempt的代码 * 删除rust的list和refcount * 为每个核心初始化idle进程 (#333) * 为每个核心初始化idle进程 * 完成了新的内核线程机制 (#335) * 调度器的pcb替换为新的Arc<ProcessControlBlock>,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336) * 把调度器的pcb替换为新的Arc<ProcessControlBlock> * 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译 * 修正一些双重加锁、细节问题 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * github workflow自动检查代码是否格式化 * cache toolchain yml * 调整rust版本的waitqueue中的pcb为新版的pcb (#343) * 解决设置rust workspace带来的“工具链不一致”的问题 (#344) * 解决设置rust workspace带来的“工具链不一致”的问题 更改workflow * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 (#341) * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 * 修改为在 WriterGuard 中维护 Irq_guard * 修正了 write_irqsave方法 * 优化了代码 * 把 set state 操作从 wakup 移动到 sched_enqueue 中 * 修正为在 wakeup 中设置 running ,以保留 set_state 的私有性 * 移除了 process_wakeup * 实现进程退出的逻辑 (#340) 实现进程退出的逻辑 * 标志进程sleep * 修复wakeup的问题 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * rust 重构 completion (#350) * 完成了completion的基本结构,待完善上级调用 * 用SpinLock保护结构体并发安全 * 修改原子变量为u32,修复符号错误 * irq guard * 修改为具有内部可变性的结构体 * temp fix * 修复了由于进程持有自旋锁导致的不被调度的问题 * 对 complete 系列方法上锁,保护 done 数据并发安全 * 移除了未使用的依赖 * 重写显示刷新驱动 (#363) * 重构显示刷新驱动 * Patch refactor process management (#366) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * waitqueue兼容C部分 (#351) * PATH * safe init * waitqueue兼容C部分 * waitqueue兼容C部分 * 删除semaphore.c,在ps2_keyboard中使用waitqueue * 删除semaphore.c,在ps2_keyboard中使用waitqueue * current_pcb的C兼容 * current_pcb的C兼容 * current_pcb的C兼容 * fmt * current_pcb的兼容 * 针对修改 * 调整代码 * fmt * 删除pcb的set flags * 更改函数名 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * merge master * Patch debug process management refactor (#372) * 能够调通,执行完textui_init * 能跑到initial kernel thread * fmt * 能够正常初始化所有服务(尚未能切换到用户程序) * 删除部分无用的extern * 存在问题:ap处理器启动后,bsp的smp_init函数return之后就出错了,怀疑是栈损坏 * 解决smp启动由于未换栈导致的内存访问错误 * debug * 1 * 1 * lock no preempt * 调通 * 优化代码,删除一些调试日志 * fix * 使用rust重写wait4 (#377) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 * wait4 * 删除c_sys_wait4 * 使用userbuffer保护裸指针 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * 消除warning * 1. 修正未设置cpu executing的问题 * 修正kthread机制可能存在的内存泄露问题 * 删除pcb文档 * 删除C的tss struct --------- Co-authored-by: Bullet <93781792+GP-Bullet@users.noreply.github.com> Co-authored-by: Chiichen <39649411+Chiichen@users.noreply.github.com> Co-authored-by: hanjiezhou <zhouhanjie@dragonos.org> Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com> Co-authored-by: houmkh <1119644616@qq.com>
This commit is contained in:
parent
b087521e07
commit
1496ba7b24
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -96,7 +96,6 @@
|
||||
"math.h": "c",
|
||||
"ipi.h": "c",
|
||||
"arch.h": "c",
|
||||
"elf.h": "c",
|
||||
"stdio.h": "c",
|
||||
"wait_queue.h": "c",
|
||||
"stddef.h": "c",
|
||||
@ -154,7 +153,6 @@
|
||||
"err.h": "c",
|
||||
"rtc.h": "c",
|
||||
"list.h": "c",
|
||||
"completion.h": "c",
|
||||
"fat32.h": "c",
|
||||
"irqflags.h": "c",
|
||||
"dirent.h": "c",
|
||||
@ -169,13 +167,13 @@
|
||||
"assert.h": "c",
|
||||
"sys_version.h": "c",
|
||||
"cmd.h": "c",
|
||||
"user_namespace.h": "c",
|
||||
"sleep.h": "c",
|
||||
"net.h": "c",
|
||||
"lz4.h": "c",
|
||||
"cmd_test.h": "c",
|
||||
"cmpxchg.h": "c",
|
||||
"mman.h": "c"
|
||||
"mman.h": "c",
|
||||
"clocksource.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"esbonio.sphinx.confDir": "",
|
||||
|
@ -5,5 +5,4 @@
|
||||
:maxdepth: 1
|
||||
|
||||
kthread
|
||||
pcb
|
||||
load_binary
|
||||
|
@ -1,134 +1,14 @@
|
||||
# kthread 内核线程
|
||||
|
||||
  内核线程模块定义在`common/kthread.h`中,提供对内核线程的及支持功能。内核线程作为内核的“分身”,能够提升系统的并行化程度以及故障容错能力。
|
||||
  内核线程模块实现在`process/kthread.rs`中,提供对内核线程的及支持功能。内核线程作为内核的“分身”,能够提升系统的并行化程度以及故障容错能力。
|
||||
|
||||
## 原理
|
||||
|
||||
  每个内核线程都运行在内核态,执行其特定的任务。
|
||||
|
||||
  内核线程的创建是通过调用`kthread_create()`或者`kthread_run()`宏,向`kthreadd`守护线程发送创建任务来实现的。也就是说,内核线程的创建,最终是由`kthreadd`来完成。
|
||||
  内核线程的创建是通过调用`KernelThreadMechanism::create()`或者`KernelThreadMechanism::create_and_run()`函数,向`kthreadd`守护线程发送创建任务来实现的。也就是说,内核线程的创建,最终是由`kthread_daemon`来完成。
|
||||
|
||||
  当内核线程被创建后,虽然会加入调度队列,但是当其被第一次调度,执行引导程序`kthread()`后,将进入休眠状态。直到其他模块使用`process_wakeup()`,它才会真正开始运行。
|
||||
  当内核线程被创建后,默认处于睡眠状态,要使用`ProcessManager::wakeup`函数将其唤醒。
|
||||
  当内核其他模块想要停止一个内核线程的时候,可以调用`KernelThreadMechanism::stop()`函数,等待内核线程的退出,然后获得返回值并清理内核线程的pcb。
|
||||
|
||||
  当内核其他模块想要停止一个内核线程的时候,可以调用`kthread_stop()`函数。该函数将会置位内核线程的`worker_private`中的`KTHREAD_SHOULD_STOP`标志位,并等待内核线程的退出,然后获得返回值并清理内核线程的pcb。
|
||||
|
||||
  内核线程应当经常检查`KTHREAD_SHOULD_STOP`标志位,以确定其是否要退出。当检测到该标志位被置位时,内核线程应当完成数据清理工作,并调用`kthread_exit()`或直接返回一个返回码,以退出内核线程。
|
||||
|
||||
## 创建内核线程
|
||||
|
||||
### kthread_create()
|
||||
|
||||
#### 原型
|
||||
|
||||
  `kthread_create(thread_fn, data, name_fmt, arg...)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  在当前NUMA结点上创建一个内核线程(DragonOS目前暂不支持NUMA,因此node可忽略。)
|
||||
|
||||
  请注意,该宏会创建一个内核线程,并将其设置为停止状态.
|
||||
|
||||
#### 参数
|
||||
|
||||
**thread_fn**
|
||||
|
||||
  该内核线程要执行的函数
|
||||
|
||||
**data**
|
||||
|
||||
  传递给 *thread_fn* 的参数数据
|
||||
|
||||
**name_fmt**
|
||||
|
||||
  printf-style format string for the thread name
|
||||
|
||||
**arg**
|
||||
|
||||
  name_fmt的参数
|
||||
|
||||
#### 返回值
|
||||
|
||||
  创建好的内核线程的pcb
|
||||
|
||||
### kthread_run()
|
||||
|
||||
#### 原型
|
||||
|
||||
  `kthread_run(thread_fn, data, name_fmt, ...)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  创建内核线程并加入调度队列。
|
||||
|
||||
  该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。
|
||||
|
||||
### kthread_run_rt()
|
||||
|
||||
#### 原型
|
||||
|
||||
  `kthread_run_rt(thread_fn, data, name_fmt, ...)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  创建内核实时线程并加入调度队列。
|
||||
|
||||
  类似`kthread_run()`,该宏定义也是`kthread_create()`的简单封装,提供创建了内核实时线程后,在设置实时进程的参数后,立即运行的功能。
|
||||
|
||||
## 停止内核线程
|
||||
|
||||
### kthread_stop()
|
||||
|
||||
#### 原型
|
||||
|
||||
  `int kthread_stop(struct process_control_block * pcb)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  当外部模块希望停止一个内核线程时,调用该函数,向kthread发送停止消息,请求其结束。并等待其退出,返回内核线程的退出返回值。
|
||||
|
||||
#### 参数
|
||||
|
||||
**pcb**
|
||||
|
||||
  内核线程的pcb
|
||||
|
||||
#### 返回值
|
||||
|
||||
  内核线程的退出返回码。
|
||||
|
||||
### kthread_should_stop()
|
||||
|
||||
|
||||
#### 原型
|
||||
|
||||
  `bool kthread_should_stop(void)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  内核线程可以调用该函数得知是否有其他进程请求结束当前内核线程。
|
||||
|
||||
#### 返回值
|
||||
|
||||
  一个bool变量
|
||||
|
||||
|
||||
| 值 | 解释 |
|
||||
| ---------- | ----------------------- |
|
||||
| true | 有其他进程请求结束该内核线程 |
|
||||
| false | 该内核线程没有收到停止消息 |
|
||||
|
||||
### kthread_exit()
|
||||
|
||||
#### 原型
|
||||
|
||||
  `void kthread_exit(long result)`
|
||||
|
||||
#### 简介
|
||||
|
||||
  让当前内核线程退出,并返回result参数给kthread_stop()函数。
|
||||
|
||||
#### 参数
|
||||
|
||||
**result**
|
||||
|
||||
  内核线程的退出返回码
|
||||
  内核线程应当经常检查`KernelThreadMechanism::should_stop()`的结果,以确定其是否要退出。当检测到需要退出时,内核线程返回一个返回码,即可退出。(注意资源的清理)
|
||||
|
@ -1,27 +0,0 @@
|
||||
# PCB 进程控制块
|
||||
|
||||
PCB的全称为process control block, 它是每个进程/线程的核心控制结构。定义于`kernel/src/process/proc-types.h`中。
|
||||
|
||||
## PCB详解
|
||||
|
||||
Todo:
|
||||
|
||||
## 与PCB的管理相关的API
|
||||
|
||||
### 根据pid寻找pcb
|
||||
|
||||
**process_find_pcb_by_pid**
|
||||
|
||||
该API提供了根据pid寻找pcb的功能,定义在`kernel/src/process/process.h`中。
|
||||
|
||||
当找到目标的pcb时,返回对应的pcb,否则返回NULL。
|
||||
|
||||
#### 参数
|
||||
|
||||
**pid**
|
||||
进程id
|
||||
|
||||
#### 返回值
|
||||
|
||||
**struct process_control_block**
|
||||
目标pcb
|
@ -25,6 +25,7 @@ num-derive = "0.3"
|
||||
# 一个no_std的hashmap、hashset
|
||||
hashbrown = "0.13.2"
|
||||
elf = { version = "0.7.2", default-features = false }
|
||||
memoffset = "0.9.0"
|
||||
atomic_enum = "0.2.0"
|
||||
|
||||
# 构建时依赖项
|
||||
|
@ -10,15 +10,14 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns)))
|
||||
|
||||
# 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_
|
||||
PIC := _INTR_APIC_
|
||||
CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include
|
||||
CFLAGS = $(GLOBAL_CFLAGS) -fno-pie -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include
|
||||
|
||||
export ASFLAGS := --64
|
||||
|
||||
LD_LIST := head.o
|
||||
|
||||
|
||||
kernel_subdirs := common driver process debug arch exception smp sched syscall ktest libs ipc time
|
||||
|
||||
kernel_subdirs := common driver debug arch exception smp sched syscall ktest libs time
|
||||
|
||||
|
||||
head.o: head.S
|
||||
@ -38,7 +37,7 @@ kernel_rust:
|
||||
all: kernel
|
||||
|
||||
@echo "Linking kernel..."
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds --no-relax
|
||||
# 生成kallsyms
|
||||
current_dir=$(pwd)
|
||||
|
||||
@ -52,7 +51,7 @@ all: kernel
|
||||
# 重新链接
|
||||
@echo "Re-Linking kernel..."
|
||||
@echo $(shell find . -name "*.o")
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds --no-relax
|
||||
@echo "Generating kernel ELF file..."
|
||||
# 生成内核文件
|
||||
$(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 kernel ../../bin/kernel/kernel.elf
|
||||
|
@ -1,3 +1,4 @@
|
||||
#![allow(dead_code)]
|
||||
use core::arch::x86_64::_popcnt64;
|
||||
|
||||
/// @brief ffz - 寻找u64中的第一个0所在的位(从第0位开始寻找)
|
||||
|
@ -1,12 +0,0 @@
|
||||
// 该函数在cmpxchg.c中实现
|
||||
extern "C" {
|
||||
fn __try_cmpxchg_q(ptr: *mut u64, old_ptr: *mut u64, new_ptr: *mut u64) -> bool;
|
||||
}
|
||||
|
||||
/// @brief 封装lock cmpxchg指令
|
||||
/// 由于Rust实现这部分的内联汇编比较麻烦(实在想不出办法),因此使用C的实现。
|
||||
#[inline]
|
||||
pub unsafe fn try_cmpxchg_q(ptr: *mut u64, old_ptr: *mut u64, new_ptr: *mut u64) -> bool {
|
||||
let retval = __try_cmpxchg_q(ptr, old_ptr, new_ptr);
|
||||
return retval;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
use crate::include::bindings::bindings::process_control_block;
|
||||
|
||||
use core::{arch::asm, sync::atomic::compiler_fence};
|
||||
|
||||
/// @brief 获取指向当前进程的pcb的可变引用
|
||||
#[inline]
|
||||
pub fn current_pcb() -> &'static mut process_control_block {
|
||||
let ret: Option<&mut process_control_block>;
|
||||
|
||||
unsafe {
|
||||
let mut tmp: u64 = !(32767u64);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
asm!("and {0}, rsp", inout(reg)(tmp),);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
ret = (tmp as *mut process_control_block).as_mut();
|
||||
}
|
||||
|
||||
ret.unwrap()
|
||||
}
|
@ -1,6 +1,2 @@
|
||||
pub mod irqflags;
|
||||
#[macro_use]
|
||||
pub mod current;
|
||||
pub mod bitops;
|
||||
pub mod cmpxchg;
|
||||
pub mod ptrace;
|
||||
pub mod irqflags;
|
||||
|
@ -1,12 +0,0 @@
|
||||
#![allow(dead_code)]
|
||||
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 {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -13,13 +13,13 @@ void __arch_spin_lock(spinlock_t *lock)
|
||||
"jmp 1b \n\t" // 尝试加锁
|
||||
"3:"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
preempt_disable();
|
||||
rs_preempt_disable();
|
||||
}
|
||||
|
||||
void __arch_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
preempt_enable();
|
||||
__asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory");
|
||||
rs_preempt_enable();
|
||||
}
|
||||
|
||||
void __arch_spin_lock_no_preempt(spinlock_t *lock)
|
||||
@ -44,13 +44,13 @@ void __arch_spin_unlock_no_preempt(spinlock_t *lock)
|
||||
long __arch_spin_trylock(spinlock_t *lock)
|
||||
{
|
||||
uint64_t tmp_val = 0;
|
||||
preempt_disable();
|
||||
rs_preempt_disable();
|
||||
// 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功
|
||||
asm volatile("lock xchg %%bx, %1 \n\t" // 确保只有1个进程能得到锁
|
||||
: "=q"(tmp_val), "=m"(lock->lock)
|
||||
: "b"(0)
|
||||
: "memory");
|
||||
if (!tmp_val)
|
||||
preempt_enable();
|
||||
rs_preempt_enable();
|
||||
return tmp_val;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
use crate::include::bindings::bindings::{process_control_block, switch_proc};
|
||||
|
||||
use core::sync::atomic::compiler_fence;
|
||||
|
||||
use super::fpu::{fp_state_restore, fp_state_save};
|
||||
|
||||
/// @brief 切换进程的上下文(没有切换页表的动作)
|
||||
///
|
||||
/// @param next 下一个进程的pcb
|
||||
/// @param trap_frame 中断上下文的栈帧
|
||||
#[inline(always)]
|
||||
pub fn switch_process(
|
||||
prev: &'static mut process_control_block,
|
||||
next: &'static mut process_control_block,
|
||||
) {
|
||||
fp_state_save(prev);
|
||||
fp_state_restore(next);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
let new_address_space = next.address_space().unwrap_or_else(|| {
|
||||
panic!(
|
||||
"switch_process: next process:{} address space is null",
|
||||
next.pid
|
||||
)
|
||||
});
|
||||
unsafe {
|
||||
// 加载页表
|
||||
new_address_space.read().user_mapper.utable.make_current();
|
||||
switch_proc(prev, next);
|
||||
}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use x86::cpuid::{cpuid, CpuIdResult};
|
||||
|
||||
/// @brief 获取当前cpu的apic id
|
||||
@ -10,13 +8,6 @@ pub fn current_cpu_id() -> u32 {
|
||||
return cpu_id;
|
||||
}
|
||||
|
||||
/// @brief 通过pause指令,让cpu休息一会儿。降低空转功耗
|
||||
pub fn cpu_relax() {
|
||||
unsafe {
|
||||
asm!("pause");
|
||||
}
|
||||
}
|
||||
|
||||
/// 重置cpu
|
||||
pub fn cpu_reset() -> ! {
|
||||
// 重启计算机
|
||||
|
@ -1,17 +1,4 @@
|
||||
use core::{
|
||||
arch::{
|
||||
asm,
|
||||
x86_64::{_fxrstor64, _fxsave64},
|
||||
},
|
||||
ffi::c_void,
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::{exception::InterruptArch, include::bindings::bindings::process_control_block};
|
||||
|
||||
use crate::arch::CurrentIrqArch;
|
||||
use core::arch::x86_64::{_fxrstor64, _fxsave64};
|
||||
|
||||
/// https://www.felixcloutier.com/x86/fxsave#tbl-3-47
|
||||
#[repr(C, align(16))]
|
||||
@ -53,94 +40,29 @@ impl Default for FpState {
|
||||
}
|
||||
}
|
||||
impl FpState {
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
assert!(core::mem::size_of::<Self>() == 512);
|
||||
return Self::default();
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
|
||||
#[inline]
|
||||
pub fn save(&mut self) {
|
||||
unsafe {
|
||||
_fxsave64(self as *mut FpState as *mut u8);
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
|
||||
#[inline]
|
||||
pub fn restore(&self) {
|
||||
unsafe {
|
||||
_fxrstor64(self as *const FpState as *const u8);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 清空fp_state
|
||||
/// 清空fp_state
|
||||
#[allow(dead_code)]
|
||||
pub fn clear(&mut self) {
|
||||
*self = Self::default();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能
|
||||
pub fn fp_state_save(pcb: &mut process_control_block) {
|
||||
// 该过程中不允许中断
|
||||
let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
|
||||
let fp: &mut FpState = if pcb.fp_state == null_mut() {
|
||||
let f = Box::leak(Box::new(FpState::default()));
|
||||
pcb.fp_state = f as *mut FpState as usize as *mut c_void;
|
||||
f
|
||||
} else {
|
||||
unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() }
|
||||
};
|
||||
|
||||
// 保存浮点寄存器
|
||||
fp.save();
|
||||
|
||||
// 关闭浮点功能
|
||||
unsafe {
|
||||
asm!(
|
||||
"mov rax, cr4",
|
||||
"and ax,~(3<<9)", //[9][10]->0
|
||||
"mov cr4,rax",
|
||||
"mov rax, cr0",
|
||||
"and ax,~(02h)", //[1]->0
|
||||
"or ax, ~(0FFFBh)", //[2]->1
|
||||
"mov cr0, rax" /*
|
||||
"mov rax, cr0",
|
||||
"and ax, 0xFFFB",
|
||||
"or ax,0x2",
|
||||
"mov cr0,rax",
|
||||
"mov rax, cr4",
|
||||
"or ax,3<<9",
|
||||
"mov cr4, rax" */
|
||||
)
|
||||
}
|
||||
drop(guard);
|
||||
}
|
||||
|
||||
/// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能
|
||||
pub fn fp_state_restore(pcb: &mut process_control_block) {
|
||||
// 该过程中不允许中断
|
||||
let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
|
||||
if pcb.fp_state == null_mut() {
|
||||
panic!("fp_state_restore: fp_state is null. pid={}", pcb.pid);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
asm! {
|
||||
"mov rax, cr0",
|
||||
"and ax, 0FFFBh",//[2]->0
|
||||
"or ax,02h",//[1]->1
|
||||
"mov cr0,rax",
|
||||
"mov rax, cr4",
|
||||
"or ax,3<<9",
|
||||
"mov cr4, rax",
|
||||
"clts",
|
||||
"fninit"
|
||||
}
|
||||
}
|
||||
|
||||
let fp = unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() };
|
||||
fp.restore();
|
||||
fp.clear();
|
||||
|
||||
drop(guard);
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
struct process_control_block;
|
||||
// 获取当前的pcb
|
||||
struct process_control_block *get_current_pcb()
|
||||
{
|
||||
struct process_control_block *current = NULL;
|
||||
// 利用了当前pcb和栈空间总大小为32k大小对齐,将rsp低15位清空,即可获得pcb的起始地址
|
||||
barrier();
|
||||
__asm__ __volatile__("andq %%rsp, %0 \n\t"
|
||||
: "=r"(current)
|
||||
: "0"(~32767UL));
|
||||
barrier();
|
||||
|
||||
return current;
|
||||
};
|
||||
#define current_pcb get_current_pcb()
|
||||
#pragma GCC pop_options
|
@ -61,3 +61,78 @@ impl InterruptArch for X86_64InterruptArch {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
/// 中断栈帧结构体
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TrapFrame {
|
||||
pub r15: ::core::ffi::c_ulong,
|
||||
pub r14: ::core::ffi::c_ulong,
|
||||
pub r13: ::core::ffi::c_ulong,
|
||||
pub r12: ::core::ffi::c_ulong,
|
||||
pub r11: ::core::ffi::c_ulong,
|
||||
pub r10: ::core::ffi::c_ulong,
|
||||
pub r9: ::core::ffi::c_ulong,
|
||||
pub r8: ::core::ffi::c_ulong,
|
||||
pub rbx: ::core::ffi::c_ulong,
|
||||
pub rcx: ::core::ffi::c_ulong,
|
||||
pub rdx: ::core::ffi::c_ulong,
|
||||
pub rsi: ::core::ffi::c_ulong,
|
||||
pub rdi: ::core::ffi::c_ulong,
|
||||
pub rbp: ::core::ffi::c_ulong,
|
||||
pub ds: ::core::ffi::c_ulong,
|
||||
pub es: ::core::ffi::c_ulong,
|
||||
pub rax: ::core::ffi::c_ulong,
|
||||
pub func: ::core::ffi::c_ulong,
|
||||
pub errcode: ::core::ffi::c_ulong,
|
||||
pub rip: ::core::ffi::c_ulong,
|
||||
pub cs: ::core::ffi::c_ulong,
|
||||
pub rflags: ::core::ffi::c_ulong,
|
||||
pub rsp: ::core::ffi::c_ulong,
|
||||
pub ss: ::core::ffi::c_ulong,
|
||||
}
|
||||
|
||||
impl TrapFrame {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
r15: 0,
|
||||
r14: 0,
|
||||
r13: 0,
|
||||
r12: 0,
|
||||
r11: 0,
|
||||
r10: 0,
|
||||
r9: 0,
|
||||
r8: 0,
|
||||
rbx: 0,
|
||||
rcx: 0,
|
||||
rdx: 0,
|
||||
rsi: 0,
|
||||
rdi: 0,
|
||||
rbp: 0,
|
||||
ds: 0,
|
||||
es: 0,
|
||||
rax: 0,
|
||||
func: 0,
|
||||
errcode: 0,
|
||||
rip: 0,
|
||||
cs: 0,
|
||||
rflags: 0,
|
||||
rsp: 0,
|
||||
ss: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置中断栈帧返回值
|
||||
pub fn set_return_value(&mut self, value: usize) {
|
||||
self.rax = value as u64;
|
||||
}
|
||||
|
||||
/// 判断当前中断是否来自用户模式
|
||||
pub fn from_user(&self) -> bool {
|
||||
if (self.cs & 0x3) != 0 {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
kernel/src/arch/x86_64/ipc/mod.rs
Normal file
10
kernel/src/arch/x86_64/ipc/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use super::interrupt::TrapFrame;
|
||||
|
||||
use crate::{arch::CurrentIrqArch, exception::InterruptArch};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn do_signal(_frame: &mut TrapFrame) {
|
||||
CurrentIrqArch::interrupt_enable();
|
||||
// todo: 处理信号
|
||||
return;
|
||||
}
|
@ -389,7 +389,6 @@ unsafe fn allocator_init() {
|
||||
|
||||
// 初始化buddy_allocator
|
||||
let buddy_allocator = unsafe { BuddyAllocator::<X86_64MMArch>::new(bump_allocator).unwrap() };
|
||||
|
||||
// 设置全局的页帧分配器
|
||||
unsafe { set_inner_allocator(buddy_allocator) };
|
||||
kinfo!("Successfully initialized buddy allocator");
|
||||
|
@ -1,15 +1,17 @@
|
||||
#[macro_use]
|
||||
pub mod asm;
|
||||
pub mod context;
|
||||
pub mod cpu;
|
||||
pub mod fpu;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
pub mod libs;
|
||||
pub mod mm;
|
||||
pub mod msi;
|
||||
pub mod pci;
|
||||
pub mod process;
|
||||
pub mod rand;
|
||||
pub mod sched;
|
||||
pub mod smp;
|
||||
pub mod syscall;
|
||||
|
||||
pub use self::pci::pci::X86_64PciArch as PciArch;
|
||||
|
13
kernel/src/arch/x86_64/process/c_adapter.rs
Normal file
13
kernel/src/arch/x86_64/process/c_adapter.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use super::table::TSSManager;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn set_current_core_tss(stack_start: usize, ist0: usize) {
|
||||
let current_tss = TSSManager::current_tss();
|
||||
current_tss.set_rsp(x86::Ring::Ring0, stack_start as u64);
|
||||
current_tss.set_ist(0, ist0 as u64);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_load_current_core_tss() {
|
||||
TSSManager::load_tr();
|
||||
}
|
98
kernel/src/arch/x86_64/process/kthread.rs
Normal file
98
kernel/src/arch/x86_64/process/kthread.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
interrupt::TrapFrame,
|
||||
process::table::{KERNEL_CS, KERNEL_DS},
|
||||
},
|
||||
process::{
|
||||
fork::CloneFlags,
|
||||
kthread::{kernel_thread_bootstrap_stage2, KernelThreadCreateInfo, KernelThreadMechanism},
|
||||
Pid, ProcessManager,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
impl KernelThreadMechanism {
|
||||
/// 伪造trapframe,创建内核线程
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回创建的内核线程的pid
|
||||
pub fn __inner_create(
|
||||
info: &Arc<KernelThreadCreateInfo>,
|
||||
clone_flags: CloneFlags,
|
||||
) -> Result<Pid, SystemError> {
|
||||
// WARNING: If create failed, we must drop the info manually or it will cause memory leak. (refcount will not decrease when create failed)
|
||||
let create_info: *const KernelThreadCreateInfo =
|
||||
KernelThreadCreateInfo::generate_unsafe_arc_ptr(info.clone());
|
||||
|
||||
let mut frame = TrapFrame::new();
|
||||
frame.rbx = create_info as usize as u64;
|
||||
frame.ds = KERNEL_DS.bits() as u64;
|
||||
frame.es = KERNEL_DS.bits() as u64;
|
||||
frame.cs = KERNEL_CS.bits() as u64;
|
||||
frame.ss = KERNEL_DS.bits() as u64;
|
||||
|
||||
// 使能中断
|
||||
frame.rflags |= 1 << 9;
|
||||
|
||||
frame.rip = kernel_thread_bootstrap_stage1 as usize as u64;
|
||||
|
||||
// fork失败的话,子线程不会执行。否则将导致内存安全问题。
|
||||
let pid = ProcessManager::fork(&mut frame, clone_flags).map_err(|e| {
|
||||
unsafe { KernelThreadCreateInfo::parse_unsafe_arc_ptr(create_info) };
|
||||
e
|
||||
})?;
|
||||
|
||||
ProcessManager::find(pid)
|
||||
.unwrap()
|
||||
.set_name(info.name().clone());
|
||||
|
||||
return Ok(pid);
|
||||
}
|
||||
}
|
||||
|
||||
/// 内核线程引导函数的第一阶段
|
||||
///
|
||||
/// 当内核线程开始执行时,会先执行这个函数,这个函数会将伪造的trapframe中的数据弹出,然后跳转到第二阶段
|
||||
///
|
||||
/// 跳转之后,指向Box<KernelThreadClosure>的指针将传入到stage2的函数
|
||||
#[naked]
|
||||
pub(super) unsafe extern "sysv64" fn kernel_thread_bootstrap_stage1() {
|
||||
asm!(
|
||||
concat!(
|
||||
"
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rbx
|
||||
pop rcx
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rax
|
||||
mov ds, ax
|
||||
pop rax
|
||||
mov es, ax
|
||||
pop rax
|
||||
add rsp, 0x20
|
||||
popfq
|
||||
add rsp, 0x10
|
||||
mov rdi, rbx
|
||||
jmp {stage2_func}
|
||||
"
|
||||
),
|
||||
stage2_func = sym kernel_thread_bootstrap_stage2,
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
496
kernel/src/arch/x86_64/process/mod.rs
Normal file
496
kernel/src/arch/x86_64/process/mod.rs
Normal file
@ -0,0 +1,496 @@
|
||||
use core::{
|
||||
arch::asm,
|
||||
intrinsics::unlikely,
|
||||
mem::ManuallyDrop,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
|
||||
use memoffset::offset_of;
|
||||
use x86::{controlregs::Cr4, segmentation::SegmentSelector};
|
||||
|
||||
use crate::{
|
||||
arch::process::table::TSSManager,
|
||||
exception::InterruptArch,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
mm::{
|
||||
percpu::{PerCpu, PerCpuVar},
|
||||
VirtAddr,
|
||||
},
|
||||
process::{
|
||||
fork::CloneFlags, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager,
|
||||
SwitchResult, SWITCH_RESULT,
|
||||
},
|
||||
syscall::{Syscall, SystemError},
|
||||
};
|
||||
|
||||
use self::{
|
||||
kthread::kernel_thread_bootstrap_stage1,
|
||||
table::{switch_fs_and_gs, KERNEL_DS, USER_DS},
|
||||
};
|
||||
|
||||
use super::{fpu::FpState, interrupt::TrapFrame, CurrentIrqArch};
|
||||
|
||||
mod c_adapter;
|
||||
pub mod kthread;
|
||||
pub mod syscall;
|
||||
pub mod table;
|
||||
|
||||
extern "C" {
|
||||
/// 从中断返回
|
||||
fn ret_from_intr();
|
||||
}
|
||||
|
||||
/// PCB中与架构相关的信息
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct ArchPCBInfo {
|
||||
rflags: usize,
|
||||
rbx: usize,
|
||||
r12: usize,
|
||||
r13: usize,
|
||||
r14: usize,
|
||||
r15: usize,
|
||||
rbp: usize,
|
||||
rsp: usize,
|
||||
rip: usize,
|
||||
cr2: usize,
|
||||
fsbase: usize,
|
||||
gsbase: usize,
|
||||
fs: u16,
|
||||
gs: u16,
|
||||
|
||||
/// 浮点寄存器的状态
|
||||
fp_state: Option<FpState>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl ArchPCBInfo {
|
||||
/// 创建一个新的ArchPCBInfo
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `kstack`:内核栈的引用,如果为None,则不会设置rsp和rbp。如果为Some,则会设置rsp和rbp为内核栈的最高地址。
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回一个新的ArchPCBInfo
|
||||
pub fn new(kstack: Option<&KernelStack>) -> Self {
|
||||
let mut r = Self {
|
||||
rflags: 0,
|
||||
rbx: 0,
|
||||
r12: 0,
|
||||
r13: 0,
|
||||
r14: 0,
|
||||
r15: 0,
|
||||
rbp: 0,
|
||||
rsp: 0,
|
||||
rip: 0,
|
||||
cr2: 0,
|
||||
fsbase: 0,
|
||||
gsbase: 0,
|
||||
fs: KERNEL_DS.bits(),
|
||||
gs: KERNEL_DS.bits(),
|
||||
fp_state: None,
|
||||
};
|
||||
|
||||
if kstack.is_some() {
|
||||
let kstack = kstack.unwrap();
|
||||
r.rsp = kstack.stack_max_address().data();
|
||||
r.rbp = kstack.stack_max_address().data();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
pub fn set_stack(&mut self, stack: VirtAddr) {
|
||||
self.rsp = stack.data();
|
||||
}
|
||||
|
||||
pub fn set_stack_base(&mut self, stack_base: VirtAddr) {
|
||||
self.rbp = stack_base.data();
|
||||
}
|
||||
|
||||
pub fn rbp(&self) -> usize {
|
||||
self.rbp
|
||||
}
|
||||
|
||||
pub unsafe fn push_to_stack(&mut self, value: usize) {
|
||||
self.rsp -= core::mem::size_of::<usize>();
|
||||
*(self.rsp as *mut usize) = value;
|
||||
}
|
||||
|
||||
pub unsafe fn pop_from_stack(&mut self) -> usize {
|
||||
let value = *(self.rsp as *const usize);
|
||||
self.rsp += core::mem::size_of::<usize>();
|
||||
value
|
||||
}
|
||||
|
||||
pub fn save_fp_state(&mut self) {
|
||||
if self.fp_state.is_none() {
|
||||
self.fp_state = Some(FpState::new());
|
||||
}
|
||||
|
||||
self.fp_state.as_mut().unwrap().save();
|
||||
}
|
||||
|
||||
pub fn restore_fp_state(&mut self) {
|
||||
if unlikely(self.fp_state.is_none()) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.fp_state.as_mut().unwrap().restore();
|
||||
}
|
||||
|
||||
pub unsafe fn save_fsbase(&mut self) {
|
||||
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
|
||||
self.fsbase = x86::current::segmentation::rdfsbase() as usize;
|
||||
} else {
|
||||
self.fsbase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn save_gsbase(&mut self) {
|
||||
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
|
||||
self.gsbase = x86::current::segmentation::rdgsbase() as usize;
|
||||
} else {
|
||||
self.gsbase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn restore_fsbase(&mut self) {
|
||||
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
|
||||
x86::current::segmentation::wrfsbase(self.fsbase as u64);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn restore_gsbase(&mut self) {
|
||||
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
|
||||
x86::current::segmentation::wrgsbase(self.gsbase as u64);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fsbase(&self) -> usize {
|
||||
self.fsbase
|
||||
}
|
||||
|
||||
pub fn gsbase(&self) -> usize {
|
||||
self.gsbase
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessControlBlock {
|
||||
/// 获取当前进程的pcb
|
||||
pub fn arch_current_pcb() -> Arc<Self> {
|
||||
// 获取栈指针
|
||||
let ptr = VirtAddr::new(x86::current::registers::rsp() as usize);
|
||||
let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1)));
|
||||
// 从内核栈的最低地址处取出pcb的地址
|
||||
let p = stack_base.data() as *const *const ProcessControlBlock;
|
||||
if unlikely((unsafe { *p }).is_null()) {
|
||||
panic!("current_pcb is null");
|
||||
}
|
||||
unsafe {
|
||||
// 为了防止内核栈的pcb指针被释放,这里需要将其包装一下,使得Arc的drop不会被调用
|
||||
let arc_wrapper: ManuallyDrop<Arc<ProcessControlBlock>> =
|
||||
ManuallyDrop::new(Arc::from_raw(*p));
|
||||
|
||||
let new_arc: Arc<ProcessControlBlock> = Arc::clone(&arc_wrapper);
|
||||
return new_arc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessManager {
|
||||
pub fn arch_init() {
|
||||
{
|
||||
// 初始化进程切换结果 per cpu变量
|
||||
let mut switch_res_vec: Vec<SwitchResult> = Vec::new();
|
||||
for _ in 0..PerCpu::MAX_CPU_NUM {
|
||||
switch_res_vec.push(SwitchResult::new());
|
||||
}
|
||||
unsafe {
|
||||
SWITCH_RESULT = Some(PerCpuVar::new(switch_res_vec).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
/// fork的过程中复制线程
|
||||
///
|
||||
/// 由于这个过程与具体的架构相关,所以放在这里
|
||||
pub fn copy_thread(
|
||||
_clone_flags: &CloneFlags,
|
||||
current_pcb: &Arc<ProcessControlBlock>,
|
||||
new_pcb: &Arc<ProcessControlBlock>,
|
||||
current_trapframe: &TrapFrame,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut child_trapframe = current_trapframe.clone();
|
||||
|
||||
// 子进程的返回值为0
|
||||
child_trapframe.set_return_value(0);
|
||||
|
||||
// 设置子进程的栈基址(开始执行中断返回流程时的栈基址)
|
||||
let mut new_arch_guard = new_pcb.arch_info();
|
||||
let kernel_stack_guard = new_pcb.kernel_stack();
|
||||
|
||||
// 设置子进程在内核态开始执行时的rsp、rbp
|
||||
new_arch_guard.set_stack_base(kernel_stack_guard.stack_max_address());
|
||||
|
||||
let trap_frame_vaddr: VirtAddr =
|
||||
kernel_stack_guard.stack_max_address() - core::mem::size_of::<TrapFrame>();
|
||||
new_arch_guard.set_stack(trap_frame_vaddr);
|
||||
|
||||
// 拷贝栈帧
|
||||
unsafe {
|
||||
let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame;
|
||||
*trap_frame_ptr = child_trapframe;
|
||||
}
|
||||
|
||||
let current_arch_guard = current_pcb.arch_info_irqsave();
|
||||
new_arch_guard.fsbase = current_arch_guard.fsbase;
|
||||
new_arch_guard.gsbase = current_arch_guard.gsbase;
|
||||
new_arch_guard.fs = current_arch_guard.fs;
|
||||
new_arch_guard.gs = current_arch_guard.gs;
|
||||
new_arch_guard.fp_state = current_arch_guard.fp_state.clone();
|
||||
|
||||
// 拷贝浮点寄存器的状态
|
||||
if let Some(fp_state) = current_arch_guard.fp_state.as_ref() {
|
||||
new_arch_guard.fp_state = Some(*fp_state);
|
||||
}
|
||||
drop(current_arch_guard);
|
||||
|
||||
// 设置返回地址(子进程开始执行的指令地址)
|
||||
|
||||
if new_pcb.flags().contains(ProcessFlags::KTHREAD) {
|
||||
let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize;
|
||||
|
||||
new_arch_guard.rip = kthread_bootstrap_stage1_func_addr;
|
||||
} else {
|
||||
new_arch_guard.rip = ret_from_intr as usize;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 切换进程
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `prev`:上一个进程的pcb
|
||||
/// - `next`:下一个进程的pcb
|
||||
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
|
||||
assert!(CurrentIrqArch::is_irq_enabled() == false);
|
||||
|
||||
// 保存浮点寄存器
|
||||
prev.arch_info().save_fp_state();
|
||||
// 切换浮点寄存器
|
||||
next.arch_info().restore_fp_state();
|
||||
|
||||
// 切换fsbase
|
||||
prev.arch_info().save_fsbase();
|
||||
next.arch_info().restore_fsbase();
|
||||
|
||||
// 切换gsbase
|
||||
prev.arch_info().save_gsbase();
|
||||
next.arch_info().restore_gsbase();
|
||||
|
||||
// 切换地址空间
|
||||
let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
next_addr_space.read().user_mapper.utable.make_current();
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
// 切换内核栈
|
||||
|
||||
// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
|
||||
let next_arch = SpinLockGuard::leak(next.arch_info());
|
||||
let prev_arch = SpinLockGuard::leak(prev.arch_info());
|
||||
|
||||
prev_arch.rip = switch_back as usize;
|
||||
|
||||
// 恢复当前的 preempt count*2
|
||||
ProcessManager::current_pcb().preempt_enable();
|
||||
ProcessManager::current_pcb().preempt_enable();
|
||||
SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev.clone());
|
||||
SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next.clone());
|
||||
|
||||
// 切换tss
|
||||
TSSManager::current_tss().set_rsp(
|
||||
x86::Ring::Ring0,
|
||||
next.kernel_stack().stack_max_address().data() as u64,
|
||||
);
|
||||
// kdebug!("switch tss ok");
|
||||
|
||||
// 正式切换上下文
|
||||
switch_to_inner(prev_arch, next_arch);
|
||||
}
|
||||
}
|
||||
|
||||
/// 保存上下文,然后切换进程,接着jmp到`switch_finish_hook`钩子函数
|
||||
#[naked]
|
||||
unsafe extern "sysv64" fn switch_to_inner(prev: &mut ArchPCBInfo, next: &mut ArchPCBInfo) {
|
||||
asm!(
|
||||
// As a quick reminder for those who are unfamiliar with the System V ABI (extern "C"):
|
||||
//
|
||||
// - the current parameters are passed in the registers `rdi`, `rsi`,
|
||||
// - we can modify scratch registers, e.g. rax
|
||||
// - we cannot change callee-preserved registers arbitrarily, e.g. rbx, which is why we
|
||||
// store them here in the first place.
|
||||
concat!("
|
||||
// Save old registers, and load new ones
|
||||
mov [rdi + {off_rbx}], rbx
|
||||
mov rbx, [rsi + {off_rbx}]
|
||||
|
||||
mov [rdi + {off_r12}], r12
|
||||
mov r12, [rsi + {off_r12}]
|
||||
|
||||
mov [rdi + {off_r13}], r13
|
||||
mov r13, [rsi + {off_r13}]
|
||||
|
||||
mov [rdi + {off_r14}], r14
|
||||
mov r14, [rsi + {off_r14}]
|
||||
|
||||
mov [rdi + {off_r15}], r15
|
||||
mov r15, [rsi + {off_r15}]
|
||||
|
||||
// switch segment registers (这些寄存器只能通过接下来的switch_hook的return来切换)
|
||||
mov [rdi + {off_fs}], fs
|
||||
mov [rdi + {off_gs}], gs
|
||||
|
||||
push rbp
|
||||
push rax
|
||||
|
||||
mov [rdi + {off_rbp}], rbp
|
||||
mov rbp, [rsi + {off_rbp}]
|
||||
|
||||
mov [rdi + {off_rsp}], rsp
|
||||
mov rsp, [rsi + {off_rsp}]
|
||||
|
||||
// // push RFLAGS (can only be modified via stack)
|
||||
pushfq
|
||||
// // pop RFLAGS into `self.rflags`
|
||||
pop QWORD PTR [rdi + {off_rflags}]
|
||||
|
||||
// // push `next.rflags`
|
||||
push QWORD PTR [rsi + {off_rflags}]
|
||||
// // pop into RFLAGS
|
||||
popfq
|
||||
|
||||
// push next rip to stack
|
||||
push QWORD PTR [rsi + {off_rip}]
|
||||
|
||||
|
||||
// When we return, we cannot even guarantee that the return address on the stack, points to
|
||||
// the calling function. Thus, we have to execute this Rust hook by
|
||||
// ourselves, which will unlock the contexts before the later switch.
|
||||
|
||||
// Note that switch_finish_hook will be responsible for executing `ret`.
|
||||
jmp {switch_hook}
|
||||
"),
|
||||
|
||||
off_rflags = const(offset_of!(ArchPCBInfo, rflags)),
|
||||
|
||||
off_rbx = const(offset_of!(ArchPCBInfo, rbx)),
|
||||
off_r12 = const(offset_of!(ArchPCBInfo, r12)),
|
||||
off_r13 = const(offset_of!(ArchPCBInfo, r13)),
|
||||
off_r14 = const(offset_of!(ArchPCBInfo, r14)),
|
||||
off_rbp = const(offset_of!(ArchPCBInfo, rbp)),
|
||||
off_rsp = const(offset_of!(ArchPCBInfo, rsp)),
|
||||
off_r15 = const(offset_of!(ArchPCBInfo, r15)),
|
||||
off_rip = const(offset_of!(ArchPCBInfo, rip)),
|
||||
off_fs = const(offset_of!(ArchPCBInfo, fs)),
|
||||
off_gs = const(offset_of!(ArchPCBInfo, gs)),
|
||||
|
||||
switch_hook = sym crate::process::switch_finish_hook,
|
||||
options(noreturn),
|
||||
);
|
||||
}
|
||||
|
||||
/// 从`switch_to_inner`返回后,执行这个函数
|
||||
///
|
||||
/// 也就是说,当进程再次被调度时,会从这里开始执行
|
||||
#[inline(never)]
|
||||
unsafe extern "sysv64" fn switch_back() {
|
||||
asm!(concat!(
|
||||
"
|
||||
pop rax
|
||||
pop rbp
|
||||
"
|
||||
))
|
||||
}
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
// 以下代码不能发生中断
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
|
||||
let current_pcb = ProcessManager::current_pcb();
|
||||
let trap_frame_vaddr = VirtAddr::new(
|
||||
current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(),
|
||||
);
|
||||
// kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr);
|
||||
let new_rip = VirtAddr::new(ret_from_intr as usize);
|
||||
|
||||
assert!(
|
||||
(x86::current::registers::rsp() as usize) < trap_frame_vaddr.data(),
|
||||
"arch_switch_to_user(): current_rsp >= fake trap
|
||||
frame vaddr, this may cause some illegal access to memory!
|
||||
rsp: {:#x}, trap_frame_vaddr: {:#x}",
|
||||
x86::current::registers::rsp() as usize,
|
||||
trap_frame_vaddr.data()
|
||||
);
|
||||
|
||||
let mut arch_guard = current_pcb.arch_info_irqsave();
|
||||
arch_guard.rsp = trap_frame_vaddr.data();
|
||||
|
||||
arch_guard.fs = USER_DS.bits();
|
||||
arch_guard.gs = USER_DS.bits();
|
||||
|
||||
switch_fs_and_gs(
|
||||
SegmentSelector::from_bits_truncate(arch_guard.fs),
|
||||
SegmentSelector::from_bits_truncate(arch_guard.gs),
|
||||
);
|
||||
arch_guard.rip = new_rip.data();
|
||||
|
||||
drop(arch_guard);
|
||||
|
||||
// 删除kthread的标志
|
||||
current_pcb.flags().remove(ProcessFlags::KTHREAD);
|
||||
current_pcb.worker_private().take();
|
||||
|
||||
let mut trap_frame = TrapFrame::new();
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}",
|
||||
pid = current_pcb.pid(),
|
||||
e = e
|
||||
);
|
||||
});
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||
|
||||
drop(current_pcb);
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
ready_to_switch_to_user(trap_frame, trap_frame_vaddr.data(), new_rip.data());
|
||||
}
|
||||
|
||||
/// 由于需要依赖ret来切换到用户态,所以不能inline
|
||||
#[inline(never)]
|
||||
unsafe extern "sysv64" fn ready_to_switch_to_user(
|
||||
trap_frame: TrapFrame,
|
||||
trapframe_vaddr: usize,
|
||||
new_rip: usize,
|
||||
) -> ! {
|
||||
*(trapframe_vaddr as *mut TrapFrame) = trap_frame;
|
||||
asm!(
|
||||
"mov rsp, {trapframe_vaddr}",
|
||||
"push {new_rip}",
|
||||
"ret",
|
||||
trapframe_vaddr = in(reg) trapframe_vaddr,
|
||||
new_rip = in(reg) new_rip
|
||||
);
|
||||
unreachable!()
|
||||
}
|
116
kernel/src/arch/x86_64/process/syscall.rs
Normal file
116
kernel/src/arch/x86_64/process/syscall.rs
Normal file
@ -0,0 +1,116 @@
|
||||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
interrupt::TrapFrame,
|
||||
process::table::{USER_CS, USER_DS},
|
||||
CurrentIrqArch,
|
||||
},
|
||||
exception::InterruptArch,
|
||||
mm::ucontext::AddressSpace,
|
||||
process::{
|
||||
exec::{load_binary_file, ExecParam, ExecParamFlags},
|
||||
ProcessManager,
|
||||
},
|
||||
syscall::{Syscall, SystemError},
|
||||
};
|
||||
|
||||
impl Syscall {
|
||||
pub fn do_execve(
|
||||
path: String,
|
||||
argv: Vec<String>,
|
||||
envp: Vec<String>,
|
||||
regs: &mut TrapFrame,
|
||||
) -> Result<(), SystemError> {
|
||||
// kdebug!(
|
||||
// "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
|
||||
// path,
|
||||
// argv,
|
||||
// envp
|
||||
// );
|
||||
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
|
||||
let mut basic_info = pcb.basic_mut();
|
||||
// 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
|
||||
let old_address_space = basic_info.user_vm();
|
||||
|
||||
// 在pcb中原来的用户地址空间
|
||||
unsafe {
|
||||
basic_info.set_user_vm(None);
|
||||
}
|
||||
// 创建新的地址空间并设置为当前地址空间
|
||||
let address_space = AddressSpace::new(true).expect("Failed to create new address space");
|
||||
unsafe {
|
||||
basic_info.set_user_vm(Some(address_space.clone()));
|
||||
}
|
||||
|
||||
// to avoid deadlock
|
||||
drop(basic_info);
|
||||
|
||||
assert!(
|
||||
AddressSpace::is_current(&address_space),
|
||||
"Failed to set address space"
|
||||
);
|
||||
// kdebug!("Switch to new address space");
|
||||
|
||||
// 切换到新的用户地址空间
|
||||
unsafe { address_space.read().user_mapper.utable.make_current() };
|
||||
|
||||
drop(old_address_space);
|
||||
drop(irq_guard);
|
||||
// kdebug!("to load binary file");
|
||||
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
|
||||
|
||||
// 加载可执行文件
|
||||
let load_result = load_binary_file(&mut param)
|
||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
||||
// kdebug!("load binary file done");
|
||||
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||
param.init_info_mut().args = argv;
|
||||
param.init_info_mut().envs = envp;
|
||||
|
||||
// 把proc_init_info写到用户栈上
|
||||
|
||||
let (user_sp, argv_ptr) = unsafe {
|
||||
param
|
||||
.init_info()
|
||||
.push_at(
|
||||
address_space
|
||||
.write()
|
||||
.user_stack_mut()
|
||||
.expect("No user stack found"),
|
||||
)
|
||||
.expect("Failed to push proc_init_info to user stack")
|
||||
};
|
||||
|
||||
// kdebug!("write proc_init_info to user stack done");
|
||||
|
||||
// (兼容旧版libc)把argv的指针写到寄存器内
|
||||
// TODO: 改写旧版libc,不再需要这个兼容
|
||||
regs.rdi = param.init_info().args.len() as u64;
|
||||
regs.rsi = argv_ptr.data() as u64;
|
||||
|
||||
// 设置系统调用返回时的寄存器状态
|
||||
// TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
|
||||
regs.rsp = user_sp.data() as u64;
|
||||
regs.rbp = user_sp.data() as u64;
|
||||
regs.rip = load_result.entry_point().data() as u64;
|
||||
|
||||
regs.cs = USER_CS.bits() as u64;
|
||||
regs.ds = USER_DS.bits() as u64;
|
||||
regs.ss = USER_DS.bits() as u64;
|
||||
regs.es = 0;
|
||||
regs.rflags = 0x200;
|
||||
regs.rax = 1;
|
||||
|
||||
// kdebug!("regs: {:?}\n", regs);
|
||||
|
||||
// kdebug!(
|
||||
// "tmp_rs_execve: done, load_result.entry_point()={:?}",
|
||||
// load_result.entry_point()
|
||||
// );
|
||||
return Ok(());
|
||||
}
|
||||
}
|
75
kernel/src/arch/x86_64/process/table.rs
Normal file
75
kernel/src/arch/x86_64/process/table.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use x86::{current::task::TaskStateSegment, segmentation::SegmentSelector, Ring};
|
||||
|
||||
use crate::{
|
||||
mm::{percpu::PerCpu, VirtAddr},
|
||||
smp::core::smp_get_processor_id,
|
||||
};
|
||||
|
||||
// === 段选择子在GDT中的索引 ===
|
||||
/// kernel code segment selector
|
||||
pub const KERNEL_CS: SegmentSelector = SegmentSelector::new(1, Ring::Ring0);
|
||||
/// kernel data segment selector
|
||||
pub const KERNEL_DS: SegmentSelector = SegmentSelector::new(2, Ring::Ring0);
|
||||
/// user code segment selector
|
||||
pub const USER_CS: SegmentSelector = SegmentSelector::new(5, Ring::Ring3);
|
||||
/// user data segment selector
|
||||
pub const USER_DS: SegmentSelector = SegmentSelector::new(6, Ring::Ring3);
|
||||
|
||||
static mut TSS_MANAGER: TSSManager = TSSManager::new();
|
||||
|
||||
extern "C" {
|
||||
static mut GDT_Table: [u64; 512];
|
||||
}
|
||||
/// 切换fs和gs段寄存器
|
||||
///
|
||||
/// 由于需要return使得它生效,所以不能inline
|
||||
#[inline(never)]
|
||||
pub unsafe fn switch_fs_and_gs(fs: SegmentSelector, gs: SegmentSelector) {
|
||||
x86::segmentation::load_fs(fs);
|
||||
x86::segmentation::load_gs(gs);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TSSManager {
|
||||
tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM],
|
||||
}
|
||||
|
||||
impl TSSManager {
|
||||
const fn new() -> Self {
|
||||
return Self {
|
||||
tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM],
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取当前CPU的TSS
|
||||
pub unsafe fn current_tss() -> &'static mut TaskStateSegment {
|
||||
&mut TSS_MANAGER.tss[smp_get_processor_id() as usize]
|
||||
}
|
||||
|
||||
/// 加载当前CPU的TSS
|
||||
pub unsafe fn load_tr() {
|
||||
let index = (10 + smp_get_processor_id() * 2) as u16;
|
||||
let selector = SegmentSelector::new(index, Ring::Ring0);
|
||||
|
||||
Self::set_tss_descriptor(
|
||||
index,
|
||||
VirtAddr::new(Self::current_tss() as *mut TaskStateSegment as usize),
|
||||
);
|
||||
x86::task::load_tr(selector);
|
||||
}
|
||||
|
||||
unsafe fn set_tss_descriptor(index: u16, vaddr: VirtAddr) {
|
||||
const LIMIT: u64 = 103;
|
||||
let gdt_vaddr = VirtAddr::new(&GDT_Table as *const _ as usize);
|
||||
|
||||
let gdt: &mut [u64] = core::slice::from_raw_parts_mut(gdt_vaddr.data() as *mut u64, 512);
|
||||
|
||||
let vaddr = vaddr.data() as u64;
|
||||
gdt[index as usize] = (LIMIT & 0xffff)
|
||||
| ((vaddr & 0xffff) << 16)
|
||||
| (((vaddr >> 16) & 0xff) << 32)
|
||||
| (0x89 << 40)
|
||||
| (((vaddr >> 24) & 0xff) << 56);
|
||||
gdt[index as usize + 1] = ((vaddr >> 32) & 0xffffffff) | 0;
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
use crate::include::bindings::bindings::{enter_syscall_int, SYS_SCHED};
|
||||
use crate::{include::bindings::bindings::enter_syscall_int, syscall::SYS_SCHED};
|
||||
|
||||
/// @brief 若内核代码不处在中断上下文中,那么将可以使用本函数,发起一个sys_sched系统调用,然后运行调度器。
|
||||
/// 由于只能在中断上下文中进行进程切换,因此需要发起一个系统调用SYS_SCHED。
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sched() {
|
||||
unsafe {
|
||||
enter_syscall_int(SYS_SCHED.into(), 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
enter_syscall_int(SYS_SCHED as u64, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
61
kernel/src/arch/x86_64/smp/mod.rs
Normal file
61
kernel/src/arch/x86_64/smp/mod.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use core::{arch::asm, hint::spin_loop, sync::atomic::compiler_fence};
|
||||
|
||||
use memoffset::offset_of;
|
||||
|
||||
use crate::{
|
||||
arch::process::table::TSSManager, exception::InterruptArch,
|
||||
include::bindings::bindings::cpu_core_info, kdebug, process::ProcessManager,
|
||||
smp::core::smp_get_processor_id,
|
||||
};
|
||||
|
||||
use super::CurrentIrqArch;
|
||||
|
||||
extern "C" {
|
||||
fn smp_ap_start_stage2();
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct ApStartStackInfo {
|
||||
vaddr: usize,
|
||||
}
|
||||
|
||||
/// AP处理器启动时执行
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn smp_ap_start() -> ! {
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
let vaddr = cpu_core_info[smp_get_processor_id() as usize].stack_start as usize;
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
let v = ApStartStackInfo { vaddr };
|
||||
smp_init_switch_stack(&v);
|
||||
}
|
||||
|
||||
#[naked]
|
||||
unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! {
|
||||
asm!(concat!("
|
||||
mov rsp, [rdi + {off_rsp}]
|
||||
mov rbp, [rdi + {off_rsp}]
|
||||
jmp {stage1}
|
||||
"),
|
||||
off_rsp = const(offset_of!(ApStartStackInfo, vaddr)),
|
||||
stage1 = sym smp_ap_start_stage1,
|
||||
options(noreturn));
|
||||
}
|
||||
|
||||
unsafe extern "C" fn smp_ap_start_stage1() -> ! {
|
||||
let id = smp_get_processor_id();
|
||||
kdebug!("smp_ap_start_stage1: id: {}\n", id);
|
||||
let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id() as usize].clone();
|
||||
|
||||
let tss = TSSManager::current_tss();
|
||||
|
||||
tss.set_rsp(
|
||||
x86::Ring::Ring0,
|
||||
current_idle.kernel_stack().stack_max_address().data() as u64,
|
||||
);
|
||||
TSSManager::load_tr();
|
||||
|
||||
smp_ap_start_stage2();
|
||||
loop {
|
||||
spin_loop();
|
||||
}
|
||||
}
|
@ -1,28 +1,15 @@
|
||||
use core::{ffi::c_void, panic};
|
||||
use core::ffi::c_void;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use alloc::string::String;
|
||||
|
||||
use crate::{
|
||||
arch::{asm::current::current_pcb, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
filesystem::vfs::MAX_PATHLEN,
|
||||
include::bindings::bindings::{
|
||||
pt_regs, set_system_trap_gate, CLONE_FS, CLONE_SIGNAL, CLONE_VM, USER_CS, USER_DS,
|
||||
},
|
||||
ipc::signal::sys_rt_sigreturn,
|
||||
mm::{ucontext::AddressSpace, verify_area, VirtAddr},
|
||||
process::exec::{load_binary_file, ExecParam, ExecParamFlags},
|
||||
syscall::{
|
||||
user_access::{check_and_clone_cstr, check_and_clone_cstr_array},
|
||||
Syscall, SystemError, SYS_EXECVE, SYS_FORK, SYS_RT_SIGRETURN, SYS_VFORK,
|
||||
},
|
||||
include::bindings::bindings::set_system_trap_gate,
|
||||
syscall::{Syscall, SystemError, SYS_RT_SIGRETURN},
|
||||
};
|
||||
|
||||
use super::{asm::ptrace::user_mode, mm::barrier::mfence};
|
||||
use super::{interrupt::TrapFrame, mm::barrier::mfence};
|
||||
|
||||
extern "C" {
|
||||
fn do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u64;
|
||||
|
||||
fn syscall_int();
|
||||
}
|
||||
|
||||
@ -35,85 +22,28 @@ macro_rules! syscall_return {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
|
||||
let syscall_num = regs.rax as usize;
|
||||
pub extern "C" fn syscall_handler(frame: &mut TrapFrame) -> () {
|
||||
let syscall_num = frame.rax as usize;
|
||||
let args = [
|
||||
regs.r8 as usize,
|
||||
regs.r9 as usize,
|
||||
regs.r10 as usize,
|
||||
regs.r11 as usize,
|
||||
regs.r12 as usize,
|
||||
regs.r13 as usize,
|
||||
regs.r14 as usize,
|
||||
regs.r15 as usize,
|
||||
frame.r8 as usize,
|
||||
frame.r9 as usize,
|
||||
frame.r10 as usize,
|
||||
frame.r11 as usize,
|
||||
frame.r12 as usize,
|
||||
frame.r13 as usize,
|
||||
frame.r14 as usize,
|
||||
frame.r15 as usize,
|
||||
];
|
||||
mfence();
|
||||
mfence();
|
||||
let from_user = user_mode(regs);
|
||||
|
||||
// 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。
|
||||
match syscall_num {
|
||||
SYS_FORK => unsafe {
|
||||
syscall_return!(do_fork(regs, 0, regs.rsp, 0), regs);
|
||||
},
|
||||
SYS_VFORK => unsafe {
|
||||
syscall_return!(
|
||||
do_fork(
|
||||
regs,
|
||||
(CLONE_VM | CLONE_FS | CLONE_SIGNAL) as u64,
|
||||
regs.rsp,
|
||||
0,
|
||||
),
|
||||
regs
|
||||
);
|
||||
},
|
||||
SYS_EXECVE => {
|
||||
let path_ptr = args[0];
|
||||
let argv_ptr = args[1];
|
||||
let env_ptr = args[2];
|
||||
|
||||
// 权限校验
|
||||
if from_user
|
||||
&& (verify_area(VirtAddr::new(path_ptr), MAX_PATHLEN).is_err()
|
||||
|| verify_area(VirtAddr::new(argv_ptr), MAX_PATHLEN).is_err()
|
||||
|| verify_area(VirtAddr::new(env_ptr), MAX_PATHLEN).is_err())
|
||||
{
|
||||
syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs);
|
||||
} else {
|
||||
unsafe {
|
||||
// kdebug!("syscall: execve\n");
|
||||
syscall_return!(
|
||||
rs_do_execve(
|
||||
path_ptr as *const u8,
|
||||
argv_ptr as *const *const u8,
|
||||
env_ptr as *const *const u8,
|
||||
regs
|
||||
),
|
||||
regs
|
||||
);
|
||||
// let path = String::from("/bin/about.elf");
|
||||
// let argv = vec![String::from("/bin/about.elf")];
|
||||
// let envp = vec![String::from("PATH=/bin")];
|
||||
// let r = tmp_rs_execve(path, argv, envp, regs);
|
||||
// kdebug!("syscall: execve r: {:?}\n", r);
|
||||
|
||||
// syscall_return!(
|
||||
// r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize),
|
||||
// regs
|
||||
// )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SYS_RT_SIGRETURN => {
|
||||
syscall_return!(sys_rt_sigreturn(regs), regs);
|
||||
syscall_return!(SystemError::ENOSYS.to_posix_errno() as usize, frame);
|
||||
}
|
||||
// SYS_SCHED => {
|
||||
// syscall_return!(sched(from_user) as u64, regs);
|
||||
// }
|
||||
_ => {}
|
||||
}
|
||||
syscall_return!(Syscall::handle(syscall_num, &args, from_user) as u64, regs);
|
||||
syscall_return!(Syscall::handle(syscall_num, &args, frame) as u64, frame);
|
||||
}
|
||||
|
||||
/// 系统调用初始化
|
||||
@ -123,142 +53,15 @@ pub fn arch_syscall_init() -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn rs_do_execve(
|
||||
path: *const u8,
|
||||
argv: *const *const u8,
|
||||
envp: *const *const u8,
|
||||
regs: &mut pt_regs,
|
||||
) -> usize {
|
||||
if path.is_null() {
|
||||
return SystemError::EINVAL.to_posix_errno() as usize;
|
||||
}
|
||||
|
||||
let x = || {
|
||||
let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
|
||||
let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
|
||||
let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
|
||||
Ok((path, argv, envp))
|
||||
};
|
||||
let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
|
||||
if let Err(e) = r {
|
||||
panic!("Failed to execve: {:?}", e);
|
||||
}
|
||||
let (path, argv, envp) = r.unwrap();
|
||||
|
||||
return tmp_rs_execve(path, argv, envp, regs)
|
||||
.map(|_| 0)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Failed to execve, pid: {} error: {:?}",
|
||||
current_pcb().pid,
|
||||
e
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/// 执行第一个用户进程的函数(只应该被调用一次)
|
||||
///
|
||||
/// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_exec_init_process(regs: &mut pt_regs) -> usize {
|
||||
pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> usize {
|
||||
let path = String::from("/bin/shell.elf");
|
||||
let argv = vec![String::from("/bin/shell.elf")];
|
||||
let envp = vec![String::from("PATH=/bin")];
|
||||
let r = tmp_rs_execve(path, argv, envp, regs);
|
||||
let r = Syscall::do_execve(path, argv, envp, frame);
|
||||
// kdebug!("rs_exec_init_process: r: {:?}\n", r);
|
||||
return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize);
|
||||
}
|
||||
|
||||
/// 临时的execve系统调用实现,以后要把它改为普通的系统调用。
|
||||
///
|
||||
/// 现在放在这里的原因是,还没有重构中断管理模块,未实现TrapFrame这个抽象,
|
||||
/// 导致我们必须手动设置中断返回时,各个寄存器的值,这个过程很繁琐,所以暂时放在这里。
|
||||
fn tmp_rs_execve(
|
||||
path: String,
|
||||
argv: Vec<String>,
|
||||
envp: Vec<String>,
|
||||
regs: &mut pt_regs,
|
||||
) -> Result<(), SystemError> {
|
||||
// kdebug!(
|
||||
// "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
|
||||
// path,
|
||||
// argv,
|
||||
// envp
|
||||
// );
|
||||
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
// 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
|
||||
let old_address_space = current_pcb().address_space();
|
||||
// 在pcb中原来的用户地址空间
|
||||
unsafe {
|
||||
current_pcb().drop_address_space();
|
||||
}
|
||||
// 创建新的地址空间并设置为当前地址空间
|
||||
let address_space = AddressSpace::new(true).expect("Failed to create new address space");
|
||||
unsafe {
|
||||
current_pcb().set_address_space(address_space.clone());
|
||||
}
|
||||
assert!(
|
||||
AddressSpace::is_current(&address_space),
|
||||
"Failed to set address space"
|
||||
);
|
||||
// kdebug!("Switch to new address space");
|
||||
|
||||
// 切换到新的用户地址空间
|
||||
unsafe { address_space.read().user_mapper.utable.make_current() };
|
||||
|
||||
drop(old_address_space);
|
||||
drop(irq_guard);
|
||||
// kdebug!("to load binary file");
|
||||
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
|
||||
// 加载可执行文件
|
||||
let load_result = load_binary_file(&mut param)
|
||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
||||
// kdebug!("load binary file done");
|
||||
|
||||
param.init_info_mut().args = argv;
|
||||
param.init_info_mut().envs = envp;
|
||||
|
||||
// 把proc_init_info写到用户栈上
|
||||
|
||||
let (user_sp, argv_ptr) = unsafe {
|
||||
param
|
||||
.init_info()
|
||||
.push_at(
|
||||
address_space
|
||||
.write()
|
||||
.user_stack_mut()
|
||||
.expect("No user stack found"),
|
||||
)
|
||||
.expect("Failed to push proc_init_info to user stack")
|
||||
};
|
||||
|
||||
// kdebug!("write proc_init_info to user stack done");
|
||||
|
||||
// (兼容旧版libc)把argv的指针写到寄存器内
|
||||
// TODO: 改写旧版libc,不再需要这个兼容
|
||||
regs.rdi = param.init_info().args.len() as u64;
|
||||
regs.rsi = argv_ptr.data() as u64;
|
||||
|
||||
// 设置系统调用返回时的寄存器状态
|
||||
// TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
|
||||
regs.rsp = user_sp.data() as u64;
|
||||
regs.rbp = user_sp.data() as u64;
|
||||
regs.rip = load_result.entry_point().data() as u64;
|
||||
|
||||
regs.cs = USER_CS as u64 | 3;
|
||||
regs.ds = USER_DS as u64 | 3;
|
||||
regs.ss = USER_DS as u64 | 3;
|
||||
regs.es = 0;
|
||||
regs.rflags = 0x200;
|
||||
regs.rax = 1;
|
||||
|
||||
// kdebug!("regs: {:?}\n", regs);
|
||||
|
||||
// kdebug!(
|
||||
// "tmp_rs_execve: done, load_result.entry_point()={:?}",
|
||||
// load_result.entry_point()
|
||||
// );
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <DragonOS/stdint.h>
|
||||
#include <common/glib.h>
|
||||
#include <common/mutex.h>
|
||||
#include <common/semaphore.h>
|
||||
|
||||
#define BLK_TYPE_AHCI 0
|
||||
|
||||
@ -83,5 +81,4 @@ struct blk_gendisk
|
||||
struct block_device *partition; // 磁盘分区数组
|
||||
const struct block_device_operation *fops; // 磁盘操作
|
||||
void *private_data;
|
||||
mutex_t open_mutex; // open()/close()操作的互斥锁
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <process/process.h>
|
||||
#include <time/sleep.h>
|
||||
#include <time/timer.h>
|
||||
|
||||
// 永久地设置该completion已经被完成,不会再有进程等待
|
||||
#define COMPLETE_ALL UINT32_MAX
|
||||
|
||||
struct completion
|
||||
{
|
||||
unsigned int done;
|
||||
wait_queue_head_t wait_queue;
|
||||
};
|
||||
|
||||
#define DECLARE_COMPLETION_ON_STACK(name) \
|
||||
struct completion name = {0}; \
|
||||
completion_init(&name);
|
||||
|
||||
/**
|
||||
* 对外函数声明
|
||||
*/
|
||||
void completion_init(struct completion *x);
|
||||
void complete(struct completion *x);
|
||||
void complete_all(struct completion *x);
|
||||
void wait_for_completion(struct completion *x);
|
||||
long wait_for_completion_timeout(struct completion *x, long timeout);
|
||||
void wait_for_completion_interruptible(struct completion *x);
|
||||
long wait_for_completion_interruptible_timeout(struct completion *x, long timeout);
|
||||
void wait_for_multicompletion(struct completion x[], int n);
|
||||
bool try_wait_for_completion(struct completion *x);
|
||||
bool completion_done(struct completion *x);
|
||||
struct completion *completion_alloc();
|
||||
/**
|
||||
* 测试函数声明 (测试代码辅助函数)
|
||||
*/
|
||||
struct __test_data
|
||||
{
|
||||
int id;
|
||||
struct completion *one_to_one;
|
||||
struct completion *one_to_many;
|
||||
struct completion *many_to_one;
|
||||
};
|
||||
|
||||
int __test_completion_waiter(void *data); // 等待者
|
||||
int __test_completion_worker(void *data); // 执行者
|
||||
void __test_completion();
|
@ -56,7 +56,6 @@ struct cpu_core_info_t
|
||||
{
|
||||
uint64_t stack_start; // 栈基地址
|
||||
uint64_t ist_stack_start; // IST栈基地址
|
||||
uint64_t tss_vaddr; // tss地址
|
||||
};
|
||||
|
||||
extern struct cpu_core_info_t cpu_core_info[MAX_CPU_NUM];
|
||||
|
@ -358,10 +358,3 @@ Values in this inclusive range are reserved for OS-specific semantics.
|
||||
|
||||
|
||||
// --> end ========== program header =========
|
||||
|
||||
/**
|
||||
* @brief 校验是否为ELF文件
|
||||
*
|
||||
* @param ehdr
|
||||
*/
|
||||
bool elf_check(void * ehdr);
|
@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/err.h>
|
||||
#include <common/numa.h>
|
||||
#include <process/proc-types.h>
|
||||
#include <process/process.h>
|
||||
|
||||
/**
|
||||
* @brief kthread信息
|
||||
* 该结构体将会绑定到pcb的worker_private中
|
||||
*/
|
||||
struct kthread_info_t
|
||||
{
|
||||
uint64_t flags;
|
||||
uint32_t cpu;
|
||||
int result;
|
||||
int (*thread_fn)(void *);
|
||||
void *data;
|
||||
// todo: 将这里改为completion机制
|
||||
bool exited; // 是否已退出
|
||||
char *full_name; // 内核线程的名称
|
||||
};
|
||||
|
||||
struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node,
|
||||
const char name_fmt[], ...);
|
||||
/**
|
||||
* @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_create(thread_fn, data, name_fmt, arg...) \
|
||||
kthread_create_on_node(thread_fn, data, NUMA_NO_NODE, name_fmt, ##arg)
|
||||
|
||||
/**
|
||||
* @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(thread_fn, data, name_fmt, ...) \
|
||||
({ \
|
||||
struct process_control_block *__kt = kthread_create(thread_fn, data, name_fmt, ##__VA_ARGS__); \
|
||||
if (!IS_ERR(__kt)) \
|
||||
process_wakeup(__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发送停止信号,请求其结束
|
||||
*
|
||||
* @param pcb 内核线程的pcb
|
||||
* @return int 错误码
|
||||
*/
|
||||
int kthread_stop(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出
|
||||
*
|
||||
* @return true 内核线程应该退出
|
||||
* @return false 无需退出
|
||||
*/
|
||||
bool kthread_should_stop(void);
|
||||
|
||||
/**
|
||||
* @brief 让当前内核线程退出,并返回result参数给kthread_stop()函数
|
||||
*
|
||||
* @param result 返回值
|
||||
*/
|
||||
void kthread_exit(long result);
|
||||
|
||||
/**
|
||||
* @brief 初始化kthread机制(只应被process_init调用)
|
||||
*
|
||||
* @return int 错误码
|
||||
*/
|
||||
int kthread_mechanism_init();
|
||||
|
||||
/**
|
||||
* @brief 设置pcb中的worker_private字段(只应被设置一次)
|
||||
*
|
||||
* @param pcb pcb
|
||||
* @return bool 成功或失败
|
||||
*/
|
||||
bool kthread_set_worker_private(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 获取pcb中的kthread结构体
|
||||
*
|
||||
* @param pcb pcb
|
||||
* @return struct kthread* kthread信息结构体
|
||||
*/
|
||||
struct kthread_info_t *to_kthread(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 释放pcb指向的worker private
|
||||
*
|
||||
* @param pcb 要释放的pcb
|
||||
*/
|
||||
void free_kthread_struct(struct process_control_block *pcb);
|
@ -1,69 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/atomic.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/glib.h>
|
||||
#include <process/proc-types.h>
|
||||
|
||||
/**
|
||||
* @brief Mutex - 互斥锁
|
||||
*
|
||||
* - 同一时间只有1个任务可以持有mutex
|
||||
* - 不允许递归地加锁、解锁
|
||||
* - 只允许通过mutex的api来操作mutex
|
||||
* - 在硬中断、软中断中不能使用mutex
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
|
||||
atomic_t count; // 锁计数。1->已解锁。 0->已上锁,且有可能存在等待者
|
||||
spinlock_t wait_lock; // mutex操作锁,用于对mutex的list的操作进行加锁
|
||||
struct List wait_list; // Mutex的等待队列
|
||||
} mutex_t;
|
||||
|
||||
/**
|
||||
* @brief 在mutex上的等待者的结构体
|
||||
*
|
||||
*/
|
||||
struct mutex_waiter_t
|
||||
{
|
||||
struct List list;
|
||||
struct process_control_block *pcb;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化互斥量
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_init(mutex_t *lock);
|
||||
|
||||
/**
|
||||
* @brief 对互斥量加锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_lock(mutex_t *lock);
|
||||
|
||||
/**
|
||||
* @brief 对互斥量解锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_unlock(mutex_t *lock);
|
||||
|
||||
/**
|
||||
* @brief 尝试对互斥量加锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*
|
||||
* @return 成功加锁->1, 加锁失败->0
|
||||
*/
|
||||
int mutex_trylock(mutex_t *lock);
|
||||
|
||||
/**
|
||||
* @brief 判断mutex是否已被加锁
|
||||
*
|
||||
* @return 已加锁->1, 未加锁->0
|
||||
*/
|
||||
#define mutex_is_locked(lock) ((atomic_read(&(lock)->count) == 1) ? 0 : 1)
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @file semaphore.h
|
||||
* @author fslngjin (lonjin@RinGoTek.cn)
|
||||
* @brief 信号量
|
||||
* @version 0.1
|
||||
* @date 2022-04-12
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <common/atomic.h>
|
||||
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
/**
|
||||
* @brief 信号量的结构体
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
atomic_t counter;
|
||||
wait_queue_node_t wait_queue;
|
||||
} semaphore_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化信号量
|
||||
*
|
||||
* @param sema 信号量对象
|
||||
* @param count 信号量的初始值
|
||||
*/
|
||||
static __always_inline void semaphore_init(semaphore_t *sema, ul count)
|
||||
{
|
||||
atomic_set(&sema->counter, count);
|
||||
wait_queue_init(&sema->wait_queue, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 信号量down
|
||||
*
|
||||
* @param sema
|
||||
*/
|
||||
void semaphore_down(semaphore_t *sema);
|
||||
|
||||
void semaphore_up(semaphore_t *sema);
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "./sys/types.h"
|
||||
|
||||
#define NULL 0
|
||||
#define NULL (void*)0
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t; // Signed integer type of the result of subtracting two pointers.
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// todo: 引入用户命名空间
|
||||
struct user_namespace
|
||||
{
|
||||
|
||||
};
|
@ -1,118 +0,0 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
#include <common/spinlock.h>
|
||||
struct process_control_block;
|
||||
|
||||
// todo: 按照linux里面的样子,修正等待队列。也就是修正好wait_queue_node和wait_queue_head的意思。
|
||||
|
||||
/**
|
||||
* @brief 信号量的等待队列
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
struct List wait_list;
|
||||
struct process_control_block *pcb;
|
||||
} wait_queue_node_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化等待队列
|
||||
*
|
||||
* @param wait_queue 等待队列
|
||||
* @param pcb pcb
|
||||
*/
|
||||
void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head, void *lock);
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断)
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head);
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程
|
||||
*
|
||||
* @param wait_queue_head 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct List wait_list;
|
||||
spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
|
||||
} wait_queue_head_t;
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK(name, pcb) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK_SELF(name) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC(name, pcb) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC_SELF(name) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
||||
struct wait_queue_head_t name = {0}; \
|
||||
wait_queue_head_init(&name);
|
||||
|
||||
/**
|
||||
* @brief 初始化wait_queue队列头
|
||||
*
|
||||
* @param wait_queue
|
||||
*/
|
||||
void wait_queue_head_init(wait_queue_head_t *wait_queue);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
* @param lock
|
||||
*/
|
||||
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
|
||||
*
|
||||
* @param wait_queue_head_t q: 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);
|
@ -36,7 +36,7 @@ void traceback(struct pt_regs *regs)
|
||||
// 先检验是否为用户态出错,若为用户态出错,则直接返回
|
||||
if (verify_area(regs->rbp, 0))
|
||||
{
|
||||
printk_color(YELLOW, BLACK, "Kernel traceback: Fault in userland. pid=%ld, rbp=%#018lx\n", current_pcb->pid, regs->rbp);
|
||||
printk_color(YELLOW, BLACK, "Kernel traceback: Fault in userland. pid=%ld, rbp=%#018lx\n", rs_current_pcb_pid(), regs->rbp);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ void traceback(struct pt_regs *regs)
|
||||
|
||||
// 当前栈帧的rbp的地址大于等于内核栈的rbp的时候,表明调用栈已经到头了,追踪结束。
|
||||
// 当前rbp的地址为用户空间时,直接退出
|
||||
if((uint64_t)(rbp) >= current_pcb->thread->rbp || ((uint64_t)rbp<regs->rsp))
|
||||
if ((uint64_t)(rbp) >= rs_current_pcb_thread_rbp() || ((uint64_t)rbp < regs->rsp))
|
||||
break;
|
||||
|
||||
printk_color(ORANGE, BLACK, "rbp:%#018lx,*rbp:%#018lx\n", rbp, *rbp);
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
kernel_driver_subdirs:=video interrupt pci acpi disk keyboard mouse multiboot2 timers hid
|
||||
kernel_driver_subdirs:=interrupt pci acpi disk keyboard mouse multiboot2 timers hid
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
@ -151,13 +151,6 @@ impl core::hash::Hash for DeviceNumber {
|
||||
}
|
||||
|
||||
impl DeviceNumber {
|
||||
/// @brief: 设备号创建
|
||||
/// @parameter: dev_t: 设备号
|
||||
/// @return: 设备号实例
|
||||
pub fn new(dev_t: usize) -> DeviceNumber {
|
||||
Self(dev_t)
|
||||
}
|
||||
|
||||
/// @brief: 获取主设备号
|
||||
/// @parameter: none
|
||||
/// @return: 主设备号
|
||||
|
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief 初始化ahci模块
|
||||
*
|
||||
*/
|
||||
extern void ahci_init();
|
@ -45,16 +45,6 @@ const AHCI_SUBCLASS: u8 = 0x6;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const HBA_PxIS_TFES: u32 = 1 << 30;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ahci_init() -> i32 {
|
||||
let r = ahci_rust_init();
|
||||
if r.is_ok() {
|
||||
return 0;
|
||||
} else {
|
||||
return r.unwrap_err().to_posix_errno();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 寻找所有的ahci设备
|
||||
/// @param list 链表的写锁
|
||||
/// @return Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> 成功则返回包含所有ahci设备结构体的可变引用的链表,失败则返回err
|
||||
@ -66,12 +56,12 @@ fn ahci_device_search<'a>(
|
||||
if result.is_empty() {
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
kdebug!("{}", result.len());
|
||||
Ok(result)
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// @brief: 初始化 ahci
|
||||
pub fn ahci_rust_init() -> Result<(), SystemError> {
|
||||
pub fn ahci_init() -> Result<(), SystemError> {
|
||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||
let ahci_device = ahci_device_search(&mut list)?;
|
||||
// 全局数据 - 列表
|
||||
@ -193,7 +183,7 @@ fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
|
||||
|
||||
/// @brief: 测试函数
|
||||
pub fn __test_ahci() {
|
||||
let _res = ahci_rust_init();
|
||||
let _res = ahci_init();
|
||||
let disk: Arc<LockedAhciDisk> = get_disks_by_name("ahci_disk_0".to_string()).unwrap();
|
||||
#[deny(overflowing_literals)]
|
||||
let mut buf = [0u8; 3000usize];
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <common/printk.h>
|
||||
#include <driver/acpi/acpi.h>
|
||||
#include <exception/gate.h>
|
||||
|
||||
#include <driver/uart/uart.h>
|
||||
#include <exception/softirq.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
@ -15,6 +15,9 @@
|
||||
#pragma GCC optimize("O0")
|
||||
// 导出定义在irq.c中的中段门表
|
||||
extern void (*interrupt_table[24])(void);
|
||||
extern uint32_t rs_current_pcb_preempt_count();
|
||||
extern uint32_t rs_current_pcb_pid();
|
||||
extern uint32_t rs_current_pcb_flags();
|
||||
|
||||
static bool flag_support_apic = false;
|
||||
static bool flag_support_x2apic = false;
|
||||
@ -357,6 +360,7 @@ void apic_local_apic_init()
|
||||
*/
|
||||
int apic_init()
|
||||
{
|
||||
cli();
|
||||
kinfo("Initializing APIC...");
|
||||
// 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套,然后处理器重新加载导致数据被抹掉
|
||||
for (int i = 32; i <= 55; ++i)
|
||||
@ -398,7 +402,7 @@ int apic_init()
|
||||
kwarn("Cannot get RCBA address. RCBA_phys=%#010lx", RCBA_phys);
|
||||
}
|
||||
kinfo("APIC initialized.");
|
||||
sti();
|
||||
// sti();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
@ -465,13 +469,15 @@ void do_IRQ(struct pt_regs *rsp, ul number)
|
||||
|
||||
// kdebug("after softirq");
|
||||
// 检测当前进程是否持有自旋锁,若持有自旋锁,则不进行抢占式的进程调度
|
||||
if (current_pcb->preempt_count > 0)
|
||||
if (rs_current_pcb_preempt_count() > 0)
|
||||
{
|
||||
return;
|
||||
else if (current_pcb->preempt_count < 0)
|
||||
kBUG("current_pcb->preempt_count<0! pid=%d", current_pcb->pid); // should not be here
|
||||
}
|
||||
else if (rs_current_pcb_preempt_count() < 0)
|
||||
kBUG("current_pcb->preempt_count<0! pid=%d", rs_current_pcb_pid()); // should not be here
|
||||
|
||||
// 检测当前进程是否可被调度
|
||||
if (current_pcb->flags & PF_NEED_SCHED && number == APIC_TIMER_IRQ_NUM)
|
||||
if ((rs_current_pcb_flags() & PF_NEED_SCHED) && number == APIC_TIMER_IRQ_NUM)
|
||||
{
|
||||
io_mfence();
|
||||
sched();
|
||||
|
2
kernel/src/driver/interrupt/apic/apic2rust.h
Normal file
2
kernel/src/driver/interrupt/apic/apic2rust.h
Normal file
@ -0,0 +1,2 @@
|
||||
#include <common/stddef.h>
|
||||
extern uint64_t ioapic_get_base_paddr();
|
@ -107,16 +107,17 @@ void apic_timer_init()
|
||||
while (1)
|
||||
hlt();
|
||||
}
|
||||
spin_lock(&apic_timer_init_lock);
|
||||
kinfo("Initializing apic timer for cpu %d", proc_current_cpu_id);
|
||||
uint64_t flags = 0;
|
||||
spin_lock_irqsave(&apic_timer_init_lock, flags);
|
||||
kinfo("Initializing apic timer for cpu %d", rs_current_pcb_cpuid());
|
||||
io_mfence();
|
||||
irq_register(APIC_TIMER_IRQ_NUM, &apic_timer_ticks_result, &apic_timer_handler, 0, &apic_timer_intr_controller,
|
||||
"apic timer");
|
||||
io_mfence();
|
||||
if (proc_current_cpu_id == 0)
|
||||
if (rs_current_pcb_cpuid() == 0)
|
||||
{
|
||||
bsp_initialized = true;
|
||||
}
|
||||
spin_unlock(&apic_timer_init_lock);
|
||||
// kinfo("Successfully initialized apic timer for cpu %d", proc_current_cpu_id);
|
||||
kdebug("apic timer init done for cpu %d", rs_current_pcb_cpuid());
|
||||
spin_unlock_irqrestore(&apic_timer_init_lock, flags);
|
||||
}
|
@ -4,15 +4,12 @@
|
||||
#include <mm/slab.h>
|
||||
#include <common/printk.h>
|
||||
#include <filesystem/vfs/VFS.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/kfifo.h>
|
||||
|
||||
// 键盘输入缓冲区
|
||||
static struct kfifo_t kb_buf;
|
||||
|
||||
// 缓冲区等待队列
|
||||
static wait_queue_node_t ps2_keyboard_wait_queue;
|
||||
extern void ps2_keyboard_register(struct vfs_file_operations_t *);
|
||||
extern void ps2_keyboard_parse_keycode(uint8_t input);
|
||||
|
||||
@ -101,8 +98,8 @@ long ps2_keyboard_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *filp,
|
||||
long ps2_keyboard_read(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
|
||||
{
|
||||
// 缓冲区为空则等待
|
||||
if (kfifo_empty(&kb_buf))
|
||||
wait_queue_sleep_on(&ps2_keyboard_wait_queue);
|
||||
while (kfifo_empty(&kb_buf))
|
||||
;
|
||||
|
||||
count = (count > kb_buf.size) ? kb_buf.size : count;
|
||||
return kfifo_out(&kb_buf, buf, count);
|
||||
@ -145,15 +142,6 @@ void ps2_keyboard_handler(ul irq_num, ul buf_vaddr, struct pt_regs *regs)
|
||||
{
|
||||
unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA);
|
||||
ps2_keyboard_parse_keycode((uint8_t)x);
|
||||
uint8_t count = kfifo_in((struct kfifo_t *)buf_vaddr, &x, sizeof(unsigned char));
|
||||
// if (count == 0)
|
||||
// {
|
||||
// kwarn("ps2 keyboard buffer full.");
|
||||
// return;
|
||||
// }
|
||||
|
||||
wait_queue_wakeup(&ps2_keyboard_wait_queue, PROC_UNINTERRUPTIBLE);
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief 初始化键盘驱动程序的函数
|
||||
@ -195,7 +183,7 @@ void ps2_keyboard_init()
|
||||
for (int j = 0; j < 1000; ++j)
|
||||
nop();
|
||||
|
||||
wait_queue_init(&ps2_keyboard_wait_queue, NULL);
|
||||
|
||||
// 初始化键盘缓冲区的读写锁
|
||||
spin_init(&ps2_kb_buf_rw_lock);
|
||||
|
||||
@ -218,5 +206,4 @@ void ps2_keyboard_exit()
|
||||
{
|
||||
irq_unregister(PS2_KEYBOARD_INTR_VECTOR);
|
||||
kfifo_free_alloc(&kb_buf);
|
||||
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
#include <smp/ipi.h>
|
||||
#include <driver/video/video.h>
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <process/preempt.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
@ -29,6 +29,7 @@ extern uint64_t Cpu_tsc_freq; // 导出自cpu.c
|
||||
extern struct rtc_time_t rtc_now; // 导出全局墙上时钟
|
||||
extern uint64_t rs_update_timer_jiffies(uint64_t);
|
||||
|
||||
extern uint32_t rs_current_pcb_pid();
|
||||
enum
|
||||
{
|
||||
GCAP_ID = 0x00,
|
||||
@ -80,17 +81,6 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
if (rs_timer_get_first_expire() <= rs_clock())
|
||||
rs_raise_softirq(TIMER_SIRQ);
|
||||
|
||||
// 当时间到了,或进程发生切换时,刷新帧缓冲区
|
||||
if (rs_clock() >= video_refresh_expire_jiffies || (video_last_refresh_pid != current_pcb->pid))
|
||||
{
|
||||
rs_raise_softirq(VIDEO_REFRESH_SIRQ);
|
||||
// 超过130ms仍未刷新完成,则重新发起刷新(防止由于进程异常退出导致的屏幕无法刷新)
|
||||
if (unlikely(rs_clock() >= (video_refresh_expire_jiffies + (1 << 17))))
|
||||
{
|
||||
video_refresh_expire_jiffies = rs_clock() + (1 << 20);
|
||||
rs_clear_softirq_pending(VIDEO_REFRESH_SIRQ);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -119,6 +109,7 @@ void HPET_measure_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
*/
|
||||
void HPET_measure_freq()
|
||||
{
|
||||
rs_preempt_disable();
|
||||
kinfo("Measuring local APIC timer's frequency...");
|
||||
const uint64_t interval = APIC_TIMER_INTERVAL; // 测量给定时间内的计数
|
||||
struct apic_IO_APIC_RTE_entry entry;
|
||||
@ -175,6 +166,8 @@ void HPET_measure_freq()
|
||||
Cpu_tsc_freq = (test_tsc_end - test_tsc_start) * (1000UL / interval);
|
||||
|
||||
kinfo("TSC frequency: %ldMHz", Cpu_tsc_freq / 1000000);
|
||||
|
||||
rs_preempt_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,10 +0,0 @@
|
||||
SRC = $(wildcard *.c)
|
||||
OBJ = $(SRC:.c=.o)
|
||||
CFLAGS += -I .
|
||||
|
||||
.PHONY: all
|
||||
|
||||
all: $(OBJ)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
@ -1,65 +1,332 @@
|
||||
use core::{
|
||||
ptr::null_mut,
|
||||
ffi::{c_uint, c_void},
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
exception::softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
|
||||
include::bindings::bindings::video_refresh_framebuffer,
|
||||
arch::MMArch,
|
||||
driver::uart::uart_device::c_uart_send_str,
|
||||
driver::uart::uart_device::UartPort::COM1,
|
||||
include::bindings::bindings::{
|
||||
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
||||
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
|
||||
},
|
||||
kinfo,
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
lib_ui::screen_manager::{ScmBuffer, ScmBufferFlag, ScmBufferInfo},
|
||||
rwlock::{RwLock, RwLockReadGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
mm::{
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper,
|
||||
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
},
|
||||
syscall::SystemError,
|
||||
time::timer::{Timer, TimerFunction},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VideoRefreshFramebuffer {
|
||||
static mut __MAMAGER: Option<VideoRefreshManager> = None;
|
||||
|
||||
pub fn video_refresh_manager() -> &'static VideoRefreshManager {
|
||||
return unsafe {
|
||||
&__MAMAGER
|
||||
.as_ref()
|
||||
.expect("Video refresh manager has not been initialized yet!")
|
||||
};
|
||||
}
|
||||
|
||||
///管理显示刷新变量的结构体
|
||||
pub struct VideoRefreshManager {
|
||||
device_buffer: RwLock<ScmBufferInfo>,
|
||||
fb_info: multiboot_tag_framebuffer_info_t,
|
||||
refresh_target: RwLock<Option<Arc<SpinLock<Box<[u32]>>>>>,
|
||||
running: AtomicBool,
|
||||
}
|
||||
|
||||
impl SoftirqVec for VideoRefreshFramebuffer {
|
||||
fn run(&self) {
|
||||
if self.set_run() == false {
|
||||
return;
|
||||
const REFRESH_INTERVAL: u64 = 30;
|
||||
|
||||
impl VideoRefreshManager {
|
||||
/**
|
||||
* @brief 启动定时刷新
|
||||
* @return 启动成功: true, 失败: false
|
||||
*/
|
||||
pub fn run_video_refresh(&self) -> bool {
|
||||
//设置Manager运行标志
|
||||
let res = self.set_run();
|
||||
|
||||
//设置成功则开始任务,否则直接返回false
|
||||
if res {
|
||||
//第一次将expire_jiffies设置小一点,使得这次刷新尽快开始,后续的刷新将按照REFRESH_INTERVAL间隔进行
|
||||
let timer = Timer::new(VideoRefreshExecutor::new(), 1);
|
||||
//将新一次定时任务加入队列
|
||||
timer.activate();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
video_refresh_framebuffer(null_mut());
|
||||
}
|
||||
|
||||
self.clear_run();
|
||||
}
|
||||
}
|
||||
impl VideoRefreshFramebuffer {
|
||||
pub fn new() -> VideoRefreshFramebuffer {
|
||||
VideoRefreshFramebuffer {
|
||||
running: AtomicBool::new(false),
|
||||
}
|
||||
/// 停止定时刷新
|
||||
#[allow(dead_code)]
|
||||
pub fn stop_video_refresh(&self) {
|
||||
self.running.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn set_run(&self) -> bool {
|
||||
let x = self
|
||||
let res = self
|
||||
.running
|
||||
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
|
||||
if x.is_ok() {
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
|
||||
if res.is_ok() {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_run(&self) {
|
||||
self.running.store(false, Ordering::Release);
|
||||
/**
|
||||
* @brief VBE帧缓存区的地址重新映射
|
||||
* 将帧缓存区映射到地址SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE处
|
||||
*/
|
||||
fn init_frame_buffer(&self) {
|
||||
kinfo!("Re-mapping VBE frame buffer...");
|
||||
let buf_vaddr = VirtAddr::new(
|
||||
SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + FRAME_BUFFER_MAPPING_OFFSET as usize,
|
||||
);
|
||||
|
||||
let mut frame_buffer_info_graud = self.device_buffer.write();
|
||||
if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_graud).buf {
|
||||
*vaddr = buf_vaddr;
|
||||
}
|
||||
|
||||
// 地址映射
|
||||
let mut paddr = PhysAddr::new(self.fb_info.framebuffer_addr as usize);
|
||||
let count = PageFrameCount::new(
|
||||
page_align_up(frame_buffer_info_graud.buf_size()) / MMArch::PAGE_SIZE,
|
||||
);
|
||||
let page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
|
||||
|
||||
let mut kernel_mapper = KernelMapper::lock();
|
||||
let mut kernel_mapper = kernel_mapper.as_mut();
|
||||
assert!(kernel_mapper.is_some());
|
||||
let mut vaddr = buf_vaddr;
|
||||
unsafe {
|
||||
for _ in 0..count.data() {
|
||||
let flusher = kernel_mapper
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.map_phys(vaddr, paddr, page_flags)
|
||||
.unwrap();
|
||||
|
||||
flusher.flush();
|
||||
vaddr += MMArch::PAGE_SIZE;
|
||||
paddr += MMArch::PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
kinfo!("VBE frame buffer successfully Re-mapped!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化显示模块,需先低级初始化才能高级初始化
|
||||
* @param level 初始化等级
|
||||
* false -> 低级初始化:不使用double buffer
|
||||
* true ->高级初始化:增加double buffer的支持
|
||||
* @return int
|
||||
*/
|
||||
pub fn video_reinitialize(&self, level: bool) -> Result<(), SystemError> {
|
||||
if !level {
|
||||
self.init_frame_buffer();
|
||||
} else {
|
||||
// 开启屏幕计时刷新
|
||||
assert!(self.run_video_refresh());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置帧缓冲区刷新目标
|
||||
*
|
||||
* @param buf
|
||||
* @return int
|
||||
*/
|
||||
pub fn set_refresh_target(&self, buf_info: &ScmBufferInfo) -> Result<(), SystemError> {
|
||||
let mut refresh_target = self.refresh_target.write_irqsave();
|
||||
if let ScmBuffer::DoubleBuffer(double_buffer) = &buf_info.buf {
|
||||
*refresh_target = Some(double_buffer.clone());
|
||||
return Ok(());
|
||||
}
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn refresh_target(&self) -> RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>> {
|
||||
let x = self.refresh_target.read();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
pub fn device_buffer(&self) -> RwLockReadGuard<'_, ScmBufferInfo> {
|
||||
return self.device_buffer.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化显示驱动
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
pub unsafe fn video_init() -> Result<(), SystemError> {
|
||||
static INIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
if INIT
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_err()
|
||||
{
|
||||
panic!("Try to init video twice!");
|
||||
}
|
||||
|
||||
let mut _reserved: u32 = 0;
|
||||
|
||||
let mut fb_info: MaybeUninit<multiboot_tag_framebuffer_info_t> = MaybeUninit::uninit();
|
||||
//从multiboot2中读取帧缓冲区信息至fb_info
|
||||
multiboot2_iter(
|
||||
Some(multiboot2_get_Framebuffer_info),
|
||||
fb_info.as_mut_ptr() as usize as *mut c_void,
|
||||
&mut _reserved as *mut c_uint,
|
||||
);
|
||||
fb_info.assume_init();
|
||||
let fb_info: multiboot_tag_framebuffer_info_t = core::mem::transmute(fb_info);
|
||||
|
||||
let width = fb_info.framebuffer_width;
|
||||
let height = fb_info.framebuffer_height;
|
||||
|
||||
//初始化帧缓冲区信息结构体
|
||||
let (bit_depth, flags) = if fb_info.framebuffer_type == 2 {
|
||||
//当type=2时,width与height用字符数表示,故depth=8
|
||||
|
||||
(8u32, ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_FB)
|
||||
} else {
|
||||
//否则为图像模式,depth应参照帧缓冲区信息里面的每个像素的位数
|
||||
(
|
||||
fb_info.framebuffer_bpp as u32,
|
||||
ScmBufferFlag::SCM_BF_PIXEL | ScmBufferFlag::SCM_BF_FB,
|
||||
)
|
||||
};
|
||||
|
||||
let buf_vaddr = VirtAddr::new(0xffff800003200000);
|
||||
let device_buffer = ScmBufferInfo::new_device_buffer(
|
||||
width,
|
||||
height,
|
||||
width * height * ((bit_depth + 7) / 8),
|
||||
bit_depth,
|
||||
flags,
|
||||
buf_vaddr,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let init_text = "Video driver to map.\n\0";
|
||||
c_uart_send_str(COM1 as u16, init_text.as_ptr());
|
||||
|
||||
//地址映射
|
||||
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||
let count = PageFrameCount::new(
|
||||
page_align_up(device_buffer.buf_size() as usize) / MMArch::PAGE_SIZE,
|
||||
);
|
||||
pseudo_map_phys(buf_vaddr, paddr, count);
|
||||
|
||||
let result = Self {
|
||||
fb_info,
|
||||
device_buffer: RwLock::new(device_buffer),
|
||||
refresh_target: RwLock::new(None),
|
||||
running: AtomicBool::new(false),
|
||||
};
|
||||
|
||||
__MAMAGER = Some(result);
|
||||
|
||||
let init_text = "Video driver initialized.\n\0";
|
||||
c_uart_send_str(COM1 as u16, init_text.as_ptr());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_softirq_video() {
|
||||
// kdebug!("register_softirq_video");
|
||||
let handler = Arc::new(VideoRefreshFramebuffer::new());
|
||||
softirq_vectors()
|
||||
.register_softirq(SoftirqNumber::VideoRefresh, handler)
|
||||
.expect("register_softirq_video run failed");
|
||||
//刷新任务执行器
|
||||
#[derive(Debug)]
|
||||
struct VideoRefreshExecutor;
|
||||
|
||||
impl VideoRefreshExecutor {
|
||||
fn new() -> Box<VideoRefreshExecutor> {
|
||||
return Box::new(VideoRefreshExecutor);
|
||||
}
|
||||
}
|
||||
// ======= 以下为给C提供的接口,video重构完后请删除 =======
|
||||
|
||||
impl TimerFunction for VideoRefreshExecutor {
|
||||
/**
|
||||
* @brief 交给定时器执行的任务,此方法不应手动调用
|
||||
* @return Ok(())
|
||||
*/
|
||||
fn run(&mut self) -> Result<(), SystemError> {
|
||||
// 获得Manager
|
||||
let manager = video_refresh_manager();
|
||||
|
||||
let start_next_refresh = || {
|
||||
//判断是否还需要刷新,若需要则继续分配下一次计时任务,否则不分配
|
||||
if manager.running.load(Ordering::SeqCst) {
|
||||
let timer = Timer::new(VideoRefreshExecutor::new(), REFRESH_INTERVAL);
|
||||
//将新一次定时任务加入队列
|
||||
timer.activate();
|
||||
}
|
||||
};
|
||||
|
||||
let mut refresh_target: Option<RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>>> =
|
||||
None;
|
||||
const TRY_TIMES: i32 = 2;
|
||||
for i in 0..TRY_TIMES {
|
||||
let g = manager.refresh_target.try_read();
|
||||
if g.is_none() {
|
||||
if i == TRY_TIMES - 1 {
|
||||
start_next_refresh();
|
||||
return Ok(());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
refresh_target = Some(g.unwrap());
|
||||
break;
|
||||
}
|
||||
|
||||
let refresh_target = refresh_target.unwrap();
|
||||
|
||||
if let ScmBuffer::DeviceBuffer(vaddr) = manager.device_buffer().buf {
|
||||
let p = vaddr.as_ptr() as *mut u8;
|
||||
let mut target_guard = None;
|
||||
for _ in 0..2 {
|
||||
if let Ok(guard) = refresh_target.as_ref().unwrap().try_lock_irqsave() {
|
||||
target_guard = Some(guard);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if target_guard.is_none() {
|
||||
start_next_refresh();
|
||||
return Ok(());
|
||||
}
|
||||
let mut target_guard = target_guard.unwrap();
|
||||
unsafe {
|
||||
p.copy_from_nonoverlapping(
|
||||
target_guard.as_mut_ptr() as *mut u8,
|
||||
manager.device_buffer().buf_size() as usize,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
start_next_refresh();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_register_softirq_video() {
|
||||
register_softirq_video();
|
||||
pub unsafe extern "C" fn rs_video_init() -> i32 {
|
||||
return VideoRefreshManager::video_init()
|
||||
.map(|_| 0)
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
}
|
||||
|
@ -1,213 +0,0 @@
|
||||
#include "video.h"
|
||||
#include <common/kprint.h>
|
||||
#include <common/kthread.h>
|
||||
#include <common/printk.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/time.h>
|
||||
#include <driver/multiboot2/multiboot2.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <exception/softirq.h>
|
||||
#include <mm/mm.h>
|
||||
#include <mm/slab.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
#include <time/timer.h>
|
||||
|
||||
extern void rs_register_softirq_video();
|
||||
|
||||
uint64_t video_refresh_expire_jiffies = 0;
|
||||
uint64_t video_last_refresh_pid = -1;
|
||||
struct scm_buffer_info_t video_frame_buffer_info = {0};
|
||||
static struct multiboot_tag_framebuffer_info_t __fb_info;
|
||||
// static struct scm_buffer_info_t *_video_refresh_target = NULL;
|
||||
static struct scm_buffer_info_t video_refresh_target = {0};
|
||||
static struct process_control_block *video_daemon_pcb = NULL;
|
||||
static spinlock_t daemon_refresh_lock;
|
||||
|
||||
#define REFRESH_INTERVAL 15UL // 启动刷新帧缓冲区任务的时间间隔
|
||||
|
||||
/**
|
||||
* @brief VBE帧缓存区的地址重新映射
|
||||
* 将帧缓存区映射到地址SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE处
|
||||
*/
|
||||
void init_frame_buffer()
|
||||
{
|
||||
kinfo("Re-mapping VBE frame buffer...");
|
||||
|
||||
video_frame_buffer_info.vaddr = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + FRAME_BUFFER_MAPPING_OFFSET;
|
||||
rs_map_phys(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
|
||||
|
||||
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
|
||||
kinfo("VBE frame buffer successfully Re-mapped!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief video守护进程, 按时刷新帧缓冲区
|
||||
* @param unused
|
||||
* @return int
|
||||
*/
|
||||
int video_refresh_daemon(void *unused)
|
||||
{
|
||||
// 初始化锁, 这个锁只会在daemon中使用
|
||||
spin_init(&daemon_refresh_lock);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (rs_clock() >= video_refresh_expire_jiffies)
|
||||
{
|
||||
|
||||
if (likely(video_refresh_target.size != 0))
|
||||
{
|
||||
spin_lock(&daemon_refresh_lock);
|
||||
if (video_frame_buffer_info.vaddr != NULL)
|
||||
{
|
||||
// kdebug("video_frame_buffer_info.vaddr = %#018lx,get_video_refresh_target_vaddr()= %#018lx" ,video_frame_buffer_info.vaddr,get_video_refresh_target_vaddr());
|
||||
|
||||
memcpy((void *)video_frame_buffer_info.vaddr, (void *)get_video_refresh_target_vaddr(),
|
||||
video_refresh_target.size);
|
||||
}
|
||||
spin_unlock(&daemon_refresh_lock);
|
||||
video_daemon_pcb->virtual_runtime =
|
||||
0xfffff0000000; // 临时解决由于显示刷新进程的虚拟运行时间过大/过小,导致其不运行,或者一直运行的问题。将来应使用实时调度解决它
|
||||
}
|
||||
video_refresh_expire_jiffies = rs_timer_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
|
||||
}
|
||||
video_daemon_pcb->state &= ~PROC_RUNNING;
|
||||
video_daemon_pcb->flags |= PF_NEED_SCHED;
|
||||
sched();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t get_video_refresh_target_vaddr()
|
||||
{
|
||||
return video_refresh_target.vaddr;
|
||||
}
|
||||
/**
|
||||
* @brief 唤醒video的守护进程
|
||||
*/
|
||||
void video_refresh_framebuffer(void *data)
|
||||
{
|
||||
if (unlikely(video_daemon_pcb == NULL))
|
||||
return;
|
||||
if (rs_clock() >= video_refresh_expire_jiffies)
|
||||
{
|
||||
video_daemon_pcb->virtual_runtime = 0;
|
||||
process_wakeup(video_daemon_pcb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化显示模块,需先低级初始化才能高级初始化
|
||||
* @param level 初始化等级
|
||||
* false -> 低级初始化:不使用double buffer
|
||||
* true ->高级初始化:增加double buffer的支持
|
||||
* @return int
|
||||
*/
|
||||
int video_reinitialize(bool level) // 这个函数会在main.c调用, 保证 video_init() 先被调用
|
||||
{
|
||||
if (level == false)
|
||||
init_frame_buffer();
|
||||
else
|
||||
{
|
||||
rs_unregister_softirq(VIDEO_REFRESH_SIRQ);
|
||||
// 计算开始时间
|
||||
video_refresh_expire_jiffies = rs_timer_next_n_ms_jiffies(50 * REFRESH_INTERVAL);
|
||||
kdebug("video_frame_buffer_info.vaddr = %#018lx,get_video_refresh_target_vaddr()= %#018lx", video_frame_buffer_info.vaddr, get_video_refresh_target_vaddr());
|
||||
|
||||
io_mfence();
|
||||
// 创建video守护进程
|
||||
video_daemon_pcb = kthread_run(&video_refresh_daemon, NULL, "Video refresh daemon");
|
||||
io_mfence();
|
||||
video_daemon_pcb->virtual_runtime = 0; // 特殊情况, 最高优先级, 以后再改
|
||||
// 启用屏幕刷新软中断
|
||||
rs_register_softirq_video();
|
||||
rs_raise_softirq(VIDEO_REFRESH_SIRQ);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置帧缓冲区刷新目标
|
||||
*
|
||||
* @param buf
|
||||
* @return int
|
||||
*/
|
||||
|
||||
int video_set_refresh_target(struct scm_buffer_info_t buf)
|
||||
{
|
||||
|
||||
rs_unregister_softirq(VIDEO_REFRESH_SIRQ);
|
||||
// todo: 在completion实现后,在这里等待其他刷新任务完成,再进行下一步。
|
||||
|
||||
// int counter = 100;
|
||||
|
||||
// while ((get_softirq_pending() & (1 << VIDEO_REFRESH_SIRQ)) && counter > 0)
|
||||
// {
|
||||
// --counter;
|
||||
// rs_usleep(1000);
|
||||
// }
|
||||
// kdebug("buf = %#018lx", buf);
|
||||
|
||||
video_refresh_target = buf;
|
||||
|
||||
rs_register_softirq_video();
|
||||
kdebug("register softirq video done");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化显示驱动
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int video_init()
|
||||
{
|
||||
|
||||
memset(&video_frame_buffer_info, 0, sizeof(struct scm_buffer_info_t));
|
||||
memset(&__fb_info, 0, sizeof(struct multiboot_tag_framebuffer_info_t));
|
||||
// _video_refresh_target = NULL;
|
||||
video_refresh_target = (struct scm_buffer_info_t){0};
|
||||
io_mfence();
|
||||
// 从multiboot2获取帧缓冲区信息
|
||||
int reserved;
|
||||
multiboot2_iter(multiboot2_get_Framebuffer_info, &__fb_info, &reserved);
|
||||
io_mfence();
|
||||
|
||||
// 初始化帧缓冲区信息结构体
|
||||
if (__fb_info.framebuffer_type == 2)
|
||||
{
|
||||
video_frame_buffer_info.bit_depth = 8; // type=2时,width和height是按照字符数来表示的,因此depth=8
|
||||
video_frame_buffer_info.flags |= SCM_BF_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_frame_buffer_info.bit_depth = __fb_info.framebuffer_bpp;
|
||||
video_frame_buffer_info.flags |= SCM_BF_PIXEL;
|
||||
}
|
||||
|
||||
video_frame_buffer_info.flags |= SCM_BF_FB;
|
||||
video_frame_buffer_info.width = __fb_info.framebuffer_width;
|
||||
video_frame_buffer_info.height = __fb_info.framebuffer_height;
|
||||
io_mfence();
|
||||
|
||||
video_frame_buffer_info.size =
|
||||
video_frame_buffer_info.width * video_frame_buffer_info.height * ((video_frame_buffer_info.bit_depth + 7) / 8);
|
||||
// 先临时映射到50M的位置,稍后再重新映射
|
||||
video_frame_buffer_info.vaddr = 0xffff800003200000;
|
||||
|
||||
char init_text1[] = "Video driver to map.\n";
|
||||
for (int i = 0; i < sizeof(init_text1) - 1; ++i)
|
||||
c_uart_send(COM1, init_text1[i]);
|
||||
|
||||
rs_pseudo_map_phys(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size);
|
||||
|
||||
io_mfence();
|
||||
char init_text2[] = "Video driver initialized.\n";
|
||||
for (int i = 0; i < sizeof(init_text2) - 1; ++i)
|
||||
{
|
||||
c_uart_send(COM1, init_text2[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
#include <stdbool.h>
|
||||
#include <libs/lib_ui/screen_manager.h>
|
||||
extern struct scm_buffer_info_t video_frame_buffer_info;
|
||||
/**
|
||||
* @brief 重新初始化显示驱动,需先低级初始化才能高级初始化
|
||||
* @param level 初始化等级
|
||||
* false -> 低级初始化:不使用double buffer
|
||||
* true ->高级初始化:增加double buffer的支持
|
||||
* @return int
|
||||
*/
|
||||
int video_reinitialize(bool level);
|
||||
|
||||
/**
|
||||
* @brief 初始化显示驱动
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int video_init();
|
||||
|
||||
/**
|
||||
* @brief 设置帧缓冲区刷新目标
|
||||
*
|
||||
* @param buf
|
||||
* @return int
|
||||
*/
|
||||
// int video_set_refresh_target(struct scm_buffer_info_t *buf);
|
||||
int video_set_refresh_target(struct scm_buffer_info_t buf);
|
||||
|
||||
extern uint64_t video_refresh_expire_jiffies;
|
||||
extern uint64_t video_last_refresh_pid;
|
||||
|
||||
void video_refresh_framebuffer(void *data);
|
||||
uint64_t get_video_refresh_target_vaddr();
|
@ -77,7 +77,7 @@ fn device_type(pci_device_id: u16) -> DeviceType {
|
||||
pub struct PciTransport {
|
||||
device_type: DeviceType,
|
||||
/// The bus, device and function identifier for the VirtIO device.
|
||||
bus_device_function: BusDeviceFunction,
|
||||
_bus_device_function: BusDeviceFunction,
|
||||
/// The common configuration structure within some BAR.
|
||||
common_cfg: NonNull<CommonCfg>,
|
||||
/// The start of the queue notification region within some BAR.
|
||||
@ -182,7 +182,7 @@ impl PciTransport {
|
||||
};
|
||||
Ok(Self {
|
||||
device_type,
|
||||
bus_device_function,
|
||||
_bus_device_function: bus_device_function,
|
||||
common_cfg,
|
||||
notify_region,
|
||||
notify_off_multiplier,
|
||||
|
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
|
||||
//寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备后续也可添加)
|
||||
extern void rs_virtio_probe();
|
@ -18,12 +18,6 @@ enum VirtioError {
|
||||
NetDeviceNotFound,
|
||||
}
|
||||
|
||||
/// @brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_virtio_probe() {
|
||||
virtio_probe();
|
||||
}
|
||||
|
||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||
pub fn virtio_probe() {
|
||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||
|
@ -10,15 +10,13 @@ use alloc::{boxed::Box, sync::Arc};
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
use crate::{
|
||||
arch::interrupt::{cli, sti},
|
||||
arch::CurrentIrqArch,
|
||||
arch::{
|
||||
asm::current::current_pcb,
|
||||
interrupt::{cli, sti},
|
||||
},
|
||||
exception::InterruptArch,
|
||||
include::bindings::bindings::MAX_CPU_NUM,
|
||||
kdebug, kinfo,
|
||||
libs::rwlock::RwLock,
|
||||
process::ProcessManager,
|
||||
smp::core::smp_get_processor_id,
|
||||
syscall::SystemError,
|
||||
time::timer::clock,
|
||||
@ -193,17 +191,17 @@ impl Softirq {
|
||||
continue;
|
||||
}
|
||||
|
||||
let prev_count = current_pcb().preempt_count;
|
||||
let prev_count: usize = ProcessManager::current_pcb().preempt_count();
|
||||
|
||||
softirq_func.as_ref().unwrap().run();
|
||||
if unlikely(prev_count != current_pcb().preempt_count) {
|
||||
if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) {
|
||||
kdebug!(
|
||||
"entered softirq {:?} with preempt_count {:?},exited with {:?}",
|
||||
i,
|
||||
prev_count,
|
||||
current_pcb().preempt_count
|
||||
ProcessManager::current_pcb().preempt_count()
|
||||
);
|
||||
current_pcb().preempt_count = prev_count;
|
||||
unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,10 @@ void do_divide_error(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
// kerror("do_divide_error(0)");
|
||||
kerror("do_divide_error(0),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\t pid=%d\n", error_code,
|
||||
regs->rsp, regs->rip, proc_current_cpu_id, current_pcb->pid);
|
||||
regs->rsp, regs->rip, rs_current_cpu_id(), rs_current_pcb_pid());
|
||||
traceback(regs);
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 1 #DB 调试异常
|
||||
@ -25,7 +25,7 @@ void do_debug(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(RED, BLACK, "ERROR / TRAP");
|
||||
printk(" ] do_debug(1),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d, pid:%d\n", error_code, regs->rsp, regs->rip,
|
||||
proc_current_cpu_id, current_pcb->pid);
|
||||
rs_current_pcb_cpuid(), rs_current_pcb_pid());
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -38,7 +38,7 @@ void do_nmi(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(BLUE, BLACK, "INT");
|
||||
printk(" ] do_nmi(2),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp, regs->rip,
|
||||
proc_current_cpu_id);
|
||||
rs_current_pcb_cpuid());
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -51,7 +51,7 @@ void do_int3(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(YELLOW, BLACK, "TRAP");
|
||||
printk(" ] do_int3(3),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp, regs->rip,
|
||||
proc_current_cpu_id);
|
||||
rs_current_pcb_cpuid());
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -64,10 +64,8 @@ void do_overflow(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(YELLOW, BLACK, "TRAP");
|
||||
printk(" ] do_overflow(4),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 5 #BR 越界异常
|
||||
@ -75,7 +73,7 @@ void do_bounds(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_bounds(5),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp, regs->rip,
|
||||
proc_current_cpu_id);
|
||||
rs_current_pcb_cpuid());
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -86,10 +84,9 @@ void do_undefined_opcode(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_undefined_opcode(6),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d, pid:%ld", error_code,
|
||||
regs->rsp, regs->rip, proc_current_cpu_id, current_pcb->pid);
|
||||
regs->rsp, regs->rip, rs_current_pcb_cpuid(), rs_current_pcb_pid());
|
||||
traceback(regs);
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 7 #NM 设备异常(FPU不存在)
|
||||
@ -97,10 +94,9 @@ void do_dev_not_avaliable(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_dev_not_avaliable(7),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d, pid=%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id, current_pcb->pid);
|
||||
regs->rip, rs_current_pcb_cpuid(), rs_current_pcb_pid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 8 #DF 双重错误
|
||||
@ -110,10 +106,9 @@ void do_double_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(RED, BLACK, "Terminate");
|
||||
printk(" ] do_double_fault(8),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
traceback(regs);
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 9 协处理器越界(保留)
|
||||
@ -121,10 +116,9 @@ void do_coprocessor_segment_overrun(struct pt_regs *regs, unsigned long error_co
|
||||
{
|
||||
|
||||
kerror("do_coprocessor_segment_overrun(9),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code,
|
||||
regs->rsp, regs->rip, proc_current_cpu_id);
|
||||
regs->rsp, regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 10 #TS 无效的TSS段
|
||||
@ -134,7 +128,7 @@ void do_invalid_TSS(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("[");
|
||||
printk_color(RED, BLACK, "ERROR");
|
||||
printk("] do_invalid_TSS(10),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
printk_color(YELLOW, BLACK, "Information:\n");
|
||||
// 解析错误码
|
||||
@ -155,8 +149,7 @@ void do_invalid_TSS(struct pt_regs *regs, unsigned long error_code)
|
||||
|
||||
printk("\n");
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 11 #NP 段不存在
|
||||
@ -164,10 +157,8 @@ void do_segment_not_exists(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_segment_not_exists(11),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 12 #SS SS段错误
|
||||
@ -175,11 +166,10 @@ void do_stack_segment_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_stack_segment_fault(12),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
// kinfo("cs=%#04x, ds=%#04x, ss=%#04x", regs->cs, regs->ds, regs->ss);
|
||||
traceback(regs);
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 13 #GP 通用保护性异常
|
||||
@ -187,7 +177,7 @@ void do_general_protection(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_general_protection(13),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\tpid=%ld\n", error_code,
|
||||
regs->rsp, regs->rip, proc_current_cpu_id, current_pcb->pid);
|
||||
regs->rsp, regs->rip, rs_current_pcb_cpuid(), rs_current_pcb_pid());
|
||||
if (error_code & 0x01)
|
||||
printk_color(RED, BLACK,
|
||||
"The exception occurred during delivery of an event external to the program,such as an interrupt "
|
||||
@ -206,20 +196,19 @@ void do_general_protection(struct pt_regs *regs, unsigned long error_code)
|
||||
|
||||
printk_color(RED, BLACK, "Segment Selector Index:%#010x\n", error_code & 0xfff8);
|
||||
traceback(regs);
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 14 #PF 页故障
|
||||
void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
cli();
|
||||
unsigned long cr2 = 0;
|
||||
|
||||
__asm__ __volatile__("movq %%cr2, %0" : "=r"(cr2)::"memory");
|
||||
|
||||
kerror("do_page_fault(14),Error code :%#018lx,RSP:%#018lx, RBP=%#018lx, RIP:%#018lx CPU:%d, pid=%d\n", error_code,
|
||||
regs->rsp, regs->rbp, regs->rip, proc_current_cpu_id, current_pcb->pid);
|
||||
regs->rsp, regs->rbp, regs->rip, rs_current_pcb_cpuid(), rs_current_pcb_pid());
|
||||
kerror("regs->rax = %#018lx\n", regs->rax);
|
||||
if (!(error_code & 0x01))
|
||||
printk_color(RED, BLACK, "Page Not-Present,\t");
|
||||
@ -245,7 +234,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
printk_color(RED, BLACK, "CR2:%#018lx\n", cr2);
|
||||
|
||||
traceback(regs);
|
||||
process_do_exit(-1);
|
||||
sti();
|
||||
rs_process_do_exit(-1);
|
||||
// current_pcb->state = PROC_STOPPED;
|
||||
// sched();
|
||||
}
|
||||
@ -257,7 +247,7 @@ void do_x87_FPU_error(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_x87_FPU_error(16),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -268,10 +258,9 @@ void do_alignment_check(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_alignment_check(17),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 18 #MC 机器检测
|
||||
@ -279,10 +268,9 @@ void do_machine_check(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_machine_check(18),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 19 #XM SIMD浮点异常
|
||||
@ -290,10 +278,9 @@ void do_SIMD_exception(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_SIMD_exception(19),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
|
||||
regs->rip, proc_current_cpu_id);
|
||||
regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 20 #VE 虚拟化异常
|
||||
@ -301,10 +288,9 @@ void do_virtualization_exception(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
|
||||
kerror("do_virtualization_exception(20),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code,
|
||||
regs->rsp, regs->rip, proc_current_cpu_id);
|
||||
regs->rsp, regs->rip, rs_current_pcb_cpuid());
|
||||
|
||||
current_pcb->state = PROC_STOPPED;
|
||||
sched();
|
||||
rs_process_do_exit(-1);
|
||||
}
|
||||
|
||||
// 21-21 Intel保留,请勿使用
|
||||
|
@ -4,23 +4,22 @@ use alloc::{
|
||||
borrow::ToOwned,
|
||||
collections::BTreeMap,
|
||||
format,
|
||||
string::{String, ToString},
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
filesystem::vfs::{
|
||||
core::{generate_inode_id, ROOT_INODE},
|
||||
FileType,
|
||||
},
|
||||
include::bindings::bindings::{pid_t, process_find_pcb_by_pid},
|
||||
kerror, kinfo,
|
||||
libs::{
|
||||
once::Once,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
process::{Pid, ProcessManager},
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -55,7 +54,7 @@ impl From<u8> for ProcFileType {
|
||||
#[derive(Debug)]
|
||||
pub struct InodeInfo {
|
||||
///进程的pid
|
||||
pid: i64,
|
||||
pid: Pid,
|
||||
///文件类型
|
||||
ftype: ProcFileType,
|
||||
//其他需要传入的信息在此定义
|
||||
@ -119,11 +118,11 @@ impl ProcFSInode {
|
||||
///
|
||||
fn open_status(&self, pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
|
||||
// 获取该pid对应的pcb结构体
|
||||
let pid: &i64 = &self.fdata.pid;
|
||||
let pcb = unsafe { process_find_pcb_by_pid(*pid).as_mut() };
|
||||
let pid = self.fdata.pid;
|
||||
let pcb = ProcessManager::find(pid);
|
||||
let pcb = if pcb.is_none() {
|
||||
kerror!(
|
||||
"ProcFS: Cannot find pcb for pid {} when opening its 'status' file.",
|
||||
"ProcFS: Cannot find pcb for pid {:?} when opening its 'status' file.",
|
||||
pid
|
||||
);
|
||||
return Err(SystemError::ESRCH);
|
||||
@ -132,47 +131,50 @@ impl ProcFSInode {
|
||||
};
|
||||
// 传入数据
|
||||
let pdata: &mut Vec<u8> = &mut pdata.data;
|
||||
// !!!!!由于目前有bug,不能获取到pcb的name,因此暂时用'Unknown'代替
|
||||
let tmp_name: Vec<u8> = "Unknown".as_bytes().to_vec();
|
||||
// kdebug!("pcb.name={:?}", pcb.name);
|
||||
// let mut tmp_name: Vec<u8> = Vec::with_capacity(pcb.name.len());
|
||||
// for val in pcb.name.iter() {
|
||||
// tmp_name.push(*val as u8);
|
||||
// }
|
||||
|
||||
pdata.append(
|
||||
&mut format!(
|
||||
"Name:\t{}",
|
||||
String::from_utf8(tmp_name).unwrap_or("NULL".to_string())
|
||||
)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\nstate:\t{}", pcb.state).as_bytes().to_owned());
|
||||
pdata.append(&mut format!("\npid:\t{}", pcb.pid).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\nPpid:\t{}", unsafe { *pcb.parent_pcb }.pid)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\ncpu_id:\t{}", pcb.cpu_id).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\npriority:\t{}", pcb.priority)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(
|
||||
&mut format!("\npreempt:\t{}", pcb.preempt_count)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(
|
||||
&mut format!("\nvrtime:\t{}", pcb.virtual_runtime)
|
||||
&mut format!("Name:\t{}", pcb.basic().name())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let binding = current_pcb().address_space().unwrap();
|
||||
let sched_info_guard = pcb.sched_info();
|
||||
let state = sched_info_guard.state();
|
||||
let cpu_id = sched_info_guard
|
||||
.on_cpu()
|
||||
.map(|cpu| cpu as i32)
|
||||
.unwrap_or(-1);
|
||||
|
||||
let priority = sched_info_guard.priority();
|
||||
let vrtime = sched_info_guard.virtual_runtime();
|
||||
|
||||
drop(sched_info_guard);
|
||||
|
||||
pdata.append(&mut format!("\nState:\t{:?}", state).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\nPid:\t{}", pcb.pid().into())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(
|
||||
&mut format!("\nPpid:\t{}", pcb.basic().ppid().into())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\ncpu_id:\t{}", cpu_id).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\npriority:\t{}", priority.data())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(
|
||||
&mut format!("\npreempt:\t{}", pcb.preempt_count())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\nvrtime:\t{}", vrtime).as_bytes().to_owned());
|
||||
|
||||
let binding = pcb.basic().user_vm().unwrap();
|
||||
let address_space_guard = binding.read();
|
||||
// todo: 当前进程运行过程中占用内存的峰值
|
||||
let hiwater_vm: u64 = 0;
|
||||
@ -188,7 +190,12 @@ impl ProcFSInode {
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\nVmData:\t{} kB", data).as_bytes().to_owned());
|
||||
pdata.append(&mut format!("\nVmExe:\t{} kB\n", text).as_bytes().to_owned());
|
||||
pdata.append(&mut format!("\nVmExe:\t{} kB", text).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\nflags: {:?}\n", pcb.flags().clone())
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
// 去除多余的\0
|
||||
self.trim_string(pdata);
|
||||
@ -263,7 +270,7 @@ impl ProcFS {
|
||||
},
|
||||
fs: Weak::default(),
|
||||
fdata: InodeInfo {
|
||||
pid: 0,
|
||||
pid: Pid::new(0),
|
||||
ftype: ProcFileType::Default,
|
||||
},
|
||||
})));
|
||||
@ -283,7 +290,7 @@ impl ProcFS {
|
||||
|
||||
/// @brief 进程注册函数
|
||||
/// @usage 在进程中调用并创建进程对应文件
|
||||
pub fn register_pid(&self, pid: i64) -> Result<(), SystemError> {
|
||||
pub fn register_pid(&self, pid: Pid) -> Result<(), SystemError> {
|
||||
// 获取当前inode
|
||||
let proc: Arc<dyn IndexNode> = self.root_inode();
|
||||
// 创建对应进程文件夹
|
||||
@ -305,11 +312,11 @@ impl ProcFS {
|
||||
|
||||
/// @brief 解除进程注册
|
||||
///
|
||||
pub fn unregister_pid(&self, pid: i64) -> Result<(), SystemError> {
|
||||
pub fn unregister_pid(&self, pid: Pid) -> Result<(), SystemError> {
|
||||
// 获取当前inode
|
||||
let proc: Arc<dyn IndexNode> = self.root_inode();
|
||||
// 获取进程文件夹
|
||||
let pid_dir: Arc<dyn IndexNode> = proc.find(&format!("{}", pid))?;
|
||||
let pid_dir: Arc<dyn IndexNode> = proc.find(&pid.to_string())?;
|
||||
// 删除进程文件夹下文件
|
||||
pid_dir.unlink("status")?;
|
||||
|
||||
@ -317,7 +324,7 @@ impl ProcFS {
|
||||
// let pf= pid_dir.find("status").expect("Cannot find status");
|
||||
|
||||
// 删除进程文件夹
|
||||
proc.unlink(&format!("{}", pid))?;
|
||||
proc.unlink(&pid.to_string())?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@ -514,7 +521,7 @@ impl IndexNode for LockedProcFSInode {
|
||||
},
|
||||
fs: inode.fs.clone(),
|
||||
fdata: InodeInfo {
|
||||
pid: 0,
|
||||
pid: Pid::new(0),
|
||||
ftype: ProcFileType::Default,
|
||||
},
|
||||
})));
|
||||
@ -657,18 +664,8 @@ impl IndexNode for LockedProcFSInode {
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_procfs_register_pid(pid: pid_t) -> u64 {
|
||||
let r = procfs_register_pid(pid);
|
||||
if r.is_ok() {
|
||||
return 0;
|
||||
} else {
|
||||
return r.unwrap_err() as u64;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 向procfs注册进程
|
||||
pub fn procfs_register_pid(pid: pid_t) -> Result<(), SystemError> {
|
||||
pub fn procfs_register_pid(pid: Pid) -> Result<(), SystemError> {
|
||||
let procfs_inode = ROOT_INODE().find("proc")?;
|
||||
|
||||
let procfs_inode = procfs_inode
|
||||
@ -683,18 +680,8 @@ pub fn procfs_register_pid(pid: pid_t) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_procfs_unregister_pid(pid: pid_t) -> u64 {
|
||||
let r = procfs_unregister_pid(pid);
|
||||
if r.is_ok() {
|
||||
return 0;
|
||||
} else {
|
||||
return r.unwrap_err() as u64;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 在ProcFS中,解除进程的注册
|
||||
pub fn procfs_unregister_pid(pid: pid_t) -> Result<(), SystemError> {
|
||||
pub fn procfs_unregister_pid(pid: Pid) -> Result<(), SystemError> {
|
||||
// 获取procfs实例
|
||||
let procfs_inode: Arc<dyn IndexNode> = ROOT_INODE().find("proc")?;
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <common/fcntl.h>
|
||||
#include <common/glib.h>
|
||||
#include <common/lockref.h>
|
||||
#include <common/user_namespace.h>
|
||||
#include <DragonOS/stdint.h>
|
||||
#include <mm/slab.h>
|
||||
|
||||
|
@ -144,8 +144,7 @@ fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemE
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mount_root_fs() -> i32 {
|
||||
pub fn mount_root_fs() -> Result<(), SystemError> {
|
||||
kinfo!("Try to mount FAT32 as root fs...");
|
||||
let partiton: Arc<Partition> = ahci::get_disks_by_name("ahci_disk_0".to_string())
|
||||
.unwrap()
|
||||
@ -174,7 +173,7 @@ pub extern "C" fn mount_root_fs() -> i32 {
|
||||
}
|
||||
kinfo!("Successfully migrate rootfs to FAT32!");
|
||||
|
||||
return 0;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// @brief 创建文件/文件夹
|
||||
|
@ -1,16 +1,16 @@
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
driver::{
|
||||
base::{block::SeekFrom, device::DevicePrivateData},
|
||||
tty::TtyFilePrivateData,
|
||||
},
|
||||
filesystem::procfs::ProcfsFilePrivateData,
|
||||
include::bindings::bindings::process_control_block,
|
||||
kerror,
|
||||
libs::spinlock::SpinLock,
|
||||
process::ProcessManager,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -299,16 +299,16 @@ impl File {
|
||||
|
||||
/// @brief 尝试克隆一个文件
|
||||
///
|
||||
/// @return Option<Box<File>> 克隆后的文件结构体。如果克隆失败,返回None
|
||||
pub fn try_clone(&self) -> Option<Box<File>> {
|
||||
let mut res: Box<File> = Box::new(Self {
|
||||
/// @return Option<File> 克隆后的文件结构体。如果克隆失败,返回None
|
||||
pub fn try_clone(&self) -> Option<File> {
|
||||
let mut res = Self {
|
||||
inode: self.inode.clone(),
|
||||
offset: self.offset.clone(),
|
||||
mode: self.mode.clone(),
|
||||
file_type: self.file_type.clone(),
|
||||
readdir_subdirs_name: self.readdir_subdirs_name.clone(),
|
||||
private_data: self.private_data.clone(),
|
||||
});
|
||||
};
|
||||
// 调用inode的open方法,让inode知道有新的文件打开了这个inode
|
||||
if self.inode.open(&mut res.private_data, &res.mode).is_err() {
|
||||
return None;
|
||||
@ -361,7 +361,7 @@ impl File {
|
||||
///
|
||||
/// @return 成功:Ok()
|
||||
/// 失败:Err(错误码)
|
||||
pub fn ftruncate(&mut self, len: usize) -> Result<(), SystemError> {
|
||||
pub fn ftruncate(&self, len: usize) -> Result<(), SystemError> {
|
||||
// 如果文件不可写,返回错误
|
||||
self.writeable()?;
|
||||
|
||||
@ -377,8 +377,8 @@ impl Drop for File {
|
||||
// 打印错误信息
|
||||
if r.is_err() {
|
||||
kerror!(
|
||||
"pid: {} failed to close file: {:?}, errno={:?}",
|
||||
current_pcb().pid,
|
||||
"pid: {:?} failed to close file: {:?}, errno={:?}",
|
||||
ProcessManager::current_pcb().pid(),
|
||||
self,
|
||||
r.unwrap_err()
|
||||
);
|
||||
@ -390,49 +390,48 @@ impl Drop for File {
|
||||
#[derive(Debug)]
|
||||
pub struct FileDescriptorVec {
|
||||
/// 当前进程打开的文件描述符
|
||||
pub fds: [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD],
|
||||
fds: [Option<Arc<SpinLock<File>>>; FileDescriptorVec::PROCESS_MAX_FD],
|
||||
}
|
||||
|
||||
impl FileDescriptorVec {
|
||||
pub const PROCESS_MAX_FD: usize = 32;
|
||||
|
||||
pub fn new() -> Box<FileDescriptorVec> {
|
||||
pub fn new() -> FileDescriptorVec {
|
||||
// 先声明一个未初始化的数组
|
||||
let mut data: [MaybeUninit<Option<Box<File>>>; FileDescriptorVec::PROCESS_MAX_FD] =
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
let mut data: [MaybeUninit<Option<Arc<SpinLock<File>>>>;
|
||||
FileDescriptorVec::PROCESS_MAX_FD] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
||||
// 逐个把每个元素初始化为None
|
||||
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
|
||||
data[i] = MaybeUninit::new(None);
|
||||
}
|
||||
// 由于一切都初始化完毕,因此将未初始化的类型强制转换为已经初始化的类型
|
||||
let data: [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD] = unsafe {
|
||||
core::mem::transmute::<_, [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD]>(data)
|
||||
let data: [Option<Arc<SpinLock<File>>>; FileDescriptorVec::PROCESS_MAX_FD] = unsafe {
|
||||
core::mem::transmute::<
|
||||
_,
|
||||
[Option<Arc<SpinLock<File>>>; FileDescriptorVec::PROCESS_MAX_FD],
|
||||
>(data)
|
||||
};
|
||||
|
||||
// 初始化文件描述符数组结构体
|
||||
return Box::new(FileDescriptorVec { fds: data });
|
||||
return FileDescriptorVec { fds: data };
|
||||
}
|
||||
|
||||
/// @brief 克隆一个文件描述符数组
|
||||
///
|
||||
/// @return Box<FileDescriptorVec> 克隆后的文件描述符数组
|
||||
pub fn clone(&self) -> Box<FileDescriptorVec> {
|
||||
let mut res: Box<FileDescriptorVec> = FileDescriptorVec::new();
|
||||
/// @return FileDescriptorVec 克隆后的文件描述符数组
|
||||
pub fn clone(&self) -> FileDescriptorVec {
|
||||
let mut res = FileDescriptorVec::new();
|
||||
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
|
||||
if let Some(file) = &self.fds[i] {
|
||||
res.fds[i] = file.try_clone();
|
||||
if let Some(file) = file.lock().try_clone() {
|
||||
res.fds[i] = Some(Arc::new(SpinLock::new(file)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @brief 从pcb的fds字段,获取文件描述符数组的可变引用
|
||||
#[inline]
|
||||
pub fn from_pcb(pcb: &'static process_control_block) -> Option<&'static mut FileDescriptorVec> {
|
||||
return unsafe { (pcb.fds as usize as *mut FileDescriptorVec).as_mut() };
|
||||
}
|
||||
|
||||
/// @brief 判断文件描述符序号是否合法
|
||||
///
|
||||
/// @return true 合法
|
||||
@ -446,4 +445,73 @@ impl FileDescriptorVec {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// 申请文件描述符,并把文件对象存入其中。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `file` 要存放的文件对象
|
||||
/// - `fd` 如果为Some(i32),表示指定要申请这个文件描述符,如果这个文件描述符已经被使用,那么返回EBADF
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// - `Ok(i32)` 申请成功,返回申请到的文件描述符
|
||||
/// - `Err(SystemError)` 申请失败,返回错误码,并且,file对象将被drop掉
|
||||
pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> {
|
||||
if fd.is_some() {
|
||||
// 指定了要申请的文件描述符编号
|
||||
let new_fd = fd.unwrap();
|
||||
let x = &mut self.fds[new_fd as usize];
|
||||
if x.is_none() {
|
||||
*x = Some(Arc::new(SpinLock::new(file)));
|
||||
return Ok(new_fd);
|
||||
} else {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
} else {
|
||||
// 没有指定要申请的文件描述符编号
|
||||
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
|
||||
if self.fds[i].is_none() {
|
||||
self.fds[i] = Some(Arc::new(SpinLock::new(file)));
|
||||
return Ok(i as i32);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据文件描述符序号,获取文件结构体的Arc指针
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fd` 文件描述符序号
|
||||
pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<SpinLock<File>>> {
|
||||
if !FileDescriptorVec::validate_fd(fd) {
|
||||
return None;
|
||||
}
|
||||
return self.fds[fd as usize].clone();
|
||||
}
|
||||
|
||||
/// 释放文件描述符,同时关闭文件。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fd` 文件描述符序号
|
||||
pub fn drop_fd(&mut self, fd: i32) -> Result<(), SystemError> {
|
||||
// 判断文件描述符的数字是否超过限制
|
||||
if !FileDescriptorVec::validate_fd(fd) {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
let f = self.get_file_by_fd(fd);
|
||||
if f.is_none() {
|
||||
// 如果文件描述符不存在,报错
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
// 把文件描述符数组对应位置设置为空
|
||||
let file = self.fds[fd as usize].take().unwrap();
|
||||
assert!(Arc::strong_count(&file) == 1);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
kernel_io_subdirs:=block
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
||||
$(kernel_io_subdirs): ECHO
|
||||
|
||||
$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)"
|
||||
|
||||
all: $(kernel_io_subdirs)
|
||||
|
||||
|
||||
clean:
|
||||
echo "Done."
|
@ -1,17 +0,0 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
|
||||
kernel_io_block_objs:= $(shell find ./*.c )
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
||||
$(kernel_io_block_objs): ECHO
|
||||
$(CC) $(CFLAGS) -c $@ -o $@.o
|
||||
|
||||
all: $(kernel_io_block_objs)
|
||||
|
||||
|
||||
clean:
|
||||
echo "Done."
|
@ -1 +0,0 @@
|
||||
// pub mod block_io_scheduler;
|
@ -1,4 +1,7 @@
|
||||
use core::any::Any;
|
||||
use core::{
|
||||
any::Any,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
@ -91,12 +94,15 @@ impl MountFSInode {
|
||||
// 创建Weak指针
|
||||
let weak: Weak<MountFSInode> = Arc::downgrade(&inode);
|
||||
// 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
|
||||
let ptr: *mut MountFSInode = Arc::into_raw(inode) as *mut Self;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
let ptr: *mut MountFSInode = Arc::into_raw(inode.clone()) as *mut Self;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
(*ptr).self_ref = weak;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// 返回初始化好的MountFSInode对象
|
||||
return Arc::from_raw(ptr);
|
||||
return inode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,9 +144,14 @@ impl IndexNode for MountFSInode {
|
||||
mode: u32,
|
||||
data: usize,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
return self
|
||||
return Ok(MountFSInode {
|
||||
inner_inode: self
|
||||
.inner_inode
|
||||
.create_with_data(name, file_type, mode, data);
|
||||
.create_with_data(name, file_type, mode, data)?,
|
||||
mount_fs: self.mount_fs.clone(),
|
||||
self_ref: Weak::default(),
|
||||
}
|
||||
.wrap());
|
||||
}
|
||||
|
||||
fn truncate(&self, len: usize) -> Result<(), SystemError> {
|
||||
|
@ -1,11 +1,17 @@
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
driver::base::block::SeekFrom,
|
||||
filesystem::vfs::file::FileDescriptorVec,
|
||||
include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM},
|
||||
kerror,
|
||||
libs::rwlock::RwLockWriteGuard,
|
||||
mm::VirtAddr,
|
||||
process::ProcessManager,
|
||||
syscall::{Syscall, SystemError},
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -128,6 +134,7 @@ impl Syscall {
|
||||
/// @return 文件描述符编号,或者是错误码
|
||||
pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
|
||||
// kdebug!("open: path: {}, mode: {:?}", path, mode);
|
||||
|
||||
// 文件名过长
|
||||
if path.len() > PAGE_4K_SIZE as usize {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
@ -181,8 +188,12 @@ impl Syscall {
|
||||
}
|
||||
|
||||
// 把文件对象存入pcb
|
||||
let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
|
||||
// kdebug!("open: fd: {:?}", r);
|
||||
let r = ProcessManager::current_pcb()
|
||||
.fd_table()
|
||||
.write()
|
||||
.alloc_fd(file, None)
|
||||
.map(|fd| fd as usize);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -192,8 +203,10 @@ impl Syscall {
|
||||
///
|
||||
/// @return 成功返回0,失败返回错误码
|
||||
pub fn close(fd: usize) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::close: fd: {}", fd);
|
||||
return current_pcb().drop_fd(fd as i32).map(|_| 0);
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let mut fd_table_guard = binding.write();
|
||||
|
||||
return fd_table_guard.drop_fd(fd as i32).map(|_| 0);
|
||||
}
|
||||
|
||||
/// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
|
||||
@ -204,14 +217,18 @@ impl Syscall {
|
||||
/// @return Ok(usize) 成功读取的数据的字节数
|
||||
/// @return Err(SystemError) 读取失败,返回posix错误码
|
||||
pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::read: fd: {}, len={}", fd, buf.len());
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
|
||||
let file = fd_table_guard.get_file_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let file: &mut File = file.unwrap();
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
let file = file.unwrap();
|
||||
|
||||
return file.read(buf.len(), buf);
|
||||
return file.lock_no_preempt().read(buf.len(), buf);
|
||||
}
|
||||
|
||||
/// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
|
||||
@ -222,14 +239,16 @@ impl Syscall {
|
||||
/// @return Ok(usize) 成功写入的数据的字节数
|
||||
/// @return Err(SystemError) 写入失败,返回posix错误码
|
||||
pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::write: fd: {}, len={}", fd, buf.len());
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let file: &mut File = file.unwrap();
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
|
||||
return file.write(buf.len(), buf);
|
||||
let file = fd_table_guard
|
||||
.get_file_by_fd(fd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
return file.lock_no_preempt().write(buf.len(), buf);
|
||||
}
|
||||
|
||||
/// @brief 调整文件操作指针的位置
|
||||
@ -240,13 +259,15 @@ impl Syscall {
|
||||
/// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
|
||||
/// @return Err(SystemError) 调整失败,返回posix错误码
|
||||
pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek);
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let file: &mut File = file.unwrap();
|
||||
return file.lseek(seek);
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
let file = fd_table_guard
|
||||
.get_file_by_fd(fd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
return file.lock_no_preempt().lseek(seek);
|
||||
}
|
||||
|
||||
/// @brief 切换工作目录
|
||||
@ -272,29 +293,71 @@ impl Syscall {
|
||||
///
|
||||
/// ENAMETOOLONG | 路径过长
|
||||
pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
|
||||
let proc = ProcessManager::current_pcb();
|
||||
// Copy path to kernel space to avoid some security issues
|
||||
let path: Box<&str> = Box::new(dest_path);
|
||||
let inode = match ROOT_INODE().lookup(&path) {
|
||||
let path = dest_path.to_string();
|
||||
let mut new_path = String::from("");
|
||||
if path.len() > 0 {
|
||||
let cwd = match path.as_bytes()[0] {
|
||||
b'/' => String::from("/"),
|
||||
_ => proc.basic().cwd(),
|
||||
};
|
||||
let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
|
||||
let path_split = path.split("/").filter(|&x| x != "");
|
||||
for seg in path_split {
|
||||
if seg == ".." {
|
||||
cwd_vec.pop();
|
||||
} else if seg == "." {
|
||||
// 当前目录
|
||||
} else {
|
||||
cwd_vec.push(seg);
|
||||
}
|
||||
}
|
||||
//proc.basic().set_path(String::from(""));
|
||||
for seg in cwd_vec {
|
||||
new_path.push_str("/");
|
||||
new_path.push_str(seg);
|
||||
}
|
||||
if new_path == "" {
|
||||
new_path = String::from("/");
|
||||
}
|
||||
}
|
||||
let inode = match ROOT_INODE().lookup(&new_path) {
|
||||
Err(e) => {
|
||||
kerror!("Change Directory Failed, Error = {:?}", e);
|
||||
return Err(SystemError::ENOENT);
|
||||
}
|
||||
Ok(i) => i,
|
||||
};
|
||||
|
||||
match inode.metadata() {
|
||||
Err(e) => {
|
||||
kerror!("INode Get MetaData Failed, Error = {:?}", e);
|
||||
return Err(SystemError::ENOENT);
|
||||
}
|
||||
Ok(i) => {
|
||||
if let FileType::Dir = i.file_type {
|
||||
let metadata = inode.metadata()?;
|
||||
if metadata.file_type == FileType::Dir {
|
||||
proc.basic_mut().set_cwd(String::from(new_path));
|
||||
return Ok(0);
|
||||
} else {
|
||||
return Err(SystemError::ENOTDIR);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 获取当前进程的工作目录路径
|
||||
///
|
||||
/// @param buf 指向缓冲区的指针
|
||||
/// @param size 缓冲区的大小
|
||||
///
|
||||
/// @return 成功,返回的指针指向包含工作目录路径的字符串
|
||||
/// @return 错误,没有足够的空间
|
||||
pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> {
|
||||
let proc = ProcessManager::current_pcb();
|
||||
let cwd = proc.basic().cwd();
|
||||
|
||||
let cwd_bytes = cwd.as_bytes();
|
||||
let cwd_len = cwd_bytes.len();
|
||||
if cwd_len + 1 > buf.len() {
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
buf[..cwd_len].copy_from_slice(cwd_bytes);
|
||||
buf[cwd_len] = 0;
|
||||
|
||||
return Ok(VirtAddr::new(buf.as_ptr() as usize));
|
||||
}
|
||||
|
||||
/// @brief 获取目录中的数据
|
||||
@ -314,15 +377,15 @@ impl Syscall {
|
||||
}
|
||||
|
||||
// 获取fd
|
||||
let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) {
|
||||
None => {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
Some(file) => file,
|
||||
};
|
||||
// kdebug!("file={file:?}");
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
let file = fd_table_guard
|
||||
.get_file_by_fd(fd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
|
||||
return file.readdir(dirent).map(|x| x as usize);
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
return file.lock_no_preempt().readdir(dirent).map(|x| x as usize);
|
||||
}
|
||||
|
||||
/// @brief 创建文件夹
|
||||
@ -375,26 +438,21 @@ impl Syscall {
|
||||
|
||||
/// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
|
||||
pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
// 获得当前文件描述符数组
|
||||
// 确认oldfd是否有效
|
||||
if FileDescriptorVec::validate_fd(oldfd) {
|
||||
if let Some(file) = &fds.fds[oldfd as usize] {
|
||||
// 尝试获取对应的文件结构体
|
||||
let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?;
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let mut fd_table_guard = binding.write();
|
||||
|
||||
let old_file = fd_table_guard
|
||||
.get_file_by_fd(oldfd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
|
||||
let new_file = old_file
|
||||
.lock_no_preempt()
|
||||
.try_clone()
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
// 申请文件描述符,并把文件对象存入其中
|
||||
let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize);
|
||||
let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize);
|
||||
return res;
|
||||
}
|
||||
// oldfd对应的文件不存在
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
} else {
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
|
||||
/// 并返回新复制的文件结构体对应的fd.
|
||||
@ -410,44 +468,47 @@ impl Syscall {
|
||||
/// - 成功:新文件描述符
|
||||
/// - 失败:错误码
|
||||
pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
// 获得当前文件描述符数组
|
||||
if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
|
||||
//确认oldfd, newid是否有效
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let mut fd_table_guard = binding.write();
|
||||
return Self::do_dup2(oldfd, newfd, &mut fd_table_guard);
|
||||
}
|
||||
|
||||
fn do_dup2(
|
||||
oldfd: i32,
|
||||
newfd: i32,
|
||||
fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
|
||||
) -> Result<usize, SystemError> {
|
||||
// 确认oldfd, newid是否有效
|
||||
if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
if oldfd == newfd {
|
||||
// 若oldfd与newfd相等
|
||||
return Ok(newfd as usize);
|
||||
}
|
||||
|
||||
if let Some(file) = &fds.fds[oldfd as usize] {
|
||||
if fds.fds[newfd as usize].is_some() {
|
||||
let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some();
|
||||
if new_exists {
|
||||
// close newfd
|
||||
if let Err(_) = current_pcb().drop_fd(newfd) {
|
||||
if let Err(_) = fd_table_guard.drop_fd(newfd) {
|
||||
// An I/O error occurred while attempting to close fildes2.
|
||||
return Err(SystemError::EIO);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取对应的文件结构体
|
||||
let file_cp = file.try_clone();
|
||||
if file_cp.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let old_file = fd_table_guard
|
||||
.get_file_by_fd(oldfd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
let new_file = old_file
|
||||
.lock_no_preempt()
|
||||
.try_clone()
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
// 申请文件描述符,并把文件对象存入其中
|
||||
let res = current_pcb()
|
||||
.alloc_fd(*file_cp.unwrap(), Some(newfd))
|
||||
let res = fd_table_guard
|
||||
.alloc_fd(new_file, Some(newfd))
|
||||
.map(|x| x as usize);
|
||||
|
||||
return res;
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
} else {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
// 从pcb获取文件描述符数组失败
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
|
||||
/// # fcntl
|
||||
///
|
||||
@ -464,73 +525,74 @@ impl Syscall {
|
||||
}
|
||||
let arg = arg as usize;
|
||||
for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if fds.fds[i as usize].is_none() {
|
||||
return Self::dup2(fd, i as i32);
|
||||
}
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let mut fd_table_guard = binding.write();
|
||||
if fd_table_guard.get_file_by_fd(fd).is_none() {
|
||||
return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
FcntlCommand::GetFd => {
|
||||
// Get file descriptor flags.
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &fds.fds[fd as usize] {
|
||||
if file.close_on_exec() {
|
||||
if file.lock().close_on_exec() {
|
||||
return Ok(FD_CLOEXEC as usize);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
FcntlCommand::SetFd => {
|
||||
// Set file descriptor flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.write();
|
||||
|
||||
if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
let arg = arg as u32;
|
||||
if arg & FD_CLOEXEC != 0 {
|
||||
file.set_close_on_exec(true);
|
||||
file.lock().set_close_on_exec(true);
|
||||
} else {
|
||||
file.set_close_on_exec(false);
|
||||
file.lock().set_close_on_exec(false);
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
FcntlCommand::GetFlags => {
|
||||
// Get file status flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &fds.fds[fd as usize] {
|
||||
return Ok(file.mode().bits() as usize);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
|
||||
if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
return Ok(file.lock_no_preempt().mode().bits() as usize);
|
||||
}
|
||||
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
FcntlCommand::SetFlags => {
|
||||
// Set file status flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.write();
|
||||
|
||||
if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
|
||||
let arg = arg as u32;
|
||||
let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
|
||||
file.set_mode(mode)?;
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
file.lock_no_preempt().set_mode(mode)?;
|
||||
return Ok(0);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
_ => {
|
||||
@ -560,25 +622,31 @@ impl Syscall {
|
||||
///
|
||||
/// 如果成功,返回0,否则返回错误码.
|
||||
pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let r = file.ftruncate(len).map(|_| 0);
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
|
||||
if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
let r = file.lock_no_preempt().ftruncate(len).map(|_| 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
|
||||
let cur = current_pcb();
|
||||
match cur.get_file_ref_by_fd(fd) {
|
||||
Some(file) => {
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
let file = fd_table_guard
|
||||
.get_file_by_fd(fd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
// drop guard 以避免无法调度的问题
|
||||
drop(fd_table_guard);
|
||||
|
||||
let mut kstat = PosixKstat::new();
|
||||
// 获取文件信息
|
||||
match file.metadata() {
|
||||
Ok(metadata) => {
|
||||
let metadata = file.lock().metadata()?;
|
||||
kstat.size = metadata.size as i64;
|
||||
kstat.dev_id = metadata.dev_id as u64;
|
||||
kstat.inode = metadata.inode_id as u64;
|
||||
@ -597,7 +665,7 @@ impl Syscall {
|
||||
kstat.gid = metadata.gid as i32;
|
||||
kstat.rdev = metadata.raw_dev as i64;
|
||||
kstat.mode.bits = metadata.mode;
|
||||
match file.file_type() {
|
||||
match file.lock().file_type() {
|
||||
FileType::File => kstat.mode.insert(ModeType::S_IFMT),
|
||||
FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
|
||||
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
|
||||
@ -606,20 +674,12 @@ impl Syscall {
|
||||
FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
|
||||
FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
return Ok(kstat);
|
||||
}
|
||||
None => {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
|
||||
match Self::do_fstat(fd) {
|
||||
Ok(kstat) => {
|
||||
let kstat = Self::do_fstat(fd)?;
|
||||
if usr_kstat.is_null() {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
@ -628,11 +688,7 @@ impl Syscall {
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct IoVec {
|
||||
|
@ -401,45 +401,6 @@ repeat_set_idt:
|
||||
dec %rcx
|
||||
jne repeat_set_idt
|
||||
|
||||
SetUp_TSS64:
|
||||
// == 设置64位的任务状态段表 ===
|
||||
//rdx保存高8B, rax保存低8B
|
||||
leaq TSS64_Table(%rip), %rdx // 获取定义在process.c中的initial_tss[0]的地址
|
||||
|
||||
movq $0xffff800000000000, %r8
|
||||
addq %r8, %rdx
|
||||
|
||||
xorq %rax, %rax
|
||||
xorq %rcx, %rcx
|
||||
|
||||
// 设置TSS描述符的47:40位为1000 1001
|
||||
movq $0x89, %rax
|
||||
shlq $40, %rax
|
||||
|
||||
// 设置段基地址31:24
|
||||
movl %edx, %ecx
|
||||
shrl $24, %ecx
|
||||
shlq $56, %rcx
|
||||
addq %rcx, %rax
|
||||
|
||||
xorq %rcx, %rcx
|
||||
|
||||
// 设置段基地址23:00
|
||||
movl %edx, %ecx
|
||||
andl $0xffffff, %ecx // 清空ecx的中有效值的高8位(也就是上面已经赋值了的)
|
||||
shlq $16, %rcx
|
||||
addq %rcx, %rax
|
||||
|
||||
addq $103, %rax // 设置段长度
|
||||
|
||||
leaq GDT_Table(%rip), %rdi
|
||||
movq %rax, 80(%rdi) // 把低八B存储到GDT第10项
|
||||
shrq $32, %rdx
|
||||
movq %rdx, 88(%rdi) // 高8B存到GDT第11项
|
||||
|
||||
// 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载)
|
||||
// mov $0x50, %ax // 设置起始地址为80
|
||||
// ltr %ax
|
||||
|
||||
//now enable SSE and the like
|
||||
movq %cr0, %rax
|
||||
@ -451,7 +412,6 @@ SetUp_TSS64:
|
||||
movq %rax, %cr4
|
||||
|
||||
|
||||
|
||||
movq go_to_kernel(%rip), %rax /* movq address */
|
||||
pushq $0x08
|
||||
pushq %rax
|
||||
@ -525,6 +485,9 @@ go_to_ignore_int:
|
||||
ENTRY(head_stack_start)
|
||||
.quad initial_proc_union + 32768
|
||||
|
||||
.align 32768
|
||||
initial_proc_union:
|
||||
.fill 32768, 1, 0
|
||||
|
||||
// 初始化页表
|
||||
.align 0x1000 //设置为4k对齐
|
||||
@ -591,12 +554,7 @@ IDT_POINTER64:
|
||||
IDT_LIMIT64: .word IDT_END - IDT_Table - 1
|
||||
IDT_BASE64: .quad IDT_Table + 0xffff800000000000
|
||||
|
||||
// 64位的TSS表
|
||||
.global TSS64_Table
|
||||
|
||||
TSS64_Table:
|
||||
.fill 13, 8, 0
|
||||
TSS64_END:
|
||||
|
||||
.section .bootstrap.data
|
||||
mb2_magic: .quad 0
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <common/list.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/sys/types.h>
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
// 系统最大支持的信号数量
|
||||
#define MAX_SIG_NUM 64
|
||||
|
@ -11,7 +11,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/blk_types.h>
|
||||
#include <common/completion.h>
|
||||
#include <common/crc16.h>
|
||||
#include <common/crc32.h>
|
||||
#include <common/crc64.h>
|
||||
@ -20,7 +19,6 @@
|
||||
#include <common/glib.h>
|
||||
#include <common/idr.h>
|
||||
#include <common/kfifo.h>
|
||||
#include <common/kthread.h>
|
||||
#include <common/list.h>
|
||||
#include <common/lz4.h>
|
||||
#include <common/printk.h>
|
||||
@ -29,10 +27,7 @@
|
||||
#include <common/string.h>
|
||||
#include <common/time.h>
|
||||
#include <common/unistd.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <driver/multiboot2/multiboot2.h>
|
||||
#include <driver/video/video.h>
|
||||
#include <driver/virtio/virtio.h>
|
||||
#include <exception/gate.h>
|
||||
#include <include/DragonOS/refcount.h>
|
||||
#include <include/DragonOS/signal.h>
|
||||
@ -48,3 +43,4 @@
|
||||
#include <time/sleep.h>
|
||||
#include <driver/pci/pci_irq.h>
|
||||
#include <common/errno.h>
|
||||
#include <common/cpu.h>
|
||||
|
@ -1,10 +0,0 @@
|
||||
|
||||
all:
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
# pipe.o: pipe.c
|
||||
# $(CC) $(CFLAGS) -c pipe.c -o pipe.o
|
||||
|
||||
clean:
|
||||
echo "Done."
|
@ -1,4 +1,2 @@
|
||||
pub mod pipe;
|
||||
pub mod signal;
|
||||
pub mod signal_types;
|
||||
pub mod syscall;
|
||||
|
@ -5,8 +5,8 @@ use crate::{
|
||||
core::generate_inode_id, file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||
Metadata, PollStatus,
|
||||
},
|
||||
include::bindings::bindings::PROC_INTERRUPTIBLE,
|
||||
libs::{spinlock::SpinLock, wait_queue::WaitQueue},
|
||||
process::ProcessState,
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
@ -89,12 +89,16 @@ impl IndexNode for LockedPipeInode {
|
||||
|
||||
// 如果管道里面没有数据,则唤醒写端,
|
||||
while inode.valid_cnt == 0 {
|
||||
inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
inode
|
||||
.write_wait_queue
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
|
||||
// 如果为非阻塞管道,直接返回错误
|
||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
||||
drop(inode);
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
|
||||
// 否则在读等待队列中睡眠,并释放锁
|
||||
unsafe {
|
||||
let irq_guard = CurrentIrqArch::save_and_disable_irq();
|
||||
@ -132,7 +136,9 @@ impl IndexNode for LockedPipeInode {
|
||||
inode.valid_cnt -= num as i32;
|
||||
|
||||
//读完后解锁并唤醒等待在写等待队列中的进程
|
||||
inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
inode
|
||||
.write_wait_queue
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
//返回读取的字节数
|
||||
return Ok(num);
|
||||
}
|
||||
@ -175,12 +181,16 @@ impl IndexNode for LockedPipeInode {
|
||||
|
||||
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
|
||||
// 唤醒读端
|
||||
inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
inode
|
||||
.read_wait_queue
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
|
||||
// 如果为非阻塞管道,直接返回错误
|
||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
||||
drop(inode);
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
|
||||
// 解锁并睡眠
|
||||
unsafe {
|
||||
let irq_guard = CurrentIrqArch::save_and_disable_irq();
|
||||
@ -208,7 +218,9 @@ impl IndexNode for LockedPipeInode {
|
||||
inode.valid_cnt += len as i32;
|
||||
|
||||
// 读完后解锁并唤醒等待在读等待队列中的进程
|
||||
inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
inode
|
||||
.read_wait_queue
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
// 返回写入的字节数
|
||||
return Ok(len);
|
||||
}
|
||||
|
@ -1,922 +0,0 @@
|
||||
use core::{
|
||||
ffi::c_void,
|
||||
intrinsics::size_of,
|
||||
ptr::{null_mut, read_volatile},
|
||||
sync::atomic::compiler_fence,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
asm::{bitops::ffz, current::current_pcb, ptrace::user_mode},
|
||||
fpu::FpState,
|
||||
interrupt::sti,
|
||||
},
|
||||
include::bindings::bindings::{
|
||||
pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs,
|
||||
spinlock_t, verify_area, NULL, PF_EXITING, PF_KTHREAD, PF_SIGNALED, PF_WAKEKILL,
|
||||
PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR,
|
||||
},
|
||||
ipc::signal_types::sigset_add,
|
||||
kBUG, kdebug, kerror, kwarn,
|
||||
libs::{
|
||||
ffi_convert::FFIBind2Rust,
|
||||
spinlock::{
|
||||
spin_is_locked, spin_lock_irq, spin_lock_irqsave, spin_unlock_irq,
|
||||
spin_unlock_irqrestore,
|
||||
},
|
||||
},
|
||||
process::{
|
||||
pid::PidType,
|
||||
process::{process_is_stopped, process_kick, process_wake_up_state},
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::signal_types::{
|
||||
si_code_val, sig_is_member, sigaction, sigaction__union_u, sigcontext, sigframe,
|
||||
sighand_struct, siginfo, signal_struct, sigpending, sigset_clear, sigset_del, sigset_delmask,
|
||||
sigset_equal, sigset_t, SigQueue, SignalNumber, MAX_SIG_NUM, SA_ALL_FLAGS, SA_FLAG_DFL,
|
||||
SA_FLAG_IGN, SA_FLAG_IMMUTABLE, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
|
||||
};
|
||||
|
||||
/// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
|
||||
pub static DEFAULT_SIGACTION: sigaction = sigaction {
|
||||
_u: sigaction__union_u {
|
||||
_sa_handler: NULL as u64,
|
||||
},
|
||||
sa_flags: SA_FLAG_DFL,
|
||||
sa_mask: 0,
|
||||
sa_restorer: NULL as u64,
|
||||
};
|
||||
|
||||
/// 默认的“忽略信号”的sigaction
|
||||
#[allow(dead_code)]
|
||||
pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction {
|
||||
_u: sigaction__union_u {
|
||||
_sa_handler: NULL as u64,
|
||||
},
|
||||
sa_flags: SA_FLAG_IGN,
|
||||
sa_mask: 0,
|
||||
sa_restorer: NULL as u64,
|
||||
};
|
||||
|
||||
/// 通过kill的方式向目标进程发送信号
|
||||
/// @param sig 要发送的信号
|
||||
/// @param info 要发送的信息
|
||||
/// @param pid 进程id(目前只支持pid>0)
|
||||
pub fn signal_kill_something_info(
|
||||
sig: SignalNumber,
|
||||
info: Option<&mut siginfo>,
|
||||
pid: pid_t,
|
||||
) -> Result<i32, SystemError> {
|
||||
// 暂时不支持特殊的kill操作
|
||||
if pid <= 0 {
|
||||
kwarn!("Kill operation not support: pid={}", pid);
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||
}
|
||||
|
||||
// kill单个进程
|
||||
return signal_kill_proc_info(sig, info, pid);
|
||||
}
|
||||
|
||||
fn signal_kill_proc_info(
|
||||
sig: SignalNumber,
|
||||
info: Option<&mut siginfo>,
|
||||
pid: pid_t,
|
||||
) -> Result<i32, SystemError> {
|
||||
let mut retval = Err(SystemError::ESRCH);
|
||||
|
||||
// step1: 当进程管理模块拥有pcblist_lock之后,对其加锁
|
||||
|
||||
// step2: 根据pid找到pcb
|
||||
let pcb = unsafe { process_find_pcb_by_pid(pid).as_mut() };
|
||||
|
||||
if pcb.is_none() {
|
||||
kwarn!("No such process.");
|
||||
return retval;
|
||||
}
|
||||
|
||||
// println!("Target pcb = {:?}", pcb.as_ref().unwrap());
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// step3: 调用signal_send_sig_info函数,发送信息
|
||||
retval = signal_send_sig_info(sig, info, pcb.unwrap());
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// step4: 解锁
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// @brief 验证信号的值是否在范围内
|
||||
#[inline]
|
||||
fn verify_signal(sig: SignalNumber) -> bool {
|
||||
return if (sig as i32) <= MAX_SIG_NUM {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief 在发送信号给指定的进程前,做一些权限检查. 检查是否有权限发送
|
||||
/// @param sig 要发送的信号
|
||||
/// @param info 要发送的信息
|
||||
/// @param target_pcb 信号的接收者
|
||||
fn signal_send_sig_info(
|
||||
sig: SignalNumber,
|
||||
info: Option<&mut siginfo>,
|
||||
target_pcb: &mut process_control_block,
|
||||
) -> Result<i32, SystemError> {
|
||||
// kdebug!("signal_send_sig_info");
|
||||
// 检查sig是否符合要求,如果不符合要求,则退出。
|
||||
if !verify_signal(sig) {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
// 信号符合要求,可以发送
|
||||
|
||||
let mut retval = Err(SystemError::ESRCH);
|
||||
let mut flags: usize = 0;
|
||||
// 如果上锁成功,则发送信号
|
||||
if !lock_process_sighand(target_pcb, &mut flags).is_none() {
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// 发送信号
|
||||
retval = send_signal_locked(sig, info, target_pcb, PidType::PID);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// kdebug!("flags=0x{:016x}", flags);
|
||||
// 对sighand放锁
|
||||
unlock_process_sighand(target_pcb, flags);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// @brief 对pcb的sighand结构体中的siglock进行加锁,并关闭中断
|
||||
/// @param pcb 目标pcb
|
||||
/// @param flags 用来保存rflags的变量
|
||||
/// @return 指向sighand_struct的可变引用
|
||||
fn lock_process_sighand<'a>(
|
||||
pcb: &'a mut process_control_block,
|
||||
flags: &mut usize,
|
||||
) -> Option<&'a mut sighand_struct> {
|
||||
// kdebug!("lock_process_sighand");
|
||||
|
||||
let sighand_ptr = sighand_struct::convert_mut(unsafe { &mut *pcb.sighand });
|
||||
// kdebug!("sighand_ptr={:?}", &sighand_ptr);
|
||||
if !sighand_ptr.is_some() {
|
||||
kBUG!("Sighand ptr of process {pid} is NULL!", pid = pcb.pid);
|
||||
return None;
|
||||
}
|
||||
|
||||
let lock = { &mut sighand_ptr.unwrap().siglock };
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
let ret = unsafe { ((*pcb).sighand as *mut sighand_struct).as_mut() };
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// @brief 对pcb的sighand结构体中的siglock进行放锁,并恢复之前存储的rflags
|
||||
/// @param pcb 目标pcb
|
||||
/// @param flags 用来保存rflags的变量,将这个值恢复到rflags寄存器中
|
||||
fn unlock_process_sighand(pcb: &mut process_control_block, flags: usize) {
|
||||
let lock = unsafe { &mut (*pcb.sighand).siglock };
|
||||
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
}
|
||||
|
||||
/// @brief 判断是否需要强制发送信号,然后发送信号
|
||||
/// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。
|
||||
///
|
||||
/// @return SystemError 错误码
|
||||
fn send_signal_locked(
|
||||
sig: SignalNumber,
|
||||
info: Option<&mut siginfo>,
|
||||
pcb: &mut process_control_block,
|
||||
pt: PidType,
|
||||
) -> Result<i32, SystemError> {
|
||||
// 是否强制发送信号
|
||||
let mut force_send = false;
|
||||
// signal的信息为空
|
||||
if info.is_none() {
|
||||
// todo: 判断signal是否来自于一个祖先进程的namespace,如果是,则强制发送信号
|
||||
} else {
|
||||
force_send = unsafe { info.as_ref().unwrap()._sinfo.data.si_code }
|
||||
== (si_code_val::SI_KERNEL as i32);
|
||||
}
|
||||
|
||||
// kdebug!("force send={}", force_send);
|
||||
|
||||
return __send_signal_locked(sig, info, pcb, pt, force_send);
|
||||
}
|
||||
|
||||
/// @brief 发送信号
|
||||
/// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。
|
||||
///
|
||||
/// @param sig 信号
|
||||
/// @param _info 信号携带的信息
|
||||
/// @param pcb 目标进程的pcb
|
||||
/// @param pt siginfo结构体中,pid字段代表的含义
|
||||
/// @return SystemError 错误码
|
||||
fn __send_signal_locked(
|
||||
sig: SignalNumber,
|
||||
info: Option<&mut siginfo>,
|
||||
pcb: &mut process_control_block,
|
||||
pt: PidType,
|
||||
_force_send: bool,
|
||||
) -> Result<i32, SystemError> {
|
||||
// kdebug!("__send_signal_locked");
|
||||
|
||||
// 判断该进入该函数时,是否已经持有了锁
|
||||
assert!(spin_is_locked(unsafe { &(*pcb.sighand).siglock }));
|
||||
|
||||
let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// 如果是kill或者目标pcb是内核线程,则无需获取sigqueue,直接发送信号即可
|
||||
if sig == SignalNumber::SIGKILL || (pcb.flags & (PF_KTHREAD as u64)) != 0 {
|
||||
complete_signal(sig, pcb, pt);
|
||||
} else {
|
||||
// 如果是其他信号,则加入到sigqueue内,然后complete_signal
|
||||
let mut q: siginfo;
|
||||
match info {
|
||||
Some(x) => {
|
||||
// 已经显式指定了siginfo,则直接使用它。
|
||||
q = x.clone();
|
||||
}
|
||||
None => {
|
||||
// 不需要显示指定siginfo,因此设置为默认值
|
||||
q = siginfo::new(sig, 0, si_code_val::SI_USER);
|
||||
q._sinfo.data._sifields._kill._pid = current_pcb().pid;
|
||||
}
|
||||
}
|
||||
|
||||
let sq: &mut SigQueue = SigQueue::from_c_void(current_pcb().sig_pending.sigqueue);
|
||||
sq.q.push(q);
|
||||
complete_signal(sig, pcb, pt);
|
||||
}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// @brief 将信号添加到目标进程的sig_pending。在引入进程组后,本函数还将负责把信号传递给整个进程组。
|
||||
///
|
||||
/// @param sig 信号
|
||||
/// @param pcb 目标pcb
|
||||
/// @param pt siginfo结构体中,pid字段代表的含义
|
||||
fn complete_signal(sig: SignalNumber, pcb: &mut process_control_block, pt: PidType) {
|
||||
// kdebug!("complete_signal");
|
||||
|
||||
// todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
|
||||
// 将这个信号加到目标进程的sig_pending中
|
||||
sigset_add(
|
||||
sigset_t::convert_mut(&mut pcb.sig_pending.signal).unwrap(),
|
||||
sig,
|
||||
);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// ===== 寻找需要wakeup的目标进程 =====
|
||||
// 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
|
||||
// todo: 当引入进程组的概念后,需要完善这里,使得它能寻找一个目标进程来唤醒,接着执行信号处理的操作。
|
||||
|
||||
let _signal: Option<&mut signal_struct> = signal_struct::convert_mut(pcb.signal);
|
||||
|
||||
let mut _target: Option<&mut process_control_block> = None;
|
||||
|
||||
// 判断目标进程是否想接收这个信号
|
||||
if wants_signal(sig, pcb) {
|
||||
_target = Some(pcb);
|
||||
} else if pt == PidType::PID {
|
||||
/*
|
||||
* There is just one thread and it does not need to be woken.
|
||||
* It will dequeue unblocked signals before it runs again.
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise try to find a suitable thread.
|
||||
* 由于目前每个进程只有1个线程,因此当前情况可以返回。信号队列的dequeue操作不需要考虑同步阻塞的问题。
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
// todo:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
|
||||
// todo!();
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// todo: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
|
||||
if _target.is_some() {
|
||||
signal_wake_up(pcb, sig == SignalNumber::SIGKILL);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 本函数用于检测指定的进程是否想要接收SIG这个信号。
|
||||
/// 当我们对于进程组中的所有进程都运行了这个检查之后,我们将可以找到组内愿意接收信号的进程。
|
||||
/// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。
|
||||
#[inline]
|
||||
fn wants_signal(sig: SignalNumber, pcb: &process_control_block) -> bool {
|
||||
// 如果改进程屏蔽了这个signal,则不能接收
|
||||
if sig_is_member(sigset_t::convert_ref(&pcb.sig_blocked).unwrap(), sig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果进程正在退出,则不能接收信号
|
||||
if (pcb.flags & (PF_EXITING as u64)) > 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
if sig == SignalNumber::SIGKILL {
|
||||
return true;
|
||||
}
|
||||
|
||||
if process_is_stopped(pcb) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项
|
||||
|
||||
// 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
|
||||
return !has_sig_pending(pcb);
|
||||
}
|
||||
|
||||
/// @brief 判断signal的处理是否可能使得整个进程组退出
|
||||
/// @return true 可能会导致退出(不一定)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn sig_fatal(pcb: &process_control_block, sig: SignalNumber) -> bool {
|
||||
let handler = unsafe {
|
||||
sighand_struct::convert_ref(pcb.sighand).unwrap().action[(sig as usize) - 1]
|
||||
._u
|
||||
._sa_handler
|
||||
};
|
||||
|
||||
// 如果handler是空,采用默认函数,signal处理可能会导致进程退出。
|
||||
if handler == NULL.into() {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: 参照linux的sig_fatal实现完整功能
|
||||
}
|
||||
|
||||
/// @brief 判断某个进程是否有信号正在等待处理
|
||||
#[inline]
|
||||
fn has_sig_pending(pcb: &process_control_block) -> bool {
|
||||
let ptr = &sigpending::convert_ref(&(*pcb).sig_pending).unwrap().signal;
|
||||
if unsafe { read_volatile(ptr) } != 0 {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn signal_wake_up(pcb: &mut process_control_block, fatal: bool) {
|
||||
// kdebug!("signal_wake_up");
|
||||
let mut state: u64 = 0;
|
||||
if fatal {
|
||||
state = PF_WAKEKILL as u64;
|
||||
}
|
||||
signal_wake_up_state(pcb, state);
|
||||
}
|
||||
|
||||
fn signal_wake_up_state(pcb: &mut process_control_block, state: u64) {
|
||||
assert!(spin_is_locked(&unsafe { (*pcb.sighand).siglock }));
|
||||
// todo: 设置线程结构体的标志位为TIF_SIGPENDING
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
|
||||
if !process_wake_up_state(pcb, state | (PROC_INTERRUPTIBLE as u64)) {
|
||||
process_kick(pcb);
|
||||
}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// @brief 信号处理函数。该函数在进程退出内核态的时候会被调用,且调用前会关闭中断。
|
||||
#[no_mangle]
|
||||
pub extern "C" fn do_signal(regs: &mut pt_regs) {
|
||||
// 检查sigpending是否为0
|
||||
if current_pcb().sig_pending.signal == 0 || (!user_mode(regs)) {
|
||||
// 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回
|
||||
sti();
|
||||
return;
|
||||
}
|
||||
|
||||
// 做完上面的检查后,开中断
|
||||
sti();
|
||||
|
||||
let oldset = current_pcb().sig_blocked;
|
||||
loop {
|
||||
let (sig_number, info, ka) = get_signal_to_deliver(regs.clone());
|
||||
// 所有的信号都处理完了
|
||||
if sig_number == SignalNumber::INVALID {
|
||||
return;
|
||||
}
|
||||
kdebug!(
|
||||
"To handle signal [{}] for pid:{}",
|
||||
sig_number as i32,
|
||||
current_pcb().pid
|
||||
);
|
||||
let res = handle_signal(sig_number, ka.unwrap(), &info.unwrap(), &oldset, regs);
|
||||
if res.is_err() {
|
||||
kerror!(
|
||||
"Error occurred when handling signal: {}, pid={}, errcode={:?}",
|
||||
sig_number as i32,
|
||||
current_pcb().pid,
|
||||
res.unwrap_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 获取要被发送的信号的signumber, siginfo, 以及对应的sigaction结构体
|
||||
fn get_signal_to_deliver(
|
||||
_regs: pt_regs,
|
||||
) -> (
|
||||
SignalNumber,
|
||||
Option<siginfo>,
|
||||
Option<&'static mut sigaction>,
|
||||
) {
|
||||
let mut info: Option<siginfo>;
|
||||
let ka: Option<&mut sigaction>;
|
||||
let mut sig_number;
|
||||
let sighand: &mut sighand_struct;
|
||||
|
||||
{
|
||||
let _tmp = sighand_struct::convert_mut(current_pcb().sighand);
|
||||
if let Some(i) = _tmp {
|
||||
sighand = i;
|
||||
} else {
|
||||
panic!("Sighand is NULL! pid={}", current_pcb().pid);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(&mut sighand.siglock);
|
||||
loop {
|
||||
(sig_number, info) =
|
||||
dequeue_signal(sigset_t::convert_mut(&mut current_pcb().sig_blocked).unwrap());
|
||||
|
||||
// 如果信号非法,则直接返回
|
||||
if sig_number == SignalNumber::INVALID {
|
||||
spin_unlock_irq(unsafe { (&mut (*current_pcb().sighand).siglock) as *mut spinlock_t });
|
||||
return (sig_number, None, None);
|
||||
}
|
||||
|
||||
// 获取指向sigaction结构体的引用
|
||||
let hand = sighand_struct::convert_mut(current_pcb().sighand).unwrap();
|
||||
// kdebug!("hand=0x{:018x}", hand as *const sighand_struct as usize);
|
||||
let tmp_ka = &mut hand.action[sig_number as usize - 1];
|
||||
|
||||
// 如果当前动作是忽略这个信号,则不管它了。
|
||||
if (tmp_ka.sa_flags & SA_FLAG_IGN) != 0 {
|
||||
continue;
|
||||
} else if (tmp_ka.sa_flags & SA_FLAG_DFL) == 0 {
|
||||
// 当前不采用默认的信号处理函数
|
||||
ka = Some(tmp_ka);
|
||||
break;
|
||||
}
|
||||
kdebug!(
|
||||
"Use default handler to handle signal [{}] for pid {}",
|
||||
sig_number as i32,
|
||||
current_pcb().pid
|
||||
);
|
||||
// ===== 经过上面的判断,如果能走到这一步,就意味着我们采用默认的信号处理函数来处理这个信号 =====
|
||||
spin_unlock_irq(&mut sighand.siglock);
|
||||
// 标记当前进程由于信号而退出
|
||||
current_pcb().flags |= PF_SIGNALED as u64;
|
||||
|
||||
// 执行进程的退出动作
|
||||
unsafe { process_do_exit(info.unwrap()._sinfo.data.si_signo as u64) };
|
||||
/* NOT REACHED 这部分代码将不会到达 */
|
||||
}
|
||||
spin_unlock_irq(&mut sighand.siglock);
|
||||
return (sig_number, info, ka);
|
||||
}
|
||||
|
||||
/// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
|
||||
/// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
|
||||
fn dequeue_signal(sig_mask: &mut sigset_t) -> (SignalNumber, Option<siginfo>) {
|
||||
// kdebug!("dequeue signal");
|
||||
// 获取下一个要处理的信号的编号
|
||||
let sig = next_signal(
|
||||
sigpending::convert_ref(&(current_pcb().sig_pending)).unwrap(),
|
||||
sig_mask,
|
||||
);
|
||||
|
||||
let info: Option<siginfo>;
|
||||
if sig != SignalNumber::INVALID {
|
||||
// 如果下一个要处理的信号是合法的,则收集其siginfo
|
||||
info = Some(collect_signal(
|
||||
sig,
|
||||
sigpending::convert_mut(&mut current_pcb().sig_pending).unwrap(),
|
||||
));
|
||||
} else {
|
||||
info = None;
|
||||
}
|
||||
|
||||
// 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
|
||||
recalc_sigpending();
|
||||
return (sig, info);
|
||||
}
|
||||
|
||||
/// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高)
|
||||
///
|
||||
/// @param pending 等待处理的信号
|
||||
/// @param sig_mask 屏蔽了的信号
|
||||
/// @return i32 下一个要处理的信号的number. 如果为0,则无效
|
||||
fn next_signal(pending: &sigpending, sig_mask: &sigset_t) -> SignalNumber {
|
||||
let mut sig = SignalNumber::INVALID;
|
||||
|
||||
let s = pending.signal;
|
||||
let m = *sig_mask;
|
||||
|
||||
// 获取第一个待处理的信号的号码
|
||||
let x = s & (!m);
|
||||
if x != 0 {
|
||||
sig = SignalNumber::from(ffz(!x) + 1);
|
||||
return sig;
|
||||
}
|
||||
|
||||
// 暂时只支持64种信号信号
|
||||
assert_eq!(_NSIG_U64_CNT, 1);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/// @brief 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
|
||||
fn recalc_sigpending() {
|
||||
// todo:
|
||||
}
|
||||
|
||||
/// @brief 收集信号的信息
|
||||
///
|
||||
/// @param sig 要收集的信号的信息
|
||||
/// @param pending 信号的排队等待标志
|
||||
/// @return siginfo 信号的信息
|
||||
fn collect_signal(sig: SignalNumber, pending: &mut sigpending) -> siginfo {
|
||||
let (info, still_pending) = unsafe { pending.queue.as_mut() }
|
||||
.unwrap()
|
||||
.find_and_delete(sig);
|
||||
|
||||
// 如果没有仍在等待的信号,则清除pending位
|
||||
if !still_pending {
|
||||
sigset_del(&mut pending.signal, sig);
|
||||
}
|
||||
|
||||
if info.is_some() {
|
||||
return info.unwrap();
|
||||
} else {
|
||||
// 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。
|
||||
let mut ret = siginfo::new(sig, 0, si_code_val::SI_USER);
|
||||
ret._sinfo.data._sifields._kill._pid = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 真正发送signal,执行自定义的处理函数
|
||||
///
|
||||
/// @param sig 信号number
|
||||
/// @param ka 信号响应动作
|
||||
/// @param info 信号信息
|
||||
/// @param oldset
|
||||
/// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
|
||||
///
|
||||
/// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
|
||||
fn handle_signal(
|
||||
sig: SignalNumber,
|
||||
ka: &mut sigaction,
|
||||
info: &siginfo,
|
||||
oldset: &sigset_t,
|
||||
regs: &mut pt_regs,
|
||||
) -> Result<i32, SystemError> {
|
||||
// 设置栈帧
|
||||
let retval = setup_frame(sig, ka, info, oldset, regs);
|
||||
if retval.is_err() {
|
||||
return retval;
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。
|
||||
///
|
||||
/// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
|
||||
fn setup_frame(
|
||||
sig: SignalNumber,
|
||||
ka: &mut sigaction,
|
||||
info: &siginfo,
|
||||
oldset: &sigset_t,
|
||||
regs: &mut pt_regs,
|
||||
) -> Result<i32, SystemError> {
|
||||
let mut err = 0;
|
||||
let frame: *mut sigframe = get_stack(ka, ®s, size_of::<sigframe>());
|
||||
// kdebug!("frame=0x{:016x}", frame as usize);
|
||||
// 要求这个frame的地址位于用户空间,因此进行校验
|
||||
let access_check_ok = unsafe { verify_area(frame as u64, size_of::<sigframe>() as u64) };
|
||||
if !access_check_ok {
|
||||
// 如果地址区域位于内核空间,则直接报错
|
||||
// todo: 生成一个sigsegv
|
||||
kerror!("In setup frame: access check failed");
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(*frame).arg0 = sig as u64;
|
||||
(*frame).arg1 = &((*frame).info) as *const siginfo as usize;
|
||||
(*frame).arg2 = &((*frame).context) as *const sigcontext as usize;
|
||||
(*frame).handler = ka._u._sa_handler as usize as *mut c_void;
|
||||
}
|
||||
|
||||
// 将当前进程的fp_state拷贝到用户栈
|
||||
if current_pcb().fp_state != null_mut() {
|
||||
unsafe {
|
||||
let fp_state: &mut FpState = (current_pcb().fp_state as usize as *mut FpState)
|
||||
.as_mut()
|
||||
.unwrap();
|
||||
(*frame).context.sc_stack.fpstate = *fp_state;
|
||||
// 保存完毕后,清空fp_state,以免下次save的时候,出现SIMD exception
|
||||
fp_state.clear();
|
||||
}
|
||||
}
|
||||
// 将siginfo拷贝到用户栈
|
||||
err |= copy_siginfo_to_user(unsafe { &mut (*frame).info }, info).unwrap_or(1);
|
||||
|
||||
// todo: 拷贝处理程序备用栈的地址、大小、ss_flags
|
||||
|
||||
err |= setup_sigcontext(unsafe { &mut (*frame).context }, oldset, ®s).unwrap_or(1);
|
||||
|
||||
// 为了与Linux的兼容性,64位程序必须由用户自行指定restorer
|
||||
if ka.sa_flags & SA_FLAG_RESTORER != 0 {
|
||||
unsafe {
|
||||
(*frame).ret_code_ptr = ka.sa_restorer as usize as *mut c_void;
|
||||
}
|
||||
} else {
|
||||
kerror!(
|
||||
"pid-{} forgot to set SA_FLAG_RESTORER for signal {}",
|
||||
current_pcb().pid,
|
||||
sig as i32
|
||||
);
|
||||
err = 1;
|
||||
}
|
||||
if err != 0 {
|
||||
// todo: 在这里生成一个sigsegv,然后core dump
|
||||
//临时解决方案:退出当前进程
|
||||
unsafe {
|
||||
process_do_exit(1);
|
||||
}
|
||||
}
|
||||
// 传入信号处理函数的第一个参数
|
||||
regs.rdi = sig as u64;
|
||||
regs.rsi = unsafe { &(*frame).info as *const siginfo as u64 };
|
||||
regs.rsp = frame as u64;
|
||||
regs.rip = unsafe { ka._u._sa_handler };
|
||||
|
||||
// todo: 传入新版的sa_sigaction的处理函数的第三个参数
|
||||
|
||||
// 如果handler位于内核空间
|
||||
if regs.rip >= USER_MAX_LINEAR_ADDR {
|
||||
// 如果当前是SIGSEGV,则采用默认函数处理
|
||||
if sig == SignalNumber::SIGSEGV {
|
||||
ka.sa_flags |= SA_FLAG_DFL;
|
||||
}
|
||||
|
||||
// 将rip设置为0
|
||||
regs.rip = 0;
|
||||
}
|
||||
|
||||
// 设置cs和ds寄存器
|
||||
regs.cs = (USER_CS | 0x3) as u64;
|
||||
regs.ds = (USER_DS | 0x3) as u64;
|
||||
|
||||
return if err == 0 {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(SystemError::EPERM)
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_stack(_ka: &sigaction, regs: &pt_regs, size: usize) -> *mut sigframe {
|
||||
// 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小
|
||||
let mut rsp: usize = (regs.rsp as usize) - 128 - size;
|
||||
// 按照要求进行对齐
|
||||
rsp &= (-(STACK_ALIGN as i64)) as usize;
|
||||
return rsp as *mut sigframe;
|
||||
}
|
||||
|
||||
/// @brief 将siginfo结构体拷贝到用户栈
|
||||
fn copy_siginfo_to_user(to: *mut siginfo, from: &siginfo) -> Result<i32, SystemError> {
|
||||
// 验证目标地址是否为用户空间
|
||||
if unsafe { !verify_area(to as u64, size_of::<siginfo>() as u64) } {
|
||||
// 如果目标地址空间不为用户空间,则直接返回错误码 -EPERM
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
|
||||
let retval: Result<i32, SystemError> = Ok(0);
|
||||
|
||||
// todo: 将这里按照si_code的类型来分别拷贝不同的信息。
|
||||
// 这里参考linux-2.6.39 网址: http://opengrok.ringotek.cn/xref/linux-2.6.39/arch/ia64/kernel/signal.c#137
|
||||
|
||||
unsafe {
|
||||
(*to)._sinfo.data._sifields._kill._pid = from._sinfo.data._sifields._kill._pid;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// @brief 设置目标的sigcontext
|
||||
///
|
||||
/// @param context 要被设置的目标sigcontext
|
||||
/// @param mask 要被暂存的信号mask标志位
|
||||
/// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
|
||||
fn setup_sigcontext(
|
||||
context: &mut sigcontext,
|
||||
mask: &sigset_t,
|
||||
regs: &pt_regs,
|
||||
) -> Result<i32, SystemError> {
|
||||
let current_thread = current_pcb().thread;
|
||||
|
||||
context.oldmask = *mask;
|
||||
context.regs = regs.clone();
|
||||
context.trap_num = unsafe { (*current_thread).trap_num };
|
||||
context.err_code = unsafe { (*current_thread).err_code };
|
||||
context.cr2 = unsafe { (*current_thread).cr2 };
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// @brief 将指定的sigcontext恢复到当前进程的内核栈帧中,并将当前线程结构体的几个参数进行恢复
|
||||
///
|
||||
/// @param context 要被恢复的context
|
||||
/// @param regs 目标栈帧(也就是把context恢复到这个栈帧中)
|
||||
///
|
||||
/// @return bool true -> 成功恢复
|
||||
/// false -> 执行失败
|
||||
fn restore_sigcontext(context: *const sigcontext, regs: &mut pt_regs) -> bool {
|
||||
let mut current_thread = current_pcb().thread;
|
||||
unsafe {
|
||||
*regs = (*context).regs;
|
||||
|
||||
(*current_thread).trap_num = (*context).trap_num;
|
||||
(*current_thread).cr2 = (*context).cr2;
|
||||
(*current_thread).err_code = (*context).err_code;
|
||||
|
||||
// 如果当前进程有fpstate,则将其恢复到pcb的fp_state中
|
||||
*(current_pcb().fp_state as usize as *mut FpState) = (*context).sc_stack.fpstate;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为Default
|
||||
/// 除非某个信号被设置为ignore且force_default为false,否则都不会将其恢复
|
||||
///
|
||||
/// @param pcb 要被刷新的pcb
|
||||
/// @param force_default 是否强制将sigaction恢复成默认状态
|
||||
pub fn flush_signal_handlers(pcb: *mut process_control_block, force_default: bool) {
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
|
||||
let action = unsafe { &mut (*(*pcb).sighand).action };
|
||||
for ka in action.iter_mut() {
|
||||
if force_default || (ka.sa_flags != SA_FLAG_IGN) {
|
||||
ka.sa_flags = SA_FLAG_DFL;
|
||||
ka._u._sa_handler = None;
|
||||
}
|
||||
// 清除flags中,除了DFL和IGN以外的所有标志
|
||||
ka.sa_flags &= SA_FLAG_DFL | SA_FLAG_IGN;
|
||||
ka.sa_restorer = None;
|
||||
sigset_clear(&mut ka.sa_mask);
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn do_sigaction(
|
||||
sig: SignalNumber,
|
||||
act: Option<&mut sigaction>,
|
||||
old_act: Option<&mut sigaction>,
|
||||
) -> Result<(), SystemError> {
|
||||
let pcb = current_pcb();
|
||||
|
||||
// 指向当前信号的action的引用
|
||||
let action =
|
||||
sigaction::convert_mut(unsafe { &mut (*(pcb.sighand)).action[(sig as usize) - 1] })
|
||||
.unwrap();
|
||||
|
||||
spin_lock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
|
||||
|
||||
if (action.sa_flags & SA_FLAG_IMMUTABLE) != 0 {
|
||||
spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
// 如果需要保存原有的sigaction
|
||||
// 写的这么恶心,还得感谢rust的所有权系统...old_act的所有权被传入了这个闭包之后,必须要把所有权返回给外面。(也许是我不会用才导致写的这么丑,但是它确实能跑)
|
||||
let old_act: Option<&mut sigaction> = {
|
||||
if old_act.is_some() {
|
||||
let oa = old_act.unwrap();
|
||||
*(oa) = *action;
|
||||
Some(oa)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// 清除所有的脏的sa_flags位(也就是清除那些未使用的)
|
||||
let act = {
|
||||
if act.is_some() {
|
||||
let ac = act.unwrap();
|
||||
ac.sa_flags &= SA_ALL_FLAGS;
|
||||
Some(ac)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if old_act.is_some() {
|
||||
old_act.unwrap().sa_flags &= SA_ALL_FLAGS;
|
||||
}
|
||||
|
||||
if act.is_some() {
|
||||
let ac = act.unwrap();
|
||||
// 将act.sa_mask的SIGKILL SIGSTOP的屏蔽清除
|
||||
sigset_delmask(
|
||||
&mut ac.sa_mask,
|
||||
sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
|
||||
);
|
||||
|
||||
// 将新的sigaction拷贝到进程的action中
|
||||
*action = *ac;
|
||||
|
||||
/*
|
||||
* 根据POSIX 3.3.1.3规定:
|
||||
* 1.不管一个信号是否被阻塞,只要将其设置SIG_IGN,如果当前已经存在了正在pending的信号,那么就把这个信号忽略。
|
||||
*
|
||||
* 2.不管一个信号是否被阻塞,只要将其设置SIG_DFL,如果当前已经存在了正在pending的信号,
|
||||
并且对这个信号的默认处理方式是忽略它,那么就会把pending的信号忽略。
|
||||
*/
|
||||
if action.ignored(sig) {
|
||||
let mut mask: sigset_t = 0;
|
||||
sigset_clear(&mut mask);
|
||||
sigset_add(&mut mask, sig);
|
||||
let sq: &mut SigQueue = SigQueue::from_c_void(pcb.sig_pending.sigqueue);
|
||||
sq.flush_by_mask(&mask);
|
||||
|
||||
// todo: 当有了多个线程后,在这里进行操作,把每个线程的sigqueue都进行刷新
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// @brief 对于给定的signal number,将u64中对应的位进行置位
|
||||
pub fn sigmask(sig: SignalNumber) -> u64 {
|
||||
// 减1的原因是,sigset的第0位表示信号1
|
||||
return 1u64 << ((sig as i32) - 1);
|
||||
}
|
||||
|
||||
pub fn sys_rt_sigreturn(regs: &mut pt_regs) -> u64 {
|
||||
let frame = regs.rsp as usize as *mut sigframe;
|
||||
|
||||
// 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
|
||||
if unsafe { !verify_area(frame as u64, size_of::<sigframe>() as u64) } {
|
||||
// todo:这里改为生成一个sigsegv
|
||||
// 退出进程
|
||||
unsafe {
|
||||
process_do_exit(SignalNumber::SIGSEGV as u64);
|
||||
}
|
||||
}
|
||||
|
||||
let mut sigmask: sigset_t = unsafe { (*frame).context.oldmask };
|
||||
set_current_sig_blocked(&mut sigmask);
|
||||
|
||||
// 从用户栈恢复sigcontext
|
||||
if restore_sigcontext(unsafe { &mut (*frame).context }, regs) == false {
|
||||
// todo:这里改为生成一个sigsegv
|
||||
// 退出进程
|
||||
unsafe {
|
||||
process_do_exit(SignalNumber::SIGSEGV as u64);
|
||||
}
|
||||
}
|
||||
|
||||
// 由于系统调用的返回值会被系统调用模块被存放在rax寄存器,因此,为了还原原来的那个系统调用的返回值,我们需要在这里返回恢复后的rax的值
|
||||
return regs.rax;
|
||||
}
|
||||
|
||||
fn set_current_sig_blocked(new_set: &mut sigset_t) {
|
||||
sigset_delmask(
|
||||
new_set,
|
||||
sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
|
||||
);
|
||||
|
||||
let mut pcb = current_pcb();
|
||||
|
||||
/*
|
||||
如果当前pcb的sig_blocked和新的相等,那么就不用改变它。
|
||||
请注意,一个进程的sig_blocked字段不能被其他进程修改!
|
||||
*/
|
||||
if sigset_equal(&pcb.sig_blocked, new_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lock: &mut spinlock_t = &mut sighand_struct::convert_mut(pcb.sighand).unwrap().siglock;
|
||||
spin_lock_irq(lock);
|
||||
// todo: 当一个进程有多个线程后,在这里需要设置每个线程的block字段,并且 retarget_shared_pending(虽然我还没搞明白linux这部分是干啥的)
|
||||
|
||||
// 设置当前进程的sig blocked
|
||||
pcb.sig_blocked = *new_set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(lock);
|
||||
}
|
@ -1,669 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
// 这是signal暴露给其他模块的公有的接口文件
|
||||
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::arch::fpu::FpState;
|
||||
use crate::include::bindings::bindings::NULL;
|
||||
// todo: 将这里更换为手动编写的ffi绑定
|
||||
use crate::include::bindings::bindings::atomic_t;
|
||||
use crate::include::bindings::bindings::pt_regs;
|
||||
use crate::include::bindings::bindings::spinlock_t;
|
||||
use crate::kerror;
|
||||
use crate::libs::ffi_convert::FFIBind2Rust;
|
||||
use crate::libs::ffi_convert::__convert_mut;
|
||||
use crate::libs::ffi_convert::__convert_ref;
|
||||
use crate::libs::refcount::RefCount;
|
||||
|
||||
/// 请注意,sigset_t这个bitmap, 第0位表示sig=1的信号。也就是说,SignalNumber-1才是sigset_t中对应的位
|
||||
pub type sigset_t = u64;
|
||||
/// 存储信号处理函数的地址(来自用户态)
|
||||
pub type __signalfn_t = u64;
|
||||
pub type __sighandler_t = __signalfn_t;
|
||||
/// 存储信号处理恢复函数的地址(来自用户态)
|
||||
pub type __sigrestorer_fn_t = u64;
|
||||
pub type __sigrestorer_t = __sigrestorer_fn_t;
|
||||
|
||||
/// 最大的信号数量(改动这个值的时候请同步到signal.h)
|
||||
pub const MAX_SIG_NUM: i32 = 64;
|
||||
/// sigset所占用的u64的数量(改动这个值的时候请同步到signal.h)
|
||||
pub const _NSIG_U64_CNT: i32 = MAX_SIG_NUM / 64;
|
||||
/// 信号处理的栈的栈指针的最小对齐数量
|
||||
pub const STACK_ALIGN: u64 = 16;
|
||||
|
||||
/// 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁
|
||||
/// 因此signal_struct不用加锁
|
||||
/// **请将该结构体与`include/DragonOS/signal.h`中的保持同步**
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct signal_struct {
|
||||
pub sig_cnt: atomic_t,
|
||||
}
|
||||
|
||||
impl Default for signal_struct {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sig_cnt: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sigaction中的信号处理函数结构体
|
||||
* 分为两种处理函数
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union sigaction__union_u {
|
||||
pub _sa_handler: __sighandler_t, // 传统处理函数
|
||||
pub _sa_sigaction: ::core::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
sig: ::core::ffi::c_int,
|
||||
sinfo: *mut siginfo,
|
||||
arg1: *mut ::core::ffi::c_void,
|
||||
),
|
||||
>,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for sigaction__union_u {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.write_str("sigaction__union_u")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for sigaction__union_u {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
_sa_handler: NULL as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============ sigaction结构体中的的sa_flags的可选值 begin ===========
|
||||
pub const SA_FLAG_DFL: u64 = 1u64 << 0; // 当前sigaction表示系统默认的动作
|
||||
pub const SA_FLAG_IGN: u64 = 1u64 << 1; // 当前sigaction表示忽略信号的动作
|
||||
pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指定的restorer
|
||||
pub const SA_FLAG_IMMUTABLE: u64 = 1u64 << 3; // 当前sigaction不可被更改
|
||||
|
||||
/// 所有的sa_flags的mask。(用于去除那些不存在的sa_flags位)
|
||||
pub const SA_ALL_FLAGS: u64 = SA_FLAG_IGN | SA_FLAG_DFL | SA_FLAG_RESTORER | SA_FLAG_IMMUTABLE;
|
||||
|
||||
// ============ sigaction结构体中的的sa_flags的可选值 end ===========
|
||||
|
||||
/// 用户态程序传入的SIG_DFL的值
|
||||
pub const USER_SIG_DFL: u64 = 0;
|
||||
/// 用户态程序传入的SIG_IGN的值
|
||||
pub const USER_SIG_IGN: u64 = 1;
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct sigaction {
|
||||
pub _u: sigaction__union_u,
|
||||
pub sa_flags: u64,
|
||||
pub sa_mask: sigset_t, // 为了可扩展性而设置的sa_mask
|
||||
/// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
|
||||
pub sa_restorer: __sigrestorer_t,
|
||||
}
|
||||
|
||||
impl Default for sigaction {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
_u: Default::default(),
|
||||
sa_flags: Default::default(),
|
||||
sa_mask: Default::default(),
|
||||
sa_restorer: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sigaction {
|
||||
/// @brief 判断这个sigaction是否被忽略
|
||||
pub fn ignored(&self, _sig: SignalNumber) -> bool {
|
||||
if (self.sa_flags & SA_FLAG_IGN) != 0 {
|
||||
return true;
|
||||
}
|
||||
// todo: 增加对sa_flags为SA_FLAG_DFL,但是默认处理函数为忽略的情况的判断
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 用户态传入的sigaction结构体(符合posix规范)
|
||||
/// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct user_sigaction {
|
||||
pub sa_handler: *mut core::ffi::c_void,
|
||||
pub sa_sigaction: *mut core::ffi::c_void,
|
||||
pub sa_mask: sigset_t,
|
||||
pub sa_flags: u64,
|
||||
pub sa_restorer: *mut core::ffi::c_void,
|
||||
}
|
||||
|
||||
/**
|
||||
* 信号消息的结构体,作为参数传入sigaction结构体中指向的处理函数
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct siginfo {
|
||||
pub _sinfo: __siginfo_union,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union __siginfo_union {
|
||||
pub data: __siginfo_union_data,
|
||||
pub padding: [u64; 4usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct __siginfo_union_data {
|
||||
pub si_signo: i32,
|
||||
pub si_code: i32,
|
||||
pub si_errno: i32,
|
||||
pub reserved: u32,
|
||||
pub _sifields: __sifields,
|
||||
}
|
||||
|
||||
/**
|
||||
* siginfo中,根据signal的来源不同,该union中对应了不同的数据./=
|
||||
* 请注意,该union最大占用16字节
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union __sifields {
|
||||
pub _kill: __sifields__kill,
|
||||
}
|
||||
|
||||
/**
|
||||
* 来自kill命令的signal
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct __sifields__kill {
|
||||
pub _pid: i64, /* 发起kill的进程的pid */
|
||||
}
|
||||
|
||||
impl siginfo {
|
||||
pub fn new(sig: SignalNumber, _si_errno: i32, _si_code: si_code_val) -> Self {
|
||||
siginfo {
|
||||
_sinfo: __siginfo_union {
|
||||
data: __siginfo_union_data {
|
||||
si_signo: sig as i32,
|
||||
si_code: _si_code as i32,
|
||||
si_errno: _si_errno,
|
||||
reserved: 0,
|
||||
_sifields: super::signal_types::__sifields {
|
||||
_kill: super::signal_types::__sifields__kill { _pid: 0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for siginfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
unsafe {
|
||||
f.write_fmt(format_args!(
|
||||
"si_signo:{}, si_code:{}, si_errno:{}, _pid:{}",
|
||||
self._sinfo.data.si_signo,
|
||||
self._sinfo.data.si_code,
|
||||
self._sinfo.data.si_errno,
|
||||
self._sinfo.data._sifields._kill._pid
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体,位于pcb之中
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct sighand_struct {
|
||||
pub siglock: spinlock_t,
|
||||
pub count: RefCount,
|
||||
pub action: [sigaction; MAX_SIG_NUM as usize],
|
||||
}
|
||||
|
||||
impl Default for sighand_struct {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
siglock: Default::default(),
|
||||
count: Default::default(),
|
||||
action: [Default::default(); MAX_SIG_NUM as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 正在等待的信号的标志位
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct sigpending {
|
||||
pub signal: sigset_t,
|
||||
/// 信号队列
|
||||
pub queue: *mut SigQueue,
|
||||
}
|
||||
|
||||
/// siginfo中的si_code的可选值
|
||||
/// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态
|
||||
#[allow(dead_code)]
|
||||
#[repr(i32)]
|
||||
pub enum si_code_val {
|
||||
/// sent by kill, sigsend, raise
|
||||
SI_USER = 0,
|
||||
/// sent by kernel from somewhere
|
||||
SI_KERNEL = 0x80,
|
||||
/// 通过sigqueue发送
|
||||
SI_QUEUE = -1,
|
||||
/// 定时器过期时发送
|
||||
SI_TIMER = -2,
|
||||
/// 当实时消息队列的状态发生改变时发送
|
||||
SI_MESGQ = -3,
|
||||
/// 当异步IO完成时发送
|
||||
SI_ASYNCIO = -4,
|
||||
/// sent by queued SIGIO
|
||||
SI_SIGIO = -5,
|
||||
}
|
||||
|
||||
impl si_code_val {
|
||||
/// 为si_code_val这个枚举类型实现从i32转换到枚举类型的转换函数
|
||||
#[allow(dead_code)]
|
||||
pub fn from_i32(x: i32) -> si_code_val {
|
||||
match x {
|
||||
0 => Self::SI_USER,
|
||||
0x80 => Self::SI_KERNEL,
|
||||
-1 => Self::SI_QUEUE,
|
||||
-2 => Self::SI_TIMER,
|
||||
-3 => Self::SI_MESGQ,
|
||||
-4 => Self::SI_ASYNCIO,
|
||||
-5 => Self::SI_SIGIO,
|
||||
_ => panic!("si code not valid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum SignalNumber {
|
||||
INVALID = 0,
|
||||
SIGHUP = 1,
|
||||
SIGINT,
|
||||
SIGQUIT,
|
||||
SIGILL,
|
||||
SIGTRAP,
|
||||
/// SIGABRT和SIGIOT共用这个号码
|
||||
SIGABRT_OR_IOT,
|
||||
SIGBUS,
|
||||
SIGFPE,
|
||||
SIGKILL,
|
||||
SIGUSR1,
|
||||
|
||||
SIGSEGV = 11,
|
||||
SIGUSR2,
|
||||
SIGPIPE,
|
||||
SIGALRM,
|
||||
SIGTERM,
|
||||
SIGSTKFLT,
|
||||
SIGCHLD,
|
||||
SIGCONT,
|
||||
SIGSTOP,
|
||||
SIGTSTP,
|
||||
|
||||
SIGTTIN = 21,
|
||||
SIGTTOU,
|
||||
SIGURG,
|
||||
SIGXCPU,
|
||||
SIGXFSZ,
|
||||
SIGVTALRM,
|
||||
SIGPROF,
|
||||
SIGWINCH,
|
||||
/// SIGIO和SIGPOLL共用这个号码
|
||||
SIGIO_OR_POLL,
|
||||
SIGPWR,
|
||||
|
||||
SIGSYS = 31,
|
||||
}
|
||||
|
||||
/// 为SignalNumber实现判断相等的trait
|
||||
impl PartialEq for SignalNumber {
|
||||
fn eq(&self, other: &SignalNumber) -> bool {
|
||||
*self as i32 == *other as i32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for SignalNumber {
|
||||
fn from(value: i32) -> Self {
|
||||
if Self::valid_signal_number(value) {
|
||||
let ret: SignalNumber = unsafe { core::mem::transmute(value) };
|
||||
return ret;
|
||||
} else {
|
||||
kerror!("Try to convert an invalid number to SignalNumber");
|
||||
return SignalNumber::INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
impl SignalNumber {
|
||||
/// 判断一个数字是否为可用的信号
|
||||
fn valid_signal_number(x: i32) -> bool {
|
||||
if x > 0 && x < MAX_SIG_NUM {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const SIGRTMIN: i32 = 32;
|
||||
#[allow(dead_code)]
|
||||
pub const SIGRTMAX: i32 = MAX_SIG_NUM;
|
||||
|
||||
/// @brief 将给定的signal_struct解析为Rust的signal.rs中定义的signal_struct的引用
|
||||
///
|
||||
/// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::signal_struct> for signal_struct {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::signal_struct,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::signal_struct,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的siginfo解析为Rust的signal.rs中定义的siginfo的引用
|
||||
///
|
||||
/// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::siginfo> for siginfo {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::siginfo,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::siginfo,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的sigset_t解析为Rust的signal.rs中定义的sigset_t的引用
|
||||
///
|
||||
/// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::sigset_t> for sigset_t {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::sigset_t,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::sigset_t,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的sigpending解析为Rust的signal.rs中定义的sigpending的引用
|
||||
///
|
||||
/// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::sigpending> for sigpending {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::sigpending,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::sigpending,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的来自bindgen的sighand_struct解析为Rust的signal.rs中定义的sighand_struct的引用
|
||||
///
|
||||
/// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的,会导致无法自定义功能的问题。
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighand_struct {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::sighand_struct,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::sighand_struct,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的来自bindgen的sigaction解析为Rust的signal.rs中定义的sigaction的引用
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::sigaction,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::sigaction,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 进程接收到的信号的队列
|
||||
pub struct SigQueue {
|
||||
pub q: Vec<siginfo>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl SigQueue {
|
||||
/// @brief 初始化一个新的信号队列
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
SigQueue {
|
||||
q: Vec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
|
||||
///
|
||||
/// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
|
||||
pub fn find(&self, sig: SignalNumber) -> (Option<&siginfo>, bool) {
|
||||
// 是否存在多个满足条件的siginfo
|
||||
let mut still_pending = false;
|
||||
let mut info: Option<&siginfo> = None;
|
||||
|
||||
for x in self.q.iter() {
|
||||
if unsafe { x._sinfo.data.si_signo } == sig as i32 {
|
||||
if info.is_some() {
|
||||
still_pending = true;
|
||||
break;
|
||||
} else {
|
||||
info = Some(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (info, still_pending);
|
||||
}
|
||||
|
||||
/// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
|
||||
///
|
||||
/// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
|
||||
pub fn find_and_delete(&mut self, sig: SignalNumber) -> (Option<siginfo>, bool) {
|
||||
// 是否存在多个满足条件的siginfo
|
||||
let mut still_pending = false;
|
||||
let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
|
||||
|
||||
let filter = |x: &mut siginfo| {
|
||||
if unsafe { x._sinfo.data.si_signo } == sig as i32 {
|
||||
if !first {
|
||||
// 如果之前已经筛选出了一个元素,则不把当前元素删除
|
||||
still_pending = true;
|
||||
return false;
|
||||
} else {
|
||||
// 当前是第一个被筛选出来的元素
|
||||
first = false;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// 从sigqueue中过滤出结果
|
||||
let mut filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
|
||||
// 筛选出的结果不能大于1个
|
||||
assert!(filter_result.len() <= 1);
|
||||
|
||||
return (filter_result.pop(), still_pending);
|
||||
}
|
||||
|
||||
/// @brief 从sigqueue中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
|
||||
pub fn flush_by_mask(&mut self, mask: &sigset_t) {
|
||||
// 定义过滤器,从sigqueue中删除mask中被置位的信号
|
||||
let filter = |x: &mut siginfo| {
|
||||
if sig_is_member(mask, SignalNumber::from(unsafe { x._sinfo.data.si_signo })) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
let filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
|
||||
// 回收这些siginfo
|
||||
for x in filter_result {
|
||||
drop(x)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 从C的void*指针转换为static生命周期的可变引用
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SigQueue {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
q: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 清除sigset中,某个信号对应的标志位
|
||||
#[inline]
|
||||
pub fn sigset_del(set: &mut sigset_t, sig: SignalNumber) {
|
||||
let sig = sig as i32 - 1;
|
||||
if _NSIG_U64_CNT == 1 {
|
||||
*set &= !(1 << sig);
|
||||
} else {
|
||||
// 暂时不支持超过64个信号
|
||||
panic!("Unsupported signal number: {:?}", sig);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将指定的信号在sigset中的对应bit进行置位
|
||||
#[inline]
|
||||
pub fn sigset_add(set: &mut sigset_t, sig: SignalNumber) {
|
||||
*set |= 1 << ((sig as u32) - 1);
|
||||
}
|
||||
|
||||
/// @brief 将sigset清零
|
||||
#[inline]
|
||||
pub fn sigset_clear(set: &mut sigset_t) {
|
||||
*set = 0;
|
||||
}
|
||||
|
||||
/// @brief 将mask中置为1的位,在sigset中清零
|
||||
#[inline]
|
||||
pub fn sigset_delmask(set: &mut sigset_t, mask: u64) {
|
||||
*set &= !mask;
|
||||
}
|
||||
|
||||
/// @brief 判断两个sigset是否相等
|
||||
#[inline]
|
||||
pub fn sigset_equal(a: &sigset_t, b: &sigset_t) -> bool {
|
||||
if _NSIG_U64_CNT == 1 {
|
||||
return *a == *b;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief 使用指定的值,初始化sigset(为支持将来超过64个signal留下接口)
|
||||
#[inline]
|
||||
pub fn sigset_init(new_set: &mut sigset_t, mask: u64) {
|
||||
*new_set = mask;
|
||||
match _NSIG_U64_CNT {
|
||||
1 => {}
|
||||
_ => {
|
||||
// 暂时不支持大于64个信号
|
||||
todo!();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief 判断指定的信号在sigset中的对应位是否被置位
|
||||
/// @return true: 给定的信号在sigset中被置位
|
||||
/// @return false: 给定的信号在sigset中没有被置位
|
||||
#[inline]
|
||||
pub fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
|
||||
return if 1 & (set >> ((_sig as u32) - 1)) != 0 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct sigframe {
|
||||
/// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
|
||||
pub ret_code_ptr: *mut core::ffi::c_void,
|
||||
/// signum
|
||||
pub arg0: u64,
|
||||
/// siginfo pointer
|
||||
pub arg1: usize,
|
||||
/// sigcontext pointer
|
||||
pub arg2: usize,
|
||||
|
||||
pub handler: *mut c_void,
|
||||
pub info: siginfo,
|
||||
pub context: sigcontext,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct sigcontext {
|
||||
/// sigcontext的标志位
|
||||
pub sc_flags: u64,
|
||||
pub sc_stack: signal_stack, // 信号处理程序备用栈信息
|
||||
|
||||
pub regs: pt_regs, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
|
||||
pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
|
||||
pub oldmask: u64, // 暂存的执行信号处理函数之前的,被设置block的信号
|
||||
pub cr2: u64, // 用来保存线程结构体中的cr2字段
|
||||
pub err_code: u64, // 用来保存线程结构体中的err_code字段
|
||||
// todo: 支持x87浮点处理器后,在这里增加浮点处理器的状态结构体指针
|
||||
pub reserved_for_x87_state: u64,
|
||||
pub reserved: [u64; 8],
|
||||
}
|
||||
|
||||
/// @brief 信号处理备用栈的信息
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct signal_stack {
|
||||
pub sp: *mut c_void,
|
||||
pub flags: u32,
|
||||
pub size: u32,
|
||||
pub fpstate: FpState,
|
||||
}
|
@ -1,25 +1,12 @@
|
||||
use core::{
|
||||
ffi::{c_int, c_void},
|
||||
sync::atomic::compiler_fence,
|
||||
};
|
||||
use core::ffi::c_int;
|
||||
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
filesystem::vfs::file::{File, FileMode},
|
||||
include::bindings::bindings::{pid_t, verify_area, NULL},
|
||||
kwarn,
|
||||
process::{Pid, ProcessManager},
|
||||
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
|
||||
};
|
||||
|
||||
use super::{
|
||||
pipe::LockedPipeInode,
|
||||
signal::{signal_kill_something_info, DEFAULT_SIGACTION, DEFAULT_SIGACTION_IGNORE},
|
||||
signal_types::{
|
||||
SignalNumber, __siginfo_union, __siginfo_union_data, si_code_val, sigaction,
|
||||
sigaction__union_u, siginfo, sigset_init, sigset_t, user_sigaction, SA_FLAG_DFL,
|
||||
SA_FLAG_IGN, SA_FLAG_RESTORER, USER_SIG_DFL, USER_SIG_IGN,
|
||||
},
|
||||
};
|
||||
use super::pipe::LockedPipeInode;
|
||||
|
||||
impl Syscall {
|
||||
/// # 创建带参数的匿名管道
|
||||
@ -43,8 +30,12 @@ impl Syscall {
|
||||
read_file.set_close_on_exec(true);
|
||||
write_file.set_close_on_exec(true);
|
||||
}
|
||||
let read_fd = current_pcb().alloc_fd(read_file, None)?;
|
||||
let write_fd = current_pcb().alloc_fd(write_file, None)?;
|
||||
let fd_table_ptr = ProcessManager::current_pcb().fd_table();
|
||||
let mut fd_table_guard = fd_table_ptr.write();
|
||||
let read_fd = fd_table_guard.alloc_fd(read_file, None)?;
|
||||
let write_fd = fd_table_guard.alloc_fd(write_file, None)?;
|
||||
|
||||
drop(fd_table_guard);
|
||||
|
||||
fd[0] = read_fd;
|
||||
fd[1] = write_fd;
|
||||
@ -53,35 +44,10 @@ impl Syscall {
|
||||
Err(SystemError::EINVAL)
|
||||
}
|
||||
}
|
||||
pub fn kill(pid: pid_t, sig: c_int) -> Result<usize, SystemError> {
|
||||
let sig = SignalNumber::from(sig);
|
||||
if sig == SignalNumber::INVALID {
|
||||
// 传入的signal数值不合法
|
||||
kwarn!("Not a valid signal number");
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
// 初始化signal info
|
||||
let mut info = siginfo {
|
||||
_sinfo: __siginfo_union {
|
||||
data: __siginfo_union_data {
|
||||
si_signo: sig as i32,
|
||||
si_code: si_code_val::SI_USER as i32,
|
||||
si_errno: 0,
|
||||
reserved: 0,
|
||||
_sifields: super::signal_types::__sifields {
|
||||
_kill: super::signal_types::__sifields__kill { _pid: pid },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
|
||||
let retval = signal_kill_something_info(sig, Some(&mut info), pid).map(|x| x as usize);
|
||||
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
|
||||
return retval;
|
||||
pub fn kill(_pid: Pid, _sig: c_int) -> Result<usize, SystemError> {
|
||||
// todo: 由于进程管理重构,目前删除了signal功能,将来重新实现它。
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
/// @brief 用户程序用于设置信号处理动作的函数(遵循posix2008)
|
||||
@ -93,123 +59,12 @@ impl Syscall {
|
||||
/// @return int 错误码
|
||||
#[no_mangle]
|
||||
pub fn sigaction(
|
||||
sig: c_int,
|
||||
act: usize,
|
||||
old_act: usize,
|
||||
_sig: c_int,
|
||||
_act: usize,
|
||||
_old_act: usize,
|
||||
_from_user: bool,
|
||||
) -> Result<usize, SystemError> {
|
||||
// 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样
|
||||
let act = act as *mut user_sigaction;
|
||||
let mut old_act = old_act as *mut user_sigaction;
|
||||
let mut new_ka: sigaction = Default::default();
|
||||
let mut old_ka: sigaction = Default::default();
|
||||
|
||||
// 如果传入的,新的sigaction不为空
|
||||
if !act.is_null() {
|
||||
// 如果参数的范围不在用户空间,则返回错误
|
||||
if unsafe {
|
||||
!verify_area(
|
||||
act as usize as u64,
|
||||
core::mem::size_of::<sigaction>() as u64,
|
||||
)
|
||||
} {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
let mask: sigset_t = unsafe { (*act).sa_mask };
|
||||
let _input_sah = unsafe { (*act).sa_handler as u64 };
|
||||
// kdebug!("_input_sah={}", _input_sah);
|
||||
match _input_sah {
|
||||
USER_SIG_DFL | USER_SIG_IGN => {
|
||||
if _input_sah == USER_SIG_DFL {
|
||||
new_ka = DEFAULT_SIGACTION;
|
||||
new_ka.sa_flags = (unsafe { (*act).sa_flags }
|
||||
& (!(SA_FLAG_DFL | SA_FLAG_IGN)))
|
||||
| SA_FLAG_DFL;
|
||||
} else {
|
||||
new_ka = DEFAULT_SIGACTION_IGNORE;
|
||||
new_ka.sa_flags = (unsafe { (*act).sa_flags }
|
||||
& (!(SA_FLAG_DFL | SA_FLAG_IGN)))
|
||||
| SA_FLAG_IGN;
|
||||
}
|
||||
|
||||
let sar = unsafe { (*act).sa_restorer };
|
||||
new_ka.sa_restorer = sar as u64;
|
||||
}
|
||||
_ => {
|
||||
// 从用户空间获得sigaction结构体
|
||||
new_ka = sigaction {
|
||||
_u: sigaction__union_u {
|
||||
_sa_handler: unsafe { (*act).sa_handler as u64 },
|
||||
},
|
||||
sa_flags: unsafe { (*act).sa_flags },
|
||||
sa_mask: sigset_t::default(),
|
||||
sa_restorer: unsafe { (*act).sa_restorer as u64 },
|
||||
};
|
||||
}
|
||||
}
|
||||
// kdebug!("new_ka={:?}", new_ka);
|
||||
// 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer)
|
||||
if new_ka.sa_restorer != NULL as u64 {
|
||||
new_ka.sa_flags |= SA_FLAG_RESTORER;
|
||||
} else {
|
||||
kwarn!(
|
||||
"pid:{}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.",
|
||||
current_pcb().pid,
|
||||
sig
|
||||
);
|
||||
}
|
||||
sigset_init(&mut new_ka.sa_mask, mask);
|
||||
}
|
||||
|
||||
let sig = SignalNumber::from(sig as i32);
|
||||
// 如果给出的信号值不合法
|
||||
if sig == SignalNumber::INVALID {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let retval = super::signal::do_sigaction(
|
||||
sig,
|
||||
if act.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(&mut new_ka)
|
||||
},
|
||||
if old_act.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(&mut old_ka)
|
||||
},
|
||||
);
|
||||
|
||||
// 将原本的sigaction拷贝到用户程序指定的地址
|
||||
if (retval == Ok(())) && (!old_act.is_null()) {
|
||||
if unsafe {
|
||||
!verify_area(
|
||||
old_act as usize as u64,
|
||||
core::mem::size_of::<sigaction>() as u64,
|
||||
)
|
||||
} {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
// !!!!!!!!!!todo: 检查这里old_ka的mask,是否位SIG_IGN SIG_DFL,如果是,则将_sa_handler字段替换为对应的值
|
||||
let sah: u64;
|
||||
let flag = old_ka.sa_flags & (SA_FLAG_DFL | SA_FLAG_IGN);
|
||||
match flag {
|
||||
SA_FLAG_DFL => {
|
||||
sah = USER_SIG_DFL;
|
||||
}
|
||||
SA_FLAG_IGN => {
|
||||
sah = USER_SIG_IGN;
|
||||
}
|
||||
_ => sah = unsafe { old_ka._u._sa_handler },
|
||||
}
|
||||
unsafe {
|
||||
(*old_act).sa_handler = sah as *mut c_void;
|
||||
(*old_act).sa_flags = old_ka.sa_flags;
|
||||
(*old_act).sa_mask = old_ka.sa_mask;
|
||||
(*old_act).sa_restorer = old_ka.sa_restorer as *mut c_void;
|
||||
}
|
||||
}
|
||||
return retval.map(|_| 0);
|
||||
// todo: 由于进程管理重构,目前删除了signal功能,将来重新实现它。
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,6 @@
|
||||
*/
|
||||
pid_t ktest_start(int (*func)(void* arg), void* arg)
|
||||
{
|
||||
return kernel_thread(func, arg, 0);
|
||||
kerror("Fix me: ktest_start, to use new process management.");
|
||||
while(1);
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
#include "ktest_utils.h"
|
||||
#include <common/mutex.h>
|
||||
#include <common/time.h>
|
||||
#include <common/sys/wait.h>
|
||||
#include <process/process.h>
|
||||
|
||||
static mutex_t mtx;
|
||||
|
||||
/**
|
||||
* @brief 测试是否能够加锁
|
||||
*
|
||||
* @param arg0
|
||||
* @param arg1
|
||||
* @return long
|
||||
*/
|
||||
static long ktest_mutex_case0(uint64_t arg0, uint64_t arg1)
|
||||
{
|
||||
assert(mutex_is_locked(&mtx) == 0);
|
||||
mutex_lock(&mtx);
|
||||
assert(mutex_is_locked(&mtx) == 1);
|
||||
mutex_unlock(&mtx);
|
||||
assert(mutex_is_locked(&mtx) == 0);
|
||||
assert(mutex_trylock(&mtx) == 1);
|
||||
mutex_unlock(&mtx);
|
||||
assert(mutex_is_locked(&mtx) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试用例1的辅助线程
|
||||
*
|
||||
* @param arg
|
||||
* @return long
|
||||
*/
|
||||
static int ktest_mutex_case1_pid1(void* arg)
|
||||
{
|
||||
kTEST("ktest_mutex_case1_subproc start.");
|
||||
assert(mutex_is_locked(&mtx) == 1);
|
||||
mutex_lock(&mtx);
|
||||
assert(atomic_read(&mtx.count) == 0);
|
||||
assert(list_empty(&mtx.wait_list));
|
||||
|
||||
mutex_unlock(&mtx);
|
||||
kTEST("ktest_mutex_case1_subproc exit.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long ktest_mutex_case1(uint64_t arg0, uint64_t arg1)
|
||||
{
|
||||
if (!assert(mutex_is_locked(&mtx) == 0))
|
||||
goto failed;
|
||||
|
||||
// 加锁
|
||||
mutex_lock(&mtx);
|
||||
// 启动另一个线程
|
||||
pid_t pid = kernel_thread(ktest_mutex_case1_pid1, 0, 0);
|
||||
// 等待100ms
|
||||
rs_usleep(100000);
|
||||
while (list_empty(&mtx.wait_list))
|
||||
;
|
||||
|
||||
// 当子线程加锁后,计数应当为0
|
||||
assert(atomic_read(&mtx.count) == 0);
|
||||
struct mutex_waiter_t *wt = container_of(list_next(&mtx.wait_list), struct mutex_waiter_t, list);
|
||||
assert(wt->pcb->pid == pid);
|
||||
|
||||
mutex_unlock(&mtx);
|
||||
|
||||
int stat = 1;
|
||||
waitpid(pid, &stat, 0);
|
||||
assert(stat == 0);
|
||||
return 0;
|
||||
failed:;
|
||||
kTEST("mutex test case1 failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ktest_case_table kt_mutex_func_table[] = {
|
||||
ktest_mutex_case0,
|
||||
ktest_mutex_case1,
|
||||
};
|
||||
int ktest_test_mutex(void* arg)
|
||||
{
|
||||
kTEST("Testing mutex...");
|
||||
mutex_init(&mtx);
|
||||
|
||||
for (int i = 0; i < sizeof(kt_mutex_func_table) / sizeof(ktest_case_table); ++i)
|
||||
{
|
||||
kTEST("Testing case %d", i);
|
||||
kt_mutex_func_table[i](i, 0);
|
||||
}
|
||||
kTEST("mutex Test done.");
|
||||
return 0;
|
||||
}
|
@ -3,11 +3,13 @@
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(asm_const)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(c_void_variant)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(is_some_and)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(trait_upcasting)]
|
||||
@ -45,6 +47,7 @@ extern crate bitflags;
|
||||
extern crate elf;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate memoffset;
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
@ -53,14 +56,9 @@ extern crate thingbuf;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern crate x86;
|
||||
|
||||
use crate::libs::lib_ui::textui::FontColor;
|
||||
use crate::mm::allocator::kernel_allocator::KernelAllocator;
|
||||
|
||||
// <3>
|
||||
use crate::{
|
||||
arch::asm::current::current_pcb, include::bindings::bindings::process_do_exit,
|
||||
net::net_core::net_init,
|
||||
};
|
||||
use crate::process::ProcessManager;
|
||||
|
||||
// 声明全局的分配器
|
||||
#[cfg_attr(not(test), global_allocator)]
|
||||
@ -95,20 +93,6 @@ pub fn panic(info: &PanicInfo) -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
println!("Current PCB:\n\t{:?}", current_pcb());
|
||||
unsafe {
|
||||
process_do_exit(u64::MAX);
|
||||
};
|
||||
loop {}
|
||||
}
|
||||
|
||||
/// 该函数用作测试,在process.c的initial_kernel_thread()中调用了此函数
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_demo_func() -> i32 {
|
||||
printk_color!(FontColor::GREEN, FontColor::BLACK, "__rust_demo_func()\n");
|
||||
let r = net_init();
|
||||
if r.is_err() {
|
||||
kwarn!("net_init() failed: {:?}", r.err().unwrap());
|
||||
}
|
||||
return 0;
|
||||
println!("Current PCB:\n\t{:?}", *(ProcessManager::current_pcb()));
|
||||
ProcessManager::exit(usize::MAX);
|
||||
}
|
||||
|
@ -57,6 +57,12 @@ impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||
return AlignedBox {
|
||||
inner: Unique::new_unchecked(ptr),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const ALIGN: usize> Debug for AlignedBox<T, ALIGN> {
|
||||
|
@ -9,7 +9,6 @@ use elf::{endian::AnyEndian, file::FileHeader, segment::ProgramHeader};
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
current_pcb,
|
||||
driver::base::block::SeekFrom,
|
||||
kerror,
|
||||
libs::align::page_align_up,
|
||||
@ -22,6 +21,7 @@ use crate::{
|
||||
process::{
|
||||
abi::AtType,
|
||||
exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
|
||||
ProcessManager,
|
||||
},
|
||||
syscall::{
|
||||
user_access::{clear_user, copy_to_user},
|
||||
@ -93,6 +93,7 @@ impl ElfLoader {
|
||||
) -> Result<(), ExecError> {
|
||||
let start = self.elf_page_start(start);
|
||||
let end = self.elf_page_align_up(end);
|
||||
|
||||
if end > start {
|
||||
let r = user_vm_guard.map_anonymous(
|
||||
start,
|
||||
@ -192,8 +193,8 @@ impl ElfLoader {
|
||||
let map_err_handler = |err: SystemError| {
|
||||
if err == SystemError::EEXIST {
|
||||
kerror!(
|
||||
"Pid: {}, elf segment at {:p} overlaps with existing mapping",
|
||||
current_pcb().pid,
|
||||
"Pid: {:?}, elf segment at {:p} overlaps with existing mapping",
|
||||
ProcessManager::current_pcb().pid(),
|
||||
addr_to_map.as_ptr::<u8>()
|
||||
);
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ macro_rules! int_like {
|
||||
pub const fn from(x: $backing_type) -> Self {
|
||||
$new_type_name(x)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn new(x: $backing_type) -> Self {
|
||||
Self::from(x)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,6 +52,7 @@ macro_rules! int_like {
|
||||
|
||||
/// A mutable holder for T that can safely be shared among threads.
|
||||
/// Runtime equivalent to using `AtomicUsize`, just type-safer.
|
||||
#[derive(Debug)]
|
||||
pub struct $new_atomic_type_name {
|
||||
container: $backing_atomic_type,
|
||||
}
|
||||
@ -112,6 +118,14 @@ macro_rules! int_like {
|
||||
Err(result) => Err($new_type_name::from(result)),
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn fetch_add(
|
||||
&self,
|
||||
val: $new_type_name,
|
||||
order: ::core::sync::atomic::Ordering,
|
||||
) -> $new_type_name {
|
||||
$new_type_name::from(self.container.fetch_add(val.into(), order))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,31 +1,4 @@
|
||||
#pragma once
|
||||
#include <common/sys/types.h>
|
||||
#include <common/glib.h>
|
||||
|
||||
// 帧缓冲区标志位
|
||||
#define SCM_BF_FB (1 << 0) // 当前buffer是设备显存中的帧缓冲区
|
||||
#define SCM_BF_DB (1 << 1) // 当前buffer是双缓冲
|
||||
#define SCM_BF_TEXT (1 << 2) // 使用文本模式
|
||||
#define SCM_BF_PIXEL (1 << 3) // 使用图像模式
|
||||
|
||||
// ui框架类型
|
||||
#define SCM_FRAMWORK_TYPE_TEXT (uint8_t)0
|
||||
#define SCM_FRAMWORK_TYPE_GUI (uint8_t)1
|
||||
|
||||
/**
|
||||
* @brief 帧缓冲区信息结构体
|
||||
*
|
||||
*/
|
||||
struct scm_buffer_info_t
|
||||
{
|
||||
uint32_t width; // 帧缓冲区宽度(pixel或columns)
|
||||
uint32_t height; // 帧缓冲区高度(pixel或lines)
|
||||
uint32_t size; // 帧缓冲区大小(bytes)
|
||||
uint32_t bit_depth; // 像素点位深度
|
||||
|
||||
uint64_t vaddr; // 帧缓冲区的地址
|
||||
uint64_t flags; // 帧缓冲区标志位
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化屏幕管理模块
|
||||
@ -38,21 +11,3 @@ extern void scm_init();
|
||||
*
|
||||
*/
|
||||
extern void scm_reinit();
|
||||
|
||||
/**
|
||||
* @brief 允许双缓冲区
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
extern int scm_enable_double_buffer();
|
||||
|
||||
/**
|
||||
* @brief 允许往窗口打印信息
|
||||
*
|
||||
*/
|
||||
extern void scm_enable_put_to_window();
|
||||
/**
|
||||
* @brief 禁止往窗口打印信息
|
||||
*
|
||||
*/
|
||||
extern void scm_disable_put_to_window();
|
||||
|
@ -7,27 +7,23 @@ use core::{
|
||||
use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::uart::uart_device::{c_uart_send_str, UartPort},
|
||||
include::bindings::bindings::{
|
||||
scm_buffer_info_t, video_frame_buffer_info, video_reinitialize, video_set_refresh_target,
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send_str, UartPort},
|
||||
video::video_refresh_manager,
|
||||
},
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
mm::VirtAddr,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use super::textui_no_alloc::textui_init_no_alloc;
|
||||
|
||||
lazy_static! {
|
||||
/// 全局的UI框架列表
|
||||
pub static ref SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> =
|
||||
/// 全局的UI框架列表
|
||||
pub static SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> =
|
||||
SpinLock::new(LinkedList::new());
|
||||
/// 当前在使用的UI框架
|
||||
pub static ref CURRENT_FRAMEWORK: RwLock<Option<Arc<dyn ScmUiFramework>>> = RwLock::new(None);
|
||||
|
||||
}
|
||||
/// 当前在使用的UI框架
|
||||
pub static CURRENT_FRAMEWORK: RwLock<Option<Arc<dyn ScmUiFramework>>> = RwLock::new(None);
|
||||
|
||||
/// 是否启用双缓冲
|
||||
pub static SCM_DOUBLE_BUFFER_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
@ -48,12 +44,13 @@ pub enum ScmFramworkType {
|
||||
Gui,
|
||||
Unused,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ScmBuffer {
|
||||
DeviceBuffer(Option<VirtAddr>),
|
||||
DoubleBuffer(Option<Box<[u32]>>),
|
||||
DeviceBuffer(VirtAddr),
|
||||
DoubleBuffer(Arc<SpinLock<Box<[u32]>>>),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ScmBufferInfo {
|
||||
width: u32, // 帧缓冲区宽度(pixel或columns)
|
||||
height: u32, // 帧缓冲区高度(pixel或lines)
|
||||
@ -62,29 +59,8 @@ pub struct ScmBufferInfo {
|
||||
pub buf: ScmBuffer,
|
||||
flags: ScmBufferFlag, // 帧缓冲区标志位
|
||||
}
|
||||
impl Clone for ScmBufferInfo {
|
||||
fn clone(&self) -> Self {
|
||||
match self.buf {
|
||||
ScmBuffer::DeviceBuffer(_) => ScmBufferInfo {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
size: self.size,
|
||||
bit_depth: self.bit_depth,
|
||||
flags: self.flags,
|
||||
buf: ScmBuffer::DeviceBuffer(Option::None),
|
||||
},
|
||||
ScmBuffer::DoubleBuffer(_) => ScmBufferInfo {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
size: self.size,
|
||||
bit_depth: self.bit_depth,
|
||||
flags: self.flags,
|
||||
buf: ScmBuffer::DoubleBuffer(Option::None),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl ScmBufferInfo {
|
||||
/// 创建新的帧缓冲区信息
|
||||
///
|
||||
@ -95,78 +71,77 @@ impl ScmBufferInfo {
|
||||
/// ## 返回值
|
||||
///
|
||||
/// - `Result<Self, SystemError>` 创建成功返回新的帧缓冲区结构体,创建失败返回错误码
|
||||
pub fn new(buf_type: ScmBufferFlag) -> Result<Self, SystemError> {
|
||||
pub fn new(mut buf_type: ScmBufferFlag) -> Result<Self, SystemError> {
|
||||
if unlikely(SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) == false) {
|
||||
let buf_info = ScmBufferInfo::from(unsafe { &video_frame_buffer_info });
|
||||
|
||||
return Ok(buf_info);
|
||||
let mut device_buffer = video_refresh_manager().device_buffer().clone();
|
||||
buf_type.remove(ScmBufferFlag::SCM_BF_DB);
|
||||
buf_type.insert(ScmBufferFlag::SCM_BF_FB);
|
||||
device_buffer.flags = buf_type;
|
||||
return Ok(device_buffer);
|
||||
} else {
|
||||
// 创建双缓冲区
|
||||
let mut frame_buffer_info: ScmBufferInfo =
|
||||
ScmBufferInfo::from(unsafe { &video_frame_buffer_info });
|
||||
let device_buffer_guard = video_refresh_manager().device_buffer();
|
||||
|
||||
frame_buffer_info.flags = buf_type;
|
||||
// 这里还是改成使用box来存储数组,如果直接用vec存储,在multiboot2_iter那里会报错,不知为何
|
||||
frame_buffer_info.buf = ScmBuffer::DoubleBuffer(Some(
|
||||
Box::new(vec![
|
||||
0;
|
||||
unsafe { (video_frame_buffer_info.size / 4) as usize }
|
||||
])
|
||||
.into_boxed_slice(),
|
||||
let buf_space: Arc<SpinLock<Box<[u32]>>> = Arc::new(SpinLock::new(
|
||||
vec![0u32; (device_buffer_guard.size / 4) as usize].into_boxed_slice(),
|
||||
));
|
||||
|
||||
return Ok(frame_buffer_info);
|
||||
}
|
||||
}
|
||||
assert!(buf_type.contains(ScmBufferFlag::SCM_BF_DB));
|
||||
|
||||
// 重构了video后可以删除
|
||||
fn vaddr(&mut self) -> VirtAddr {
|
||||
match &self.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
if !vaddr.is_none() {
|
||||
vaddr.unwrap()
|
||||
} else {
|
||||
return VirtAddr::new(0);
|
||||
}
|
||||
}
|
||||
ScmBuffer::DoubleBuffer(buf) => {
|
||||
if !buf.is_none() {
|
||||
let address = self.buf().as_ptr();
|
||||
VirtAddr::new(address as usize)
|
||||
} else {
|
||||
return VirtAddr::new(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(
|
||||
device_buffer_guard.size as usize,
|
||||
buf_space.lock().len() * core::mem::size_of::<u32>()
|
||||
);
|
||||
|
||||
fn buf(&mut self) -> &mut [u32] {
|
||||
let len = self.buf_size() / 4;
|
||||
match &mut self.buf {
|
||||
ScmBuffer::DoubleBuffer(buf) => match buf.as_mut() {
|
||||
Some(buf) => buf,
|
||||
None => panic!("Buffer is none"),
|
||||
},
|
||||
ScmBuffer::DeviceBuffer(vaddr) => match vaddr.as_mut() {
|
||||
Some(vaddr) => {
|
||||
let buf: &mut [u32] = unsafe {
|
||||
core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len as usize)
|
||||
// 创建双缓冲区
|
||||
let buffer = Self {
|
||||
width: device_buffer_guard.width,
|
||||
height: device_buffer_guard.height,
|
||||
size: device_buffer_guard.size,
|
||||
bit_depth: device_buffer_guard.bit_depth,
|
||||
flags: buf_type,
|
||||
buf: ScmBuffer::DoubleBuffer(buf_space),
|
||||
};
|
||||
return buf;
|
||||
}
|
||||
None => panic!("Buffer is none"),
|
||||
},
|
||||
drop(device_buffer_guard);
|
||||
|
||||
return Ok(buffer);
|
||||
}
|
||||
}
|
||||
pub fn buf_size(&self) -> u32 {
|
||||
self.size
|
||||
|
||||
pub unsafe fn new_device_buffer(
|
||||
width: u32,
|
||||
height: u32,
|
||||
size: u32,
|
||||
bit_depth: u32,
|
||||
buf_type: ScmBufferFlag,
|
||||
vaddr: VirtAddr,
|
||||
) -> Result<Self, SystemError> {
|
||||
let buffer = Self {
|
||||
width,
|
||||
height,
|
||||
size,
|
||||
bit_depth,
|
||||
flags: buf_type,
|
||||
buf: ScmBuffer::DeviceBuffer(vaddr),
|
||||
};
|
||||
return Ok(buffer);
|
||||
}
|
||||
pub fn buf_height(&self) -> u32 {
|
||||
|
||||
pub fn buf_size(&self) -> usize {
|
||||
self.size as usize
|
||||
}
|
||||
|
||||
pub fn bit_depth(&self) -> u32 {
|
||||
self.bit_depth
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u32 {
|
||||
self.height
|
||||
}
|
||||
pub fn buf_width(&self) -> u32 {
|
||||
|
||||
pub fn width(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
pub fn is_double_buffer(&self) -> bool {
|
||||
match &self.buf {
|
||||
ScmBuffer::DoubleBuffer(_) => true,
|
||||
@ -179,34 +154,46 @@ impl ScmBufferInfo {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_from_nonoverlapping(&mut self, src: &ScmBufferInfo) {
|
||||
assert!(self.buf_size() == src.buf_size());
|
||||
match &self.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
let len = self.buf_size() / core::mem::size_of::<u32>();
|
||||
let self_buf_guard =
|
||||
unsafe { core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len) };
|
||||
match &src.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
let src_buf_guard =
|
||||
unsafe { core::slice::from_raw_parts(vaddr.data() as *const u32, len) };
|
||||
self_buf_guard.copy_from_slice(src_buf_guard);
|
||||
}
|
||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||
let src_buf_guard = double_buffer.lock();
|
||||
self_buf_guard.copy_from_slice(src_buf_guard.as_ref());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||
let mut double_buffer_guard = double_buffer.lock();
|
||||
match &src.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
let len = src.buf_size() / core::mem::size_of::<u32>();
|
||||
double_buffer_guard.as_mut().copy_from_slice(unsafe {
|
||||
core::slice::from_raw_parts(vaddr.data() as *const u32, len)
|
||||
});
|
||||
}
|
||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||
let x = double_buffer.lock();
|
||||
double_buffer_guard.as_mut().copy_from_slice(x.as_ref());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重构了video后可以删除
|
||||
impl From<&scm_buffer_info_t> for ScmBufferInfo {
|
||||
fn from(value: &scm_buffer_info_t) -> Self {
|
||||
Self {
|
||||
width: value.width,
|
||||
height: value.height,
|
||||
size: value.size,
|
||||
bit_depth: value.bit_depth,
|
||||
buf: ScmBuffer::DeviceBuffer(Some(VirtAddr::new(value.vaddr as usize))),
|
||||
flags: ScmBufferFlag::from_bits_truncate(value.flags as u8),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Into<scm_buffer_info_t> for ScmBufferInfo {
|
||||
fn into(mut self) -> scm_buffer_info_t {
|
||||
let vaddr = self.vaddr();
|
||||
scm_buffer_info_t {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
size: self.size,
|
||||
bit_depth: self.bit_depth,
|
||||
vaddr: vaddr.data() as u64,
|
||||
flags: self.flags.bits as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct ScmUiFrameworkId(u32);
|
||||
|
||||
@ -234,7 +221,10 @@ impl ScmUiFrameworkMetadata {
|
||||
id: ScmUiFrameworkId::new(),
|
||||
name,
|
||||
framework_type: ScmFramworkType::Text,
|
||||
buf_info: ScmBufferInfo::new(ScmBufferFlag::SCM_BF_TEXT).unwrap(),
|
||||
buf_info: ScmBufferInfo::new(
|
||||
ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_DB,
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
return result;
|
||||
@ -249,22 +239,6 @@ impl ScmUiFrameworkMetadata {
|
||||
pub fn set_buf_info(&mut self, buf_info: ScmBufferInfo) {
|
||||
self.buf_info = buf_info;
|
||||
}
|
||||
pub fn buf_is_none(&self) -> bool {
|
||||
match &self.buf_info.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
return vaddr.is_none();
|
||||
}
|
||||
ScmBuffer::DoubleBuffer(buf) => {
|
||||
return buf.is_none();
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn buf(&mut self) -> &mut [u32] {
|
||||
if self.buf_is_none() {
|
||||
panic!("buf is none");
|
||||
}
|
||||
self.buf_info.buf()
|
||||
}
|
||||
}
|
||||
pub trait ScmUiFramework: Sync + Send + Debug {
|
||||
// 安装ui框架的回调函数
|
||||
@ -325,15 +299,10 @@ pub fn scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, S
|
||||
let mut current_framework = CURRENT_FRAMEWORK.write();
|
||||
|
||||
if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) == true {
|
||||
let buf: scm_buffer_info_t = metadata.buf_info.into();
|
||||
let retval = unsafe { video_set_refresh_target(buf) };
|
||||
if retval == 0 {
|
||||
framework.enable()?;
|
||||
}
|
||||
} else {
|
||||
framework.enable()?;
|
||||
video_refresh_manager().set_refresh_target(&metadata.buf_info)?;
|
||||
}
|
||||
|
||||
framework.enable()?;
|
||||
current_framework.replace(framework);
|
||||
|
||||
return Ok(0);
|
||||
@ -357,20 +326,9 @@ pub fn scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemErr
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// 允许双缓冲区
|
||||
#[no_mangle]
|
||||
pub extern "C" fn scm_enable_double_buffer() -> i32 {
|
||||
let r = true_scm_enable_double_buffer().unwrap_or_else(|e| e.to_posix_errno());
|
||||
if r.is_negative() {
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"scm enable double buffer fail.\n\0".as_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
fn true_scm_enable_double_buffer() -> Result<i32, SystemError> {
|
||||
/// 屏幕管理器启用双缓冲区
|
||||
#[allow(dead_code)]
|
||||
pub fn scm_enable_double_buffer() -> Result<i32, SystemError> {
|
||||
if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
|
||||
// 已经开启了双缓冲区了, 直接退出
|
||||
return Ok(0);
|
||||
@ -383,17 +341,19 @@ fn true_scm_enable_double_buffer() -> Result<i32, SystemError> {
|
||||
drop(scm_list);
|
||||
SCM_DOUBLE_BUFFER_ENABLED.store(true, Ordering::SeqCst);
|
||||
// 创建双缓冲区
|
||||
let mut buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
|
||||
let mut refresh_target_buf: scm_buffer_info_t = buf_info.clone().into();
|
||||
// 重构video后进行修改
|
||||
refresh_target_buf.vaddr = buf_info.vaddr().data() as u64;
|
||||
let buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
|
||||
|
||||
// 设置定时刷新的对象
|
||||
video_refresh_manager()
|
||||
.set_refresh_target(&buf_info)
|
||||
.expect("set refresh target failed");
|
||||
|
||||
// 设置当前框架的帧缓冲区
|
||||
CURRENT_FRAMEWORK
|
||||
.write()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.change(buf_info)?;
|
||||
// 设置定时刷新的对象
|
||||
unsafe { video_set_refresh_target(refresh_target_buf) };
|
||||
// 遍历当前所有使用帧缓冲区的框架,更新为双缓冲区
|
||||
for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
|
||||
if !(*framework).metadata()?.buf_info.is_double_buffer() {
|
||||
@ -403,14 +363,14 @@ fn true_scm_enable_double_buffer() -> Result<i32, SystemError> {
|
||||
}
|
||||
}
|
||||
// 通知显示驱动,启动双缓冲
|
||||
unsafe { video_reinitialize(true) };
|
||||
video_refresh_manager().video_reinitialize(true)?;
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// 允许往窗口打印信息
|
||||
#[no_mangle]
|
||||
pub fn scm_enable_put_to_window() {
|
||||
// mm之前要继续往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
|
||||
// mm之前要继续往窗口打印信息时,因为没有动态内存分配(textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
|
||||
if CURRENT_FRAMEWORK.read().is_none() {
|
||||
super::textui::ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst);
|
||||
} else {
|
||||
@ -429,7 +389,6 @@ pub fn scm_enable_put_to_window() {
|
||||
}
|
||||
}
|
||||
/// 禁止往窗口打印信息
|
||||
#[no_mangle]
|
||||
pub fn scm_disable_put_to_window() {
|
||||
// mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
|
||||
if CURRENT_FRAMEWORK.read().is_none() {
|
||||
@ -460,12 +419,15 @@ pub extern "C" fn scm_reinit() -> i32 {
|
||||
return r;
|
||||
}
|
||||
fn true_scm_reinit() -> Result<i32, SystemError> {
|
||||
unsafe { video_reinitialize(false) };
|
||||
video_refresh_manager()
|
||||
.video_reinitialize(false)
|
||||
.expect("video reinitialize failed");
|
||||
|
||||
// 遍历当前所有使用帧缓冲区的框架,更新地址
|
||||
let device_buffer = video_refresh_manager().device_buffer().clone();
|
||||
for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
|
||||
if framework.metadata()?.buf_info().is_device_buffer() {
|
||||
framework.change(unsafe { ScmBufferInfo::from(&video_frame_buffer_info) })?;
|
||||
framework.change(device_buffer.clone())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
use crate::{
|
||||
driver::uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
|
||||
include::bindings::bindings::video_frame_buffer_info,
|
||||
kinfo,
|
||||
libs::{lib_ui::font::FONT_8x16, spinlock::SpinLock},
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send, c_uart_send_str, UartPort},
|
||||
video::video_refresh_manager,
|
||||
},
|
||||
kdebug, kinfo,
|
||||
libs::{
|
||||
lib_ui::font::FONT_8x16,
|
||||
rwlock::RwLock,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
use alloc::{boxed::Box, collections::LinkedList, string::ToString};
|
||||
@ -16,13 +22,14 @@ use core::{
|
||||
|
||||
use super::{
|
||||
screen_manager::{
|
||||
scm_register, ScmBufferInfo, ScmFramworkType, ScmUiFramework, ScmUiFrameworkMetadata,
|
||||
scm_register, ScmBuffer, ScmBufferInfo, ScmFramworkType, ScmUiFramework,
|
||||
ScmUiFrameworkMetadata,
|
||||
},
|
||||
textui_no_alloc::no_init_textui_putchar_window,
|
||||
};
|
||||
|
||||
/// 声明全局的TEXTUI_FRAMEWORK
|
||||
static mut __TEXTUI_FRAMEWORK: Option<Box<TextUiFramework>> = None;
|
||||
static mut __TEXTUI_FRAMEWORK: Option<Arc<TextUiFramework>> = None;
|
||||
|
||||
/// 每个字符的宽度和高度(像素)
|
||||
pub const TEXTUI_CHAR_WIDTH: u32 = 8;
|
||||
@ -34,18 +41,25 @@ pub static mut TEXTUI_IS_INIT: bool = false;
|
||||
pub static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
/// 获取TEXTUI_FRAMEWORK的可变实例
|
||||
pub fn textui_framework() -> &'static mut TextUiFramework {
|
||||
return unsafe { __TEXTUI_FRAMEWORK.as_mut().unwrap() };
|
||||
pub fn textui_framework() -> Arc<TextUiFramework> {
|
||||
unsafe {
|
||||
return __TEXTUI_FRAMEWORK
|
||||
.as_ref()
|
||||
.expect("Textui framework has not been initialized yet!")
|
||||
.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化TEXTUI_FRAMEWORK
|
||||
pub unsafe fn textui_framwork_init() {
|
||||
if __TEXTUI_FRAMEWORK.is_none() {
|
||||
kinfo!("textuiframework init");
|
||||
let metadata = ScmUiFrameworkMetadata::new("TextUI".to_string(), ScmFramworkType::Text);
|
||||
kdebug!("textui metadata: {:?}", metadata);
|
||||
// 为textui框架生成第一个窗口
|
||||
let vlines_num = (metadata.buf_info().buf_height() / TEXTUI_CHAR_HEIGHT) as usize;
|
||||
let vlines_num = (metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as usize;
|
||||
|
||||
let chars_num = (metadata.buf_info().buf_width() / TEXTUI_CHAR_WIDTH) as usize;
|
||||
let chars_num = (metadata.buf_info().width() / TEXTUI_CHAR_WIDTH) as usize;
|
||||
|
||||
let initial_window = TextuiWindow::new(
|
||||
WindowFlag::TEXTUI_CHROMATIC,
|
||||
@ -62,12 +76,21 @@ pub unsafe fn textui_framwork_init() {
|
||||
Arc::new(SpinLock::new(LinkedList::new()));
|
||||
window_list.lock().push_back(current_window.clone());
|
||||
|
||||
__TEXTUI_FRAMEWORK = Some(Box::new(TextUiFramework::new(
|
||||
__TEXTUI_FRAMEWORK = Some(Arc::new(TextUiFramework::new(
|
||||
metadata,
|
||||
window_list,
|
||||
current_window,
|
||||
default_window,
|
||||
)));
|
||||
|
||||
scm_register(textui_framework()).expect("register textui framework failed");
|
||||
kdebug!("textui framework init success");
|
||||
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"\ntext ui initialized\n\0".as_ptr(),
|
||||
);
|
||||
unsafe { TEXTUI_IS_INIT = true };
|
||||
} else {
|
||||
panic!("Try to init TEXTUI_FRAMEWORK twice!");
|
||||
}
|
||||
@ -254,21 +277,52 @@ pub struct TextuiCharChromatic {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TextuiBuf<'a>(&'a mut [u32]);
|
||||
pub struct TextuiBuf<'a> {
|
||||
buf: Option<&'a mut [u32]>,
|
||||
guard: Option<SpinLockGuard<'a, Box<[u32]>>>,
|
||||
}
|
||||
|
||||
impl TextuiBuf<'_> {
|
||||
pub fn new(buf: &mut [u32]) -> TextuiBuf {
|
||||
TextuiBuf(buf)
|
||||
pub fn new(buf: &mut ScmBufferInfo) -> TextuiBuf {
|
||||
let len = buf.buf_size() / 4;
|
||||
|
||||
match &buf.buf {
|
||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||
return TextuiBuf {
|
||||
buf: Some(unsafe {
|
||||
core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len)
|
||||
}),
|
||||
guard: None,
|
||||
};
|
||||
}
|
||||
|
||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||
let guard: SpinLockGuard<'_, Box<[u32]>> = double_buffer.lock();
|
||||
|
||||
return TextuiBuf {
|
||||
buf: None,
|
||||
guard: Some(guard),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buf_mut(&mut self) -> &mut [u32] {
|
||||
if let Some(buf) = &mut self.buf {
|
||||
return buf;
|
||||
} else {
|
||||
return self.guard.as_mut().unwrap().as_mut();
|
||||
}
|
||||
}
|
||||
pub fn put_color_in_pixel(&mut self, color: u32, index: usize) {
|
||||
let buf: &mut [u32] = self.0;
|
||||
let buf: &mut [u32] = self.buf_mut();
|
||||
buf[index] = color;
|
||||
}
|
||||
pub fn get_index_of_next_line(now_index: usize) -> usize {
|
||||
textui_framework().metadata.buf_info().buf_width() as usize + now_index
|
||||
textui_framework().metadata.read().buf_info().width() as usize + now_index
|
||||
}
|
||||
pub fn get_index_by_x_y(x: usize, y: usize) -> usize {
|
||||
textui_framework().metadata.buf_info().buf_width() as usize * y + x
|
||||
textui_framework().metadata.read().buf_info().width() as usize * y + x
|
||||
}
|
||||
pub fn get_start_index_by_lineid_lineindex(lineid: LineId, lineindex: LineIndex) -> usize {
|
||||
// x 左上角列像素点位置
|
||||
@ -325,7 +379,10 @@ impl TextuiCharChromatic {
|
||||
|
||||
let mut count = TextuiBuf::get_start_index_by_lineid_lineindex(lineid, lineindex);
|
||||
|
||||
let mut buf = TextuiBuf::new(textui_framework().metadata.buf());
|
||||
let mut _binding = textui_framework().metadata.read().buf_info();
|
||||
|
||||
let mut buf = TextuiBuf::new(&mut _binding);
|
||||
|
||||
// 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点
|
||||
for i in 0..TEXTUI_CHAR_HEIGHT {
|
||||
let start = count;
|
||||
@ -356,8 +413,15 @@ impl TextuiCharChromatic {
|
||||
|
||||
let id_y: u32 = lineid.into();
|
||||
let y: u32 = id_y * TEXTUI_CHAR_HEIGHT;
|
||||
|
||||
let buf_width = video_refresh_manager().device_buffer().width();
|
||||
// 找到输入缓冲区的起始地址位置
|
||||
let fb = unsafe { video_frame_buffer_info.vaddr };
|
||||
let buf_start =
|
||||
if let ScmBuffer::DeviceBuffer(vaddr) = video_refresh_manager().device_buffer().buf {
|
||||
vaddr
|
||||
} else {
|
||||
panic!("device buffer is not init");
|
||||
};
|
||||
|
||||
let mut testbit: u32; // 用来测试特定行的某列是背景还是字体本身
|
||||
|
||||
@ -365,9 +429,9 @@ impl TextuiCharChromatic {
|
||||
for i in 0..TEXTUI_CHAR_HEIGHT {
|
||||
// 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x)
|
||||
|
||||
let mut addr: *mut u32 = (fb
|
||||
+ unsafe { video_frame_buffer_info.width } as u64 * 4 * (y as u64 + i as u64)
|
||||
+ 4 * x as u64) as *mut u32;
|
||||
let mut addr: *mut u32 =
|
||||
(buf_start + buf_width as usize * 4 * (y as usize + i as usize) + 4 * x as usize)
|
||||
.data() as *mut u32;
|
||||
|
||||
testbit = 1 << (TEXTUI_CHAR_WIDTH + 1);
|
||||
|
||||
@ -808,7 +872,7 @@ impl Default for TextuiWindow {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct TextUiFramework {
|
||||
metadata: ScmUiFrameworkMetadata,
|
||||
metadata: RwLock<ScmUiFrameworkMetadata>,
|
||||
window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>,
|
||||
actual_line: AtomicI32, // 真实行的数量(textui的帧缓冲区能容纳的内容的行数)
|
||||
current_window: Arc<SpinLock<TextuiWindow>>, // 当前的主窗口
|
||||
@ -823,9 +887,9 @@ impl TextUiFramework {
|
||||
default_window: Arc<SpinLock<TextuiWindow>>,
|
||||
) -> Self {
|
||||
let actual_line =
|
||||
AtomicI32::new((&metadata.buf_info().buf_height() / TEXTUI_CHAR_HEIGHT) as i32);
|
||||
AtomicI32::new((&metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as i32);
|
||||
let inner = TextUiFramework {
|
||||
metadata,
|
||||
metadata: RwLock::new(metadata),
|
||||
window_list,
|
||||
actual_line,
|
||||
current_window,
|
||||
@ -835,7 +899,7 @@ impl TextUiFramework {
|
||||
}
|
||||
}
|
||||
|
||||
impl ScmUiFramework for &mut TextUiFramework {
|
||||
impl ScmUiFramework for TextUiFramework {
|
||||
// 安装ui框架的回调函数
|
||||
fn install(&self) -> Result<i32, SystemError> {
|
||||
c_uart_send_str(
|
||||
@ -861,10 +925,16 @@ impl ScmUiFramework for &mut TextUiFramework {
|
||||
}
|
||||
// 改变ui框架的帧缓冲区的回调函数
|
||||
fn change(&self, buf_info: ScmBufferInfo) -> Result<i32, SystemError> {
|
||||
let src_buf = textui_framework().metadata.buf();
|
||||
textui_framework().metadata.set_buf_info(buf_info);
|
||||
let dst_buf = textui_framework().metadata.buf();
|
||||
dst_buf.copy_from_slice(src_buf);
|
||||
let old_buf = textui_framework().metadata.read().buf_info();
|
||||
|
||||
textui_framework().metadata.write().set_buf_info(buf_info);
|
||||
|
||||
let mut new_buf = textui_framework().metadata.read().buf_info();
|
||||
|
||||
new_buf.copy_from_nonoverlapping(&old_buf);
|
||||
kdebug!("textui change buf_info: old: {:?}", old_buf);
|
||||
kdebug!("textui change buf_info: new: {:?}", new_buf);
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
/// 获取ScmUiFramework的元数据
|
||||
@ -873,7 +943,7 @@ impl ScmUiFramework for &mut TextUiFramework {
|
||||
/// -成功:Ok(ScmUiFramework的元数据)
|
||||
/// -失败:Err(错误码)
|
||||
fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> {
|
||||
let metadata = self.metadata.clone();
|
||||
let metadata = self.metadata.read().clone();
|
||||
|
||||
return Ok(metadata);
|
||||
}
|
||||
@ -952,16 +1022,6 @@ pub extern "C" fn rs_textui_init() -> i32 {
|
||||
|
||||
fn textui_init() -> Result<i32, SystemError> {
|
||||
unsafe { textui_framwork_init() };
|
||||
let textui_framework = textui_framework();
|
||||
|
||||
unsafe { TEXTUI_IS_INIT = true };
|
||||
|
||||
scm_register(Arc::new(textui_framework))?;
|
||||
|
||||
c_uart_send_str(
|
||||
UartPort::COM1.to_u16(),
|
||||
"\ntext ui initialized\n\0".as_ptr(),
|
||||
);
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
|
@ -4,8 +4,10 @@ use core::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::uart::uart_device::{c_uart_send, UartPort},
|
||||
include::bindings::bindings::video_frame_buffer_info,
|
||||
driver::{
|
||||
uart::uart_device::{c_uart_send, UartPort},
|
||||
video::video_refresh_manager,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -21,15 +23,11 @@ pub static NO_ALLOC_OPERATIONS_INDEX: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
/// 当系统刚启动的时候,由于内存管理未初始化,而texiui需要动态内存分配。因此只能暂时暴力往屏幕(video_frame_buffer_info)输出信息
|
||||
pub fn textui_init_no_alloc() {
|
||||
TRUE_LINE_NUM.store(
|
||||
unsafe { (video_frame_buffer_info.height / TEXTUI_CHAR_HEIGHT) as i32 },
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
let height = video_refresh_manager().device_buffer().height();
|
||||
let width = video_refresh_manager().device_buffer().width();
|
||||
TRUE_LINE_NUM.store((height / TEXTUI_CHAR_HEIGHT) as i32, Ordering::SeqCst);
|
||||
|
||||
CHAR_PER_LINE.store(
|
||||
unsafe { (video_frame_buffer_info.width / TEXTUI_CHAR_WIDTH) as i32 },
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
CHAR_PER_LINE.store((width / TEXTUI_CHAR_WIDTH) as i32, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn no_init_textui_putchar_window(
|
||||
|
@ -1,18 +0,0 @@
|
||||
use crate::include::bindings::bindings::List;
|
||||
|
||||
/// @brief 初始化链表
|
||||
#[inline]
|
||||
pub fn list_init(list: *mut List) {
|
||||
unsafe { *list }.prev = list;
|
||||
unsafe { *list }.next = list;
|
||||
}
|
||||
|
||||
impl Default for List {
|
||||
fn default() -> Self {
|
||||
let x = Self {
|
||||
prev: 0 as *mut List,
|
||||
next: 0 as *mut List,
|
||||
};
|
||||
return x;
|
||||
}
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
#![allow(dead_code)]
|
||||
use super::spinlock::RawSpinlock;
|
||||
use crate::{arch::asm::cmpxchg::try_cmpxchg_q, syscall::SystemError};
|
||||
use core::{fmt::Debug, intrinsics::size_of};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// 由于需要cmpxchg,所以整个lockref按照8字节对齐
|
||||
#[repr(align(8))]
|
||||
#[derive(Debug)]
|
||||
pub struct LockRef {
|
||||
pub lock: RawSpinlock,
|
||||
pub count: i32,
|
||||
}
|
||||
|
||||
/// 除了x86_64以外的架构,不使用cmpxchg进行优化
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
pub struct LockRef {
|
||||
lock: RawSpinlock,
|
||||
count: i32,
|
||||
}
|
||||
|
||||
enum CmpxchgMode {
|
||||
Increase,
|
||||
IncreaseNotZero,
|
||||
IncreaseNotDead,
|
||||
Decrease,
|
||||
DecreaseReturn,
|
||||
DecreaseNotZero,
|
||||
DecreaseOrLockNotZero,
|
||||
}
|
||||
|
||||
impl LockRef {
|
||||
pub const INIT: LockRef = LockRef {
|
||||
lock: RawSpinlock::INIT,
|
||||
count: 0,
|
||||
};
|
||||
|
||||
pub fn new() -> LockRef {
|
||||
assert_eq!(size_of::<LockRef>(), 8);
|
||||
return LockRef::INIT;
|
||||
}
|
||||
|
||||
/// @brief 为X86架构实现cmpxchg循环,以支持无锁操作。
|
||||
///
|
||||
/// @return 操作成功:返回Ok(new.count)
|
||||
/// @return 操作失败,原因:超时 => 返回Err(SystemError::ETIMEDOUT)
|
||||
/// @return 操作失败,原因:不满足规则 => 返回Err(SystemError::E2BIG)
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[inline]
|
||||
fn cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32> {
|
||||
use core::ptr::read_volatile;
|
||||
|
||||
use crate::arch::cpu::cpu_relax;
|
||||
|
||||
let mut old: LockRef = LockRef::INIT;
|
||||
old.count = unsafe { read_volatile(&self.count) };
|
||||
for _ in 0..100 {
|
||||
if !old.lock.is_locked() {
|
||||
let mut new = LockRef::INIT;
|
||||
unsafe {
|
||||
*(&mut new as *mut LockRef as *mut usize as *mut u64) =
|
||||
read_volatile(&mut old as *mut LockRef as *mut usize as *mut u64);
|
||||
new.lock.set_value(false);
|
||||
}
|
||||
|
||||
// 根据不同情况,执行不同代码
|
||||
match mode {
|
||||
CmpxchgMode::Increase => {
|
||||
new.count += 1;
|
||||
}
|
||||
CmpxchgMode::IncreaseNotZero => {
|
||||
// 操作失败
|
||||
if old.count <= 0 {
|
||||
return Err(1);
|
||||
}
|
||||
new.count += 1;
|
||||
}
|
||||
|
||||
CmpxchgMode::IncreaseNotDead => {
|
||||
if old.count < 0 {
|
||||
return Err(1);
|
||||
}
|
||||
new.count += 1;
|
||||
}
|
||||
|
||||
CmpxchgMode::Decrease | CmpxchgMode::DecreaseReturn => {
|
||||
if old.count <= 0 {
|
||||
return Err(1);
|
||||
}
|
||||
new.count -= 1;
|
||||
}
|
||||
CmpxchgMode::DecreaseNotZero | CmpxchgMode::DecreaseOrLockNotZero => {
|
||||
if old.count <= 1 {
|
||||
return Err(1);
|
||||
}
|
||||
new.count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if unsafe {
|
||||
try_cmpxchg_q(
|
||||
self as *mut LockRef as *mut usize as *mut u64,
|
||||
&mut old as *mut LockRef as *mut usize as *mut u64,
|
||||
&mut new as *mut LockRef as *mut usize as *mut u64,
|
||||
)
|
||||
} {
|
||||
// 无锁操作成功,返回新的值
|
||||
return Ok(new.count);
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
return Err(SystemError::ETIMEDOUT.to_posix_errno());
|
||||
}
|
||||
|
||||
/// @brief 对于不支持无锁lockref的架构,直接返回Err(SystemError::EOPNOTSUPP_OR_ENOTSUP),表示不支持
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
#[inline]
|
||||
fn cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32> {
|
||||
use crate::include::bindings::bindings::EOPNOTSUPP_OR_ENOTSUP;
|
||||
|
||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP.to_posix_errno());
|
||||
}
|
||||
|
||||
/// @brief 原子的将引用计数加1
|
||||
pub fn inc(&mut self) {
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::Increase);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.lock.lock();
|
||||
self.count += 1;
|
||||
self.lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将引用计数加1.如果原来的count≤0,则操作失败。
|
||||
*
|
||||
* @return Ok(self.count) 操作成功
|
||||
* @return Err(SystemError::EPERM) 操作失败
|
||||
*/
|
||||
pub fn inc_not_zero(&mut self) -> Result<i32, SystemError> {
|
||||
{
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::IncreaseNotZero);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
} else if cmpxchg_result.unwrap_err() == 1 {
|
||||
// 不满足not zero 的条件
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
}
|
||||
let mut retval = Err(SystemError::EPERM);
|
||||
self.lock.lock();
|
||||
|
||||
if self.count > 0 {
|
||||
self.count += 1;
|
||||
retval = Ok(self.count);
|
||||
}
|
||||
|
||||
self.lock.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 引用计数自增1。(除非该lockref已经被标记为死亡)
|
||||
*
|
||||
* @return Ok(self.count) 操作成功
|
||||
* @return Err(SystemError::EPERM) 操作失败,lockref已死亡
|
||||
*/
|
||||
pub fn inc_not_dead(&mut self) -> Result<i32, SystemError> {
|
||||
{
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::IncreaseNotDead);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
} else if cmpxchg_result.unwrap_err() == 1 {
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
}
|
||||
// 快捷路径操作失败,尝试加锁
|
||||
let mut retval = Err(SystemError::EPERM);
|
||||
|
||||
self.lock.lock();
|
||||
if self.count >= 0 {
|
||||
self.count += 1;
|
||||
retval = Ok(self.count);
|
||||
}
|
||||
self.lock.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将引用计数-1。如果已处于count≤0的状态,则返回SystemError::EPERM
|
||||
*
|
||||
* 本函数与lockref_dec_return()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会再次尝试通过加锁来执行操作
|
||||
* 而后者会直接返回错误
|
||||
*
|
||||
* @return Ok(self.count) 操作成功,返回新的引用变量值
|
||||
* @return Err(SystemError::EPERM) 操作失败,lockref处于count≤0的状态
|
||||
*/
|
||||
pub fn dec(&mut self) -> Result<i32, SystemError> {
|
||||
{
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::Decrease);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
}
|
||||
}
|
||||
let retval: Result<i32, SystemError>;
|
||||
self.lock.lock();
|
||||
|
||||
if self.count > 0 {
|
||||
self.count -= 1;
|
||||
retval = Ok(self.count);
|
||||
} else {
|
||||
retval = Err(SystemError::EPERM);
|
||||
}
|
||||
|
||||
self.lock.unlock();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将引用计数减1。如果处于已加锁或count≤0的状态,则返回SystemError::EPERM
|
||||
* 若当前处理器架构不支持cmpxchg,则退化为self.dec()
|
||||
*
|
||||
* 本函数与lockref_dec()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会直接返回错误
|
||||
* 而后者会再次尝试通过加锁来执行操作
|
||||
*
|
||||
* @return Ok(self.count) 操作成功,返回新的引用变量值
|
||||
* @return Err(SystemError::EPERM) 操作失败,lockref处于已加锁或count≤0的状态
|
||||
*/
|
||||
pub fn dec_return(&mut self) -> Result<i32, SystemError> {
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseReturn);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
} else if *cmpxchg_result.as_ref().unwrap_err() == 1 {
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
// 由于cmpxchg超时,操作失败
|
||||
if *cmpxchg_result.as_ref().unwrap_err()
|
||||
!= SystemError::EOPNOTSUPP_OR_ENOTSUP.to_posix_errno()
|
||||
{
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
// 能走到这里,代表架构当前不支持cmpxchg
|
||||
// 退化为直接dec,加锁
|
||||
return self.dec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将引用计数减1。若当前的引用计数≤1,则操作失败
|
||||
*
|
||||
* 该函数与lockref_dec_or_lock_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会直接返回Err(SystemError::EPERM)
|
||||
* 而后者在这种情况下,会尝试加锁来进行操作。
|
||||
*
|
||||
* @return Ok(self.count) 成功将引用计数减1
|
||||
* @return Err(SystemError::EPERM) 如果当前的引用计数≤1,操作失败
|
||||
*/
|
||||
pub fn dec_not_zero(&mut self) -> Result<i32, SystemError> {
|
||||
{
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseNotZero);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
} else if cmpxchg_result.unwrap_err() == 1 {
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
let retval: Result<i32, SystemError>;
|
||||
self.lock.lock();
|
||||
if self.count > 1 {
|
||||
self.count -= 1;
|
||||
retval = Ok(self.count);
|
||||
} else {
|
||||
retval = Err(SystemError::EPERM);
|
||||
}
|
||||
self.lock.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将引用计数减1。若当前的引用计数≤1,则操作失败
|
||||
*
|
||||
* 该函数与lockref_dec_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会尝试加锁来进行操作。
|
||||
* 而后者在这种情况下,会直接返回Err(SystemError::EPERM).
|
||||
*
|
||||
* @return Ok(self.count) 成功将引用计数减1
|
||||
* @return Err(SystemError::EPERM) 如果当前的引用计数≤1,操作失败
|
||||
*/
|
||||
pub fn dec_or_lock_not_zero(&mut self) -> Result<i32, SystemError> {
|
||||
{
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseOrLockNotZero);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
let retval: Result<i32, SystemError>;
|
||||
self.lock.lock();
|
||||
if self.count > 1 {
|
||||
self.count -= 1;
|
||||
retval = Ok(self.count);
|
||||
} else {
|
||||
retval = Err(SystemError::EPERM);
|
||||
}
|
||||
self.lock.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子地将lockref变量标记为已经死亡(将count设置为负值)
|
||||
*/
|
||||
pub fn mark_dead(&mut self) {
|
||||
self.lock.lock();
|
||||
self.count = -128;
|
||||
self.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 您可以使用以下代码测试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);
|
||||
|
||||
assert!(lockref.dec().is_err());
|
||||
assert_eq!(lockref.count, 0);
|
||||
|
||||
lockref.inc();
|
||||
assert_eq!(lockref.count, 1);
|
||||
|
||||
assert!(lockref.dec_not_zero().is_err());
|
||||
|
||||
lockref.inc();
|
||||
assert_eq!(lockref.count, 2);
|
||||
|
||||
assert!(lockref.dec_not_zero().is_ok());
|
||||
|
||||
lockref.mark_dead();
|
||||
assert!(lockref.count < 0);
|
||||
|
||||
assert!(lockref.inc_not_dead().is_err());
|
||||
kdebug!("lockref={:?}", lockref);
|
||||
*/
|
@ -8,15 +8,12 @@ pub mod int_like;
|
||||
pub mod keyboard_parser;
|
||||
pub mod lazy_init;
|
||||
pub mod lib_ui;
|
||||
pub mod list;
|
||||
pub mod lockref;
|
||||
pub mod mutex;
|
||||
pub mod notifier;
|
||||
pub mod once;
|
||||
pub mod printk;
|
||||
pub mod rbtree;
|
||||
#[macro_use]
|
||||
pub mod refcount;
|
||||
pub mod rwlock;
|
||||
pub mod semaphore;
|
||||
pub mod spinlock;
|
||||
|
@ -1,121 +0,0 @@
|
||||
#include <common/mutex.h>
|
||||
#include <mm/slab.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
/**
|
||||
* @brief 初始化互斥量
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_init(mutex_t *lock)
|
||||
{
|
||||
atomic_set(&lock->count, 1);
|
||||
spin_init(&lock->wait_lock);
|
||||
list_init(&lock->wait_list);
|
||||
}
|
||||
|
||||
static void __mutex_sleep()
|
||||
{
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
current_pcb->flags |= PF_NEED_SCHED;
|
||||
sched();
|
||||
}
|
||||
|
||||
static void __mutex_acquire(mutex_t *lock)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* @brief 对互斥量加锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_lock(mutex_t *lock)
|
||||
{
|
||||
bool lock_ok = 0;
|
||||
|
||||
while (lock_ok == false)
|
||||
{
|
||||
spin_lock(&lock->wait_lock);
|
||||
if (likely(mutex_is_locked(lock)))
|
||||
{
|
||||
struct mutex_waiter_t *waiter = (struct mutex_waiter_t *)kzalloc(sizeof(struct mutex_waiter_t), 0);
|
||||
if (waiter == NULL)
|
||||
{
|
||||
kerror("In mutex_lock: no memory to alloc waiter. Program's behaviour might be indetermined!");
|
||||
spin_unlock(&lock->wait_lock);
|
||||
return;
|
||||
}
|
||||
// memset(waiter, 0, sizeof(struct mutex_waiter_t));
|
||||
waiter->pcb = current_pcb;
|
||||
list_init(&waiter->list);
|
||||
list_append(&lock->wait_list, &waiter->list);
|
||||
|
||||
spin_unlock(&lock->wait_lock);
|
||||
|
||||
__mutex_sleep();
|
||||
}
|
||||
else
|
||||
{
|
||||
atomic_dec(&lock->count);
|
||||
spin_unlock(&lock->wait_lock);
|
||||
lock_ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 对互斥量解锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*/
|
||||
void mutex_unlock(mutex_t *lock)
|
||||
{
|
||||
if (unlikely(!mutex_is_locked(lock)))
|
||||
return;
|
||||
|
||||
spin_lock(&lock->wait_lock);
|
||||
struct mutex_waiter_t *wt = NULL;
|
||||
if (mutex_is_locked(lock))
|
||||
{
|
||||
if (!list_empty(&lock->wait_list))
|
||||
wt = container_of(list_next(&lock->wait_list), struct mutex_waiter_t, list);
|
||||
|
||||
atomic_inc(&lock->count);
|
||||
if (wt != NULL)
|
||||
list_del(&wt->list);
|
||||
}
|
||||
|
||||
spin_unlock(&lock->wait_lock);
|
||||
|
||||
if (wt != NULL)
|
||||
{
|
||||
process_wakeup(wt->pcb);
|
||||
kfree(wt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试对互斥量加锁
|
||||
*
|
||||
* @param lock mutex结构体
|
||||
*
|
||||
* @return 成功加锁->1, 加锁失败->0
|
||||
*/
|
||||
int mutex_trylock(mutex_t *lock)
|
||||
{
|
||||
if (mutex_is_locked(lock))
|
||||
return 0;
|
||||
|
||||
spin_lock(&lock->wait_lock);
|
||||
if (mutex_is_locked(lock))
|
||||
{
|
||||
spin_unlock(&lock->wait_lock);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
atomic_dec(&lock->count);
|
||||
spin_unlock(&lock->wait_lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -3,14 +3,13 @@ use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use alloc::collections::LinkedList;
|
||||
use alloc::{collections::LinkedList, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
arch::{asm::current::current_pcb, sched::sched},
|
||||
include::bindings::bindings::{
|
||||
pid_t, process_control_block, process_wakeup, PROC_INTERRUPTIBLE, PROC_RUNNING,
|
||||
},
|
||||
arch::{sched::sched, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
process::{Pid, ProcessControlBlock, ProcessManager},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -21,7 +20,7 @@ struct MutexInner {
|
||||
/// 当前Mutex是否已经被上锁(上锁时,为true)
|
||||
is_locked: bool,
|
||||
/// 等待获得这个锁的进程的链表
|
||||
wait_list: LinkedList<&'static mut process_control_block>,
|
||||
wait_list: LinkedList<Arc<ProcessControlBlock>>,
|
||||
}
|
||||
|
||||
/// @brief Mutex互斥量结构体
|
||||
@ -50,7 +49,7 @@ impl<T> Mutex<T> {
|
||||
data: UnsafeCell::new(value),
|
||||
inner: SpinLock::new(MutexInner {
|
||||
is_locked: false,
|
||||
wait_list: LinkedList::<&'static mut process_control_block>::new(),
|
||||
wait_list: LinkedList::new(),
|
||||
}),
|
||||
};
|
||||
}
|
||||
@ -65,8 +64,9 @@ impl<T> Mutex<T> {
|
||||
// 当前mutex已经上锁
|
||||
if inner.is_locked {
|
||||
// 检查当前进程是否处于等待队列中,如果不在,就加到等待队列内
|
||||
if self.check_pid_in_wait_list(&inner, current_pcb().pid) == false {
|
||||
inner.wait_list.push_back(current_pcb());
|
||||
if self.check_pid_in_wait_list(&inner, ProcessManager::current_pcb().pid()) == false
|
||||
{
|
||||
inner.wait_list.push_back(ProcessManager::current_pcb());
|
||||
}
|
||||
|
||||
// 加到等待唤醒的队列,然后睡眠
|
||||
@ -104,8 +104,9 @@ impl<T> Mutex<T> {
|
||||
|
||||
/// @brief Mutex内部的睡眠函数
|
||||
fn __sleep(&self) {
|
||||
current_pcb().state &= !(PROC_RUNNING as u64);
|
||||
current_pcb().state |= PROC_INTERRUPTIBLE as u64;
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).ok();
|
||||
drop(irq_guard);
|
||||
sched();
|
||||
}
|
||||
|
||||
@ -123,19 +124,17 @@ impl<T> Mutex<T> {
|
||||
}
|
||||
|
||||
// wait_list不为空,则获取下一个要被唤醒的进程的pcb
|
||||
let to_wakeup: &mut process_control_block = inner.wait_list.pop_front().unwrap();
|
||||
let to_wakeup: Arc<ProcessControlBlock> = inner.wait_list.pop_front().unwrap();
|
||||
drop(inner);
|
||||
|
||||
unsafe {
|
||||
process_wakeup(to_wakeup);
|
||||
}
|
||||
ProcessManager::wakeup(&to_wakeup).ok();
|
||||
}
|
||||
|
||||
/// @brief 检查进程是否在该mutex的等待队列内
|
||||
#[inline]
|
||||
fn check_pid_in_wait_list(&self, inner: &MutexInner, pid: pid_t) -> bool {
|
||||
fn check_pid_in_wait_list(&self, inner: &MutexInner, pid: Pid) -> bool {
|
||||
for p in inner.wait_list.iter() {
|
||||
if p.pid == pid {
|
||||
if p.pid() == pid {
|
||||
// 在等待队列内
|
||||
return true;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ macro_rules! printk_color {
|
||||
#[macro_export]
|
||||
macro_rules! kdebug {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ macro_rules! kdebug {
|
||||
#[macro_export]
|
||||
macro_rules! kinfo {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ macro_rules! kinfo {
|
||||
macro_rules! kwarn {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::YELLOW, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ WARN ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ macro_rules! kwarn {
|
||||
macro_rules! kerror {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ ERROR ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ macro_rules! kerror {
|
||||
macro_rules! kBUG {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ BUG ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,67 +0,0 @@
|
||||
use crate::{
|
||||
include::bindings::bindings::{atomic_dec, atomic_inc, atomic_t},
|
||||
kwarn,
|
||||
};
|
||||
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
refs: atomic_t { value: 1 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用
|
||||
impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCount {
|
||||
fn convert_mut(
|
||||
src: *mut crate::include::bindings::bindings::refcount_struct,
|
||||
) -> Option<&'static mut Self> {
|
||||
return __convert_mut(src);
|
||||
}
|
||||
fn convert_ref(
|
||||
src: *const crate::include::bindings::bindings::refcount_struct,
|
||||
) -> Option<&'static Self> {
|
||||
return __convert_ref(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 以指定的值初始化refcount
|
||||
macro_rules! REFCOUNT_INIT {
|
||||
($x:expr) => {
|
||||
$crate::libs::refcount::RefCount {
|
||||
refs: $crate::include::bindings::bindings::atomic_t { value: $x },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief 引用计数自增1
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn refcount_inc(r: &mut RefCount) {
|
||||
if atomic_read(&r.refs) == 0 {
|
||||
kwarn!("Refcount increased from 0, may be use-after free");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
atomic_inc(&mut r.refs);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 引用计数自减1
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn refcount_dec(r: &mut RefCount) {
|
||||
unsafe {
|
||||
atomic_dec(&mut r.refs);
|
||||
}
|
||||
}
|
@ -8,7 +8,9 @@ use core::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
process::preempt::{preempt_disable, preempt_enable},
|
||||
arch::CurrentIrqArch,
|
||||
exception::{InterruptArch, IrqFlagsGuard},
|
||||
process::ProcessManager,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -59,6 +61,7 @@ pub struct RwLockUpgradableGuard<'a, T: 'a> {
|
||||
pub struct RwLockWriteGuard<'a, T: 'a> {
|
||||
data: *mut T,
|
||||
inner: &'a RwLock<T>,
|
||||
irq_guard: Option<IrqFlagsGuard>,
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> Send for RwLock<T> {}
|
||||
@ -113,10 +116,10 @@ impl<T> RwLock<T> {
|
||||
#[inline]
|
||||
/// @brief 尝试获取READER守卫
|
||||
pub fn try_read(&self) -> Option<RwLockReadGuard<T>> {
|
||||
preempt_disable();
|
||||
ProcessManager::preempt_disable();
|
||||
let r = self.inner_try_read();
|
||||
if r.is_none() {
|
||||
preempt_enable();
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -177,10 +180,10 @@ impl<T> RwLock<T> {
|
||||
#[inline]
|
||||
/// @brief 尝试获得WRITER守卫
|
||||
pub fn try_write(&self) -> Option<RwLockWriteGuard<T>> {
|
||||
preempt_disable();
|
||||
ProcessManager::preempt_disable();
|
||||
let r = self.inner_try_write();
|
||||
if r.is_none() {
|
||||
preempt_enable();
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -198,6 +201,7 @@ impl<T> RwLock<T> {
|
||||
return Some(RwLockWriteGuard {
|
||||
data: unsafe { &mut *self.data.get() },
|
||||
inner: self,
|
||||
irq_guard: None,
|
||||
});
|
||||
} else {
|
||||
return None;
|
||||
@ -216,14 +220,30 @@ impl<T> RwLock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 获取WRITER守卫并关中断
|
||||
pub fn write_irqsave(&self) -> RwLockWriteGuard<T> {
|
||||
loop {
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
match self.try_write() {
|
||||
Some(mut guard) => {
|
||||
guard.irq_guard = Some(irq_guard);
|
||||
return guard;
|
||||
}
|
||||
None => spin_loop(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 尝试获得UPGRADER守卫
|
||||
pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>> {
|
||||
preempt_disable();
|
||||
ProcessManager::preempt_disable();
|
||||
let r = self.inner_try_upgradeable_read();
|
||||
if r.is_none() {
|
||||
preempt_enable();
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -329,6 +349,7 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
Ok(RwLockWriteGuard {
|
||||
data: unsafe { &mut *inner.data.get() },
|
||||
inner,
|
||||
irq_guard: None,
|
||||
})
|
||||
} else {
|
||||
Err(self)
|
||||
@ -477,7 +498,7 @@ impl<'rwlock, T> Drop for RwLockReadGuard<'rwlock, T> {
|
||||
fn drop(&mut self) {
|
||||
debug_assert!(self.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED) > 0);
|
||||
self.lock.fetch_sub(READER, Ordering::Release);
|
||||
preempt_enable();
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,7 +509,7 @@ impl<'rwlock, T> Drop for RwLockUpgradableGuard<'rwlock, T> {
|
||||
UPGRADED
|
||||
);
|
||||
self.inner.lock.fetch_sub(UPGRADED, Ordering::AcqRel);
|
||||
preempt_enable();
|
||||
ProcessManager::preempt_enable();
|
||||
//这里为啥要AcqRel? Release应该就行了?
|
||||
}
|
||||
}
|
||||
@ -499,7 +520,7 @@ impl<'rwlock, T> Drop for RwLockWriteGuard<'rwlock, T> {
|
||||
self.inner
|
||||
.lock
|
||||
.fetch_and(!(WRITER | UPGRADED), Ordering::Release);
|
||||
|
||||
preempt_enable();
|
||||
self.irq_guard.take();
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
#include <common/semaphore.h>
|
||||
#include <sched/sched.h>
|
||||
#include <process/process.h>
|
||||
|
||||
|
||||
void semaphore_down(semaphore_t *sema)
|
||||
{
|
||||
if (atomic_read(&sema->counter) > 0) // 信号量大于0,资源充足
|
||||
atomic_dec(&sema->counter);
|
||||
else // 资源不足,进程休眠
|
||||
{
|
||||
// 将当前进程加入信号量的等待队列
|
||||
wait_queue_node_t wait;
|
||||
wait_queue_init(&wait, current_pcb);
|
||||
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
|
||||
list_append(&sema->wait_queue.wait_list, &wait.wait_list);
|
||||
|
||||
// 执行调度
|
||||
current_pcb->flags |= PF_NEED_SCHED;
|
||||
sched();
|
||||
}
|
||||
}
|
||||
|
||||
void semaphore_up(semaphore_t *sema)
|
||||
{
|
||||
if (list_empty(&sema->wait_queue.wait_list)) // 没有进程在等待资源
|
||||
{
|
||||
atomic_inc(&sema->counter);
|
||||
}
|
||||
else // 有进程在等待资源,唤醒进程
|
||||
{
|
||||
|
||||
wait_queue_node_t *wq = container_of(list_next(&sema->wait_queue.wait_list), wait_queue_node_t, wait_list);
|
||||
list_del(&wq->wait_list);
|
||||
|
||||
process_wakeup_immediately(wq->pcb);
|
||||
}
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
use core::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use crate::{arch::asm::current::current_pcb, kdebug, syscall::SystemError};
|
||||
use crate::{kdebug, process::ProcessManager, syscall::SystemError};
|
||||
|
||||
use super::wait_queue::WaitQueue;
|
||||
|
||||
@ -47,11 +47,11 @@ impl Semaphore {
|
||||
self.counter.fetch_add(1, Ordering::Release);
|
||||
} else {
|
||||
//尝试唤醒
|
||||
if !self.wait_queue.wakeup(0x_ffff_ffff_ffff_ffff) {
|
||||
if !self.wait_queue.wakeup(None) {
|
||||
//如果唤醒失败,打印错误信息
|
||||
kdebug!(
|
||||
"Semaphore wakeup failed: current pid= {}, semaphore={:?}",
|
||||
current_pcb().pid,
|
||||
ProcessManager::current_pcb().pid().into(),
|
||||
self
|
||||
);
|
||||
}
|
||||
|
@ -1,169 +1,21 @@
|
||||
#![allow(dead_code)]
|
||||
use core::cell::UnsafeCell;
|
||||
use core::hint::spin_loop;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr::read_volatile;
|
||||
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use crate::arch::asm::irqflags::{local_irq_restore, local_irq_save};
|
||||
use crate::arch::interrupt::{cli, sti};
|
||||
|
||||
use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
|
||||
use crate::process::preempt::{preempt_disable, preempt_enable};
|
||||
use crate::arch::CurrentIrqArch;
|
||||
use crate::exception::{InterruptArch, IrqFlagsGuard};
|
||||
use crate::process::ProcessManager;
|
||||
use crate::syscall::SystemError;
|
||||
|
||||
/// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
|
||||
#[inline]
|
||||
pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut usize) {
|
||||
*flags = local_irq_save();
|
||||
unsafe {
|
||||
spin_lock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 恢复rflags以及中断状态并解锁自旋锁
|
||||
#[inline]
|
||||
pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: usize) {
|
||||
unsafe {
|
||||
spin_unlock(lock);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/// 判断一个自旋锁是否已经被加锁
|
||||
#[inline]
|
||||
pub fn spin_is_locked(lock: &spinlock_t) -> bool {
|
||||
let val = unsafe { read_volatile(&lock.lock as *const i8) };
|
||||
|
||||
return if val == 0 { true } else { false };
|
||||
}
|
||||
|
||||
impl Default for spinlock_t {
|
||||
fn default() -> Self {
|
||||
Self { lock: 1 }
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 关闭中断并加锁
|
||||
pub fn spin_lock_irq(lock: *mut spinlock_t) {
|
||||
cli();
|
||||
unsafe {
|
||||
spin_lock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 解锁并开中断
|
||||
pub fn spin_unlock_irq(lock: *mut spinlock_t) {
|
||||
unsafe {
|
||||
spin_unlock(lock);
|
||||
}
|
||||
sti();
|
||||
}
|
||||
|
||||
/// 原始的Spinlock(自旋锁)
|
||||
/// 请注意,这个自旋锁和C的不兼容。
|
||||
///
|
||||
/// @param self.0 这个AtomicBool的值为false时,表示没有被加锁。当它为true时,表示自旋锁已经被上锁。
|
||||
#[derive(Debug)]
|
||||
pub struct RawSpinlock(AtomicBool);
|
||||
|
||||
impl RawSpinlock {
|
||||
/// @brief 初始化自旋锁
|
||||
pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
|
||||
|
||||
/// @brief 加锁
|
||||
pub fn lock(&self) {
|
||||
while !self.try_lock() {}
|
||||
}
|
||||
|
||||
/// @brief 关中断并加锁
|
||||
pub fn lock_irq(&self) {
|
||||
cli();
|
||||
self.lock();
|
||||
}
|
||||
|
||||
/// @brief 尝试加锁
|
||||
/// @return 加锁成功->true
|
||||
/// 加锁失败->false
|
||||
pub fn try_lock(&self) -> bool {
|
||||
// 先增加自旋锁持有计数
|
||||
preempt_disable();
|
||||
|
||||
let res = self
|
||||
.0
|
||||
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_ok();
|
||||
|
||||
// 如果加锁失败恢复自旋锁持有计数
|
||||
if res == false {
|
||||
preempt_enable();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @brief 解锁
|
||||
pub fn unlock(&self) {
|
||||
// 减少自旋锁持有计数
|
||||
preempt_enable();
|
||||
self.0.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
/// 解锁,但是不更改preempt count
|
||||
unsafe fn unlock_no_preempt(&self) {
|
||||
self.0.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
/// @brief 放锁并开中断
|
||||
pub fn unlock_irq(&self) {
|
||||
self.unlock();
|
||||
sti();
|
||||
}
|
||||
|
||||
/// @brief 判断自旋锁是否被上锁
|
||||
///
|
||||
/// @return true 自旋锁被上锁
|
||||
/// @return false 自旋锁处于解锁状态
|
||||
pub fn is_locked(&self) -> bool {
|
||||
return self.0.load(Ordering::Relaxed).into();
|
||||
}
|
||||
|
||||
/// @brief 强制设置自旋锁的状态
|
||||
/// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
|
||||
pub unsafe fn set_value(&mut self, value: bool) {
|
||||
self.0.store(value, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
|
||||
pub fn lock_irqsave(&self, flags: &mut usize) {
|
||||
*flags = local_irq_save();
|
||||
self.lock();
|
||||
}
|
||||
|
||||
/// @brief 恢复rflags以及中断状态并解锁自旋锁
|
||||
pub fn unlock_irqrestore(&self, flags: usize) {
|
||||
self.unlock();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
|
||||
/// @return 加锁成功->true
|
||||
/// 加锁失败->false
|
||||
#[inline(always)]
|
||||
pub fn try_lock_irqsave(&self, flags: &mut usize) -> bool {
|
||||
*flags = local_irq_save();
|
||||
if self.try_lock() {
|
||||
return true;
|
||||
}
|
||||
local_irq_restore(*flags);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// 实现了守卫的SpinLock, 能够支持内部可变性
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct SpinLock<T> {
|
||||
lock: RawSpinlock,
|
||||
lock: AtomicBool,
|
||||
/// 自旋锁保护的数据
|
||||
data: UnsafeCell<T>,
|
||||
}
|
||||
@ -174,7 +26,8 @@ pub struct SpinLock<T> {
|
||||
#[derive(Debug)]
|
||||
pub struct SpinLockGuard<'a, T: 'a> {
|
||||
lock: &'a SpinLock<T>,
|
||||
flag: usize,
|
||||
irq_flag: Option<IrqFlagsGuard>,
|
||||
flags: SpinLockGuardFlags,
|
||||
}
|
||||
|
||||
impl<'a, T: 'a> SpinLockGuard<'a, T> {
|
||||
@ -193,6 +46,12 @@ impl<'a, T: 'a> SpinLockGuard<'a, T> {
|
||||
// We know statically that only we are referencing data
|
||||
unsafe { &mut *this.lock.data.get() }
|
||||
}
|
||||
|
||||
fn unlock_no_preempt(&self) {
|
||||
unsafe {
|
||||
self.lock.force_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 向编译器保证,SpinLock在线程之间是安全的.
|
||||
@ -202,48 +61,89 @@ unsafe impl<T> Sync for SpinLock<T> where T: Send {}
|
||||
impl<T> SpinLock<T> {
|
||||
pub const fn new(value: T) -> Self {
|
||||
return Self {
|
||||
lock: RawSpinlock::INIT,
|
||||
lock: AtomicBool::new(false),
|
||||
data: UnsafeCell::new(value),
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn lock(&self) -> SpinLockGuard<T> {
|
||||
self.lock.lock();
|
||||
// 加锁成功,返回一个守卫
|
||||
return SpinLockGuard {
|
||||
lock: self,
|
||||
flag: 0,
|
||||
};
|
||||
loop {
|
||||
let res = self.try_lock();
|
||||
if res.is_ok() {
|
||||
return res.unwrap();
|
||||
}
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
/// 加锁,但是不更改preempt count
|
||||
#[inline(always)]
|
||||
pub fn lock_no_preempt(&self) -> SpinLockGuard<T> {
|
||||
loop {
|
||||
if let Ok(guard) = self.try_lock_no_preempt() {
|
||||
return guard;
|
||||
}
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
|
||||
let mut flags: usize = 0;
|
||||
|
||||
self.lock.lock_irqsave(&mut flags);
|
||||
// 加锁成功,返回一个守卫
|
||||
return SpinLockGuard {
|
||||
lock: self,
|
||||
flag: flags,
|
||||
};
|
||||
loop {
|
||||
if let Ok(guard) = self.try_lock_irqsave() {
|
||||
return guard;
|
||||
}
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
|
||||
if self.lock.try_lock() {
|
||||
// 先增加自旋锁持有计数
|
||||
ProcessManager::preempt_disable();
|
||||
|
||||
if self.inner_try_lock() {
|
||||
return Ok(SpinLockGuard {
|
||||
lock: self,
|
||||
flag: 0,
|
||||
irq_flag: None,
|
||||
flags: SpinLockGuardFlags::empty(),
|
||||
});
|
||||
}
|
||||
|
||||
// 如果加锁失败恢复自旋锁持有计数
|
||||
ProcessManager::preempt_enable();
|
||||
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
|
||||
fn inner_try_lock(&self) -> bool {
|
||||
let res = self
|
||||
.lock
|
||||
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_ok();
|
||||
return res;
|
||||
}
|
||||
|
||||
pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
|
||||
let mut flags: usize = 0;
|
||||
if self.lock.try_lock_irqsave(&mut flags) {
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::preempt_disable();
|
||||
if self.inner_try_lock() {
|
||||
return Ok(SpinLockGuard {
|
||||
lock: self,
|
||||
flag: flags,
|
||||
irq_flag: Some(irq_guard),
|
||||
flags: SpinLockGuardFlags::empty(),
|
||||
});
|
||||
}
|
||||
ProcessManager::preempt_enable();
|
||||
drop(irq_guard);
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
|
||||
pub fn try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError> {
|
||||
if self.inner_try_lock() {
|
||||
return Ok(SpinLockGuard {
|
||||
lock: self,
|
||||
irq_flag: None,
|
||||
flags: SpinLockGuardFlags::NO_PREEMPT,
|
||||
});
|
||||
}
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
@ -256,7 +156,12 @@ impl<T> SpinLock<T> {
|
||||
/// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
|
||||
/// 如非必要,请不要使用这个函数。
|
||||
pub unsafe fn force_unlock(&self) {
|
||||
self.lock.unlock_no_preempt();
|
||||
self.lock.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
fn unlock(&self) {
|
||||
self.lock.store(false, Ordering::Release);
|
||||
ProcessManager::preempt_enable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,10 +184,19 @@ impl<T> DerefMut for SpinLockGuard<'_, T> {
|
||||
/// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
|
||||
impl<T> Drop for SpinLockGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.flag != 0 {
|
||||
self.lock.lock.unlock_irqrestore(self.flag);
|
||||
if self.flags.contains(SpinLockGuardFlags::NO_PREEMPT) {
|
||||
self.unlock_no_preempt();
|
||||
} else {
|
||||
self.lock.lock.unlock();
|
||||
self.lock.unlock();
|
||||
}
|
||||
// restore irq
|
||||
self.irq_flag.take();
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct SpinLockGuardFlags: u8 {
|
||||
/// 守卫是由“*no_preempt”方法获得的
|
||||
const NO_PREEMPT = (1<<0);
|
||||
}
|
||||
}
|
||||
|
@ -1,84 +0,0 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <mm/slab.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
/**
|
||||
* @brief 初始化等待队列
|
||||
*
|
||||
* @param wait_queue 等待队列
|
||||
* @param pcb pcb
|
||||
*/
|
||||
void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb)
|
||||
{
|
||||
list_init(&wait_queue->wait_list);
|
||||
wait_queue->pcb = pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head)
|
||||
{
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0);
|
||||
wait_queue_init(wait, current_pcb);
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
list_append(&wait_queue_head->wait_list, &wait->wait_list);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head,
|
||||
void *lock)
|
||||
{
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0);
|
||||
wait_queue_init(wait, current_pcb);
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
list_append(&wait_queue_head->wait_list, &wait->wait_list);
|
||||
spin_unlock((spinlock_t *)lock);
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断)
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head)
|
||||
{
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0);
|
||||
wait_queue_init(wait, current_pcb);
|
||||
current_pcb->state = PROC_INTERRUPTIBLE;
|
||||
list_append(&wait_queue_head->wait_list, &wait->wait_list);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程
|
||||
*
|
||||
* @param wait_queue_head
|
||||
* @param state
|
||||
*/
|
||||
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state)
|
||||
{
|
||||
if (list_empty(&wait_queue_head->wait_list))
|
||||
return;
|
||||
wait_queue_node_t *wait = container_of(list_next(&wait_queue_head->wait_list), wait_queue_node_t, wait_list);
|
||||
|
||||
// 符合唤醒条件
|
||||
if (wait->pcb->state & state)
|
||||
{
|
||||
list_del(&wait->wait_list);
|
||||
process_wakeup(wait->pcb);
|
||||
kfree(wait);
|
||||
}
|
||||
}
|
@ -1,36 +1,22 @@
|
||||
#![allow(dead_code)]
|
||||
use alloc::{collections::LinkedList, vec::Vec};
|
||||
use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::{asm::current::current_pcb, sched::sched, CurrentIrqArch},
|
||||
arch::{sched::sched, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
include::bindings::bindings::{
|
||||
process_control_block, process_wakeup, wait_queue_head_t, PROC_INTERRUPTIBLE,
|
||||
PROC_UNINTERRUPTIBLE,
|
||||
},
|
||||
kerror,
|
||||
process::{ProcessControlBlock, ProcessManager, ProcessState},
|
||||
};
|
||||
|
||||
use super::{
|
||||
list::list_init,
|
||||
mutex::MutexGuard,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
impl Default for wait_queue_head_t {
|
||||
fn default() -> Self {
|
||||
let mut x = Self {
|
||||
wait_list: Default::default(),
|
||||
lock: Default::default(),
|
||||
};
|
||||
list_init(&mut x.wait_list);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerWaitQueue {
|
||||
/// 等待队列的链表
|
||||
wait_list: LinkedList<&'static mut process_control_block>,
|
||||
wait_list: LinkedList<Arc<ProcessControlBlock>>,
|
||||
}
|
||||
|
||||
/// 被自旋锁保护的等待队列
|
||||
@ -42,11 +28,12 @@ impl WaitQueue {
|
||||
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
|
||||
pub fn sleep(&self) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_INTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(guard);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
@ -56,8 +43,12 @@ impl WaitQueue {
|
||||
F: FnOnce(),
|
||||
{
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_INTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
f();
|
||||
drop(guard);
|
||||
sched();
|
||||
@ -81,15 +72,32 @@ impl WaitQueue {
|
||||
// 安全检查:确保当前处于中断禁止状态
|
||||
assert!(CurrentIrqArch::is_irq_enabled() == false);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_INTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(guard);
|
||||
}
|
||||
|
||||
pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
|
||||
// 安全检查:确保当前处于中断禁止状态
|
||||
assert!(CurrentIrqArch::is_irq_enabled() == false);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(guard);
|
||||
}
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
|
||||
pub fn sleep_uninterruptible(&self) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(guard);
|
||||
sched();
|
||||
}
|
||||
@ -98,8 +106,12 @@ impl WaitQueue {
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
|
||||
pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_INTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(to_unlock);
|
||||
drop(guard);
|
||||
sched();
|
||||
@ -109,8 +121,12 @@ impl WaitQueue {
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
|
||||
pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_INTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(to_unlock);
|
||||
drop(guard);
|
||||
sched();
|
||||
@ -120,8 +136,12 @@ impl WaitQueue {
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
|
||||
pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
drop(to_unlock);
|
||||
drop(guard);
|
||||
sched();
|
||||
@ -131,8 +151,14 @@ impl WaitQueue {
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
|
||||
pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
|
||||
guard.wait_list.push_back(current_pcb());
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
});
|
||||
drop(irq_guard);
|
||||
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
|
||||
drop(to_unlock);
|
||||
drop(guard);
|
||||
sched();
|
||||
@ -141,51 +167,50 @@ impl WaitQueue {
|
||||
/// @brief 唤醒在队列中等待的第一个进程。
|
||||
/// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
|
||||
///
|
||||
/// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。
|
||||
/// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
|
||||
///
|
||||
/// @return true 成功唤醒进程
|
||||
/// @return false 没有唤醒进程
|
||||
pub fn wakeup(&self, state: u64) -> bool {
|
||||
pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
// 如果队列为空,则返回
|
||||
if guard.wait_list.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
|
||||
if (guard.wait_list.front().unwrap().state & state) != 0 {
|
||||
let to_wakeup = guard.wait_list.pop_front().unwrap();
|
||||
unsafe {
|
||||
process_wakeup(to_wakeup);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if let Some(state) = state {
|
||||
if guard.wait_list.front().unwrap().sched_info().state() != state {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let to_wakeup = guard.wait_list.pop_front().unwrap();
|
||||
let res = ProcessManager::wakeup(&to_wakeup).is_ok();
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @brief 唤醒在队列中,符合条件的所有进程。
|
||||
///
|
||||
/// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。
|
||||
pub fn wakeup_all(&self, state: u64) {
|
||||
/// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
|
||||
pub fn wakeup_all(&self, state: Option<ProcessState>) {
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
|
||||
// 如果队列为空,则返回
|
||||
if guard.wait_list.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut to_push_back: Vec<&mut process_control_block> = Vec::new();
|
||||
let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
|
||||
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
|
||||
while let Some(to_wakeup) = guard.wait_list.pop_front() {
|
||||
if (to_wakeup.state & state) != 0 {
|
||||
unsafe {
|
||||
process_wakeup(to_wakeup);
|
||||
if let Some(state) = state {
|
||||
if to_wakeup.sched_info().state() == state {
|
||||
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
|
||||
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
to_push_back.push(to_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
for to_wakeup in to_push_back {
|
||||
guard.wait_list.push_back(to_wakeup);
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
#include <common/wait_queue.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
/**
|
||||
* @brief 初始化等待队列
|
||||
*
|
||||
* @param wait_queue 等待队列
|
||||
* @param pcb pcb
|
||||
*/
|
||||
void wait_queue_head_init(wait_queue_head_t *wait_queue)
|
||||
{
|
||||
list_init(&wait_queue->wait_list);
|
||||
spin_init(&wait_queue->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait)
|
||||
{
|
||||
BUG_ON(wait->pcb == NULL);
|
||||
|
||||
wait->pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
list_append(&q->wait_list, &wait->wait_list);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock)
|
||||
{
|
||||
BUG_ON(wait->pcb == NULL);
|
||||
|
||||
wait->pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
list_append(&q->wait_list, &wait->wait_list);
|
||||
spin_unlock((spinlock_t *)lock);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait)
|
||||
{
|
||||
BUG_ON(wait->pcb == NULL);
|
||||
|
||||
wait->pcb->state = PROC_INTERRUPTIBLE;
|
||||
list_append(&q->wait_list, &wait->wait_list);
|
||||
|
||||
sched();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
|
||||
*
|
||||
* @param wait_queue_head
|
||||
* @param state
|
||||
*/
|
||||
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state)
|
||||
{
|
||||
if (list_empty(&q->wait_list))
|
||||
return;
|
||||
|
||||
wait_queue_node_t *wait = container_of(list_next(&q->wait_list), wait_queue_node_t, wait_list);
|
||||
|
||||
// 符合唤醒条件
|
||||
if (wait->pcb->state & state)
|
||||
{
|
||||
list_del_init(&wait->wait_list);
|
||||
process_wakeup_immediately(wait->pcb);
|
||||
}
|
||||
}
|
@ -22,14 +22,12 @@
|
||||
#include <filesystem/vfs/VFS.h>
|
||||
|
||||
#include "driver/acpi/acpi.h"
|
||||
#include "driver/disk/ahci/ahci.h"
|
||||
#include "driver/disk/ata.h"
|
||||
#include "driver/keyboard/ps2_keyboard.h"
|
||||
#include "driver/mouse/ps2_mouse.h"
|
||||
#include "driver/multiboot2/multiboot2.h"
|
||||
#include <driver/timers/HPET/HPET.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <driver/video/video.h>
|
||||
#include <time/timer.h>
|
||||
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
@ -38,6 +36,8 @@ extern int rs_device_init();
|
||||
extern int rs_tty_init();
|
||||
extern void rs_softirq_init();
|
||||
extern void rs_mm_init();
|
||||
extern int rs_video_init();
|
||||
extern void rs_kthread_init();
|
||||
|
||||
ul bsp_idt_size, bsp_gdt_size;
|
||||
|
||||
@ -45,6 +45,7 @@ ul bsp_idt_size, bsp_gdt_size;
|
||||
#pragma GCC optimize("O0")
|
||||
struct gdtr gdtp;
|
||||
struct idtr idtp;
|
||||
ul _stack_start;
|
||||
void reload_gdt()
|
||||
{
|
||||
|
||||
@ -72,8 +73,7 @@ void system_initialize()
|
||||
{
|
||||
c_uart_init(COM1, 115200);
|
||||
|
||||
video_init();
|
||||
|
||||
rs_video_init();
|
||||
scm_init();
|
||||
// 重新加载gdt和idt
|
||||
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
||||
@ -81,14 +81,10 @@ void system_initialize()
|
||||
_stack_start = head_stack_start; // 保存init proc的栈基地址(由于之后取消了地址重映射,因此必须在这里重新保存)
|
||||
kdebug("_stack_start=%#018lx", _stack_start);
|
||||
|
||||
load_TR(10); // 加载TR寄存器
|
||||
set_tss64((uint *)&initial_tss[0], _stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr,
|
||||
tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
|
||||
set_current_core_tss(_stack_start, 0);
|
||||
rs_load_current_core_tss();
|
||||
|
||||
cpu_core_info[0].stack_start = _stack_start;
|
||||
cpu_core_info[0].tss_vaddr = (uint64_t)&initial_tss[0];
|
||||
// kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
|
||||
// kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
|
||||
|
||||
// 初始化中断描述符表
|
||||
sys_vector_init();
|
||||
@ -104,34 +100,21 @@ void system_initialize()
|
||||
io_mfence();
|
||||
scm_reinit();
|
||||
rs_textui_init();
|
||||
|
||||
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
|
||||
io_mfence();
|
||||
// =========== 重新设置initial_tss[0]的ist
|
||||
uchar *ptr = (uchar *)kzalloc(STACK_SIZE, 0) + STACK_SIZE;
|
||||
((struct process_control_block *)(ptr - STACK_SIZE))->cpu_id = 0;
|
||||
|
||||
initial_tss[0].ist1 = (ul)ptr;
|
||||
initial_tss[0].ist2 = (ul)ptr;
|
||||
initial_tss[0].ist3 = (ul)ptr;
|
||||
initial_tss[0].ist4 = (ul)ptr;
|
||||
initial_tss[0].ist5 = (ul)ptr;
|
||||
initial_tss[0].ist6 = (ul)ptr;
|
||||
initial_tss[0].ist7 = (ul)ptr;
|
||||
// ===========================
|
||||
|
||||
acpi_init();
|
||||
io_mfence();
|
||||
sched_init();
|
||||
io_mfence();
|
||||
// 初始化中断模块
|
||||
irq_init();
|
||||
rs_process_init();
|
||||
sched_init();
|
||||
|
||||
sti();
|
||||
io_mfence();
|
||||
|
||||
// softirq_init();
|
||||
rs_softirq_init();
|
||||
|
||||
current_pcb->cpu_id = 0;
|
||||
current_pcb->preempt_count = 0;
|
||||
|
||||
syscall_init();
|
||||
io_mfence();
|
||||
|
||||
@ -146,13 +129,9 @@ void system_initialize()
|
||||
vfs_init();
|
||||
rs_device_init();
|
||||
rs_tty_init();
|
||||
io_mfence();
|
||||
// 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块
|
||||
// 并且,因为smp的IDLE进程的初始化依赖于进程管理模块,
|
||||
// 因此必须在进程管理模块初始化完毕后再初始化smp。
|
||||
io_mfence();
|
||||
|
||||
process_init();
|
||||
rs_kthread_init();
|
||||
io_mfence();
|
||||
|
||||
io_mfence();
|
||||
rs_clocksource_boot_finish();
|
||||
@ -169,20 +148,15 @@ void system_initialize()
|
||||
// 这里必须加内存屏障,否则会出错
|
||||
io_mfence();
|
||||
smp_init();
|
||||
|
||||
io_mfence();
|
||||
|
||||
HPET_init();
|
||||
|
||||
io_mfence();
|
||||
HPET_measure_freq();
|
||||
io_mfence();
|
||||
// current_pcb->preempt_count = 0;
|
||||
// kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
|
||||
|
||||
// 启用double buffer
|
||||
// scm_enable_double_buffer(); // 因为时序问题, 该函数调用被移到 initial_kernel_thread
|
||||
io_mfence();
|
||||
|
||||
cli();
|
||||
HPET_enable();
|
||||
|
||||
io_mfence();
|
||||
@ -190,6 +164,9 @@ void system_initialize()
|
||||
|
||||
apic_timer_init();
|
||||
io_mfence();
|
||||
sti();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// 操作系统内核从这里开始执行
|
||||
@ -206,9 +183,6 @@ void Start_Kernel(void)
|
||||
reload_gdt();
|
||||
reload_idt();
|
||||
|
||||
// 重新设置TSS描述符
|
||||
set_tss_descriptor(10, (void *)(&initial_tss[0]));
|
||||
|
||||
mb2_info &= 0xffffffff;
|
||||
mb2_magic &= 0xffffffff;
|
||||
multiboot2_magic = (uint)mb2_magic;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user