Refactor sleeplock to remove raw pointers
This commit is contained in:
parent
36d7724fb8
commit
9f23b68c00
@ -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);
|
||||
|
@ -126,7 +126,6 @@ void pop_off(void);
|
||||
// sleeplock.c
|
||||
void acquiresleep(struct sleeplock*);
|
||||
void releasesleep(struct sleeplock *);
|
||||
int holdingsleep(struct sleeplock*);
|
||||
void initsleeplock(struct sleeplock*, char*);
|
||||
|
||||
// string.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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -391,6 +391,21 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
||||
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).
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user