implement guards for spinlock and sleeplock
This commit is contained in:
parent
f468ba9e48
commit
38e44e020b
@ -73,10 +73,9 @@ pub unsafe extern "C" fn kfree(pa: *mut u8) {
|
||||
|
||||
let run: *mut Run = pa.cast();
|
||||
|
||||
kmem.lock.lock_unguarded();
|
||||
let _guard = kmem.lock.lock();
|
||||
(*run).next = kmem.freelist;
|
||||
kmem.freelist = run;
|
||||
kmem.lock.unlock();
|
||||
}
|
||||
|
||||
/// Allocate one 4096-byte page of physical memory.
|
||||
@ -85,15 +84,13 @@ pub unsafe extern "C" fn kfree(pa: *mut u8) {
|
||||
/// Returns 0 if the memory cannot be allocated.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kalloc() -> *mut u8 {
|
||||
kmem.lock.lock_unguarded();
|
||||
let _guard = kmem.lock.lock();
|
||||
|
||||
let run = kmem.freelist;
|
||||
if !run.is_null() {
|
||||
kmem.freelist = (*run).next;
|
||||
}
|
||||
|
||||
kmem.lock.unlock();
|
||||
|
||||
if !run.is_null() {
|
||||
memset(run.cast(), 0, PGSIZE as u32);
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ pub struct PrintLock {
|
||||
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => {{
|
||||
unsafe { $crate::printf::PRINT_LOCK.lock_unguarded() };
|
||||
// Still unsafe because static mut.
|
||||
let _guard = unsafe { $crate::printf::PRINT_LOCK.lock() };
|
||||
|
||||
// Allocate a page of memory as the buffer and release it when we're done.
|
||||
let buf = unsafe { $crate::kalloc::kalloc() as *mut [u8; 4096] };
|
||||
@ -29,7 +30,6 @@ macro_rules! print {
|
||||
}
|
||||
|
||||
unsafe { $crate::kalloc::kfree(buf.cast()) };
|
||||
unsafe { $crate::printf::PRINT_LOCK.unlock() };
|
||||
}};
|
||||
}
|
||||
pub(crate) use print;
|
||||
@ -58,8 +58,7 @@ pub unsafe extern "C" fn printstr(s: *const c_char) {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn printfinit() {
|
||||
PRINT_LOCK = Spinlock::new(
|
||||
CStr::from_bytes_with_nul(b"pr\0")
|
||||
.unwrap()
|
||||
CStr::from_bytes_with_nul_unchecked(b"pr\0")
|
||||
.as_ptr()
|
||||
.cast_mut(),
|
||||
);
|
||||
|
@ -247,11 +247,9 @@ pub unsafe extern "C" fn myproc() -> *mut Proc {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn allocpid() -> i32 {
|
||||
let lock = addr_of_mut!(pid_lock);
|
||||
(*lock).lock_unguarded();
|
||||
let _guard = pid_lock.lock();
|
||||
let pid = nextpid;
|
||||
nextpid += 1;
|
||||
(*lock).unlock();
|
||||
pid
|
||||
}
|
||||
|
||||
@ -375,10 +373,9 @@ pub unsafe extern "C" fn growproc(n: i32) -> i32 {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn r#yield() {
|
||||
let p = myproc();
|
||||
(*p).lock.lock_unguarded();
|
||||
let _guard = (*p).lock.lock();
|
||||
(*p).state = ProcState::Runnable;
|
||||
sched();
|
||||
(*p).lock.unlock();
|
||||
}
|
||||
|
||||
/// Switch to scheduler. Must hold only p->lock
|
||||
@ -421,7 +418,7 @@ pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) {
|
||||
// (wakeup locks p->lock),
|
||||
// so it's okay to release lk.
|
||||
|
||||
(*p).lock.lock_unguarded();
|
||||
let _guard = (*p).lock.lock();
|
||||
(*lock).unlock();
|
||||
|
||||
// Go to sleep.
|
||||
@ -434,7 +431,6 @@ pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) {
|
||||
(*p).chan = null_mut();
|
||||
|
||||
// Reacquire original lock.
|
||||
(*p).lock.unlock();
|
||||
(*lock).lock_unguarded();
|
||||
}
|
||||
|
||||
@ -442,7 +438,7 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
||||
let p = myproc();
|
||||
let mutex = mutex.mutex;
|
||||
|
||||
(*p).lock.lock_unguarded();
|
||||
let _guard = (*p).lock.lock();
|
||||
mutex.unlock();
|
||||
|
||||
// Go to sleep.
|
||||
@ -455,7 +451,6 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
||||
(*p).chan = null_mut();
|
||||
|
||||
// Reacquire original lock.
|
||||
(*p).lock.unlock();
|
||||
let guard = mutex.lock();
|
||||
core::mem::forget(guard);
|
||||
}
|
||||
@ -466,7 +461,7 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kill(pid: i32) -> i32 {
|
||||
for p in &mut proc {
|
||||
p.lock.lock_unguarded();
|
||||
let _guard = p.lock.lock();
|
||||
|
||||
if p.pid == pid {
|
||||
p.killed = 1;
|
||||
@ -476,25 +471,21 @@ pub unsafe extern "C" fn kill(pid: i32) -> i32 {
|
||||
p.state = ProcState::Runnable;
|
||||
}
|
||||
|
||||
p.lock.unlock();
|
||||
return 0;
|
||||
}
|
||||
p.lock.unlock();
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn setkilled(p: *mut Proc) {
|
||||
(*p).lock.lock_unguarded();
|
||||
let _guard = (*p).lock.lock();
|
||||
(*p).killed = 1;
|
||||
(*p).lock.unlock();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 {
|
||||
(*p).lock.lock_unguarded();
|
||||
let _guard = (*p).lock.lock();
|
||||
let k = (*p).killed;
|
||||
(*p).lock.unlock();
|
||||
k
|
||||
}
|
||||
|
@ -34,22 +34,35 @@ impl Sleeplock {
|
||||
self.locked > 0 && self.pid == unsafe { (*myproc()).pid }
|
||||
}
|
||||
pub unsafe fn lock_unguarded(&self) {
|
||||
self.inner.lock_unguarded();
|
||||
let _guard = self.inner.lock();
|
||||
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 fn lock(&self) -> SleeplockGuard<'_> {
|
||||
unsafe {
|
||||
self.lock_unguarded();
|
||||
}
|
||||
SleeplockGuard { lock: self }
|
||||
}
|
||||
pub unsafe fn unlock(&self) {
|
||||
self.inner.lock_unguarded();
|
||||
let _guard = self.inner.lock();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SleeplockGuard<'l> {
|
||||
pub lock: &'l Sleeplock,
|
||||
}
|
||||
impl<'l> Drop for SleeplockGuard<'l> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.lock.unlock() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,12 @@ impl Spinlock {
|
||||
// The lock is now locked and we can write our CPU info.
|
||||
this.cpu = mycpu();
|
||||
}
|
||||
pub fn lock(&self) -> SpinlockGuard<'_> {
|
||||
unsafe {
|
||||
self.lock_unguarded();
|
||||
}
|
||||
SpinlockGuard { lock: self }
|
||||
}
|
||||
pub unsafe fn unlock(&self) {
|
||||
if !self.held_by_current_cpu() {
|
||||
panic!("Attempt to release lock from different CPU");
|
||||
@ -66,6 +72,15 @@ impl Spinlock {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpinlockGuard<'l> {
|
||||
pub lock: &'l Spinlock,
|
||||
}
|
||||
impl<'l> Drop for SpinlockGuard<'l> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.lock.unlock() }
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn initlock(lock: *mut Spinlock, name: *mut c_char) {
|
||||
*lock = Spinlock::new(name);
|
||||
|
@ -46,7 +46,7 @@ pub unsafe extern "C" fn sys_sleep() -> u64 {
|
||||
let mut n = 0i32;
|
||||
argint(0, addr_of_mut!(n));
|
||||
|
||||
crate::trap::tickslock.lock_unguarded();
|
||||
let _guard = crate::trap::tickslock.lock();
|
||||
let ticks = crate::trap::ticks;
|
||||
while crate::trap::ticks < ticks + n as u32 {
|
||||
if killed(myproc()) > 0 {
|
||||
@ -58,7 +58,6 @@ pub unsafe extern "C" fn sys_sleep() -> u64 {
|
||||
addr_of_mut!(crate::trap::tickslock).cast(),
|
||||
)
|
||||
}
|
||||
crate::trap::tickslock.unlock();
|
||||
0
|
||||
}
|
||||
|
||||
@ -72,8 +71,7 @@ pub unsafe extern "C" fn sys_kill() -> u64 {
|
||||
/// Returns how many clock tick interrupts have occurred since start.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sys_uptime() -> u64 {
|
||||
crate::trap::tickslock.lock_unguarded();
|
||||
let _guard = crate::trap::tickslock.lock();
|
||||
let ticks = crate::trap::ticks;
|
||||
crate::trap::tickslock.unlock();
|
||||
ticks as u64
|
||||
}
|
||||
|
@ -45,10 +45,9 @@ pub unsafe extern "C" fn trapinithart() {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn clockintr() {
|
||||
tickslock.lock_unguarded();
|
||||
let _guard = tickslock.lock();
|
||||
ticks += 1;
|
||||
wakeup(addr_of_mut!(ticks).cast());
|
||||
tickslock.unlock();
|
||||
}
|
||||
|
||||
/// Check if it's an external interrupt or software interrupt and handle it.
|
||||
|
@ -158,7 +158,7 @@ pub(crate) unsafe fn uartinit() {
|
||||
/// from interrupts, it's only suitable for use
|
||||
/// by write().
|
||||
pub(crate) unsafe fn uartputc(c: u8) {
|
||||
uart_tx_lock.lock_unguarded();
|
||||
let _guard = uart_tx_lock.lock();
|
||||
// let mut buf = uart_tx_buf.lock_unguarded();
|
||||
// let u = uart.lock_unguarded();
|
||||
|
||||
@ -180,7 +180,6 @@ pub(crate) unsafe fn uartputc(c: u8) {
|
||||
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
|
||||
uart_tx_w += 1;
|
||||
uartstart();
|
||||
uart_tx_lock.unlock();
|
||||
}
|
||||
|
||||
/// If the UART is idle, and a character is waiting
|
||||
@ -231,7 +230,6 @@ pub(crate) unsafe fn uartintr() {
|
||||
}
|
||||
|
||||
// Send buffered characters.
|
||||
uart_tx_lock.lock_unguarded();
|
||||
let _guard = uart_tx_lock.lock();
|
||||
uartstart();
|
||||
uart_tx_lock.unlock();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user