mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-25 22:33:22 +00:00
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:
@ -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 => {
|
||||
|
@ -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(¤t_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
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user