mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 16:16:16 +04:00
Blocking getchar
This commit is contained in:
parent
0a6b4fb8f2
commit
16fb733497
@ -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, T>(f: F) -> JoinHandle<T>
|
||||
F: Send + 'static + FnOnce() -> T,
|
||||
T: Send + 'static,
|
||||
{
|
||||
info!("spawn:");
|
||||
trace!("spawn:");
|
||||
|
||||
// 注意到下面的问题:
|
||||
// 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.
|
||||
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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -29,7 +29,6 @@ impl SerialRead for SerialPort {
|
||||
let ports = self as *mut _ as *mut [Pio<u8>; 6];
|
||||
let line_sts = &(*ports)[5];
|
||||
let data = &(*ports)[0];
|
||||
while line_sts.read() & 1 != 1 {}
|
||||
data.read()
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,7 @@ fn keyboard() {
|
||||
fn com1() {
|
||||
use arch::driver::serial::*;
|
||||
trace!("\nInterupt: COM1");
|
||||
::trap::serial(COM1.lock().receive() as char);
|
||||
}
|
||||
|
||||
fn com2() {
|
||||
|
@ -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 {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 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);
|
||||
}
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user