Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kernel/src/driver/tty/tty_job_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl TtyJobCtrlManager {
ProcessManager::current_pcb()
.flags()
.insert(ProcessFlags::HAS_PENDING_SIGNAL);

log::debug!("job_ctrl_ioctl: kill. pgid: {pgid}, tty_pgid: {tty_pgid:?}");
return Err(SystemError::ERESTARTSYS);
}
}
Expand Down
46 changes: 34 additions & 12 deletions kernel/src/filesystem/eventfd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ impl EventFdInode {
let count = self.eventfd.lock().count;
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 {
Expand Down Expand Up @@ -125,6 +140,11 @@ impl IndexNode for EventFdInode {
}

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(), {});
if r.is_err() {
ProcessManager::current_pcb()
Expand All @@ -138,7 +158,7 @@ impl IndexNode for EventFdInode {
}
let mut val = lock_efd.count;

let mut eventfd = self.eventfd.lock();
let mut eventfd = lock_efd;
if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) {
eventfd.count -= 1;
val = 1;
Expand All @@ -147,8 +167,9 @@ impl IndexNode for EventFdInode {
}
let val_bytes = val.to_ne_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中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;

Expand Down Expand Up @@ -178,6 +199,9 @@ impl IndexNode for EventFdInode {
return Err(SystemError::EINVAL);
}
loop {
if ProcessManager::current_pcb().has_pending_signal() {
return Err(SystemError::ERESTARTSYS);
}
let eventfd = self.eventfd.lock();
if u64::MAX - eventfd.count > val {
break;
Expand All @@ -189,13 +213,17 @@ impl IndexNode for EventFdInode {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
drop(eventfd);
self.wait_queue.sleep();
self.wait_queue.sleep().ok();
}
let mut eventfd = self.eventfd.lock();
eventfd.count += val;
drop(eventfd);
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中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
return Ok(8);
Expand All @@ -206,14 +234,8 @@ impl IndexNode for EventFdInode {
/// - 如果 counter 的值大于 0 ,那么 fd 的状态就是可读的
/// - 如果能无阻塞地写入一个至少为 1 的值,那么 fd 的状态就是可写的
fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
let mut events = EPollEventType::empty();
if self.eventfd.lock().count != 0 {
events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM;
}
if self.eventfd.lock().count != u64::MAX {
events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
}
return Ok(events.bits() as usize);
let self_guard = self.eventfd.lock();
self.do_poll(_private_data, &self_guard)
}

fn metadata(&self) -> Result<Metadata, SystemError> {
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/libs/semaphore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Semaphore {
fn down(&self) {
if self.counter.fetch_sub(1, Ordering::Release) <= 0 {
self.counter.fetch_add(1, Ordering::Relaxed);
self.wait_queue.sleep();
self.wait_queue.sleep().ok();
//资源不充足,信号量<=0, 此时进程睡眠
}
}
Expand Down
120 changes: 86 additions & 34 deletions kernel/src/libs/wait_queue.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// #![allow(dead_code)]
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 system_error::SystemError;

Expand All @@ -19,23 +19,40 @@ use super::{

#[derive(Debug)]
struct InnerWaitQueue {
/// 等待队列是否已经死亡, 如果已经死亡, 则不能再添加新的等待进程
dead: bool,
/// 等待队列的链表
wait_list: LinkedList<Arc<ProcessControlBlock>>,
wait_list: VecDeque<Arc<ProcessControlBlock>>,
}

/// 被自旋锁保护的等待队列
#[derive(Debug)]
pub struct WaitQueue(SpinLock<InnerWaitQueue>);
pub struct WaitQueue {
inner: SpinLock<InnerWaitQueue>,
}

#[allow(dead_code)]
impl WaitQueue {
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> {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
let pcb = ProcessManager::current_pcb();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
if Signal::signal_pending_state(interruptible, false, &pcb) {
return Err(SystemError::ERESTARTSYS);
} else {
Expand All @@ -51,7 +68,7 @@ impl WaitQueue {
pub fn finish_wait(&self) {
let pcb = ProcessManager::current_pcb();
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_wakeup();
Expand All @@ -62,34 +79,49 @@ impl WaitQueue {
}

/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
pub fn sleep(&self) {
pub fn sleep(&self) -> Result<(), SystemError> {
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| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
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函数闭包
pub fn sleep_with_func<F>(&self, f: F)
pub fn sleep_with_func<F>(&self, f: F) -> Result<(), SystemError>
where
F: FnOnce(),
{
before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}

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);
schedule(SchedMode::SM_NONE);

Ok(())
}

/// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。
Expand All @@ -106,80 +138,95 @@ impl WaitQueue {
///
/// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数,
/// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。
pub unsafe fn sleep_without_schedule(&self) {
pub unsafe fn sleep_without_schedule(&self) -> Result<(), SystemError> {
before_sleep_check(1);
// 安全检查:确保当前处于中断禁止状态
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| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
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);
// 安全检查:确保当前处于中断禁止状态
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| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
Ok(())
}
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
pub fn sleep_uninterruptible(&self) {
pub fn sleep_uninterruptible(&self) -> Result<(), SystemError> {
before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
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);
schedule(SchedMode::SM_NONE);
Ok(())
}

/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
/// 在当前进程的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);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();
if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
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);
schedule(SchedMode::SM_NONE);
Ok(())
}

/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
/// 在当前进程的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);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let mut guard: SpinLockGuard<InnerWaitQueue> = self.inner_irqsave();

if !guard.can_sleep() {
return Err(SystemError::ESRCH);
}
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);
schedule(SchedMode::SM_NONE);
Ok(())
}

/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
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() };
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
Expand All @@ -195,7 +242,7 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
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() };
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
Expand All @@ -217,7 +264,7 @@ impl WaitQueue {
/// @return true 成功唤醒进程
/// @return false 没有唤醒进程
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() {
return false;
Expand Down Expand Up @@ -246,7 +293,7 @@ impl WaitQueue {
///
/// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
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() {
return;
Expand Down Expand Up @@ -281,14 +328,19 @@ impl WaitQueue {

/// @brief 获得当前等待队列的大小
pub fn len(&self) -> usize {
return self.0.lock().wait_list.len();
return self.inner_irqsave().wait_list.len();
}
}

impl 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) {
Expand Down
Loading
Loading