From 16fb733497522e1f8a5f3e6183c21629679f9e19 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Fri, 2 Nov 2018 16:36:46 +0800 Subject: [PATCH] Blocking getchar --- crate/process/src/thread.rs | 8 ++--- kernel/src/arch/riscv32/interrupt.rs | 7 ++++ kernel/src/arch/x86_64/driver/serial.rs | 1 - kernel/src/arch/x86_64/interrupt/handler.rs | 1 + kernel/src/console.rs | 38 +++++++++++++++++++-- kernel/src/trap.rs | 6 +++- riscv-pk/machine/uart16550.c | 2 ++ 7 files changed, 54 insertions(+), 9 deletions(-) diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index 1c8b1ade..7ffa0e6b 100644 --- a/crate/process/src/thread.rs +++ b/crate/process/src/thread.rs @@ -40,7 +40,7 @@ pub fn current() -> Thread { /// Puts the current thread to sleep for the specified amount of time. pub fn sleep(dur: Duration) { let time = dur_to_ticks(dur); - info!("sleep: {:?} ticks", time); + trace!("sleep: {:?} ticks", time); processor().manager().sleep(current().id(), time); park(); @@ -58,7 +58,7 @@ pub fn spawn(f: F) -> JoinHandle F: Send + 'static + FnOnce() -> T, T: Send + 'static, { - info!("spawn:"); + trace!("spawn:"); // 注意到下面的问题: // Processor只能从入口地址entry+参数arg创建新线程 @@ -108,13 +108,13 @@ pub fn spawn(f: F) -> JoinHandle /// Cooperatively gives up a timeslice to the OS scheduler. pub fn yield_now() { - info!("yield:"); + trace!("yield:"); processor().yield_now(); } /// Blocks unless or until the current thread's token is made available. pub fn park() { - info!("park:"); + trace!("park:"); processor().manager().sleep(current().id(), 0); processor().yield_now(); } diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index bad1812e..2229845d 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -16,6 +16,8 @@ pub fn init() { stvec::write(__alltraps as usize, stvec::TrapMode::Direct); // Enable IPI sie::set_ssoft(); + // Enable serial interrupt + sie::set_sext(); } info!("interrupt: init end"); } @@ -44,6 +46,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E}; trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); match tf.scause.cause() { + Trap::Interrupt(I::SupervisorExternal) => serial(), Trap::Interrupt(I::SupervisorSoft) => ipi(), Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), @@ -53,6 +56,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { trace!("Interrupt end"); } +fn serial() { + ::trap::serial(super::io::getchar()); +} + fn ipi() { debug!("IPI"); super::bbl::sbi::clear_ipi(); diff --git a/kernel/src/arch/x86_64/driver/serial.rs b/kernel/src/arch/x86_64/driver/serial.rs index 182e7339..fb398993 100644 --- a/kernel/src/arch/x86_64/driver/serial.rs +++ b/kernel/src/arch/x86_64/driver/serial.rs @@ -29,7 +29,6 @@ impl SerialRead for SerialPort { let ports = self as *mut _ as *mut [Pio; 6]; let line_sts = &(*ports)[5]; let data = &(*ports)[0]; - while line_sts.read() & 1 != 1 {} data.read() } } diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index a9e9ecf0..7c727d7b 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -131,6 +131,7 @@ fn keyboard() { fn com1() { use arch::driver::serial::*; trace!("\nInterupt: COM1"); + ::trap::serial(COM1.lock().receive() as char); } fn com2() { diff --git a/kernel/src/console.rs b/kernel/src/console.rs index 9f6efbd7..178b2680 100644 --- a/kernel/src/console.rs +++ b/kernel/src/console.rs @@ -1,11 +1,13 @@ use core::ops::Deref; use alloc::string::String; -use arch::io::getchar; +use alloc::collections::VecDeque; +use sync::Condvar; +use sync::SpinNoIrqLock as Mutex; pub fn get_line() -> String { let mut s = String::new(); loop { - let c = getchar(); + let c = get_char(); match c { '\u{7f}' /* '\b' */ => { if s.pop().is_some() { @@ -23,4 +25,34 @@ pub fn get_line() -> String { _ => {} } } -} \ No newline at end of file +} + +#[derive(Default)] +pub struct InputQueue { + buf: Mutex>, + pushed: Condvar, +} + +impl InputQueue { + pub fn push(&self, c: char) { + self.buf.lock().push_back(c); + self.pushed.notify_one(); + } + pub fn pop(&self) -> char { + loop { + let ret = self.buf.lock().pop_front(); + match ret { + Some(c) => return c, + None => self.pushed._wait(), + } + } + } +} + +lazy_static! { + pub static ref CONSOLE_INPUT: InputQueue = InputQueue::default(); +} + +pub fn get_char() -> char { + CONSOLE_INPUT.pop() +} diff --git a/kernel/src/trap.rs b/kernel/src/trap.rs index 529fd203..acfd17ab 100644 --- a/kernel/src/trap.rs +++ b/kernel/src/trap.rs @@ -5,10 +5,10 @@ use arch::cpu; pub static mut TICK: usize = 0; pub fn timer() { - processor().tick(); if cpu::id() == 0 { unsafe { TICK += 1; } } + processor().tick(); } pub fn error(tf: &TrapFrame) -> ! { @@ -19,4 +19,8 @@ pub fn error(tf: &TrapFrame) -> ! { processor().manager().exit(pid, 0x100); processor().yield_now(); unreachable!(); +} + +pub fn serial(c: char) { + ::console::CONSOLE_INPUT.push(c); } \ No newline at end of file diff --git a/riscv-pk/machine/uart16550.c b/riscv-pk/machine/uart16550.c index fe1ba99a..93fbb43a 100644 --- a/riscv-pk/machine/uart16550.c +++ b/riscv-pk/machine/uart16550.c @@ -57,6 +57,8 @@ static void uart16550_done(const struct fdt_scan_node *node, void *extra) uart16550[1] = 0x00; // (hi byte) uart16550[3] = 0x03; // 8 bits, no parity, one stop bit uart16550[2] = 0xC7; // Enable FIFO, clear them, with 14-byte threshold + uart16550[4] = 0x0B; + uart16550[1] = 0x01; // Enable interrupt } void query_uart16550(uintptr_t fdt)