implement guards for spinlock and sleeplock
This commit is contained in:
parent
f468ba9e48
commit
38e44e020b
@ -73,10 +73,9 @@ pub unsafe extern "C" fn kfree(pa: *mut u8) {
|
|||||||
|
|
||||||
let run: *mut Run = pa.cast();
|
let run: *mut Run = pa.cast();
|
||||||
|
|
||||||
kmem.lock.lock_unguarded();
|
let _guard = kmem.lock.lock();
|
||||||
(*run).next = kmem.freelist;
|
(*run).next = kmem.freelist;
|
||||||
kmem.freelist = run;
|
kmem.freelist = run;
|
||||||
kmem.lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate one 4096-byte page of physical memory.
|
/// Allocate one 4096-byte page of physical memory.
|
||||||
@ -85,15 +84,13 @@ pub unsafe extern "C" fn kfree(pa: *mut u8) {
|
|||||||
/// Returns 0 if the memory cannot be allocated.
|
/// Returns 0 if the memory cannot be allocated.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn kalloc() -> *mut u8 {
|
pub unsafe extern "C" fn kalloc() -> *mut u8 {
|
||||||
kmem.lock.lock_unguarded();
|
let _guard = kmem.lock.lock();
|
||||||
|
|
||||||
let run = kmem.freelist;
|
let run = kmem.freelist;
|
||||||
if !run.is_null() {
|
if !run.is_null() {
|
||||||
kmem.freelist = (*run).next;
|
kmem.freelist = (*run).next;
|
||||||
}
|
}
|
||||||
|
|
||||||
kmem.lock.unlock();
|
|
||||||
|
|
||||||
if !run.is_null() {
|
if !run.is_null() {
|
||||||
memset(run.cast(), 0, PGSIZE as u32);
|
memset(run.cast(), 0, PGSIZE as u32);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,8 @@ pub struct PrintLock {
|
|||||||
|
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => {{
|
($($arg:tt)*) => {{
|
||||||
unsafe { $crate::printf::PRINT_LOCK.lock_unguarded() };
|
// Still unsafe because static mut.
|
||||||
|
let _guard = unsafe { $crate::printf::PRINT_LOCK.lock() };
|
||||||
|
|
||||||
// Allocate a page of memory as the buffer and release it when we're done.
|
// Allocate a page of memory as the buffer and release it when we're done.
|
||||||
let buf = unsafe { $crate::kalloc::kalloc() as *mut [u8; 4096] };
|
let buf = unsafe { $crate::kalloc::kalloc() as *mut [u8; 4096] };
|
||||||
@ -29,7 +30,6 @@ macro_rules! print {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe { $crate::kalloc::kfree(buf.cast()) };
|
unsafe { $crate::kalloc::kfree(buf.cast()) };
|
||||||
unsafe { $crate::printf::PRINT_LOCK.unlock() };
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
pub(crate) use print;
|
pub(crate) use print;
|
||||||
@ -58,8 +58,7 @@ pub unsafe extern "C" fn printstr(s: *const c_char) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn printfinit() {
|
pub unsafe extern "C" fn printfinit() {
|
||||||
PRINT_LOCK = Spinlock::new(
|
PRINT_LOCK = Spinlock::new(
|
||||||
CStr::from_bytes_with_nul(b"pr\0")
|
CStr::from_bytes_with_nul_unchecked(b"pr\0")
|
||||||
.unwrap()
|
|
||||||
.as_ptr()
|
.as_ptr()
|
||||||
.cast_mut(),
|
.cast_mut(),
|
||||||
);
|
);
|
||||||
|
@ -247,11 +247,9 @@ pub unsafe extern "C" fn myproc() -> *mut Proc {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn allocpid() -> i32 {
|
pub unsafe extern "C" fn allocpid() -> i32 {
|
||||||
let lock = addr_of_mut!(pid_lock);
|
let _guard = pid_lock.lock();
|
||||||
(*lock).lock_unguarded();
|
|
||||||
let pid = nextpid;
|
let pid = nextpid;
|
||||||
nextpid += 1;
|
nextpid += 1;
|
||||||
(*lock).unlock();
|
|
||||||
pid
|
pid
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,10 +373,9 @@ pub unsafe extern "C" fn growproc(n: i32) -> i32 {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn r#yield() {
|
pub unsafe extern "C" fn r#yield() {
|
||||||
let p = myproc();
|
let p = myproc();
|
||||||
(*p).lock.lock_unguarded();
|
let _guard = (*p).lock.lock();
|
||||||
(*p).state = ProcState::Runnable;
|
(*p).state = ProcState::Runnable;
|
||||||
sched();
|
sched();
|
||||||
(*p).lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch to scheduler. Must hold only p->lock
|
/// Switch to scheduler. Must hold only p->lock
|
||||||
@ -421,7 +418,7 @@ pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) {
|
|||||||
// (wakeup locks p->lock),
|
// (wakeup locks p->lock),
|
||||||
// so it's okay to release lk.
|
// so it's okay to release lk.
|
||||||
|
|
||||||
(*p).lock.lock_unguarded();
|
let _guard = (*p).lock.lock();
|
||||||
(*lock).unlock();
|
(*lock).unlock();
|
||||||
|
|
||||||
// Go to sleep.
|
// Go to sleep.
|
||||||
@ -434,7 +431,6 @@ pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) {
|
|||||||
(*p).chan = null_mut();
|
(*p).chan = null_mut();
|
||||||
|
|
||||||
// Reacquire original lock.
|
// Reacquire original lock.
|
||||||
(*p).lock.unlock();
|
|
||||||
(*lock).lock_unguarded();
|
(*lock).lock_unguarded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +438,7 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
|||||||
let p = myproc();
|
let p = myproc();
|
||||||
let mutex = mutex.mutex;
|
let mutex = mutex.mutex;
|
||||||
|
|
||||||
(*p).lock.lock_unguarded();
|
let _guard = (*p).lock.lock();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
// Go to sleep.
|
// Go to sleep.
|
||||||
@ -455,7 +451,6 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
|||||||
(*p).chan = null_mut();
|
(*p).chan = null_mut();
|
||||||
|
|
||||||
// Reacquire original lock.
|
// Reacquire original lock.
|
||||||
(*p).lock.unlock();
|
|
||||||
let guard = mutex.lock();
|
let guard = mutex.lock();
|
||||||
core::mem::forget(guard);
|
core::mem::forget(guard);
|
||||||
}
|
}
|
||||||
@ -466,7 +461,7 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn kill(pid: i32) -> i32 {
|
pub unsafe extern "C" fn kill(pid: i32) -> i32 {
|
||||||
for p in &mut proc {
|
for p in &mut proc {
|
||||||
p.lock.lock_unguarded();
|
let _guard = p.lock.lock();
|
||||||
|
|
||||||
if p.pid == pid {
|
if p.pid == pid {
|
||||||
p.killed = 1;
|
p.killed = 1;
|
||||||
@ -476,25 +471,21 @@ pub unsafe extern "C" fn kill(pid: i32) -> i32 {
|
|||||||
p.state = ProcState::Runnable;
|
p.state = ProcState::Runnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.lock.unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
p.lock.unlock();
|
|
||||||
}
|
}
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn setkilled(p: *mut Proc) {
|
pub unsafe extern "C" fn setkilled(p: *mut Proc) {
|
||||||
(*p).lock.lock_unguarded();
|
let _guard = (*p).lock.lock();
|
||||||
(*p).killed = 1;
|
(*p).killed = 1;
|
||||||
(*p).lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 {
|
pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 {
|
||||||
(*p).lock.lock_unguarded();
|
let _guard = (*p).lock.lock();
|
||||||
let k = (*p).killed;
|
let k = (*p).killed;
|
||||||
(*p).lock.unlock();
|
|
||||||
k
|
k
|
||||||
}
|
}
|
||||||
|
@ -34,22 +34,35 @@ impl Sleeplock {
|
|||||||
self.locked > 0 && self.pid == unsafe { (*myproc()).pid }
|
self.locked > 0 && self.pid == unsafe { (*myproc()).pid }
|
||||||
}
|
}
|
||||||
pub unsafe fn lock_unguarded(&self) {
|
pub unsafe fn lock_unguarded(&self) {
|
||||||
self.inner.lock_unguarded();
|
let _guard = self.inner.lock();
|
||||||
while self.locked > 0 {
|
while self.locked > 0 {
|
||||||
sleep(addr_of!(*self).cast_mut().cast(), addr_of!(self.inner).cast_mut().cast());
|
sleep(addr_of!(*self).cast_mut().cast(), addr_of!(self.inner).cast_mut().cast());
|
||||||
}
|
}
|
||||||
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
||||||
this.locked = 1;
|
this.locked = 1;
|
||||||
this.pid = (*myproc()).pid;
|
this.pid = (*myproc()).pid;
|
||||||
self.inner.unlock();
|
}
|
||||||
|
pub fn lock(&self) -> SleeplockGuard<'_> {
|
||||||
|
unsafe {
|
||||||
|
self.lock_unguarded();
|
||||||
|
}
|
||||||
|
SleeplockGuard { lock: self }
|
||||||
}
|
}
|
||||||
pub unsafe fn unlock(&self) {
|
pub unsafe fn unlock(&self) {
|
||||||
self.inner.lock_unguarded();
|
let _guard = self.inner.lock();
|
||||||
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
||||||
this.locked = 0;
|
this.locked = 0;
|
||||||
this.pid = 0;
|
this.pid = 0;
|
||||||
wakeup(addr_of!(*self).cast_mut().cast());
|
wakeup(addr_of!(*self).cast_mut().cast());
|
||||||
self.inner.unlock();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SleeplockGuard<'l> {
|
||||||
|
pub lock: &'l Sleeplock,
|
||||||
|
}
|
||||||
|
impl<'l> Drop for SleeplockGuard<'l> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.lock.unlock() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,12 @@ impl Spinlock {
|
|||||||
// The lock is now locked and we can write our CPU info.
|
// The lock is now locked and we can write our CPU info.
|
||||||
this.cpu = mycpu();
|
this.cpu = mycpu();
|
||||||
}
|
}
|
||||||
|
pub fn lock(&self) -> SpinlockGuard<'_> {
|
||||||
|
unsafe {
|
||||||
|
self.lock_unguarded();
|
||||||
|
}
|
||||||
|
SpinlockGuard { lock: self }
|
||||||
|
}
|
||||||
pub unsafe fn unlock(&self) {
|
pub unsafe fn unlock(&self) {
|
||||||
if !self.held_by_current_cpu() {
|
if !self.held_by_current_cpu() {
|
||||||
panic!("Attempt to release lock from different CPU");
|
panic!("Attempt to release lock from different CPU");
|
||||||
@ -66,6 +72,15 @@ impl Spinlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SpinlockGuard<'l> {
|
||||||
|
pub lock: &'l Spinlock,
|
||||||
|
}
|
||||||
|
impl<'l> Drop for SpinlockGuard<'l> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.lock.unlock() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn initlock(lock: *mut Spinlock, name: *mut c_char) {
|
pub unsafe extern "C" fn initlock(lock: *mut Spinlock, name: *mut c_char) {
|
||||||
*lock = Spinlock::new(name);
|
*lock = Spinlock::new(name);
|
||||||
|
@ -46,7 +46,7 @@ pub unsafe extern "C" fn sys_sleep() -> u64 {
|
|||||||
let mut n = 0i32;
|
let mut n = 0i32;
|
||||||
argint(0, addr_of_mut!(n));
|
argint(0, addr_of_mut!(n));
|
||||||
|
|
||||||
crate::trap::tickslock.lock_unguarded();
|
let _guard = crate::trap::tickslock.lock();
|
||||||
let ticks = crate::trap::ticks;
|
let ticks = crate::trap::ticks;
|
||||||
while crate::trap::ticks < ticks + n as u32 {
|
while crate::trap::ticks < ticks + n as u32 {
|
||||||
if killed(myproc()) > 0 {
|
if killed(myproc()) > 0 {
|
||||||
@ -58,7 +58,6 @@ pub unsafe extern "C" fn sys_sleep() -> u64 {
|
|||||||
addr_of_mut!(crate::trap::tickslock).cast(),
|
addr_of_mut!(crate::trap::tickslock).cast(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
crate::trap::tickslock.unlock();
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +71,7 @@ pub unsafe extern "C" fn sys_kill() -> u64 {
|
|||||||
/// Returns how many clock tick interrupts have occurred since start.
|
/// Returns how many clock tick interrupts have occurred since start.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sys_uptime() -> u64 {
|
pub unsafe extern "C" fn sys_uptime() -> u64 {
|
||||||
crate::trap::tickslock.lock_unguarded();
|
let _guard = crate::trap::tickslock.lock();
|
||||||
let ticks = crate::trap::ticks;
|
let ticks = crate::trap::ticks;
|
||||||
crate::trap::tickslock.unlock();
|
|
||||||
ticks as u64
|
ticks as u64
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,9 @@ pub unsafe extern "C" fn trapinithart() {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn clockintr() {
|
pub unsafe extern "C" fn clockintr() {
|
||||||
tickslock.lock_unguarded();
|
let _guard = tickslock.lock();
|
||||||
ticks += 1;
|
ticks += 1;
|
||||||
wakeup(addr_of_mut!(ticks).cast());
|
wakeup(addr_of_mut!(ticks).cast());
|
||||||
tickslock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if it's an external interrupt or software interrupt and handle it.
|
/// Check if it's an external interrupt or software interrupt and handle it.
|
||||||
|
@ -158,7 +158,7 @@ pub(crate) unsafe fn uartinit() {
|
|||||||
/// from interrupts, it's only suitable for use
|
/// from interrupts, it's only suitable for use
|
||||||
/// by write().
|
/// by write().
|
||||||
pub(crate) unsafe fn uartputc(c: u8) {
|
pub(crate) unsafe fn uartputc(c: u8) {
|
||||||
uart_tx_lock.lock_unguarded();
|
let _guard = uart_tx_lock.lock();
|
||||||
// let mut buf = uart_tx_buf.lock_unguarded();
|
// let mut buf = uart_tx_buf.lock_unguarded();
|
||||||
// let u = uart.lock_unguarded();
|
// let u = uart.lock_unguarded();
|
||||||
|
|
||||||
@ -180,7 +180,6 @@ pub(crate) unsafe fn uartputc(c: u8) {
|
|||||||
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
|
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
|
||||||
uart_tx_w += 1;
|
uart_tx_w += 1;
|
||||||
uartstart();
|
uartstart();
|
||||||
uart_tx_lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the UART is idle, and a character is waiting
|
/// If the UART is idle, and a character is waiting
|
||||||
@ -231,7 +230,6 @@ pub(crate) unsafe fn uartintr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send buffered characters.
|
// Send buffered characters.
|
||||||
uart_tx_lock.lock_unguarded();
|
let _guard = uart_tx_lock.lock();
|
||||||
uartstart();
|
uartstart();
|
||||||
uart_tx_lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user