LoGin 2b72148cae
feat(syscall): 实现syscall restart (#1075)
能够在系统调用返回ERESTARTSYS时,信号处理结束后,自动重启系统调用.

TODO: 实现wait等需要restart_block的系统调用的重启

Signed-off-by: longjin <longjin@DragonOS.org>
2024-12-13 00:56:20 +08:00

499 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::sync::atomic::compiler_fence;
use crate::{
arch::ipc::signal::{SigCode, Signal},
filesystem::vfs::{
core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem,
FileType, IndexNode, Metadata,
},
libs::{
spinlock::{SpinLock, SpinLockGuard},
wait_queue::WaitQueue,
},
net::event_poll::{EPollEventType, EPollItem, EventPoll},
process::{ProcessFlags, ProcessManager, ProcessState},
sched::SchedMode,
time::PosixTimeSpec,
};
use alloc::{
collections::LinkedList,
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
use super::signal_types::{SigInfo, SigType};
/// 我们设定pipe_buff的总大小为1024字节
const PIPE_BUFF_SIZE: usize = 1024;
#[derive(Debug, Clone)]
pub struct PipeFsPrivateData {
mode: FileMode,
}
impl PipeFsPrivateData {
pub fn new(mode: FileMode) -> Self {
return PipeFsPrivateData { mode };
}
pub fn set_mode(&mut self, mode: FileMode) {
self.mode = mode;
}
}
/// @brief 管道文件i节点(锁)
#[derive(Debug)]
pub struct LockedPipeInode {
inner: SpinLock<InnerPipeInode>,
read_wait_queue: WaitQueue,
write_wait_queue: WaitQueue,
}
/// @brief 管道文件i节点(无锁)
#[derive(Debug)]
pub struct InnerPipeInode {
self_ref: Weak<LockedPipeInode>,
/// 管道内可读的数据数
valid_cnt: i32,
read_pos: i32,
write_pos: i32,
data: [u8; PIPE_BUFF_SIZE],
/// INode 元数据
metadata: Metadata,
reader: u32,
writer: u32,
had_reader: bool,
epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
}
impl InnerPipeInode {
pub fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
let mut events = EPollEventType::empty();
let mode = if let FilePrivateData::Pipefs(PipeFsPrivateData { mode }) = private_data {
mode
} else {
return Err(SystemError::EBADFD);
};
if mode.contains(FileMode::O_RDONLY) {
if self.valid_cnt != 0 {
// 有数据可读
events.insert(EPollEventType::EPOLLIN & EPollEventType::EPOLLRDNORM);
}
// 没有写者
if self.writer == 0 {
events.insert(EPollEventType::EPOLLHUP)
}
}
if mode.contains(FileMode::O_WRONLY) {
// 管道内数据未满
if self.valid_cnt as usize != PIPE_BUFF_SIZE {
events.insert(EPollEventType::EPOLLIN & EPollEventType::EPOLLWRNORM);
}
// 没有读者
if self.reader == 0 {
events.insert(EPollEventType::EPOLLERR);
}
}
Ok(events.bits() as usize)
}
pub fn add_epoll(&mut self, epitem: Arc<EPollItem>) -> Result<(), SystemError> {
self.epitems.lock().push_back(epitem);
Ok(())
}
fn buf_full(&self) -> bool {
return self.valid_cnt as usize == PIPE_BUFF_SIZE;
}
pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> {
let is_remove = !self
.epitems
.lock_irqsave()
.extract_if(|x| x.epoll().ptr_eq(epoll))
.collect::<Vec<_>>()
.is_empty();
if is_remove {
return Ok(());
}
Err(SystemError::ENOENT)
}
}
impl LockedPipeInode {
pub fn new() -> Arc<Self> {
let inner = InnerPipeInode {
self_ref: Weak::default(),
valid_cnt: 0,
read_pos: 0,
write_pos: 0,
had_reader: false,
data: [0; PIPE_BUFF_SIZE],
metadata: Metadata {
dev_id: 0,
inode_id: generate_inode_id(),
size: PIPE_BUFF_SIZE as i64,
blk_size: 0,
blocks: 0,
atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(),
file_type: FileType::Pipe,
mode: ModeType::from_bits_truncate(0o666),
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: Default::default(),
},
reader: 0,
writer: 0,
epitems: SpinLock::new(LinkedList::new()),
};
let result = Arc::new(Self {
inner: SpinLock::new(inner),
read_wait_queue: WaitQueue::default(),
write_wait_queue: WaitQueue::default(),
});
let mut guard = result.inner.lock();
guard.self_ref = Arc::downgrade(&result);
// 释放锁
drop(guard); //这一步其实不需要只要离开作用域guard生命周期结束自会解锁
return result;
}
pub fn inner(&self) -> &SpinLock<InnerPipeInode> {
&self.inner
}
fn readable(&self) -> bool {
let inode = self.inner.lock();
return inode.valid_cnt > 0 || inode.writer == 0;
}
fn writeable(&self) -> bool {
let inode = self.inner.lock();
return !inode.buf_full() || inode.reader == 0;
}
}
impl IndexNode for LockedPipeInode {
fn read_at(
&self,
_offset: usize,
len: usize,
buf: &mut [u8],
data_guard: SpinLockGuard<FilePrivateData>,
) -> Result<usize, SystemError> {
let data = data_guard.clone();
drop(data_guard);
// 获取mode
let mode: FileMode;
if let FilePrivateData::Pipefs(pdata) = &data {
mode = pdata.mode;
} else {
return Err(SystemError::EBADF);
}
if buf.len() < len {
return Err(SystemError::EINVAL);
}
// log::debug!("pipe mode: {:?}", mode);
// 加锁
let mut inode = self.inner.lock();
// 如果管道里面没有数据,则唤醒写端,
while inode.valid_cnt == 0 {
// 如果当前管道写者数为0则返回EOF
if inode.writer == 0 {
return Ok(0);
}
self.write_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
// 如果为非阻塞管道,直接返回错误
if mode.contains(FileMode::O_NONBLOCK) {
drop(inode);
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
// 否则在读等待队列中睡眠,并释放锁
drop(inode);
let r = wq_wait_event_interruptible!(self.read_wait_queue, self.readable(), {});
if r.is_err() {
ProcessManager::current_pcb()
.flags()
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
return Err(SystemError::ERESTARTSYS);
}
inode = self.inner.lock();
}
let mut num = inode.valid_cnt as usize;
//决定要输出的字节
let start = inode.read_pos as usize;
//如果读端希望读取的字节数大于有效字节数,则输出有效字节
let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE;
//如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节
if len < inode.valid_cnt as usize {
end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE;
num = len;
}
// 从管道拷贝数据到用户的缓冲区
if end < start {
buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]);
buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]);
} else {
buf[0..num].copy_from_slice(&inode.data[start..end]);
}
//更新读位置以及valid_cnt
inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32;
inode.valid_cnt -= num as i32;
// 读完以后如果未读完,则唤醒下一个读者
if inode.valid_cnt > 0 {
self.read_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
}
//读完后解锁并唤醒等待在写等待队列中的进程
self.write_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?;
//返回读取的字节数
return Ok(num);
}
fn open(
&self,
mut data: SpinLockGuard<FilePrivateData>,
mode: &crate::filesystem::vfs::file::FileMode,
) -> Result<(), SystemError> {
let accmode = mode.accmode();
let mut guard = self.inner.lock();
// 不能以读写方式打开管道
if accmode == FileMode::O_RDWR.bits() {
return Err(SystemError::EACCES);
} else if accmode == FileMode::O_RDONLY.bits() {
guard.reader += 1;
guard.had_reader = true;
// println!(
// "FIFO: pipe try open in read mode with reader pid:{:?}",
// ProcessManager::current_pid()
// );
} else if accmode == FileMode::O_WRONLY.bits() {
// println!(
// "FIFO: pipe try open in write mode with {} reader, writer pid:{:?}",
// guard.reader,
// ProcessManager::current_pid()
// );
if guard.reader == 0 && mode.contains(FileMode::O_NONBLOCK) {
return Err(SystemError::ENXIO);
}
guard.writer += 1;
}
// 设置mode
*data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode });
return Ok(());
}
fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
let inode = self.inner.lock();
let mut metadata = inode.metadata.clone();
metadata.size = inode.data.len() as i64;
return Ok(metadata);
}
fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
let mode: FileMode;
if let FilePrivateData::Pipefs(pipe_data) = &*data {
mode = pipe_data.mode;
} else {
return Err(SystemError::EBADF);
}
let accmode = mode.accmode();
let mut guard = self.inner.lock();
// 写端关闭
if accmode == FileMode::O_WRONLY.bits() {
assert!(guard.writer > 0);
guard.writer -= 1;
// 如果已经没有写端了,则唤醒读端
if guard.writer == 0 {
self.read_wait_queue
.wakeup_all(Some(ProcessState::Blocked(true)));
}
}
// 读端关闭
if accmode == FileMode::O_RDONLY.bits() {
assert!(guard.reader > 0);
guard.reader -= 1;
// 如果已经没有写端了,则唤醒读端
if guard.reader == 0 {
self.write_wait_queue
.wakeup_all(Some(ProcessState::Blocked(true)));
}
}
return Ok(());
}
fn write_at(
&self,
_offset: usize,
len: usize,
buf: &[u8],
data: SpinLockGuard<FilePrivateData>,
) -> Result<usize, SystemError> {
// 获取mode
let mode: FileMode;
if let FilePrivateData::Pipefs(pdata) = &*data {
mode = pdata.mode;
} else {
return Err(SystemError::EBADF);
}
if buf.len() < len || len > PIPE_BUFF_SIZE {
return Err(SystemError::EINVAL);
}
// 加锁
let mut inode = self.inner.lock();
if inode.reader == 0 {
if !inode.had_reader {
// 如果从未有读端,直接返回 ENXIO无论是否阻塞模式
return Err(SystemError::ENXIO);
} else {
// 如果曾经有读端,现在已关闭
match mode.contains(FileMode::O_NONBLOCK) {
true => {
// 非阻塞模式,直接返回 EPIPE
return Err(SystemError::EPIPE);
}
false => {
let sig = Signal::SIGPIPE;
let mut info = SigInfo::new(
sig,
0,
SigCode::Kernel,
SigType::Kill(ProcessManager::current_pid()),
);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let _retval = sig
.send_signal_info(Some(&mut info), ProcessManager::current_pid())
.map(|x| x as usize);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return Err(SystemError::EPIPE);
}
}
}
}
// 如果管道空间不够
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
// 唤醒读端
self.read_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
// 如果为非阻塞管道,直接返回错误
if mode.contains(FileMode::O_NONBLOCK) {
drop(inode);
return Err(SystemError::ENOMEM);
}
// 解锁并睡眠
drop(inode);
let r = wq_wait_event_interruptible!(self.write_wait_queue, self.writeable(), {});
if r.is_err() {
return Err(SystemError::ERESTARTSYS);
}
inode = self.inner.lock();
}
// 决定要输入的字节
let start = inode.write_pos as usize;
let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE;
// 从用户的缓冲区拷贝数据到管道
if end < start {
inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]);
inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]);
} else {
inode.data[start..end].copy_from_slice(&buf[0..len]);
}
// 更新写位置以及valid_cnt
inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32;
inode.valid_cnt += len as i32;
// 写完后还有位置,则唤醒下一个写者
if (inode.valid_cnt as usize) < PIPE_BUFF_SIZE {
self.write_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
}
// 读完后解锁并唤醒等待在读等待队列中的进程
self.read_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?;
// 返回写入的字节数
return Ok(len);
}
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn get_entry_name_and_metadata(
&self,
ino: crate::filesystem::vfs::InodeId,
) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> {
// 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
let name = self.get_entry_name(ino)?;
let entry = self.find(&name)?;
return Ok((name, entry.metadata()?));
}
fn fs(&self) -> Arc<(dyn FileSystem)> {
todo!()
}
fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
return Err(SystemError::ENOSYS);
}
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
return self.inner.lock().poll(private_data);
}
}