restructure sleeplock.rs
This commit is contained in:
parent
548be7daea
commit
f468ba9e48
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user