1use alloc::{
4 sync::{Arc, Weak},
5 vec::{self, Vec},
6};
7
8use crate::{
9 sync::Mutex,
10 util::{ring_buffer::RingBuffer, user_buffer::UserBuffer},
11};
12
13pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) {
15 let buffer = Arc::new(Mutex::new(PipeRingBuffer::new()));
16 let read_end = Arc::new(Pipe::init_read_end(buffer.clone()));
17 let write_end = Arc::new(Pipe::init_write_end(buffer.clone()));
18 buffer.lock().set_write_end(&write_end);
19 (read_end, write_end)
20}
21
22pub struct Pipe {
24 readable: bool,
25 writable: bool,
26 buffer: Arc<Mutex<PipeRingBuffer>>,
27}
28
29impl Pipe {
30 pub fn init_read_end(buffer: Arc<Mutex<PipeRingBuffer>>) -> Self {
32 Self {
33 readable: true,
34 writable: false,
35 buffer,
36 }
37 }
38
39 pub fn init_write_end(buffer: Arc<Mutex<PipeRingBuffer>>) -> Self {
41 Self {
42 readable: false,
43 writable: true,
44 buffer,
45 }
46 }
47
48 pub fn read(&self, buf: UserBuffer) -> usize {
51 if buf.is_empty() {
52 return 0;
53 }
54 let cap = buf.len();
55 let mut data = Vec::with_capacity(cap);
56 {
57 let mut rb = self.buffer.lock();
58 while data.len() < cap {
59 match rb.read_byte() {
60 Some(b) => data.push(b),
61 None => break,
62 }
63 }
64 }
65 let n = data.len();
66 unsafe { buf.copy_to_user(&data) };
71 n
72 }
73
74 pub fn write(&self, buf: UserBuffer) -> usize {
77 if buf.is_empty() {
78 return 0;
79 }
80 let data = unsafe { buf.copy_from_user() };
84 let mut wrote = 0;
85 {
86 let mut rb = self.buffer.lock();
87 for byte in data {
88 if rb.write_byte(byte).is_ok() {
89 wrote += 1;
90 } else {
91 break;
92 }
93 }
94 }
95 wrote
96 }
97}
98
99pub(crate) struct PipeRingBuffer {
101 buffer: RingBuffer,
102 write_end: Option<Weak<Pipe>>,
103}
104
105impl PipeRingBuffer {
106 pub fn new() -> Self {
108 Self {
109 buffer: RingBuffer::new(),
110 write_end: None,
111 }
112 }
113
114 pub fn read_byte(&mut self) -> Option<u8> {
116 self.buffer.read_byte()
117 }
118
119 pub fn write_byte(&mut self, byte: u8) -> Result<(), ()> {
121 self.buffer.write_byte(byte)
122 }
123
124 pub fn available_space(&self) -> usize {
126 self.buffer.available_space()
127 }
128
129 pub fn set_write_end(&mut self, write_end: &Arc<Pipe>) {
131 self.write_end = Some(Arc::downgrade(write_end));
132 }
133
134 pub fn all_write_ends_dropped(&self) -> bool {
136 self.write_end
137 .as_ref()
138 .map_or(true, |weak| weak.upgrade().is_none())
139 }
140}