mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-21 17:06:25 +04:00
use ksync for both easy-fs and os
This commit is contained in:
parent
c1e30a1bf6
commit
5b38d93763
@ -9,6 +9,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
clap = "2.33.3"
|
||||
easy-fs = { path = "../easy-fs" }
|
||||
ksync = { path = "../ksync" }
|
||||
rand = "0.8.0"
|
||||
|
||||
# [features]
|
||||
|
@ -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() {}
|
@ -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]
|
||||
|
@ -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<dyn BlockDevice>, 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;
|
||||
|
@ -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<u8>,
|
||||
@ -77,7 +77,7 @@ impl Drop for BlockCache {
|
||||
const BLOCK_CACHE_SIZE: usize = 16;
|
||||
|
||||
pub struct BlockCacheManager {
|
||||
queue: VecDeque<(usize, Arc<Mutex<BlockCache>>)>,
|
||||
queue: VecDeque<(usize, Arc<UPIntrFreeCell<BlockCache>>)>,
|
||||
}
|
||||
|
||||
impl BlockCacheManager {
|
||||
@ -91,7 +91,7 @@ impl BlockCacheManager {
|
||||
&mut self,
|
||||
block_id: usize,
|
||||
block_device: Arc<dyn BlockDevice>,
|
||||
) -> Arc<Mutex<BlockCache>> {
|
||||
) -> Arc<UPIntrFreeCell<BlockCache>> {
|
||||
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<BlockCacheManager> =
|
||||
Mutex::new(BlockCacheManager::new());
|
||||
pub static ref BLOCK_CACHE_MANAGER: UPIntrFreeCell<BlockCacheManager> =
|
||||
unsafe { UPIntrFreeCell::new(BlockCacheManager::new()) };
|
||||
}
|
||||
|
||||
pub fn get_block_cache(
|
||||
block_id: usize,
|
||||
block_device: Arc<dyn BlockDevice>,
|
||||
) -> Arc<Mutex<BlockCache>> {
|
||||
) -> Arc<UPIntrFreeCell<BlockCache>> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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<dyn BlockDevice>,
|
||||
@ -21,7 +21,7 @@ impl EasyFileSystem {
|
||||
block_device: Arc<dyn BlockDevice>,
|
||||
total_blocks: u32,
|
||||
inode_bitmap_blocks: u32,
|
||||
) -> Arc<Mutex<Self>> {
|
||||
) -> Arc<UPIntrFreeCell<Self>> {
|
||||
// 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<dyn BlockDevice>) -> Arc<Mutex<Self>> {
|
||||
pub fn open(block_device: Arc<dyn BlockDevice>) -> Arc<UPIntrFreeCell<Self>> {
|
||||
// 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<Mutex<Self>>) -> Inode {
|
||||
let block_device = Arc::clone(&efs.lock().block_device);
|
||||
pub fn root_inode(efs: &Arc<UPIntrFreeCell<Self>>) -> 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;
|
||||
|
@ -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];
|
||||
|
@ -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<Mutex<EasyFileSystem>>,
|
||||
fs: Arc<UPIntrFreeCell<EasyFileSystem>>,
|
||||
block_device: Arc<dyn BlockDevice>,
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ impl Inode {
|
||||
pub fn new(
|
||||
block_id: u32,
|
||||
block_offset: usize,
|
||||
fs: Arc<Mutex<EasyFileSystem>>,
|
||||
fs: Arc<UPIntrFreeCell<EasyFileSystem>>,
|
||||
block_device: Arc<dyn BlockDevice>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -32,13 +32,13 @@ impl Inode {
|
||||
|
||||
fn read_disk_inode<V>(&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<V>(&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<Arc<Inode>> {
|
||||
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<EasyFileSystem>,
|
||||
fs: &mut UPIntrRefMut<EasyFileSystem>,
|
||||
) {
|
||||
if new_size < disk_inode.size {
|
||||
return;
|
||||
@ -92,7 +92,7 @@ impl Inode {
|
||||
}
|
||||
|
||||
pub fn create(&self, name: &str) -> Option<Arc<Inode>> {
|
||||
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<String> {
|
||||
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<String> = 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);
|
||||
|
9
ksync/Cargo.toml
Normal file
9
ksync/Cargo.toml
Normal file
@ -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"] }
|
143
ksync/src/lib.rs
Normal file
143
ksync/src/lib.rs
Normal file
@ -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<T> {
|
||||
/// inner data
|
||||
inner: RefCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPSafeCell<T> {}
|
||||
|
||||
impl<T> UPSafeCell<T> {
|
||||
/// 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<T> {
|
||||
inner: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPSafeCellRaw<T> {}
|
||||
|
||||
impl<T> UPSafeCellRaw<T> {
|
||||
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<IntrMaskingInfo> =
|
||||
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<T> {
|
||||
/// inner data
|
||||
inner: RefCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPIntrFreeCell<T> {}
|
||||
|
||||
pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
|
||||
|
||||
impl<T> UPIntrFreeCell<T> {
|
||||
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<F, V>(&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()
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -83,9 +83,11 @@ impl OpenFlags {
|
||||
}
|
||||
|
||||
pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
|
||||
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)))
|
||||
|
@ -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<T> {
|
||||
/// inner data
|
||||
inner: RefCell<T>,
|
||||
// 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<T> Sync for UPSafeCell<T> {}
|
||||
|
||||
impl<T> UPSafeCell<T> {
|
||||
/// 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<T> {
|
||||
inner: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPSafeCellRaw<T> {}
|
||||
|
||||
impl<T> UPSafeCellRaw<T> {
|
||||
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<IntrMaskingInfo> =
|
||||
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<T> {
|
||||
/// inner data
|
||||
inner: RefCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for UPIntrFreeCell<T> {}
|
||||
|
||||
pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
|
||||
|
||||
impl<T> UPIntrFreeCell<T> {
|
||||
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<F, V>(&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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
55
user/src/bin/usertests2.rs
Normal file
55
user/src/bin/usertests2.rs
Normal file
@ -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::<u8>()]);
|
||||
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
|
||||
}
|
Loading…
Reference in New Issue
Block a user