diff --git a/os/Makefile b/os/Makefile index 0c1fb7c7..3e5caad7 100644 --- a/os/Makefile +++ b/os/Makefile @@ -76,7 +76,7 @@ disasm: kernel disasm-vim: kernel @$(OBJDUMP) $(DISASM) $(KERNEL_ELF) > $(DISASM_TMP) - @vim $(DISASM_TMP) + @nvim $(DISASM_TMP) @rm $(DISASM_TMP) run: run-inner diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs index 8d509a4b..38de3442 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -44,12 +44,15 @@ pub fn device_init() { } pub fn irq_handler() { + //crate::println!("->irq_handler"); let mut plic = unsafe { PLIC::new(VIRT_PLIC) }; let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor); + //crate::println!("intr_src={}", intr_src_id); match intr_src_id { 1 => BLOCK_DEVICE.handle_irq(), 10 => UART.handle_irq(), _ => panic!("unsupported IRQ {}", intr_src_id), } plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id); + //crate::println!("irq_handler->"); } diff --git a/os/src/console.rs b/os/src/console.rs index 31614c64..9f27b4bb 100644 --- a/os/src/console.rs +++ b/os/src/console.rs @@ -1,12 +1,14 @@ use crate::drivers::chardev::{CharDevice, UART}; use core::fmt::{self, Write}; +use crate::sbi::console_putchar; struct Stdout; impl Write for Stdout { fn write_str(&mut self, s: &str) -> fmt::Result { for c in s.chars() { - UART.write(c as u8); + //UART.write(c as u8); + console_putchar(c as usize); } Ok(()) } diff --git a/os/src/drivers/block/sdcard.rs b/os/src/drivers/block/sdcard.rs index 32d94431..9b12ffd2 100644 --- a/os/src/drivers/block/sdcard.rs +++ b/os/src/drivers/block/sdcard.rs @@ -3,7 +3,7 @@ #![allow(unused)] use super::BlockDevice; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use core::convert::TryInto; use k210_hal::prelude::*; use k210_pac::{Peripherals, SPI0}; @@ -715,8 +715,8 @@ fn io_init() { } lazy_static! { - static ref PERIPHERALS: UPSafeCell = - unsafe { UPSafeCell::new(Peripherals::take().unwrap()) }; + static ref PERIPHERALS: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(Peripherals::take().unwrap()) }; } fn init_sdcard() -> SDCard> { @@ -740,11 +740,11 @@ fn init_sdcard() -> SDCard> { sd } -pub struct SDCardWrapper(UPSafeCell>>); +pub struct SDCardWrapper(UPIntrFreeCell>>); impl SDCardWrapper { pub fn new() -> Self { - unsafe { Self(UPSafeCell::new(init_sdcard())) } + unsafe { Self(UPIntrFreeCell::new(init_sdcard())) } } } diff --git a/os/src/drivers/block/virtio_blk.rs b/os/src/drivers/block/virtio_blk.rs index 67eb0c33..7993fb6a 100644 --- a/os/src/drivers/block/virtio_blk.rs +++ b/os/src/drivers/block/virtio_blk.rs @@ -3,7 +3,8 @@ use crate::mm::{ frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum, StepByOne, VirtAddr, }; -use crate::sync::{Condvar, UPSafeCell}; +use crate::sync::{Condvar, UPIntrFreeCell}; +use crate::task::schedule; use crate::DEV_NON_BLOCKING_ACCESS; use alloc::collections::BTreeMap; use alloc::vec::Vec; @@ -14,23 +15,24 @@ use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader}; const VIRTIO0: usize = 0x10001000; pub struct VirtIOBlock { - virtio_blk: UPSafeCell>, + virtio_blk: UPIntrFreeCell>, condvars: BTreeMap, } lazy_static! { - static ref QUEUE_FRAMES: UPSafeCell> = unsafe { UPSafeCell::new(Vec::new()) }; + static ref QUEUE_FRAMES: UPIntrFreeCell> = unsafe { UPIntrFreeCell::new(Vec::new()) }; } impl BlockDevice for VirtIOBlock { fn read_block(&self, block_id: usize, buf: &mut [u8]) { let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access(); if nb { - let mut blk = self.virtio_blk.exclusive_access(); let mut resp = BlkResp::default(); - let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() }; - drop(blk); - self.condvars.get(&token).unwrap().wait(); + let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| { + let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() }; + self.condvars.get(&token).unwrap().wait_no_sched() + }); + schedule(task_cx_ptr); assert_eq!( resp.status(), RespStatus::Ok, @@ -46,11 +48,12 @@ impl BlockDevice for VirtIOBlock { fn write_block(&self, block_id: usize, buf: &[u8]) { let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access(); if nb { - let mut blk = self.virtio_blk.exclusive_access(); let mut resp = BlkResp::default(); - let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() }; - drop(blk); - self.condvars.get(&token).unwrap().wait(); + let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| { + let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() }; + self.condvars.get(&token).unwrap().wait_no_sched() + }); + schedule(task_cx_ptr); assert_eq!( resp.status(), RespStatus::Ok, @@ -64,17 +67,21 @@ impl BlockDevice for VirtIOBlock { } } fn handle_irq(&self) { - let mut blk = self.virtio_blk.exclusive_access(); - while let Ok(token) = blk.pop_used() { - self.condvars.get(&token).unwrap().signal(); - } + //println!("into handle_irq"); + self.virtio_blk.exclusive_session(|blk| { + //println!("not panic here"); + while let Ok(token) = blk.pop_used() { + //println!("wakeup virtio.token {}", token); + self.condvars.get(&token).unwrap().signal(); + } + }); } } impl VirtIOBlock { pub fn new() -> Self { let virtio_blk = unsafe { - UPSafeCell::new(VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap()) + UPIntrFreeCell::new(VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap()) }; let mut condvars = BTreeMap::new(); let channels = virtio_blk.exclusive_access().virt_queue_size(); diff --git a/os/src/drivers/chardev/ns16550a.rs b/os/src/drivers/chardev/ns16550a.rs index df3fd809..46139994 100644 --- a/os/src/drivers/chardev/ns16550a.rs +++ b/os/src/drivers/chardev/ns16550a.rs @@ -1,13 +1,14 @@ +///! Ref: https://www.lammertbies.nl/comm/info/serial-uart +///! Ref: ns16550a datasheet: https://datasheetspdf.com/pdf-file/605590/NationalSemiconductor/NS16550A/1 +///! Ref: ns16450 datasheet: https://datasheetspdf.com/pdf-file/1311818/NationalSemiconductor/NS16450/1 + use super::CharDevice; -use crate::sync::{Condvar, UPSafeCell}; +use crate::sync::{Condvar, UPIntrFreeCell}; +use crate::task::schedule; use alloc::collections::VecDeque; use bitflags::*; use volatile::{ReadOnly, Volatile, WriteOnly}; -///! Ref: https://www.lammertbies.nl/comm/info/serial-uart -///! Ref: ns16550a datasheet: https://datasheetspdf.com/pdf-file/605590/NationalSemiconductor/NS16550A/1 -///! Ref: ns16450 datasheet: https://datasheetspdf.com/pdf-file/1311818/NationalSemiconductor/NS16450/1 - bitflags! { /// InterruptEnableRegister pub struct IER: u8 { @@ -125,7 +126,7 @@ struct NS16550aInner { } pub struct NS16550a { - inner: UPSafeCell, + inner: UPIntrFreeCell, condvar: Condvar, } @@ -137,7 +138,7 @@ impl NS16550a { }; inner.ns16550a.init(); Self { - inner: unsafe { UPSafeCell::new(inner) }, + inner: unsafe { UPIntrFreeCell::new(inner) }, condvar: Condvar::new(), } } @@ -145,13 +146,16 @@ impl NS16550a { impl CharDevice for NS16550a { fn read(&self) -> u8 { + println!("NS16550a::read"); loop { let mut inner = self.inner.exclusive_access(); if let Some(ch) = inner.read_buffer.pop_front() { return ch; } else { + println!("no ch yet!"); + let task_cx_ptr = self.condvar.wait_no_sched(); drop(inner); - self.condvar.wait(); + schedule(task_cx_ptr); } } } @@ -163,10 +167,12 @@ impl CharDevice for NS16550a { let mut inner = self.inner.exclusive_access(); let mut count = 0; while let Some(ch) = inner.ns16550a.read() { + println!("got {}", ch as char); count += 1; inner.read_buffer.push_back(ch); } drop(inner); + //assert_eq!(count, 1); if count > 0 { self.condvar.signal(); } diff --git a/os/src/drivers/plic.rs b/os/src/drivers/plic.rs index fa71dbf1..b1f662f3 100644 --- a/os/src/drivers/plic.rs +++ b/os/src/drivers/plic.rs @@ -1,3 +1,4 @@ +#[allow(clippy::upper_case_acronyms)] pub struct PLIC { base_addr: usize, } diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs index 19e4953d..321338d4 100644 --- a/os/src/fs/inode.rs +++ b/os/src/fs/inode.rs @@ -1,7 +1,7 @@ use super::File; use crate::drivers::BLOCK_DEVICE; use crate::mm::UserBuffer; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::sync::Arc; use alloc::vec::Vec; use bitflags::*; @@ -11,7 +11,7 @@ use lazy_static::*; pub struct OSInode { readable: bool, writable: bool, - inner: UPSafeCell, + inner: UPIntrFreeCell, } pub struct OSInodeInner { @@ -24,7 +24,7 @@ impl OSInode { Self { readable, writable, - inner: unsafe { UPSafeCell::new(OSInodeInner { offset: 0, inode }) }, + inner: unsafe { UPIntrFreeCell::new(OSInodeInner { offset: 0, inode }) }, } } pub fn read_all(&self) -> Vec { diff --git a/os/src/fs/pipe.rs b/os/src/fs/pipe.rs index 75caac54..18c74d51 100644 --- a/os/src/fs/pipe.rs +++ b/os/src/fs/pipe.rs @@ -1,6 +1,6 @@ use super::File; use crate::mm::UserBuffer; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::sync::{Arc, Weak}; use crate::task::suspend_current_and_run_next; @@ -8,18 +8,18 @@ use crate::task::suspend_current_and_run_next; pub struct Pipe { readable: bool, writable: bool, - buffer: Arc>, + buffer: Arc>, } impl Pipe { - pub fn read_end_with_buffer(buffer: Arc>) -> Self { + pub fn read_end_with_buffer(buffer: Arc>) -> Self { Self { readable: true, writable: false, buffer, } } - pub fn write_end_with_buffer(buffer: Arc>) -> Self { + pub fn write_end_with_buffer(buffer: Arc>) -> Self { Self { readable: false, writable: true, @@ -98,7 +98,7 @@ impl PipeRingBuffer { /// Return (read_end, write_end) pub fn make_pipe() -> (Arc, Arc) { - let buffer = Arc::new(unsafe { UPSafeCell::new(PipeRingBuffer::new()) }); + let buffer = Arc::new(unsafe { UPIntrFreeCell::new(PipeRingBuffer::new()) }); let read_end = Arc::new(Pipe::read_end_with_buffer(buffer.clone())); let write_end = Arc::new(Pipe::write_end_with_buffer(buffer.clone())); buffer.exclusive_access().set_write_end(&write_end); diff --git a/os/src/fs/stdio.rs b/os/src/fs/stdio.rs index 7a3adeda..99d07c23 100644 --- a/os/src/fs/stdio.rs +++ b/os/src/fs/stdio.rs @@ -14,6 +14,7 @@ impl File for Stdin { } fn read(&self, mut user_buf: UserBuffer) -> usize { assert_eq!(user_buf.len(), 1); + println!("before UART.read() in Stdin::read()"); let ch = UART.read(); unsafe { user_buf.buffers[0].as_mut_ptr().write_volatile(ch); diff --git a/os/src/main.rs b/os/src/main.rs index 77ebbbbc..a9323be1 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -43,10 +43,10 @@ fn clear_bss() { } use lazy_static::*; -use sync::UPSafeCell; +use sync::UPIntrFreeCell; lazy_static! { - pub static ref DEV_NON_BLOCKING_ACCESS: UPSafeCell = unsafe { UPSafeCell::new(false) }; + pub static ref DEV_NON_BLOCKING_ACCESS: UPIntrFreeCell = unsafe { UPIntrFreeCell::new(false) }; } #[no_mangle] diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 4bc7db26..3c62324b 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -1,6 +1,6 @@ use super::{PhysAddr, PhysPageNum}; use crate::config::MEMORY_END; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::vec::Vec; use core::fmt::{self, Debug, Formatter}; use lazy_static::*; @@ -83,8 +83,8 @@ impl FrameAllocator for StackFrameAllocator { type FrameAllocatorImpl = StackFrameAllocator; lazy_static! { - pub static ref FRAME_ALLOCATOR: UPSafeCell = - unsafe { UPSafeCell::new(FrameAllocatorImpl::new()) }; + pub static ref FRAME_ALLOCATOR: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(FrameAllocatorImpl::new()) }; } pub fn init_frame_allocator() { diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index aba1ae57..0862dc7a 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -3,7 +3,7 @@ use super::{PTEFlags, PageTable, PageTableEntry}; use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; use super::{StepByOne, VPNRange}; use crate::config::{MEMORY_END, MMIO, PAGE_SIZE, TRAMPOLINE}; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::collections::BTreeMap; use alloc::sync::Arc; use alloc::vec::Vec; @@ -25,8 +25,8 @@ extern "C" { } lazy_static! { - pub static ref KERNEL_SPACE: Arc> = - Arc::new(unsafe { UPSafeCell::new(MemorySet::new_kernel()) }); + pub static ref KERNEL_SPACE: Arc> = + Arc::new(unsafe { UPIntrFreeCell::new(MemorySet::new_kernel()) }); } pub fn kernel_token() -> usize { diff --git a/os/src/sync/condvar.rs b/os/src/sync/condvar.rs index d7943e1d..8435a7dd 100644 --- a/os/src/sync/condvar.rs +++ b/os/src/sync/condvar.rs @@ -1,9 +1,9 @@ -use crate::sync::{Mutex, UPSafeCell}; -use crate::task::{add_task, block_current_and_run_next, current_task, TaskControlBlock}; +use crate::sync::{Mutex, UPIntrFreeCell}; +use crate::task::{add_task, block_current_task, block_current_and_run_next, current_task, TaskControlBlock, TaskContext}; use alloc::{collections::VecDeque, sync::Arc}; pub struct Condvar { - pub inner: UPSafeCell, + pub inner: UPIntrFreeCell, } pub struct CondvarInner { @@ -14,7 +14,7 @@ impl Condvar { pub fn new() -> Self { Self { inner: unsafe { - UPSafeCell::new(CondvarInner { + UPIntrFreeCell::new(CondvarInner { wait_queue: VecDeque::new(), }) }, @@ -35,6 +35,13 @@ impl Condvar { block_current_and_run_next(); } + pub fn wait_no_sched(&self) -> *mut TaskContext { + self.inner.exclusive_session(|inner| { + inner.wait_queue.push_back(current_task().unwrap()); + }); + block_current_task() + } + pub fn wait_with_mutex(&self, mutex: Arc) { mutex.unlock(); let mut inner = self.inner.exclusive_access(); diff --git a/os/src/sync/mod.rs b/os/src/sync/mod.rs index 7e948aa6..d9a00b5b 100644 --- a/os/src/sync/mod.rs +++ b/os/src/sync/mod.rs @@ -6,4 +6,4 @@ mod up; pub use condvar::Condvar; pub use mutex::{Mutex, MutexBlocking, MutexSpin}; pub use semaphore::Semaphore; -pub use up::UPSafeCell; +pub use up::{UPIntrFreeCell, UPIntrRefMut}; diff --git a/os/src/sync/mutex.rs b/os/src/sync/mutex.rs index be58f795..463638b3 100644 --- a/os/src/sync/mutex.rs +++ b/os/src/sync/mutex.rs @@ -1,4 +1,4 @@ -use super::UPSafeCell; +use super::UPIntrFreeCell; use crate::task::TaskControlBlock; use crate::task::{add_task, current_task}; use crate::task::{block_current_and_run_next, suspend_current_and_run_next}; @@ -10,13 +10,13 @@ pub trait Mutex: Sync + Send { } pub struct MutexSpin { - locked: UPSafeCell, + locked: UPIntrFreeCell, } impl MutexSpin { pub fn new() -> Self { Self { - locked: unsafe { UPSafeCell::new(false) }, + locked: unsafe { UPIntrFreeCell::new(false) }, } } } @@ -43,7 +43,7 @@ impl Mutex for MutexSpin { } pub struct MutexBlocking { - inner: UPSafeCell, + inner: UPIntrFreeCell, } pub struct MutexBlockingInner { @@ -55,7 +55,7 @@ impl MutexBlocking { pub fn new() -> Self { Self { inner: unsafe { - UPSafeCell::new(MutexBlockingInner { + UPIntrFreeCell::new(MutexBlockingInner { locked: false, wait_queue: VecDeque::new(), }) diff --git a/os/src/sync/semaphore.rs b/os/src/sync/semaphore.rs index 7f3870f8..354db29f 100644 --- a/os/src/sync/semaphore.rs +++ b/os/src/sync/semaphore.rs @@ -1,9 +1,9 @@ -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use crate::task::{add_task, block_current_and_run_next, current_task, TaskControlBlock}; use alloc::{collections::VecDeque, sync::Arc}; pub struct Semaphore { - pub inner: UPSafeCell, + pub inner: UPIntrFreeCell, } pub struct SemaphoreInner { @@ -15,7 +15,7 @@ impl Semaphore { pub fn new(res_count: usize) -> Self { Self { inner: unsafe { - UPSafeCell::new(SemaphoreInner { + UPIntrFreeCell::new(SemaphoreInner { count: res_count as isize, wait_queue: VecDeque::new(), }) diff --git a/os/src/sync/up.rs b/os/src/sync/up.rs index c7b2c9ee..c5db9e5b 100644 --- a/os/src/sync/up.rs +++ b/os/src/sync/up.rs @@ -1,4 +1,7 @@ -use core::cell::{RefCell, RefMut}; +use core::cell::{RefCell, RefMut, UnsafeCell}; +use core::ops::{Deref, DerefMut}; +use riscv::register::sstatus; +use lazy_static::*; /// Wrap a static data structure inside it so that we are /// able to access it without any `unsafe`. @@ -27,3 +30,103 @@ impl UPSafeCell { self.inner.borrow_mut() } } + +pub struct UPSafeCellRaw { + inner: UnsafeCell, +} + +unsafe impl Sync for UPSafeCellRaw {} + +impl UPSafeCellRaw { + pub unsafe fn new(value: T) -> Self { + Self { + inner: UnsafeCell::new(value), + } + } + pub fn get_mut(&self) -> &mut T { + unsafe { &mut (*self.inner.get()) } + } +} + +pub struct IntrMaskingInfo { + nested_level: usize, + sie_before_masking: bool, +} + +lazy_static! { + static ref INTR_MASKING_INFO: UPSafeCellRaw = unsafe { + UPSafeCellRaw::new(IntrMaskingInfo::new()) + }; +} + +impl IntrMaskingInfo { + pub fn new() -> Self { + Self { + nested_level: 0, + sie_before_masking: false, + } + } + + pub fn enter(&mut self) { + let sie = sstatus::read().sie(); + unsafe { sstatus::clear_sie(); } + if self.nested_level == 0 { + self.sie_before_masking = sie; + } + self.nested_level += 1; + } + + pub fn exit(&mut self) { + self.nested_level -= 1; + if self.nested_level == 0 && self.sie_before_masking { + unsafe { sstatus::set_sie(); } + } + } +} + +pub struct UPIntrFreeCell { + /// inner data + inner: RefCell, +} + +unsafe impl Sync for UPIntrFreeCell {} + +pub struct UPIntrRefMut<'a, T>(Option>); + +impl UPIntrFreeCell { + pub unsafe fn new(value: T) -> Self { + Self { + inner: RefCell::new(value), + } + } + /// Panic if the data has been borrowed. + pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> { + INTR_MASKING_INFO.get_mut().enter(); + UPIntrRefMut(Some(self.inner.borrow_mut())) + } + + pub fn exclusive_session(&self, f: F) -> V where F: FnOnce(&mut T) -> V { + let mut inner = self.exclusive_access(); + f(inner.deref_mut()) + } +} + +impl<'a, T> Drop for UPIntrRefMut<'a, T> { + fn drop(&mut self) { + self.0 = None; + INTR_MASKING_INFO.get_mut().exit(); + } +} + +impl<'a, T> Deref for UPIntrRefMut<'a, T> { + type Target = T; + fn deref(&self) -> &Self::Target { + self.0.as_ref().unwrap().deref() + } +} +impl<'a, T> DerefMut for UPIntrRefMut<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.0.as_mut().unwrap().deref_mut() + } +} + diff --git a/os/src/task/id.rs b/os/src/task/id.rs index 178a09f6..e336c500 100644 --- a/os/src/task/id.rs +++ b/os/src/task/id.rs @@ -1,7 +1,7 @@ use super::ProcessControlBlock; use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE, TRAP_CONTEXT_BASE, USER_STACK_SIZE}; use crate::mm::{MapPermission, PhysPageNum, VirtAddr, KERNEL_SPACE}; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::{ sync::{Arc, Weak}, vec::Vec, @@ -40,10 +40,10 @@ impl RecycleAllocator { } lazy_static! { - static ref PID_ALLOCATOR: UPSafeCell = - unsafe { UPSafeCell::new(RecycleAllocator::new()) }; - static ref KSTACK_ALLOCATOR: UPSafeCell = - unsafe { UPSafeCell::new(RecycleAllocator::new()) }; + static ref PID_ALLOCATOR: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(RecycleAllocator::new()) }; + static ref KSTACK_ALLOCATOR: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(RecycleAllocator::new()) }; } pub struct PidHandle(pub usize); diff --git a/os/src/task/manager.rs b/os/src/task/manager.rs index 5ed68ae7..168ba32e 100644 --- a/os/src/task/manager.rs +++ b/os/src/task/manager.rs @@ -1,5 +1,5 @@ use super::{ProcessControlBlock, TaskControlBlock}; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use alloc::collections::{BTreeMap, VecDeque}; use alloc::sync::Arc; use lazy_static::*; @@ -24,10 +24,10 @@ impl TaskManager { } lazy_static! { - pub static ref TASK_MANAGER: UPSafeCell = - unsafe { UPSafeCell::new(TaskManager::new()) }; - pub static ref PID2PCB: UPSafeCell>> = - unsafe { UPSafeCell::new(BTreeMap::new()) }; + pub static ref TASK_MANAGER: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(TaskManager::new()) }; + pub static ref PID2PCB: UPIntrFreeCell>> = + unsafe { UPIntrFreeCell::new(BTreeMap::new()) }; } pub fn add_task(task: Arc) { diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 1bd7b2a7..858848a7 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -43,12 +43,16 @@ pub fn suspend_current_and_run_next() { schedule(task_cx_ptr); } -pub fn block_current_and_run_next() { +/// This function must be followed by a schedule +pub fn block_current_task() -> *mut TaskContext { let task = take_current_task().unwrap(); let mut task_inner = task.inner_exclusive_access(); - let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext; task_inner.task_status = TaskStatus::Blocking; - drop(task_inner); + &mut task_inner.task_cx as *mut TaskContext +} + +pub fn block_current_and_run_next() { + let task_cx_ptr = block_current_task(); schedule(task_cx_ptr); } diff --git a/os/src/task/process.rs b/os/src/task/process.rs index ffff14fe..b3976b7c 100644 --- a/os/src/task/process.rs +++ b/os/src/task/process.rs @@ -5,19 +5,18 @@ use super::{add_task, SignalFlags}; use super::{pid_alloc, PidHandle}; use crate::fs::{File, Stdin, Stdout}; use crate::mm::{translated_refmut, MemorySet, KERNEL_SPACE}; -use crate::sync::{Condvar, Mutex, Semaphore, UPSafeCell}; +use crate::sync::{Condvar, Mutex, Semaphore, UPIntrFreeCell, UPIntrRefMut}; use crate::trap::{trap_handler, TrapContext}; use alloc::string::String; use alloc::sync::{Arc, Weak}; use alloc::vec; use alloc::vec::Vec; -use core::cell::RefMut; pub struct ProcessControlBlock { // immutable pub pid: PidHandle, // mutable - inner: UPSafeCell, + inner: UPIntrFreeCell, } pub struct ProcessControlBlockInner { @@ -68,7 +67,7 @@ impl ProcessControlBlockInner { } impl ProcessControlBlock { - pub fn inner_exclusive_access(&self) -> RefMut<'_, ProcessControlBlockInner> { + pub fn inner_exclusive_access(&self) -> UPIntrRefMut<'_, ProcessControlBlockInner> { self.inner.exclusive_access() } @@ -80,7 +79,7 @@ impl ProcessControlBlock { let process = Arc::new(Self { pid: pid_handle, inner: unsafe { - UPSafeCell::new(ProcessControlBlockInner { + UPIntrFreeCell::new(ProcessControlBlockInner { is_zombie: false, memory_set, parent: None, @@ -206,7 +205,7 @@ impl ProcessControlBlock { let child = Arc::new(Self { pid, inner: unsafe { - UPSafeCell::new(ProcessControlBlockInner { + UPIntrFreeCell::new(ProcessControlBlockInner { is_zombie: false, memory_set, parent: Some(Arc::downgrade(self)), diff --git a/os/src/task/processor.rs b/os/src/task/processor.rs index 3c1a22f6..347d3725 100644 --- a/os/src/task/processor.rs +++ b/os/src/task/processor.rs @@ -1,7 +1,7 @@ use super::__switch; use super::{fetch_task, TaskStatus}; use super::{ProcessControlBlock, TaskContext, TaskControlBlock}; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use crate::trap::TrapContext; use alloc::sync::Arc; use lazy_static::*; @@ -30,7 +30,7 @@ impl Processor { } lazy_static! { - pub static ref PROCESSOR: UPSafeCell = unsafe { UPSafeCell::new(Processor::new()) }; + pub static ref PROCESSOR: UPIntrFreeCell = unsafe { UPIntrFreeCell::new(Processor::new()) }; } pub fn run_tasks() { diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 99900de3..7b65ee6b 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,20 +1,19 @@ use super::id::TaskUserRes; use super::{kstack_alloc, KernelStack, ProcessControlBlock, TaskContext}; use crate::trap::TrapContext; -use crate::{mm::PhysPageNum, sync::UPSafeCell}; +use crate::{mm::PhysPageNum, sync::{UPIntrFreeCell, UPIntrRefMut}}; use alloc::sync::{Arc, Weak}; -use core::cell::RefMut; pub struct TaskControlBlock { // immutable pub process: Weak, pub kstack: KernelStack, // mutable - inner: UPSafeCell, + inner: UPIntrFreeCell, } impl TaskControlBlock { - pub fn inner_exclusive_access(&self) -> RefMut<'_, TaskControlBlockInner> { + pub fn inner_exclusive_access(&self) -> UPIntrRefMut<'_, TaskControlBlockInner> { self.inner.exclusive_access() } @@ -58,7 +57,7 @@ impl TaskControlBlock { process: Arc::downgrade(&process), kstack, inner: unsafe { - UPSafeCell::new(TaskControlBlockInner { + UPIntrFreeCell::new(TaskControlBlockInner { res: Some(res), trap_cx_ppn, task_cx: TaskContext::goto_trap_return(kstack_top), diff --git a/os/src/timer.rs b/os/src/timer.rs index 3baed0f7..06a70dea 100644 --- a/os/src/timer.rs +++ b/os/src/timer.rs @@ -2,7 +2,7 @@ use core::cmp::Ordering; use crate::config::CLOCK_FREQ; use crate::sbi::set_timer; -use crate::sync::UPSafeCell; +use crate::sync::UPIntrFreeCell; use crate::task::{add_task, TaskControlBlock}; use alloc::collections::BinaryHeap; use alloc::sync::Arc; @@ -50,8 +50,8 @@ impl Ord for TimerCondVar { } lazy_static! { - static ref TIMERS: UPSafeCell> = - unsafe { UPSafeCell::new(BinaryHeap::::new()) }; + static ref TIMERS: UPIntrFreeCell> = + unsafe { UPIntrFreeCell::new(BinaryHeap::::new()) }; } pub fn add_timer(expire_ms: usize, task: Arc) { diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 287afd3e..21755400 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -11,7 +11,7 @@ use core::arch::{asm, global_asm}; use riscv::register::{ mtvec::TrapMode, scause::{self, Exception, Interrupt, Trap}, - sie, stval, stvec, + sie, stval, stvec, sstatus, sscratch, }; global_asm!(include_str!("trap.S")); @@ -21,8 +21,14 @@ pub fn init() { } fn set_kernel_trap_entry() { + extern "C" { + fn __alltraps(); + fn __alltraps_k(); + } + let __alltraps_k_va = __alltraps_k as usize - __alltraps as usize + TRAMPOLINE; unsafe { - stvec::write(trap_from_kernel as usize, TrapMode::Direct); + stvec::write(__alltraps_k_va, TrapMode::Direct); + sscratch::write(trap_from_kernel as usize); } } @@ -38,16 +44,28 @@ pub fn enable_timer_interrupt() { } } +fn enable_supervisor_interrupt() { + unsafe { + sstatus::set_sie(); + } +} + #[no_mangle] pub fn trap_handler() -> ! { set_kernel_trap_entry(); let scause = scause::read(); let stval = stval::read(); + //println!("into {:?}", scause.cause()); match scause.cause() { Trap::Exception(Exception::UserEnvCall) => { // jump to next instruction anyway let mut cx = current_trap_cx(); cx.sepc += 4; + + //println!("syscall id={}", cx.x[17]); + //println!("after setting sstatus.sie"); + enable_supervisor_interrupt(); + // get system call return value let result = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]); // cx is changed during sys_exec, so we have to call it again @@ -107,6 +125,7 @@ pub fn trap_return() -> ! { fn __restore(); } let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; + //println!("before return"); unsafe { asm!( "fence.i", @@ -120,10 +139,37 @@ pub fn trap_return() -> ! { } #[no_mangle] -pub fn trap_from_kernel() -> ! { +pub fn trap_from_kernel(trap_cx: &TrapContext) { + /* use riscv::register::sepc; + println!("a trap {:?} from kernel!", scause::read().cause()); println!("stval = {:#x}, sepc = {:#x}", stval::read(), sepc::read()); - panic!("a trap {:?} from kernel!", scause::read().cause()); + //panic!("a trap {:?} from kernel!", scause::read().cause()); + */ + //panic!("a trap {:?} from kernel!", scause::read().cause()); + //println!("->trap_from_kernel"); + //println!("a trap {:?} from kernel!", scause::read().cause()); + //println!("sepc = {:#x}", trap_cx.sepc); + let scause = scause::read(); + let stval = stval::read(); + match scause.cause() { + Trap::Interrupt(Interrupt::SupervisorExternal) => { + crate::board::irq_handler(); + }, + Trap::Interrupt(Interrupt::SupervisorTimer) => { + set_next_trigger(); + check_timer(); + // do not schedule now + }, + _ => { + panic!( + "Unsupported trap from kernel: {:?}, stval = {:#x}!", + scause.cause(), + stval + ); + }, + } + //println!("trap_from_kernel->"); } pub use context::TrapContext; diff --git a/os/src/trap/trap.S b/os/src/trap/trap.S index c0e2d153..407307ca 100644 --- a/os/src/trap/trap.S +++ b/os/src/trap/trap.S @@ -8,6 +8,8 @@ .section .text.trampoline .globl __alltraps .globl __restore + .globl __alltraps_k + .globl __restore_k .align 2 __alltraps: csrrw sp, sscratch, sp @@ -67,3 +69,36 @@ __restore: # back to user stack ld sp, 2*8(sp) sret + + .align 2 +__alltraps_k: + addi sp, sp, -34*8 + sd x1, 1*8(sp) + sd x3, 3*8(sp) + .set n, 5 + .rept 27 + SAVE_GP %n + .set n, n+1 + .endr + csrr t0, sstatus + csrr t1, sepc + sd t0, 32*8(sp) + sd t1, 33*8(sp) + mv a0, sp + csrr t2, sscratch + jalr t2 + +__restore_k: + ld t0, 32*8(sp) + ld t1, 33*8(sp) + csrw sstatus, t0 + csrw sepc, t1 + ld x1, 1*8(sp) + ld x3, 3*8(sp) + .set n, 5 + .rept 27 + LOAD_GP %n + .set n, n+1 + .endr + addi sp, sp, 34*8 + sret