Code Transplanting: Blocking getchar

master
lcy1996 6 years ago
parent 9adcea44d5
commit 0b900b6f03

@ -22,6 +22,8 @@ pub fn init() {
stvec::write(__alltraps as usize, stvec::TrapMode::Direct); stvec::write(__alltraps as usize, stvec::TrapMode::Direct);
// Enable IPI // Enable IPI
sie::set_ssoft(); sie::set_ssoft();
// Enable serial interrupt
sie::set_sext();
} }
info!("interrupt: init end"); info!("interrupt: init end");
} }
@ -72,6 +74,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E}; use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E};
trace!("Interrupt: {:?}", tf.scause.cause()); trace!("Interrupt: {:?}", tf.scause.cause());
match tf.scause.cause() { match tf.scause.cause() {
Trap::Interrupt(I::SupervisorExternal) => serial(),
Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Interrupt(I::SupervisorTimer) => timer(),
Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf),
Trap::Exception(E::UserEnvCall) => syscall(tf), Trap::Exception(E::UserEnvCall) => syscall(tf),
@ -83,6 +86,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
trace!("Interrupt end"); trace!("Interrupt end");
} }
fn serial() {
::trap::serial(super::io::getchar());
}
fn ipi() { fn ipi() {
debug!("IPI"); debug!("IPI");
super::bbl::sbi::clear_ipi(); super::bbl::sbi::clear_ipi();

@ -1,11 +1,14 @@
use core::ops::Deref; use core::ops::Deref;
use alloc::string::String; use alloc::string::String;
use arch::io::getchar; use arch::io::getchar;
use alloc::collections::VecDeque;
use sync::Condvar;
use sync::SpinNoIrqLock as Mutex;
pub fn get_line() -> String { pub fn get_line() -> String {
let mut s = String::new(); let mut s = String::new();
loop { loop {
let c = getchar(); let c = get_char();
match c { match c {
'\u{7f}' /* '\b' */ => { '\u{7f}' /* '\b' */ => {
if s.pop().is_some() { if s.pop().is_some() {
@ -23,4 +26,31 @@ pub fn get_line() -> String {
_ => {} _ => {}
} }
} }
}
#[derive(Default)]
pub struct InputQueue {
buf: Mutex<VecDeque<char>>,
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()
} }

@ -5,10 +5,10 @@ use arch::cpu;
pub static mut TICK: usize = 0; pub static mut TICK: usize = 0;
pub fn timer() { pub fn timer() {
processor().tick();
if cpu::id() == 0 { if cpu::id() == 0 {
unsafe { TICK += 1; } unsafe { TICK += 1; }
} }
processor().tick();
//info!("finish before return!"); //info!("finish before return!");
} }
@ -20,4 +20,8 @@ pub fn error(tf: &TrapFrame) -> ! {
processor().manager().exit(pid, 0x100); processor().manager().exit(pid, 0x100);
processor().yield_now(); processor().yield_now();
unreachable!(); unreachable!();
} }
pub fn serial(c: char) {
::console::CONSOLE_INPUT.push(c);
}

@ -57,6 +57,8 @@ static void uart16550_done(const struct fdt_scan_node *node, void *extra)
uart16550[1] = 0x00; // (hi byte) uart16550[1] = 0x00; // (hi byte)
uart16550[3] = 0x03; // 8 bits, no parity, one stop bit uart16550[3] = 0x03; // 8 bits, no parity, one stop bit
uart16550[2] = 0xC7; // Enable FIFO, clear them, with 14-byte threshold 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) void query_uart16550(uintptr_t fdt)

Loading…
Cancel
Save