use Mutex instead of Spinlock
This commit is contained in:
parent
bc8aa35180
commit
d46c341aaf
@ -2,7 +2,7 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
console::consoleintr, proc::wakeup, queue::Queue, sync::spinlock::Spinlock,
|
console::consoleintr, proc::wakeup, queue::Queue, sync::mutex::Mutex,
|
||||||
trap::InterruptBlocker,
|
trap::InterruptBlocker,
|
||||||
};
|
};
|
||||||
use core::ptr::addr_of;
|
use core::ptr::addr_of;
|
||||||
@ -60,16 +60,14 @@ impl Register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Uart {
|
pub struct Uart {
|
||||||
pub lock: Spinlock,
|
|
||||||
pub base_address: usize,
|
pub base_address: usize,
|
||||||
pub buffer: Queue<u8>,
|
pub buffer: Mutex<Queue<u8>>,
|
||||||
}
|
}
|
||||||
impl Uart {
|
impl Uart {
|
||||||
pub const fn new(base_address: usize) -> Uart {
|
pub const fn new(base_address: usize) -> Uart {
|
||||||
Uart {
|
Uart {
|
||||||
lock: Spinlock::new(),
|
|
||||||
base_address,
|
base_address,
|
||||||
buffer: Queue::new(),
|
buffer: Mutex::new(Queue::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Initialize the UART.
|
/// Initialize the UART.
|
||||||
@ -97,7 +95,6 @@ impl Uart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send buffered characters.
|
// Send buffered characters.
|
||||||
let _guard = self.lock.lock();
|
|
||||||
self.send_buffered_bytes();
|
self.send_buffered_bytes();
|
||||||
}
|
}
|
||||||
/// Read one byte from the UART.
|
/// Read one byte from the UART.
|
||||||
@ -135,7 +132,7 @@ impl Uart {
|
|||||||
/// Write a byte to the UART and buffer it.
|
/// Write a byte to the UART and buffer it.
|
||||||
/// Should not be used in interrupts.
|
/// Should not be used in interrupts.
|
||||||
pub fn write_byte_buffered(&self, b: u8) {
|
pub fn write_byte_buffered(&self, b: u8) {
|
||||||
let guard = self.lock.lock();
|
let mut buf = self.buffer.lock_spinning();
|
||||||
|
|
||||||
if unsafe { crate::PANICKED } {
|
if unsafe { crate::PANICKED } {
|
||||||
loop {
|
loop {
|
||||||
@ -144,19 +141,17 @@ impl Uart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sleep until there is space in the buffer.
|
// Sleep until there is space in the buffer.
|
||||||
while self.buffer.space_remaining() == 0 {
|
while buf.space_remaining() == 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
guard.sleep(addr_of!(*self).cast_mut().cast());
|
buf.sleep(addr_of!(*self).cast_mut().cast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafely cast self as mutable.
|
|
||||||
// self.lock is held so it should be fine.
|
|
||||||
let this: &mut Uart = unsafe { &mut *addr_of!(*self).cast_mut() };
|
|
||||||
|
|
||||||
// Add the byte onto the end of the queue.
|
// Add the byte onto the end of the queue.
|
||||||
this.buffer.push_back(b).expect("space in the uart queue");
|
buf.push_back(b).expect("space in the uart queue");
|
||||||
this.send_buffered_bytes();
|
// Drop buf so that send_buffered_bytes() can lock it again.
|
||||||
|
core::mem::drop(buf);
|
||||||
|
self.send_buffered_bytes();
|
||||||
}
|
}
|
||||||
pub fn write_slice_buffered(&self, bytes: &[u8]) {
|
pub fn write_slice_buffered(&self, bytes: &[u8]) {
|
||||||
for b in bytes {
|
for b in bytes {
|
||||||
@ -167,10 +162,10 @@ impl Uart {
|
|||||||
/// waiting in the transmit buffer, send it.
|
/// waiting in the transmit buffer, send it.
|
||||||
/// self.lock should be held.
|
/// self.lock should be held.
|
||||||
fn send_buffered_bytes(&self) {
|
fn send_buffered_bytes(&self) {
|
||||||
let this: &mut Uart = unsafe { &mut *addr_of!(*self).cast_mut() };
|
let mut buf = self.buffer.lock_spinning();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if Register::LineStatus.read(this.base_address) & LSR_TX_IDLE == 0 {
|
if Register::LineStatus.read(self.base_address) & LSR_TX_IDLE == 0 {
|
||||||
// The UART transmit holding register is full,
|
// The UART transmit holding register is full,
|
||||||
// so we cannot give it another byte.
|
// so we cannot give it another byte.
|
||||||
// It will interrupt when it's ready for a new byte.
|
// It will interrupt when it's ready for a new byte.
|
||||||
@ -178,7 +173,7 @@ impl Uart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pop a byte from the front of the queue.
|
// Pop a byte from the front of the queue.
|
||||||
let Some(b) = this.buffer.pop_front() else {
|
let Some(b) = buf.pop_front() else {
|
||||||
// The buffer is empty, we're finished sending bytes.
|
// The buffer is empty, we're finished sending bytes.
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -188,7 +183,7 @@ impl Uart {
|
|||||||
wakeup(addr_of!(*self).cast_mut().cast());
|
wakeup(addr_of!(*self).cast_mut().cast());
|
||||||
}
|
}
|
||||||
|
|
||||||
Register::TransmitHolding.write(this.base_address, b);
|
Register::TransmitHolding.write(self.base_address, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user