Blocking getchar

master
WangRunji 6 years ago
parent 0a6b4fb8f2
commit 16fb733497

@ -40,7 +40,7 @@ pub fn current() -> Thread {
/// Puts the current thread to sleep for the specified amount of time. /// Puts the current thread to sleep for the specified amount of time.
pub fn sleep(dur: Duration) { pub fn sleep(dur: Duration) {
let time = dur_to_ticks(dur); let time = dur_to_ticks(dur);
info!("sleep: {:?} ticks", time); trace!("sleep: {:?} ticks", time);
processor().manager().sleep(current().id(), time); processor().manager().sleep(current().id(), time);
park(); park();
@ -58,7 +58,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
F: Send + 'static + FnOnce() -> T, F: Send + 'static + FnOnce() -> T,
T: Send + 'static, T: Send + 'static,
{ {
info!("spawn:"); trace!("spawn:");
// 注意到下面的问题: // 注意到下面的问题:
// Processor只能从入口地址entry+参数arg创建新线程 // Processor只能从入口地址entry+参数arg创建新线程
@ -108,13 +108,13 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
/// Cooperatively gives up a timeslice to the OS scheduler. /// Cooperatively gives up a timeslice to the OS scheduler.
pub fn yield_now() { pub fn yield_now() {
info!("yield:"); trace!("yield:");
processor().yield_now(); processor().yield_now();
} }
/// Blocks unless or until the current thread's token is made available. /// Blocks unless or until the current thread's token is made available.
pub fn park() { pub fn park() {
info!("park:"); trace!("park:");
processor().manager().sleep(current().id(), 0); processor().manager().sleep(current().id(), 0);
processor().yield_now(); processor().yield_now();
} }

@ -16,6 +16,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");
} }
@ -44,6 +46,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 @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause()); trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause());
match tf.scause.cause() { match tf.scause.cause() {
Trap::Interrupt(I::SupervisorExternal) => serial(),
Trap::Interrupt(I::SupervisorSoft) => ipi(), Trap::Interrupt(I::SupervisorSoft) => ipi(),
Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Interrupt(I::SupervisorTimer) => timer(),
Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf),
@ -53,6 +56,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();

@ -29,7 +29,6 @@ impl SerialRead for SerialPort {
let ports = self as *mut _ as *mut [Pio<u8>; 6]; let ports = self as *mut _ as *mut [Pio<u8>; 6];
let line_sts = &(*ports)[5]; let line_sts = &(*ports)[5];
let data = &(*ports)[0]; let data = &(*ports)[0];
while line_sts.read() & 1 != 1 {}
data.read() data.read()
} }
} }

@ -131,6 +131,7 @@ fn keyboard() {
fn com1() { fn com1() {
use arch::driver::serial::*; use arch::driver::serial::*;
trace!("\nInterupt: COM1"); trace!("\nInterupt: COM1");
::trap::serial(COM1.lock().receive() as char);
} }
fn com2() { fn com2() {

@ -1,11 +1,13 @@
use core::ops::Deref; use core::ops::Deref;
use alloc::string::String; 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 { 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() {
@ -24,3 +26,33 @@ 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();
} }
pub fn error(tf: &TrapFrame) -> ! { pub fn error(tf: &TrapFrame) -> ! {
@ -20,3 +20,7 @@ pub fn error(tf: &TrapFrame) -> ! {
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