diff --git a/easy-fs-fuse/Cargo.toml b/easy-fs-fuse/Cargo.toml index 5c5e68d5..3470de93 100644 --- a/easy-fs-fuse/Cargo.toml +++ b/easy-fs-fuse/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] clap = "2.33.3" easy-fs = { path = "../easy-fs" } +ksync = { path = "../ksync" } rand = "0.8.0" # [features] diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs index bb9ff761..4f0da2e9 100644 --- a/easy-fs-fuse/src/main.rs +++ b/easy-fs-fuse/src/main.rs @@ -153,3 +153,16 @@ fn efs_test() -> std::io::Result<()> { Ok(()) } + +// extern "C" { +// fn swap_and_disable_intr() -> bool; +// fn enable_intr(); +// } + +#[no_mangle] +extern "C" fn swap_and_disable_intr() -> bool { + false +} + +#[no_mangle] +extern "C" fn enable_intr() {} \ No newline at end of file diff --git a/easy-fs/Cargo.toml b/easy-fs/Cargo.toml index 7a2f38ed..a2d79abc 100644 --- a/easy-fs/Cargo.toml +++ b/easy-fs/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -spin = "0.7.0" +ksync = { path = "../ksync" } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } [profile.release] diff --git a/easy-fs/src/bitmap.rs b/easy-fs/src/bitmap.rs index 2cea613e..6cf5c61b 100644 --- a/easy-fs/src/bitmap.rs +++ b/easy-fs/src/bitmap.rs @@ -31,7 +31,7 @@ impl Bitmap { block_id + self.start_block_id as usize, Arc::clone(block_device), ) - .lock() + .exclusive_access() .modify(0, |bitmap_block: &mut BitmapBlock| { if let Some((bits64_pos, inner_pos)) = bitmap_block .iter() @@ -56,7 +56,7 @@ impl Bitmap { pub fn dealloc(&self, block_device: &Arc, bit: usize) { let (block_pos, bits64_pos, inner_pos) = decomposition(bit); get_block_cache(block_pos + self.start_block_id, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |bitmap_block: &mut BitmapBlock| { assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0); bitmap_block[bits64_pos] -= 1u64 << inner_pos; diff --git a/easy-fs/src/block_cache.rs b/easy-fs/src/block_cache.rs index 1b3b9697..0eae543a 100644 --- a/easy-fs/src/block_cache.rs +++ b/easy-fs/src/block_cache.rs @@ -4,7 +4,7 @@ use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; use lazy_static::*; -use spin::Mutex; +use ksync::UPIntrFreeCell; pub struct BlockCache { cache: Vec, @@ -77,7 +77,7 @@ impl Drop for BlockCache { const BLOCK_CACHE_SIZE: usize = 16; pub struct BlockCacheManager { - queue: VecDeque<(usize, Arc>)>, + queue: VecDeque<(usize, Arc>)>, } impl BlockCacheManager { @@ -91,7 +91,7 @@ impl BlockCacheManager { &mut self, block_id: usize, block_device: Arc, - ) -> Arc> { + ) -> Arc> { if let Some(pair) = self.queue.iter().find(|pair| pair.0 == block_id) { Arc::clone(&pair.1) } else { @@ -110,10 +110,10 @@ impl BlockCacheManager { } } // load block into mem and push back - let block_cache = Arc::new(Mutex::new(BlockCache::new( + let block_cache = Arc::new(unsafe { UPIntrFreeCell::new(BlockCache::new( block_id, Arc::clone(&block_device), - ))); + ))}); self.queue.push_back((block_id, Arc::clone(&block_cache))); block_cache } @@ -121,22 +121,22 @@ impl BlockCacheManager { } lazy_static! { - pub static ref BLOCK_CACHE_MANAGER: Mutex = - Mutex::new(BlockCacheManager::new()); + pub static ref BLOCK_CACHE_MANAGER: UPIntrFreeCell = + unsafe { UPIntrFreeCell::new(BlockCacheManager::new()) }; } pub fn get_block_cache( block_id: usize, block_device: Arc, -) -> Arc> { +) -> Arc> { BLOCK_CACHE_MANAGER - .lock() + .exclusive_access() .get_block_cache(block_id, block_device) } pub fn block_cache_sync_all() { - let manager = BLOCK_CACHE_MANAGER.lock(); + let manager = BLOCK_CACHE_MANAGER.exclusive_access(); for (_, cache) in manager.queue.iter() { - cache.lock().sync(); + cache.exclusive_access().sync(); } } diff --git a/easy-fs/src/efs.rs b/easy-fs/src/efs.rs index 82e95ae0..0382a1cb 100644 --- a/easy-fs/src/efs.rs +++ b/easy-fs/src/efs.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::BLOCK_SZ; use alloc::sync::Arc; -use spin::Mutex; +use ksync::UPIntrFreeCell; pub struct EasyFileSystem { pub block_device: Arc, @@ -21,7 +21,7 @@ impl EasyFileSystem { block_device: Arc, total_blocks: u32, inode_bitmap_blocks: u32, - ) -> Arc> { + ) -> Arc> { // calculate block size of areas & create bitmaps let inode_bitmap = Bitmap::new(1, inode_bitmap_blocks as usize); let inode_num = inode_bitmap.maximum(); @@ -45,7 +45,7 @@ impl EasyFileSystem { // clear all blocks for i in 0..total_blocks { get_block_cache(i as usize, Arc::clone(&block_device)) - .lock() + .exclusive_access() .modify(0, |data_block: &mut DataBlock| { for byte in data_block.iter_mut() { *byte = 0; @@ -53,7 +53,7 @@ impl EasyFileSystem { }); } // initialize SuperBlock - get_block_cache(0, Arc::clone(&block_device)).lock().modify( + get_block_cache(0, Arc::clone(&block_device)).exclusive_access().modify( 0, |super_block: &mut SuperBlock| { super_block.initialize( @@ -70,18 +70,18 @@ impl EasyFileSystem { assert_eq!(efs.alloc_inode(), 0); let (root_inode_block_id, root_inode_offset) = efs.get_disk_inode_pos(0); get_block_cache(root_inode_block_id as usize, Arc::clone(&block_device)) - .lock() + .exclusive_access() .modify(root_inode_offset, |disk_inode: &mut DiskInode| { disk_inode.initialize(DiskInodeType::Directory); }); block_cache_sync_all(); - Arc::new(Mutex::new(efs)) + Arc::new(unsafe { UPIntrFreeCell::new(efs) }) } - pub fn open(block_device: Arc) -> Arc> { + pub fn open(block_device: Arc) -> Arc> { // read SuperBlock get_block_cache(0, Arc::clone(&block_device)) - .lock() + .exclusive_access() .read(0, |super_block: &SuperBlock| { assert!(super_block.is_valid(), "Error loading EFS!"); let inode_total_blocks = @@ -96,14 +96,14 @@ impl EasyFileSystem { inode_area_start_block: 1 + super_block.inode_bitmap_blocks, data_area_start_block: 1 + inode_total_blocks + super_block.data_bitmap_blocks, }; - Arc::new(Mutex::new(efs)) + Arc::new(unsafe { UPIntrFreeCell::new(efs) }) }) } - pub fn root_inode(efs: &Arc>) -> Inode { - let block_device = Arc::clone(&efs.lock().block_device); + pub fn root_inode(efs: &Arc>) -> Inode { + let block_device = Arc::clone(&efs.exclusive_access().block_device); // acquire efs lock temporarily - let (block_id, block_offset) = efs.lock().get_disk_inode_pos(0); + let (block_id, block_offset) = efs.exclusive_access().get_disk_inode_pos(0); // release efs lock Inode::new(block_id, block_offset, Arc::clone(efs), block_device) } @@ -133,7 +133,7 @@ impl EasyFileSystem { pub fn dealloc_data(&mut self, block_id: u32) { get_block_cache(block_id as usize, Arc::clone(&self.block_device)) - .lock() + .exclusive_access() .modify(0, |data_block: &mut DataBlock| { data_block.iter_mut().for_each(|p| { *p = 0; diff --git a/easy-fs/src/layout.rs b/easy-fs/src/layout.rs index 618484cf..5cad9832 100644 --- a/easy-fs/src/layout.rs +++ b/easy-fs/src/layout.rs @@ -126,19 +126,19 @@ impl DiskInode { self.direct[inner_id] } else if inner_id < INDIRECT1_BOUND { get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .read(0, |indirect_block: &IndirectBlock| { indirect_block[inner_id - INODE_DIRECT_COUNT] }) } else { let last = inner_id - INDIRECT1_BOUND; let indirect1 = get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .read(0, |indirect2: &IndirectBlock| { indirect2[last / INODE_INDIRECT1_COUNT] }); get_block_cache(indirect1 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .read(0, |indirect1: &IndirectBlock| { indirect1[last % INODE_INDIRECT1_COUNT] }) @@ -171,7 +171,7 @@ impl DiskInode { } // fill indirect1 get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect1: &mut IndirectBlock| { while current_blocks < total_blocks.min(INODE_INDIRECT1_COUNT as u32) { indirect1[current_blocks as usize] = new_blocks.next().unwrap(); @@ -195,7 +195,7 @@ impl DiskInode { let b1 = total_blocks as usize % INODE_INDIRECT1_COUNT; // alloc low-level indirect1 get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect2: &mut IndirectBlock| { while (a0 < a1) || (a0 == a1 && b0 < b1) { if b0 == 0 { @@ -203,7 +203,7 @@ impl DiskInode { } // fill current get_block_cache(indirect2[a0] as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect1: &mut IndirectBlock| { indirect1[b0] = new_blocks.next().unwrap(); }); @@ -241,7 +241,7 @@ impl DiskInode { } // indirect1 get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect1: &mut IndirectBlock| { while current_blocks < data_blocks.min(INODE_INDIRECT1_COUNT) { v.push(indirect1[current_blocks]); @@ -262,13 +262,13 @@ impl DiskInode { let a1 = data_blocks / INODE_INDIRECT1_COUNT; let b1 = data_blocks % INODE_INDIRECT1_COUNT; get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect2: &mut IndirectBlock| { // full indirect1 blocks for entry in indirect2.iter_mut().take(a1) { v.push(*entry); get_block_cache(*entry as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect1: &mut IndirectBlock| { for entry in indirect1.iter() { v.push(*entry); @@ -279,7 +279,7 @@ impl DiskInode { if b1 > 0 { v.push(indirect2[a1]); get_block_cache(indirect2[a1] as usize, Arc::clone(block_device)) - .lock() + .exclusive_access() .modify(0, |indirect1: &mut IndirectBlock| { for entry in indirect1.iter().take(b1) { v.push(*entry); @@ -315,7 +315,7 @@ impl DiskInode { self.get_block_id(start_block as u32, block_device) as usize, Arc::clone(block_device), ) - .lock() + .exclusive_access() .read(0, |data_block: &DataBlock| { let src = &data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_read_size]; dst.copy_from_slice(src); @@ -352,7 +352,7 @@ impl DiskInode { self.get_block_id(start_block as u32, block_device) as usize, Arc::clone(block_device), ) - .lock() + .exclusive_access() .modify(0, |data_block: &mut DataBlock| { let src = &buf[write_size..write_size + block_write_size]; let dst = &mut data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_write_size]; diff --git a/easy-fs/src/vfs.rs b/easy-fs/src/vfs.rs index 7290fa47..242789ad 100644 --- a/easy-fs/src/vfs.rs +++ b/easy-fs/src/vfs.rs @@ -5,12 +5,12 @@ use super::{ use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; -use spin::{Mutex, MutexGuard}; +use ksync::{UPIntrFreeCell, UPIntrRefMut}; pub struct Inode { block_id: usize, block_offset: usize, - fs: Arc>, + fs: Arc>, block_device: Arc, } @@ -19,7 +19,7 @@ impl Inode { pub fn new( block_id: u32, block_offset: usize, - fs: Arc>, + fs: Arc>, block_device: Arc, ) -> Self { Self { @@ -32,13 +32,13 @@ impl Inode { fn read_disk_inode(&self, f: impl FnOnce(&DiskInode) -> V) -> V { get_block_cache(self.block_id, Arc::clone(&self.block_device)) - .lock() + .exclusive_access() .read(self.block_offset, f) } fn modify_disk_inode(&self, f: impl FnOnce(&mut DiskInode) -> V) -> V { get_block_cache(self.block_id, Arc::clone(&self.block_device)) - .lock() + .exclusive_access() .modify(self.block_offset, f) } @@ -60,7 +60,7 @@ impl Inode { } pub fn find(&self, name: &str) -> Option> { - let fs = self.fs.lock(); + let fs = self.fs.exclusive_access(); self.read_disk_inode(|disk_inode| { self.find_inode_id(name, disk_inode).map(|inode_id| { let (block_id, block_offset) = fs.get_disk_inode_pos(inode_id); @@ -78,7 +78,7 @@ impl Inode { &self, new_size: u32, disk_inode: &mut DiskInode, - fs: &mut MutexGuard, + fs: &mut UPIntrRefMut, ) { if new_size < disk_inode.size { return; @@ -92,7 +92,7 @@ impl Inode { } pub fn create(&self, name: &str) -> Option> { - let mut fs = self.fs.lock(); + let mut fs = self.fs.exclusive_access(); let op = |root_inode: &mut DiskInode| { // assert it is a directory assert!(root_inode.is_dir()); @@ -108,7 +108,7 @@ impl Inode { // initialize inode let (new_inode_block_id, new_inode_block_offset) = fs.get_disk_inode_pos(new_inode_id); get_block_cache(new_inode_block_id as usize, Arc::clone(&self.block_device)) - .lock() + .exclusive_access() .modify(new_inode_block_offset, |new_inode: &mut DiskInode| { new_inode.initialize(DiskInodeType::File); }); @@ -140,7 +140,7 @@ impl Inode { } pub fn ls(&self) -> Vec { - let _fs = self.fs.lock(); + let _fs = self.fs.exclusive_access(); self.read_disk_inode(|disk_inode| { let file_count = (disk_inode.size as usize) / DIRENT_SZ; let mut v: Vec = Vec::new(); @@ -157,12 +157,12 @@ impl Inode { } pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize { - let _fs = self.fs.lock(); + let _fs = self.fs.exclusive_access(); self.read_disk_inode(|disk_inode| disk_inode.read_at(offset, buf, &self.block_device)) } pub fn write_at(&self, offset: usize, buf: &[u8]) -> usize { - let mut fs = self.fs.lock(); + let mut fs = self.fs.exclusive_access(); let size = self.modify_disk_inode(|disk_inode| { self.increase_size((offset + buf.len()) as u32, disk_inode, &mut fs); disk_inode.write_at(offset, buf, &self.block_device) @@ -172,7 +172,7 @@ impl Inode { } pub fn clear(&self) { - let mut fs = self.fs.lock(); + let mut fs = self.fs.exclusive_access(); self.modify_disk_inode(|disk_inode| { let size = disk_inode.size; let data_blocks_dealloc = disk_inode.clear_size(&self.block_device); diff --git a/ksync/Cargo.toml b/ksync/Cargo.toml new file mode 100644 index 00000000..3596ffa0 --- /dev/null +++ b/ksync/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ksync" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } \ No newline at end of file diff --git a/ksync/src/lib.rs b/ksync/src/lib.rs new file mode 100644 index 00000000..eaafe749 --- /dev/null +++ b/ksync/src/lib.rs @@ -0,0 +1,143 @@ +#![no_std] + +use core::cell::{RefCell, RefMut, UnsafeCell}; +use core::ops::{Deref, DerefMut}; +use lazy_static::*; + +/// Wrap a static data structure inside it so that we are +/// able to access it without any `unsafe`. +/// +/// We should only use it in uniprocessor. +/// +/// In order to get mutable reference of inner data, call +/// `exclusive_access`. +pub struct UPSafeCell { + /// inner data + inner: RefCell, +} + +unsafe impl Sync for UPSafeCell {} + +impl UPSafeCell { + /// User is responsible to guarantee that inner struct is only used in + /// uniprocessor. + pub unsafe fn new(value: T) -> Self { + Self { + inner: RefCell::new(value), + } + } + /// Panic if the data has been borrowed. + pub fn exclusive_access(&self) -> RefMut<'_, T> { + self.inner.borrow_mut() + } +} + +extern "C" { + fn swap_and_disable_intr() -> bool; + fn enable_intr(); +} + +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()) } + } +} + +struct IntrMaskingInfo { + nested_level: usize, + intr_enable_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, + intr_enable_before_masking: false, + } + } + + pub fn enter(&mut self) { + let prev_enable = unsafe { + swap_and_disable_intr() + }; + if self.nested_level == 0 { + self.intr_enable_before_masking = prev_enable; + } + self.nested_level += 1; + } + + pub fn exit(&mut self) { + self.nested_level -= 1; + if self.nested_level == 0 && self.intr_enable_before_masking { + unsafe { + enable_intr(); + } + } + } +} + +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/Cargo.toml b/os/Cargo.toml index e23fe161..419e4373 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -18,6 +18,7 @@ lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "3f4 easy-fs = { path = "../easy-fs" } embedded-graphics = "0.7.1" tinybmp = "0.3.1" +ksync = { path = "../ksync" } [profile.release] debug = true diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs index 321338d4..47f4a88b 100644 --- a/os/src/fs/inode.rs +++ b/os/src/fs/inode.rs @@ -83,9 +83,11 @@ impl OpenFlags { } pub fn open_file(name: &str, flags: OpenFlags) -> Option> { + println!("open_file :1"); let (readable, writable) = flags.read_write(); if flags.contains(OpenFlags::CREATE) { if let Some(inode) = ROOT_INODE.find(name) { + println!("open_file :2"); // clear size inode.clear(); Some(Arc::new(OSInode::new(readable, writable, inode))) diff --git a/os/src/sync/up.rs b/os/src/sync/up.rs index 6c7a0f4a..14cb81bf 100644 --- a/os/src/sync/up.rs +++ b/os/src/sync/up.rs @@ -1,140 +1,23 @@ -use core::cell::{RefCell, RefMut, UnsafeCell}; -use core::ops::{Deref, DerefMut}; -use lazy_static::*; +pub use ksync::{UPIntrFreeCell, UPIntrRefMut}; use riscv::register::sstatus; -/* -/// Wrap a static data structure inside it so that we are -/// able to access it without any `unsafe`. -/// -/// We should only use it in uniprocessor. -/// -/// In order to get mutable reference of inner data, call -/// `exclusive_access`. -pub struct UPSafeCell { - /// inner data - inner: RefCell, +// extern "C" { +// fn swap_and_disable_intr() -> bool; +// fn enable_intr(); +// } + +#[no_mangle] +extern "C" fn swap_and_disable_intr() -> bool { + let sie = sstatus::read().sie(); + unsafe { + sstatus::clear_sie(); + } + sie } -unsafe impl Sync for UPSafeCell {} - -impl UPSafeCell { - /// User is responsible to guarantee that inner struct is only used in - /// uniprocessor. - pub unsafe fn new(value: T) -> Self { - Self { - inner: RefCell::new(value), - } +#[no_mangle] +extern "C" fn enable_intr() { + unsafe { + sstatus::set_sie(); } - /// Panic if the data has been borrowed. - pub fn exclusive_access(&self) -> RefMut<'_, T> { - 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() - } -} +} \ No newline at end of file diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 7d5b67ab..3c3dafdb 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -55,8 +55,11 @@ pub fn sys_exec(path: *const u8, mut args: *const usize) -> isize { args = args.add(1); } } + println!("sys_exec :1"); if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) { + println!("sys_exec :2"); let all_data = app_inode.read_all(); + println!("sys_exec :3"); let process = current_process(); let argc = args_vec.len(); process.exec(all_data.as_slice(), args_vec); diff --git a/user/src/bin/usertests2.rs b/user/src/bin/usertests2.rs new file mode 100644 index 00000000..b9ee9dfc --- /dev/null +++ b/user/src/bin/usertests2.rs @@ -0,0 +1,55 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +const TESTS: &[&str] = &[ + "hello_world\0", + "yield\0", + "exit\0", + "forktest_simple\0", + "forktest\0", + "forktest2\0", + "forktree\0", + "filetest_simple\0", + "cat\0", + "pipetest\0", + "mpsc_sem\0", + "phil_din_mutex\0", + "adder_mutex_spin\0", + "condsync_sem\0", + "condsync_condvar\0", + "threads\0", + "threads_arg\0", +]; + +const TEST_NUM: usize = TESTS.len(); + +use user_lib::{exec, fork, waitpid}; + +#[no_mangle] +pub fn main() -> i32 { + let mut pids = [0; TEST_NUM]; + for (i, &test) in TESTS.iter().enumerate() { + println!("Usertests: Running {}", test); + let pid = fork(); + if pid == 0 { + exec(&*test, &[core::ptr::null::()]); + panic!("unreachable!"); + } else { + pids[i] = pid; + } + } + let mut xstate: i32 = Default::default(); + for (i, &test) in TESTS.iter().enumerate() { + let wait_pid = waitpid(pids[i] as usize, &mut xstate); + assert_eq!(pids[i], wait_pid); + println!( + "\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", + test, pids[i], xstate + ); + } + println!("Basic usertests passed!"); + 0 +}