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}, proc::{myproc, sleep, wakeup},
sync::spinlock::{self, Spinlock}, 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)] #[repr(C)]
pub struct Sleeplock { pub struct Sleeplock {
@ -11,41 +11,66 @@ pub struct Sleeplock {
pub name: *mut c_char, pub name: *mut c_char,
pub pid: i32, 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] #[no_mangle]
pub unsafe extern "C" fn initsleeplock(lock: *mut Sleeplock, name: *mut c_char) { pub unsafe extern "C" fn initsleeplock(lock: *mut Sleeplock, name: *mut c_char) {
spinlock::initlock(addr_of_mut!((*lock).inner), name); (*lock) = Sleeplock::new(name);
(*lock).name = name;
(*lock).locked = 0;
(*lock).pid = 0;
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn acquiresleep(lock: *mut Sleeplock) { pub unsafe extern "C" fn acquiresleep(lock: *mut Sleeplock) {
(*lock).inner.lock_unguarded(); (*lock).lock_unguarded();
while (*lock).locked > 0 {
sleep(lock.cast(), addr_of_mut!((*lock).inner));
}
(*lock).locked = 1;
(*lock).pid = (*myproc()).pid;
(*lock).inner.unlock()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn releasesleep(lock: *mut Sleeplock) { pub unsafe extern "C" fn releasesleep(lock: *mut Sleeplock) {
(*lock).inner.lock_unguarded(); (*lock).unlock();
(*lock).locked = 0;
(*lock).pid = 0;
wakeup(lock.cast());
(*lock).inner.unlock();
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn holdingsleep(lock: *mut Sleeplock) -> i32 { pub unsafe extern "C" fn holdingsleep(lock: *mut Sleeplock) -> i32 {
(*lock).inner.lock_unguarded(); if (*lock).held_by_current_proc() {
let holding = ((*lock).locked > 0) && ((*lock).pid == (*myproc()).pid);
(*lock).inner.unlock();
if holding {
1 1
} else { } else {
0 0

View File

@ -4,7 +4,7 @@ use crate::{
}; };
use core::{ use core::{
ffi::c_char, ffi::c_char,
ptr::null_mut, ptr::{null_mut, addr_of},
sync::atomic::{AtomicBool, Ordering}, sync::atomic::{AtomicBool, Ordering},
}; };
@ -36,29 +36,31 @@ impl Spinlock {
pub fn held_by_current_cpu(&self) -> bool { pub fn held_by_current_cpu(&self) -> bool {
self.cpu == unsafe { mycpu() } && self.locked.load(Ordering::Relaxed) self.cpu == unsafe { mycpu() } && self.locked.load(Ordering::Relaxed)
} }
pub unsafe fn lock_unguarded(&mut self) { pub unsafe fn lock_unguarded(&self) {
push_off(); push_off();
if self.held_by_current_cpu() { if self.held_by_current_cpu() {
panic!("Attempt to acquire twice by the same 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(); core::hint::spin_loop();
} }
// 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();
self.cpu = mycpu();
} }
pub unsafe fn unlock(&mut 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");
} }
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(); pop_off();
} }