mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 03:56:42 +00:00
Replace Mutex with Spinlock in tty to avoid deadlock
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
2b59a406a6
commit
2985cdced6
@ -1,10 +1,11 @@
|
|||||||
//! A port-mapped UART. Copied from uart_16550.
|
//! A port-mapped UART. Copied from uart_16550.
|
||||||
|
|
||||||
use crate::arch::x86::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
use crate::arch::x86::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
||||||
|
use crate::sync::SpinLock;
|
||||||
use crate::trap::IrqAllocateHandle;
|
use crate::trap::IrqAllocateHandle;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use spin::{Mutex, Once};
|
use spin::Once;
|
||||||
use trapframe::TrapFrame;
|
use trapframe::TrapFrame;
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
@ -24,9 +25,9 @@ static SERIAL_MODEM_CTRL: IoPort<u8, WriteOnlyAccess> =
|
|||||||
unsafe { IoPort::new(SERIAL_DATA_PORT + 4) };
|
unsafe { IoPort::new(SERIAL_DATA_PORT + 4) };
|
||||||
static SERIAL_LINE_STS: IoPort<u8, ReadWriteAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 5) };
|
static SERIAL_LINE_STS: IoPort<u8, ReadWriteAccess> = unsafe { IoPort::new(SERIAL_DATA_PORT + 5) };
|
||||||
|
|
||||||
static CONSOLE_IRQ_CALLBACK: Once<Mutex<IrqAllocateHandle>> = Once::new();
|
static CONSOLE_IRQ_CALLBACK: Once<SpinLock<IrqAllocateHandle>> = Once::new();
|
||||||
static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>>> =
|
static SERIAL_INPUT_CALLBACKS: SpinLock<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>>> =
|
||||||
Mutex::new(Vec::new());
|
SpinLock::new(Vec::new());
|
||||||
|
|
||||||
/// Initializes the serial port.
|
/// Initializes the serial port.
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
@ -56,7 +57,7 @@ pub fn register_serial_input_callback(f: impl Fn(u8) + Send + Sync + 'static) {
|
|||||||
pub(crate) fn callback_init() {
|
pub(crate) fn callback_init() {
|
||||||
let mut irq = crate::arch::x86::kernel::pic::allocate_irq(4).unwrap();
|
let mut irq = crate::arch::x86::kernel::pic::allocate_irq(4).unwrap();
|
||||||
irq.on_active(handle_serial_input);
|
irq.on_active(handle_serial_input);
|
||||||
CONSOLE_IRQ_CALLBACK.call_once(|| Mutex::new(irq));
|
CONSOLE_IRQ_CALLBACK.call_once(|| SpinLock::new(irq));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_serial_input_irq_handler<F>(callback: F)
|
pub(crate) fn register_serial_input_irq_handler<F>(callback: F)
|
||||||
@ -72,10 +73,11 @@ where
|
|||||||
|
|
||||||
fn handle_serial_input(trap_frame: &TrapFrame) {
|
fn handle_serial_input(trap_frame: &TrapFrame) {
|
||||||
// debug!("keyboard interrupt was met");
|
// debug!("keyboard interrupt was met");
|
||||||
if SERIAL_INPUT_CALLBACKS.is_locked() {
|
let lock = if let Some(lock) = SERIAL_INPUT_CALLBACKS.try_lock() {
|
||||||
|
lock
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
let lock = SERIAL_INPUT_CALLBACKS.lock();
|
|
||||||
let received_char = receive_char().unwrap();
|
let received_char = receive_char().unwrap();
|
||||||
debug!("receive char = {:?}", received_char);
|
debug!("receive char = {:?}", received_char);
|
||||||
for callback in lock.iter() {
|
for callback in lock.iter() {
|
||||||
|
@ -12,8 +12,10 @@ use core::{
|
|||||||
ops::{Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
};
|
};
|
||||||
use font8x8::UnicodeFonts;
|
use font8x8::UnicodeFonts;
|
||||||
use jinux_frame::{config::PAGE_SIZE, mmio::Mmio, vm::VmIo, LimineFramebufferRequest};
|
use jinux_frame::{
|
||||||
use spin::{Mutex, Once};
|
config::PAGE_SIZE, mmio::Mmio, sync::SpinLock, vm::VmIo, LimineFramebufferRequest,
|
||||||
|
};
|
||||||
|
use spin::Once;
|
||||||
|
|
||||||
#[init_component]
|
#[init_component]
|
||||||
fn framebuffer_init() -> Result<(), ComponentInitError> {
|
fn framebuffer_init() -> Result<(), ComponentInitError> {
|
||||||
@ -21,7 +23,7 @@ fn framebuffer_init() -> Result<(), ComponentInitError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) static WRITER: Once<Mutex<Writer>> = Once::new();
|
pub(crate) static WRITER: Once<SpinLock<Writer>> = Once::new();
|
||||||
static FRAMEBUFFER_REUEST: LimineFramebufferRequest = LimineFramebufferRequest::new(0);
|
static FRAMEBUFFER_REUEST: LimineFramebufferRequest = LimineFramebufferRequest::new(0);
|
||||||
|
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
@ -64,7 +66,7 @@ pub(crate) fn init() {
|
|||||||
};
|
};
|
||||||
writer.clear();
|
writer.clear();
|
||||||
|
|
||||||
WRITER.call_once(|| Mutex::new(writer));
|
WRITER.call_once(|| SpinLock::new(writer));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Writer {
|
pub(crate) struct Writer {
|
||||||
|
@ -11,6 +11,7 @@ pub fn init() -> Result<()> {
|
|||||||
add_node(null, "null")?;
|
add_node(null, "null")?;
|
||||||
let zero = Arc::new(zero::Zero);
|
let zero = Arc::new(zero::Zero);
|
||||||
add_node(zero, "zero")?;
|
add_node(zero, "zero")?;
|
||||||
|
tty::init();
|
||||||
let tty = tty::get_n_tty().clone();
|
let tty = tty::get_n_tty().clone();
|
||||||
add_node(tty, "tty")?;
|
add_node(tty, "tty")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,28 +1,30 @@
|
|||||||
pub use jinux_frame::arch::x86::device::serial::register_serial_input_callback;
|
pub use jinux_frame::arch::x86::device::serial::register_serial_input_callback;
|
||||||
|
use spin::Once;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
device::tty::{get_n_tty, Tty},
|
device::tty::{get_n_tty, Tty},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
pub static TTY_DRIVER: Once<Arc<TtyDriver>> = Once::new();
|
||||||
pub static ref TTY_DRIVER: Arc<TtyDriver> = {
|
|
||||||
let tty_driver = Arc::new(TtyDriver::new());
|
pub(super) fn init() {
|
||||||
// FIXME: install n_tty into tty_driver?
|
register_serial_input_callback(serial_input_callback);
|
||||||
let n_tty = get_n_tty();
|
let tty_driver = Arc::new(TtyDriver::new());
|
||||||
tty_driver.install(n_tty.clone());
|
// FIXME: install n_tty into tty_driver?
|
||||||
tty_driver
|
let n_tty = get_n_tty();
|
||||||
};
|
tty_driver.install(n_tty.clone());
|
||||||
|
TTY_DRIVER.call_once(|| tty_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TtyDriver {
|
pub struct TtyDriver {
|
||||||
ttys: Mutex<Vec<Arc<Tty>>>,
|
ttys: SpinLock<Vec<Arc<Tty>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TtyDriver {
|
impl TtyDriver {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ttys: Mutex::new(Vec::new()),
|
ttys: SpinLock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,9 +72,5 @@ fn serial_input_callback(item: u8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_tty_driver() -> &'static TtyDriver {
|
fn get_tty_driver() -> &'static TtyDriver {
|
||||||
&TTY_DRIVER
|
TTY_DRIVER.get().unwrap()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
register_serial_input_callback(serial_input_callback);
|
|
||||||
}
|
}
|
@ -15,13 +15,13 @@ const BUFFER_CAPACITY: usize = 4096;
|
|||||||
|
|
||||||
pub struct LineDiscipline {
|
pub struct LineDiscipline {
|
||||||
/// current line
|
/// current line
|
||||||
current_line: RwLock<CurrentLine>,
|
current_line: SpinLock<CurrentLine>,
|
||||||
/// The read buffer
|
/// The read buffer
|
||||||
read_buffer: Mutex<StaticRb<u8, BUFFER_CAPACITY>>,
|
read_buffer: SpinLock<StaticRb<u8, BUFFER_CAPACITY>>,
|
||||||
/// The foreground process group
|
/// The foreground process group
|
||||||
foreground: RwLock<Option<Pgid>>,
|
foreground: SpinLock<Option<Pgid>>,
|
||||||
/// termios
|
/// termios
|
||||||
termios: RwLock<KernelTermios>,
|
termios: SpinLock<KernelTermios>,
|
||||||
/// Pollee
|
/// Pollee
|
||||||
pollee: Pollee,
|
pollee: Pollee,
|
||||||
}
|
}
|
||||||
@ -65,17 +65,17 @@ impl LineDiscipline {
|
|||||||
/// create a new line discipline
|
/// create a new line discipline
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_line: RwLock::new(CurrentLine::new()),
|
current_line: SpinLock::new(CurrentLine::new()),
|
||||||
read_buffer: Mutex::new(StaticRb::default()),
|
read_buffer: SpinLock::new(StaticRb::default()),
|
||||||
foreground: RwLock::new(None),
|
foreground: SpinLock::new(None),
|
||||||
termios: RwLock::new(KernelTermios::default()),
|
termios: SpinLock::new(KernelTermios::default()),
|
||||||
pollee: Pollee::new(IoEvents::empty()),
|
pollee: Pollee::new(IoEvents::empty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// push char to line discipline. This function should be called in input interrupt handler.
|
/// push char to line discipline. This function should be called in input interrupt handler.
|
||||||
pub fn push_char(&self, mut item: u8) {
|
pub fn push_char(&self, mut item: u8) {
|
||||||
let termios = self.termios.read();
|
let termios = self.termios.lock();
|
||||||
if termios.contains_icrnl() {
|
if termios.contains_icrnl() {
|
||||||
if item == b'\r' {
|
if item == b'\r' {
|
||||||
item = b'\n'
|
item = b'\n'
|
||||||
@ -85,7 +85,7 @@ impl LineDiscipline {
|
|||||||
if item == *termios.get_special_char(CC_C_CHAR::VINTR) {
|
if item == *termios.get_special_char(CC_C_CHAR::VINTR) {
|
||||||
// type Ctrl + C, signal SIGINT
|
// type Ctrl + C, signal SIGINT
|
||||||
if termios.contains_isig() {
|
if termios.contains_isig() {
|
||||||
if let Some(fg) = *self.foreground.read() {
|
if let Some(fg) = *self.foreground.lock() {
|
||||||
let kernel_signal = KernelSignal::new(SIGINT);
|
let kernel_signal = KernelSignal::new(SIGINT);
|
||||||
let fg_group = process_table::pgid_to_process_group(fg).unwrap();
|
let fg_group = process_table::pgid_to_process_group(fg).unwrap();
|
||||||
fg_group.kernel_signal(kernel_signal);
|
fg_group.kernel_signal(kernel_signal);
|
||||||
@ -94,7 +94,7 @@ impl LineDiscipline {
|
|||||||
} else if item == *termios.get_special_char(CC_C_CHAR::VQUIT) {
|
} else if item == *termios.get_special_char(CC_C_CHAR::VQUIT) {
|
||||||
// type Ctrl + \, signal SIGQUIT
|
// type Ctrl + \, signal SIGQUIT
|
||||||
if termios.contains_isig() {
|
if termios.contains_isig() {
|
||||||
if let Some(fg) = *self.foreground.read() {
|
if let Some(fg) = *self.foreground.lock() {
|
||||||
let kernel_signal = KernelSignal::new(SIGQUIT);
|
let kernel_signal = KernelSignal::new(SIGQUIT);
|
||||||
let fg_group = process_table::pgid_to_process_group(fg).unwrap();
|
let fg_group = process_table::pgid_to_process_group(fg).unwrap();
|
||||||
fg_group.kernel_signal(kernel_signal);
|
fg_group.kernel_signal(kernel_signal);
|
||||||
@ -102,17 +102,17 @@ impl LineDiscipline {
|
|||||||
}
|
}
|
||||||
} else if item == *termios.get_special_char(CC_C_CHAR::VKILL) {
|
} else if item == *termios.get_special_char(CC_C_CHAR::VKILL) {
|
||||||
// erase current line
|
// erase current line
|
||||||
self.current_line.write().drain();
|
self.current_line.lock().drain();
|
||||||
} else if item == *termios.get_special_char(CC_C_CHAR::VERASE) {
|
} else if item == *termios.get_special_char(CC_C_CHAR::VERASE) {
|
||||||
// type backspace
|
// type backspace
|
||||||
let mut current_line = self.current_line.write();
|
let mut current_line = self.current_line.lock();
|
||||||
if !current_line.is_empty() {
|
if !current_line.is_empty() {
|
||||||
current_line.backspace();
|
current_line.backspace();
|
||||||
}
|
}
|
||||||
} else if meet_new_line(item, &self.get_termios()) {
|
} else if meet_new_line(item, &self.termios()) {
|
||||||
// a new line was met. We currently add the item to buffer.
|
// a new line was met. We currently add the item to buffer.
|
||||||
// when we read content, the item should be skipped if it's EOF.
|
// when we read content, the item should be skipped if it's EOF.
|
||||||
let mut current_line = self.current_line.write();
|
let mut current_line = self.current_line.lock();
|
||||||
current_line.push_char(item);
|
current_line.push_char(item);
|
||||||
let current_line_chars = current_line.drain();
|
let current_line_chars = current_line.drain();
|
||||||
for char in current_line_chars {
|
for char in current_line_chars {
|
||||||
@ -120,7 +120,7 @@ impl LineDiscipline {
|
|||||||
}
|
}
|
||||||
} else if item >= 0x20 && item < 0x7f {
|
} else if item >= 0x20 && item < 0x7f {
|
||||||
// printable character
|
// printable character
|
||||||
self.current_line.write().push_char(item);
|
self.current_line.lock().push_char(item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// raw mode
|
// raw mode
|
||||||
@ -148,7 +148,7 @@ impl LineDiscipline {
|
|||||||
let ch = char::from(item);
|
let ch = char::from(item);
|
||||||
print!("{}", ch);
|
print!("{}", ch);
|
||||||
}
|
}
|
||||||
let termios = self.termios.read();
|
let termios = self.termios.lock();
|
||||||
if item == *termios.get_special_char(CC_C_CHAR::VERASE) {
|
if item == *termios.get_special_char(CC_C_CHAR::VERASE) {
|
||||||
// write a space to overwrite current character
|
// write a space to overwrite current character
|
||||||
let bytes: [u8; 3] = [b'\x08', b' ', b'\x08'];
|
let bytes: [u8; 3] = [b'\x08', b' ', b'\x08'];
|
||||||
@ -202,7 +202,7 @@ impl LineDiscipline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (vmin, vtime) = {
|
let (vmin, vtime) = {
|
||||||
let termios = self.termios.read();
|
let termios = self.termios.lock();
|
||||||
let vmin = *termios.get_special_char(CC_C_CHAR::VMIN);
|
let vmin = *termios.get_special_char(CC_C_CHAR::VMIN);
|
||||||
let vtime = *termios.get_special_char(CC_C_CHAR::VTIME);
|
let vtime = *termios.get_special_char(CC_C_CHAR::VTIME);
|
||||||
(vmin, vtime)
|
(vmin, vtime)
|
||||||
@ -246,10 +246,11 @@ impl LineDiscipline {
|
|||||||
let mut read_len = 0;
|
let mut read_len = 0;
|
||||||
for i in 0..max_read_len {
|
for i in 0..max_read_len {
|
||||||
if let Some(next_char) = buffer.pop() {
|
if let Some(next_char) = buffer.pop() {
|
||||||
if self.termios.read().is_canonical_mode() {
|
let termios = self.termios.lock();
|
||||||
|
if termios.is_canonical_mode() {
|
||||||
// canonical mode, read until meet new line
|
// canonical mode, read until meet new line
|
||||||
if meet_new_line(next_char, &self.termios.read()) {
|
if meet_new_line(next_char, &termios) {
|
||||||
if !should_not_be_read(next_char, &self.termios.read()) {
|
if !should_not_be_read(next_char, &termios) {
|
||||||
dst[i] = next_char;
|
dst[i] = next_char;
|
||||||
read_len += 1;
|
read_len += 1;
|
||||||
}
|
}
|
||||||
@ -291,7 +292,7 @@ impl LineDiscipline {
|
|||||||
/// whether the current process belongs to foreground process group
|
/// whether the current process belongs to foreground process group
|
||||||
fn current_belongs_to_foreground(&self) -> bool {
|
fn current_belongs_to_foreground(&self) -> bool {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
if let Some(fg_pgid) = *self.foreground.read() {
|
if let Some(fg_pgid) = *self.foreground.lock() {
|
||||||
if let Some(process_group) = process_table::pgid_to_process_group(fg_pgid) {
|
if let Some(process_group) = process_table::pgid_to_process_group(fg_pgid) {
|
||||||
if process_group.contains_process(current.pid()) {
|
if process_group.contains_process(current.pid()) {
|
||||||
return true;
|
return true;
|
||||||
@ -304,7 +305,7 @@ impl LineDiscipline {
|
|||||||
|
|
||||||
/// set foreground process group
|
/// set foreground process group
|
||||||
pub fn set_fg(&self, fg_pgid: Pgid) {
|
pub fn set_fg(&self, fg_pgid: Pgid) {
|
||||||
*self.foreground.write() = Some(fg_pgid);
|
*self.foreground.lock() = Some(fg_pgid);
|
||||||
// Some background processes may be waiting on the wait queue, when set_fg, the background processes may be able to read.
|
// Some background processes may be waiting on the wait queue, when set_fg, the background processes may be able to read.
|
||||||
if self.is_readable() {
|
if self.is_readable() {
|
||||||
self.pollee.add_events(IoEvents::IN);
|
self.pollee.add_events(IoEvents::IN);
|
||||||
@ -312,8 +313,8 @@ impl LineDiscipline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// get foreground process group id
|
/// get foreground process group id
|
||||||
pub fn get_fg(&self) -> Option<Pgid> {
|
pub fn fg_pgid(&self) -> Option<Pgid> {
|
||||||
*self.foreground.read()
|
*self.foreground.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// whether there is buffered data
|
/// whether there is buffered data
|
||||||
@ -321,12 +322,12 @@ impl LineDiscipline {
|
|||||||
self.read_buffer.lock().len() == 0
|
self.read_buffer.lock().len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_termios(&self) -> KernelTermios {
|
pub fn termios(&self) -> KernelTermios {
|
||||||
*self.termios.read()
|
*self.termios.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_termios(&self, termios: KernelTermios) {
|
pub fn set_termios(&self, termios: KernelTermios) {
|
||||||
*self.termios.write() = termios;
|
*self.termios.lock() = termios;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
|
use spin::Once;
|
||||||
|
|
||||||
|
use self::driver::TtyDriver;
|
||||||
use self::line_discipline::LineDiscipline;
|
use self::line_discipline::LineDiscipline;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::driver::tty::TtyDriver;
|
|
||||||
use crate::fs::utils::{IoEvents, IoctlCmd, Poller};
|
use crate::fs::utils::{IoEvents, IoctlCmd, Poller};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::Pgid;
|
use crate::process::Pgid;
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
|
||||||
|
pub mod driver;
|
||||||
pub mod line_discipline;
|
pub mod line_discipline;
|
||||||
pub mod termio;
|
pub mod termio;
|
||||||
|
|
||||||
lazy_static! {
|
static N_TTY: Once<Arc<Tty>> = Once::new();
|
||||||
static ref N_TTY: Arc<Tty> = {
|
|
||||||
let name = CString::new("console").unwrap();
|
pub(super) fn init() {
|
||||||
Arc::new(Tty::new(name))
|
let name = CString::new("console").unwrap();
|
||||||
};
|
let tty = Arc::new(Tty::new(name));
|
||||||
|
N_TTY.call_once(|| tty);
|
||||||
|
driver::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tty {
|
pub struct Tty {
|
||||||
@ -22,7 +27,7 @@ pub struct Tty {
|
|||||||
/// line discipline
|
/// line discipline
|
||||||
ldisc: LineDiscipline,
|
ldisc: LineDiscipline,
|
||||||
/// driver
|
/// driver
|
||||||
driver: Mutex<Weak<TtyDriver>>,
|
driver: SpinLock<Weak<TtyDriver>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tty {
|
impl Tty {
|
||||||
@ -30,7 +35,7 @@ impl Tty {
|
|||||||
Tty {
|
Tty {
|
||||||
name,
|
name,
|
||||||
ldisc: LineDiscipline::new(),
|
ldisc: LineDiscipline::new(),
|
||||||
driver: Mutex::new(Weak::new()),
|
driver: SpinLock::new(Weak::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,14 +84,14 @@ impl Device for Tty {
|
|||||||
match cmd {
|
match cmd {
|
||||||
IoctlCmd::TCGETS => {
|
IoctlCmd::TCGETS => {
|
||||||
// Get terminal attributes
|
// Get terminal attributes
|
||||||
let termios = self.ldisc.get_termios();
|
let termios = self.ldisc.termios();
|
||||||
trace!("get termios = {:?}", termios);
|
trace!("get termios = {:?}", termios);
|
||||||
write_val_to_user(arg, &termios)?;
|
write_val_to_user(arg, &termios)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::TIOCGPGRP => {
|
IoctlCmd::TIOCGPGRP => {
|
||||||
// FIXME: Get the process group ID of the foreground process group on this terminal.
|
// FIXME: Get the process group ID of the foreground process group on this terminal.
|
||||||
let fg_pgid = self.ldisc.get_fg();
|
let fg_pgid = self.ldisc.fg_pgid();
|
||||||
match fg_pgid {
|
match fg_pgid {
|
||||||
None => return_errno_with_message!(Errno::ENOENT, "No fg process group"),
|
None => return_errno_with_message!(Errno::ENOENT, "No fg process group"),
|
||||||
Some(fg_pgid) => {
|
Some(fg_pgid) => {
|
||||||
@ -120,5 +125,5 @@ impl Device for Tty {
|
|||||||
|
|
||||||
/// FIXME: should we maintain a static console?
|
/// FIXME: should we maintain a static console?
|
||||||
pub fn get_n_tty() -> &'static Arc<Tty> {
|
pub fn get_n_tty() -> &'static Arc<Tty> {
|
||||||
&N_TTY
|
N_TTY.get().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
pub mod tty;
|
|
||||||
|
|
||||||
use jinux_input::INPUT_COMPONENT;
|
use jinux_input::INPUT_COMPONENT;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
@ -8,7 +6,6 @@ pub fn init() {
|
|||||||
for comp in INPUT_COMPONENT.get().unwrap().get_input_device() {
|
for comp in INPUT_COMPONENT.get().unwrap().get_input_device() {
|
||||||
info!("input device name:{}", comp.name());
|
info!("input device name:{}", comp.name());
|
||||||
}
|
}
|
||||||
tty::init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -18,6 +18,7 @@ pub(crate) use core::ffi::CStr;
|
|||||||
pub(crate) use int_to_c_enum::TryFromInt;
|
pub(crate) use int_to_c_enum::TryFromInt;
|
||||||
pub(crate) use jinux_frame::config::PAGE_SIZE;
|
pub(crate) use jinux_frame::config::PAGE_SIZE;
|
||||||
// pub(crate) use jinux_frame::sync::{Mutex, MutexGuard};
|
// pub(crate) use jinux_frame::sync::{Mutex, MutexGuard};
|
||||||
|
pub(crate) use jinux_frame::sync::{SpinLock, SpinLockGuard};
|
||||||
pub(crate) use jinux_frame::vm::Vaddr;
|
pub(crate) use jinux_frame::vm::Vaddr;
|
||||||
pub(crate) use jinux_frame::{print, println};
|
pub(crate) use jinux_frame::{print, println};
|
||||||
pub(crate) use log::{debug, error, info, trace, warn};
|
pub(crate) use log::{debug, error, info, trace, warn};
|
||||||
|
Reference in New Issue
Block a user