From f468ba9e48f33bfa40af9ec8d65a1934711c38d7 Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Sat, 21 Oct 2023 21:56:23 -0600 Subject: [PATCH] restructure sleeplock.rs --- kernel/rustkernel/src/sync/sleeplock.rs | 67 +++++++++++++++++-------- kernel/rustkernel/src/sync/spinlock.rs | 18 ++++--- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/kernel/rustkernel/src/sync/sleeplock.rs b/kernel/rustkernel/src/sync/sleeplock.rs index 0045aad..fedbf85 100644 --- a/kernel/rustkernel/src/sync/sleeplock.rs +++ b/kernel/rustkernel/src/sync/sleeplock.rs @@ -2,7 +2,7 @@ use crate::{ proc::{myproc, sleep, wakeup}, sync::spinlock::{self, Spinlock}, }; -use core::{ffi::c_char, ptr::addr_of_mut}; +use core::{ffi::c_char, ptr::{addr_of, null_mut}}; #[repr(C)] pub struct Sleeplock { @@ -11,41 +11,66 @@ pub struct Sleeplock { pub name: *mut c_char, pub pid: i32, } +impl Sleeplock { + pub const unsafe fn uninitialized() -> Sleeplock { + Sleeplock { + locked: 0, + inner: Spinlock::uninitialized(), + name: null_mut(), + pid: 0, + } + } + /// Initializes a `Sleeplock`. + pub const fn new(name: *mut c_char) -> Sleeplock { + Sleeplock { + locked: 0, + inner: Spinlock::new(name), + name, + pid: 0, + } + } + /// Check whether this proc is holding the lock. + pub fn held_by_current_proc(&self) -> bool { + self.locked > 0 && self.pid == unsafe { (*myproc()).pid } + } + pub unsafe fn lock_unguarded(&self) { + self.inner.lock_unguarded(); + 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 unsafe fn unlock(&self) { + self.inner.lock_unguarded(); + 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(); + } +} #[no_mangle] pub unsafe extern "C" fn initsleeplock(lock: *mut Sleeplock, name: *mut c_char) { - spinlock::initlock(addr_of_mut!((*lock).inner), name); - (*lock).name = name; - (*lock).locked = 0; - (*lock).pid = 0; + (*lock) = Sleeplock::new(name); } #[no_mangle] pub unsafe extern "C" fn acquiresleep(lock: *mut Sleeplock) { - (*lock).inner.lock_unguarded(); - while (*lock).locked > 0 { - sleep(lock.cast(), addr_of_mut!((*lock).inner)); - } - (*lock).locked = 1; - (*lock).pid = (*myproc()).pid; - (*lock).inner.unlock() + (*lock).lock_unguarded(); } #[no_mangle] pub unsafe extern "C" fn releasesleep(lock: *mut Sleeplock) { - (*lock).inner.lock_unguarded(); - (*lock).locked = 0; - (*lock).pid = 0; - wakeup(lock.cast()); - (*lock).inner.unlock(); + (*lock).unlock(); } #[no_mangle] pub unsafe extern "C" fn holdingsleep(lock: *mut Sleeplock) -> i32 { - (*lock).inner.lock_unguarded(); - let holding = ((*lock).locked > 0) && ((*lock).pid == (*myproc()).pid); - (*lock).inner.unlock(); - if holding { + if (*lock).held_by_current_proc() { 1 } else { 0 diff --git a/kernel/rustkernel/src/sync/spinlock.rs b/kernel/rustkernel/src/sync/spinlock.rs index 9ff3663..1a78e9e 100644 --- a/kernel/rustkernel/src/sync/spinlock.rs +++ b/kernel/rustkernel/src/sync/spinlock.rs @@ -4,7 +4,7 @@ use crate::{ }; use core::{ ffi::c_char, - ptr::null_mut, + ptr::{null_mut, addr_of}, sync::atomic::{AtomicBool, Ordering}, }; @@ -36,29 +36,31 @@ impl Spinlock { pub fn held_by_current_cpu(&self) -> bool { self.cpu == unsafe { mycpu() } && self.locked.load(Ordering::Relaxed) } - pub unsafe fn lock_unguarded(&mut self) { + pub unsafe fn lock_unguarded(&self) { push_off(); if self.held_by_current_cpu() { panic!("Attempt to acquire twice by the same CPU"); } - while self.locked.swap(true, Ordering::Acquire) { + let this: &mut Self = &mut *addr_of!(*self).cast_mut(); + + while this.locked.swap(true, Ordering::Acquire) { core::hint::spin_loop(); } // The lock is now locked and we can write our CPU info. - - self.cpu = mycpu(); + this.cpu = mycpu(); } - pub unsafe fn unlock(&mut self) { + pub unsafe fn unlock(&self) { if !self.held_by_current_cpu() { panic!("Attempt to release lock from different CPU"); } - self.cpu = null_mut(); + let this: &mut Self = &mut *addr_of!(*self).cast_mut(); - self.locked.store(false, Ordering::Release); + this.cpu = null_mut(); + this.locked.store(false, Ordering::Release); pop_off(); }