diff --git a/kernel/bio.c b/kernel/bio.c index 60d91a6..d8ea209 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -106,8 +106,6 @@ bread(uint dev, uint blockno) void bwrite(struct buf *b) { - if(!holdingsleep(&b->lock)) - panic("bwrite"); virtio_disk_rw(b, 1); } @@ -116,9 +114,6 @@ bwrite(struct buf *b) void brelse(struct buf *b) { - if(!holdingsleep(&b->lock)) - panic("brelse"); - releasesleep(&b->lock); acquire(&bcache.lock); diff --git a/kernel/defs.h b/kernel/defs.h index d9605f3..61de271 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -125,8 +125,7 @@ void pop_off(void); // sleeplock.c void acquiresleep(struct sleeplock*); -void releasesleep(struct sleeplock*); -int holdingsleep(struct sleeplock*); +void releasesleep(struct sleeplock *); void initsleeplock(struct sleeplock*, char*); // string.c diff --git a/kernel/fs.c b/kernel/fs.c index c81cb06..f9c0872 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -317,10 +317,11 @@ ilock(struct inode *ip) } // Unlock the given inode. +// Caller should hold ip->lock void iunlock(struct inode *ip) { - if(ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1) + if (ip == 0 || ip->ref < 1) panic("iunlock"); releasesleep(&ip->lock); diff --git a/kernel/ramdisk.c b/kernel/ramdisk.c index 8b215ee..402a747 100644 --- a/kernel/ramdisk.c +++ b/kernel/ramdisk.c @@ -16,11 +16,10 @@ void ramdiskinit(void); // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. // Else if B_VALID is not set, read buf from disk, set B_VALID. +// Caller should hold b->lock void ramdiskrw(struct buf *b) { - if(!holdingsleep(&b->lock)) - panic("ramdiskrw: buf not locked"); if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) panic("ramdiskrw: nothing to do"); diff --git a/kernel/rustkernel/src/proc.rs b/kernel/rustkernel/src/proc.rs index 7f4fc98..cca0d33 100644 --- a/kernel/rustkernel/src/proc.rs +++ b/kernel/rustkernel/src/proc.rs @@ -391,6 +391,21 @@ pub unsafe fn sleep_mutex(chan: *mut c_void, mutex: &mut SpinMutexGuard) { core::mem::forget(guard); } +/// Sleep until `wakeup(chan)` is called somewhere else. +pub unsafe fn sleep(chan: *mut c_void) { + let p = myproc(); + let _guard = (*p).lock.lock(); + + // Go to sleep. + (*p).chan = chan; + (*p).state = ProcState::Sleeping; + + sched(); + + // Tidy up. + (*p).chan = null_mut(); +} + /// Kill the process with the given pid. /// The victim won't exit until it tries to return /// to user space (see usertrap() in trap.c). diff --git a/kernel/rustkernel/src/sync/sleeplock.rs b/kernel/rustkernel/src/sync/sleeplock.rs index e1bd985..9d0401e 100644 --- a/kernel/rustkernel/src/sync/sleeplock.rs +++ b/kernel/rustkernel/src/sync/sleeplock.rs @@ -1,53 +1,27 @@ -use crate::{ - proc::{myproc, sleep_lock, wakeup}, - sync::spinlock::Spinlock, -}; +use crate::proc::{wakeup, sleep}; use core::{ ffi::c_char, - ptr::{addr_of, null_mut}, + ptr::addr_of, + sync::atomic::{AtomicBool, Ordering}, }; #[repr(C)] +#[derive(Default)] pub struct Sleeplock { - pub locked: u32, - pub inner: Spinlock, - pub name: *mut c_char, - pub pid: i32, + pub locked: AtomicBool, } impl Sleeplock { - pub const unsafe fn uninitialized() -> Sleeplock { + pub const fn new() -> Sleeplock { Sleeplock { - locked: 0, - inner: Spinlock::new(), - name: null_mut(), - pid: 0, + locked: AtomicBool::new(false), } } - /// Initializes a `Sleeplock`. - pub const fn new(name: *mut c_char) -> Sleeplock { - Sleeplock { - locked: 0, - inner: Spinlock::new(), - 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 } - } #[allow(clippy::while_immutable_condition)] pub unsafe fn lock_unguarded(&self) { - let _guard = self.inner.lock(); - while self.locked > 0 { - sleep_lock( - addr_of!(*self).cast_mut().cast(), - addr_of!(self.inner).cast_mut().cast(), - ); + while self.locked.swap(true, Ordering::Acquire) { + // Put the process to sleep until it gets released. + sleep(addr_of!(*self).cast_mut().cast()); } - let this: &mut Self = &mut *addr_of!(*self).cast_mut(); - this.locked = 1; - this.pid = (*myproc()).pid; } pub fn lock(&self) -> SleeplockGuard<'_> { unsafe { @@ -56,10 +30,7 @@ impl Sleeplock { SleeplockGuard { lock: self } } pub unsafe fn unlock(&self) { - let _guard = self.inner.lock(); - let this: &mut Self = &mut *addr_of!(*self).cast_mut(); - this.locked = 0; - this.pid = 0; + self.locked.store(false, Ordering::Release); wakeup(addr_of!(*self).cast_mut().cast()); } } @@ -74,8 +45,8 @@ impl<'l> Drop for SleeplockGuard<'l> { } #[no_mangle] -pub unsafe extern "C" fn initsleeplock(lock: *mut Sleeplock, name: *mut c_char) { - (*lock) = Sleeplock::new(name); +pub unsafe extern "C" fn initsleeplock(lock: *mut Sleeplock, _name: *mut c_char) { + (*lock) = Sleeplock::new(); } #[no_mangle] @@ -87,12 +58,3 @@ pub unsafe extern "C" fn acquiresleep(lock: *mut Sleeplock) { pub unsafe extern "C" fn releasesleep(lock: *mut Sleeplock) { (*lock).unlock(); } - -#[no_mangle] -pub unsafe extern "C" fn holdingsleep(lock: *mut Sleeplock) -> i32 { - if (*lock).held_by_current_proc() { - 1 - } else { - 0 - } -} diff --git a/kernel/sleeplock.h b/kernel/sleeplock.h index 951be20..69fd4fa 100644 --- a/kernel/sleeplock.h +++ b/kernel/sleeplock.h @@ -4,11 +4,7 @@ // Long-term locks for processes struct sleeplock { - uint locked; // Is the lock held? - struct spinlock lk; // spinlock protecting this sleep lock - - // For debugging: - char *name; // Name of lock. - int pid; // Process holding lock + // Is the lock held? + uint8 locked; };