use ksync for both easy-fs and os

This commit is contained in:
Yifan Wu 2023-02-10 18:11:46 +08:00
parent c1e30a1bf6
commit 5b38d93763
15 changed files with 297 additions and 187 deletions

View File

@ -9,6 +9,7 @@ edition = "2018"
[dependencies] [dependencies]
clap = "2.33.3" clap = "2.33.3"
easy-fs = { path = "../easy-fs" } easy-fs = { path = "../easy-fs" }
ksync = { path = "../ksync" }
rand = "0.8.0" rand = "0.8.0"
# [features] # [features]

View File

@ -153,3 +153,16 @@ fn efs_test() -> std::io::Result<()> {
Ok(()) 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() {}

View File

@ -7,7 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
spin = "0.7.0" ksync = { path = "../ksync" }
lazy_static = { version = "1.4.0", features = ["spin_no_std"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
[profile.release] [profile.release]

View File

@ -31,7 +31,7 @@ impl Bitmap {
block_id + self.start_block_id as usize, block_id + self.start_block_id as usize,
Arc::clone(block_device), Arc::clone(block_device),
) )
.lock() .exclusive_access()
.modify(0, |bitmap_block: &mut BitmapBlock| { .modify(0, |bitmap_block: &mut BitmapBlock| {
if let Some((bits64_pos, inner_pos)) = bitmap_block if let Some((bits64_pos, inner_pos)) = bitmap_block
.iter() .iter()
@ -56,7 +56,7 @@ impl Bitmap {
pub fn dealloc(&self, block_device: &Arc<dyn BlockDevice>, bit: usize) { pub fn dealloc(&self, block_device: &Arc<dyn BlockDevice>, bit: usize) {
let (block_pos, bits64_pos, inner_pos) = decomposition(bit); let (block_pos, bits64_pos, inner_pos) = decomposition(bit);
get_block_cache(block_pos + self.start_block_id, Arc::clone(block_device)) get_block_cache(block_pos + self.start_block_id, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |bitmap_block: &mut BitmapBlock| { .modify(0, |bitmap_block: &mut BitmapBlock| {
assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0); assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0);
bitmap_block[bits64_pos] -= 1u64 << inner_pos; bitmap_block[bits64_pos] -= 1u64 << inner_pos;

View File

@ -4,7 +4,7 @@ use alloc::sync::Arc;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use lazy_static::*; use lazy_static::*;
use spin::Mutex; use ksync::UPIntrFreeCell;
pub struct BlockCache { pub struct BlockCache {
cache: Vec<u8>, cache: Vec<u8>,
@ -77,7 +77,7 @@ impl Drop for BlockCache {
const BLOCK_CACHE_SIZE: usize = 16; const BLOCK_CACHE_SIZE: usize = 16;
pub struct BlockCacheManager { pub struct BlockCacheManager {
queue: VecDeque<(usize, Arc<Mutex<BlockCache>>)>, queue: VecDeque<(usize, Arc<UPIntrFreeCell<BlockCache>>)>,
} }
impl BlockCacheManager { impl BlockCacheManager {
@ -91,7 +91,7 @@ impl BlockCacheManager {
&mut self, &mut self,
block_id: usize, block_id: usize,
block_device: Arc<dyn BlockDevice>, block_device: Arc<dyn BlockDevice>,
) -> Arc<Mutex<BlockCache>> { ) -> Arc<UPIntrFreeCell<BlockCache>> {
if let Some(pair) = self.queue.iter().find(|pair| pair.0 == block_id) { if let Some(pair) = self.queue.iter().find(|pair| pair.0 == block_id) {
Arc::clone(&pair.1) Arc::clone(&pair.1)
} else { } else {
@ -110,10 +110,10 @@ impl BlockCacheManager {
} }
} }
// load block into mem and push back // 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, block_id,
Arc::clone(&block_device), Arc::clone(&block_device),
))); ))});
self.queue.push_back((block_id, Arc::clone(&block_cache))); self.queue.push_back((block_id, Arc::clone(&block_cache)));
block_cache block_cache
} }
@ -121,22 +121,22 @@ impl BlockCacheManager {
} }
lazy_static! { lazy_static! {
pub static ref BLOCK_CACHE_MANAGER: Mutex<BlockCacheManager> = pub static ref BLOCK_CACHE_MANAGER: UPIntrFreeCell<BlockCacheManager> =
Mutex::new(BlockCacheManager::new()); unsafe { UPIntrFreeCell::new(BlockCacheManager::new()) };
} }
pub fn get_block_cache( pub fn get_block_cache(
block_id: usize, block_id: usize,
block_device: Arc<dyn BlockDevice>, block_device: Arc<dyn BlockDevice>,
) -> Arc<Mutex<BlockCache>> { ) -> Arc<UPIntrFreeCell<BlockCache>> {
BLOCK_CACHE_MANAGER BLOCK_CACHE_MANAGER
.lock() .exclusive_access()
.get_block_cache(block_id, block_device) .get_block_cache(block_id, block_device)
} }
pub fn block_cache_sync_all() { 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() { for (_, cache) in manager.queue.iter() {
cache.lock().sync(); cache.exclusive_access().sync();
} }
} }

View File

@ -4,7 +4,7 @@ use super::{
}; };
use crate::BLOCK_SZ; use crate::BLOCK_SZ;
use alloc::sync::Arc; use alloc::sync::Arc;
use spin::Mutex; use ksync::UPIntrFreeCell;
pub struct EasyFileSystem { pub struct EasyFileSystem {
pub block_device: Arc<dyn BlockDevice>, pub block_device: Arc<dyn BlockDevice>,
@ -21,7 +21,7 @@ impl EasyFileSystem {
block_device: Arc<dyn BlockDevice>, block_device: Arc<dyn BlockDevice>,
total_blocks: u32, total_blocks: u32,
inode_bitmap_blocks: u32, inode_bitmap_blocks: u32,
) -> Arc<Mutex<Self>> { ) -> Arc<UPIntrFreeCell<Self>> {
// calculate block size of areas & create bitmaps // calculate block size of areas & create bitmaps
let inode_bitmap = Bitmap::new(1, inode_bitmap_blocks as usize); let inode_bitmap = Bitmap::new(1, inode_bitmap_blocks as usize);
let inode_num = inode_bitmap.maximum(); let inode_num = inode_bitmap.maximum();
@ -45,7 +45,7 @@ impl EasyFileSystem {
// clear all blocks // clear all blocks
for i in 0..total_blocks { for i in 0..total_blocks {
get_block_cache(i as usize, Arc::clone(&block_device)) get_block_cache(i as usize, Arc::clone(&block_device))
.lock() .exclusive_access()
.modify(0, |data_block: &mut DataBlock| { .modify(0, |data_block: &mut DataBlock| {
for byte in data_block.iter_mut() { for byte in data_block.iter_mut() {
*byte = 0; *byte = 0;
@ -53,7 +53,7 @@ impl EasyFileSystem {
}); });
} }
// initialize SuperBlock // initialize SuperBlock
get_block_cache(0, Arc::clone(&block_device)).lock().modify( get_block_cache(0, Arc::clone(&block_device)).exclusive_access().modify(
0, 0,
|super_block: &mut SuperBlock| { |super_block: &mut SuperBlock| {
super_block.initialize( super_block.initialize(
@ -70,18 +70,18 @@ impl EasyFileSystem {
assert_eq!(efs.alloc_inode(), 0); assert_eq!(efs.alloc_inode(), 0);
let (root_inode_block_id, root_inode_offset) = efs.get_disk_inode_pos(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)) get_block_cache(root_inode_block_id as usize, Arc::clone(&block_device))
.lock() .exclusive_access()
.modify(root_inode_offset, |disk_inode: &mut DiskInode| { .modify(root_inode_offset, |disk_inode: &mut DiskInode| {
disk_inode.initialize(DiskInodeType::Directory); disk_inode.initialize(DiskInodeType::Directory);
}); });
block_cache_sync_all(); 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 // read SuperBlock
get_block_cache(0, Arc::clone(&block_device)) get_block_cache(0, Arc::clone(&block_device))
.lock() .exclusive_access()
.read(0, |super_block: &SuperBlock| { .read(0, |super_block: &SuperBlock| {
assert!(super_block.is_valid(), "Error loading EFS!"); assert!(super_block.is_valid(), "Error loading EFS!");
let inode_total_blocks = let inode_total_blocks =
@ -96,14 +96,14 @@ impl EasyFileSystem {
inode_area_start_block: 1 + super_block.inode_bitmap_blocks, inode_area_start_block: 1 + super_block.inode_bitmap_blocks,
data_area_start_block: 1 + inode_total_blocks + super_block.data_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 { pub fn root_inode(efs: &Arc<UPIntrFreeCell<Self>>) -> Inode {
let block_device = Arc::clone(&efs.lock().block_device); let block_device = Arc::clone(&efs.exclusive_access().block_device);
// acquire efs lock temporarily // 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 // release efs lock
Inode::new(block_id, block_offset, Arc::clone(efs), block_device) 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) { pub fn dealloc_data(&mut self, block_id: u32) {
get_block_cache(block_id as usize, Arc::clone(&self.block_device)) get_block_cache(block_id as usize, Arc::clone(&self.block_device))
.lock() .exclusive_access()
.modify(0, |data_block: &mut DataBlock| { .modify(0, |data_block: &mut DataBlock| {
data_block.iter_mut().for_each(|p| { data_block.iter_mut().for_each(|p| {
*p = 0; *p = 0;

View File

@ -126,19 +126,19 @@ impl DiskInode {
self.direct[inner_id] self.direct[inner_id]
} else if inner_id < INDIRECT1_BOUND { } else if inner_id < INDIRECT1_BOUND {
get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) get_block_cache(self.indirect1 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.read(0, |indirect_block: &IndirectBlock| { .read(0, |indirect_block: &IndirectBlock| {
indirect_block[inner_id - INODE_DIRECT_COUNT] indirect_block[inner_id - INODE_DIRECT_COUNT]
}) })
} else { } else {
let last = inner_id - INDIRECT1_BOUND; let last = inner_id - INDIRECT1_BOUND;
let indirect1 = get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) let indirect1 = get_block_cache(self.indirect2 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.read(0, |indirect2: &IndirectBlock| { .read(0, |indirect2: &IndirectBlock| {
indirect2[last / INODE_INDIRECT1_COUNT] indirect2[last / INODE_INDIRECT1_COUNT]
}); });
get_block_cache(indirect1 as usize, Arc::clone(block_device)) get_block_cache(indirect1 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.read(0, |indirect1: &IndirectBlock| { .read(0, |indirect1: &IndirectBlock| {
indirect1[last % INODE_INDIRECT1_COUNT] indirect1[last % INODE_INDIRECT1_COUNT]
}) })
@ -171,7 +171,7 @@ impl DiskInode {
} }
// fill indirect1 // fill indirect1
get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) get_block_cache(self.indirect1 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect1: &mut IndirectBlock| { .modify(0, |indirect1: &mut IndirectBlock| {
while current_blocks < total_blocks.min(INODE_INDIRECT1_COUNT as u32) { while current_blocks < total_blocks.min(INODE_INDIRECT1_COUNT as u32) {
indirect1[current_blocks as usize] = new_blocks.next().unwrap(); indirect1[current_blocks as usize] = new_blocks.next().unwrap();
@ -195,7 +195,7 @@ impl DiskInode {
let b1 = total_blocks as usize % INODE_INDIRECT1_COUNT; let b1 = total_blocks as usize % INODE_INDIRECT1_COUNT;
// alloc low-level indirect1 // alloc low-level indirect1
get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) get_block_cache(self.indirect2 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect2: &mut IndirectBlock| { .modify(0, |indirect2: &mut IndirectBlock| {
while (a0 < a1) || (a0 == a1 && b0 < b1) { while (a0 < a1) || (a0 == a1 && b0 < b1) {
if b0 == 0 { if b0 == 0 {
@ -203,7 +203,7 @@ impl DiskInode {
} }
// fill current // fill current
get_block_cache(indirect2[a0] as usize, Arc::clone(block_device)) get_block_cache(indirect2[a0] as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect1: &mut IndirectBlock| { .modify(0, |indirect1: &mut IndirectBlock| {
indirect1[b0] = new_blocks.next().unwrap(); indirect1[b0] = new_blocks.next().unwrap();
}); });
@ -241,7 +241,7 @@ impl DiskInode {
} }
// indirect1 // indirect1
get_block_cache(self.indirect1 as usize, Arc::clone(block_device)) get_block_cache(self.indirect1 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect1: &mut IndirectBlock| { .modify(0, |indirect1: &mut IndirectBlock| {
while current_blocks < data_blocks.min(INODE_INDIRECT1_COUNT) { while current_blocks < data_blocks.min(INODE_INDIRECT1_COUNT) {
v.push(indirect1[current_blocks]); v.push(indirect1[current_blocks]);
@ -262,13 +262,13 @@ impl DiskInode {
let a1 = data_blocks / INODE_INDIRECT1_COUNT; let a1 = data_blocks / INODE_INDIRECT1_COUNT;
let b1 = data_blocks % INODE_INDIRECT1_COUNT; let b1 = data_blocks % INODE_INDIRECT1_COUNT;
get_block_cache(self.indirect2 as usize, Arc::clone(block_device)) get_block_cache(self.indirect2 as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect2: &mut IndirectBlock| { .modify(0, |indirect2: &mut IndirectBlock| {
// full indirect1 blocks // full indirect1 blocks
for entry in indirect2.iter_mut().take(a1) { for entry in indirect2.iter_mut().take(a1) {
v.push(*entry); v.push(*entry);
get_block_cache(*entry as usize, Arc::clone(block_device)) get_block_cache(*entry as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect1: &mut IndirectBlock| { .modify(0, |indirect1: &mut IndirectBlock| {
for entry in indirect1.iter() { for entry in indirect1.iter() {
v.push(*entry); v.push(*entry);
@ -279,7 +279,7 @@ impl DiskInode {
if b1 > 0 { if b1 > 0 {
v.push(indirect2[a1]); v.push(indirect2[a1]);
get_block_cache(indirect2[a1] as usize, Arc::clone(block_device)) get_block_cache(indirect2[a1] as usize, Arc::clone(block_device))
.lock() .exclusive_access()
.modify(0, |indirect1: &mut IndirectBlock| { .modify(0, |indirect1: &mut IndirectBlock| {
for entry in indirect1.iter().take(b1) { for entry in indirect1.iter().take(b1) {
v.push(*entry); v.push(*entry);
@ -315,7 +315,7 @@ impl DiskInode {
self.get_block_id(start_block as u32, block_device) as usize, self.get_block_id(start_block as u32, block_device) as usize,
Arc::clone(block_device), Arc::clone(block_device),
) )
.lock() .exclusive_access()
.read(0, |data_block: &DataBlock| { .read(0, |data_block: &DataBlock| {
let src = &data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_read_size]; let src = &data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_read_size];
dst.copy_from_slice(src); dst.copy_from_slice(src);
@ -352,7 +352,7 @@ impl DiskInode {
self.get_block_id(start_block as u32, block_device) as usize, self.get_block_id(start_block as u32, block_device) as usize,
Arc::clone(block_device), Arc::clone(block_device),
) )
.lock() .exclusive_access()
.modify(0, |data_block: &mut DataBlock| { .modify(0, |data_block: &mut DataBlock| {
let src = &buf[write_size..write_size + block_write_size]; let src = &buf[write_size..write_size + block_write_size];
let dst = &mut data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_write_size]; let dst = &mut data_block[start % BLOCK_SZ..start % BLOCK_SZ + block_write_size];

View File

@ -5,12 +5,12 @@ use super::{
use alloc::string::String; use alloc::string::String;
use alloc::sync::Arc; use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use spin::{Mutex, MutexGuard}; use ksync::{UPIntrFreeCell, UPIntrRefMut};
pub struct Inode { pub struct Inode {
block_id: usize, block_id: usize,
block_offset: usize, block_offset: usize,
fs: Arc<Mutex<EasyFileSystem>>, fs: Arc<UPIntrFreeCell<EasyFileSystem>>,
block_device: Arc<dyn BlockDevice>, block_device: Arc<dyn BlockDevice>,
} }
@ -19,7 +19,7 @@ impl Inode {
pub fn new( pub fn new(
block_id: u32, block_id: u32,
block_offset: usize, block_offset: usize,
fs: Arc<Mutex<EasyFileSystem>>, fs: Arc<UPIntrFreeCell<EasyFileSystem>>,
block_device: Arc<dyn BlockDevice>, block_device: Arc<dyn BlockDevice>,
) -> Self { ) -> Self {
Self { Self {
@ -32,13 +32,13 @@ impl Inode {
fn read_disk_inode<V>(&self, f: impl FnOnce(&DiskInode) -> V) -> V { fn read_disk_inode<V>(&self, f: impl FnOnce(&DiskInode) -> V) -> V {
get_block_cache(self.block_id, Arc::clone(&self.block_device)) get_block_cache(self.block_id, Arc::clone(&self.block_device))
.lock() .exclusive_access()
.read(self.block_offset, f) .read(self.block_offset, f)
} }
fn modify_disk_inode<V>(&self, f: impl FnOnce(&mut DiskInode) -> V) -> V { fn modify_disk_inode<V>(&self, f: impl FnOnce(&mut DiskInode) -> V) -> V {
get_block_cache(self.block_id, Arc::clone(&self.block_device)) get_block_cache(self.block_id, Arc::clone(&self.block_device))
.lock() .exclusive_access()
.modify(self.block_offset, f) .modify(self.block_offset, f)
} }
@ -60,7 +60,7 @@ impl Inode {
} }
pub fn find(&self, name: &str) -> Option<Arc<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.read_disk_inode(|disk_inode| {
self.find_inode_id(name, disk_inode).map(|inode_id| { self.find_inode_id(name, disk_inode).map(|inode_id| {
let (block_id, block_offset) = fs.get_disk_inode_pos(inode_id); let (block_id, block_offset) = fs.get_disk_inode_pos(inode_id);
@ -78,7 +78,7 @@ impl Inode {
&self, &self,
new_size: u32, new_size: u32,
disk_inode: &mut DiskInode, disk_inode: &mut DiskInode,
fs: &mut MutexGuard<EasyFileSystem>, fs: &mut UPIntrRefMut<EasyFileSystem>,
) { ) {
if new_size < disk_inode.size { if new_size < disk_inode.size {
return; return;
@ -92,7 +92,7 @@ impl Inode {
} }
pub fn create(&self, name: &str) -> Option<Arc<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| { let op = |root_inode: &mut DiskInode| {
// assert it is a directory // assert it is a directory
assert!(root_inode.is_dir()); assert!(root_inode.is_dir());
@ -108,7 +108,7 @@ impl Inode {
// initialize inode // initialize inode
let (new_inode_block_id, new_inode_block_offset) = fs.get_disk_inode_pos(new_inode_id); 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)) 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| { .modify(new_inode_block_offset, |new_inode: &mut DiskInode| {
new_inode.initialize(DiskInodeType::File); new_inode.initialize(DiskInodeType::File);
}); });
@ -140,7 +140,7 @@ impl Inode {
} }
pub fn ls(&self) -> Vec<String> { pub fn ls(&self) -> Vec<String> {
let _fs = self.fs.lock(); let _fs = self.fs.exclusive_access();
self.read_disk_inode(|disk_inode| { self.read_disk_inode(|disk_inode| {
let file_count = (disk_inode.size as usize) / DIRENT_SZ; let file_count = (disk_inode.size as usize) / DIRENT_SZ;
let mut v: Vec<String> = Vec::new(); let mut v: Vec<String> = Vec::new();
@ -157,12 +157,12 @@ impl Inode {
} }
pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize { 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)) 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 { 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| { let size = self.modify_disk_inode(|disk_inode| {
self.increase_size((offset + buf.len()) as u32, disk_inode, &mut fs); self.increase_size((offset + buf.len()) as u32, disk_inode, &mut fs);
disk_inode.write_at(offset, buf, &self.block_device) disk_inode.write_at(offset, buf, &self.block_device)
@ -172,7 +172,7 @@ impl Inode {
} }
pub fn clear(&self) { pub fn clear(&self) {
let mut fs = self.fs.lock(); let mut fs = self.fs.exclusive_access();
self.modify_disk_inode(|disk_inode| { self.modify_disk_inode(|disk_inode| {
let size = disk_inode.size; let size = disk_inode.size;
let data_blocks_dealloc = disk_inode.clear_size(&self.block_device); let data_blocks_dealloc = disk_inode.clear_size(&self.block_device);

9
ksync/Cargo.toml Normal file
View 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
View 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()
}
}

View File

@ -18,6 +18,7 @@ lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "3f4
easy-fs = { path = "../easy-fs" } easy-fs = { path = "../easy-fs" }
embedded-graphics = "0.7.1" embedded-graphics = "0.7.1"
tinybmp = "0.3.1" tinybmp = "0.3.1"
ksync = { path = "../ksync" }
[profile.release] [profile.release]
debug = true debug = true

View File

@ -83,9 +83,11 @@ impl OpenFlags {
} }
pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> { pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
println!("open_file :1");
let (readable, writable) = flags.read_write(); let (readable, writable) = flags.read_write();
if flags.contains(OpenFlags::CREATE) { if flags.contains(OpenFlags::CREATE) {
if let Some(inode) = ROOT_INODE.find(name) { if let Some(inode) = ROOT_INODE.find(name) {
println!("open_file :2");
// clear size // clear size
inode.clear(); inode.clear();
Some(Arc::new(OSInode::new(readable, writable, inode))) Some(Arc::new(OSInode::new(readable, writable, inode)))

View File

@ -1,140 +1,23 @@
use core::cell::{RefCell, RefMut, UnsafeCell}; pub use ksync::{UPIntrFreeCell, UPIntrRefMut};
use core::ops::{Deref, DerefMut};
use lazy_static::*;
use riscv::register::sstatus; use riscv::register::sstatus;
/* // extern "C" {
/// Wrap a static data structure inside it so that we are // fn swap_and_disable_intr() -> bool;
/// able to access it without any `unsafe`. // fn enable_intr();
/// // }
/// 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> {} #[no_mangle]
extern "C" fn swap_and_disable_intr() -> bool {
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()
}
}
*/
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(); let sie = sstatus::read().sie();
unsafe { unsafe {
sstatus::clear_sie(); sstatus::clear_sie();
} }
if self.nested_level == 0 { sie
self.sie_before_masking = sie;
}
self.nested_level += 1;
} }
pub fn exit(&mut self) { #[no_mangle]
self.nested_level -= 1; extern "C" fn enable_intr() {
if self.nested_level == 0 && self.sie_before_masking {
unsafe { unsafe {
sstatus::set_sie(); 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()
}
}

View File

@ -55,8 +55,11 @@ pub fn sys_exec(path: *const u8, mut args: *const usize) -> isize {
args = args.add(1); args = args.add(1);
} }
} }
println!("sys_exec :1");
if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) { if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) {
println!("sys_exec :2");
let all_data = app_inode.read_all(); let all_data = app_inode.read_all();
println!("sys_exec :3");
let process = current_process(); let process = current_process();
let argc = args_vec.len(); let argc = args_vec.len();
process.exec(all_data.as_slice(), args_vec); process.exec(all_data.as_slice(), args_vec);

View 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
}