Remove Upsafecell; Fix kernel cannot be tested bug

This commit is contained in:
Yuke Peng
2023-03-05 23:32:25 -08:00
committed by Tate, Hongliang Tian
parent 54119e80bc
commit 4d3539f5ea
16 changed files with 119 additions and 164 deletions

View File

@ -18,7 +18,8 @@ cd -
# Copy the needed files into an ISO image.
mkdir -p target/iso_root
cp $KERNEL boot/limine/conf/limine.cfg target/iso_root
cp $KERNEL target/iso_root/jinux
cp boot/limine/conf/limine.cfg target/iso_root
cp target/limine/limine.sys target/iso_root
cp target/limine/limine-cd.bin target/iso_root
cp target/limine/limine-cd-efi.bin target/iso_root

View File

@ -1,6 +1,7 @@
use anyhow::anyhow;
use std::{
fs::OpenOptions,
ops::Add,
path::{Path, PathBuf},
process::{Command, ExitStatus},
time::Duration,
@ -23,7 +24,7 @@ const COMMON_ARGS: &[&str] = &[
const RUN_ARGS: &[&str] = &["-s"];
const TEST_ARGS: &[&str] = &[];
const TEST_TIMEOUT_SECS: u64 = 10;
const TEST_TIMEOUT_SECS: u64 = 30;
fn main() -> anyhow::Result<()> {
let mut args = std::env::args().skip(1);
let kernel_binary_path = {
@ -46,9 +47,14 @@ fn main() -> anyhow::Result<()> {
let kernel_iso_path = {
let a = kernel_binary_path.parent().unwrap();
a.join("jinux.iso")
let str = kernel_binary_path
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string();
a.join(str.add(".iso"))
};
// let bios = create_disk_images(&kernel_binary_path);
if no_boot {
println!("Created disk image at `{}`", kernel_iso_path.display());
@ -68,6 +74,7 @@ fn main() -> anyhow::Result<()> {
if binary_kind.is_test() {
args.append(&mut TEST_ARGS.to_vec());
run_cmd.args(args);
println!("running:{:?}", run_cmd);
let exit_status = run_test_command(run_cmd)?;
match exit_status.code() {
@ -77,6 +84,7 @@ fn main() -> anyhow::Result<()> {
} else {
args.append(&mut RUN_ARGS.to_vec());
run_cmd.args(args);
println!("running:{:?}", run_cmd);
let exit_status = run_cmd.status()?;
if !exit_status.success() {

View File

@ -6,12 +6,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
}
fn limine_build_script() -> Result<(), Box<dyn Error + Send + Sync>> {
// Get the name of the package.
let kernel_name = env::var("CARGO_PKG_NAME")?;
// Tell rustc to pass the linker script to the linker.
println!("cargo:rustc-link-arg-bin={kernel_name}=--script=boot/limine/conf/linker.ld");
// Have cargo rerun this script if the linker script or CARGO_PKG_ENV changes.
println!("cargo:rerun-if-changed=boot/limine/conf/linker.ld");
println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME");

View File

@ -35,7 +35,6 @@ pub(crate) mod x86_64_util;
pub use self::error::Error;
pub use self::prelude::Result;
pub(crate) use self::sync::up::UPSafeCell;
use alloc::vec::Vec;
use core::{mem, panic::PanicInfo};
pub use device::serial::receive_char;

View File

@ -1,19 +1,18 @@
use alloc::vec::Vec;
use spin::Mutex;
use crate::{config::PAGE_SIZE, vm::Paddr, UPSafeCell};
use crate::{config::PAGE_SIZE, vm::Paddr};
use super::address::PhysAddr;
use lazy_static::lazy_static;
lazy_static! {
static ref FRAME_ALLOCATOR: UPSafeCell<FreeListAllocator> = unsafe {
UPSafeCell::new(FreeListAllocator {
current: 0,
end: 0,
free_list: Vec::new(),
})
};
static ref FRAME_ALLOCATOR: Mutex<FreeListAllocator> = Mutex::new(FreeListAllocator {
current: 0,
end: 0,
free_list: Vec::new(),
});
}
trait FrameAllocator {
@ -62,7 +61,7 @@ impl PhysFrame {
pub fn alloc() -> Option<Self> {
FRAME_ALLOCATOR
.exclusive_access()
.lock()
.alloc()
.map(|pa| Self { start_pa: pa })
}
@ -73,7 +72,7 @@ impl PhysFrame {
}
pub fn dealloc(pa: usize) {
FRAME_ALLOCATOR.exclusive_access().dealloc(pa)
FRAME_ALLOCATOR.lock().dealloc(pa)
}
pub fn alloc_zero() -> Option<Self> {
@ -93,11 +92,11 @@ impl PhysFrame {
impl Drop for PhysFrame {
fn drop(&mut self) {
FRAME_ALLOCATOR.exclusive_access().dealloc(self.start_pa);
FRAME_ALLOCATOR.lock().dealloc(self.start_pa);
}
}
pub(crate) fn init(start: usize, size: usize) {
FRAME_ALLOCATOR.exclusive_access().current = start;
FRAME_ALLOCATOR.exclusive_access().end = start + size;
FRAME_ALLOCATOR.lock().current = start;
FRAME_ALLOCATOR.lock().end = start + size;
}

View File

@ -1,17 +1,23 @@
use super::{memory_set::MapArea, *};
use super::{
address::{PhysAddr, VirtAddr},
memory_set::MapArea,
PTFlags,
};
use crate::{
config::{ENTRY_COUNT, PAGE_SIZE, PHYS_OFFSET},
println,
vm::VmFrame,
*,
x86_64_util,
};
use ::log::info;
use alloc::{collections::BTreeMap, vec, vec::Vec};
use core::{fmt, panic};
use lazy_static::lazy_static;
use spin::Mutex;
lazy_static! {
pub(crate) static ref ALL_MAPPED_PTE: UPSafeCell<BTreeMap<usize, PageTableEntry>> =
unsafe { UPSafeCell::new(BTreeMap::new()) };
pub(crate) static ref ALL_MAPPED_PTE: Mutex<BTreeMap<usize, PageTableEntry>> =
Mutex::new(BTreeMap::new());
}
#[derive(Clone, Copy)]
@ -58,7 +64,7 @@ impl PageTable {
pub fn new() -> Self {
let root_frame = VmFrame::alloc_zero().unwrap();
let p4 = table_of(root_frame.start_pa());
let map_pte = ALL_MAPPED_PTE.exclusive_access();
let map_pte = ALL_MAPPED_PTE.lock();
for (index, pte) in map_pte.iter() {
p4[*index] = *pte;
}
@ -262,7 +268,7 @@ pub(crate) fn init() {
// Cancel mapping in lowest addresses.
p4[0].0 = 0;
// there is mapping where index is 1,2,3, so user may not use these value
let mut map_pte = ALL_MAPPED_PTE.exclusive_access();
let mut map_pte = ALL_MAPPED_PTE.lock();
for i in 0..512 {
if p4[i].flags().contains(PTFlags::PRESENT) {
map_pte.insert(i, p4[i]);

View File

@ -1,7 +1,6 @@
mod atomic_bits;
mod rcu;
mod spin;
pub(crate) mod up;
mod wait;
pub use self::atomic_bits::AtomicBits;

View File

@ -1,36 +0,0 @@
use core::cell::{Ref, RefCell, RefMut};
#[derive(Debug)]
/// 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(crate) 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()
}
/// Panic if the data has been borrowed.
pub fn get_ref(&self) -> Ref<'_, T> {
self.inner.borrow()
}
}

View File

@ -3,9 +3,9 @@ use super::{
task::{context_switch, TaskContext},
Task, TaskStatus,
};
use crate::UPSafeCell;
use alloc::sync::Arc;
use lazy_static::*;
use lazy_static::lazy_static;
use spin::Mutex;
pub struct Processor {
current: Option<Arc<Task>>,
@ -34,19 +34,19 @@ impl Processor {
}
lazy_static! {
static ref PROCESSOR: UPSafeCell<Processor> = unsafe { UPSafeCell::new(Processor::new()) };
static ref PROCESSOR: Mutex<Processor> = Mutex::new(Processor::new());
}
pub fn take_current_task() -> Option<Arc<Task>> {
PROCESSOR.exclusive_access().take_current()
PROCESSOR.lock().take_current()
}
pub fn current_task() -> Option<Arc<Task>> {
PROCESSOR.exclusive_access().current()
PROCESSOR.lock().current()
}
pub(crate) fn get_idle_task_cx_ptr() -> *mut TaskContext {
PROCESSOR.exclusive_access().get_idle_task_cx_ptr()
PROCESSOR.lock().get_idle_task_cx_ptr()
}
/// call this function to switch to other task by using GLOBAL_SCHEDULER
@ -68,19 +68,17 @@ pub fn switch_to_task(next_task: Arc<Task>) {
let next_task_cx_ptr = &next_task.inner_ctx() as *const TaskContext;
let current_task: Arc<Task>;
let current_task_cx_ptr = if current_task_option.is_none() {
PROCESSOR.exclusive_access().get_idle_task_cx_ptr()
PROCESSOR.lock().get_idle_task_cx_ptr()
} else {
current_task = current_task_option.unwrap();
if current_task.status() != TaskStatus::Exited {
GLOBAL_SCHEDULER
.exclusive_access()
.enqueue(current_task.clone());
GLOBAL_SCHEDULER.lock().enqueue(current_task.clone());
}
&mut current_task.inner_exclusive_access().ctx as *mut TaskContext
};
// change the current task to the next task
PROCESSOR.exclusive_access().current = Some(next_task.clone());
PROCESSOR.lock().current = Some(next_task.clone());
unsafe {
context_switch(current_task_cx_ptr, next_task_cx_ptr);
}

View File

@ -1,11 +1,12 @@
use crate::prelude::*;
use crate::task::Task;
use crate::{prelude::*, UPSafeCell};
use lazy_static::lazy_static;
use spin::Mutex;
lazy_static! {
pub(crate) static ref GLOBAL_SCHEDULER: UPSafeCell<GlobalScheduler> =
unsafe { UPSafeCell::new(GlobalScheduler { scheduler: None }) };
pub(crate) static ref GLOBAL_SCHEDULER: Mutex<GlobalScheduler> =
Mutex::new(GlobalScheduler { scheduler: None });
}
/// A scheduler for tasks.
@ -42,13 +43,13 @@ impl GlobalScheduler {
///
/// This must be called before invoking `Task::spawn`.
pub fn set_scheduler(scheduler: &'static dyn Scheduler) {
GLOBAL_SCHEDULER.exclusive_access().scheduler = Some(scheduler);
GLOBAL_SCHEDULER.lock().scheduler = Some(scheduler);
}
pub fn fetch_task() -> Option<Arc<Task>> {
GLOBAL_SCHEDULER.exclusive_access().dequeue()
GLOBAL_SCHEDULER.lock().dequeue()
}
pub fn add_task(task: Arc<Task>) {
GLOBAL_SCHEDULER.exclusive_access().enqueue(task);
GLOBAL_SCHEDULER.lock().enqueue(task);
}

View File

@ -1,15 +1,15 @@
use core::cell::RefMut;
use core::mem::size_of;
use lazy_static::lazy_static;
use spin::{Mutex, MutexGuard};
use crate::cell::Cell;
use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE};
use crate::prelude::*;
use crate::task::processor::switch_to_task;
use crate::trap::{CalleeRegs, SyscallFrame, TrapFrame};
use crate::user::{syscall_switch_to_user_space, trap_switch_to_user_space, UserSpace};
use crate::vm::{VmAllocOptions, VmFrameVec};
use crate::{prelude::*, UPSafeCell};
use intrusive_collections::intrusive_adapter;
use intrusive_collections::LinkedListAtomicLink;
@ -60,20 +60,18 @@ lazy_static! {
func: Box::new(context_switch_to_user_space),
data: Box::new(None::<u8>),
user_space: None,
task_inner: unsafe {
UPSafeCell::new(TaskInner {
task_inner: Mutex::new(TaskInner {
task_status: TaskStatus::Runnable,
ctx: TaskContext::default(),
is_from_trap:false,
})
},
}),
exit_code: usize::MAX,
kstack: KernelStack::new(),
link: LinkedListAtomicLink::new(),
};
task.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
task.task_inner.exclusive_access().ctx.rip = context_switch_to_user_space as usize;
task.task_inner.exclusive_access().ctx.regs.rsp = (task.kstack.frame.end_pa().unwrap().kvaddr().0
task.task_inner.lock().task_status = TaskStatus::Runnable;
task.task_inner.lock().ctx.rip = context_switch_to_user_space as usize;
task.task_inner.lock().ctx.regs.rsp = (task.kstack.frame.end_pa().unwrap().kvaddr().0
- size_of::<usize>()
- size_of::<SyscallFrame>()) as u64;
task
@ -98,7 +96,7 @@ pub struct Task {
func: Box<dyn Fn() + Send + Sync>,
data: Box<dyn Any + Send + Sync>,
user_space: Option<Arc<UserSpace>>,
task_inner: UPSafeCell<TaskInner>,
task_inner: Mutex<TaskInner>,
exit_code: usize,
/// kernel stack, note that the top is SyscallFrame/TrapFrame
kstack: KernelStack,
@ -122,13 +120,13 @@ impl Task {
}
/// get inner
pub(crate) fn inner_exclusive_access(&self) -> RefMut<'_, TaskInner> {
self.task_inner.exclusive_access()
pub(crate) fn inner_exclusive_access(&self) -> MutexGuard<'_, TaskInner> {
self.task_inner.lock()
}
/// get inner
pub(crate) fn inner_ctx(&self) -> TaskContext {
self.task_inner.exclusive_access().ctx
self.task_inner.lock().ctx
}
/// Yields execution so that another task may be scheduled.
@ -165,24 +163,21 @@ impl Task {
func: Box::new(task_fn),
data: Box::new(task_data),
user_space,
task_inner: unsafe {
UPSafeCell::new(TaskInner {
task_status: TaskStatus::Runnable,
ctx: TaskContext::default(),
is_from_trap: false,
})
},
task_inner: Mutex::new(TaskInner {
task_status: TaskStatus::Runnable,
ctx: TaskContext::default(),
is_from_trap: false,
}),
exit_code: 0,
kstack: KernelStack::new(),
link: LinkedListAtomicLink::new(),
};
result.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
result.task_inner.exclusive_access().ctx.rip = kernel_task_entry as usize;
result.task_inner.exclusive_access().ctx.regs.rsp =
(result.kstack.frame.end_pa().unwrap().kvaddr().0
- size_of::<usize>()
- size_of::<SyscallFrame>()) as u64;
result.task_inner.lock().task_status = TaskStatus::Runnable;
result.task_inner.lock().ctx.rip = kernel_task_entry as usize;
result.task_inner.lock().ctx.regs.rsp = (result.kstack.frame.end_pa().unwrap().kvaddr().0
- size_of::<usize>()
- size_of::<SyscallFrame>()) as u64;
let arc_self = Arc::new(result);
switch_to_task(arc_self.clone());
@ -210,24 +205,21 @@ impl Task {
func: Box::new(task_fn),
data: Box::new(task_data),
user_space,
task_inner: unsafe {
UPSafeCell::new(TaskInner {
task_status: TaskStatus::Runnable,
ctx: TaskContext::default(),
is_from_trap: false,
})
},
task_inner: Mutex::new(TaskInner {
task_status: TaskStatus::Runnable,
ctx: TaskContext::default(),
is_from_trap: false,
}),
exit_code: 0,
kstack: KernelStack::new(),
link: LinkedListAtomicLink::new(),
};
result.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
result.task_inner.exclusive_access().ctx.rip = kernel_task_entry as usize;
result.task_inner.exclusive_access().ctx.regs.rsp =
(result.kstack.frame.end_pa().unwrap().kvaddr().0
- size_of::<usize>()
- size_of::<SyscallFrame>()) as u64;
result.task_inner.lock().task_status = TaskStatus::Runnable;
result.task_inner.lock().ctx.rip = kernel_task_entry as usize;
result.task_inner.lock().ctx.regs.rsp = (result.kstack.frame.end_pa().unwrap().kvaddr().0
- size_of::<usize>()
- size_of::<SyscallFrame>()) as u64;
Ok(Arc::new(result))
}
@ -264,7 +256,7 @@ impl Task {
/// Returns the task status.
pub fn status(&self) -> TaskStatus {
self.task_inner.exclusive_access().task_status
self.task_inner.lock().task_status
}
/// Returns the task data.

View File

@ -3,19 +3,15 @@
#![feature(custom_test_frameworks)]
#![test_runner(jinux_frame::test_runner)]
#![reexport_test_harness_main = "test_main"]
use bootloader::{entry_point, BootInfo};
extern crate alloc;
use alloc::sync::Arc;
use core::panic::PanicInfo;
use jinux_frame::println;
static mut INPUT_VALUE: u8 = 0;
entry_point!(kernel_test_main);
fn kernel_test_main(boot_info: &'static mut BootInfo) -> ! {
jinux_frame::init(boot_info);
jinux_std::driver::tty::init();
#[no_mangle]
pub extern "C" fn _start() -> ! {
jinux_frame::init();
test_main();
loop {}
}
@ -34,11 +30,12 @@ fn test_input() {
while INPUT_VALUE == 0 {
jinux_frame::hlt();
}
println!("input value:{}", INPUT_VALUE);
// println!("input value:{}", INPUT_VALUE);
}
}
pub fn input_callback(input: u8) {
println!("input value:{}", input);
unsafe {
INPUT_VALUE = input;
}

View File

@ -3,18 +3,15 @@
#![feature(custom_test_frameworks)]
#![test_runner(jinux_frame::test_runner)]
#![reexport_test_harness_main = "test_main"]
use bootloader::{entry_point, BootInfo};
extern crate alloc;
use alloc::sync::Arc;
use core::panic::PanicInfo;
use jinux_frame::println;
static mut INPUT_VALUE: u8 = 0;
entry_point!(kernel_test_main);
fn kernel_test_main(boot_info: &'static mut BootInfo) -> ! {
jinux_frame::init(boot_info);
#[no_mangle]
pub extern "C" fn _start() -> ! {
jinux_frame::init();
test_main();
loop {}
}

View File

@ -3,13 +3,11 @@
#![feature(custom_test_frameworks)]
#![test_runner(jinux_frame::test_runner)]
#![reexport_test_harness_main = "test_main"]
use bootloader::{entry_point, BootInfo};
use core::panic::PanicInfo;
entry_point!(kernel_test_main);
fn kernel_test_main(boot_info: &'static mut BootInfo) -> ! {
jinux_frame::init(boot_info);
#[no_mangle]
pub extern "C" fn _start() -> ! {
jinux_frame::init();
test_main();
loop {}
}

View File

@ -3,7 +3,6 @@
#![feature(custom_test_frameworks)]
#![test_runner(jinux_frame::test_runner)]
#![reexport_test_harness_main = "test_main"]
use bootloader::{entry_point, BootInfo};
use jinux_frame::timer::Timer;
extern crate alloc;
use alloc::sync::Arc;
@ -13,10 +12,9 @@ use jinux_frame::println;
static mut TICK: usize = 0;
entry_point!(kernel_test_main);
fn kernel_test_main(boot_info: &'static mut BootInfo) -> ! {
jinux_frame::init(boot_info);
#[no_mangle]
pub extern "C" fn _start() -> ! {
jinux_frame::init();
test_main();
loop {}
}

View File

@ -1,17 +1,20 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"pre-link-args": {
},
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"pre-link-args": {
"ld.lld": [
"-Tboot/limine/conf/linker.ld"
]
},
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}