From 4022cc3ed75e04c05d7e9a778e799d31b5f81d48 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 11 Jan 2023 09:02:54 -0800 Subject: [PATCH 1/8] 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 e9007f6..39f8173 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 83fb721..e55232d 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 ce36b2e..b28fd9c 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 0000000..bf77667 --- /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 0000000..6cc2e66 --- /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 31ce9ba..0d0db85 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 0000000..fbed4e3 --- /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 0000000..87d0dda --- /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 4430e86d5ad48c40f5c88fe1eebbe700a083d9ca Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 11 Jan 2023 19:37:36 -0800 Subject: [PATCH 2/8] 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 127a4ce..7122cec 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 857f12a..d7c40fc 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 531eec4..d10dc33 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 7e5a20a..4819ea6 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 8792f62..cf147a0 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 275fb17..1ecfe99 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 bec0b93..7cdd394 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 9482a30..77d62f4 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 af1585c..2758825 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 5d41c0c..c5ba8a4 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 7a28259..ee86bd3 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 d883d52..d28073f 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 f0cecc49409bfecd4c99cf2bcee0408cd5532e44 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Thu, 12 Jan 2023 00:21:57 -0800 Subject: [PATCH 3/8] 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 ded2765..d8f4216 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 d7c40fc..a9f5f0b 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 4819ea6..1103c57 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 35e06d5..7b1233e 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 39f8173..c8696be 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 e55232d..ccf5b89 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 b28fd9c..080c472 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 1e5b5a1..5b820d8 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 6cc2e66..baaa338 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 4e84c5767e9d50c19a5d19ae18551aa31bb08fbc Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 13 Jan 2023 09:54:54 +0800 Subject: [PATCH 4/8] 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 0000000..e7b1611 --- /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 0000000..fe2cdb1 --- /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 0000000..963dd75 --- /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 0000000..b96f933 --- /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 0000000..bba1f23 --- /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 0000000..fc5ff18 --- /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 0000000..d950eca --- /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 0000000..1c77777 --- /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 089841d..1fa2c41 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 c7b6747..0000000 --- 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 2feaed0..0000000 --- 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 0e4fe83..0000000 --- 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 e5affc4..0000000 --- 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 ed3bcec..0000000 --- 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 eb706fd..a631314 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 8326bf15165f7d612e2e38488ae3c338e36f8286 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Tue, 17 Jan 2023 13:28:31 +0800 Subject: [PATCH 5/8] 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 c8696be..a459dbc 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 274a7c0eb27a315e93bec77854f3ea176c097cb6 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Thu, 19 Jan 2023 13:55:17 +0800 Subject: [PATCH 6/8] 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 97e76bd..9ed25ae 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 c620890..ffc5c0e 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 24e40f3722b410a1f4e8f23daf8307d16c41bb98 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 20 Jan 2023 01:54:13 +0800 Subject: [PATCH 7/8] 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 714782c..b8ad07b 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 463638b..2b2db10 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 354db29..cb62c20 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 168ba32..7672cf5 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 9ed25ae..c835480 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 7be2d01..83c969d 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 29ef0a52d539f72f1d76e46f2c7a5b442e1c2896 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 25 Jan 2023 10:32:03 +0800 Subject: [PATCH 8/8] 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 7b1233e..d1816c6 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 0000000..db0a80b --- /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 0000000..0eb4b17 --- /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 a631314..9ee0340 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)] = &[