Move sleep_lock and sleep_mutex functionality as methods of Spinlock and SpinMutex
This commit is contained in:
parent
9f23b68c00
commit
585da48917
@ -13,7 +13,7 @@ pub mod uart;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::file::{devsw, CONSOLE},
|
fs::file::{devsw, CONSOLE},
|
||||||
proc::{killed, myproc, procdump, sleep_mutex, wakeup},
|
proc::{killed, myproc, procdump, wakeup},
|
||||||
sync::spinmutex::SpinMutex,
|
sync::spinmutex::SpinMutex,
|
||||||
};
|
};
|
||||||
use core::{ffi::c_void, ptr::addr_of_mut};
|
use core::{ffi::c_void, ptr::addr_of_mut};
|
||||||
@ -120,9 +120,8 @@ pub fn consoleread(user_dst: i32, mut dst: u64, mut n: i32) -> i32 {
|
|||||||
// cons.lock.unlock();
|
// cons.lock.unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// let channel = addr_of_mut!(console.read_index).cast();
|
let channel = addr_of_mut!(console.read_index).cast();
|
||||||
// console.sleep(channel);
|
console.sleep(channel);
|
||||||
sleep_mutex(addr_of_mut!(console.read_index).cast(), &mut console);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *console.read_byte();
|
c = *console.read_byte();
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
mem::kalloc::kfree,
|
mem::kalloc::kfree,
|
||||||
riscv::{self, Pagetable, PTE_W},
|
riscv::{self, Pagetable, PTE_W},
|
||||||
sync::spinlock::Spinlock,
|
sync::spinlock::{Spinlock, SpinlockGuard},
|
||||||
sync::spinmutex::SpinMutexGuard,
|
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::{c_char, c_void},
|
ffi::{c_char, c_void},
|
||||||
@ -341,53 +340,13 @@ pub unsafe extern "C" fn sched() {
|
|||||||
(*c).previous_interrupts_enabled = previous_interrupts_enabled;
|
(*c).previous_interrupts_enabled = previous_interrupts_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Atomically release lock and sleep on chan.
|
/// The lock should already be locked.
|
||||||
/// Reacquires lock when awakened.
|
/// Unsafely create a new guard for it so that we can call SpinlockGuard.sleep().
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) {
|
pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) {
|
||||||
let p = myproc();
|
let lock: &Spinlock = &*lock;
|
||||||
|
let guard = SpinlockGuard { lock };
|
||||||
// Must acquire p->lock in order to
|
guard.sleep(chan);
|
||||||
// change p->state and then call sched.
|
|
||||||
// Once we hold p->lock, we can be
|
|
||||||
// guaranteed that we won't miss any wakeup
|
|
||||||
// (wakeup locks p->lock),
|
|
||||||
// so it's okay to release lk.
|
|
||||||
|
|
||||||
let _guard = (*p).lock.lock();
|
|
||||||
(*lock).unlock();
|
|
||||||
|
|
||||||
// Go to sleep.
|
|
||||||
(*p).chan = chan;
|
|
||||||
(*p).state = ProcState::Sleeping;
|
|
||||||
|
|
||||||
sched();
|
|
||||||
|
|
||||||
// Tidy up.
|
|
||||||
(*p).chan = null_mut();
|
|
||||||
|
|
||||||
// Reacquire original lock.
|
|
||||||
(*lock).lock_unguarded();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
|
||||||
let p = myproc();
|
|
||||||
let mutex = mutex.mutex;
|
|
||||||
|
|
||||||
let _guard = (*p).lock.lock();
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
// Go to sleep.
|
|
||||||
(*p).chan = chan;
|
|
||||||
(*p).state = ProcState::Sleeping;
|
|
||||||
|
|
||||||
sched();
|
|
||||||
|
|
||||||
// Tidy up.
|
|
||||||
(*p).chan = null_mut();
|
|
||||||
|
|
||||||
// Reacquire original lock.
|
|
||||||
let guard = mutex.lock();
|
|
||||||
core::mem::forget(guard);
|
core::mem::forget(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pub(crate) mod mutex;
|
|
||||||
pub mod sleeplock;
|
pub mod sleeplock;
|
||||||
pub mod spinlock;
|
pub mod spinlock;
|
||||||
pub mod spinmutex;
|
pub mod spinmutex;
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
// use core::{
|
|
||||||
// cell::UnsafeCell,
|
|
||||||
// ops::{Deref, DerefMut, Drop},
|
|
||||||
// sync::atomic::{AtomicBool, Ordering},
|
|
||||||
// ffi::c_void,
|
|
||||||
// ptr::addr_of,
|
|
||||||
// };
|
|
||||||
// use crate::proc::{sleep, wakeup, sched, myproc, ProcState};
|
|
||||||
//
|
|
||||||
// pub struct Mutex<T> {
|
|
||||||
// locked: AtomicBool,
|
|
||||||
// inner: UnsafeCell<T>,
|
|
||||||
// }
|
|
||||||
// impl<T> Mutex<T> {
|
|
||||||
// pub const fn new(value: T) -> Mutex<T> {
|
|
||||||
// Mutex {
|
|
||||||
// locked: AtomicBool::new(false),
|
|
||||||
// inner: UnsafeCell::new(value),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// pub unsafe fn get_inner(&self) -> *mut T {
|
|
||||||
// self.inner.get()
|
|
||||||
// }
|
|
||||||
// /// Spin until the mutex is unlocked, acquiring afterwards.
|
|
||||||
// pub fn spin_lock(&self) -> MutexGuard<'_, T> {
|
|
||||||
// while self.locked.swap(true, Ordering::Acquire) {
|
|
||||||
// core::hint::spin_loop();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MutexGuard { mutex: self }
|
|
||||||
// }
|
|
||||||
// /// Sleep until the mutex is unlocked, acquiring afterwards.
|
|
||||||
// pub fn sleep_lock(&self) -> MutexGuard<'_, T> {
|
|
||||||
// while self.locked.swap(true, Ordering::Acquire) {
|
|
||||||
// unsafe {
|
|
||||||
// sleep(addr_of!(*self).cast_mut().cast());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MutexGuard { mutex: self }
|
|
||||||
// }
|
|
||||||
// pub unsafe fn unlock(&self) {
|
|
||||||
// self.locked.store(false, Ordering::Release);
|
|
||||||
// wakeup(addr_of!(*self).cast_mut().cast());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// unsafe impl<T> Sync for Mutex<T> where T: Send {}
|
|
||||||
//
|
|
||||||
// pub struct MutexGuard<'m, T> {
|
|
||||||
// pub mutex: &'m Mutex<T>,
|
|
||||||
// }
|
|
||||||
// impl<'m, T> MutexGuard<'m, T> {
|
|
||||||
// pub unsafe fn sleep(&mut self, channel: *mut c_void){
|
|
||||||
// let p = myproc();
|
|
||||||
// let _guard = (*p).lock.lock();
|
|
||||||
// self.mutex.unlock();
|
|
||||||
//
|
|
||||||
// // Go to sleep.
|
|
||||||
// (*p).chan = channel;
|
|
||||||
// (*p).state = ProcState::Sleeping;
|
|
||||||
// sched();
|
|
||||||
//
|
|
||||||
// // Clean up.
|
|
||||||
// let guard = self.mutex.spin_lock();
|
|
||||||
// core::mem::forget(guard);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl<'m, T> Deref for MutexGuard<'m, T> {
|
|
||||||
// type Target = T;
|
|
||||||
//
|
|
||||||
// fn deref(&self) -> &Self::Target {
|
|
||||||
// unsafe { &*self.mutex.get_inner() }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl<'m, T> DerefMut for MutexGuard<'m, T> {
|
|
||||||
// fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
// unsafe { &mut *self.mutex.get_inner() }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl<'m, T> Drop for MutexGuard<'m, T> {
|
|
||||||
// fn drop(&mut self) {
|
|
||||||
// unsafe { self.mutex.unlock() }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
@ -1,4 +1,4 @@
|
|||||||
use crate::proc::{wakeup, sleep};
|
use crate::proc::{sleep, wakeup};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::c_char,
|
ffi::c_char,
|
||||||
ptr::addr_of,
|
ptr::addr_of,
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
use crate::trap::{pop_intr_off, push_intr_off};
|
use crate::{
|
||||||
|
proc::{myproc, sched, ProcState},
|
||||||
|
trap::{pop_intr_off, push_intr_off},
|
||||||
|
};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::c_char,
|
ffi::c_char,
|
||||||
|
ptr::null_mut,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,6 +43,23 @@ impl Spinlock {
|
|||||||
pub struct SpinlockGuard<'l> {
|
pub struct SpinlockGuard<'l> {
|
||||||
pub lock: &'l Spinlock,
|
pub lock: &'l Spinlock,
|
||||||
}
|
}
|
||||||
|
impl<'l> SpinlockGuard<'l> {
|
||||||
|
/// Sleep until `wakeup(chan)` is called somewhere else, yielding the lock until then.
|
||||||
|
pub unsafe fn sleep(&self, chan: *mut core::ffi::c_void) {
|
||||||
|
let p = myproc();
|
||||||
|
let _guard = (*p).lock.lock();
|
||||||
|
self.lock.unlock();
|
||||||
|
|
||||||
|
// Put the process to sleep.
|
||||||
|
(*p).chan = chan;
|
||||||
|
(*p).state = ProcState::Sleeping;
|
||||||
|
sched();
|
||||||
|
|
||||||
|
// Tidy up and reacquire the lock.
|
||||||
|
(*p).chan = null_mut();
|
||||||
|
self.lock.lock_unguarded();
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<'l> Drop for SpinlockGuard<'l> {
|
impl<'l> Drop for SpinlockGuard<'l> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { self.lock.unlock() }
|
unsafe { self.lock.unlock() }
|
||||||
|
@ -1,38 +1,39 @@
|
|||||||
|
use crate::{
|
||||||
|
proc::{myproc, sched, ProcState},
|
||||||
|
sync::spinlock::Spinlock,
|
||||||
|
};
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
convert::{AsMut, AsRef},
|
convert::{AsMut, AsRef},
|
||||||
ops::{Deref, DerefMut, Drop},
|
ops::{Deref, DerefMut, Drop},
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
ptr::null_mut,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SpinMutex<T> {
|
pub struct SpinMutex<T> {
|
||||||
locked: AtomicBool,
|
lock: Spinlock,
|
||||||
pub inner: UnsafeCell<T>,
|
inner: UnsafeCell<T>,
|
||||||
}
|
}
|
||||||
impl<T> SpinMutex<T> {
|
impl<T> SpinMutex<T> {
|
||||||
pub const fn new(value: T) -> SpinMutex<T> {
|
pub const fn new(value: T) -> SpinMutex<T> {
|
||||||
SpinMutex {
|
SpinMutex {
|
||||||
locked: AtomicBool::new(false),
|
lock: Spinlock::new(),
|
||||||
inner: UnsafeCell::new(value),
|
inner: UnsafeCell::new(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub unsafe fn as_inner(&self) -> *mut T {
|
||||||
|
self.inner.get()
|
||||||
|
}
|
||||||
|
pub unsafe fn lock_unguarded(&self) {
|
||||||
|
self.lock.lock_unguarded();
|
||||||
|
}
|
||||||
pub fn lock(&self) -> SpinMutexGuard<'_, T> {
|
pub fn lock(&self) -> SpinMutexGuard<'_, T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
crate::trap::push_intr_off();
|
self.lock_unguarded();
|
||||||
}
|
}
|
||||||
|
|
||||||
while self.locked.swap(true, Ordering::Acquire) {
|
|
||||||
core::hint::spin_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
SpinMutexGuard { mutex: self }
|
SpinMutexGuard { mutex: self }
|
||||||
}
|
}
|
||||||
pub unsafe fn unlock(&self) {
|
pub unsafe fn unlock(&self) {
|
||||||
self.locked.store(false, Ordering::Release);
|
self.lock.unlock();
|
||||||
|
|
||||||
unsafe {
|
|
||||||
crate::trap::pop_intr_off();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe impl<T> Sync for SpinMutex<T> where T: Send {}
|
unsafe impl<T> Sync for SpinMutex<T> where T: Send {}
|
||||||
@ -40,16 +41,33 @@ unsafe impl<T> Sync for SpinMutex<T> where T: Send {}
|
|||||||
pub struct SpinMutexGuard<'m, T> {
|
pub struct SpinMutexGuard<'m, T> {
|
||||||
pub mutex: &'m SpinMutex<T>,
|
pub mutex: &'m SpinMutex<T>,
|
||||||
}
|
}
|
||||||
|
impl<'m, T> SpinMutexGuard<'m, T> {
|
||||||
|
/// Sleep until `wakeup(chan)` is called somewhere else, yielding access to the mutex until then.
|
||||||
|
pub unsafe fn sleep(&mut self, chan: *mut core::ffi::c_void) {
|
||||||
|
let p = myproc();
|
||||||
|
let _guard = (*p).lock.lock();
|
||||||
|
self.mutex.unlock();
|
||||||
|
|
||||||
|
// Put the process to sleep.
|
||||||
|
(*p).chan = chan;
|
||||||
|
(*p).state = ProcState::Sleeping;
|
||||||
|
sched();
|
||||||
|
|
||||||
|
// Tidy up and reacquire the mutex.
|
||||||
|
(*p).chan = null_mut();
|
||||||
|
self.mutex.lock_unguarded();
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<'m, T> Deref for SpinMutexGuard<'m, T> {
|
impl<'m, T> Deref for SpinMutexGuard<'m, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
unsafe { &*self.mutex.inner.get() }
|
unsafe { &*self.mutex.as_inner() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'m, T> DerefMut for SpinMutexGuard<'m, T> {
|
impl<'m, T> DerefMut for SpinMutexGuard<'m, T> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe { &mut *self.mutex.inner.get() }
|
unsafe { &mut *self.mutex.as_inner() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'m, T> AsRef<T> for SpinMutexGuard<'m, T> {
|
impl<'m, T> AsRef<T> for SpinMutexGuard<'m, T> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user