Skip to content
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
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,10 @@
"user_namespace.h": "c",
"sleep.h": "c",
"net.h": "c",
"lz4.h": "c"
"lz4.h": "c",
"cmd_test.h": "c"
},
"C_Cpp.errorSquiggles": "Enabled",
"C_Cpp.errorSquiggles": "enabled",
"esbonio.sphinx.confDir": "",
"rust-analyzer.cargo.target": "x86_64-unknown-none",
"rust-analyzer.checkOnSave.allTargets": false,
Expand Down
45 changes: 44 additions & 1 deletion kernel/src/arch/x86_64/interrupt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#![allow(dead_code)]
use core::arch::asm;
use core::{
arch::asm,
sync::atomic::{compiler_fence, Ordering},
};

use crate::exception::{InterruptArch, IrqFlags, IrqFlagsGuard};

use super::asm::irqflags::{local_irq_restore, local_irq_save};

/// @brief 关闭中断
#[inline]
Expand All @@ -16,3 +23,39 @@ pub fn sti() {
asm!("sti");
}
}

pub struct X86_64InterruptArch;

impl InterruptArch for X86_64InterruptArch {
unsafe fn interrupt_enable() {
sti();
}

unsafe fn interrupt_disable() {
cli();
}

fn is_irq_enabled() -> bool {
let rflags: u64;
unsafe {
asm!("pushfq; pop {}", out(reg) rflags);
}
return rflags & (1 << 9) != 0;
}

unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
compiler_fence(Ordering::SeqCst);
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
let flags = IrqFlags::new(rflags);
let guard = IrqFlagsGuard::new(flags);
compiler_fence(Ordering::SeqCst);
return guard;
}

unsafe fn restore_irq(flags: IrqFlags) {
compiler_fence(Ordering::SeqCst);
local_irq_restore(&flags.flags());
compiler_fence(Ordering::SeqCst);
}
}
2 changes: 2 additions & 0 deletions kernel/src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ pub mod mm;
pub mod pci;
pub mod rand;
pub mod sched;

pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
72 changes: 72 additions & 0 deletions kernel/src/exception/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,73 @@
use crate::arch::CurrentIrqArch;

pub mod softirq;

/// @brief 中断相关的操作
pub trait InterruptArch: Send + Sync {
/// @brief 使能中断
unsafe fn interrupt_enable();
/// @brief 禁止中断
unsafe fn interrupt_disable();
/// @brief 检查中断是否被禁止
fn is_irq_enabled() -> bool;

/// @brief 保存当前中断状态,并且禁止中断
unsafe fn save_and_disable_irq() -> IrqFlagsGuard;
unsafe fn restore_irq(flags: IrqFlags);
}

#[derive(Debug, Clone, Copy)]
pub struct IrqFlags {
flags: u64,
}

impl IrqFlags {
pub fn new(flags: u64) -> Self {
IrqFlags { flags }
}

pub fn flags(&self) -> u64 {
self.flags
}
}

/// @brief 当前中断状态的保护器,当该对象被drop时,会恢复之前的中断状态
///
/// # Example
///
/// ```
/// use crate::arch::CurrentIrqArch;
///
/// // disable irq and save irq state (这是唯一的获取IrqFlagsGuard的方法)
/// let guard = unsafe{CurrentIrqArch::save_and_disable_irq()};
///
/// // do something
///
/// // 销毁guard时,会恢复之前的中断状态
/// drop(guard);
///
/// ```
#[derive(Debug)]
pub struct IrqFlagsGuard {
flags: IrqFlags,
}

impl IrqFlagsGuard {
/// @brief 创建IrqFlagsGuard对象
///
/// # Safety
///
/// 该函数不安全,因为它不会检查flags是否是一个有效的IrqFlags对象, 而当它被drop时,会恢复flags中的中断状态
///
/// 该函数只应被`CurrentIrqArch::save_and_disable_irq`调用
pub unsafe fn new(flags: IrqFlags) -> Self {
IrqFlagsGuard { flags }
}
}
impl Drop for IrqFlagsGuard {
fn drop(&mut self) {
unsafe {
CurrentIrqArch::restore_irq(self.flags);
}
}
}
2 changes: 2 additions & 0 deletions kernel/src/ipc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod pipe;
pub mod signal;
pub mod signal_types;
pub mod syscall;
230 changes: 230 additions & 0 deletions kernel/src/ipc/pipe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
use crate::{
arch::{sched::sched, CurrentIrqArch},
exception::InterruptArch,
filesystem::vfs::{
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
PollStatus,
},
include::bindings::bindings::PROC_INTERRUPTIBLE,
libs::{spinlock::SpinLock, wait_queue::WaitQueue},
syscall::SystemError,
time::TimeSpec,
};

use alloc::sync::{Arc, Weak};

/// 我们设定pipe_buff的总大小为1024字节
const PIPE_BUFF_SIZE: usize = 1024;

/// @brief 管道文件i节点(锁)
#[derive(Debug)]
pub struct LockedPipeInode(SpinLock<InnerPipeInode>);

/// @brief 管道文件i节点(无锁)
#[derive(Debug)]
pub struct InnerPipeInode {
self_ref: Weak<LockedPipeInode>,
valid_cnt: i32,
read_pos: i32,
write_pos: i32,
read_wait_queue: WaitQueue,
write_wait_queue: WaitQueue,
data: [u8; PIPE_BUFF_SIZE],
/// INode 元数据
metadata: Metadata,
}

impl LockedPipeInode {
pub fn new() -> Arc<Self> {
let inner = InnerPipeInode {
self_ref: Weak::default(),
valid_cnt: 0,
read_pos: 0,
write_pos: 0,
read_wait_queue: WaitQueue::INIT,
write_wait_queue: WaitQueue::INIT,
data: [0; PIPE_BUFF_SIZE],

metadata: Metadata {
dev_id: 0,
inode_id: generate_inode_id(),
size: 0,
blk_size: 0,
blocks: 0,
atime: TimeSpec::default(),
mtime: TimeSpec::default(),
ctime: TimeSpec::default(),
file_type: FileType::Pipe,
mode: 0o666,
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: 0,
},
};
let result = Arc::new(Self(SpinLock::new(inner)));
let mut guard = result.0.lock();
guard.self_ref = Arc::downgrade(&result);
// 释放锁
drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁
return result;
}
}

impl IndexNode for LockedPipeInode {
fn read_at(
&self,
_offset: usize,
len: usize,
buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, crate::syscall::SystemError> {
if buf.len() < len {
return Err(SystemError::EINVAL);
}
// 加锁
let mut inode = self.0.lock();

//如果管道里面没有数据,则唤醒写端,
while inode.valid_cnt == 0 {
inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());

// 在读等待队列中睡眠,并释放锁
unsafe {
let irq_guard = CurrentIrqArch::save_and_disable_irq();
inode.read_wait_queue.sleep_without_schedule();
drop(inode);

drop(irq_guard);
}
sched();
inode = self.0.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;

//读完后解锁并唤醒等待在写等待队列中的进程
inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
//返回读取的字节数
return Ok(num);
}

fn open(
&self,
_data: &mut FilePrivateData,
_mode: &crate::filesystem::vfs::file::FileMode,
) -> Result<(), SystemError> {
return Ok(());
}

fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
let inode = self.0.lock();
let mut metadata = inode.metadata.clone();
metadata.size = inode.data.len() as i64;

return Ok(metadata);
}

fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
return Ok(());
}

fn write_at(
&self,
_offset: usize,
len: usize,
buf: &[u8],
_data: &mut FilePrivateData,
) -> Result<usize, crate::syscall::SystemError> {
if buf.len() < len || len > PIPE_BUFF_SIZE {
return Err(SystemError::EINVAL);
}
// 加锁

let mut inode = self.0.lock();

// 如果管道空间不够

while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
// 唤醒读端
inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
// 解锁并睡眠
unsafe {
let irq_guard = CurrentIrqArch::save_and_disable_irq();
inode.write_wait_queue.sleep_without_schedule();
drop(inode);
drop(irq_guard);
}
sched();
inode = self.0.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;

// 读完后解锁并唤醒等待在读等待队列中的进程
inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
// 返回写入的字节数
return Ok(len);
}

fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> {
return Ok(PollStatus::READ | PollStatus::WRITE);
}

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::EOPNOTSUPP_OR_ENOTSUP);
}
}
Loading