fix: 修复wait4系统调用部分语义与Linux不一致的问题 (#1080)

* fix: 修复wait4系统调用部分语义与Linux不一致的问题

解决wait不住/wait之后卡死的bug

---------

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-01-01 14:25:46 +08:00 committed by GitHub
parent 57b20d2326
commit bcf0382763
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 264 additions and 143 deletions

View File

@ -65,7 +65,7 @@ impl TtyJobCtrlManager {
ProcessManager::current_pcb() ProcessManager::current_pcb()
.flags() .flags()
.insert(ProcessFlags::HAS_PENDING_SIGNAL); .insert(ProcessFlags::HAS_PENDING_SIGNAL);
log::debug!("job_ctrl_ioctl: kill. pgid: {pgid}, tty_pgid: {tty_pgid:?}");
return Err(SystemError::ERESTARTSYS); return Err(SystemError::ERESTARTSYS);
} }
} }

View File

@ -82,6 +82,21 @@ impl EventFdInode {
let count = self.eventfd.lock().count; let count = self.eventfd.lock().count;
return count > 0; return count > 0;
} }
fn do_poll(
&self,
_private_data: &FilePrivateData,
self_guard: &SpinLockGuard<'_, EventFd>,
) -> Result<usize, SystemError> {
let mut events = EPollEventType::empty();
if self_guard.count != 0 {
events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM;
}
if self_guard.count != u64::MAX {
events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
}
return Ok(events.bits() as usize);
}
} }
impl IndexNode for EventFdInode { impl IndexNode for EventFdInode {
@ -125,6 +140,11 @@ impl IndexNode for EventFdInode {
} }
drop(lock_efd); drop(lock_efd);
if ProcessManager::current_pcb().has_pending_signal_fast() {
return Err(SystemError::ERESTARTSYS);
}
let r = wq_wait_event_interruptible!(self.wait_queue, self.readable(), {}); let r = wq_wait_event_interruptible!(self.wait_queue, self.readable(), {});
if r.is_err() { if r.is_err() {
ProcessManager::current_pcb() ProcessManager::current_pcb()
@ -138,7 +158,7 @@ impl IndexNode for EventFdInode {
} }
let mut val = lock_efd.count; let mut val = lock_efd.count;
let mut eventfd = self.eventfd.lock(); let mut eventfd = lock_efd;
if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) { if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) {
eventfd.count -= 1; eventfd.count -= 1;
val = 1; val = 1;
@ -147,8 +167,9 @@ impl IndexNode for EventFdInode {
} }
let val_bytes = val.to_ne_bytes(); let val_bytes = val.to_ne_bytes();
buf[..8].copy_from_slice(&val_bytes); buf[..8].copy_from_slice(&val_bytes);
let pollflag = EPollEventType::from_bits_truncate(self.do_poll(&data, &eventfd)? as u32);
drop(eventfd);
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?; EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
@ -178,6 +199,9 @@ impl IndexNode for EventFdInode {
return Err(SystemError::EINVAL); return Err(SystemError::EINVAL);
} }
loop { loop {
if ProcessManager::current_pcb().has_pending_signal() {
return Err(SystemError::ERESTARTSYS);
}
let eventfd = self.eventfd.lock(); let eventfd = self.eventfd.lock();
if u64::MAX - eventfd.count > val { if u64::MAX - eventfd.count > val {
break; break;
@ -189,13 +213,17 @@ impl IndexNode for EventFdInode {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
} }
drop(eventfd); drop(eventfd);
self.wait_queue.sleep(); self.wait_queue.sleep().ok();
} }
let mut eventfd = self.eventfd.lock(); let mut eventfd = self.eventfd.lock();
eventfd.count += val; eventfd.count += val;
drop(eventfd);
self.wait_queue.wakeup_all(None); self.wait_queue.wakeup_all(None);
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32); let eventfd = self.eventfd.lock();
let pollflag = EPollEventType::from_bits_truncate(self.do_poll(&data, &eventfd)? as u32);
drop(eventfd);
// 唤醒epoll中等待的进程 // 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?; EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
return Ok(8); return Ok(8);
@ -206,14 +234,8 @@ impl IndexNode for EventFdInode {
/// - 如果 counter 的值大于 0 ,那么 fd 的状态就是可读的 /// - 如果 counter 的值大于 0 ,那么 fd 的状态就是可读的
/// - 如果能无阻塞地写入一个至少为 1 的值,那么 fd 的状态就是可写的 /// - 如果能无阻塞地写入一个至少为 1 的值,那么 fd 的状态就是可写的
fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> { fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
let mut events = EPollEventType::empty(); let self_guard = self.eventfd.lock();
if self.eventfd.lock().count != 0 { self.do_poll(_private_data, &self_guard)
events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM;
}
if self.eventfd.lock().count != u64::MAX {
events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
}
return Ok(events.bits() as usize);
} }
fn metadata(&self) -> Result<Metadata, SystemError> { fn metadata(&self) -> Result<Metadata, SystemError> {

View File

@ -37,7 +37,7 @@ impl Semaphore {
fn down(&self) { fn down(&self) {
if self.counter.fetch_sub(1, Ordering::Release) <= 0 { if self.counter.fetch_sub(1, Ordering::Release) <= 0 {
self.counter.fetch_add(1, Ordering::Relaxed); self.counter.fetch_add(1, Ordering::Relaxed);
self.wait_queue.sleep(); self.wait_queue.sleep().ok();
//资源不充足,信号量<=0, 此时进程睡眠 //资源不充足,信号量<=0, 此时进程睡眠
} }
} }

View File

@ -1,7 +1,7 @@
// #![allow(dead_code)] // #![allow(dead_code)]
use core::intrinsics::unlikely; use core::intrinsics::unlikely;
use alloc::{collections::LinkedList, sync::Arc, vec::Vec}; use alloc::{collections::VecDeque, sync::Arc, vec::Vec};
use log::{error, warn}; use log::{error, warn};
use system_error::SystemError; use system_error::SystemError;
@ -19,23 +19,40 @@ use super::{
#[derive(Debug)] #[derive(Debug)]
struct InnerWaitQueue { struct InnerWaitQueue {
/// 等待队列是否已经死亡, 如果已经死亡, 则不能再添加新的等待进程
dead: bool,
/// 等待队列的链表 /// 等待队列的链表
wait_list: LinkedList<Arc<ProcessControlBlock>>, wait_list: VecDeque<Arc<ProcessControlBlock>>,
} }
/// 被自旋锁保护的等待队列 /// 被自旋锁保护的等待队列
#[derive(Debug)] #[derive(Debug)]
pub struct WaitQueue(SpinLock<InnerWaitQueue>); pub struct WaitQueue {
inner: SpinLock<InnerWaitQueue>,
}
#[allow(dead_code)] #[allow(dead_code)]
impl WaitQueue { impl WaitQueue {
pub const fn default() -> Self { pub const fn default() -> Self {
WaitQueue(SpinLock::new(InnerWaitQueue::INIT)) WaitQueue {
inner: SpinLock::new(InnerWaitQueue::INIT),
}
}
fn inner_irqsave(&self) -> SpinLockGuard<InnerWaitQueue> {
self.inner.lock_irqsave()
}
fn inner(&self) -> SpinLockGuard<InnerWaitQueue> {
self.inner.lock()
} }
pub fn prepare_to_wait_event(&self, interruptible: bool) -> Result<(), SystemError> { pub fn prepare_to_wait_event(&self, interruptible: bool) -> Result<(), SystemError> {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let pcb = ProcessManager::current_pcb(); let pcb = ProcessManager::current_pcb();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
if Signal::signal_pending_state(interruptible, false, &pcb) { if Signal::signal_pending_state(interruptible, false, &pcb) {
return Err(SystemError::ERESTARTSYS); return Err(SystemError::ERESTARTSYS);
} else { } else {
@ -51,7 +68,7 @@ impl WaitQueue {
pub fn finish_wait(&self) { pub fn finish_wait(&self) {
let pcb = ProcessManager::current_pcb(); let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info().inner_lock_write_irqsave(); let mut writer = pcb.sched_info().inner_lock_write_irqsave();
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
writer.set_state(ProcessState::Runnable); writer.set_state(ProcessState::Runnable);
writer.set_wakeup(); writer.set_wakeup();
@ -62,34 +79,49 @@ impl WaitQueue {
} }
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
pub fn sleep(&self) { pub fn sleep(&self) -> Result<(), SystemError> {
before_sleep_check(0); before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(true).unwrap_or_else(|e| { ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
Ok(())
}
/// 标记等待队列已经死亡,不能再添加新的等待进程
pub fn mark_dead(&self) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
guard.dead = true;
drop(guard);
} }
/// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前执行f函数闭包 /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前执行f函数闭包
pub fn sleep_with_func<F>(&self, f: F) pub fn sleep_with_func<F>(&self, f: F) -> Result<(), SystemError>
where where
F: FnOnce(), F: FnOnce(),
{ {
before_sleep_check(0); before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(true).unwrap_or_else(|e| { ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
drop(irq_guard);
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
f(); f();
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
Ok(())
} }
/// @brief 让当前进程在等待队列上进行等待. 但是在释放waitqueue的锁之后不会调用调度函数。 /// @brief 让当前进程在等待队列上进行等待. 但是在释放waitqueue的锁之后不会调用调度函数。
@ -106,80 +138,95 @@ impl WaitQueue {
/// ///
/// 由于sleep_without_schedule不会调用调度函数因此如果开发者忘记在执行本函数之后手动调用调度函数 /// 由于sleep_without_schedule不会调用调度函数因此如果开发者忘记在执行本函数之后手动调用调度函数
/// 由于时钟中断到来或者其他cpu kick了当前cpu可能会导致一些未定义的行为。 /// 由于时钟中断到来或者其他cpu kick了当前cpu可能会导致一些未定义的行为。
pub unsafe fn sleep_without_schedule(&self) { pub unsafe fn sleep_without_schedule(&self) -> Result<(), SystemError> {
before_sleep_check(1); before_sleep_check(1);
// 安全检查:确保当前处于中断禁止状态 // 安全检查:确保当前处于中断禁止状态
assert!(!CurrentIrqArch::is_irq_enabled()); assert!(!CurrentIrqArch::is_irq_enabled());
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(true).unwrap_or_else(|e| { ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard); drop(guard);
Ok(())
} }
pub unsafe fn sleep_without_schedule_uninterruptible(&self) { pub unsafe fn sleep_without_schedule_uninterruptible(&self) -> Result<(), SystemError> {
before_sleep_check(1); before_sleep_check(1);
// 安全检查:确保当前处于中断禁止状态 // 安全检查:确保当前处于中断禁止状态
assert!(!CurrentIrqArch::is_irq_enabled()); assert!(!CurrentIrqArch::is_irq_enabled());
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(false).unwrap_or_else(|e| { ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard); drop(guard);
Ok(())
} }
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断 /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
pub fn sleep_uninterruptible(&self) { pub fn sleep_uninterruptible(&self) -> Result<(), SystemError> {
before_sleep_check(0); before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(false).unwrap_or_else(|e| { ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
drop(irq_guard);
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
Ok(())
} }
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
/// 在当前进程的pcb加入队列后解锁指定的自旋锁。 /// 在当前进程的pcb加入队列后解锁指定的自旋锁。
pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) -> Result<(), SystemError> {
before_sleep_check(1); before_sleep_check(1);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(true).unwrap_or_else(|e| { ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
drop(irq_guard);
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock); drop(to_unlock);
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
Ok(())
} }
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
/// 在当前进程的pcb加入队列后解锁指定的Mutex。 /// 在当前进程的pcb加入队列后解锁指定的Mutex。
pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) -> Result<(), SystemError> {
before_sleep_check(1); before_sleep_check(1);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
ProcessManager::mark_sleep(true).unwrap_or_else(|e| { ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
}); });
drop(irq_guard);
guard.wait_list.push_back(ProcessManager::current_pcb()); guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock); drop(to_unlock);
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
Ok(())
} }
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
/// 在当前进程的pcb加入队列后解锁指定的自旋锁。 /// 在当前进程的pcb加入队列后解锁指定的自旋锁。
pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
before_sleep_check(1); before_sleep_check(1);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(false).unwrap_or_else(|e| { ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
@ -195,7 +242,7 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后解锁指定的Mutex。 /// 在当前进程的pcb加入队列后解锁指定的Mutex。
pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
before_sleep_check(1); before_sleep_check(1);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(false).unwrap_or_else(|e| { ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e); panic!("sleep error: {:?}", e);
@ -217,7 +264,7 @@ impl WaitQueue {
/// @return true 成功唤醒进程 /// @return true 成功唤醒进程
/// @return false 没有唤醒进程 /// @return false 没有唤醒进程
pub fn wakeup(&self, state: Option<ProcessState>) -> bool { pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
// 如果队列为空,则返回 // 如果队列为空,则返回
if guard.wait_list.is_empty() { if guard.wait_list.is_empty() {
return false; return false;
@ -246,7 +293,7 @@ impl WaitQueue {
/// ///
/// @param state 用于判断的state如果一个进程与这个state相同或者为None(表示不进行这个判断),则唤醒这个进程。 /// @param state 用于判断的state如果一个进程与这个state相同或者为None(表示不进行这个判断),则唤醒这个进程。
pub fn wakeup_all(&self, state: Option<ProcessState>) { pub fn wakeup_all(&self, state: Option<ProcessState>) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
// 如果队列为空,则返回 // 如果队列为空,则返回
if guard.wait_list.is_empty() { if guard.wait_list.is_empty() {
return; return;
@ -281,14 +328,19 @@ impl WaitQueue {
/// @brief 获得当前等待队列的大小 /// @brief 获得当前等待队列的大小
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
return self.0.lock().wait_list.len(); return self.inner_irqsave().wait_list.len();
} }
} }
impl InnerWaitQueue { impl InnerWaitQueue {
pub const INIT: InnerWaitQueue = InnerWaitQueue { pub const INIT: InnerWaitQueue = InnerWaitQueue {
wait_list: LinkedList::new(), wait_list: VecDeque::new(),
dead: false,
}; };
pub fn can_sleep(&self) -> bool {
return !self.dead;
}
} }
fn before_sleep_check(max_preempt: usize) { fn before_sleep_check(max_preempt: usize) {

View File

@ -476,8 +476,8 @@ impl EventPoll {
} }
// 如果有未处理的信号则返回错误 // 如果有未处理的信号则返回错误
if current_pcb.sig_info_irqsave().sig_pending().signal().bits() != 0 { if current_pcb.has_pending_signal_fast() {
return Err(SystemError::EINTR); return Err(SystemError::ERESTARTSYS);
} }
// 还未等待到事件发生,则睡眠 // 还未等待到事件发生,则睡眠
@ -488,12 +488,18 @@ impl EventPoll {
let jiffies = next_n_us_timer_jiffies( let jiffies = next_n_us_timer_jiffies(
(timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64, (timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64,
); );
let inner = Timer::new(handle, jiffies); let inner: Arc<Timer> = Timer::new(handle, jiffies);
inner.activate(); inner.activate();
timer = Some(inner); timer = Some(inner);
} }
let guard = epoll.0.lock_irqsave(); let guard = epoll.0.lock_irqsave();
unsafe { guard.epoll_wq.sleep_without_schedule() }; // 睡眠,等待事件发生
// 如果wq已经dead则直接返回错误
unsafe { guard.epoll_wq.sleep_without_schedule() }.inspect_err(|_| {
if let Some(timer) = timer.as_ref() {
timer.cancel();
}
})?;
drop(guard); drop(guard);
schedule(SchedMode::SM_NONE); schedule(SchedMode::SM_NONE);
// 被唤醒后,检查是否有事件可读 // 被唤醒后,检查是否有事件可读

View File

@ -5,13 +5,10 @@ use log::warn;
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
arch::{ arch::ipc::signal::{SigChildCode, Signal},
ipc::signal::{SigChildCode, Signal},
CurrentIrqArch,
},
exception::InterruptArch,
sched::{schedule, SchedMode}, sched::{schedule, SchedMode},
syscall::user_access::UserBufferWriter, syscall::user_access::UserBufferWriter,
time::{sleep::nanosleep, Duration},
}; };
use super::{ use super::{
@ -108,33 +105,37 @@ pub fn kernel_wait4(
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/exit.c#1573 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/exit.c#1573
fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> { fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
let mut retval: Result<usize, SystemError>; let mut retval: Result<usize, SystemError>;
// todo: 在signal struct里面增加等待队列并在这里初始化子进程退出的回调使得子进程退出时能唤醒当前进程。 let mut tmp_child_pcb: Option<Arc<ProcessControlBlock>> = None;
macro_rules! notask {
loop { ($outer: lifetime) => {
kwo.no_task_error = Some(SystemError::ECHILD);
let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
if let Some(err) = &kwo.no_task_error { if let Some(err) = &kwo.no_task_error {
retval = Err(err.clone()); retval = Err(err.clone());
} else { } else {
retval = Ok(0); retval = Ok(0);
} }
if !kwo.options.contains(WaitOption::WNOHANG) { if retval.is_err() && !kwo.options.contains(WaitOption::WNOHANG) {
retval = Err(SystemError::ERESTARTSYS); retval = Err(SystemError::ERESTARTSYS);
if !ProcessManager::current_pcb() if !ProcessManager::current_pcb().has_pending_signal_fast() {
.sig_info_irqsave() schedule(SchedMode::SM_PREEMPT);
.sig_pending()
.has_pending()
{
// todo: 增加子进程退出的回调后这里可以直接等待在自身的child_wait等待队列上。 // todo: 增加子进程退出的回调后这里可以直接等待在自身的child_wait等待队列上。
continue; continue;
} else { } else {
break; break $outer;
} }
} else { } else {
break; break $outer;
} }
};
}
// todo: 在signal struct里面增加等待队列并在这里初始化子进程退出的回调使得子进程退出时能唤醒当前进程。
'outer: loop {
kwo.no_task_error = Some(SystemError::ECHILD);
let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
notask!('outer);
} }
if kwo.pid_type == PidType::PID { if kwo.pid_type == PidType::PID {
@ -143,37 +144,62 @@ fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
let child_weak = Arc::downgrade(&child_pcb); let child_weak = Arc::downgrade(&child_pcb);
let r = do_waitpid(child_pcb, kwo); let r = do_waitpid(child_pcb, kwo);
if let Some(r) = r { if let Some(r) = r {
return r; retval = r;
} else { break 'outer;
child_weak.upgrade().unwrap().wait_queue.sleep(); } else if let Err(SystemError::ESRCH) = child_weak.upgrade().unwrap().wait_queue.sleep()
{
// log::debug!("do_wait: child_pcb sleep failed");
continue;
} }
} else if kwo.pid_type == PidType::MAX { } else if kwo.pid_type == PidType::MAX {
// 等待任意子进程 // 等待任意子进程
// todo: 这里有问题!如果正在for循环的过程中子进程退出了可能会导致父进程永远等待。 // todo: 这里有问题!应当让当前进程sleep到自身的child_wait等待队列上这样才高效。还没实现
let current_pcb = ProcessManager::current_pcb(); let current_pcb = ProcessManager::current_pcb();
loop {
let rd_childen = current_pcb.children.read(); let rd_childen = current_pcb.children.read();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; if rd_childen.is_empty() {
break;
}
for pid in rd_childen.iter() { for pid in rd_childen.iter() {
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?; let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
let state = pcb.sched_info().inner_lock_read_irqsave().state(); let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
let state = sched_guard.state();
if state.is_exited() { if state.is_exited() {
kwo.ret_status = state.exit_code().unwrap() as i32; kwo.ret_status = state.exit_code().unwrap() as i32;
drop(pcb); kwo.no_task_error = None;
// 由于pcb的drop方法里面要获取父进程的children字段的写锁所以这里不能直接drop pcb
// 而是要先break到外层循环以便释放父进程的children字段的锁,才能drop pcb。
// 否则会死锁。
tmp_child_pcb = Some(pcb.clone());
unsafe { ProcessManager::release(*pid) }; unsafe { ProcessManager::release(*pid) };
return Ok((*pid).into()); retval = Ok((*pid).into());
} else { break 'outer;
unsafe { pcb.wait_queue.sleep_without_schedule() };
} }
} }
drop(irq_guard); nanosleep(Duration::from_millis(100).into())?;
schedule(SchedMode::SM_NONE); }
} else { } else {
// todo: 对于pgid的处理 // todo: 对于pgid的处理
warn!("kernel_wait4: currently not support {:?}", kwo.pid_type); warn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
return Err(SystemError::EINVAL); return Err(SystemError::EINVAL);
} }
notask!('outer);
} }
drop(tmp_child_pcb);
ProcessManager::current_pcb()
.sched_info
.inner_lock_write_irqsave()
.set_state(ProcessState::Runnable);
// log::debug!(
// "do_wait, kwo.pid: {}, retval = {:?}, kwo: {:?}",
// kwo.pid,
// retval,
// kwo.no_task_error
// );
return retval; return retval;
} }

View File

@ -388,13 +388,16 @@ impl ProcessManager {
/// - `exit_code` : 进程的退出码 /// - `exit_code` : 进程的退出码
pub fn exit(exit_code: usize) -> ! { pub fn exit(exit_code: usize) -> ! {
// 关中断 // 关中断
let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let pid: Pid;
{
let pcb = ProcessManager::current_pcb(); let pcb = ProcessManager::current_pcb();
let pid = pcb.pid(); pid = pcb.pid();
pcb.sched_info pcb.sched_info
.inner_lock_write_irqsave() .inner_lock_write_irqsave()
.set_state(ProcessState::Exited(exit_code)); .set_state(ProcessState::Exited(exit_code));
pcb.wait_queue.wakeup(Some(ProcessState::Blocked(true))); pcb.wait_queue.mark_dead();
pcb.wait_queue.wakeup_all(Some(ProcessState::Blocked(true)));
let rq = cpu_rq(smp_get_processor_id().data() as usize); let rq = cpu_rq(smp_get_processor_id().data() as usize);
let (rq, guard) = rq.self_lock(); let (rq, guard) = rq.self_lock();
@ -412,8 +415,12 @@ impl ProcessManager {
if let Some(addr) = thread.clear_child_tid { if let Some(addr) = thread.clear_child_tid {
if Arc::strong_count(&pcb.basic().user_vm().expect("User VM Not found")) > 1 { if Arc::strong_count(&pcb.basic().user_vm().expect("User VM Not found")) > 1 {
let _ = let _ = Futex::futex_wake(
Futex::futex_wake(addr, FutexFlag::FLAGS_MATCH_NONE, 1, FUTEX_BITSET_MATCH_ANY); addr,
FutexFlag::FLAGS_MATCH_NONE,
1,
FUTEX_BITSET_MATCH_ANY,
);
} }
unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") }; unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
} }
@ -431,13 +438,18 @@ impl ProcessManager {
// TODO 由于未实现进程组tty记录的前台进程组等于当前进程故退出前要置空 // TODO 由于未实现进程组tty记录的前台进程组等于当前进程故退出前要置空
// 后续相关逻辑需要在SYS_EXIT_GROUP系统调用中实现 // 后续相关逻辑需要在SYS_EXIT_GROUP系统调用中实现
if let Some(tty) = pcb.sig_info_irqsave().tty() { if let Some(tty) = pcb.sig_info_irqsave().tty() {
tty.core().contorl_info_irqsave().pgid = None; // 临时解决方案!!! 临时解决方案!!! 引入进程组之后,要重写这个更新前台进程组的逻辑
let mut g = tty.core().contorl_info_irqsave();
if g.pgid == Some(pid) {
g.pgid = None;
}
} }
pcb.sig_info_mut().set_tty(None); pcb.sig_info_mut().set_tty(None);
drop(pcb); drop(pcb);
ProcessManager::exit_notify(); ProcessManager::exit_notify();
// unsafe { CurrentIrqArch::interrupt_enable() }; }
__schedule(SchedMode::SM_NONE); __schedule(SchedMode::SM_NONE);
error!("pid {pid:?} exited but sched again!"); error!("pid {pid:?} exited but sched again!");
#[allow(clippy::empty_loop)] #[allow(clippy::empty_loop)]

View File

@ -4,6 +4,7 @@ use system_error::SystemError;
use crate::{ use crate::{
libs::{spinlock::SpinLock, wait_queue::WaitQueue}, libs::{spinlock::SpinLock, wait_queue::WaitQueue},
process::ProcessManager,
time::timer::schedule_timeout, time::timer::schedule_timeout,
}; };
@ -29,20 +30,22 @@ impl Completion {
/// @return 返回剩余时间或者SystemError /// @return 返回剩余时间或者SystemError
fn do_wait_for_common(&self, mut timeout: i64, interuptible: bool) -> Result<i64, SystemError> { fn do_wait_for_common(&self, mut timeout: i64, interuptible: bool) -> Result<i64, SystemError> {
let mut inner = self.inner.lock_irqsave(); let mut inner = self.inner.lock_irqsave();
let pcb = ProcessManager::current_pcb();
if inner.done == 0 { if inner.done == 0 {
//loop break 类似 do while 保证进行一次信号检测 //loop break 类似 do while 保证进行一次信号检测
loop { loop {
//检查当前线程是否有未处理的信号 //检查当前线程是否有未处理的信号
// if (signal_pending_state(state, current)) { if pcb.sig_info_irqsave().sig_pending().has_pending() {
// timeout = -ERESTARTSYS; return Err(SystemError::ERESTARTSYS);
// break; }
//}
if interuptible { let e = if interuptible {
unsafe { inner.wait_queue.sleep_without_schedule() }; unsafe { inner.wait_queue.sleep_without_schedule() }
} else { } else {
unsafe { inner.wait_queue.sleep_without_schedule_uninterruptible() }; unsafe { inner.wait_queue.sleep_without_schedule_uninterruptible() }
};
if e.is_err() {
break;
} }
drop(inner); drop(inner);
timeout = schedule_timeout(timeout)?; timeout = schedule_timeout(timeout)?;

View File

@ -24,7 +24,7 @@ source = "git"
source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git" source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git"
# git标签或分支 # git标签或分支
# 注意: branch和revision只能二选一且source要设置为"git" # 注意: branch和revision只能二选一且source要设置为"git"
revision = "cb835e03e4" revision = "feaebefaef"
# 构建相关信息 # 构建相关信息
[build] [build]
# (可选)构建命令 # (可选)构建命令