xref: /DragonOS/kernel/src/ipc/pipe.rs (revision f678331a3315b7847f08ab32b42d5bf49a9f3a6a)
1*f678331aShanjiezhou use crate::{
2*f678331aShanjiezhou     arch::{sched::sched, CurrentIrqArch},
3*f678331aShanjiezhou     exception::InterruptArch,
4*f678331aShanjiezhou     filesystem::vfs::{
5*f678331aShanjiezhou         core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
6*f678331aShanjiezhou         PollStatus,
7*f678331aShanjiezhou     },
8*f678331aShanjiezhou     include::bindings::bindings::PROC_INTERRUPTIBLE,
9*f678331aShanjiezhou     libs::{spinlock::SpinLock, wait_queue::WaitQueue},
10*f678331aShanjiezhou     syscall::SystemError,
11*f678331aShanjiezhou     time::TimeSpec,
12*f678331aShanjiezhou };
13*f678331aShanjiezhou 
14*f678331aShanjiezhou use alloc::sync::{Arc, Weak};
15*f678331aShanjiezhou 
16*f678331aShanjiezhou /// 我们设定pipe_buff的总大小为1024字节
17*f678331aShanjiezhou const PIPE_BUFF_SIZE: usize = 1024;
18*f678331aShanjiezhou 
19*f678331aShanjiezhou /// @brief 管道文件i节点(锁)
20*f678331aShanjiezhou #[derive(Debug)]
21*f678331aShanjiezhou pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
22*f678331aShanjiezhou 
23*f678331aShanjiezhou /// @brief 管道文件i节点(无锁)
24*f678331aShanjiezhou #[derive(Debug)]
25*f678331aShanjiezhou pub struct InnerPipeInode {
26*f678331aShanjiezhou     self_ref: Weak<LockedPipeInode>,
27*f678331aShanjiezhou     valid_cnt: i32,
28*f678331aShanjiezhou     read_pos: i32,
29*f678331aShanjiezhou     write_pos: i32,
30*f678331aShanjiezhou     read_wait_queue: WaitQueue,
31*f678331aShanjiezhou     write_wait_queue: WaitQueue,
32*f678331aShanjiezhou     data: [u8; PIPE_BUFF_SIZE],
33*f678331aShanjiezhou     /// INode 元数据
34*f678331aShanjiezhou     metadata: Metadata,
35*f678331aShanjiezhou }
36*f678331aShanjiezhou 
37*f678331aShanjiezhou impl LockedPipeInode {
38*f678331aShanjiezhou     pub fn new() -> Arc<Self> {
39*f678331aShanjiezhou         let inner = InnerPipeInode {
40*f678331aShanjiezhou             self_ref: Weak::default(),
41*f678331aShanjiezhou             valid_cnt: 0,
42*f678331aShanjiezhou             read_pos: 0,
43*f678331aShanjiezhou             write_pos: 0,
44*f678331aShanjiezhou             read_wait_queue: WaitQueue::INIT,
45*f678331aShanjiezhou             write_wait_queue: WaitQueue::INIT,
46*f678331aShanjiezhou             data: [0; PIPE_BUFF_SIZE],
47*f678331aShanjiezhou 
48*f678331aShanjiezhou             metadata: Metadata {
49*f678331aShanjiezhou                 dev_id: 0,
50*f678331aShanjiezhou                 inode_id: generate_inode_id(),
51*f678331aShanjiezhou                 size: 0,
52*f678331aShanjiezhou                 blk_size: 0,
53*f678331aShanjiezhou                 blocks: 0,
54*f678331aShanjiezhou                 atime: TimeSpec::default(),
55*f678331aShanjiezhou                 mtime: TimeSpec::default(),
56*f678331aShanjiezhou                 ctime: TimeSpec::default(),
57*f678331aShanjiezhou                 file_type: FileType::Pipe,
58*f678331aShanjiezhou                 mode: 0o666,
59*f678331aShanjiezhou                 nlinks: 1,
60*f678331aShanjiezhou                 uid: 0,
61*f678331aShanjiezhou                 gid: 0,
62*f678331aShanjiezhou                 raw_dev: 0,
63*f678331aShanjiezhou             },
64*f678331aShanjiezhou         };
65*f678331aShanjiezhou         let result = Arc::new(Self(SpinLock::new(inner)));
66*f678331aShanjiezhou         let mut guard = result.0.lock();
67*f678331aShanjiezhou         guard.self_ref = Arc::downgrade(&result);
68*f678331aShanjiezhou         // 释放锁
69*f678331aShanjiezhou         drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁
70*f678331aShanjiezhou         return result;
71*f678331aShanjiezhou     }
72*f678331aShanjiezhou }
73*f678331aShanjiezhou 
74*f678331aShanjiezhou impl IndexNode for LockedPipeInode {
75*f678331aShanjiezhou     fn read_at(
76*f678331aShanjiezhou         &self,
77*f678331aShanjiezhou         _offset: usize,
78*f678331aShanjiezhou         len: usize,
79*f678331aShanjiezhou         buf: &mut [u8],
80*f678331aShanjiezhou         _data: &mut FilePrivateData,
81*f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
82*f678331aShanjiezhou         if buf.len() < len {
83*f678331aShanjiezhou             return Err(SystemError::EINVAL);
84*f678331aShanjiezhou         }
85*f678331aShanjiezhou         // 加锁
86*f678331aShanjiezhou         let mut inode = self.0.lock();
87*f678331aShanjiezhou 
88*f678331aShanjiezhou         //如果管道里面没有数据,则唤醒写端,
89*f678331aShanjiezhou         while inode.valid_cnt == 0 {
90*f678331aShanjiezhou             inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
91*f678331aShanjiezhou 
92*f678331aShanjiezhou             // 在读等待队列中睡眠,并释放锁
93*f678331aShanjiezhou             unsafe {
94*f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
95*f678331aShanjiezhou                 inode.read_wait_queue.sleep_without_schedule();
96*f678331aShanjiezhou                 drop(inode);
97*f678331aShanjiezhou 
98*f678331aShanjiezhou                 drop(irq_guard);
99*f678331aShanjiezhou             }
100*f678331aShanjiezhou             sched();
101*f678331aShanjiezhou             inode = self.0.lock();
102*f678331aShanjiezhou         }
103*f678331aShanjiezhou 
104*f678331aShanjiezhou         let mut num = inode.valid_cnt as usize;
105*f678331aShanjiezhou         //决定要输出的字节
106*f678331aShanjiezhou         let start = inode.read_pos as usize;
107*f678331aShanjiezhou         //如果读端希望读取的字节数大于有效字节数,则输出有效字节
108*f678331aShanjiezhou         let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE;
109*f678331aShanjiezhou         //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节
110*f678331aShanjiezhou         if len < inode.valid_cnt as usize {
111*f678331aShanjiezhou             end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE;
112*f678331aShanjiezhou             num = len;
113*f678331aShanjiezhou         }
114*f678331aShanjiezhou 
115*f678331aShanjiezhou         // 从管道拷贝数据到用户的缓冲区
116*f678331aShanjiezhou 
117*f678331aShanjiezhou         if end < start {
118*f678331aShanjiezhou             buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]);
119*f678331aShanjiezhou             buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]);
120*f678331aShanjiezhou         } else {
121*f678331aShanjiezhou             buf[0..num].copy_from_slice(&inode.data[start..end]);
122*f678331aShanjiezhou         }
123*f678331aShanjiezhou 
124*f678331aShanjiezhou         //更新读位置以及valid_cnt
125*f678331aShanjiezhou         inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32;
126*f678331aShanjiezhou         inode.valid_cnt -= num as i32;
127*f678331aShanjiezhou 
128*f678331aShanjiezhou         //读完后解锁并唤醒等待在写等待队列中的进程
129*f678331aShanjiezhou         inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
130*f678331aShanjiezhou         //返回读取的字节数
131*f678331aShanjiezhou         return Ok(num);
132*f678331aShanjiezhou     }
133*f678331aShanjiezhou 
134*f678331aShanjiezhou     fn open(
135*f678331aShanjiezhou         &self,
136*f678331aShanjiezhou         _data: &mut FilePrivateData,
137*f678331aShanjiezhou         _mode: &crate::filesystem::vfs::file::FileMode,
138*f678331aShanjiezhou     ) -> Result<(), SystemError> {
139*f678331aShanjiezhou         return Ok(());
140*f678331aShanjiezhou     }
141*f678331aShanjiezhou 
142*f678331aShanjiezhou     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
143*f678331aShanjiezhou         let inode = self.0.lock();
144*f678331aShanjiezhou         let mut metadata = inode.metadata.clone();
145*f678331aShanjiezhou         metadata.size = inode.data.len() as i64;
146*f678331aShanjiezhou 
147*f678331aShanjiezhou         return Ok(metadata);
148*f678331aShanjiezhou     }
149*f678331aShanjiezhou 
150*f678331aShanjiezhou     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
151*f678331aShanjiezhou         return Ok(());
152*f678331aShanjiezhou     }
153*f678331aShanjiezhou 
154*f678331aShanjiezhou     fn write_at(
155*f678331aShanjiezhou         &self,
156*f678331aShanjiezhou         _offset: usize,
157*f678331aShanjiezhou         len: usize,
158*f678331aShanjiezhou         buf: &[u8],
159*f678331aShanjiezhou         _data: &mut FilePrivateData,
160*f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
161*f678331aShanjiezhou         if buf.len() < len || len > PIPE_BUFF_SIZE {
162*f678331aShanjiezhou             return Err(SystemError::EINVAL);
163*f678331aShanjiezhou         }
164*f678331aShanjiezhou         // 加锁
165*f678331aShanjiezhou 
166*f678331aShanjiezhou         let mut inode = self.0.lock();
167*f678331aShanjiezhou 
168*f678331aShanjiezhou         // 如果管道空间不够
169*f678331aShanjiezhou 
170*f678331aShanjiezhou         while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
171*f678331aShanjiezhou             // 唤醒读端
172*f678331aShanjiezhou             inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
173*f678331aShanjiezhou             // 解锁并睡眠
174*f678331aShanjiezhou             unsafe {
175*f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
176*f678331aShanjiezhou                 inode.write_wait_queue.sleep_without_schedule();
177*f678331aShanjiezhou                 drop(inode);
178*f678331aShanjiezhou                 drop(irq_guard);
179*f678331aShanjiezhou             }
180*f678331aShanjiezhou             sched();
181*f678331aShanjiezhou             inode = self.0.lock();
182*f678331aShanjiezhou         }
183*f678331aShanjiezhou 
184*f678331aShanjiezhou         // 决定要输入的字节
185*f678331aShanjiezhou         let start = inode.write_pos as usize;
186*f678331aShanjiezhou         let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE;
187*f678331aShanjiezhou         // 从用户的缓冲区拷贝数据到管道
188*f678331aShanjiezhou 
189*f678331aShanjiezhou         if end < start {
190*f678331aShanjiezhou             inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]);
191*f678331aShanjiezhou             inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]);
192*f678331aShanjiezhou         } else {
193*f678331aShanjiezhou             inode.data[start..end].copy_from_slice(&buf[0..len]);
194*f678331aShanjiezhou         }
195*f678331aShanjiezhou         // 更新写位置以及valid_cnt
196*f678331aShanjiezhou         inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32;
197*f678331aShanjiezhou         inode.valid_cnt += len as i32;
198*f678331aShanjiezhou 
199*f678331aShanjiezhou         // 读完后解锁并唤醒等待在读等待队列中的进程
200*f678331aShanjiezhou         inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
201*f678331aShanjiezhou         // 返回写入的字节数
202*f678331aShanjiezhou         return Ok(len);
203*f678331aShanjiezhou     }
204*f678331aShanjiezhou 
205*f678331aShanjiezhou     fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> {
206*f678331aShanjiezhou         return Ok(PollStatus::READ | PollStatus::WRITE);
207*f678331aShanjiezhou     }
208*f678331aShanjiezhou 
209*f678331aShanjiezhou     fn as_any_ref(&self) -> &dyn core::any::Any {
210*f678331aShanjiezhou         self
211*f678331aShanjiezhou     }
212*f678331aShanjiezhou 
213*f678331aShanjiezhou     fn get_entry_name_and_metadata(
214*f678331aShanjiezhou         &self,
215*f678331aShanjiezhou         ino: crate::filesystem::vfs::InodeId,
216*f678331aShanjiezhou     ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> {
217*f678331aShanjiezhou         // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
218*f678331aShanjiezhou         let name = self.get_entry_name(ino)?;
219*f678331aShanjiezhou         let entry = self.find(&name)?;
220*f678331aShanjiezhou         return Ok((name, entry.metadata()?));
221*f678331aShanjiezhou     }
222*f678331aShanjiezhou 
223*f678331aShanjiezhou     fn fs(&self) -> Arc<(dyn FileSystem)> {
224*f678331aShanjiezhou         todo!()
225*f678331aShanjiezhou     }
226*f678331aShanjiezhou 
227*f678331aShanjiezhou     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
228*f678331aShanjiezhou         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
229*f678331aShanjiezhou     }
230*f678331aShanjiezhou }
231