From cd2e2307d230341ad9e0c692aebe7b0c0610b055 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Tue, 3 Jan 2023 09:32:36 +0800 Subject: [PATCH 01/22] explicitly UART.init() in rust_main --- os/src/drivers/chardev/mod.rs | 1 + os/src/drivers/chardev/ns16550a.rs | 8 +++++++- os/src/main.rs | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/os/src/drivers/chardev/mod.rs b/os/src/drivers/chardev/mod.rs index de1446d5..64c168f3 100644 --- a/os/src/drivers/chardev/mod.rs +++ b/os/src/drivers/chardev/mod.rs @@ -6,6 +6,7 @@ use lazy_static::*; pub use ns16550a::NS16550a; pub trait CharDevice { + fn init(&self); fn read(&self) -> u8; fn write(&self, ch: u8); fn handle_irq(&self); diff --git a/os/src/drivers/chardev/ns16550a.rs b/os/src/drivers/chardev/ns16550a.rs index da290633..d10dd909 100644 --- a/os/src/drivers/chardev/ns16550a.rs +++ b/os/src/drivers/chardev/ns16550a.rs @@ -135,7 +135,7 @@ impl NS16550a { ns16550a: NS16550aRaw::new(BASE_ADDR), read_buffer: VecDeque::new(), }; - inner.ns16550a.init(); + //inner.ns16550a.init(); Self { inner: unsafe { UPIntrFreeCell::new(inner) }, condvar: Condvar::new(), @@ -144,6 +144,12 @@ impl NS16550a { } impl CharDevice for NS16550a { + fn init(&self){ + let mut inner = self.inner.exclusive_access(); + inner.ns16550a.init(); + drop(inner); + } + fn read(&self) -> u8 { loop { let mut inner = self.inner.exclusive_access(); diff --git a/os/src/main.rs b/os/src/main.rs index 299e4cf2..6e910852 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -28,6 +28,8 @@ mod task; mod timer; mod trap; +use crate::drivers::chardev::CharDevice; +use crate::drivers::chardev::UART; //use syscall::create_desktop; //for test core::arch::global_asm!(include_str!("entry.asm")); @@ -55,6 +57,7 @@ lazy_static! { pub fn rust_main() -> ! { clear_bss(); mm::init(); + UART.init(); println!("KERN: init gpu"); let _gpu = GPU_DEVICE.clone(); println!("KERN: init keyboard"); From d56c5d1229bd1addf9a61deab438105b44e34ac9 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Tue, 3 Jan 2023 18:34:45 +0800 Subject: [PATCH 02/22] update move_rect Fn --- os/src/gui/paint.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/os/src/gui/paint.rs b/os/src/gui/paint.rs index 0cdf60d3..b96d187b 100644 --- a/os/src/gui/paint.rs +++ b/os/src/gui/paint.rs @@ -28,7 +28,14 @@ impl DrawingBoard { .draw(&mut self.graphics) .ok(); } + fn unpaint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) + .draw(&mut self.graphics) + .ok(); + } pub fn move_rect(&mut self, dx: i32, dy: i32) { + self.unpaint(); self.latest_pos.x += dx; self.latest_pos.y += dy; self.paint(); From 737d07db13ed142cd64a36907a1248c4bcb2eef5 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 16:11:41 +0800 Subject: [PATCH 03/22] simple gui app can run now! --- os/src/gui/graphic.rs | 4 ++++ os/src/mm/address.rs | 1 + os/src/mm/frame_allocator.rs | 3 +++ os/src/mm/memory_set.rs | 14 +++++++++++++- os/src/mm/mod.rs | 4 ++-- os/src/syscall/gui.rs | 37 ++++++++++++++++++++++++++++++++++++ os/src/syscall/mod.rs | 6 ++++++ user/Cargo.toml | 1 + user/src/bin/gui_simple.rs | 35 ++++++++++++++++++++++++++++++++++ user/src/lib.rs | 6 ++++++ user/src/syscall.rs | 11 +++++++++++ 11 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 os/src/syscall/gui.rs create mode 100644 user/src/bin/gui_simple.rs diff --git a/os/src/gui/graphic.rs b/os/src/gui/graphic.rs index d13ad613..4c18a264 100644 --- a/os/src/gui/graphic.rs +++ b/os/src/gui/graphic.rs @@ -27,6 +27,10 @@ impl Graphics { let fb = self.drv.get_framebuffer(); fb.fill(0u8); } + + pub fn get_framebuffer(&self)-> &mut [u8] { + self.drv.get_framebuffer() + } } impl OriginDimensions for Graphics { diff --git a/os/src/mm/address.rs b/os/src/mm/address.rs index cf147a08..8792f625 100644 --- a/os/src/mm/address.rs +++ b/os/src/mm/address.rs @@ -260,3 +260,4 @@ where } } pub type VPNRange = SimpleRange; +pub type PPNRange = SimpleRange; diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 1ecfe993..a2803795 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -18,6 +18,9 @@ impl FrameTracker { } Self { ppn } } + pub fn new_nowrite(ppn: PhysPageNum) -> Self { + Self { ppn } + } } impl Debug for FrameTracker { diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 663b68d9..88756172 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -1,7 +1,7 @@ use super::{frame_alloc, FrameTracker}; use super::{PTEFlags, PageTable, PageTableEntry}; use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; -use super::{StepByOne, VPNRange}; +use super::{StepByOne, VPNRange, PPNRange}; use crate::config::{MEMORY_END, MMIO, PAGE_SIZE, TRAMPOLINE}; use crate::sync::UPIntrFreeCell; use alloc::collections::BTreeMap; @@ -78,6 +78,10 @@ impl MemorySet { } self.areas.push(map_area); } + pub fn push_noalloc(&mut self, mut map_area: MapArea, ppn_range: PPNRange) { + map_area.map_noalloc(&mut self.page_table, ppn_range); + self.areas.push(map_area); + } /// Mention that trampoline is not collected by areas. fn map_trampoline(&mut self) { self.page_table.map( @@ -301,6 +305,14 @@ impl MapArea { self.map_one(page_table, vpn); } } + pub fn map_noalloc(&mut self, page_table: &mut PageTable,ppn_range:PPNRange) { + for (vpn,ppn) in core::iter::zip(self.vpn_range,ppn_range) { + self.data_frames.insert(vpn, FrameTracker::new_nowrite(ppn)); + let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); + page_table.map(vpn, ppn, pte_flags); + } + } + pub fn unmap(&mut self, page_table: &mut PageTable) { for vpn in self.vpn_range { self.unmap_one(page_table, vpn); diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 34220c4a..9482a30d 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -4,11 +4,11 @@ mod heap_allocator; mod memory_set; mod page_table; -use address::VPNRange; +pub use address::{VPNRange, PPNRange}; pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum}; pub use frame_allocator::{frame_alloc, frame_dealloc, FrameTracker}; pub use memory_set::remap_test; -pub use memory_set::{kernel_token, MapPermission, MemorySet, KERNEL_SPACE}; +pub use memory_set::{kernel_token, MapPermission, MemorySet, MapArea, MapType, KERNEL_SPACE}; use page_table::PTEFlags; pub use page_table::{ translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable, diff --git a/os/src/syscall/gui.rs b/os/src/syscall/gui.rs new file mode 100644 index 00000000..00186042 --- /dev/null +++ b/os/src/syscall/gui.rs @@ -0,0 +1,37 @@ +use crate::mm::{MapArea, MapPermission, MapType, PPNRange, PhysAddr}; +use crate::task::current_process; + +//use crate::gui::*; +use crate::drivers::GPU_DEVICE; + +const FB_VADDR: usize = 0x10000000; + +pub fn sys_framebuffer() -> isize { + let gpu = GPU_DEVICE.clone(); + let fb = gpu.get_framebuffer(); + let len = fb.len(); + println!("[kernel] FrameBuffer: addr 0x{:X}, len {}", fb.as_ptr() as usize , len); + let fb_ppn = PhysAddr::from(fb.as_ptr() as usize).floor(); + let fb_end_ppn = PhysAddr::from(fb.as_ptr() as usize + len).ceil(); + + let current_process = current_process(); + let mut inner = current_process.inner_exclusive_access(); + let mem_set = &mut inner.memory_set; + + mem_set.push_noalloc( + MapArea::new( + (FB_VADDR as usize).into(), + (FB_VADDR + len as usize).into(), + MapType::Framed, + MapPermission::R | MapPermission::W | MapPermission::U, + ), + PPNRange::new(fb_ppn, fb_end_ppn), + ); + FB_VADDR as isize +} + +pub fn sys_framebuffer_flush() -> isize { + let gpu = GPU_DEVICE.clone(); + gpu.flush(); + 0 +} \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index fa4a4cf1..3f95b94e 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -25,16 +25,20 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022; const SYSCALL_CONDVAR_CREATE: usize = 1030; const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; +const SYSCALL_FRAMEBUFFER: usize = 2000; +const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; mod fs; mod process; mod sync; mod thread; +mod gui; use fs::*; use process::*; use sync::*; use thread::*; +use gui::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { @@ -65,6 +69,8 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]), SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]), SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), + SYSCALL_FRAMEBUFFER => sys_framebuffer(), + SYSCALL_FRAMEBUFFER_FLUSH => sys_framebuffer_flush(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/user/Cargo.toml b/user/Cargo.toml index a609f4de..d8d10ccf 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } +embedded-graphics = "0.7.1" [profile.release] debug = true diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs new file mode 100644 index 00000000..df4cfbb8 --- /dev/null +++ b/user/src/bin/gui_simple.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +use user_lib::{framebuffer, framebuffer_flush}; + +#[macro_use] +extern crate user_lib; + +// use embedded_graphics::pixelcolor::Rgb888; +// use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +// use embedded_graphics::primitives::Primitive; +// use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +// use embedded_graphics::{ +// draw_target::DrawTarget, +// prelude::{OriginDimensions}, +// }; +pub const VIRTGPU_XRES: usize = 1280; +pub const VIRTGPU_YRES: usize = 800; + +#[no_mangle] +pub fn main() -> i32 { + let fb_ptr =framebuffer() as *mut u8; + println!("Hello world from user mode program! 0x{:X} , len {}", fb_ptr as usize, VIRTGPU_XRES*VIRTGPU_YRES*4); + let fb= unsafe {core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_XRES*VIRTGPU_YRES*4 as usize)}; + for y in 0..800 { + for x in 0..1280 { + let idx = (y * 1280 + x) * 4; + fb[idx] = x as u8; + fb[idx + 1] = y as u8; + fb[idx + 2] = (x + y) as u8; + } + } + framebuffer_flush(); + 0 +} diff --git a/user/src/lib.rs b/user/src/lib.rs index 729eaef3..16d4abd8 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -198,6 +198,12 @@ pub fn condvar_signal(condvar_id: usize) { pub fn condvar_wait(condvar_id: usize, mutex_id: usize) { sys_condvar_wait(condvar_id, mutex_id); } +pub fn framebuffer() -> isize { + sys_framebuffer() +} +pub fn framebuffer_flush() -> isize { + sys_framebuffer_flush() +} #[macro_export] macro_rules! vstore { diff --git a/user/src/syscall.rs b/user/src/syscall.rs index b4bb67a0..330388c2 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -25,6 +25,8 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022; const SYSCALL_CONDVAR_CREATE: usize = 1030; const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; +const SYSCALL_FRAMEBUFFER: usize = 2000; +const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -154,3 +156,12 @@ pub fn sys_condvar_signal(condvar_id: usize) -> isize { pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize { syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0]) } + + +pub fn sys_framebuffer() -> isize { + syscall(SYSCALL_FRAMEBUFFER, [0, 0, 0]) +} + +pub fn sys_framebuffer_flush() -> isize { + syscall(SYSCALL_FRAMEBUFFER_FLUSH, [0, 0, 0]) +} \ No newline at end of file From 6e8fc39ad758e79a22f3559bae161c7580756cca Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 18:17:43 +0800 Subject: [PATCH 04/22] add embedded-graphics crate, but compiling error --- user/Cargo.toml | 1 + user/src/bin/embed_graph.rs | 173 ++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 user/src/bin/embed_graph.rs diff --git a/user/Cargo.toml b/user/Cargo.toml index d8d10ccf..6666a5a9 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -11,6 +11,7 @@ buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } embedded-graphics = "0.7.1" +# lazy_static = { version = "1.4.0", features = ["spin_no_std"] } [profile.release] debug = true diff --git a/user/src/bin/embed_graph.rs b/user/src/bin/embed_graph.rs new file mode 100644 index 00000000..bbe4faf2 --- /dev/null +++ b/user/src/bin/embed_graph.rs @@ -0,0 +1,173 @@ +#![no_std] +#![no_main] + +use user_lib::{framebuffer, framebuffer_flush}; + +#[macro_use] +extern crate user_lib; + +extern crate alloc; + +use alloc::sync::Arc; +use embedded_graphics::pixelcolor::Rgb888; +use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +use embedded_graphics::primitives::Primitive; +use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; + +pub const VIRTGPU_XRES: usize = 1280; +pub const VIRTGPU_YRES: usize = 800; +pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; + +const INIT_X: i32 = 640; +const INIT_Y: i32 = 400; +const RECT_SIZE: u32 = 40; + +// lazy_static::lazy_static! { +// pub static ref FB: Arc = Arc::new(Display::new(Size::new(VIRTGPU_XRES as u32, VIRTGPU_YRES as u32), Point::new(INIT_X, INIT_Y))); +// } + +#[derive(Clone)] +pub struct Display { + pub size: Size, + pub point: Point, + pub fb: Arc<&'static mut [u8]>, +} + +impl Display { + pub fn new(size: Size, point: Point) -> Self { + let fb_ptr = framebuffer() as *mut u8; + println!( + "Hello world from user mode program! 0x{:X} , len {}", + fb_ptr as usize, VIRTGPU_LEN + ); + let fb = + unsafe { Arc::new(core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize)) }; + + Self { size, point, fb } + } + // pub fn reset(&self) { + // let fb = self.drv.get_framebuffer(); + // fb.fill(0u8); + // } +} + +impl OriginDimensions for Display { + fn size(&self) -> Size { + self.size + } +} + +impl DrawTarget for Display { + type Color = Rgb888; + + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + let fb = self.fb.clone(); + //let mut arc_data_mut = Arc::make_mut(fb); + pixels.into_iter().for_each(|px| { + let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) + as usize + * 4; + if idx + 2 >= fb.len() { + return; + } + fb[idx] = px.1.b(); + fb[idx + 1] = px.1.g(); + fb[idx + 2] = px.1.r(); + }); + framebuffer_flush(); + Ok(()) + } +} + +pub struct DrawingBoard { + disp: Display, + latest_pos: Point, +} + +impl DrawingBoard { + pub fn new() -> Self { + Self { + disp: Display::new(Size::new(1280, 800), Point::new(0, 0)), + latest_pos: Point::new(INIT_X, INIT_Y), + } + } + fn paint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) + .draw(&mut self.disp) + .ok(); + } + fn unpaint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) + .draw(&mut self.disp) + .ok(); + } + pub fn move_rect(&mut self, dx: i32, dy: i32) { + self.unpaint(); + self.latest_pos.x += dx; + self.latest_pos.y += dy; + self.paint(); + } + + // pub fn reset(&mut self) { + // self.latest_pos = Point::new(INIT_X, INIT_Y); + // self.disp.reset(); + // } +} + +// lazy_static! { +// pub static ref DRAWING_BOARD: UPIntrFreeCell = +// unsafe { UPIntrFreeCell::new(DrawingBoard::new()) }; +// } + +// pub fn init_paint() { +// DRAWING_BOARD.exclusive_session(|ripple| { +// ripple.paint(); +// }); +// } + +// pub fn move_rect(dx: i32, dy: i32) { +// DRAWING_BOARD.exclusive_session(|ripple| { +// ripple.move_rect(dx, dy); +// }); +// } + +// pub fn reset() { +// DRAWING_BOARD.exclusive_session(|ripple| { +// ripple.reset(); +// }); +// } + +#[no_mangle] +pub fn main() -> i32 { + // let fb_ptr = framebuffer() as *mut u8; + let mut board=DrawingBoard::new(); + board.paint(); + for i in 0..100 { + board.latest_pos.x += i; + board.latest_pos.y += i; + board.paint(); + } + // println!( + // "Hello world from user mode program! 0x{:X} , len {}", + // fb_ptr as usize, VIRTGPU_LEN + // ); + // let fb = unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; + // for y in 0..800 { + // for x in 0..1280 { + // let idx = (y * 1280 + x) * 4; + // fb[idx] = x as u8; + // fb[idx + 1] = y as u8; + // fb[idx + 2] = (x + y) as u8; + // } + // } + // framebuffer_flush(); + 0 +} From 7522d056baee2cd5800c1c534eaf123393bbf0e1 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 18:53:48 +0800 Subject: [PATCH 05/22] fix compiling err in usr/src/bin/embed_graph.rs --- user/src/bin/embed_graph.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/user/src/bin/embed_graph.rs b/user/src/bin/embed_graph.rs index bbe4faf2..b7886a7e 100644 --- a/user/src/bin/embed_graph.rs +++ b/user/src/bin/embed_graph.rs @@ -27,11 +27,12 @@ const RECT_SIZE: u32 = 40; // pub static ref FB: Arc = Arc::new(Display::new(Size::new(VIRTGPU_XRES as u32, VIRTGPU_YRES as u32), Point::new(INIT_X, INIT_Y))); // } -#[derive(Clone)] +//#[derive(Clone)] pub struct Display { pub size: Size, pub point: Point, - pub fb: Arc<&'static mut [u8]>, + //pub fb: Arc<&'static mut [u8]>, + pub fb: &'static mut [u8], } impl Display { @@ -41,9 +42,9 @@ impl Display { "Hello world from user mode program! 0x{:X} , len {}", fb_ptr as usize, VIRTGPU_LEN ); - let fb = - unsafe { Arc::new(core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize)) }; - + // let fb = + // unsafe { Arc::new(core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize)) }; + let fb= unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; Self { size, point, fb } } // pub fn reset(&self) { @@ -67,18 +68,19 @@ impl DrawTarget for Display { where I: IntoIterator>, { - let fb = self.fb.clone(); + //let fb = self.fb.clone(); + //let fb = self.fb; //let mut arc_data_mut = Arc::make_mut(fb); pixels.into_iter().for_each(|px| { let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) as usize * 4; - if idx + 2 >= fb.len() { + if idx + 2 >= self.fb.len() { return; } - fb[idx] = px.1.b(); - fb[idx + 1] = px.1.g(); - fb[idx + 2] = px.1.r(); + self.fb[idx] = px.1.b(); + self.fb[idx + 1] = px.1.g(); + self.fb[idx + 2] = px.1.r(); }); framebuffer_flush(); Ok(()) From 9d59a8271fe8dd95364b38dd85d89e3bbe396684 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 19:14:20 +0800 Subject: [PATCH 06/22] clean os/user codes for graph show --- os/src/drivers/input/mod.rs | 20 +---------- os/src/gui/graphic.rs | 67 ----------------------------------- os/src/gui/mod.rs | 5 --- os/src/gui/paint.rs | 69 ------------------------------------- os/src/main.rs | 3 +- user/src/bin/embed_graph.rs | 67 +++-------------------------------- 6 files changed, 7 insertions(+), 224 deletions(-) delete mode 100644 os/src/gui/graphic.rs delete mode 100644 os/src/gui/mod.rs delete mode 100644 os/src/gui/paint.rs diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index cbe89334..0db76032 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -1,8 +1,5 @@ use crate::drivers::bus::virtio::VirtioHal; -use crate::{ - gui::{move_rect, reset}, - sync::UPIntrFreeCell, -}; +use crate::sync::UPIntrFreeCell; use alloc::sync::Arc; use core::any::Any; use virtio_drivers::{VirtIOHeader, VirtIOInput}; @@ -49,21 +46,6 @@ impl InputDevice for VirtIOInputWrapper { virtio_input_decoder::DecodeType::Key(key, r#type) => { if r#type == KeyType::Press { match key { - Key::C | Key::MouseLeft => { - reset(); - } - Key::W => { - move_rect(0, -10); - } - Key::S => { - move_rect(0, 10); - } - Key::A => { - move_rect(-10, 0); - } - Key::D => { - move_rect(10, 0); - } _ => {} } } diff --git a/os/src/gui/graphic.rs b/os/src/gui/graphic.rs deleted file mode 100644 index 4c18a264..00000000 --- a/os/src/gui/graphic.rs +++ /dev/null @@ -1,67 +0,0 @@ -use alloc::sync::Arc; -use embedded_graphics::{ - draw_target::DrawTarget, - pixelcolor::Rgb888, - prelude::{OriginDimensions, Point, RgbColor, Size}, -}; - -use crate::board::VIRTGPU_XRES; -use crate::drivers::{GpuDevice, GPU_DEVICE}; - -#[derive(Clone)] -pub struct Graphics { - pub size: Size, - pub point: Point, - pub drv: Arc, -} - -impl Graphics { - pub fn new(size: Size, point: Point) -> Self { - Self { - size, - point, - drv: GPU_DEVICE.clone(), - } - } - pub fn reset(&self) { - let fb = self.drv.get_framebuffer(); - fb.fill(0u8); - } - - pub fn get_framebuffer(&self)-> &mut [u8] { - self.drv.get_framebuffer() - } -} - -impl OriginDimensions for Graphics { - fn size(&self) -> Size { - self.size - } -} - -impl DrawTarget for Graphics { - type Color = Rgb888; - - type Error = core::convert::Infallible; - - fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, - { - let fb = self.drv.get_framebuffer(); - - pixels.into_iter().for_each(|px| { - let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) - as usize - * 4; - if idx + 2 >= fb.len() { - return; - } - fb[idx] = px.1.b(); - fb[idx + 1] = px.1.g(); - fb[idx + 2] = px.1.r(); - }); - self.drv.flush(); - Ok(()) - } -} diff --git a/os/src/gui/mod.rs b/os/src/gui/mod.rs deleted file mode 100644 index 766ded82..00000000 --- a/os/src/gui/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod graphic; -mod paint; - -use graphic::Graphics; -pub use paint::{init_paint, move_rect, reset}; diff --git a/os/src/gui/paint.rs b/os/src/gui/paint.rs deleted file mode 100644 index b96d187b..00000000 --- a/os/src/gui/paint.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::Graphics; -use crate::sync::UPIntrFreeCell; -use embedded_graphics::pixelcolor::Rgb888; -use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; -use embedded_graphics::primitives::Primitive; -use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; -use lazy_static::*; - -const INIT_X: i32 = 640; -const INIT_Y: i32 = 400; -const RECT_SIZE: u32 = 40; - -pub struct DrawingBoard { - graphics: Graphics, - latest_pos: Point, -} - -impl DrawingBoard { - pub fn new() -> Self { - Self { - graphics: Graphics::new(Size::new(1280, 800), Point::new(0, 0)), - latest_pos: Point::new(INIT_X, INIT_Y), - } - } - fn paint(&mut self) { - Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) - .draw(&mut self.graphics) - .ok(); - } - fn unpaint(&mut self) { - Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) - .draw(&mut self.graphics) - .ok(); - } - pub fn move_rect(&mut self, dx: i32, dy: i32) { - self.unpaint(); - self.latest_pos.x += dx; - self.latest_pos.y += dy; - self.paint(); - } - pub fn reset(&mut self) { - self.latest_pos = Point::new(INIT_X, INIT_Y); - self.graphics.reset(); - } -} - -lazy_static! { - pub static ref DRAWING_BOARD: UPIntrFreeCell = unsafe { UPIntrFreeCell::new(DrawingBoard::new()) }; -} - -pub fn init_paint() { - DRAWING_BOARD.exclusive_session(|ripple| { - ripple.paint(); - }); -} - -pub fn move_rect(dx: i32, dy: i32) { - DRAWING_BOARD.exclusive_session(|ripple| { - ripple.move_rect(dx, dy); - }); -} - -pub fn reset() { - DRAWING_BOARD.exclusive_session(|ripple| { - ripple.reset(); - }); -} diff --git a/os/src/main.rs b/os/src/main.rs index 6e910852..a220bd72 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -18,7 +18,6 @@ mod console; mod config; mod drivers; mod fs; -mod gui; mod lang_items; mod mm; mod sbi; @@ -70,7 +69,7 @@ pub fn rust_main() -> ! { timer::set_next_trigger(); board::device_init(); fs::list_apps(); - gui::init_paint(); + //gui::init_paint(); task::add_initproc(); *DEV_NON_BLOCKING_ACCESS.exclusive_access() = true; task::run_tasks(); diff --git a/user/src/bin/embed_graph.rs b/user/src/bin/embed_graph.rs index b7886a7e..3866994c 100644 --- a/user/src/bin/embed_graph.rs +++ b/user/src/bin/embed_graph.rs @@ -8,7 +8,6 @@ extern crate user_lib; extern crate alloc; -use alloc::sync::Arc; use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; use embedded_graphics::primitives::Primitive; @@ -23,11 +22,6 @@ const INIT_X: i32 = 640; const INIT_Y: i32 = 400; const RECT_SIZE: u32 = 40; -// lazy_static::lazy_static! { -// pub static ref FB: Arc = Arc::new(Display::new(Size::new(VIRTGPU_XRES as u32, VIRTGPU_YRES as u32), Point::new(INIT_X, INIT_Y))); -// } - -//#[derive(Clone)] pub struct Display { pub size: Size, pub point: Point, @@ -42,15 +36,10 @@ impl Display { "Hello world from user mode program! 0x{:X} , len {}", fb_ptr as usize, VIRTGPU_LEN ); - // let fb = - // unsafe { Arc::new(core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize)) }; - let fb= unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; + let fb = + unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; Self { size, point, fb } } - // pub fn reset(&self) { - // let fb = self.drv.get_framebuffer(); - // fb.fill(0u8); - // } } impl OriginDimensions for Display { @@ -68,9 +57,6 @@ impl DrawTarget for Display { where I: IntoIterator>, { - //let fb = self.fb.clone(); - //let fb = self.fb; - //let mut arc_data_mut = Arc::make_mut(fb); pixels.into_iter().for_each(|px| { let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) as usize @@ -117,59 +103,16 @@ impl DrawingBoard { self.latest_pos.y += dy; self.paint(); } - - // pub fn reset(&mut self) { - // self.latest_pos = Point::new(INIT_X, INIT_Y); - // self.disp.reset(); - // } } -// lazy_static! { -// pub static ref DRAWING_BOARD: UPIntrFreeCell = -// unsafe { UPIntrFreeCell::new(DrawingBoard::new()) }; -// } - -// pub fn init_paint() { -// DRAWING_BOARD.exclusive_session(|ripple| { -// ripple.paint(); -// }); -// } - -// pub fn move_rect(dx: i32, dy: i32) { -// DRAWING_BOARD.exclusive_session(|ripple| { -// ripple.move_rect(dx, dy); -// }); -// } - -// pub fn reset() { -// DRAWING_BOARD.exclusive_session(|ripple| { -// ripple.reset(); -// }); -// } - #[no_mangle] pub fn main() -> i32 { // let fb_ptr = framebuffer() as *mut u8; - let mut board=DrawingBoard::new(); - board.paint(); - for i in 0..100 { + let mut board = DrawingBoard::new(); + for i in 0..20 { board.latest_pos.x += i; board.latest_pos.y += i; - board.paint(); + board.paint(); } - // println!( - // "Hello world from user mode program! 0x{:X} , len {}", - // fb_ptr as usize, VIRTGPU_LEN - // ); - // let fb = unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; - // for y in 0..800 { - // for x in 0..1280 { - // let idx = (y * 1280 + x) * 4; - // fb[idx] = x as u8; - // fb[idx + 1] = y as u8; - // fb[idx + 2] = (x + y) as u8; - // } - // } - // framebuffer_flush(); 0 } From c3ce3724046250111776cf91596d0540ee7bc989 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 23:35:11 +0800 Subject: [PATCH 07/22] add get input_dev events in user app, but still have some problems --- os/Cargo.toml | 4 +- os/src/drivers/input/mod.rs | 122 +++++++++++++++++++++++++-------- os/src/main.rs | 3 +- os/src/syscall/input.rs | 17 +++++ os/src/syscall/mod.rs | 4 ++ user/src/bin/inputdev_event.rs | 21 ++++++ user/src/lib.rs | 5 ++ user/src/syscall.rs | 5 ++ 8 files changed, 151 insertions(+), 30 deletions(-) create mode 100644 os/src/syscall/input.rs create mode 100644 user/src/bin/inputdev_event.rs diff --git a/os/Cargo.toml b/os/Cargo.toml index f4b2d80c..633ec105 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -13,7 +13,9 @@ buddy_system_allocator = "0.6" bitflags = "1.2.1" xmas-elf = "0.7.0" volatile = "0.3" -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } +#virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "70b5850" } + easy-fs = { path = "../easy-fs" } virtio-input-decoder = "0.1.4" embedded-graphics = "0.7.1" diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index 0db76032..76c64f7c 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -1,5 +1,8 @@ use crate::drivers::bus::virtio::VirtioHal; -use crate::sync::UPIntrFreeCell; +use crate::sync::{Condvar, UPIntrFreeCell}; +use crate::task::schedule; +use alloc::collections::BTreeMap; +use alloc::collections::VecDeque; use alloc::sync::Arc; use core::any::Any; use virtio_drivers::{VirtIOHeader, VirtIOInput}; @@ -8,50 +11,113 @@ use virtio_input_decoder::{Decoder, Key, KeyType}; const VIRTIO5: usize = 0x10005000; const VIRTIO6: usize = 0x10006000; -struct VirtIOInputWrapper(UPIntrFreeCell>); +struct VirtIOInputInner { + virtio_input: VirtIOInput<'static, VirtioHal>, + events: VecDeque, +} + +struct VirtIOInputWrapper { + inner: UPIntrFreeCell, + //condvars: BTreeMap, + //condvar: Arc:: , + condvar:Condvar, +} pub trait InputDevice: Send + Sync + Any { + fn read_event(&self) -> u64; fn handle_irq(&self); + // fn events(&self) -> &VecDeque; + fn is_empty(&self) -> bool; } lazy_static::lazy_static!( pub static ref KEYBOARD_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO5)); pub static ref MOUSE_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO6)); + // pub static ref INPUT_CONDVAR: Arc:: = Arc::new(Condvar::new()); ); +// from virtio-drivers/src/input.rs +//const QUEUE_SIZE: u16 = 32; +// pub fn read_input_event() -> u64 { +// loop { + +// //let mut inner = self.inner.exclusive_access(); +// let kb=KEYBOARD_DEVICE.clone(); +// let evs = kb.events(); +// if let Some(event) = evs.pop_front() { +// return event; +// } else { +// let task_cx_ptr = INPUT_CONDVAR.clone().wait_no_sched(); +// drop(inner); +// schedule(task_cx_ptr); +// } +// } +// } impl VirtIOInputWrapper { pub fn new(addr: usize) -> Self { - Self(unsafe { - UPIntrFreeCell::new( - VirtIOInput::::new(&mut *(addr as *mut VirtIOHeader)).unwrap(), - ) - }) + let inner = VirtIOInputInner { + virtio_input: unsafe { + VirtIOInput::::new(&mut *(addr as *mut VirtIOHeader)).unwrap() + }, + events: VecDeque::new(), + }; + + // let mut condvars = BTreeMap::new(); + // let channels = QUEUE_SIZE; + // for i in 0..channels { + // let condvar = Condvar::new(); + // condvars.insert(i, condvar); + // } + + Self { + inner: unsafe { UPIntrFreeCell::new(inner) }, + //condvar: INPUT_CONDVAR.clone(), + condvar: Condvar::new(), + } } } impl InputDevice for VirtIOInputWrapper { - fn handle_irq(&self) { - let mut input = self.0.exclusive_access(); - input.ack_interrupt(); - while let Some(event) = input.pop_pending_event() { - let dtype = match Decoder::decode( - event.event_type as usize, - event.code as usize, - event.value as usize, - ) { - Ok(dtype) => dtype, - Err(_) => break, - }; - match dtype { - virtio_input_decoder::DecodeType::Key(key, r#type) => { - if r#type == KeyType::Press { - match key { - _ => {} - } - } - } - _ => {} + fn is_empty(&self) -> bool { + self.inner.exclusive_access().events.is_empty() + } + + fn read_event(&self) -> u64 { + loop { + let mut inner = self.inner.exclusive_access(); + if let Some(event) = inner.events.pop_front() { + return event; + } else { + let task_cx_ptr = self.condvar.wait_no_sched(); + drop(inner); + schedule(task_cx_ptr); } } } + + // fn events(&self) -> &VecDeque { + // &self.inner.exclusive_access().events + // } + + fn handle_irq(&self) { + let mut count = 0; + let mut result = 0; + let mut key = 0; + self.inner.exclusive_session(|inner| { + inner.virtio_input.ack_interrupt(); + while let Some((token, event)) = inner.virtio_input.pop_pending_event() { + count += 1; + key = token; + result = (event.event_type as u64) << 48 + | (event.code as u64) << 32 + | (event.value) as u64; + inner.events.push_back(result); + println!("[KERN] inputdev_handle_irq: event: {:x}", result); + } + }); + if count > 0 { + //self.condvars.get(&key).unwrap().signal(); + self.condvar.signal(); + }; + } } diff --git a/os/src/main.rs b/os/src/main.rs index a220bd72..7e5a20ac 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -3,8 +3,8 @@ #![feature(panic_info_message)] #![feature(alloc_error_handler)] +//use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE, INPUT_CONDVAR}; use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE}; - extern crate alloc; #[macro_use] @@ -59,6 +59,7 @@ pub fn rust_main() -> ! { UART.init(); println!("KERN: init gpu"); let _gpu = GPU_DEVICE.clone(); + //let _input_condvar = INPUT_CONDVAR.clone(); println!("KERN: init keyboard"); let _keyboard = KEYBOARD_DEVICE.clone(); println!("KERN: init mouse"); diff --git a/os/src/syscall/input.rs b/os/src/syscall/input.rs new file mode 100644 index 00000000..9f59710f --- /dev/null +++ b/os/src/syscall/input.rs @@ -0,0 +1,17 @@ +//use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE,INPUT_CONDVAR,read_input_event}; +use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE}; + +pub fn sys_event_get() ->isize { + let kb = KEYBOARD_DEVICE.clone(); + let mouse = MOUSE_DEVICE.clone(); + //let input=INPUT_CONDVAR.clone(); + //read_input_event() as isize + if !kb.is_empty(){ + kb.read_event() as isize + } else if !mouse.is_empty() { + mouse.read_event() as isize + } else { + 0 + } + +} \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 3f95b94e..729caa05 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -27,18 +27,21 @@ const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; +const SYSCALL_EVENT_GET: usize = 3000; mod fs; mod process; mod sync; mod thread; mod gui; +mod input; use fs::*; use process::*; use sync::*; use thread::*; use gui::*; +use input::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { @@ -71,6 +74,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), SYSCALL_FRAMEBUFFER => sys_framebuffer(), SYSCALL_FRAMEBUFFER_FLUSH => sys_framebuffer_flush(), + SYSCALL_EVENT_GET => sys_event_get(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/user/src/bin/inputdev_event.rs b/user/src/bin/inputdev_event.rs new file mode 100644 index 00000000..1e5b5a10 --- /dev/null +++ b/user/src/bin/inputdev_event.rs @@ -0,0 +1,21 @@ +#![no_std] +#![no_main] + +use user_lib::{event_get}; + +#[macro_use] +extern crate user_lib; + +#[no_mangle] +pub fn main() -> i32 { + println!("Input device event test"); + let mut event=0; + for _ in 0..3 { + while event==0 { + event = event_get(); + } + println!("event: {:?}", event); + } + + 0 +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index 16d4abd8..dd7261ee 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -205,6 +205,11 @@ pub fn framebuffer_flush() -> isize { sys_framebuffer_flush() } +pub fn event_get() -> isize { + sys_event_get() +} + + #[macro_export] macro_rules! vstore { ($var_ref: expr, $value: expr) => { diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 330388c2..6d97b7e7 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -27,6 +27,7 @@ const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; +const SYSCALL_EVENT_GET: usize = 3000; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -164,4 +165,8 @@ pub fn sys_framebuffer() -> isize { pub fn sys_framebuffer_flush() -> isize { syscall(SYSCALL_FRAMEBUFFER_FLUSH, [0, 0, 0]) +} + +pub fn sys_event_get() -> isize { + syscall(SYSCALL_EVENT_GET, [0, 0, 0]) } \ No newline at end of file From af05b65e7fe6ad2b589cca128466d695e214be03 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 23:36:05 +0800 Subject: [PATCH 08/22] udpate gui apps, uart and gpu can work together --- user/src/bin/embed_graph.rs | 5 +- user/src/bin/embed_graph_uart.rs | 124 +++++++++++++++++++++++++++++++ user/src/bin/gui_simple.rs | 12 +-- 3 files changed, 128 insertions(+), 13 deletions(-) create mode 100644 user/src/bin/embed_graph_uart.rs diff --git a/user/src/bin/embed_graph.rs b/user/src/bin/embed_graph.rs index 3866994c..e1b3ea83 100644 --- a/user/src/bin/embed_graph.rs +++ b/user/src/bin/embed_graph.rs @@ -1,13 +1,12 @@ #![no_std] #![no_main] -use user_lib::{framebuffer, framebuffer_flush}; - #[macro_use] extern crate user_lib; - extern crate alloc; +use user_lib::{framebuffer, framebuffer_flush}; + use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; use embedded_graphics::primitives::Primitive; diff --git a/user/src/bin/embed_graph_uart.rs b/user/src/bin/embed_graph_uart.rs new file mode 100644 index 00000000..9e0933b0 --- /dev/null +++ b/user/src/bin/embed_graph_uart.rs @@ -0,0 +1,124 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::console::getchar; +use user_lib::{framebuffer, framebuffer_flush}; + +use embedded_graphics::pixelcolor::Rgb888; +use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +use embedded_graphics::primitives::Primitive; +use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; + +pub const VIRTGPU_XRES: usize = 1280; +pub const VIRTGPU_YRES: usize = 800; +pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; + +const INIT_X: i32 = 640; +const INIT_Y: i32 = 400; +const RECT_SIZE: u32 = 40; + +pub struct Display { + pub size: Size, + pub point: Point, + //pub fb: Arc<&'static mut [u8]>, + pub fb: &'static mut [u8], +} + +impl Display { + pub fn new(size: Size, point: Point) -> Self { + let fb_ptr = framebuffer() as *mut u8; + println!( + "Hello world from user mode program! 0x{:X} , len {}", + fb_ptr as usize, VIRTGPU_LEN + ); + let fb = + unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; + Self { size, point, fb } + } +} + +impl OriginDimensions for Display { + fn size(&self) -> Size { + self.size + } +} + +impl DrawTarget for Display { + type Color = Rgb888; + + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + pixels.into_iter().for_each(|px| { + let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) + as usize + * 4; + if idx + 2 >= self.fb.len() { + return; + } + self.fb[idx] = px.1.b(); + self.fb[idx + 1] = px.1.g(); + self.fb[idx + 2] = px.1.r(); + }); + framebuffer_flush(); + Ok(()) + } +} + +pub struct DrawingBoard { + disp: Display, + latest_pos: Point, +} + +impl DrawingBoard { + pub fn new() -> Self { + Self { + disp: Display::new(Size::new(1280, 800), Point::new(0, 0)), + latest_pos: Point::new(INIT_X, INIT_Y), + } + } + fn paint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) + .draw(&mut self.disp) + .ok(); + } + fn unpaint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) + .draw(&mut self.disp) + .ok(); + } + pub fn move_rect(&mut self, dx: i32, dy: i32) { + self.unpaint(); + self.latest_pos.x += dx; + self.latest_pos.y += dy; + self.paint(); + } +} + +const LF: u8 = 0x0au8; +const CR: u8 = 0x0du8; +#[no_mangle] +pub fn main() -> i32 { + // let fb_ptr = framebuffer() as *mut u8; + let mut board = DrawingBoard::new(); + for i in 0..20 { + let c=getchar(); + if c == LF || c == CR { + break; + } + board.latest_pos.x += i; + board.latest_pos.y += i; + board.paint(); + } + 0 +} diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs index df4cfbb8..83fb721d 100644 --- a/user/src/bin/gui_simple.rs +++ b/user/src/bin/gui_simple.rs @@ -1,19 +1,11 @@ #![no_std] #![no_main] -use user_lib::{framebuffer, framebuffer_flush}; - #[macro_use] extern crate user_lib; -// use embedded_graphics::pixelcolor::Rgb888; -// use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; -// use embedded_graphics::primitives::Primitive; -// use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; -// use embedded_graphics::{ -// draw_target::DrawTarget, -// prelude::{OriginDimensions}, -// }; +use user_lib::{framebuffer, framebuffer_flush}; + pub const VIRTGPU_XRES: usize = 1280; pub const VIRTGPU_YRES: usize = 800; From fbb592369ba03a49d647c7fd817b0c3294f29d9b Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sun, 8 Jan 2023 22:41:41 +0800 Subject: [PATCH 09/22] Add snake gui app and update os/usr parts. Now snake can run! --- os/Cargo.toml | 3 +- os/src/boards/qemu.rs | 2 +- os/src/drivers/chardev/ns16550a.rs | 6 +- os/src/drivers/input/mod.rs | 5 +- os/src/syscall/fs.rs | 2 +- os/src/syscall/input.rs | 12 + os/src/syscall/mod.rs | 2 + user/Cargo.toml | 9 +- user/src/bin/{embed_graph.rs => gui_rect.rs} | 0 user/src/bin/gui_snake.rs | 403 ++++++++++++++++++ .../bin/{embed_graph_uart.rs => gui_uart.rs} | 0 user/src/bin/random_num.rs | 16 + user/src/lib.rs | 7 + user/src/syscall.rs | 5 + 14 files changed, 457 insertions(+), 15 deletions(-) rename user/src/bin/{embed_graph.rs => gui_rect.rs} (100%) create mode 100644 user/src/bin/gui_snake.rs rename user/src/bin/{embed_graph_uart.rs => gui_uart.rs} (100%) create mode 100644 user/src/bin/random_num.rs diff --git a/os/Cargo.toml b/os/Cargo.toml index 633ec105..ded2765e 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -15,9 +15,8 @@ xmas-elf = "0.7.0" volatile = "0.3" #virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "70b5850" } - easy-fs = { path = "../easy-fs" } -virtio-input-decoder = "0.1.4" +#virtio-input-decoder = "0.1.4" embedded-graphics = "0.7.1" tinybmp = "0.3.1" diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs index ffabff6a..0bc0f4c2 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -12,7 +12,7 @@ pub type CharDeviceImpl = crate::drivers::chardev::NS16550a; pub const VIRT_PLIC: usize = 0xC00_0000; pub const VIRT_UART: usize = 0x1000_0000; - +#[allow(unused)] pub const VIRTGPU_XRES: u32 = 1280; #[allow(unused)] pub const VIRTGPU_YRES: u32 = 800; diff --git a/os/src/drivers/chardev/ns16550a.rs b/os/src/drivers/chardev/ns16550a.rs index d10dd909..127a4ce1 100644 --- a/os/src/drivers/chardev/ns16550a.rs +++ b/os/src/drivers/chardev/ns16550a.rs @@ -131,7 +131,7 @@ pub struct NS16550a { impl NS16550a { pub fn new() -> Self { - let mut inner = NS16550aInner { + let inner = NS16550aInner { ns16550a: NS16550aRaw::new(BASE_ADDR), read_buffer: VecDeque::new(), }; @@ -141,6 +141,10 @@ impl NS16550a { condvar: Condvar::new(), } } + + pub fn read_buffer_is_empty(&self) -> bool { + self.inner.exclusive_session(|inner| inner.read_buffer.is_empty()) + } } impl CharDevice for NS16550a { diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index 76c64f7c..857f12a3 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -1,12 +1,10 @@ use crate::drivers::bus::virtio::VirtioHal; use crate::sync::{Condvar, UPIntrFreeCell}; use crate::task::schedule; -use alloc::collections::BTreeMap; use alloc::collections::VecDeque; use alloc::sync::Arc; use core::any::Any; use virtio_drivers::{VirtIOHeader, VirtIOInput}; -use virtio_input_decoder::{Decoder, Key, KeyType}; const VIRTIO5: usize = 0x10005000; const VIRTIO6: usize = 0x10006000; @@ -112,7 +110,8 @@ impl InputDevice for VirtIOInputWrapper { | (event.code as u64) << 32 | (event.value) as u64; inner.events.push_back(result); - println!("[KERN] inputdev_handle_irq: event: {:x}", result); + // for test + //println!("[KERN] inputdev_handle_irq: event: {:x}", result); } }); if count > 0 { diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 27588257..af1585c1 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -96,4 +96,4 @@ pub fn sys_dup(fd: usize) -> isize { let new_fd = inner.alloc_fd(); inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap())); new_fd as isize -} +} \ No newline at end of file diff --git a/os/src/syscall/input.rs b/os/src/syscall/input.rs index 9f59710f..7a282598 100644 --- a/os/src/syscall/input.rs +++ b/os/src/syscall/input.rs @@ -14,4 +14,16 @@ pub fn sys_event_get() ->isize { 0 } +} + +use crate::drivers::chardev::UART; + +/// check UART's read-buffer is empty or not +pub fn sys_key_pressed() -> isize { + let res =!UART.read_buffer_is_empty(); + if res { + 1 + } else { + 0 + } } \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 729caa05..d883d52d 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -28,6 +28,7 @@ const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; const SYSCALL_EVENT_GET: usize = 3000; +const SYSCALL_KEY_PRESSED: usize = 3001; mod fs; mod process; @@ -75,6 +76,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_FRAMEBUFFER => sys_framebuffer(), SYSCALL_FRAMEBUFFER_FLUSH => sys_framebuffer_flush(), SYSCALL_EVENT_GET => sys_event_get(), + SYSCALL_KEY_PRESSED => sys_key_pressed(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/user/Cargo.toml b/user/Cargo.toml index 6666a5a9..35e06d5d 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -11,11 +11,6 @@ buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } embedded-graphics = "0.7.1" -# lazy_static = { version = "1.4.0", features = ["spin_no_std"] } - +oorandom ="11" [profile.release] -debug = true - -# [features] -# board_qemu = [] -# board_k210 = [] \ No newline at end of file +debug = true \ No newline at end of file diff --git a/user/src/bin/embed_graph.rs b/user/src/bin/gui_rect.rs similarity index 100% rename from user/src/bin/embed_graph.rs rename to user/src/bin/gui_rect.rs diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs new file mode 100644 index 00000000..c0148725 --- /dev/null +++ b/user/src/bin/gui_snake.rs @@ -0,0 +1,403 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::console::getchar; +use user_lib::{framebuffer, framebuffer_flush, key_pressed, sleep}; + +use embedded_graphics::pixelcolor::*; +use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +use embedded_graphics::primitives::Primitive; +use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +use embedded_graphics::Pixel; +use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; +use oorandom; //random generator + +pub const VIRTGPU_XRES: usize = 1280; +pub const VIRTGPU_YRES: usize = 800; +pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; + +pub struct Display { + pub size: Size, + pub point: Point, + pub fb: &'static mut [u8], +} + +impl Display { + pub fn new(size: Size, point: Point) -> Self { + let fb_ptr = framebuffer() as *mut u8; + println!( + "Hello world from user mode program! 0x{:X} , len {}", + fb_ptr as usize, VIRTGPU_LEN + ); + let fb = + unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; + Self { size, point, fb } + } +} + +impl OriginDimensions for Display { + fn size(&self) -> Size { + self.size + } +} + +impl DrawTarget for Display { + type Color = Rgb888; + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + pixels.into_iter().for_each(|px| { + let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) + as usize + * 4; + if idx + 2 >= self.fb.len() { + return; + } + self.fb[idx] = px.1.b(); + self.fb[idx + 1] = px.1.g(); + self.fb[idx + 2] = px.1.r(); + }); + framebuffer_flush(); + Ok(()) + } +} +struct Snake { + parts: [Pixel; MAX_SIZE], + len: usize, + direction: Direction, + size_x: u32, + size_y: u32, +} + +struct SnakeIntoIterator<'a, T: PixelColor, const MAX_SIZE: usize> { + snake: &'a Snake, + index: usize, +} + +impl<'a, T: PixelColor, const MAX_SIZE: usize> IntoIterator for &'a Snake { + type Item = Pixel; + type IntoIter = SnakeIntoIterator<'a, T, MAX_SIZE>; + + fn into_iter(self) -> Self::IntoIter { + SnakeIntoIterator { + snake: self, + index: 0, + } + } +} + +impl<'a, T: PixelColor, const MAX_SIZE: usize> Iterator for SnakeIntoIterator<'a, T, MAX_SIZE> { + type Item = Pixel; + + fn next(&mut self) -> Option { + let cur = self.snake.parts[self.index]; + if self.index < self.snake.len { + self.index += 1; + return Some(cur); + } + None + } +} + +impl Snake { + fn new(color: T, size_x: u32, size_y: u32) -> Snake { + Snake { + parts: [Pixel::(Point { x: 0, y: 0 }, color); MAX_SIZE], + len: 1, + direction: Direction::None, + size_x, + size_y, + } + } + fn set_direction(&mut self, direction: Direction) { + self.direction = direction; + } + fn contains(&self, this: Point) -> bool { + for part in self.into_iter() { + if part.0 == this { + return true; + }; + } + false + } + fn grow(&mut self) { + if self.len < MAX_SIZE - 1 { + self.len += 1; + } + } + fn make_step(&mut self) { + let mut i = self.len; + while i > 0 { + self.parts[i] = self.parts[i - 1]; + i -= 1; + } + match self.direction { + Direction::Left => { + if self.parts[0].0.x == 0 { + self.parts[0].0.x = (self.size_x - 1) as i32; + } else { + self.parts[0].0.x -= 1; + } + } + Direction::Right => { + if self.parts[0].0.x == (self.size_x - 1) as i32 { + self.parts[0].0.x = 0; + } else { + self.parts[0].0.x += 1; + } + } + Direction::Up => { + if self.parts[0].0.y == 0 { + self.parts[0].0.y = (self.size_y - 1) as i32; + } else { + self.parts[0].0.y -= 1; + } + } + Direction::Down => { + if self.parts[0].0.y == (self.size_y - 1) as i32 { + self.parts[0].0.y = 0; + } else { + self.parts[0].0.y += 1; + } + } + Direction::None => {} + } + } +} + +struct Food { + size_x: u32, + size_y: u32, + place: Pixel, + rng: oorandom::Rand32, +} + +impl Food { + pub fn new(color: T, size_x: u32, size_y: u32) -> Self { + let seed = 4; + let rng = oorandom::Rand32::new(seed); + Food { + size_x, + size_y, + place: Pixel(Point { x: 0, y: 0 }, color), + rng, + } + } + fn replace<'a, const MAX_SIZE: usize>(&mut self, iter_source: &Snake) { + let mut p: Point; + 'outer: loop { + let random_number = self.rng.rand_u32(); + let blocked_positions = iter_source.into_iter(); + p = Point { + x: ((random_number >> 24) as u16 % self.size_x as u16).into(), + y: ((random_number >> 16) as u16 % self.size_y as u16).into(), + }; + for blocked_position in blocked_positions { + if p == blocked_position.0 { + continue 'outer; + } + } + break; + } + self.place = Pixel:: { + 0: p, + 1: self.place.1, + } + } + fn get_pixel(&self) -> Pixel { + self.place + } +} + +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum Direction { + Left, + Right, + Up, + Down, + None, +} + +pub struct SnakeGame { + snake: Snake, + food: Food, + food_age: u32, + food_lifetime: u32, + size_x: u32, + size_y: u32, + scale_x: u32, + scale_y: u32, +} + +impl SnakeGame { + pub fn new( + size_x: u32, + size_y: u32, + scale_x: u32, + scale_y: u32, + snake_color: T, + food_color: T, + food_lifetime: u32, + ) -> Self { + let snake = Snake::::new(snake_color, size_x / scale_x, size_y / scale_y); + let mut food = Food::::new(food_color, size_x / scale_x, size_y / scale_y); + food.replace(&snake); + SnakeGame { + snake, + food, + food_age: 0, + food_lifetime, + size_x, + size_y, + scale_x, + scale_y, + } + } + pub fn set_direction(&mut self, direction: Direction) { + self.snake.set_direction(direction); + } + pub fn draw(&mut self, target: &mut D) -> () + where + D: DrawTarget, + { + self.snake.make_step(); + let hit = self.snake.contains(self.food.get_pixel().0); + if hit { + self.snake.grow(); + } + self.food_age += 1; + if self.food_age >= self.food_lifetime || hit { + self.food.replace(&self.snake); + self.food_age = 0; + } + + let mut scaled_display = ScaledDisplay:: { + real_display: target, + size_x: self.size_x / self.scale_x, + size_y: self.size_y / self.scale_y, + scale_x: self.scale_x, + scale_y: self.scale_y, + }; + + for part in self.snake.into_iter() { + _ = part.draw(&mut scaled_display); + } + _ = self.food.get_pixel().draw(&mut scaled_display); + } +} + +/// A dummy DrawTarget implementation that can magnify each pixel so the user code does not need to adapt for scaling things +struct ScaledDisplay<'a, T: DrawTarget> { + real_display: &'a mut T, + size_x: u32, + size_y: u32, + scale_x: u32, + scale_y: u32, +} + +impl<'a, T: DrawTarget> DrawTarget for ScaledDisplay<'a, T> { + type Color = T::Color; + type Error = T::Error; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + let style = PrimitiveStyle::with_fill(pixel.1); + Rectangle::new( + Point::new( + pixel.0.x * self.scale_x as i32, + pixel.0.y * self.scale_y as i32, + ), + Size::new(self.scale_x as u32, self.scale_y as u32), + ) + .into_styled(style) + .draw(self.real_display)?; + } + Ok(()) + } +} + +impl<'a, T: DrawTarget> OriginDimensions for ScaledDisplay<'a, T> { + fn size(&self) -> Size { + Size::new(self.size_x as u32, self.size_y as u32) + } +} + +#[cfg(test)] +mod tests { + + use crate::Snake; + use embedded_graphics::pixelcolor::*; + use embedded_graphics::prelude::*; + + #[test] + fn snake_basic() { + let mut snake = Snake::::new(Rgb888::RED, 8, 8); + snake.set_direction(crate::Direction::Right); + assert_eq!( + Pixel::(Point { x: 0, y: 0 }, Rgb888::RED), + snake.into_iter().next().unwrap() + ); + snake.make_step(); + assert_eq!( + Pixel::(Point { x: 1, y: 0 }, Rgb888::RED), + snake.into_iter().nth(0).unwrap() + ); + assert_eq!( + Pixel::(Point { x: 0, y: 0 }, Rgb888::RED), + snake.into_iter().nth(1).unwrap() + ); + snake.set_direction(crate::Direction::Down); + snake.make_step(); + assert_eq!( + Pixel::(Point { x: 1, y: 1 }, Rgb888::RED), + snake.into_iter().nth(0).unwrap() + ); + assert_eq!( + Pixel::(Point { x: 1, y: 0 }, Rgb888::RED), + snake.into_iter().nth(1).unwrap() + ); + assert_eq!( + Pixel::(Point { x: 0, y: 0 }, Rgb888::RED), + snake.into_iter().nth(2).unwrap() + ); + assert_eq!(true, snake.contains(Point { x: 0, y: 0 })); + assert_eq!(true, snake.contains(Point { x: 1, y: 0 })); + assert_eq!(true, snake.contains(Point { x: 1, y: 1 })); + } +} + +const LF: u8 = 0x0au8; +const CR: u8 = 0x0du8; +#[no_mangle] +pub fn main() -> i32 { + let mut disp = Display::new(Size::new(1280, 800), Point::new(0, 0)); + let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 50); + loop { + if key_pressed() { + let c = getchar(); + match c { + LF => break, + CR => break, + b'w' => game.set_direction(Direction::Up), + b's' => game.set_direction(Direction::Down), + b'a' => game.set_direction(Direction::Left), + b'd' => game.set_direction(Direction::Right), + _ => (), + } + } + let _ = disp.clear(Rgb888::BLACK).unwrap(); + game.draw(&mut disp); + sleep(10); + } + 0 +} diff --git a/user/src/bin/embed_graph_uart.rs b/user/src/bin/gui_uart.rs similarity index 100% rename from user/src/bin/embed_graph_uart.rs rename to user/src/bin/gui_uart.rs diff --git a/user/src/bin/random_num.rs b/user/src/bin/random_num.rs new file mode 100644 index 00000000..dd9ac00d --- /dev/null +++ b/user/src/bin/random_num.rs @@ -0,0 +1,16 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +use oorandom; + +#[no_mangle] +pub fn main() -> i32 { + println!("random num program!"); + let seed = 4; + let mut rng = oorandom::Rand32::new(seed); + println!("OORandom: Random number 32bit: {}", rng.rand_i32()); + println!("OORandom: Random number range: {}", rng.rand_range(1..100)); + 0 +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index dd7261ee..31ce9ba2 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -209,6 +209,13 @@ pub fn event_get() -> isize { sys_event_get() } +pub fn key_pressed() -> bool { + if sys_key_pressed() == 1 { + true + } else { + false + } +} #[macro_export] macro_rules! vstore { diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 6d97b7e7..530ea209 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -28,6 +28,7 @@ const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; const SYSCALL_EVENT_GET: usize = 3000; +const SYSCALL_KEY_PRESSED: usize = 3001; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -169,4 +170,8 @@ pub fn sys_framebuffer_flush() -> isize { pub fn sys_event_get() -> isize { syscall(SYSCALL_EVENT_GET, [0, 0, 0]) +} + +pub fn sys_key_pressed() -> isize { + syscall(SYSCALL_KEY_PRESSED, [0, 0, 0]) } \ No newline at end of file From b262781203d97f0579e2037abf752d97f36e60f9 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Tue, 10 Jan 2023 16:29:36 +0800 Subject: [PATCH 10/22] fix bug in impl Drop for FrameTracker, for the correctly mapping/unmapping display buffer in app --- os/src/mm/frame_allocator.rs | 10 +++++++--- os/src/mm/memory_set.rs | 6 +++++- os/src/syscall/gui.rs | 2 +- user/src/bin/gui_rect.rs | 1 + user/src/bin/gui_snake.rs | 1 + user/src/bin/gui_uart.rs | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index a2803795..275fb174 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -7,6 +7,7 @@ use lazy_static::*; pub struct FrameTracker { pub ppn: PhysPageNum, + pub nodrop: bool, } impl FrameTracker { @@ -16,10 +17,10 @@ impl FrameTracker { for i in bytes_array { *i = 0; } - Self { ppn } + Self { ppn, nodrop: false } } - pub fn new_nowrite(ppn: PhysPageNum) -> Self { - Self { ppn } + pub fn new_noalloc(ppn: PhysPageNum) -> Self { + Self { ppn, nodrop: true } } } @@ -31,6 +32,9 @@ impl Debug for FrameTracker { impl Drop for FrameTracker { fn drop(&mut self) { + if self.nodrop { + return; + } frame_dealloc(self.ppn); } } diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 88756172..bec0b934 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -290,6 +290,9 @@ impl MapArea { ppn = frame.ppn; self.data_frames.insert(vpn, frame); } + MapType::Noalloc => { + panic!("Noalloc should not be mapped"); + } } let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); page_table.map(vpn, ppn, pte_flags); @@ -307,7 +310,7 @@ impl MapArea { } pub fn map_noalloc(&mut self, page_table: &mut PageTable,ppn_range:PPNRange) { for (vpn,ppn) in core::iter::zip(self.vpn_range,ppn_range) { - self.data_frames.insert(vpn, FrameTracker::new_nowrite(ppn)); + self.data_frames.insert(vpn, FrameTracker::new_noalloc(ppn)); let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); page_table.map(vpn, ppn, pte_flags); } @@ -346,6 +349,7 @@ impl MapArea { pub enum MapType { Identical, Framed, + Noalloc, } bitflags! { diff --git a/os/src/syscall/gui.rs b/os/src/syscall/gui.rs index 00186042..5d41c0c6 100644 --- a/os/src/syscall/gui.rs +++ b/os/src/syscall/gui.rs @@ -22,7 +22,7 @@ pub fn sys_framebuffer() -> isize { MapArea::new( (FB_VADDR as usize).into(), (FB_VADDR + len as usize).into(), - MapType::Framed, + MapType::Noalloc, MapPermission::R | MapPermission::W | MapPermission::U, ), PPNRange::new(fb_ppn, fb_end_ppn), diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_rect.rs index e1b3ea83..e9007f60 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_rect.rs @@ -108,6 +108,7 @@ impl DrawingBoard { pub fn main() -> i32 { // let fb_ptr = framebuffer() as *mut u8; let mut board = DrawingBoard::new(); + let _ = board.disp.clear(Rgb888::BLACK).unwrap(); for i in 0..20 { board.latest_pos.x += i; board.latest_pos.y += i; diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs index c0148725..ce36b2e8 100644 --- a/user/src/bin/gui_snake.rs +++ b/user/src/bin/gui_snake.rs @@ -382,6 +382,7 @@ const CR: u8 = 0x0du8; pub fn main() -> i32 { let mut disp = Display::new(Size::new(1280, 800), Point::new(0, 0)); let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 50); + let _ = disp.clear(Rgb888::BLACK).unwrap(); loop { if key_pressed() { let c = getchar(); diff --git a/user/src/bin/gui_uart.rs b/user/src/bin/gui_uart.rs index 9e0933b0..c9577a4f 100644 --- a/user/src/bin/gui_uart.rs +++ b/user/src/bin/gui_uart.rs @@ -111,6 +111,7 @@ const CR: u8 = 0x0du8; pub fn main() -> i32 { // let fb_ptr = framebuffer() as *mut u8; let mut board = DrawingBoard::new(); + let _ = board.disp.clear(Rgb888::BLACK).unwrap(); for i in 0..20 { let c=getchar(); if c == LF || c == CR { From 7f04d674cab9c9eaa428f45f9bb7860579dca227 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 11 Jan 2023 09:02:54 -0800 Subject: [PATCH 11/22] Split user_lib into modules && provide Display in user_lib --- user/src/bin/gui_rect.rs | 66 +-------------- user/src/bin/gui_simple.rs | 27 +++--- user/src/bin/gui_snake.rs | 56 +------------ user/src/file.rs | 30 +++++++ user/src/io.rs | 78 +++++++++++++++++ user/src/lib.rs | 166 ++----------------------------------- user/src/sync.rs | 32 +++++++ user/src/task.rs | 82 ++++++++++++++++++ 8 files changed, 248 insertions(+), 289 deletions(-) create mode 100644 user/src/file.rs create mode 100644 user/src/io.rs create mode 100644 user/src/sync.rs create mode 100644 user/src/task.rs diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_rect.rs index e9007f60..39f8173d 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_rect.rs @@ -1,77 +1,19 @@ #![no_std] #![no_main] -#[macro_use] extern crate user_lib; extern crate alloc; -use user_lib::{framebuffer, framebuffer_flush}; +use user_lib::{VIRTGPU_XRES, VIRTGPU_YRES, Display}; use embedded_graphics::pixelcolor::Rgb888; -use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; -use embedded_graphics::primitives::Primitive; -use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; -use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; - -pub const VIRTGPU_XRES: usize = 1280; -pub const VIRTGPU_YRES: usize = 800; -pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; +use embedded_graphics::prelude::{DrawTarget, Drawable, Point, RgbColor, Size}; +use embedded_graphics::primitives::{Primitive, PrimitiveStyle, Rectangle}; const INIT_X: i32 = 640; const INIT_Y: i32 = 400; const RECT_SIZE: u32 = 40; -pub struct Display { - pub size: Size, - pub point: Point, - //pub fb: Arc<&'static mut [u8]>, - pub fb: &'static mut [u8], -} - -impl Display { - pub fn new(size: Size, point: Point) -> Self { - let fb_ptr = framebuffer() as *mut u8; - println!( - "Hello world from user mode program! 0x{:X} , len {}", - fb_ptr as usize, VIRTGPU_LEN - ); - let fb = - unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; - Self { size, point, fb } - } -} - -impl OriginDimensions for Display { - fn size(&self) -> Size { - self.size - } -} - -impl DrawTarget for Display { - type Color = Rgb888; - - type Error = core::convert::Infallible; - - fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, - { - pixels.into_iter().for_each(|px| { - let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) - as usize - * 4; - if idx + 2 >= self.fb.len() { - return; - } - self.fb[idx] = px.1.b(); - self.fb[idx + 1] = px.1.g(); - self.fb[idx + 2] = px.1.r(); - }); - framebuffer_flush(); - Ok(()) - } -} - pub struct DrawingBoard { disp: Display, latest_pos: Point, @@ -80,7 +22,7 @@ pub struct DrawingBoard { impl DrawingBoard { pub fn new() -> Self { Self { - disp: Display::new(Size::new(1280, 800), Point::new(0, 0)), + disp: Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)), latest_pos: Point::new(INIT_X, INIT_Y), } } diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs index 83fb721d..e55232db 100644 --- a/user/src/bin/gui_simple.rs +++ b/user/src/bin/gui_simple.rs @@ -4,24 +4,21 @@ #[macro_use] extern crate user_lib; -use user_lib::{framebuffer, framebuffer_flush}; - -pub const VIRTGPU_XRES: usize = 1280; -pub const VIRTGPU_YRES: usize = 800; +use user_lib::{VIRTGPU_XRES, VIRTGPU_YRES, Display}; +use embedded_graphics::prelude::Size; #[no_mangle] pub fn main() -> i32 { - let fb_ptr =framebuffer() as *mut u8; - println!("Hello world from user mode program! 0x{:X} , len {}", fb_ptr as usize, VIRTGPU_XRES*VIRTGPU_YRES*4); - let fb= unsafe {core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_XRES*VIRTGPU_YRES*4 as usize)}; - for y in 0..800 { - for x in 0..1280 { - let idx = (y * 1280 + x) * 4; - fb[idx] = x as u8; - fb[idx + 1] = y as u8; - fb[idx + 2] = (x + y) as u8; + let mut disp = Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)); + disp.paint_on_framebuffer(|fb| { + for y in 0..VIRTGPU_YRES as usize { + for x in 0..VIRTGPU_XRES as usize { + let idx = (y * VIRTGPU_XRES as usize + x) * 4; + fb[idx] = x as u8; + fb[idx + 1] = y as u8; + fb[idx + 2] = (x + y) as u8; + } } - } - framebuffer_flush(); + }); 0 } diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs index ce36b2e8..b28fd9c8 100644 --- a/user/src/bin/gui_snake.rs +++ b/user/src/bin/gui_snake.rs @@ -6,7 +6,7 @@ extern crate user_lib; extern crate alloc; use user_lib::console::getchar; -use user_lib::{framebuffer, framebuffer_flush, key_pressed, sleep}; +use user_lib::{Display, key_pressed, sleep, VIRTGPU_XRES, VIRTGPU_YRES}; use embedded_graphics::pixelcolor::*; use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; @@ -16,58 +16,6 @@ use embedded_graphics::Pixel; use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; use oorandom; //random generator -pub const VIRTGPU_XRES: usize = 1280; -pub const VIRTGPU_YRES: usize = 800; -pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; - -pub struct Display { - pub size: Size, - pub point: Point, - pub fb: &'static mut [u8], -} - -impl Display { - pub fn new(size: Size, point: Point) -> Self { - let fb_ptr = framebuffer() as *mut u8; - println!( - "Hello world from user mode program! 0x{:X} , len {}", - fb_ptr as usize, VIRTGPU_LEN - ); - let fb = - unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; - Self { size, point, fb } - } -} - -impl OriginDimensions for Display { - fn size(&self) -> Size { - self.size - } -} - -impl DrawTarget for Display { - type Color = Rgb888; - type Error = core::convert::Infallible; - - fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, - { - pixels.into_iter().for_each(|px| { - let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) - as usize - * 4; - if idx + 2 >= self.fb.len() { - return; - } - self.fb[idx] = px.1.b(); - self.fb[idx + 1] = px.1.g(); - self.fb[idx + 2] = px.1.r(); - }); - framebuffer_flush(); - Ok(()) - } -} struct Snake { parts: [Pixel; MAX_SIZE], len: usize, @@ -380,7 +328,7 @@ const LF: u8 = 0x0au8; const CR: u8 = 0x0du8; #[no_mangle] pub fn main() -> i32 { - let mut disp = Display::new(Size::new(1280, 800), Point::new(0, 0)); + let mut disp = Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)); let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 50); let _ = disp.clear(Rgb888::BLACK).unwrap(); loop { diff --git a/user/src/file.rs b/user/src/file.rs new file mode 100644 index 00000000..bf77667a --- /dev/null +++ b/user/src/file.rs @@ -0,0 +1,30 @@ +use super::*; + +bitflags! { + pub struct OpenFlags: u32 { + const RDONLY = 0; + const WRONLY = 1 << 0; + const RDWR = 1 << 1; + const CREATE = 1 << 9; + const TRUNC = 1 << 10; + } +} + +pub fn dup(fd: usize) -> isize { + sys_dup(fd) +} +pub fn open(path: &str, flags: OpenFlags) -> isize { + sys_open(path, flags.bits) +} +pub fn close(fd: usize) -> isize { + sys_close(fd) +} +pub fn pipe(pipe_fd: &mut [usize]) -> isize { + sys_pipe(pipe_fd) +} +pub fn read(fd: usize, buf: &mut [u8]) -> isize { + sys_read(fd, buf) +} +pub fn write(fd: usize, buf: &[u8]) -> isize { + sys_write(fd, buf) +} \ No newline at end of file diff --git a/user/src/io.rs b/user/src/io.rs new file mode 100644 index 00000000..6cc2e661 --- /dev/null +++ b/user/src/io.rs @@ -0,0 +1,78 @@ +use super::*; +use embedded_graphics::prelude::{RgbColor, Size}; +use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; +use embedded_graphics::pixelcolor::Rgb888; + +pub const VIRTGPU_XRES: u32 = 1280; +pub const VIRTGPU_YRES: u32 = 800; +pub const VIRTGPU_LEN: usize = (VIRTGPU_XRES * VIRTGPU_YRES * 4) as usize; + +pub fn framebuffer() -> isize { + sys_framebuffer() +} +pub fn framebuffer_flush() -> isize { + sys_framebuffer_flush() +} + +pub fn event_get() -> isize { + sys_event_get() +} + +pub fn key_pressed() -> bool { + if sys_key_pressed() == 1 { + true + } else { + false + } +} +pub struct Display { + pub size: Size, + pub fb: &'static mut [u8], +} + +impl Display { + pub fn new(size: Size) -> Self { + let fb_ptr = framebuffer() as *mut u8; + let fb = + unsafe { core::slice::from_raw_parts_mut(fb_ptr, VIRTGPU_LEN as usize) }; + Self { size, fb} + } + pub fn framebuffer(&mut self) -> &mut [u8] { + self.fb + } + pub fn paint_on_framebuffer(&mut self, p: impl FnOnce(&mut [u8]) -> ()) { + p(self.framebuffer()); + framebuffer_flush(); + } +} + +impl OriginDimensions for Display { + fn size(&self) -> Size { + self.size + } +} + +impl DrawTarget for Display { + type Color = Rgb888; + + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + pixels.into_iter().for_each(|px| { + let idx = (px.0.y * VIRTGPU_XRES as i32 + px.0.x) + as usize + * 4; + if idx + 2 >= self.fb.len() { + return; + } + self.fb[idx] = px.1.b(); + self.fb[idx + 1] = px.1.g(); + self.fb[idx + 2] = px.1.r(); + }); + framebuffer_flush(); + Ok(()) + } +} diff --git a/user/src/lib.rs b/user/src/lib.rs index 31ce9ba2..0d0db85f 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -8,6 +8,10 @@ pub mod console; mod lang_items; mod syscall; +mod file; +mod task; +mod sync; +mod io; extern crate alloc; #[macro_use] @@ -16,6 +20,10 @@ extern crate bitflags; use alloc::vec::Vec; use buddy_system_allocator::LockedHeap; use syscall::*; +pub use file::*; +pub use task::*; +pub use sync::*; +pub use io::*; const USER_HEAP_SIZE: usize = 32768; @@ -59,164 +67,6 @@ fn main(_argc: usize, _argv: &[&str]) -> i32 { panic!("Cannot find main!"); } -bitflags! { - pub struct OpenFlags: u32 { - const RDONLY = 0; - const WRONLY = 1 << 0; - const RDWR = 1 << 1; - const CREATE = 1 << 9; - const TRUNC = 1 << 10; - } -} - -pub fn dup(fd: usize) -> isize { - sys_dup(fd) -} -pub fn open(path: &str, flags: OpenFlags) -> isize { - sys_open(path, flags.bits) -} -pub fn close(fd: usize) -> isize { - sys_close(fd) -} -pub fn pipe(pipe_fd: &mut [usize]) -> isize { - sys_pipe(pipe_fd) -} -pub fn read(fd: usize, buf: &mut [u8]) -> isize { - sys_read(fd, buf) -} -pub fn write(fd: usize, buf: &[u8]) -> isize { - sys_write(fd, buf) -} -pub fn exit(exit_code: i32) -> ! { - sys_exit(exit_code); -} -pub fn yield_() -> isize { - sys_yield() -} -pub fn get_time() -> isize { - sys_get_time() -} -pub fn getpid() -> isize { - sys_getpid() -} -pub fn fork() -> isize { - sys_fork() -} -pub fn exec(path: &str, args: &[*const u8]) -> isize { - sys_exec(path, args) -} -pub fn wait(exit_code: &mut i32) -> isize { - loop { - match sys_waitpid(-1, exit_code as *mut _) { - -2 => { - yield_(); - } - // -1 or a real pid - exit_pid => return exit_pid, - } - } -} - -pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { - loop { - match sys_waitpid(pid as isize, exit_code as *mut _) { - -2 => { - yield_(); - } - // -1 or a real pid - exit_pid => return exit_pid, - } - } -} - -pub fn waitpid_nb(pid: usize, exit_code: &mut i32) -> isize { - sys_waitpid(pid as isize, exit_code as *mut _) -} - -bitflags! { - pub struct SignalFlags: i32 { - const SIGINT = 1 << 2; - const SIGILL = 1 << 4; - const SIGABRT = 1 << 6; - const SIGFPE = 1 << 8; - const SIGSEGV = 1 << 11; - } -} - -pub fn kill(pid: usize, signal: i32) -> isize { - sys_kill(pid, signal) -} - -pub fn sleep(sleep_ms: usize) { - sys_sleep(sleep_ms); -} - -pub fn thread_create(entry: usize, arg: usize) -> isize { - sys_thread_create(entry, arg) -} -pub fn gettid() -> isize { - sys_gettid() -} -pub fn waittid(tid: usize) -> isize { - loop { - match sys_waittid(tid) { - -2 => { - yield_(); - } - exit_code => return exit_code, - } - } -} - -pub fn mutex_create() -> isize { - sys_mutex_create(false) -} -pub fn mutex_blocking_create() -> isize { - sys_mutex_create(true) -} -pub fn mutex_lock(mutex_id: usize) { - sys_mutex_lock(mutex_id); -} -pub fn mutex_unlock(mutex_id: usize) { - sys_mutex_unlock(mutex_id); -} -pub fn semaphore_create(res_count: usize) -> isize { - sys_semaphore_create(res_count) -} -pub fn semaphore_up(sem_id: usize) { - sys_semaphore_up(sem_id); -} -pub fn semaphore_down(sem_id: usize) { - sys_semaphore_down(sem_id); -} -pub fn condvar_create() -> isize { - sys_condvar_create(0) -} -pub fn condvar_signal(condvar_id: usize) { - sys_condvar_signal(condvar_id); -} -pub fn condvar_wait(condvar_id: usize, mutex_id: usize) { - sys_condvar_wait(condvar_id, mutex_id); -} -pub fn framebuffer() -> isize { - sys_framebuffer() -} -pub fn framebuffer_flush() -> isize { - sys_framebuffer_flush() -} - -pub fn event_get() -> isize { - sys_event_get() -} - -pub fn key_pressed() -> bool { - if sys_key_pressed() == 1 { - true - } else { - false - } -} - #[macro_export] macro_rules! vstore { ($var_ref: expr, $value: expr) => { diff --git a/user/src/sync.rs b/user/src/sync.rs new file mode 100644 index 00000000..fbed4e31 --- /dev/null +++ b/user/src/sync.rs @@ -0,0 +1,32 @@ +use super::*; + +pub fn mutex_create() -> isize { + sys_mutex_create(false) +} +pub fn mutex_blocking_create() -> isize { + sys_mutex_create(true) +} +pub fn mutex_lock(mutex_id: usize) { + sys_mutex_lock(mutex_id); +} +pub fn mutex_unlock(mutex_id: usize) { + sys_mutex_unlock(mutex_id); +} +pub fn semaphore_create(res_count: usize) -> isize { + sys_semaphore_create(res_count) +} +pub fn semaphore_up(sem_id: usize) { + sys_semaphore_up(sem_id); +} +pub fn semaphore_down(sem_id: usize) { + sys_semaphore_down(sem_id); +} +pub fn condvar_create() -> isize { + sys_condvar_create(0) +} +pub fn condvar_signal(condvar_id: usize) { + sys_condvar_signal(condvar_id); +} +pub fn condvar_wait(condvar_id: usize, mutex_id: usize) { + sys_condvar_wait(condvar_id, mutex_id); +} \ No newline at end of file diff --git a/user/src/task.rs b/user/src/task.rs new file mode 100644 index 00000000..87d0ddaf --- /dev/null +++ b/user/src/task.rs @@ -0,0 +1,82 @@ +use super::*; + +pub fn exit(exit_code: i32) -> ! { + sys_exit(exit_code); +} +pub fn yield_() -> isize { + sys_yield() +} +pub fn get_time() -> isize { + sys_get_time() +} +pub fn getpid() -> isize { + sys_getpid() +} +pub fn fork() -> isize { + sys_fork() +} +pub fn exec(path: &str, args: &[*const u8]) -> isize { + sys_exec(path, args) +} +pub fn wait(exit_code: &mut i32) -> isize { + loop { + match sys_waitpid(-1, exit_code as *mut _) { + -2 => { + yield_(); + } + // -1 or a real pid + exit_pid => return exit_pid, + } + } +} + +pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { + loop { + match sys_waitpid(pid as isize, exit_code as *mut _) { + -2 => { + yield_(); + } + // -1 or a real pid + exit_pid => return exit_pid, + } + } +} + +pub fn waitpid_nb(pid: usize, exit_code: &mut i32) -> isize { + sys_waitpid(pid as isize, exit_code as *mut _) +} + +bitflags! { + pub struct SignalFlags: i32 { + const SIGINT = 1 << 2; + const SIGILL = 1 << 4; + const SIGABRT = 1 << 6; + const SIGFPE = 1 << 8; + const SIGSEGV = 1 << 11; + } +} + +pub fn kill(pid: usize, signal: i32) -> isize { + sys_kill(pid, signal) +} + +pub fn sleep(sleep_ms: usize) { + sys_sleep(sleep_ms); +} + +pub fn thread_create(entry: usize, arg: usize) -> isize { + sys_thread_create(entry, arg) +} +pub fn gettid() -> isize { + sys_gettid() +} +pub fn waittid(tid: usize) -> isize { + loop { + match sys_waittid(tid) { + -2 => { + yield_(); + } + exit_code => return exit_code, + } + } +} \ No newline at end of file From b77f2d69992a6e513ef96c814fee646e68086e4b Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 11 Jan 2023 19:37:36 -0800 Subject: [PATCH 12/22] Added MapType::Linear for framebuffer mapping & cargo fmt --- os/src/drivers/chardev/ns16550a.rs | 5 +++-- os/src/drivers/input/mod.rs | 4 ++-- os/src/fs/pipe.rs | 2 +- os/src/main.rs | 1 - os/src/mm/address.rs | 1 - os/src/mm/frame_allocator.rs | 9 +-------- os/src/mm/memory_set.rs | 28 +++++++++++---------------- os/src/mm/mod.rs | 4 ++-- os/src/syscall/fs.rs | 2 +- os/src/syscall/gui.rs | 31 ++++++++++++++---------------- os/src/syscall/input.rs | 17 ++++++++-------- os/src/syscall/mod.rs | 8 ++++---- 12 files changed, 47 insertions(+), 65 deletions(-) diff --git a/os/src/drivers/chardev/ns16550a.rs b/os/src/drivers/chardev/ns16550a.rs index 127a4ce1..7122cec1 100644 --- a/os/src/drivers/chardev/ns16550a.rs +++ b/os/src/drivers/chardev/ns16550a.rs @@ -143,12 +143,13 @@ impl NS16550a { } pub fn read_buffer_is_empty(&self) -> bool { - self.inner.exclusive_session(|inner| inner.read_buffer.is_empty()) + self.inner + .exclusive_session(|inner| inner.read_buffer.is_empty()) } } impl CharDevice for NS16550a { - fn init(&self){ + fn init(&self) { let mut inner = self.inner.exclusive_access(); inner.ns16550a.init(); drop(inner); diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index 857f12a3..d7c40fc7 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -18,7 +18,7 @@ struct VirtIOInputWrapper { inner: UPIntrFreeCell, //condvars: BTreeMap, //condvar: Arc:: , - condvar:Condvar, + condvar: Condvar, } pub trait InputDevice: Send + Sync + Any { @@ -38,7 +38,7 @@ lazy_static::lazy_static!( //const QUEUE_SIZE: u16 = 32; // pub fn read_input_event() -> u64 { // loop { - + // //let mut inner = self.inner.exclusive_access(); // let kb=KEYBOARD_DEVICE.clone(); // let evs = kb.events(); diff --git a/os/src/fs/pipe.rs b/os/src/fs/pipe.rs index 531eec49..d10dc33b 100644 --- a/os/src/fs/pipe.rs +++ b/os/src/fs/pipe.rs @@ -170,4 +170,4 @@ impl File for Pipe { } } } -} \ No newline at end of file +} diff --git a/os/src/main.rs b/os/src/main.rs index 7e5a20ac..4819ea64 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -70,7 +70,6 @@ pub fn rust_main() -> ! { timer::set_next_trigger(); board::device_init(); fs::list_apps(); - //gui::init_paint(); task::add_initproc(); *DEV_NON_BLOCKING_ACCESS.exclusive_access() = true; task::run_tasks(); diff --git a/os/src/mm/address.rs b/os/src/mm/address.rs index 8792f625..cf147a08 100644 --- a/os/src/mm/address.rs +++ b/os/src/mm/address.rs @@ -260,4 +260,3 @@ where } } pub type VPNRange = SimpleRange; -pub type PPNRange = SimpleRange; diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 275fb174..1ecfe993 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -7,7 +7,6 @@ use lazy_static::*; pub struct FrameTracker { pub ppn: PhysPageNum, - pub nodrop: bool, } impl FrameTracker { @@ -17,10 +16,7 @@ impl FrameTracker { for i in bytes_array { *i = 0; } - Self { ppn, nodrop: false } - } - pub fn new_noalloc(ppn: PhysPageNum) -> Self { - Self { ppn, nodrop: true } + Self { ppn } } } @@ -32,9 +28,6 @@ impl Debug for FrameTracker { impl Drop for FrameTracker { fn drop(&mut self) { - if self.nodrop { - return; - } frame_dealloc(self.ppn); } } diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index bec0b934..7cdd394a 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -1,7 +1,7 @@ use super::{frame_alloc, FrameTracker}; use super::{PTEFlags, PageTable, PageTableEntry}; use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; -use super::{StepByOne, VPNRange, PPNRange}; +use super::{StepByOne, VPNRange}; use crate::config::{MEMORY_END, MMIO, PAGE_SIZE, TRAMPOLINE}; use crate::sync::UPIntrFreeCell; use alloc::collections::BTreeMap; @@ -71,17 +71,16 @@ impl MemorySet { self.areas.remove(idx); } } - fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) { + /// Add a new MapArea into this MemorySet. + /// Assuming that there are no conflicts in the virtual address + /// space. + pub fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) { map_area.map(&mut self.page_table); if let Some(data) = data { map_area.copy_data(&mut self.page_table, data); } self.areas.push(map_area); } - pub fn push_noalloc(&mut self, mut map_area: MapArea, ppn_range: PPNRange) { - map_area.map_noalloc(&mut self.page_table, ppn_range); - self.areas.push(map_area); - } /// Mention that trampoline is not collected by areas. fn map_trampoline(&mut self) { self.page_table.map( @@ -290,8 +289,10 @@ impl MapArea { ppn = frame.ppn; self.data_frames.insert(vpn, frame); } - MapType::Noalloc => { - panic!("Noalloc should not be mapped"); + MapType::Linear(pn_offset) => { + // check for sv39 + assert!(vpn.0 < (1usize << 27)); + ppn = PhysPageNum((vpn.0 as isize + pn_offset) as usize); } } let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); @@ -308,14 +309,6 @@ impl MapArea { self.map_one(page_table, vpn); } } - pub fn map_noalloc(&mut self, page_table: &mut PageTable,ppn_range:PPNRange) { - for (vpn,ppn) in core::iter::zip(self.vpn_range,ppn_range) { - self.data_frames.insert(vpn, FrameTracker::new_noalloc(ppn)); - let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); - page_table.map(vpn, ppn, pte_flags); - } - } - pub fn unmap(&mut self, page_table: &mut PageTable) { for vpn in self.vpn_range { self.unmap_one(page_table, vpn); @@ -349,7 +342,8 @@ impl MapArea { pub enum MapType { Identical, Framed, - Noalloc, + /// offset of page num + Linear(isize), } bitflags! { diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 9482a30d..77d62f49 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -4,11 +4,11 @@ mod heap_allocator; mod memory_set; mod page_table; -pub use address::{VPNRange, PPNRange}; +pub use address::VPNRange; pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum}; pub use frame_allocator::{frame_alloc, frame_dealloc, FrameTracker}; pub use memory_set::remap_test; -pub use memory_set::{kernel_token, MapPermission, MemorySet, MapArea, MapType, KERNEL_SPACE}; +pub use memory_set::{kernel_token, MapArea, MapPermission, MapType, MemorySet, KERNEL_SPACE}; use page_table::PTEFlags; pub use page_table::{ translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable, diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index af1585c1..27588257 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -96,4 +96,4 @@ pub fn sys_dup(fd: usize) -> isize { let new_fd = inner.alloc_fd(); inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap())); new_fd as isize -} \ No newline at end of file +} diff --git a/os/src/syscall/gui.rs b/os/src/syscall/gui.rs index 5d41c0c6..c5ba8a4e 100644 --- a/os/src/syscall/gui.rs +++ b/os/src/syscall/gui.rs @@ -1,37 +1,34 @@ -use crate::mm::{MapArea, MapPermission, MapType, PPNRange, PhysAddr}; -use crate::task::current_process; - -//use crate::gui::*; use crate::drivers::GPU_DEVICE; +use crate::mm::{MapArea, MapPermission, MapType, PhysAddr, VirtAddr}; +use crate::task::current_process; const FB_VADDR: usize = 0x10000000; pub fn sys_framebuffer() -> isize { - let gpu = GPU_DEVICE.clone(); - let fb = gpu.get_framebuffer(); + let fb = GPU_DEVICE.get_framebuffer(); let len = fb.len(); - println!("[kernel] FrameBuffer: addr 0x{:X}, len {}", fb.as_ptr() as usize , len); - let fb_ppn = PhysAddr::from(fb.as_ptr() as usize).floor(); - let fb_end_ppn = PhysAddr::from(fb.as_ptr() as usize + len).ceil(); + // println!("[kernel] FrameBuffer: addr 0x{:X}, len {}", fb.as_ptr() as usize , len); + let fb_start_pa = PhysAddr::from(fb.as_ptr() as usize); + assert!(fb_start_pa.aligned()); + let fb_start_ppn = fb_start_pa.floor(); + let fb_start_vpn = VirtAddr::from(FB_VADDR).floor(); + let pn_offset = fb_start_ppn.0 as isize - fb_start_vpn.0 as isize; let current_process = current_process(); let mut inner = current_process.inner_exclusive_access(); - let mem_set = &mut inner.memory_set; - - mem_set.push_noalloc( + inner.memory_set.push( MapArea::new( (FB_VADDR as usize).into(), (FB_VADDR + len as usize).into(), - MapType::Noalloc, + MapType::Linear(pn_offset), MapPermission::R | MapPermission::W | MapPermission::U, ), - PPNRange::new(fb_ppn, fb_end_ppn), + None, ); FB_VADDR as isize } pub fn sys_framebuffer_flush() -> isize { - let gpu = GPU_DEVICE.clone(); - gpu.flush(); + GPU_DEVICE.flush(); 0 -} \ No newline at end of file +} diff --git a/os/src/syscall/input.rs b/os/src/syscall/input.rs index 7a282598..ee86bd39 100644 --- a/os/src/syscall/input.rs +++ b/os/src/syscall/input.rs @@ -1,29 +1,28 @@ //use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE,INPUT_CONDVAR,read_input_event}; -use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE}; +use crate::drivers::{KEYBOARD_DEVICE, MOUSE_DEVICE}; -pub fn sys_event_get() ->isize { +pub fn sys_event_get() -> isize { let kb = KEYBOARD_DEVICE.clone(); let mouse = MOUSE_DEVICE.clone(); //let input=INPUT_CONDVAR.clone(); //read_input_event() as isize - if !kb.is_empty(){ + if !kb.is_empty() { kb.read_event() as isize - } else if !mouse.is_empty() { + } else if !mouse.is_empty() { mouse.read_event() as isize } else { 0 } - } use crate::drivers::chardev::UART; /// check UART's read-buffer is empty or not -pub fn sys_key_pressed() -> isize { - let res =!UART.read_buffer_is_empty(); +pub fn sys_key_pressed() -> isize { + let res = !UART.read_buffer_is_empty(); if res { 1 } else { 0 - } -} \ No newline at end of file + } +} diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index d883d52d..d28073f7 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -31,18 +31,18 @@ const SYSCALL_EVENT_GET: usize = 3000; const SYSCALL_KEY_PRESSED: usize = 3001; mod fs; +mod gui; +mod input; mod process; mod sync; mod thread; -mod gui; -mod input; use fs::*; +use gui::*; +use input::*; use process::*; use sync::*; use thread::*; -use gui::*; -use input::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { From f4b856741b4ea3323b57b599a85c0c0eef38f4c0 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Thu, 12 Jan 2023 00:21:57 -0800 Subject: [PATCH 13/22] Decode input events in inputdev_event.rs --- os/Cargo.toml | 4 +-- os/src/drivers/input/mod.rs | 41 +--------------------- os/src/main.rs | 2 -- user/Cargo.toml | 2 ++ user/src/bin/gui_rect.rs | 1 - user/src/bin/gui_simple.rs | 1 - user/src/bin/gui_snake.rs | 1 - user/src/bin/inputdev_event.rs | 20 ++++++----- user/src/io.rs | 62 ++++++++++++++++++++++++++++------ 9 files changed, 67 insertions(+), 67 deletions(-) diff --git a/os/Cargo.toml b/os/Cargo.toml index ded2765e..d8f42164 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -13,10 +13,8 @@ buddy_system_allocator = "0.6" bitflags = "1.2.1" xmas-elf = "0.7.0" volatile = "0.3" -#virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "70b5850" } +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } easy-fs = { path = "../easy-fs" } -#virtio-input-decoder = "0.1.4" embedded-graphics = "0.7.1" tinybmp = "0.3.1" diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index d7c40fc7..a9f5f0bd 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -16,41 +16,20 @@ struct VirtIOInputInner { struct VirtIOInputWrapper { inner: UPIntrFreeCell, - //condvars: BTreeMap, - //condvar: Arc:: , condvar: Condvar, } pub trait InputDevice: Send + Sync + Any { fn read_event(&self) -> u64; fn handle_irq(&self); - // fn events(&self) -> &VecDeque; fn is_empty(&self) -> bool; } lazy_static::lazy_static!( pub static ref KEYBOARD_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO5)); pub static ref MOUSE_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO6)); - // pub static ref INPUT_CONDVAR: Arc:: = Arc::new(Condvar::new()); ); -// from virtio-drivers/src/input.rs -//const QUEUE_SIZE: u16 = 32; -// pub fn read_input_event() -> u64 { -// loop { - -// //let mut inner = self.inner.exclusive_access(); -// let kb=KEYBOARD_DEVICE.clone(); -// let evs = kb.events(); -// if let Some(event) = evs.pop_front() { -// return event; -// } else { -// let task_cx_ptr = INPUT_CONDVAR.clone().wait_no_sched(); -// drop(inner); -// schedule(task_cx_ptr); -// } -// } -// } impl VirtIOInputWrapper { pub fn new(addr: usize) -> Self { let inner = VirtIOInputInner { @@ -59,17 +38,8 @@ impl VirtIOInputWrapper { }, events: VecDeque::new(), }; - - // let mut condvars = BTreeMap::new(); - // let channels = QUEUE_SIZE; - // for i in 0..channels { - // let condvar = Condvar::new(); - // condvars.insert(i, condvar); - // } - Self { inner: unsafe { UPIntrFreeCell::new(inner) }, - //condvar: INPUT_CONDVAR.clone(), condvar: Condvar::new(), } } @@ -93,29 +63,20 @@ impl InputDevice for VirtIOInputWrapper { } } - // fn events(&self) -> &VecDeque { - // &self.inner.exclusive_access().events - // } - fn handle_irq(&self) { let mut count = 0; let mut result = 0; - let mut key = 0; self.inner.exclusive_session(|inner| { inner.virtio_input.ack_interrupt(); - while let Some((token, event)) = inner.virtio_input.pop_pending_event() { + while let Some(event) = inner.virtio_input.pop_pending_event() { count += 1; - key = token; result = (event.event_type as u64) << 48 | (event.code as u64) << 32 | (event.value) as u64; inner.events.push_back(result); - // for test - //println!("[KERN] inputdev_handle_irq: event: {:x}", result); } }); if count > 0 { - //self.condvars.get(&key).unwrap().signal(); self.condvar.signal(); }; } diff --git a/os/src/main.rs b/os/src/main.rs index 4819ea64..1103c570 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -29,7 +29,6 @@ mod trap; use crate::drivers::chardev::CharDevice; use crate::drivers::chardev::UART; -//use syscall::create_desktop; //for test core::arch::global_asm!(include_str!("entry.asm")); @@ -59,7 +58,6 @@ pub fn rust_main() -> ! { UART.init(); println!("KERN: init gpu"); let _gpu = GPU_DEVICE.clone(); - //let _input_condvar = INPUT_CONDVAR.clone(); println!("KERN: init keyboard"); let _keyboard = KEYBOARD_DEVICE.clone(); println!("KERN: init mouse"); diff --git a/user/Cargo.toml b/user/Cargo.toml index 35e06d5d..7b1233e0 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -12,5 +12,7 @@ bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } embedded-graphics = "0.7.1" oorandom ="11" +virtio-input-decoder = "0.1.4" + [profile.release] debug = true \ No newline at end of file diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_rect.rs index 39f8173d..c8696bec 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_rect.rs @@ -48,7 +48,6 @@ impl DrawingBoard { #[no_mangle] pub fn main() -> i32 { - // let fb_ptr = framebuffer() as *mut u8; let mut board = DrawingBoard::new(); let _ = board.disp.clear(Rgb888::BLACK).unwrap(); for i in 0..20 { diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs index e55232db..ccf5b89d 100644 --- a/user/src/bin/gui_simple.rs +++ b/user/src/bin/gui_simple.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] -#[macro_use] extern crate user_lib; use user_lib::{VIRTGPU_XRES, VIRTGPU_YRES, Display}; diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs index b28fd9c8..080c4725 100644 --- a/user/src/bin/gui_snake.rs +++ b/user/src/bin/gui_snake.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] -#[macro_use] extern crate user_lib; extern crate alloc; diff --git a/user/src/bin/inputdev_event.rs b/user/src/bin/inputdev_event.rs index 1e5b5a10..5b820d80 100644 --- a/user/src/bin/inputdev_event.rs +++ b/user/src/bin/inputdev_event.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] -use user_lib::{event_get}; +use user_lib::{event_get, DecodeType, Key, KeyType}; #[macro_use] extern crate user_lib; @@ -9,13 +9,17 @@ extern crate user_lib; #[no_mangle] pub fn main() -> i32 { println!("Input device event test"); - let mut event=0; - for _ in 0..3 { - while event==0 { - event = event_get(); - } - println!("event: {:?}", event); + loop { + if let Some(event) = event_get() { + if let Some(decoder_type) = event.decode() { + println!("{:?}", decoder_type); + if let DecodeType::Key(key, keytype) = decoder_type { + if key == Key::Enter && keytype == KeyType::Press { + break; + } + } + } + } } - 0 } \ No newline at end of file diff --git a/user/src/io.rs b/user/src/io.rs index 6cc2e661..baaa3382 100644 --- a/user/src/io.rs +++ b/user/src/io.rs @@ -2,6 +2,8 @@ use super::*; use embedded_graphics::prelude::{RgbColor, Size}; use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; use embedded_graphics::pixelcolor::Rgb888; +use virtio_input_decoder::Decoder; +pub use virtio_input_decoder::{DecodeType, Key, KeyType, Mouse}; pub const VIRTGPU_XRES: u32 = 1280; pub const VIRTGPU_YRES: u32 = 800; @@ -14,17 +16,6 @@ pub fn framebuffer_flush() -> isize { sys_framebuffer_flush() } -pub fn event_get() -> isize { - sys_event_get() -} - -pub fn key_pressed() -> bool { - if sys_key_pressed() == 1 { - true - } else { - false - } -} pub struct Display { pub size: Size, pub fb: &'static mut [u8], @@ -76,3 +67,52 @@ impl DrawTarget for Display { Ok(()) } } + +pub fn event_get() -> Option { + let raw_value = sys_event_get(); + if raw_value == 0 { + None + } else { + Some((raw_value as u64).into()) + } +} + +pub fn key_pressed() -> bool { + if sys_key_pressed() == 1 { + true + } else { + false + } +} + +#[repr(C)] +pub struct InputEvent { + pub event_type: u16, + pub code: u16, + pub value: u32, +} + +impl From for InputEvent { + fn from(mut v: u64) -> Self { + let value = v as u32; + v >>= 32; + let code = v as u16; + v >>= 16; + let event_type = v as u16; + Self { + event_type, + code, + value, + } + } +} + +impl InputEvent { + pub fn decode(&self) -> Option { + Decoder::decode( + self.event_type as usize, + self.code as usize, + self.value as usize, + ).ok() + } +} \ No newline at end of file From dcfcfbf03030a93f5086e6a009fc2747d5df1259 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 13 Jan 2023 09:54:54 +0800 Subject: [PATCH 14/22] updates from ch8 --- user/src/bin/adder.rs | 55 ++++++++++++++ user/src/bin/adder_atomic.rs | 72 ++++++++++++++++++ user/src/bin/adder_mutex_blocking.rs | 59 +++++++++++++++ user/src/bin/adder_mutex_spin.rs | 60 +++++++++++++++ user/src/bin/adder_peterson_spin.rs | 90 +++++++++++++++++++++++ user/src/bin/adder_peterson_yield.rs | 89 ++++++++++++++++++++++ user/src/bin/adder_simple_spin.rs | 68 +++++++++++++++++ user/src/bin/adder_simple_yield.rs | 70 ++++++++++++++++++ user/src/bin/peterson.rs | 21 +++--- user/src/bin/race_adder.rs | 42 ----------- user/src/bin/race_adder_atomic.rs | 51 ------------- user/src/bin/race_adder_loop.rs | 51 ------------- user/src/bin/race_adder_mutex_blocking.rs | 46 ------------ user/src/bin/race_adder_mutex_spin.rs | 46 ------------ user/src/bin/usertests.rs | 13 ++-- 15 files changed, 582 insertions(+), 251 deletions(-) create mode 100644 user/src/bin/adder.rs create mode 100644 user/src/bin/adder_atomic.rs create mode 100644 user/src/bin/adder_mutex_blocking.rs create mode 100644 user/src/bin/adder_mutex_spin.rs create mode 100644 user/src/bin/adder_peterson_spin.rs create mode 100644 user/src/bin/adder_peterson_yield.rs create mode 100644 user/src/bin/adder_simple_spin.rs create mode 100644 user/src/bin/adder_simple_yield.rs delete mode 100644 user/src/bin/race_adder.rs delete mode 100644 user/src/bin/race_adder_atomic.rs delete mode 100644 user/src/bin/race_adder_loop.rs delete mode 100644 user/src/bin/race_adder_mutex_blocking.rs delete mode 100644 user/src/bin/race_adder_mutex_spin.rs diff --git a/user/src/bin/adder.rs b/user/src/bin/adder.rs new file mode 100644 index 00000000..e7b16117 --- /dev/null +++ b/user/src/bin/adder.rs @@ -0,0 +1,55 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid}; + +static mut A: usize = 0; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + critical_section(&mut t); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + let start = get_time(); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_atomic.rs b/user/src/bin/adder_atomic.rs new file mode 100644 index 00000000..fe2cdb17 --- /dev/null +++ b/user/src/bin/adder_atomic.rs @@ -0,0 +1,72 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use core::sync::atomic::{AtomicBool, Ordering}; +use user_lib::{exit, get_time, thread_create, waittid, yield_}; + +static mut A: usize = 0; +static OCCUPIED: AtomicBool = AtomicBool::new(false); +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +fn lock() { + while OCCUPIED + .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) + .is_err() + { + yield_(); + } +} + +fn unlock() { + OCCUPIED.store(false, Ordering::Relaxed); +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + lock(); + critical_section(&mut t); + unlock(); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + let start = get_time(); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_mutex_blocking.rs b/user/src/bin/adder_mutex_blocking.rs new file mode 100644 index 00000000..963dd753 --- /dev/null +++ b/user/src/bin/adder_mutex_blocking.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid}; +use user_lib::{mutex_blocking_create, mutex_lock, mutex_unlock}; + +static mut A: usize = 0; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + mutex_lock(0); + critical_section(&mut t); + mutex_unlock(0); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + + let start = get_time(); + assert_eq!(mutex_blocking_create(), 0); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_mutex_spin.rs b/user/src/bin/adder_mutex_spin.rs new file mode 100644 index 00000000..b96f933c --- /dev/null +++ b/user/src/bin/adder_mutex_spin.rs @@ -0,0 +1,60 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid}; +use user_lib::{mutex_create, mutex_lock, mutex_unlock}; + +static mut A: usize = 0; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + mutex_lock(0); + critical_section(&mut t); + mutex_unlock(0); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + + let start = get_time(); + assert_eq!(mutex_create(), 0); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_peterson_spin.rs b/user/src/bin/adder_peterson_spin.rs new file mode 100644 index 00000000..bba1f239 --- /dev/null +++ b/user/src/bin/adder_peterson_spin.rs @@ -0,0 +1,90 @@ +//! It only works on a single CPU! + +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid}; +use core::sync::atomic::{compiler_fence, Ordering}; + +static mut A: usize = 0; +static mut FLAG: [bool; 2] = [false; 2]; +static mut TURN: usize = 0; +const PER_THREAD_DEFAULT: usize = 2000; +const THREAD_COUNT_DEFAULT: usize = 2; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock(id: usize) { + FLAG[id] = true; + let j = 1 - id; + TURN = j; + // Tell the compiler not to reorder memory operations + // across this fence. + compiler_fence(Ordering::SeqCst); + // Why do we need to use volatile_read here? + // Otherwise the compiler will assume that they will never + // be changed on this thread. Thus, they will be accessed + // only once! + while vload!(&FLAG[j]) && vload!(&TURN) == j {} +} + +unsafe fn unlock(id: usize) { + FLAG[id] = false; +} + +unsafe fn f(id: usize) -> ! { + let mut t = 2usize; + for _iter in 0..PER_THREAD { + lock(id); + critical_section(&mut t); + unlock(id); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + + // uncomment this if you want to check the assembly + // println!( + // "addr: lock={:#x}, unlock={:#x}", + // lock as usize, + // unlock as usize + // ); + let start = get_time(); + let mut v = Vec::new(); + assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads."); + for id in 0..thread_count { + v.push(thread_create(f as usize, id) as usize); + } + let mut time_cost = Vec::new(); + for tid in v.iter() { + time_cost.push(waittid(*tid)); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_peterson_yield.rs b/user/src/bin/adder_peterson_yield.rs new file mode 100644 index 00000000..fc5ff189 --- /dev/null +++ b/user/src/bin/adder_peterson_yield.rs @@ -0,0 +1,89 @@ +//! It only works on a single CPU! + +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid, yield_}; +use core::sync::atomic::{compiler_fence, Ordering}; + +static mut A: usize = 0; +static mut FLAG: [bool; 2] = [false; 2]; +static mut TURN: usize = 0; +const PER_THREAD_DEFAULT: usize = 2000; +const THREAD_COUNT_DEFAULT: usize = 2; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock(id: usize) { + FLAG[id] = true; + let j = 1 - id; + TURN = j; + // Tell the compiler not to reorder memory operations + // across this fence. + compiler_fence(Ordering::SeqCst); + while FLAG[j] && TURN == j { + yield_(); + } +} + +unsafe fn unlock(id: usize) { + FLAG[id] = false; +} + +unsafe fn f(id: usize) -> ! { + let mut t = 2usize; + for _iter in 0..PER_THREAD { + lock(id); + critical_section(&mut t); + unlock(id); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + + // uncomment this if you want to check the assembly + // println!( + // "addr: lock={:#x}, unlock={:#x}", + // lock as usize, + // unlock as usize + // ); + + let start = get_time(); + let mut v = Vec::new(); + assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads."); + for id in 0..thread_count { + v.push(thread_create(f as usize, id) as usize); + } + let mut time_cost = Vec::new(); + for tid in v.iter() { + time_cost.push(waittid(*tid)); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_simple_spin.rs b/user/src/bin/adder_simple_spin.rs new file mode 100644 index 00000000..d950eca5 --- /dev/null +++ b/user/src/bin/adder_simple_spin.rs @@ -0,0 +1,68 @@ +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid}; + +static mut A: usize = 0; +static mut OCCUPIED: bool = false; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock() { + while vload!(&OCCUPIED) {} + OCCUPIED = true; +} + +unsafe fn unlock() { + OCCUPIED = false; +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + lock(); + critical_section(&mut t); + unlock(); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + let start = get_time(); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_simple_yield.rs b/user/src/bin/adder_simple_yield.rs new file mode 100644 index 00000000..1c777779 --- /dev/null +++ b/user/src/bin/adder_simple_yield.rs @@ -0,0 +1,70 @@ +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid, yield_}; + +static mut A: usize = 0; +static mut OCCUPIED: bool = false; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock() { + while OCCUPIED { + yield_(); + } + OCCUPIED = true; +} + +unsafe fn unlock() { + OCCUPIED = false; +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + lock(); + critical_section(&mut t); + unlock(); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { PER_THREAD = per_thread; } + let start = get_time(); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/peterson.rs b/user/src/bin/peterson.rs index 089841d7..1fa2c416 100644 --- a/user/src/bin/peterson.rs +++ b/user/src/bin/peterson.rs @@ -10,7 +10,7 @@ extern crate core; use alloc::vec::Vec; use core::sync::atomic::{AtomicUsize, Ordering}; use user_lib::{exit, sleep, thread_create, waittid}; -const N: usize = 3; +const N: usize = 1000; static mut TURN: usize = 0; static mut FLAG: [bool; 2] = [false; 2]; @@ -29,27 +29,30 @@ fn critical_test_exit() { } fn peterson_enter_critical(id: usize, peer_id: usize) { - println!("Thread[{}] try enter", id); + // println!("Thread[{}] try enter", id); vstore!(&FLAG[id], true); vstore!(&TURN, peer_id); memory_fence!(); while vload!(&FLAG[peer_id]) && vload!(&TURN) == peer_id { - println!("Thread[{}] enter fail", id); + // println!("Thread[{}] enter fail", id); sleep(1); - println!("Thread[{}] retry enter", id); + // println!("Thread[{}] retry enter", id); } - println!("Thread[{}] enter", id); + // println!("Thread[{}] enter", id); } fn peterson_exit_critical(id: usize) { vstore!(&FLAG[id], false); - println!("Thread[{}] exit", id); + // println!("Thread[{}] exit", id); } pub fn thread_fn(id: usize) -> ! { - println!("Thread[{}] init.", id); + // println!("Thread[{}] init.", id); let peer_id: usize = id ^ 1; - for _ in 0..N { + for iter in 0..N { + if iter % 10 == 0 { + println!("[{}] it={}", id, iter); + } peterson_enter_critical(id, peer_id); critical_test_enter(); for _ in 0..3 { @@ -74,4 +77,4 @@ pub fn main() -> i32 { } println!("main thread exited."); 0 -} +} \ No newline at end of file diff --git a/user/src/bin/race_adder.rs b/user/src/bin/race_adder.rs deleted file mode 100644 index c7b6747e..00000000 --- a/user/src/bin/race_adder.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid}; - -static mut A: usize = 0; -const PER_THREAD: usize = 1000; -const THREAD_COUNT: usize = 16; - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - t = t * t % 10007; - } - a.write_volatile(cur + 1); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main() -> i32 { - let start = get_time(); - let mut v = Vec::new(); - for _ in 0..THREAD_COUNT { - v.push(thread_create(f as usize, 0) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT); - 0 -} diff --git a/user/src/bin/race_adder_atomic.rs b/user/src/bin/race_adder_atomic.rs deleted file mode 100644 index 2feaed0d..00000000 --- a/user/src/bin/race_adder_atomic.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use core::sync::atomic::{AtomicBool, Ordering}; -use user_lib::{exit, get_time, thread_create, waittid, yield_}; - -static mut A: usize = 0; -static OCCUPIED: AtomicBool = AtomicBool::new(false); -const PER_THREAD: usize = 1000; -const THREAD_COUNT: usize = 16; - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - while OCCUPIED - .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) - .is_err() - { - yield_(); - } - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - t = t * t % 10007; - } - a.write_volatile(cur + 1); - OCCUPIED.store(false, Ordering::Relaxed); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main() -> i32 { - let start = get_time(); - let mut v = Vec::new(); - for _ in 0..THREAD_COUNT { - v.push(thread_create(f as usize, 0) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT); - 0 -} diff --git a/user/src/bin/race_adder_loop.rs b/user/src/bin/race_adder_loop.rs deleted file mode 100644 index 0e4fe838..00000000 --- a/user/src/bin/race_adder_loop.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid, yield_}; - -static mut A: usize = 0; -static mut OCCUPIED: bool = false; -const PER_THREAD: usize = 1000; -const THREAD_COUNT: usize = 16; - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - while OCCUPIED { - yield_(); - } - OCCUPIED = true; - // enter critical section - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - t = t * t % 10007; - } - a.write_volatile(cur + 1); - // exit critical section - OCCUPIED = false; - } - - exit(t as i32) -} - -#[no_mangle] -pub fn main() -> i32 { - let start = get_time(); - let mut v = Vec::new(); - for _ in 0..THREAD_COUNT { - v.push(thread_create(f as usize, 0) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT); - 0 -} diff --git a/user/src/bin/race_adder_mutex_blocking.rs b/user/src/bin/race_adder_mutex_blocking.rs deleted file mode 100644 index e5affc42..00000000 --- a/user/src/bin/race_adder_mutex_blocking.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid}; -use user_lib::{mutex_blocking_create, mutex_lock, mutex_unlock}; - -static mut A: usize = 0; -const PER_THREAD: usize = 1000; -const THREAD_COUNT: usize = 16; - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - mutex_lock(0); - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - t = t * t % 10007; - } - a.write_volatile(cur + 1); - mutex_unlock(0); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main() -> i32 { - let start = get_time(); - assert_eq!(mutex_blocking_create(), 0); - let mut v = Vec::new(); - for _ in 0..THREAD_COUNT { - v.push(thread_create(f as usize, 0) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT); - 0 -} diff --git a/user/src/bin/race_adder_mutex_spin.rs b/user/src/bin/race_adder_mutex_spin.rs deleted file mode 100644 index ed3bcec9..00000000 --- a/user/src/bin/race_adder_mutex_spin.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid}; -use user_lib::{mutex_create, mutex_lock, mutex_unlock}; - -static mut A: usize = 0; -const PER_THREAD: usize = 1000; -const THREAD_COUNT: usize = 16; - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - mutex_lock(0); - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - t = t * t % 10007; - } - a.write_volatile(cur + 1); - mutex_unlock(0); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main() -> i32 { - let start = get_time(); - assert_eq!(mutex_create(), 0); - let mut v = Vec::new(); - for _ in 0..THREAD_COUNT { - v.push(thread_create(f as usize, 0) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT); - 0 -} diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index eb706fd5..a631314f 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -27,10 +27,10 @@ static SUCC_TESTS: &[(&str, &str, &str, &str, i32)] = &[ ("phil_din_mutex\0", "\0", "\0", "\0", 0), ("pipe_large_test\0", "\0", "\0", "\0", 0), ("pipetest\0", "\0", "\0", "\0", 0), - ("race_adder_arg\0", "3\0", "\0", "\0", 0), - ("race_adder_atomic\0", "\0", "\0", "\0", 0), - ("race_adder_mutex_blocking\0", "\0", "\0", "\0", 0), - ("race_adder_mutex_spin\0", "\0", "\0", "\0", 0), + ("adder_peterson_spin\0", "\0", "\0", "\0", 0), + ("adder_peterson_yield\0", "\0", "\0", "\0", 0), + ("adder_mutex_blocking\0", "\0", "\0", "\0", 0), + ("adder_mutex_spin\0", "\0", "\0", "\0", 0), ("run_pipe_test\0", "\0", "\0", "\0", 0), ("sleep_simple\0", "\0", "\0", "\0", 0), ("sleep\0", "\0", "\0", "\0", 0), @@ -49,8 +49,9 @@ static FAIL_TESTS: &[(&str, &str, &str, &str, i32)] = &[ ("priv_inst\0", "\0", "\0", "\0", -4), ("store_fault\0", "\0", "\0", "\0", -11), ("until_timeout\0", "\0", "\0", "\0", -6), - ("race_adder\0", "\0", "\0", "\0", -6), - ("huge_write_mt\0", "\0", "\0", "\0", -6), + ("adder\0", "\0", "\0", "\0", -6), + ("adder_simple_spin\0", "\0", "\0", "\0", -6), + ("adder_simple_yield\0", "\0", "\0", "\0", -6), ]; use user_lib::{exec, fork, waitpid}; From 794ba8f7a6654e4e90ac8a95fa10ce4e1a082f3f Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Tue, 17 Jan 2023 13:28:31 +0800 Subject: [PATCH 15/22] update usr app gui_ret for more graph outputs --- user/src/bin/gui_rect.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_rect.rs index c8696bec..a459dbc3 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_rect.rs @@ -1,18 +1,18 @@ #![no_std] #![no_main] -extern crate user_lib; extern crate alloc; +extern crate user_lib; -use user_lib::{VIRTGPU_XRES, VIRTGPU_YRES, Display}; +use user_lib::{Display, VIRTGPU_XRES, VIRTGPU_YRES}; use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::{DrawTarget, Drawable, Point, RgbColor, Size}; -use embedded_graphics::primitives::{Primitive, PrimitiveStyle, Rectangle}; +use embedded_graphics::primitives::{Circle, Primitive, PrimitiveStyle, Rectangle,Triangle}; -const INIT_X: i32 = 640; +const INIT_X: i32 = 80; const INIT_Y: i32 = 400; -const RECT_SIZE: u32 = 40; +const RECT_SIZE: u32 = 150; pub struct DrawingBoard { disp: Display, @@ -28,13 +28,21 @@ impl DrawingBoard { } fn paint(&mut self) { Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::RED, 10)) + .draw(&mut self.disp) + .ok(); + Circle::new(self.latest_pos + Point::new(-70, -300), 150) + .into_styled(PrimitiveStyle::with_fill(Rgb888::BLUE)) + .draw(&mut self.disp) + .ok(); + Triangle::new(self.latest_pos + Point::new(0, 150), self.latest_pos + Point::new(80, 200), self.latest_pos + Point::new(-120, 300)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 10)) .draw(&mut self.disp) .ok(); } fn unpaint(&mut self) { Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 10)) .draw(&mut self.disp) .ok(); } @@ -50,9 +58,9 @@ impl DrawingBoard { pub fn main() -> i32 { let mut board = DrawingBoard::new(); let _ = board.disp.clear(Rgb888::BLACK).unwrap(); - for i in 0..20 { - board.latest_pos.x += i; - board.latest_pos.y += i; + for i in 0..5 { + board.latest_pos.x += (RECT_SIZE as i32 + 20); + //board.latest_pos.y += i; board.paint(); } 0 From 29585b798266d528f39a69f2e200ffc9f8e5669d Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Thu, 19 Jan 2023 13:55:17 +0800 Subject: [PATCH 16/22] TaskStatus::Blocking->Blocked --- os/src/task/mod.rs | 2 +- os/src/task/task.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 97e76bd4..9ed25ae6 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -48,7 +48,7 @@ pub fn suspend_current_and_run_next() { pub fn block_current_task() -> *mut TaskContext { let task = take_current_task().unwrap(); let mut task_inner = task.inner_exclusive_access(); - task_inner.task_status = TaskStatus::Blocking; + task_inner.task_status = TaskStatus::Blocked; &mut task_inner.task_cx as *mut TaskContext } diff --git a/os/src/task/task.rs b/os/src/task/task.rs index c620890e..ffc5c0e0 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -76,5 +76,5 @@ impl TaskControlBlock { pub enum TaskStatus { Ready, Running, - Blocking, + Blocked, } From 8c09e0537ecd865ce87482359814428ce2aa0acf Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 20 Jan 2023 01:54:13 +0800 Subject: [PATCH 17/22] add_task->wakeup_task --- os/src/sync/condvar.rs | 4 ++-- os/src/sync/mutex.rs | 4 ++-- os/src/sync/semaphore.rs | 4 ++-- os/src/task/manager.rs | 9 ++++++++- os/src/task/mod.rs | 2 +- os/src/timer.rs | 4 ++-- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/os/src/sync/condvar.rs b/os/src/sync/condvar.rs index 714782c2..b8ad07b7 100644 --- a/os/src/sync/condvar.rs +++ b/os/src/sync/condvar.rs @@ -1,6 +1,6 @@ use crate::sync::{Mutex, UPIntrFreeCell}; use crate::task::{ - add_task, block_current_and_run_next, block_current_task, current_task, TaskContext, + wakeup_task, block_current_and_run_next, block_current_task, current_task, TaskContext, TaskControlBlock, }; use alloc::{collections::VecDeque, sync::Arc}; @@ -27,7 +27,7 @@ impl Condvar { pub fn signal(&self) { let mut inner = self.inner.exclusive_access(); if let Some(task) = inner.wait_queue.pop_front() { - add_task(task); + wakeup_task(task); } } diff --git a/os/src/sync/mutex.rs b/os/src/sync/mutex.rs index 463638b3..2b2db108 100644 --- a/os/src/sync/mutex.rs +++ b/os/src/sync/mutex.rs @@ -1,6 +1,6 @@ use super::UPIntrFreeCell; use crate::task::TaskControlBlock; -use crate::task::{add_task, current_task}; +use crate::task::{wakeup_task, current_task}; use crate::task::{block_current_and_run_next, suspend_current_and_run_next}; use alloc::{collections::VecDeque, sync::Arc}; @@ -80,7 +80,7 @@ impl Mutex for MutexBlocking { let mut mutex_inner = self.inner.exclusive_access(); assert!(mutex_inner.locked); if let Some(waking_task) = mutex_inner.wait_queue.pop_front() { - add_task(waking_task); + wakeup_task(waking_task); } else { mutex_inner.locked = false; } diff --git a/os/src/sync/semaphore.rs b/os/src/sync/semaphore.rs index 354db29f..cb62c201 100644 --- a/os/src/sync/semaphore.rs +++ b/os/src/sync/semaphore.rs @@ -1,5 +1,5 @@ use crate::sync::UPIntrFreeCell; -use crate::task::{add_task, block_current_and_run_next, current_task, TaskControlBlock}; +use crate::task::{wakeup_task, block_current_and_run_next, current_task, TaskControlBlock}; use alloc::{collections::VecDeque, sync::Arc}; pub struct Semaphore { @@ -28,7 +28,7 @@ impl Semaphore { inner.count += 1; if inner.count <= 0 { if let Some(task) = inner.wait_queue.pop_front() { - add_task(task); + wakeup_task(task); } } } diff --git a/os/src/task/manager.rs b/os/src/task/manager.rs index 168ba32e..7672cf53 100644 --- a/os/src/task/manager.rs +++ b/os/src/task/manager.rs @@ -1,4 +1,4 @@ -use super::{ProcessControlBlock, TaskControlBlock}; +use super::{ProcessControlBlock, TaskControlBlock, TaskStatus}; use crate::sync::UPIntrFreeCell; use alloc::collections::{BTreeMap, VecDeque}; use alloc::sync::Arc; @@ -34,6 +34,13 @@ pub fn add_task(task: Arc) { TASK_MANAGER.exclusive_access().add(task); } +pub fn wakeup_task(task: Arc) { + let mut task_inner = task.inner_exclusive_access(); + task_inner.task_status = TaskStatus::Ready; + drop(task_inner); + add_task(task); +} + pub fn fetch_task() -> Option> { TASK_MANAGER.exclusive_access().fetch() } diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 9ed25ae6..c8354805 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -18,7 +18,7 @@ use switch::__switch; pub use context::TaskContext; pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle, IDLE_PID}; -pub use manager::{add_task, pid2process, remove_from_pid2process}; +pub use manager::{add_task, wakeup_task, pid2process, remove_from_pid2process}; pub use processor::{ current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va, current_user_token, run_tasks, schedule, take_current_task, diff --git a/os/src/timer.rs b/os/src/timer.rs index 7be2d012..83c969d4 100644 --- a/os/src/timer.rs +++ b/os/src/timer.rs @@ -3,7 +3,7 @@ use core::cmp::Ordering; use crate::config::CLOCK_FREQ; use crate::sbi::set_timer; use crate::sync::UPIntrFreeCell; -use crate::task::{add_task, TaskControlBlock}; +use crate::task::{wakeup_task, TaskControlBlock}; use alloc::collections::BinaryHeap; use alloc::sync::Arc; use lazy_static::*; @@ -64,7 +64,7 @@ pub fn check_timer() { TIMERS.exclusive_session(|timers| { while let Some(timer) = timers.peek() { if timer.expire_ms <= current_ms { - add_task(Arc::clone(&timer.task)); + wakeup_task(Arc::clone(&timer.task)); timers.pop(); } else { break; From 59480f5d0d3e107a6abbe4bf061f32f0ab92dc7f Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 25 Jan 2023 10:32:03 +0800 Subject: [PATCH 18/22] Added condvar examples. --- user/Cargo.toml | 1 + user/src/bin/barrier_condvar.rs | 72 +++++++++++++++++++++++++++++++++ user/src/bin/barrier_fail.rs | 33 +++++++++++++++ user/src/bin/usertests.rs | 2 + 4 files changed, 108 insertions(+) create mode 100644 user/src/bin/barrier_condvar.rs create mode 100644 user/src/bin/barrier_fail.rs diff --git a/user/Cargo.toml b/user/Cargo.toml index 7b1233e0..d1816c64 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } embedded-graphics = "0.7.1" oorandom ="11" virtio-input-decoder = "0.1.4" diff --git a/user/src/bin/barrier_condvar.rs b/user/src/bin/barrier_condvar.rs new file mode 100644 index 00000000..db0a80ba --- /dev/null +++ b/user/src/bin/barrier_condvar.rs @@ -0,0 +1,72 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::{thread_create, exit, waittid, mutex_create, mutex_lock, mutex_unlock, condvar_create, condvar_signal, condvar_wait}; +use alloc::vec::Vec; +use core::cell::UnsafeCell; +use lazy_static::*; + +const THREAD_NUM: usize = 3; + +struct Barrier { + mutex_id: usize, + condvar_id: usize, + count: UnsafeCell, +} + +impl Barrier { + pub fn new() -> Self { + Self { + mutex_id: mutex_create() as usize, + condvar_id: condvar_create() as usize, + count: UnsafeCell::new(0), + } + } + pub fn block(&self) { + mutex_lock(self.mutex_id); + let mut count = self.count.get(); + // SAFETY: Here, the accesses of the count is in the + // critical section protected by the mutex. + unsafe { *count = *count + 1; } + if unsafe { *count } == THREAD_NUM { + condvar_signal(self.condvar_id); + } else { + condvar_wait(self.condvar_id, self.mutex_id); + condvar_signal(self.condvar_id); + } + mutex_unlock(self.mutex_id); + } +} + +unsafe impl Sync for Barrier {} + +lazy_static! { + static ref BARRIER_AB: Barrier = Barrier::new(); + static ref BARRIER_BC: Barrier = Barrier::new(); +} + +fn thread_fn() { + for _ in 0..300 { print!("a"); } + BARRIER_AB.block(); + for _ in 0..300 { print!("b"); } + BARRIER_BC.block(); + for _ in 0..300 { print!("c"); } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/barrier_fail.rs b/user/src/bin/barrier_fail.rs new file mode 100644 index 00000000..0eb4b17f --- /dev/null +++ b/user/src/bin/barrier_fail.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::{thread_create, exit, waittid}; +use alloc::vec::Vec; + +const THREAD_NUM: usize = 3; + +fn thread_fn() { + for ch in 'a'..='c' { + for _ in 0..300 { + print!("{}", ch); + } + } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index a631314f..9ee03406 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -40,6 +40,8 @@ static SUCC_TESTS: &[(&str, &str, &str, &str, i32)] = &[ ("threads_arg\0", "\0", "\0", "\0", 0), ("threads\0", "\0", "\0", "\0", 0), ("yield\0", "\0", "\0", "\0", 0), + ("barrier_fail\0", "\0", "\0", "\0", 0), + ("barrier_condvar\0", "\0", "\0", "\0", 0), ]; static FAIL_TESTS: &[(&str, &str, &str, &str, i32)] = &[ From 2437bf0bce659407598eb804d191dfee9843b25c Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 27 Jan 2023 16:57:40 +0800 Subject: [PATCH 19/22] update mpsc_sem --- user/src/bin/mpsc_sem.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/user/src/bin/mpsc_sem.rs b/user/src/bin/mpsc_sem.rs index 7b92b9b4..7b72bbb1 100644 --- a/user/src/bin/mpsc_sem.rs +++ b/user/src/bin/mpsc_sem.rs @@ -14,7 +14,7 @@ use user_lib::{thread_create, waittid}; const SEM_MUTEX: usize = 0; const SEM_EMPTY: usize = 1; -const SEM_EXISTED: usize = 2; +const SEM_AVAIL: usize = 2; const BUFFER_SIZE: usize = 8; static mut BUFFER: [usize; BUFFER_SIZE] = [0; BUFFER_SIZE]; static mut FRONT: usize = 0; @@ -27,20 +27,20 @@ unsafe fn producer(id: *const usize) -> ! { for _ in 0..NUMBER_PER_PRODUCER { semaphore_down(SEM_EMPTY); semaphore_down(SEM_MUTEX); - BUFFER[FRONT] = id; - FRONT = (FRONT + 1) % BUFFER_SIZE; + BUFFER[TAIL] = id; + TAIL = (TAIL + 1) % BUFFER_SIZE; semaphore_up(SEM_MUTEX); - semaphore_up(SEM_EXISTED); + semaphore_up(SEM_AVAIL); } exit(0) } unsafe fn consumer() -> ! { for _ in 0..PRODUCER_COUNT * NUMBER_PER_PRODUCER { - semaphore_down(SEM_EXISTED); + semaphore_down(SEM_AVAIL); semaphore_down(SEM_MUTEX); - print!("{} ", BUFFER[TAIL]); - TAIL = (TAIL + 1) % BUFFER_SIZE; + print!("{} ", BUFFER[FRONT]); + FRONT = (FRONT + 1) % BUFFER_SIZE; semaphore_up(SEM_MUTEX); semaphore_up(SEM_EMPTY); } @@ -53,7 +53,7 @@ pub fn main() -> i32 { // create semaphores assert_eq!(semaphore_create(1) as usize, SEM_MUTEX); assert_eq!(semaphore_create(BUFFER_SIZE) as usize, SEM_EMPTY); - assert_eq!(semaphore_create(0) as usize, SEM_EXISTED); + assert_eq!(semaphore_create(0) as usize, SEM_AVAIL); // create threads let ids: Vec<_> = (0..PRODUCER_COUNT).collect(); let mut threads = Vec::new(); From 948ccff15df8b6a585f5732f0c0ad22033fc1710 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 1 Feb 2023 20:46:07 +0800 Subject: [PATCH 20/22] update condvar-related testcases. --- os/src/syscall/mod.rs | 2 +- os/src/syscall/sync.rs | 2 +- user/src/bin/barrier_condvar.rs | 2 +- .../{test_condvar.rs => condsync_condvar.rs} | 118 +++++++++--------- user/src/bin/condsync_sem.rs | 64 ++++++++++ user/src/sync.rs | 2 +- user/src/syscall.rs | 4 +- 7 files changed, 129 insertions(+), 65 deletions(-) rename user/src/bin/{test_condvar.rs => condsync_condvar.rs} (95%) create mode 100644 user/src/bin/condsync_sem.rs diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index d28073f7..4052cf53 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -70,7 +70,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_SEMAPHORE_CREATE => sys_semaphore_create(args[0]), SYSCALL_SEMAPHORE_UP => sys_semaphore_up(args[0]), SYSCALL_SEMAPHORE_DOWN => sys_semaphore_down(args[0]), - SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]), + SYSCALL_CONDVAR_CREATE => sys_condvar_create(), SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]), SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), SYSCALL_FRAMEBUFFER => sys_framebuffer(), diff --git a/os/src/syscall/sync.rs b/os/src/syscall/sync.rs index e08f3296..11806699 100644 --- a/os/src/syscall/sync.rs +++ b/os/src/syscall/sync.rs @@ -93,7 +93,7 @@ pub fn sys_semaphore_down(sem_id: usize) -> isize { 0 } -pub fn sys_condvar_create(_arg: usize) -> isize { +pub fn sys_condvar_create() -> isize { let process = current_process(); let mut process_inner = process.inner_exclusive_access(); let id = if let Some(id) = process_inner diff --git a/user/src/bin/barrier_condvar.rs b/user/src/bin/barrier_condvar.rs index db0a80ba..ca0953b3 100644 --- a/user/src/bin/barrier_condvar.rs +++ b/user/src/bin/barrier_condvar.rs @@ -28,7 +28,7 @@ impl Barrier { } pub fn block(&self) { mutex_lock(self.mutex_id); - let mut count = self.count.get(); + let count = self.count.get(); // SAFETY: Here, the accesses of the count is in the // critical section protected by the mutex. unsafe { *count = *count + 1; } diff --git a/user/src/bin/test_condvar.rs b/user/src/bin/condsync_condvar.rs similarity index 95% rename from user/src/bin/test_condvar.rs rename to user/src/bin/condsync_condvar.rs index 2db9d8a4..78605ad0 100644 --- a/user/src/bin/test_condvar.rs +++ b/user/src/bin/condsync_condvar.rs @@ -1,59 +1,59 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -extern crate alloc; - -use alloc::vec; -use user_lib::exit; -use user_lib::{ - condvar_create, condvar_signal, condvar_wait, mutex_blocking_create, mutex_lock, mutex_unlock, -}; -use user_lib::{sleep, thread_create, waittid}; - -static mut A: usize = 0; - -const CONDVAR_ID: usize = 0; -const MUTEX_ID: usize = 0; - -unsafe fn first() -> ! { - sleep(10); - println!("First work, Change A --> 1 and wakeup Second"); - mutex_lock(MUTEX_ID); - A = 1; - condvar_signal(CONDVAR_ID); - mutex_unlock(MUTEX_ID); - exit(0) -} - -unsafe fn second() -> ! { - println!("Second want to continue,but need to wait A=1"); - mutex_lock(MUTEX_ID); - while A == 0 { - println!("Second: A is {}", A); - condvar_wait(CONDVAR_ID, MUTEX_ID); - } - mutex_unlock(MUTEX_ID); - println!("A is {}, Second can work now", A); - exit(0) -} - -#[no_mangle] -pub fn main() -> i32 { - // create condvar & mutex - assert_eq!(condvar_create() as usize, CONDVAR_ID); - assert_eq!(mutex_blocking_create() as usize, MUTEX_ID); - // create threads - let threads = vec![ - thread_create(first as usize, 0), - thread_create(second as usize, 0), - ]; - // wait for all threads to complete - for thread in threads.iter() { - waittid(*thread as usize); - } - println!("test_condvar passed!"); - 0 -} +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +extern crate alloc; + +use alloc::vec; +use user_lib::exit; +use user_lib::{ + condvar_create, condvar_signal, condvar_wait, mutex_blocking_create, mutex_lock, mutex_unlock, +}; +use user_lib::{sleep, thread_create, waittid}; + +static mut A: usize = 0; + +const CONDVAR_ID: usize = 0; +const MUTEX_ID: usize = 0; + +unsafe fn first() -> ! { + sleep(10); + println!("First work, Change A --> 1 and wakeup Second"); + mutex_lock(MUTEX_ID); + A = 1; + condvar_signal(CONDVAR_ID); + mutex_unlock(MUTEX_ID); + exit(0) +} + +unsafe fn second() -> ! { + println!("Second want to continue,but need to wait A=1"); + mutex_lock(MUTEX_ID); + while A == 0 { + println!("Second: A is {}", A); + condvar_wait(CONDVAR_ID, MUTEX_ID); + } + println!("A is {}, Second can work now", A); + mutex_unlock(MUTEX_ID); + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + // create condvar & mutex + assert_eq!(condvar_create() as usize, CONDVAR_ID); + assert_eq!(mutex_blocking_create() as usize, MUTEX_ID); + // create threads + let threads = vec![ + thread_create(first as usize, 0), + thread_create(second as usize, 0), + ]; + // wait for all threads to complete + for thread in threads.iter() { + waittid(*thread as usize); + } + println!("test_condvar passed!"); + 0 +} diff --git a/user/src/bin/condsync_sem.rs b/user/src/bin/condsync_sem.rs new file mode 100644 index 00000000..d7b875a7 --- /dev/null +++ b/user/src/bin/condsync_sem.rs @@ -0,0 +1,64 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +extern crate alloc; + +use alloc::vec; +use user_lib::exit; +use user_lib::{ + semaphore_create, semaphore_down, semaphore_up, mutex_blocking_create, mutex_lock, mutex_unlock, +}; +use user_lib::{sleep, thread_create, waittid}; + +static mut A: usize = 0; + +const SEM_ID: usize = 0; +const MUTEX_ID: usize = 0; + +unsafe fn first() -> ! { + sleep(10); + println!("First work, Change A --> 1 and wakeup Second"); + mutex_lock(MUTEX_ID); + A = 1; + semaphore_up(SEM_ID); + mutex_unlock(MUTEX_ID); + exit(0) +} + +unsafe fn second() -> ! { + println!("Second want to continue,but need to wait A=1"); + loop { + mutex_lock(MUTEX_ID); + if A == 0 { + println!("Second: A is {}", A); + mutex_unlock(MUTEX_ID); + semaphore_down(SEM_ID); + } else { + mutex_unlock(MUTEX_ID); + break; + } + } + println!("A is {}, Second can work now", A); + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + // create semaphore & mutex + assert_eq!(semaphore_create(0) as usize, SEM_ID); + assert_eq!(mutex_blocking_create() as usize, MUTEX_ID); + // create threads + let threads = vec![ + thread_create(first as usize, 0), + thread_create(second as usize, 0), + ]; + // wait for all threads to complete + for thread in threads.iter() { + waittid(*thread as usize); + } + println!("test_condvar passed!"); + 0 +} diff --git a/user/src/sync.rs b/user/src/sync.rs index fbed4e31..c41e4d6b 100644 --- a/user/src/sync.rs +++ b/user/src/sync.rs @@ -22,7 +22,7 @@ pub fn semaphore_down(sem_id: usize) { sys_semaphore_down(sem_id); } pub fn condvar_create() -> isize { - sys_condvar_create(0) + sys_condvar_create() } pub fn condvar_signal(condvar_id: usize) { sys_condvar_signal(condvar_id); diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 530ea209..87885f53 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -147,8 +147,8 @@ pub fn sys_semaphore_down(sem_id: usize) -> isize { syscall(SYSCALL_SEMAPHORE_DOWN, [sem_id, 0, 0]) } -pub fn sys_condvar_create(_arg: usize) -> isize { - syscall(SYSCALL_CONDVAR_CREATE, [_arg, 0, 0]) +pub fn sys_condvar_create() -> isize { + syscall(SYSCALL_CONDVAR_CREATE, [0, 0, 0]) } pub fn sys_condvar_signal(condvar_id: usize) -> isize { From 314c92a5ec5ae7f4b93a2baf5125842b365b1f4b Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 1 Feb 2023 21:00:34 +0800 Subject: [PATCH 21/22] update usertests --- user/src/bin/usertests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index 9ee03406..b522af24 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -36,7 +36,8 @@ static SUCC_TESTS: &[(&str, &str, &str, &str, i32)] = &[ ("sleep\0", "\0", "\0", "\0", 0), ("sleep_simple\0", "\0", "\0", "\0", 0), ("sync_sem\0", "\0", "\0", "\0", 0), - ("test_condvar\0", "\0", "\0", "\0", 0), + ("condsync_sem\0", "\0", "\0", "\0", 0), + ("condsync_condvar\0", "\0", "\0", "\0", 0), ("threads_arg\0", "\0", "\0", "\0", 0), ("threads\0", "\0", "\0", "\0", 0), ("yield\0", "\0", "\0", "\0", 0), From 294386e7a507d2be226e1f6db908e41da55f0fa9 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 1 Feb 2023 21:17:43 +0800 Subject: [PATCH 22/22] Remove unnecessary output. --- easy-fs-fuse/src/main.rs | 6 +++--- user/Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs index 17b24654..bb9ff761 100644 --- a/easy-fs-fuse/src/main.rs +++ b/easy-fs-fuse/src/main.rs @@ -85,9 +85,9 @@ fn easy_fs_pack() -> std::io::Result<()> { inode.write_at(0, all_data.as_slice()); } // list apps - for app in root_inode.ls() { - println!("{}", app); - } + // for app in root_inode.ls() { + // println!("{}", app); + // } Ok(()) } diff --git a/user/Makefile b/user/Makefile index c09b5e96..51703278 100644 --- a/user/Makefile +++ b/user/Makefile @@ -19,7 +19,7 @@ ifeq ($(TEST), 1) endif binary: elf - $(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));) + @$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));) build: binary