diff --git a/kernel/rustkernel/src/kalloc.rs b/kernel/rustkernel/src/kalloc.rs index b1ddb92..79f5dff 100644 --- a/kernel/rustkernel/src/kalloc.rs +++ b/kernel/rustkernel/src/kalloc.rs @@ -73,10 +73,9 @@ pub unsafe extern "C" fn kfree(pa: *mut u8) { let run: *mut Run = pa.cast(); - kmem.lock.lock_unguarded(); + let _guard = kmem.lock.lock(); (*run).next = kmem.freelist; kmem.freelist = run; - kmem.lock.unlock(); } /// 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. #[no_mangle] pub unsafe extern "C" fn kalloc() -> *mut u8 { - kmem.lock.lock_unguarded(); + let _guard = kmem.lock.lock(); let run = kmem.freelist; if !run.is_null() { kmem.freelist = (*run).next; } - kmem.lock.unlock(); - if !run.is_null() { memset(run.cast(), 0, PGSIZE as u32); } diff --git a/kernel/rustkernel/src/printf.rs b/kernel/rustkernel/src/printf.rs index da091be..f62ac97 100644 --- a/kernel/rustkernel/src/printf.rs +++ b/kernel/rustkernel/src/printf.rs @@ -14,7 +14,8 @@ pub struct PrintLock { macro_rules! print { ($($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. 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::printf::PRINT_LOCK.unlock() }; }}; } pub(crate) use print; @@ -58,8 +58,7 @@ pub unsafe extern "C" fn printstr(s: *const c_char) { #[no_mangle] pub unsafe extern "C" fn printfinit() { PRINT_LOCK = Spinlock::new( - CStr::from_bytes_with_nul(b"pr\0") - .unwrap() + CStr::from_bytes_with_nul_unchecked(b"pr\0") .as_ptr() .cast_mut(), ); diff --git a/kernel/rustkernel/src/proc.rs b/kernel/rustkernel/src/proc.rs index 9108012..f9f54f4 100644 --- a/kernel/rustkernel/src/proc.rs +++ b/kernel/rustkernel/src/proc.rs @@ -247,11 +247,9 @@ pub unsafe extern "C" fn myproc() -> *mut Proc { #[no_mangle] pub unsafe extern "C" fn allocpid() -> i32 { - let lock = addr_of_mut!(pid_lock); - (*lock).lock_unguarded(); + let _guard = pid_lock.lock(); let pid = nextpid; nextpid += 1; - (*lock).unlock(); pid } @@ -375,10 +373,9 @@ pub unsafe extern "C" fn growproc(n: i32) -> i32 { #[no_mangle] pub unsafe extern "C" fn r#yield() { let p = myproc(); - (*p).lock.lock_unguarded(); + let _guard = (*p).lock.lock(); (*p).state = ProcState::Runnable; sched(); - (*p).lock.unlock(); } /// 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), // so it's okay to release lk. - (*p).lock.lock_unguarded(); + let _guard = (*p).lock.lock(); (*lock).unlock(); // Go to sleep. @@ -434,7 +431,6 @@ pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) { (*p).chan = null_mut(); // Reacquire original lock. - (*p).lock.unlock(); (*lock).lock_unguarded(); } @@ -442,7 +438,7 @@ pub unsafe fn sleep_mutex(chan: *mut c_void, mutex: &mut SpinMutexGuard) { let p = myproc(); let mutex = mutex.mutex; - (*p).lock.lock_unguarded(); + let _guard = (*p).lock.lock(); mutex.unlock(); // Go to sleep. @@ -455,7 +451,6 @@ pub unsafe fn sleep_mutex(chan: *mut c_void, mutex: &mut SpinMutexGuard) { (*p).chan = null_mut(); // Reacquire original lock. - (*p).lock.unlock(); let guard = mutex.lock(); core::mem::forget(guard); } @@ -466,7 +461,7 @@ pub unsafe fn sleep_mutex(chan: *mut c_void, mutex: &mut SpinMutexGuard) { #[no_mangle] pub unsafe extern "C" fn kill(pid: i32) -> i32 { for p in &mut proc { - p.lock.lock_unguarded(); + let _guard = p.lock.lock(); if p.pid == pid { p.killed = 1; @@ -476,25 +471,21 @@ pub unsafe extern "C" fn kill(pid: i32) -> i32 { p.state = ProcState::Runnable; } - p.lock.unlock(); return 0; } - p.lock.unlock(); } -1 } #[no_mangle] pub unsafe extern "C" fn setkilled(p: *mut Proc) { - (*p).lock.lock_unguarded(); + let _guard = (*p).lock.lock(); (*p).killed = 1; - (*p).lock.unlock(); } #[no_mangle] pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 { - (*p).lock.lock_unguarded(); + let _guard = (*p).lock.lock(); let k = (*p).killed; - (*p).lock.unlock(); k } diff --git a/kernel/rustkernel/src/sync/sleeplock.rs b/kernel/rustkernel/src/sync/sleeplock.rs index fedbf85..eb8a176 100644 --- a/kernel/rustkernel/src/sync/sleeplock.rs +++ b/kernel/rustkernel/src/sync/sleeplock.rs @@ -34,22 +34,35 @@ impl Sleeplock { self.locked > 0 && self.pid == unsafe { (*myproc()).pid } } pub unsafe fn lock_unguarded(&self) { - self.inner.lock_unguarded(); + let _guard = self.inner.lock(); while self.locked > 0 { sleep(addr_of!(*self).cast_mut().cast(), addr_of!(self.inner).cast_mut().cast()); } let this: &mut Self = &mut *addr_of!(*self).cast_mut(); this.locked = 1; this.pid = (*myproc()).pid; - self.inner.unlock(); + } + pub fn lock(&self) -> SleeplockGuard<'_> { + unsafe { + self.lock_unguarded(); + } + SleeplockGuard { lock: 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(); this.locked = 0; this.pid = 0; 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() } } } diff --git a/kernel/rustkernel/src/sync/spinlock.rs b/kernel/rustkernel/src/sync/spinlock.rs index 1a78e9e..a13c964 100644 --- a/kernel/rustkernel/src/sync/spinlock.rs +++ b/kernel/rustkernel/src/sync/spinlock.rs @@ -52,6 +52,12 @@ impl Spinlock { // The lock is now locked and we can write our CPU info. this.cpu = mycpu(); } + pub fn lock(&self) -> SpinlockGuard<'_> { + unsafe { + self.lock_unguarded(); + } + SpinlockGuard { lock: self } + } pub unsafe fn unlock(&self) { if !self.held_by_current_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] pub unsafe extern "C" fn initlock(lock: *mut Spinlock, name: *mut c_char) { *lock = Spinlock::new(name); diff --git a/kernel/rustkernel/src/sysproc.rs b/kernel/rustkernel/src/sysproc.rs index bc73977..964d0d0 100644 --- a/kernel/rustkernel/src/sysproc.rs +++ b/kernel/rustkernel/src/sysproc.rs @@ -46,7 +46,7 @@ pub unsafe extern "C" fn sys_sleep() -> u64 { let mut n = 0i32; argint(0, addr_of_mut!(n)); - crate::trap::tickslock.lock_unguarded(); + let _guard = crate::trap::tickslock.lock(); let ticks = crate::trap::ticks; while crate::trap::ticks < ticks + n as u32 { if killed(myproc()) > 0 { @@ -58,7 +58,6 @@ pub unsafe extern "C" fn sys_sleep() -> u64 { addr_of_mut!(crate::trap::tickslock).cast(), ) } - crate::trap::tickslock.unlock(); 0 } @@ -72,8 +71,7 @@ pub unsafe extern "C" fn sys_kill() -> u64 { /// Returns how many clock tick interrupts have occurred since start. #[no_mangle] pub unsafe extern "C" fn sys_uptime() -> u64 { - crate::trap::tickslock.lock_unguarded(); + let _guard = crate::trap::tickslock.lock(); let ticks = crate::trap::ticks; - crate::trap::tickslock.unlock(); ticks as u64 } diff --git a/kernel/rustkernel/src/trap.rs b/kernel/rustkernel/src/trap.rs index 4effc27..b6d83bd 100644 --- a/kernel/rustkernel/src/trap.rs +++ b/kernel/rustkernel/src/trap.rs @@ -45,10 +45,9 @@ pub unsafe extern "C" fn trapinithart() { #[no_mangle] pub unsafe extern "C" fn clockintr() { - tickslock.lock_unguarded(); + let _guard = tickslock.lock(); ticks += 1; wakeup(addr_of_mut!(ticks).cast()); - tickslock.unlock(); } /// Check if it's an external interrupt or software interrupt and handle it. diff --git a/kernel/rustkernel/src/uart.rs b/kernel/rustkernel/src/uart.rs index 9e7bf30..a042180 100644 --- a/kernel/rustkernel/src/uart.rs +++ b/kernel/rustkernel/src/uart.rs @@ -158,7 +158,7 @@ pub(crate) unsafe fn uartinit() { /// from interrupts, it's only suitable for use /// by write(). 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 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_w += 1; uartstart(); - uart_tx_lock.unlock(); } /// If the UART is idle, and a character is waiting @@ -231,7 +230,6 @@ pub(crate) unsafe fn uartintr() { } // Send buffered characters. - uart_tx_lock.lock_unguarded(); + let _guard = uart_tx_lock.lock(); uartstart(); - uart_tx_lock.unlock(); }