restructure sleeplock.rs

This commit is contained in:
Garen Tyler 2023-10-21 21:56:23 -06:00
parent 548be7daea
commit f468ba9e48
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
2 changed files with 56 additions and 29 deletions

View File

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

View File

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