Skip to content

Commit

Permalink
pipe implement
Browse files Browse the repository at this point in the history
  • Loading branch information
buhe committed Nov 18, 2021
1 parent 2ef287c commit d7fb49e
Show file tree
Hide file tree
Showing 16 changed files with 522 additions and 47 deletions.
2 changes: 1 addition & 1 deletion docs/插播 4 驱动 LCD.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ pub trait LCDHL {
}
```

LCD 是结构体,定义了 gpiohs
LCD 用的是 SPI 总线,

11 changes: 11 additions & 0 deletions os/src/fs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mod pipe;
mod stdio;

use crate::mmu::UserBuffer;
pub trait File : Send + Sync {
fn read(&self, buf: UserBuffer) -> usize;
fn write(&self, buf: UserBuffer) -> usize;
}

pub use pipe::{Pipe, make_pipe};
pub use stdio::{Stdin, Stdout};
165 changes: 165 additions & 0 deletions os/src/fs/pipe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use super::File;
use alloc::sync::{Arc, Weak};
use spin::Mutex;
use crate::mmu::{
UserBuffer,
};
use crate::task::suspend_current_and_run_next;

pub struct Pipe {
readable: bool,
writable: bool,
buffer: Arc<Mutex<PipeRingBuffer>>,
}

impl Pipe {
pub fn read_end_with_buffer(buffer: Arc<Mutex<PipeRingBuffer>>) -> Self {
Self {
readable: true,
writable: false,
buffer,
}
}
pub fn write_end_with_buffer(buffer: Arc<Mutex<PipeRingBuffer>>) -> Self {
Self {
readable: false,
writable: true,
buffer,
}
}
}

const RING_BUFFER_SIZE: usize = 32;

#[derive(Copy, Clone, PartialEq)]
enum RingBufferStatus {
FULL,
EMPTY,
NORMAL,
}

pub struct PipeRingBuffer {
arr: [u8; RING_BUFFER_SIZE],
head: usize,
tail: usize,
status: RingBufferStatus,
write_end: Option<Weak<Pipe>>,
}

impl PipeRingBuffer {
pub fn new() -> Self {
Self {
arr: [0; RING_BUFFER_SIZE],
head: 0,
tail: 0,
status: RingBufferStatus::EMPTY,
write_end: None,
}
}
pub fn set_write_end(&mut self, write_end: &Arc<Pipe>) {
self.write_end = Some(Arc::downgrade(write_end));
}
pub fn write_byte(&mut self, byte: u8) {
self.status = RingBufferStatus::NORMAL;
self.arr[self.tail] = byte;
self.tail = (self.tail + 1) % RING_BUFFER_SIZE;
if self.tail == self.head {
self.status = RingBufferStatus::FULL;
}
}
pub fn read_byte(&mut self) -> u8 {
self.status = RingBufferStatus::NORMAL;
let c = self.arr[self.head];
self.head = (self.head + 1) % RING_BUFFER_SIZE;
if self.head == self.tail {
self.status = RingBufferStatus::EMPTY;
}
c
}
pub fn available_read(&self) -> usize {
if self.status == RingBufferStatus::EMPTY {
0
} else {
if self.tail > self.head {
self.tail - self.head
} else {
self.tail + RING_BUFFER_SIZE - self.head
}
}
}
pub fn available_write(&self) -> usize {
if self.status == RingBufferStatus::FULL {
0
} else {
RING_BUFFER_SIZE - self.available_read()
}
}
pub fn all_write_ends_closed(&self) -> bool {
self.write_end.as_ref().unwrap().upgrade().is_none()
}
}

/// Return (read_end, write_end)
pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) {
let buffer = Arc::new(Mutex::new(PipeRingBuffer::new()));
let read_end = Arc::new(
Pipe::read_end_with_buffer(buffer.clone())
);
let write_end = Arc::new(
Pipe::write_end_with_buffer(buffer.clone())
);
buffer.lock().set_write_end(&write_end);
(read_end, write_end)
}

impl File for Pipe {
fn read(&self, buf: UserBuffer) -> usize {
assert_eq!(self.readable, true);
let mut buf_iter = buf.into_iter();
let mut read_size = 0usize;
loop {
let mut ring_buffer = self.buffer.lock();
let loop_read = ring_buffer.available_read();
if loop_read == 0 {
if ring_buffer.all_write_ends_closed() {
return read_size;
}
drop(ring_buffer);
suspend_current_and_run_next();
continue;
}
// read at most loop_read bytes
for _ in 0..loop_read {
if let Some(byte_ref) = buf_iter.next() {
unsafe { *byte_ref = ring_buffer.read_byte(); }
read_size += 1;
} else {
return read_size;
}
}
}
}
fn write(&self, buf: UserBuffer) -> usize {
assert_eq!(self.writable, true);
let mut buf_iter = buf.into_iter();
let mut write_size = 0usize;
loop {
let mut ring_buffer = self.buffer.lock();
let loop_write = ring_buffer.available_write();
if loop_write == 0 {
drop(ring_buffer);
suspend_current_and_run_next();
continue;
}
// write at most loop_write bytes
for _ in 0..loop_write {
if let Some(byte_ref) = buf_iter.next() {
ring_buffer.write_byte(unsafe { *byte_ref });
write_size += 1;
} else {
return write_size;
}
}
}
}
}
43 changes: 43 additions & 0 deletions os/src/fs/stdio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use super::File;
use crate::mmu::{UserBuffer};
use crate::scall_sbi::console_getchar;
use crate::task::suspend_current_and_run_next;

pub struct Stdin;

pub struct Stdout;

impl File for Stdin {
fn read(&self, mut user_buf: UserBuffer) -> usize {
assert_eq!(user_buf.len(), 1);
// busy loop
let mut c: usize;
loop {
c = console_getchar();
if c == 0 {
suspend_current_and_run_next();
continue;
} else {
break;
}
}
let ch = c as u8;
unsafe { user_buf.buffers[0].as_mut_ptr().write_volatile(ch); }
1
}
fn write(&self, _user_buf: UserBuffer) -> usize {
panic!("Cannot write to stdin!");
}
}

impl File for Stdout {
fn read(&self, _user_buf: UserBuffer) -> usize{
panic!("Cannot read from stdout!");
}
fn write(&self, user_buf: UserBuffer) -> usize {
for buffer in user_buf.buffers.iter() {
print!("{}", core::str::from_utf8(*buffer).unwrap());
}
user_buf.len()
}
}
34 changes: 27 additions & 7 deletions os/src/link_app.S
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.section .data
.global _num_app
_num_app:
.quad 8
.quad 10
.quad app_0_start
.quad app_1_start
.quad app_2_start
Expand All @@ -12,13 +12,17 @@ _num_app:
.quad app_5_start
.quad app_6_start
.quad app_7_start
.quad app_7_end
.quad app_8_start
.quad app_9_start
.quad app_9_end

.global _app_names
_app_names:
.string "forktest"
.string "hello"
.string "initproc"
.string "pipe_large_test"
.string "pipetest"
.string "power_3"
.string "power_5"
.string "power_7"
Expand Down Expand Up @@ -54,37 +58,53 @@ app_2_end:
.global app_3_end
.align 3
app_3_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_3"
.incbin "../user/target/riscv64gc-unknown-none-elf/release/pipe_large_test"
app_3_end:

.section .data
.global app_4_start
.global app_4_end
.align 3
app_4_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_5"
.incbin "../user/target/riscv64gc-unknown-none-elf/release/pipetest"
app_4_end:

.section .data
.global app_5_start
.global app_5_end
.align 3
app_5_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_7"
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_3"
app_5_end:

.section .data
.global app_6_start
.global app_6_end
.align 3
app_6_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/sleep"
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_5"
app_6_end:

.section .data
.global app_7_start
.global app_7_end
.align 3
app_7_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/user_shell"
.incbin "../user/target/riscv64gc-unknown-none-elf/release/power_7"
app_7_end:

.section .data
.global app_8_start
.global app_8_end
.align 3
app_8_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/sleep"
app_8_end:

.section .data
.global app_9_start
.global app_9_end
.align 3
app_9_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/user_shell"
app_9_end:
1 change: 1 addition & 0 deletions os/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod scall_sbi;
mod task;
mod timer;
mod trap;
mod fs;

// use k210_soc::sysctl::{self, clock};

Expand Down
1 change: 0 additions & 1 deletion os/src/mmu/memory_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ impl MemorySet {
.find(|(_, area)| area.vpn_range.get_start() == start_vpn)
{
area.unmap(&mut self.page_table);
println!("m area len is {}", self.areas.len());
self.areas.remove(idx);
}
}
Expand Down
2 changes: 2 additions & 0 deletions os/src/mmu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ mod address;
mod frame_allocator;
mod memory_set;
mod page_table;
mod user_buffer;

pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
use address::{StepByOne, VPNRange};
pub use frame_allocator::{frame_alloc, FrameTracker};
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
pub use page_table::{translated_byte_buffer, translated_refmut, translated_str, PageTableEntry};
use page_table::{PTEFlags, PageTable};
pub use user_buffer::UserBuffer;

pub fn init() {
// 启动分页器
Expand Down
Loading

0 comments on commit d7fb49e

Please sign in to comment.