diff --git a/example/sudoku/Cargo.toml b/example/sudoku/Cargo.toml index 8b97f1a..e057119 100644 --- a/example/sudoku/Cargo.toml +++ b/example/sudoku/Cargo.toml @@ -13,7 +13,7 @@ authors = [ rkgpu = { path = "../../lib/rkgpu" } rkplat = { path = "../../lib/rkplat", features = ["has_smp", "driver_virtio_all", "driver_ns16550", "driver_goldfish_rtc"] } rkalloc = { path = "../../lib/rkalloc" } -rkboot = { path = "../../lib/rkboot", features = ["alloc_buddy", "sched_coop"] } +rkboot = { path = "../../lib/rkboot", features = ["alloc_buddy", "sched_preem"] } rkswrand = { path = "../../lib/rkswrand" } rksched = { path = "../../lib/rksched" } rklock = { path = "../../lib/rklock" } diff --git a/example/sudoku/src/cursor.rs b/example/sudoku/src/cursor.rs index f506491..4593381 100644 --- a/example/sudoku/src/cursor.rs +++ b/example/sudoku/src/cursor.rs @@ -30,15 +30,13 @@ // POSSIBILITY OF SUCH DAMAGE. use core::cmp::{max, min}; -use rkplat::drivers::virtio::__GPU_DEIVCE; use crate::DIRECTION::*; use crate::*; -use rkgpu::*; pub fn update_cursor(start_x: u32, start_y: u32, is_init: bool) { unsafe { - let (width, height) = __GPU_DEIVCE.as_mut().unwrap().resolution(); + let (width, height) = rkgpu::resolution(); if !is_init { for i in 1..(FB_CURSOR[0] + 1) as usize { FB[FB_CURSOR[5 * i - 4] as usize + 2] = FB_CURSOR[5 * i - 4 + 1] as u8; @@ -81,14 +79,14 @@ pub fn update_cursor(start_x: u32, start_y: u32, is_init: bool) { FB_CURSOR[0] = (idx_cursor / 5) as u32; draw_line(Horizontal, (max(10, start_x) - 10) as u32, (max(1, start_y) - 1) as u32, min(21, start_x + 10), BLACK, 255, 3); draw_line(Vertical, (max(1, start_x) - 1) as u32, (max(10, start_y) - 10) as u32, min(21, start_y + 10), BLACK, 255, 3); - __GPU_DEIVCE.as_mut().unwrap().flush().expect("failed to flush"); + rkgpu::screen_flush(); } } -pub unsafe fn draw_select(start_x: u32, start_y: u32, color: Color) { +pub fn draw_select(start_x: u32, start_y: u32, color: Color) { draw_line(Horizontal, start_x + 5, start_y + 5, 65, color, 255, 1); draw_line(Horizontal, start_x + 5, start_y + 70, 65, color, 255, 1); draw_line(Vertical, start_x + 5, start_y + 5, 65, color, 255, 1); draw_line(Vertical, start_x + 70, start_y + 5, 65, color, 255, 1); - __GPU_DEIVCE.as_mut().unwrap().flush().expect("failed to flush"); + super::screen_flush(); } diff --git a/example/sudoku/src/main.rs b/example/sudoku/src/main.rs index 5fee853..2489d48 100644 --- a/example/sudoku/src/main.rs +++ b/example/sudoku/src/main.rs @@ -31,12 +31,9 @@ #![no_std] #![no_main] -#![allow(unused)] -#![allow(non_upper_case_globals)] extern crate rkboot; extern crate alloc; -use rkplat::time::wall_clock; use rkgpu::*; use rkswrand::fast_random; @@ -44,7 +41,6 @@ use rksched::*; use core::time::Duration; use core::ptr::null_mut; use rklock::*; -use rktimeconv::TimePoint; pub mod key; pub mod input; @@ -57,6 +53,7 @@ pub use cursor::*; pub use output::*; use rkplat::println; +#[allow(non_upper_case_globals)] static mutex: Semaphore = Semaphore::new(0); pub struct Sudoku { @@ -188,83 +185,68 @@ pub fn if_fit_check(map: &[[usize; 9]; 9], x: usize, y: usize, number: usize, if * 返回 true 为有解,返回 false 为无解 */ -static mut timepoint: Duration = Duration::new(0, 0); - pub fn sudoku_solve(map: &mut [[usize; 9]; 9], row: usize, col: usize, depth: usize, is_init: bool) -> (bool, bool) { - unsafe { - let mut nextrow: usize = 0; - let mut nextcol: usize = 0; - if is_init { - if depth > 81 { - //println!("Out of depth!"); - return (false, true); + let mut nextrow: usize = 0; + let mut nextcol: usize = 0; + if is_init { + if depth > 81 { + //println!("Out of depth!"); + return (false, true); + } + let mut number = 0; + loop { + number += 1; + if number >= 10 { + break; } - let mut number = 0; - loop { - number += 1; - if number >= 10 { - break; - } - if !(if_fit_check(map, row, col, number, false)) { - continue; - } - map[row][col] = number; - if !(findnext_empty(map, row, &mut nextrow, &mut nextcol)) { - // 没有空位了,数独求解完成 - return (true, true); - } - let result = sudoku_solve(map, nextrow, nextcol, depth + 1, is_init); - if !result.0 { - map[row][col] = 0; - continue; - } else { - return (true, true); - } + if !(if_fit_check(map, row, col, number, false)) { + continue; + } + map[row][col] = number; + if !(findnext_empty(map, row, &mut nextrow, &mut nextcol)) { + // 没有空位了,数独求解完成 + return (true, true); } - (false, true) - } else { - let mut current_time: Duration = Duration::new(0, 0); - if depth == 0 { - timepoint = wall_clock(); + let result = sudoku_solve(map, nextrow, nextcol, depth + 1, is_init); + if !result.0 { + map[row][col] = 0; + continue; } else { - current_time = wall_clock(); - if current_time.as_secs() > timepoint.as_secs() + 1 { - timepoint = Duration::new(0, 0); - return (false, false); - } + return (true, true); + } + } + (false, true) + } else { + if depth > 81 { + return (false, true); + } + let mut number = 0; + loop { + number += 1; + if number >= 10 { + break; } - if depth > 81 { - //println!("Out of depth!"); - return (false, true); + if !(if_fit_check(map, row, col, number, false)) { + continue; } - let mut number = 0; - loop { - number += 1; - if number >= 10 { - break; - } - if !(if_fit_check(map, row, col, number, false)) { - continue; - } - map[row][col] = number; - if !(findnext_empty(map, row, &mut nextrow, &mut nextcol)) { - // 没有空位了,数独求解完成 - return (true, true); - } - let result = sudoku_solve(map, nextrow, nextcol, depth + 1, is_init); + map[row][col] = number; + if !(findnext_empty(map, row, &mut nextrow, &mut nextcol)) { + // 没有空位了,数独求解完成 + return (true, true); + } + let result = sudoku_solve(map, nextrow, nextcol, depth + 1, is_init); - if !result.1 { - map[row][col] = 0; - return (false, false); - } else if !result.0 { - map[row][col] = 0; - continue; - } else { - return (true, true); - } + if !result.1 { + map[row][col] = 0; + return (false, false); + } else if !result.0 { + map[row][col] = 0; + continue; + } else { + return (true, true); } - (false, true) } + (false, true) } } @@ -318,15 +300,15 @@ pub fn add_num(map: &mut [[usize; 9]; 9], row: usize, col: usize, num: usize, if return false; } if map[row][col] != 0 { - unsafe { mutex.signal(); } + mutex.signal(); return false; } if num > 9 || num <= 0 { - unsafe { mutex.signal(); } + mutex.signal(); return false; } if ifcheck && !(if_fit_check(map, row, col, num, false)) { - unsafe { mutex.signal(); } + mutex.signal(); return false; } @@ -405,47 +387,43 @@ pub fn hint(map: &mut [[usize; 9]; 9]) -> bool { return false; } - unsafe { show_sudoku_number(nextrow as u8, nextcol as u8, map_allzero[nextrow][nextcol] as u8, TAN); } + show_sudoku_number(nextrow as u8, nextcol as u8, map_allzero[nextrow][nextcol] as u8, TAN); return true; } pub fn error_hinter(_null: *mut u8) { - unsafe { - loop { - mutex.wait(); - printg("You can't write this number HERE!", 700, 500, RED, 255, 2); - rksched::this_thread::sleep_for(Duration::from_secs(1)); - printg(" ", 700, 500, RED, 255, 2); - } + loop { + mutex.wait(); + printg("You can't write this number HERE!", 700, 500, RED, 255, 2); + rksched::this_thread::sleep_for(Duration::from_secs(1)); + printg(" ", 700, 500, RED, 255, 2); } } fn init(sudoku: &mut Sudoku) { - unsafe { - sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), input_tracer, null_mut()).unwrap(); - - sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), error_hinter, null_mut()).unwrap(); - - sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), show_time, null_mut()).unwrap(); - rkgpu::init(); - printg("Hello, world!\nHello, OSH-2022!\nHello, Runikraft!\n", 700, 10, RED, 255, 4); - printg("Use W, A, S, and D to move selecting rectangle.\nUse up, left, down, and right to move cursor.\nUse H for hint, use O for solution.", 0, 700, BLACK, 255, 2); - update_cursor(900, 400, true); - draw_select(0, 0, RED); - draw_sudoku_lattices(PURPLE, BLACK); - screen_flush(); - row_random(&mut sudoku.map, 0); - sudoku_solve(&mut sudoku.map, 1, 1, 0, true); - hole_dig(&mut sudoku.map, 15, &mut sudoku.tag); - sudoku.map_print(); - println!("Hello sudoku!\n"); - } + unsafe {rkgpu::init();} + sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), input_tracer, null_mut()).unwrap(); + + sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), error_hinter, null_mut()).unwrap(); + + sched::create_thread("", rkalloc::get_default().unwrap(), thread::ThreadAttr::default(), rksched::thread::ThreadLimit::default(), show_time, null_mut()).unwrap(); + + printg("Hello, world!\nHello, OSH-2022!\nHello, Runikraft!\n", 700, 10, RED, 255, 4); + printg("Use W, A, S, and D to move selecting rectangle.\nUse up, left, down, and right to move cursor.\nUse H for hint, use O for solution.", 0, 700, BLACK, 255, 2); + update_cursor(900, 400, true); + draw_select(0, 0, RED); + draw_sudoku_lattices(PURPLE, BLACK); + screen_flush(); + row_random(&mut sudoku.map, 0); + sudoku_solve(&mut sudoku.map, 1, 1, 0, true); + hole_dig(&mut sudoku.map, 15, &mut sudoku.tag); + sudoku.map_print(); + println!("Hello sudoku!\n"); } #[no_mangle] fn main() { - //println!("sudoku main\n"); let mut sudoku: Sudoku = sudoku_init_zero(); init(&mut sudoku); unsafe { diff --git a/example/sudoku/src/output.rs b/example/sudoku/src/output.rs index 0860c10..2c9b1a9 100644 --- a/example/sudoku/src/output.rs +++ b/example/sudoku/src/output.rs @@ -30,14 +30,13 @@ // POSSIBILITY OF SUCH DAMAGE. use core::time::Duration; -use rkplat::drivers::virtio::__GPU_DEIVCE; use rkgpu::*; use rkplat::time::wall_clock; use rktimeconv::*; use crate::{mutex, Sudoku}; -pub unsafe fn draw_sudoku_lattices(color0: Color, color1: Color) -> u8 { - let (width, height) = __GPU_DEIVCE.as_mut().unwrap().resolution(); +pub fn draw_sudoku_lattices(color0: Color, color1: Color) -> u8 { + let (width, height) = super::resolution(); if width >= 750 && height >= 750 { for x in 0..10 { if x % 3 == 0 { @@ -58,7 +57,7 @@ pub unsafe fn draw_sudoku_lattices(color0: Color, color1: Color) -> u8 { } else { 0 } } -pub unsafe fn show_sudoku_number(pos_x: u8, pos_y: u8, number: u8, color: Color) -> u8 { +pub fn show_sudoku_number(pos_x: u8, pos_y: u8, number: u8, color: Color) -> u8 { if pos_x <= 8 && pos_y <= 8 { let start_x: u32 = 75 * pos_x as u32 + 20; let start_y: u32 = 75 * pos_y as u32 + 6; @@ -84,20 +83,18 @@ pub fn show_time(_null: *mut u8) { } pub fn error_hinter(_null: *mut u8) { - unsafe { - loop { - mutex.wait(); - printg("You can't write this number HERE!", 700, 500, RED, 255, 2); - rksched::this_thread::sleep_for(Duration::from_secs(1)); - printg(" ", 700, 500, RED, 255, 2); - } + loop { + mutex.wait(); + printg("You can't write this number HERE!", 700, 500, RED, 255, 2); + rksched::this_thread::sleep_for(Duration::from_secs(1)); + printg(" ", 700, 500, RED, 255, 2); } } impl Sudoku { // 打印当前数独信息 - pub unsafe fn map_print(&self) { + pub fn map_print(&self) { for i in 0..9 { for j in 0..9 { // show_sudoku_number(pos_x: u8, pos_y: u8, number: u8); diff --git a/lib/rkgpu/src/lib.rs b/lib/rkgpu/src/lib.rs index 1929af1..dc328fe 100644 --- a/lib/rkgpu/src/lib.rs +++ b/lib/rkgpu/src/lib.rs @@ -47,8 +47,10 @@ pub static mut FB: &mut [u8] = unsafe { &mut _EMPTY }; pub static mut FB_CURSOR: &mut [u32] = &mut [0; 1000]; pub unsafe fn init() { + let flag = rkplat::lcpu::save_irqf(); FB = __GPU_DEIVCE.as_mut().unwrap().setup_framebuffer().expect("failed to get FB"); draw_clear(LIGHT_CYAN); + rkplat::lcpu::restore_irqf(flag); } pub fn resolution() -> (u32, u32) { @@ -56,8 +58,9 @@ pub fn resolution() -> (u32, u32) { } pub fn draw_clear(color: Color) { + let flag = rkplat::lcpu::save_irqf(); unsafe { - let (width, height) = __GPU_DEIVCE.as_mut().unwrap().resolution(); + let (width, height) = resolution(); for y in 0..height as usize { for x in 0..width as usize { let idx = (y * width as usize + x) * 4; @@ -69,10 +72,13 @@ pub fn draw_clear(color: Color) { } __GPU_DEIVCE.as_mut().unwrap().flush().expect("failed to flush"); } + rkplat::lcpu::restore_irqf(flag); } pub fn screen_flush() { + let flag = rkplat::lcpu::save_irqf(); unsafe { __GPU_DEIVCE.as_mut().unwrap().flush().expect("failed to flush"); } + rkplat::lcpu::restore_irqf(flag); } diff --git a/lib/rkgpu/src/output.rs b/lib/rkgpu/src/output.rs index 6131681..0d9715d 100644 --- a/lib/rkgpu/src/output.rs +++ b/lib/rkgpu/src/output.rs @@ -27,10 +27,8 @@ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -#![allow(unused)] -use rkplat::drivers::virtio::__GPU_DEIVCE; use crate::*; -use core::cmp::{min,max}; +use core::cmp::min; pub enum DIRECTION { Horizontal, @@ -39,7 +37,8 @@ pub enum DIRECTION { pub fn draw_line(direction: DIRECTION, start_x: u32, start_y: u32, length: u32, color: Color, alpha: u8, line_width: u32) { unsafe { - let (width, height) = __GPU_DEIVCE.as_mut().unwrap().resolution(); + let (width, height) = super::resolution(); + let flag = rkplat::lcpu::save_irqf(); match direction { Horizontal => { for y in 0..min(line_width, height - start_y) { @@ -64,13 +63,16 @@ pub fn draw_line(direction: DIRECTION, start_x: u32, start_y: u32, length: u32, } } } + rkplat::lcpu::restore_irqf(flag); } } pub fn draw_font(start_x: u32, start_y: u32, color: Color, alpha: u8, ch: char, size: u8) -> u8 { unsafe { - let (width, height) = __GPU_DEIVCE.as_mut().unwrap().resolution(); + let (width, height) = super::resolution(); + if start_x + 8 * size as u32 <= width && start_y + 16 * size as u32 <= height { + let flag = rkplat::lcpu::save_irqf(); let pos = DIC[ch as usize]; for y in start_y..start_y + 16 * size as u32 { for x in start_x..start_x + 8 * size as u32 { @@ -89,25 +91,23 @@ pub fn draw_font(start_x: u32, start_y: u32, color: Color, alpha: u8, ch: char, } } } - + rkplat::lcpu::restore_irqf(flag); 0 } else { 1 } } } pub fn printg(ascii_str: &str, start_x: u32, start_y: u32, color: Color, alpha: u8, size: u8) { - unsafe { - let mut x = start_x; - let mut y = start_y; - for ascii in ascii_str.chars() { - if ascii == '\n' { - x = start_x; - y += 16 * size as u32; - } else { - draw_font(x, y, color, alpha, ascii, size); - x += 8 * size as u32; - } + let mut x = start_x; + let mut y = start_y; + for ascii in ascii_str.chars() { + if ascii == '\n' { + x = start_x; + y += 16 * size as u32; + } else { + draw_font(x, y, color, alpha, ascii, size); + x += 8 * size as u32; } - __GPU_DEIVCE.as_mut().unwrap().flush().expect("failed to flush"); } + super::screen_flush(); } diff --git a/lib/rkplat/src/riscv64/console.rs b/lib/rkplat/src/riscv64/console.rs index 1802e98..113f4d7 100644 --- a/lib/rkplat/src/riscv64/console.rs +++ b/lib/rkplat/src/riscv64/console.rs @@ -119,13 +119,17 @@ struct RustStyleOutput; static LOCK: super::spinlock::SpinLock = super::spinlock::SpinLock::new(); pub(crate) fn __print_bios(args: fmt::Arguments) { + let flag = super::lcpu::save_irqf(); let _lock = LOCK.lock(); RustStyleOutputBIOS.write_fmt(args).unwrap(); + super::lcpu::restore_irqf(flag); } pub fn __print(args: fmt::Arguments) { + let flag = super::lcpu::save_irqf(); let _lock = LOCK.lock(); RustStyleOutput.write_fmt(args).unwrap(); + super::lcpu::restore_irqf(flag); } impl Write for RustStyleOutputBIOS { diff --git a/lib/rksched/src/thread.rs b/lib/rksched/src/thread.rs index 0c109a0..a63b791 100644 --- a/lib/rksched/src/thread.rs +++ b/lib/rksched/src/thread.rs @@ -111,7 +111,8 @@ impl Default for ThreadAttr { Self { detached: WAITABLE, prio: PRIO_DEFAULT, - timeslice: Duration::from_millis(50), + //FIXME: 太小的时间片会导致无法启动GPU device + timeslice: Duration::from_millis(500), deadline: Duration::MAX, stack_size: runikraft::config::rksched::STACK_SIZE, tls_size: 0, diff --git a/lib/rkschedpreem/src/lib.rs b/lib/rkschedpreem/src/lib.rs index e94740b..375ae22 100644 --- a/lib/rkschedpreem/src/lib.rs +++ b/lib/rkschedpreem/src/lib.rs @@ -227,10 +227,9 @@ impl RKschedpreem { rkplat::lcpu::disable_irq(); let mut flag = rkplat::lcpu::save_irqf(); flag |= 1<