Rm spin::Mutex except for easy-fs & add new test huge_write & flush cache to disk after a write transaction
parent
01098eb113
commit
315e61da1a
@ -0,0 +1,3 @@
|
||||
mod up;
|
||||
|
||||
pub use up::UPSafeCell;
|
@ -0,0 +1,27 @@
|
||||
use core::cell::{RefCell, RefMut};
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
@ -1,95 +1,90 @@
|
||||
use super::TaskControlBlock;
|
||||
use super::{TaskContext, TaskControlBlock};
|
||||
use alloc::sync::Arc;
|
||||
use core::cell::RefCell;
|
||||
use lazy_static::*;
|
||||
use super::{fetch_task, TaskStatus};
|
||||
use super::__switch;
|
||||
use crate::trap::TrapContext;
|
||||
use crate::sync::UPSafeCell;
|
||||
|
||||
pub struct Processor {
|
||||
inner: RefCell<ProcessorInner>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Processor {}
|
||||
|
||||
struct ProcessorInner {
|
||||
current: Option<Arc<TaskControlBlock>>,
|
||||
idle_task_cx_ptr: usize,
|
||||
idle_task_cx: TaskContext,
|
||||
}
|
||||
|
||||
impl Processor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: RefCell::new(ProcessorInner {
|
||||
current: None,
|
||||
idle_task_cx_ptr: 0,
|
||||
}),
|
||||
current: None,
|
||||
idle_task_cx: TaskContext::zero_init(),
|
||||
}
|
||||
}
|
||||
fn get_idle_task_cx_ptr2(&self) -> *const usize {
|
||||
let inner = self.inner.borrow();
|
||||
&inner.idle_task_cx_ptr as *const usize
|
||||
fn get_idle_task_cx_ptr(&mut self) -> *mut TaskContext {
|
||||
&mut self.idle_task_cx as *mut _
|
||||
}
|
||||
pub fn run(&self) {
|
||||
loop {
|
||||
if let Some(task) = fetch_task() {
|
||||
let idle_task_cx_ptr2 = self.get_idle_task_cx_ptr2();
|
||||
// acquire
|
||||
let mut task_inner = task.acquire_inner_lock();
|
||||
let next_task_cx_ptr2 = task_inner.get_task_cx_ptr2();
|
||||
task_inner.task_status = TaskStatus::Running;
|
||||
drop(task_inner);
|
||||
// release
|
||||
self.inner.borrow_mut().current = Some(task);
|
||||
unsafe {
|
||||
__switch(
|
||||
idle_task_cx_ptr2,
|
||||
next_task_cx_ptr2,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn take_current(&self) -> Option<Arc<TaskControlBlock>> {
|
||||
self.inner.borrow_mut().current.take()
|
||||
pub fn take_current(&mut self) -> Option<Arc<TaskControlBlock>> {
|
||||
self.current.take()
|
||||
}
|
||||
pub fn current(&self) -> Option<Arc<TaskControlBlock>> {
|
||||
self.inner.borrow().current.as_ref().map(|task| Arc::clone(task))
|
||||
self.current.as_ref().map(|task| Arc::clone(task))
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PROCESSOR: Processor = Processor::new();
|
||||
pub static ref PROCESSOR: UPSafeCell<Processor> = unsafe {
|
||||
UPSafeCell::new(Processor::new())
|
||||
};
|
||||
}
|
||||
|
||||
pub fn run_tasks() {
|
||||
PROCESSOR.run();
|
||||
loop {
|
||||
let mut processor = PROCESSOR.exclusive_access();
|
||||
if let Some(task) = fetch_task() {
|
||||
let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
|
||||
// access coming task TCB exclusively
|
||||
let mut task_inner = task.inner_exclusive_access();
|
||||
let next_task_cx_ptr = &task_inner.task_cx as *const TaskContext;
|
||||
task_inner.task_status = TaskStatus::Running;
|
||||
drop(task_inner);
|
||||
// release coming task TCB manually
|
||||
processor.current = Some(task);
|
||||
// release processor manually
|
||||
drop(processor);
|
||||
unsafe {
|
||||
__switch(
|
||||
idle_task_cx_ptr,
|
||||
next_task_cx_ptr,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_current_task() -> Option<Arc<TaskControlBlock>> {
|
||||
PROCESSOR.take_current()
|
||||
PROCESSOR.exclusive_access().take_current()
|
||||
}
|
||||
|
||||
pub fn current_task() -> Option<Arc<TaskControlBlock>> {
|
||||
PROCESSOR.current()
|
||||
PROCESSOR.exclusive_access().current()
|
||||
}
|
||||
|
||||
pub fn current_user_token() -> usize {
|
||||
let task = current_task().unwrap();
|
||||
let token = task.acquire_inner_lock().get_user_token();
|
||||
let token = task.inner_exclusive_access().get_user_token();
|
||||
token
|
||||
}
|
||||
|
||||
pub fn current_trap_cx() -> &'static mut TrapContext {
|
||||
current_task().unwrap().acquire_inner_lock().get_trap_cx()
|
||||
current_task().unwrap().inner_exclusive_access().get_trap_cx()
|
||||
}
|
||||
|
||||
pub fn schedule(switched_task_cx_ptr2: *const usize) {
|
||||
let idle_task_cx_ptr2 = PROCESSOR.get_idle_task_cx_ptr2();
|
||||
pub fn schedule(switched_task_cx_ptr: *mut TaskContext) {
|
||||
let mut processor = PROCESSOR.exclusive_access();
|
||||
let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
|
||||
drop(processor);
|
||||
unsafe {
|
||||
__switch(
|
||||
switched_task_cx_ptr2,
|
||||
idle_task_cx_ptr2,
|
||||
switched_task_cx_ptr,
|
||||
idle_task_cx_ptr,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,34 @@
|
||||
.altmacro
|
||||
.macro SAVE_SN n
|
||||
sd s\n, (\n+1)*8(sp)
|
||||
sd s\n, (\n+2)*8(a0)
|
||||
.endm
|
||||
.macro LOAD_SN n
|
||||
ld s\n, (\n+1)*8(sp)
|
||||
ld s\n, (\n+2)*8(a1)
|
||||
.endm
|
||||
.section .text
|
||||
.globl __switch
|
||||
__switch:
|
||||
# __switch(
|
||||
# current_task_cx_ptr2: &*const TaskContext,
|
||||
# next_task_cx_ptr2: &*const TaskContext
|
||||
# current_task_cx_ptr: *mut TaskContext,
|
||||
# next_task_cx_ptr: *const TaskContext
|
||||
# )
|
||||
# push TaskContext to current sp and save its address to where a0 points to
|
||||
addi sp, sp, -13*8
|
||||
sd sp, 0(a0)
|
||||
# fill TaskContext with ra & s0-s11
|
||||
sd ra, 0(sp)
|
||||
# save kernel stack of current task
|
||||
sd sp, 8(a0)
|
||||
# save ra & s0~s11 of current execution
|
||||
sd ra, 0(a0)
|
||||
.set n, 0
|
||||
.rept 12
|
||||
SAVE_SN %n
|
||||
.set n, n + 1
|
||||
.endr
|
||||
# ready for loading TaskContext a1 points to
|
||||
ld sp, 0(a1)
|
||||
# load registers in the TaskContext
|
||||
ld ra, 0(sp)
|
||||
# restore ra & s0~s11 of next execution
|
||||
ld ra, 0(a1)
|
||||
.set n, 0
|
||||
.rept 12
|
||||
LOAD_SN %n
|
||||
.set n, n + 1
|
||||
.endr
|
||||
# pop TaskContext
|
||||
addi sp, sp, 13*8
|
||||
# restore kernel stack of next task
|
||||
ld sp, 8(a1)
|
||||
ret
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
global_asm!(include_str!("switch.S"));
|
||||
|
||||
use super::TaskContext;
|
||||
|
||||
extern "C" {
|
||||
pub fn __switch(
|
||||
current_task_cx_ptr2: *const usize,
|
||||
next_task_cx_ptr2: *const usize
|
||||
current_task_cx_ptr: *mut TaskContext,
|
||||
next_task_cx_ptr: *const TaskContext
|
||||
);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
nightly-2021-01-30
|
||||
nightly-2021-07-15
|
||||
|
@ -0,0 +1,36 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
|
||||
use user_lib::{
|
||||
OpenFlags,
|
||||
open,
|
||||
close,
|
||||
write,
|
||||
get_time,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
let mut buffer = [0u8; 1024]; // 1KiB
|
||||
for i in 0..buffer.len() {
|
||||
buffer[i] = i as u8;
|
||||
}
|
||||
let f = open("testf", OpenFlags::CREATE | OpenFlags::WRONLY);
|
||||
if f < 0 {
|
||||
panic!("Open test file failed!");
|
||||
}
|
||||
let f = f as usize;
|
||||
let start = get_time();
|
||||
let size_mb = 5usize;
|
||||
for _ in 0..1024*size_mb {
|
||||
write(f, &buffer);
|
||||
}
|
||||
close(f);
|
||||
let time_ms = (get_time() - start) as usize;
|
||||
let speed_kbs = size_mb * 1000000 / time_ms;
|
||||
println!("time cost = {}ms, write speed = {}KiB/s", time_ms, speed_kbs);
|
||||
0
|
||||
}
|
Loading…
Reference in new issue