Still a lot of bugs :(
This commit is contained in:
parent
704eae3bb0
commit
26f44233f6
27 changed files with 308 additions and 95 deletions
|
@ -1,9 +1,9 @@
|
|||
use crate::sync::{Mutex, UPSafeCell};
|
||||
use crate::task::{add_task, block_current_and_run_next, current_task, TaskControlBlock};
|
||||
use crate::sync::{Mutex, UPIntrFreeCell};
|
||||
use crate::task::{add_task, block_current_task, block_current_and_run_next, current_task, TaskControlBlock, TaskContext};
|
||||
use alloc::{collections::VecDeque, sync::Arc};
|
||||
|
||||
pub struct Condvar {
|
||||
pub inner: UPSafeCell<CondvarInner>,
|
||||
pub inner: UPIntrFreeCell<CondvarInner>,
|
||||
}
|
||||
|
||||
pub struct CondvarInner {
|
||||
|
@ -14,7 +14,7 @@ impl Condvar {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPSafeCell::new(CondvarInner {
|
||||
UPIntrFreeCell::new(CondvarInner {
|
||||
wait_queue: VecDeque::new(),
|
||||
})
|
||||
},
|
||||
|
@ -35,6 +35,13 @@ impl Condvar {
|
|||
block_current_and_run_next();
|
||||
}
|
||||
|
||||
pub fn wait_no_sched(&self) -> *mut TaskContext {
|
||||
self.inner.exclusive_session(|inner| {
|
||||
inner.wait_queue.push_back(current_task().unwrap());
|
||||
});
|
||||
block_current_task()
|
||||
}
|
||||
|
||||
pub fn wait_with_mutex(&self, mutex: Arc<dyn Mutex>) {
|
||||
mutex.unlock();
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
|
|
|
@ -6,4 +6,4 @@ mod up;
|
|||
pub use condvar::Condvar;
|
||||
pub use mutex::{Mutex, MutexBlocking, MutexSpin};
|
||||
pub use semaphore::Semaphore;
|
||||
pub use up::UPSafeCell;
|
||||
pub use up::{UPIntrFreeCell, UPIntrRefMut};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::UPSafeCell;
|
||||
use super::UPIntrFreeCell;
|
||||
use crate::task::TaskControlBlock;
|
||||
use crate::task::{add_task, current_task};
|
||||
use crate::task::{block_current_and_run_next, suspend_current_and_run_next};
|
||||
|
@ -10,13 +10,13 @@ pub trait Mutex: Sync + Send {
|
|||
}
|
||||
|
||||
pub struct MutexSpin {
|
||||
locked: UPSafeCell<bool>,
|
||||
locked: UPIntrFreeCell<bool>,
|
||||
}
|
||||
|
||||
impl MutexSpin {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
locked: unsafe { UPSafeCell::new(false) },
|
||||
locked: unsafe { UPIntrFreeCell::new(false) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ impl Mutex for MutexSpin {
|
|||
}
|
||||
|
||||
pub struct MutexBlocking {
|
||||
inner: UPSafeCell<MutexBlockingInner>,
|
||||
inner: UPIntrFreeCell<MutexBlockingInner>,
|
||||
}
|
||||
|
||||
pub struct MutexBlockingInner {
|
||||
|
@ -55,7 +55,7 @@ impl MutexBlocking {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPSafeCell::new(MutexBlockingInner {
|
||||
UPIntrFreeCell::new(MutexBlockingInner {
|
||||
locked: false,
|
||||
wait_queue: VecDeque::new(),
|
||||
})
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::sync::UPSafeCell;
|
||||
use crate::sync::UPIntrFreeCell;
|
||||
use crate::task::{add_task, block_current_and_run_next, current_task, TaskControlBlock};
|
||||
use alloc::{collections::VecDeque, sync::Arc};
|
||||
|
||||
pub struct Semaphore {
|
||||
pub inner: UPSafeCell<SemaphoreInner>,
|
||||
pub inner: UPIntrFreeCell<SemaphoreInner>,
|
||||
}
|
||||
|
||||
pub struct SemaphoreInner {
|
||||
|
@ -15,7 +15,7 @@ impl Semaphore {
|
|||
pub fn new(res_count: usize) -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPSafeCell::new(SemaphoreInner {
|
||||
UPIntrFreeCell::new(SemaphoreInner {
|
||||
count: res_count as isize,
|
||||
wait_queue: VecDeque::new(),
|
||||
})
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use core::cell::{RefCell, RefMut};
|
||||
use core::cell::{RefCell, RefMut, UnsafeCell};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use riscv::register::sstatus;
|
||||
use lazy_static::*;
|
||||
|
||||
/// Wrap a static data structure inside it so that we are
|
||||
/// able to access it without any `unsafe`.
|
||||
|
@ -27,3 +30,103 @@ impl<T> UPSafeCell<T> {
|
|||
self.inner.borrow_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UPSafeCellRaw<T> {
|
||||
inner: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPSafeCellRaw<T> {}
|
||||
|
||||
impl<T> UPSafeCellRaw<T> {
|
||||
pub unsafe fn new(value: T) -> Self {
|
||||
Self {
|
||||
inner: UnsafeCell::new(value),
|
||||
}
|
||||
}
|
||||
pub fn get_mut(&self) -> &mut T {
|
||||
unsafe { &mut (*self.inner.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntrMaskingInfo {
|
||||
nested_level: usize,
|
||||
sie_before_masking: bool,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref INTR_MASKING_INFO: UPSafeCellRaw<IntrMaskingInfo> = unsafe {
|
||||
UPSafeCellRaw::new(IntrMaskingInfo::new())
|
||||
};
|
||||
}
|
||||
|
||||
impl IntrMaskingInfo {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
nested_level: 0,
|
||||
sie_before_masking: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter(&mut self) {
|
||||
let sie = sstatus::read().sie();
|
||||
unsafe { sstatus::clear_sie(); }
|
||||
if self.nested_level == 0 {
|
||||
self.sie_before_masking = sie;
|
||||
}
|
||||
self.nested_level += 1;
|
||||
}
|
||||
|
||||
pub fn exit(&mut self) {
|
||||
self.nested_level -= 1;
|
||||
if self.nested_level == 0 && self.sie_before_masking {
|
||||
unsafe { sstatus::set_sie(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UPIntrFreeCell<T> {
|
||||
/// inner data
|
||||
inner: RefCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPIntrFreeCell<T> {}
|
||||
|
||||
pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
|
||||
|
||||
impl<T> UPIntrFreeCell<T> {
|
||||
pub unsafe fn new(value: T) -> Self {
|
||||
Self {
|
||||
inner: RefCell::new(value),
|
||||
}
|
||||
}
|
||||
/// Panic if the data has been borrowed.
|
||||
pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> {
|
||||
INTR_MASKING_INFO.get_mut().enter();
|
||||
UPIntrRefMut(Some(self.inner.borrow_mut()))
|
||||
}
|
||||
|
||||
pub fn exclusive_session<F, V>(&self, f: F) -> V where F: FnOnce(&mut T) -> V {
|
||||
let mut inner = self.exclusive_access();
|
||||
f(inner.deref_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for UPIntrRefMut<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.0 = None;
|
||||
INTR_MASKING_INFO.get_mut().exit();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for UPIntrRefMut<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.as_ref().unwrap().deref()
|
||||
}
|
||||
}
|
||||
impl<'a, T> DerefMut for UPIntrRefMut<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.0.as_mut().unwrap().deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue