Patch fix sched and net lockdep error (#479)

- fix: 修复调度器,软中断,定时器,网络子系统的部分锁的使用不符合锁依赖安全规范的问题
- fix: 修复创建pcb时内核栈爆栈的问题
- 把异常的trap gate改成intr gate

---------

Co-authored-by: GnoCiYeH <heyicong@dragonos.org>
This commit is contained in:
LoGin
2023-12-27 14:27:12 +08:00
committed by GitHub
parent 91e9d4ab55
commit 0d6cf65aa1
28 changed files with 406 additions and 246 deletions

View File

@ -154,8 +154,9 @@ fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
for pid in rd_childen.iter() {
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
if pcb.sched_info().state().is_exited() {
kwo.ret_status = pcb.sched_info().state().exit_code().unwrap() as i32;
let state = pcb.sched_info().inner_lock_read_irqsave().state();
if state.is_exited() {
kwo.ret_status = state.exit_code().unwrap() as i32;
drop(pcb);
unsafe { ProcessManager::release(pid.clone()) };
return Ok(pid.clone().into());
@ -179,7 +180,7 @@ fn do_waitpid(
child_pcb: Arc<ProcessControlBlock>,
kwo: &mut KernelWaitOption,
) -> Option<Result<usize, SystemError>> {
let state = child_pcb.sched_info().state();
let state = child_pcb.sched_info().inner_lock_read_irqsave().state();
// 获取退出码
match state {
ProcessState::Runnable => {

View File

@ -159,6 +159,7 @@ impl ProcessManager {
let new_kstack: KernelStack = KernelStack::new()?;
let name = current_pcb.basic().name().to_string();
let pcb = ProcessControlBlock::new(name, new_kstack);
let mut args = KernelCloneArgs::new();
@ -166,7 +167,6 @@ impl ProcessManager {
args.exit_signal = Signal::SIGCHLD;
Self::copy_process(&current_pcb, &pcb, args, current_trapframe)?;
ProcessManager::add_pcb(pcb.clone());
// 向procfs注册进程
@ -232,7 +232,7 @@ impl ProcessManager {
unsafe { new_pcb.basic_mut().set_user_vm(Some(old_address_space)) };
return Ok(());
}
let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| {
let new_address_space = old_address_space.write_irqsave().try_clone().unwrap_or_else(|e| {
panic!(
"copy_mm: Failed to clone address space of current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), new_pcb.pid(), e
@ -242,6 +242,7 @@ impl ProcessManager {
return Ok(());
}
#[inline(never)]
fn copy_files(
clone_flags: &CloneFlags,
current_pcb: &Arc<ProcessControlBlock>,
@ -274,7 +275,8 @@ impl ProcessManager {
}
if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
(*new_pcb.sig_struct()).handlers = current_pcb.sig_struct().handlers.clone();
(*new_pcb.sig_struct_irqsave()).handlers =
current_pcb.sig_struct_irqsave().handlers.clone();
}
return Ok(());
}
@ -288,8 +290,8 @@ impl ProcessManager {
/// ## 参数
///
/// - clone_flags 标志位
/// - des_pcb 目标pcb
/// - src_pcb 拷贝源pcb
/// - current_pcb 拷贝源pcb
/// - pcb 目标pcb
///
/// ## return
/// - 发生错误时返回Err(SystemError)
@ -350,7 +352,7 @@ impl ProcessManager {
// 克隆架构相关
let guard = current_pcb.arch_info_irqsave();
pcb.arch_info().clone_from(&guard);
unsafe { pcb.arch_info().clone_from(&guard) };
drop(guard);
// 为内核线程设置WorkerPrivate

View File

@ -291,7 +291,6 @@ impl KernelThreadMechanism {
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
)
.expect("Failed to create kthread daemon");
let pcb = ProcessManager::find(kthreadd_pid).unwrap();
ProcessManager::wakeup(&pcb).expect("Failed to wakeup kthread daemon");
unsafe {
@ -379,7 +378,7 @@ impl KernelThreadMechanism {
// 忙等目标内核线程退出
// todo: 使用completion机制优化这里
loop {
if let ProcessState::Exited(code) = pcb.sched_info().state() {
if let ProcessState::Exited(code) = pcb.sched_info().inner_lock_read_irqsave().state() {
return Ok(code);
}
spin_loop();

View File

@ -112,7 +112,7 @@ impl ProcessManager {
compiler_fence(Ordering::SeqCst);
};
ALL_PROCESS.lock().replace(HashMap::new());
ALL_PROCESS.lock_irqsave().replace(HashMap::new());
Self::arch_init();
kdebug!("process arch init done.");
Self::init_idle();
@ -164,7 +164,7 @@ impl ProcessManager {
///
/// 如果找到了对应的进程那么返回该进程的pcb否则返回None
pub fn find(pid: Pid) -> Option<Arc<ProcessControlBlock>> {
return ALL_PROCESS.lock().as_ref()?.get(&pid).cloned();
return ALL_PROCESS.lock_irqsave().as_ref()?.get(&pid).cloned();
}
/// 向系统中添加一个进程的pcb
@ -178,7 +178,7 @@ impl ProcessManager {
/// 无
pub fn add_pcb(pcb: Arc<ProcessControlBlock>) {
ALL_PROCESS
.lock()
.lock_irqsave()
.as_mut()
.unwrap()
.insert(pcb.pid(), pcb.clone());
@ -187,9 +187,9 @@ impl ProcessManager {
/// 唤醒一个进程
pub fn wakeup(pcb: &Arc<ProcessControlBlock>) -> Result<(), SystemError> {
let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let state = pcb.sched_info().state();
let state = pcb.sched_info().inner_lock_read_irqsave().state();
if state.is_blocked() {
let mut writer: RwLockWriteGuard<'_, ProcessSchedulerInfo> = pcb.sched_info_mut();
let mut writer = pcb.sched_info().inner_lock_write_irqsave();
let state = writer.state();
if state.is_blocked() {
writer.set_state(ProcessState::Runnable);
@ -213,9 +213,9 @@ impl ProcessManager {
/// 唤醒暂停的进程
pub fn wakeup_stop(pcb: &Arc<ProcessControlBlock>) -> Result<(), SystemError> {
let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let state = pcb.sched_info().state();
let state = pcb.sched_info().inner_lock_read_irqsave().state();
if let ProcessState::Stopped = state {
let mut writer = pcb.sched_info_mut();
let mut writer = pcb.sched_info().inner_lock_write_irqsave();
let state = writer.state();
if let ProcessState::Stopped = state {
writer.set_state(ProcessState::Runnable);
@ -251,7 +251,7 @@ impl ProcessManager {
);
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info_mut_irqsave();
let mut writer = pcb.sched_info().inner_lock_write_irqsave();
if !matches!(writer.state(), ProcessState::Exited(_)) {
writer.set_state(ProcessState::Blocked(interruptable));
pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
@ -276,7 +276,7 @@ impl ProcessManager {
);
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info_mut_irqsave();
let mut writer = pcb.sched_info().inner_lock_write_irqsave();
if !matches!(writer.state(), ProcessState::Exited(_)) {
writer.set_state(ProcessState::Stopped);
pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
@ -321,10 +321,10 @@ impl ProcessManager {
/// - `exit_code` : 进程的退出码
pub fn exit(exit_code: usize) -> ! {
// 关中断
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
unsafe { CurrentIrqArch::interrupt_disable() };
let pcb = ProcessManager::current_pcb();
pcb.sched_info
.write()
.inner_lock_write_irqsave()
.set_state(ProcessState::Exited(exit_code));
pcb.wait_queue.wakeup(Some(ProcessState::Blocked(true)));
@ -350,7 +350,7 @@ impl ProcessManager {
unsafe { pcb.basic_mut().set_user_vm(None) };
drop(pcb);
ProcessManager::exit_notify();
drop(irq_guard);
unsafe { CurrentIrqArch::interrupt_enable() };
sched();
loop {}
@ -373,7 +373,7 @@ impl ProcessManager {
// panic!()
// }
ALL_PROCESS.lock().as_mut().unwrap().remove(&pid);
ALL_PROCESS.lock_irqsave().as_mut().unwrap().remove(&pid);
}
}
@ -544,7 +544,7 @@ pub struct ProcessControlBlock {
syscall_stack: RwLock<KernelStack>,
/// 与调度相关的信息
sched_info: RwLock<ProcessSchedulerInfo>,
sched_info: ProcessSchedulerInfo,
/// 与处理器架构相关的信息
arch_info: SpinLock<ArchPCBInfo>,
/// 与信号处理相关的信息(似乎可以是无锁的)
@ -592,6 +592,7 @@ impl ProcessControlBlock {
return Self::do_create_pcb(name, kstack, true);
}
#[inline(never)]
fn do_create_pcb(name: String, kstack: KernelStack, is_idle: bool) -> Arc<Self> {
let (pid, ppid, cwd) = if is_idle {
(Pid(0), Pid(0), "/".to_string())
@ -624,7 +625,7 @@ impl ProcessControlBlock {
sched_info,
arch_info,
sig_info: RwLock::new(ProcessSignalInfo::default()),
sig_struct: SpinLock::new(SignalStruct::default()),
sig_struct: SpinLock::new(SignalStruct::new()),
exit_signal: AtomicSignal::new(Signal::SIGCHLD),
parent_pcb: RwLock::new(ppcb.clone()),
real_parent_pcb: RwLock::new(ppcb),
@ -657,7 +658,7 @@ impl ProcessControlBlock {
// 将当前pcb加入父进程的子进程哈希表中
if pcb.pid() > Pid(1) {
if let Some(ppcb_arc) = pcb.parent_pcb.read().upgrade() {
let mut children = ppcb_arc.children.write();
let mut children = ppcb_arc.children.write_irqsave();
children.push(pcb.pid());
} else {
panic!("parent pcb is None");
@ -702,6 +703,8 @@ impl ProcessControlBlock {
return self.flags.get_mut();
}
/// 请注意,这个值能在中断上下文中读取,但不能被中断上下文修改
/// 否则会导致死锁
#[inline(always)]
pub fn basic(&self) -> RwLockReadGuard<ProcessBasicInfo> {
return self.basic.read();
@ -714,19 +717,28 @@ impl ProcessControlBlock {
#[inline(always)]
pub fn basic_mut(&self) -> RwLockWriteGuard<ProcessBasicInfo> {
return self.basic.write();
}
#[inline(always)]
pub fn arch_info(&self) -> SpinLockGuard<ArchPCBInfo> {
return self.arch_info.lock();
return self.basic.write_irqsave();
}
/// # 获取arch info的锁同时关闭中断
#[inline(always)]
pub fn arch_info_irqsave(&self) -> SpinLockGuard<ArchPCBInfo> {
return self.arch_info.lock_irqsave();
}
/// # 获取arch info的锁但是不关闭中断
///
/// 由于arch info在进程切换的时候会使用到
/// 因此在中断上下文外获取arch info 而不irqsave是不安全的.
///
/// 只能在以下情况下使用这个函数:
/// - 在中断上下文中中断已经禁用获取arch info的锁。
/// - 刚刚创建新的pcb
#[inline(always)]
pub unsafe fn arch_info(&self) -> SpinLockGuard<ArchPCBInfo> {
return self.arch_info.lock();
}
#[inline(always)]
pub fn kernel_stack(&self) -> RwLockReadGuard<KernelStack> {
return self.kernel_stack.read();
@ -739,48 +751,8 @@ impl ProcessControlBlock {
}
#[inline(always)]
pub fn sched_info(&self) -> RwLockReadGuard<ProcessSchedulerInfo> {
return self.sched_info.read();
}
#[inline(always)]
pub fn try_sched_info(&self, times: u8) -> Option<RwLockReadGuard<ProcessSchedulerInfo>> {
for _ in 0..times {
if let Some(r) = self.sched_info.try_read() {
return Some(r);
}
}
return None;
}
#[allow(dead_code)]
#[inline(always)]
pub fn sched_info_irqsave(&self) -> RwLockReadGuard<ProcessSchedulerInfo> {
return self.sched_info.read_irqsave();
}
#[inline(always)]
pub fn sched_info_try_upgradeable_irqsave(
&self,
times: u8,
) -> Option<RwLockUpgradableGuard<ProcessSchedulerInfo>> {
for _ in 0..times {
if let Some(r) = self.sched_info.try_upgradeable_read_irqsave() {
return Some(r);
}
}
return None;
}
#[inline(always)]
pub fn sched_info_mut(&self) -> RwLockWriteGuard<ProcessSchedulerInfo> {
return self.sched_info.write();
}
#[inline(always)]
pub fn sched_info_mut_irqsave(&self) -> RwLockWriteGuard<ProcessSchedulerInfo> {
return self.sched_info.write_irqsave();
pub fn sched_info(&self) -> &ProcessSchedulerInfo {
return &self.sched_info;
}
#[inline(always)]
@ -877,7 +849,7 @@ impl ProcessControlBlock {
}
pub fn sig_info_mut(&self) -> RwLockWriteGuard<ProcessSignalInfo> {
self.sig_info.write()
self.sig_info.write_irqsave()
}
pub fn try_siginfo_mut(&self, times: u8) -> Option<RwLockWriteGuard<ProcessSignalInfo>> {
@ -904,7 +876,7 @@ impl ProcessControlBlock {
return None;
}
pub fn sig_struct_irq(&self) -> SpinLockGuard<SignalStruct> {
pub fn sig_struct_irqsave(&self) -> SpinLockGuard<SignalStruct> {
self.sig_struct.lock_irqsave()
}
}
@ -971,6 +943,7 @@ pub struct ProcessBasicInfo {
}
impl ProcessBasicInfo {
#[inline(never)]
pub fn new(
pgid: Pid,
ppid: Pid,
@ -1036,11 +1009,7 @@ pub struct ProcessSchedulerInfo {
/// 如果当前进程等待被迁移到另一个cpu核心上也就是flags中的PF_NEED_MIGRATE被置位
/// 该字段存储要被迁移到的目标处理器核心号
migrate_to: AtomicI32,
/// 当前进程的状态
state: ProcessState,
/// 进程的调度策略
sched_policy: SchedPolicy,
inner_locked: RwLock<InnerSchedInfo>,
/// 进程的调度优先级
priority: SchedPriority,
/// 当前进程的虚拟运行时间
@ -1049,21 +1018,46 @@ pub struct ProcessSchedulerInfo {
rt_time_slice: AtomicIsize,
}
#[derive(Debug)]
pub struct InnerSchedInfo {
/// 当前进程的状态
state: ProcessState,
/// 进程的调度策略
sched_policy: SchedPolicy,
}
impl InnerSchedInfo {
pub fn state(&self) -> ProcessState {
return self.state;
}
pub fn set_state(&mut self, state: ProcessState) {
self.state = state;
}
pub fn policy(&self) -> SchedPolicy {
return self.sched_policy;
}
}
impl ProcessSchedulerInfo {
pub fn new(on_cpu: Option<u32>) -> RwLock<Self> {
#[inline(never)]
pub fn new(on_cpu: Option<u32>) -> Self {
let cpu_id = match on_cpu {
Some(cpu_id) => cpu_id as i32,
None => -1,
};
return RwLock::new(Self {
return Self {
on_cpu: AtomicI32::new(cpu_id),
migrate_to: AtomicI32::new(-1),
state: ProcessState::Blocked(false),
sched_policy: SchedPolicy::CFS,
inner_locked: RwLock::new(InnerSchedInfo {
state: ProcessState::Blocked(false),
sched_policy: SchedPolicy::CFS,
}),
virtual_runtime: AtomicIsize::new(0),
rt_time_slice: AtomicIsize::new(0),
priority: SchedPriority::new(100).unwrap(),
});
};
}
pub fn on_cpu(&self) -> Option<u32> {
@ -1100,16 +1094,38 @@ impl ProcessSchedulerInfo {
}
}
pub fn state(&self) -> ProcessState {
return self.state;
pub fn inner_lock_write_irqsave(&self) -> RwLockWriteGuard<InnerSchedInfo> {
return self.inner_locked.write_irqsave();
}
pub fn set_state(&mut self, state: ProcessState) {
self.state = state;
pub fn inner_lock_read_irqsave(&self) -> RwLockReadGuard<InnerSchedInfo> {
return self.inner_locked.read_irqsave();
}
pub fn policy(&self) -> SchedPolicy {
return self.sched_policy;
pub fn inner_lock_try_read_irqsave(
&self,
times: u8,
) -> Option<RwLockReadGuard<InnerSchedInfo>> {
for _ in 0..times {
if let Some(r) = self.inner_locked.try_read_irqsave() {
return Some(r);
}
}
return None;
}
pub fn inner_lock_try_upgradable_read_irqsave(
&self,
times: u8,
) -> Option<RwLockUpgradableGuard<InnerSchedInfo>> {
for _ in 0..times {
if let Some(r) = self.inner_locked.try_upgradeable_read_irqsave() {
return Some(r);
}
}
return None;
}
pub fn virtual_runtime(&self) -> isize {