implement guards for spinlock and sleeplock

This commit is contained in:
Garen Tyler 2023-10-21 22:13:46 -06:00
parent f468ba9e48
commit 38e44e020b
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
8 changed files with 49 additions and 39 deletions

View File

@ -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);
} }

View File

@ -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(),
); );

View File

@ -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
} }

View File

@ -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() }
} }
} }

View File

@ -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);

View File

@ -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
} }

View File

@ -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.

View File

@ -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();
} }