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