mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 08:26:17 +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.
|
/// 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…
Reference in New Issue
Block a user