diff --git a/Cargo.lock b/Cargo.lock index 39856e0d..03c1b74f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -705,6 +705,7 @@ dependencies = [ "log", "netcore", "platform", + "shim", "smoltcp", "spin", "vfscore", @@ -748,7 +749,6 @@ dependencies = [ "config", "constants", "device_interface", - "downcast-rs", "ksync", "log", "loopback", @@ -757,6 +757,7 @@ dependencies = [ "netcore", "platform", "rtc", + "shim", "spin", "timer", "uart16550", @@ -1505,6 +1506,7 @@ dependencies = [ "page-table", "platform", "riscv", + "shim", "smpscheduler", "spin", "syscall-table", @@ -2729,6 +2731,14 @@ dependencies = [ "spin", ] +[[package]] +name = "shim" +version = "0.1.0" +dependencies = [ + "downcast-rs", + "spin", +] + [[package]] name = "shlex" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index f6f573eb..a331bf9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ members = [ "kernel", "subsystems/unwinder", "subsystems/knet", + "subsystems/shim", ] diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 8ee480f0..f9a1c89f 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -20,7 +20,7 @@ timer = { path = "../subsystems/timer" } ksync = { path = "../subsystems/ksync" } knet = { path = "../subsystems/knet" } gmanager = { path = "../subsystems/gmanager" } - +shim = { path = "../subsystems/shim", features = ["kernel"]} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index bb6b96ec..85acf784 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -42,8 +42,8 @@ fn main(hart_id: usize) { println!("{:#?}", machine_info); mem::init_memory_system(machine_info.memory.end, true); interrupt::init_plic(machine_info.plic.start); - drivers::register_task_func(Box::new(DriverTaskImpl)); - devices::init_device(Box::new(DriverTaskImpl)); + shim::register_task_func(Box::new(DriverTaskImpl)); + devices::init_device(); vfs::init_filesystem().expect("init filesystem failed"); trap::init_trap_subsystem(); arch::allow_access_user_memory(); diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index ae7bbbd3..a0e40284 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -11,8 +11,7 @@ pub use crate::task::task::FsContext; use alloc::sync::Arc; use alloc::vec::Vec; pub use cpu::*; -use devices::DeviceWithTask; -use drivers::{DriverTask, DriverWithTask}; +use shim::{KTask, KTaskShim}; use smpscheduler::FifoTask; use spin::Lazy; pub use task::{StatisticalData, Task, TaskState}; @@ -56,7 +55,7 @@ fn kthread_init() { } } -impl DriverTask for Task { +impl KTask for Task { fn to_wait(&self) { self.update_state(TaskState::Waiting) } @@ -70,28 +69,24 @@ impl DriverTask for Task { } } pub struct DriverTaskImpl; -impl DriverWithTask for DriverTaskImpl { - fn get_task(&self) -> Arc { +impl KTaskShim for DriverTaskImpl { + fn get_task(&self) -> Arc { let task = current_task().unwrap(); task.clone() } - fn put_task(&self, task: Arc) { + fn put_task(&self, task: Arc) { let task = task.downcast_arc::().map_err(|_| ()).unwrap(); GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); } - fn suspend(&self) { do_suspend(); } -} -impl DeviceWithTask for DriverTaskImpl { fn transfer_ptr_raw(&self, ptr: usize) -> usize { let task = current_task().unwrap(); task.transfer_raw(ptr) } - fn transfer_buf_raw(&self, src: usize, size: usize) -> Vec<&mut [u8]> { let task = current_task().unwrap(); task.transfer_buffer(src as *const u8, size) @@ -99,4 +94,4 @@ impl DeviceWithTask for DriverTaskImpl { } // online test has no sort.src -// pub static SORT_SRC: &[u8] = include_bytes!("../../../sdcard/sort.src"); +// pub static SORT_SRC: &[u8] = include_bytes!("../../../tests/testbin-second-stage/sort.src"); diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 55c773d5..feb2801c 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -289,10 +289,6 @@ impl Task { } } } else { - // if it is a thread, we should not remove it from parent's children - // if self.access_inner().children.len() == 0 { - // self.access_inner().address_space.lock().release(); - // } } self.access_inner().state = TaskState::Terminated; } diff --git a/subsystems/devices/Cargo.toml b/subsystems/devices/Cargo.toml index 8098f5dc..bae715de 100644 --- a/subsystems/devices/Cargo.toml +++ b/subsystems/devices/Cargo.toml @@ -14,7 +14,7 @@ ksync = { path = "../ksync" } interrupt = { path = "../interrupt" } drivers = { path = "../drivers" } device_interface = { path = "../device_interface" } - +shim = { path = "../shim", features = ["lib"] } spin = "0" fdt = { git = "https://github.com/repnop/fdt" } log = "0" diff --git a/subsystems/devices/src/lib.rs b/subsystems/devices/src/lib.rs index 06c4379c..6f038cd1 100644 --- a/subsystems/devices/src/lib.rs +++ b/subsystems/devices/src/lib.rs @@ -29,7 +29,6 @@ use interrupt::register_device_to_plic; use log::info; use platform::println; pub use rtc::{RTCDevice, RTC_DEVICE}; -use spin::Once; pub use uart::{UARTDevice, UART_DEVICE}; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; use virtio_drivers::transport::{DeviceType, Transport}; @@ -40,68 +39,11 @@ pub struct DeviceInfo { pub need_register: bool, } -static TASK_FUNC: Once> = Once::new(); - -pub trait DeviceWithTask: Send + Sync { - fn transfer_ptr_raw(&self, ptr: usize) -> usize; - fn transfer_buf_raw(&self, src: usize, size: usize) -> Vec<&mut [u8]>; -} - -impl dyn DeviceWithTask { - fn copy_data_to_task(&self, src: *const T, dst: *mut T) { - let size = core::mem::size_of::(); - let bufs = self.transfer_buf_raw(dst as usize, size); - let src = unsafe { core::slice::from_raw_parts(src as *const u8, size) }; - let mut start = 0; - for buffer in bufs { - let len = if start + buffer.len() > size { - size - start - } else { - buffer.len() - }; - unsafe { - core::ptr::copy_nonoverlapping(src.as_ptr().add(start), buffer.as_mut_ptr(), len); - } - start += len; - } - } - fn copy_data_from_task(&self, src: *const T, dst: *mut T) { - let size = core::mem::size_of::(); - let bufs = self.transfer_buf_raw(src as usize, size); - let dst = unsafe { core::slice::from_raw_parts_mut(dst as *mut u8, size) }; - let mut start = 0; - for buffer in bufs { - let len = if start + buffer.len() > size { - size - start - } else { - buffer.len() - }; - unsafe { - core::ptr::copy_nonoverlapping(buffer.as_ptr(), dst.as_mut_ptr().add(start), len); - } - start += len; - } - } - fn transfer_ptr_mut(&self, ptr: *mut T) -> &'static mut T { - let ptr = ptr as usize; - let ptr = self.transfer_ptr_raw(ptr); - unsafe { &mut *(ptr as *mut T) } - } - fn transfer_ptr(&self, ptr: *const T) -> &'static T { - let ptr = ptr as usize; - let ptr = self.transfer_ptr_raw(ptr); - unsafe { &*(ptr as *const T) } - } -} - /// Probe all devices from device tree and init them. /// # Warning /// Before init device, we should init platform first. /// -/// todo!(The task_func should be replaced) -pub fn init_device(task_func: Box) { - TASK_FUNC.call_once(|| task_func); - +pub fn init_device() { let dtb_ptr = platform::platform_dtb_ptr(); let dtb = unsafe { Fdt::from_ptr(dtb_ptr as *const u8).unwrap() }; diff --git a/subsystems/devices/src/rtc.rs b/subsystems/devices/src/rtc.rs index 955a5497..e502aeea 100644 --- a/subsystems/devices/src/rtc.rs +++ b/subsystems/devices/src/rtc.rs @@ -1,4 +1,3 @@ -use crate::TASK_FUNC; use alloc::format; use alloc::sync::Arc; use constants::io::{RtcTime, TeletypeCommand}; @@ -51,16 +50,11 @@ impl VfsFile for RTCDevice { todo!() } fn ioctl(&self, cmd: u32, arg: usize) -> VfsResult { - // let task = current_task().unwrap(); - // let mut task_inner = task.access_inner(); let cmd = TeletypeCommand::try_from(cmd).map_err(|_| VfsError::Invalid)?; match cmd { TeletypeCommand::RTC_RD_TIME => { let time = self.device.read_time(); - TASK_FUNC - .get() - .unwrap() - .copy_data_to_task(&time, arg as *mut RtcTime); + shim::copy_data_to_task(&time, arg as *mut RtcTime); } _ => return Err(VfsError::Invalid), } diff --git a/subsystems/devices/src/uart.rs b/subsystems/devices/src/uart.rs index 77a347cd..be73e3cc 100644 --- a/subsystems/devices/src/uart.rs +++ b/subsystems/devices/src/uart.rs @@ -1,4 +1,3 @@ -use crate::TASK_FUNC; use alloc::sync::Arc; use constants::io::{LocalModes, TeletypeCommand, Termios, WinSize}; use constants::DeviceId; @@ -95,53 +94,31 @@ impl VfsFile for UARTDevice { fn ioctl(&self, cmd: u32, arg: usize) -> VfsResult { let mut io = self.io.lock(); let cmd = TeletypeCommand::try_from(cmd).unwrap(); - - // let task = current_task().unwrap(); - // let mut task_inner = task.access_inner(); - return match cmd { TeletypeCommand::TCGETS | TeletypeCommand::TCGETA => { - // task_inner.copy_to_user(&io.termios, arg as *mut Termios); - TASK_FUNC - .get() - .unwrap() - .copy_data_to_task(&io.termios, arg as *mut Termios); + shim::copy_data_to_task(&io.termios, arg as *mut Termios); Ok(0) } TeletypeCommand::TCSETS | TeletypeCommand::TCSETSW | TeletypeCommand::TCSETSF => { - // task_inner.copy_from_user(arg as *const Termios, &mut io.termios); - TASK_FUNC - .get() - .unwrap() - .copy_data_from_task(arg as *const Termios, &mut io.termios); + shim::copy_data_from_task(arg as *const Termios, &mut io.termios); Ok(0) } TeletypeCommand::TIOCGPGRP => { - // let word = task_inner.transfer_raw_ptr_mut(arg as *mut u32); - let word = TASK_FUNC.get().unwrap().transfer_ptr_mut(arg as *mut u32); + let word = shim::transfer_ptr_mut(arg as *mut u32); *word = io.foreground_pgid; Ok(0) } TeletypeCommand::TIOCSPGRP => { - // let word = task_inner.transfer_raw_ptr(arg as *const u32); - let word = TASK_FUNC.get().unwrap().transfer_ptr(arg as *const u32); + let word = shim::transfer_ptr(arg as *const u32); io.foreground_pgid = *word; Ok(0) } TeletypeCommand::TIOCGWINSZ => { - // task_inner.copy_to_user(&io.winsize, arg as *mut WinSize); - TASK_FUNC - .get() - .unwrap() - .copy_data_to_task(&io.winsize, arg as *mut WinSize); + shim::copy_data_to_task(&io.winsize, arg as *mut WinSize); Ok(0) } TeletypeCommand::TIOCSWINSZ => { - // task_inner.copy_from_user(arg as *const WinSize, &mut io.winsize); - TASK_FUNC - .get() - .unwrap() - .copy_data_from_task(arg as *const WinSize, &mut io.winsize); + shim::copy_data_from_task(arg as *const WinSize, &mut io.winsize); Ok(0) } _ => { diff --git a/subsystems/drivers/Cargo.toml b/subsystems/drivers/Cargo.toml index 06a8f7de..fd6bcf90 100644 --- a/subsystems/drivers/Cargo.toml +++ b/subsystems/drivers/Cargo.toml @@ -14,11 +14,13 @@ mem = { path = "../mem" } log = "0" timer = { path = "../timer" } platform = { path = "../platform" } -spin = "0" +shim = { path = "../shim", features = ["lib"] } + +spin = "0" virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers",rev = "de1c3b1" } rtc = { git = "https://github.com/os-module/rtc.git" } -lru = "0.10.0" +lru = "0" # uart uart16550 = { version = "0.0.1"} @@ -31,5 +33,4 @@ virtio-net = { git = "https://github.com/os-module/simple-net" } netcore = { git = "https://github.com/os-module/simple-net" } visionfive2-sd = { git = "https://github.com/os-module/visionfive2-sd.git" } -downcast-rs = { version = "1.2.0", default-features = false } diff --git a/subsystems/drivers/src/input.rs b/subsystems/drivers/src/input.rs index 94d0de05..ecb7855c 100644 --- a/subsystems/drivers/src/input.rs +++ b/subsystems/drivers/src/input.rs @@ -8,8 +8,8 @@ use virtio_drivers::device::input::VirtIOInput; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; use crate::hal::HalImpl; -use crate::{DriverTask, DRIVER_TASK}; use ksync::Mutex; +use shim::KTask; pub struct VirtIOInputDriver { inner: Mutex, @@ -23,7 +23,7 @@ struct InputDriverInner { max_events: u32, driver: VirtIOInput, events: VecDeque, - wait_queue: VecDeque>, + wait_queue: VecDeque>, } impl VirtIOInputDriver { @@ -67,15 +67,11 @@ impl InputDevice for VirtIOInputDriver { if let Some(event) = inner.events.pop_front() { return event; } - // let process = current_task().unwrap(); - // process.update_state(TaskState::Waiting); - // inner.wait_queue.push_back(process.clone()); - let task = DRIVER_TASK.get().unwrap().get_task(); + let task = shim::current_task(); task.to_wait(); inner.wait_queue.push_back(task); } // drop the lock - // schedule(); - DRIVER_TASK.get().unwrap().suspend(); + shim::suspend(); // yield current task } } @@ -103,10 +99,8 @@ impl DeviceBase for VirtIOInputDriver { } while !inner.wait_queue.is_empty() && count > 0 { let task = inner.wait_queue.pop_front().unwrap(); - // process.update_state(TaskState::Ready); - // GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(process))); task.to_wakeup(); - DRIVER_TASK.get().unwrap().put_task(task); + shim::put_task(task); count -= 1; } info!("read {} events", count); diff --git a/subsystems/drivers/src/lib.rs b/subsystems/drivers/src/lib.rs index 86d800c3..c983bc57 100644 --- a/subsystems/drivers/src/lib.rs +++ b/subsystems/drivers/src/lib.rs @@ -1,11 +1,6 @@ #![no_std] extern crate alloc; -use alloc::boxed::Box; -use alloc::sync::Arc; -use downcast_rs::{impl_downcast, DowncastSync}; -use spin::Once; - pub mod block_device; pub mod gpu; pub mod hal; @@ -13,23 +8,3 @@ pub mod input; pub mod net; pub mod rtc; pub mod uart; - -pub trait DriverTask: Send + Sync + DowncastSync { - fn to_wait(&self); - fn to_wakeup(&self); - fn have_signal(&self) -> bool; -} - -impl_downcast!(sync DriverTask); - -pub trait DriverWithTask: Send + Sync { - fn get_task(&self) -> Arc; - fn put_task(&self, task: Arc); - fn suspend(&self); -} - -static DRIVER_TASK: Once> = Once::new(); - -pub fn register_task_func(task_func: Box) { - DRIVER_TASK.call_once(|| task_func); -} diff --git a/subsystems/drivers/src/net.rs b/subsystems/drivers/src/net.rs index 68c4de4c..e83959d8 100644 --- a/subsystems/drivers/src/net.rs +++ b/subsystems/drivers/src/net.rs @@ -1,14 +1,12 @@ use core::ptr::NonNull; use crate::hal::HalImpl; +pub use loopback::LoopbackDev; use netcore::{KernelNetFunc, NetInstant}; use timer::TimeSpec; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; use virtio_net::VirtIONetDeviceWrapper; -use crate::DRIVER_TASK; -pub use loopback::LoopbackDev; - pub const NET_BUFFER_LEN: usize = 4096; pub const NET_QUEUE_SIZE: usize = 128; @@ -51,10 +49,9 @@ impl KernelNetFunc for NetNeedFunc { } } fn yield_now(&self) -> bool { - // use crate::task::current_task; - // use crate::task::do_suspend; // do_suspend(); - DRIVER_TASK.get().unwrap().suspend(); + shim::suspend(); + // interrupt by signal // let task = current_task().unwrap(); // let task_inner = task.access_inner(); @@ -62,7 +59,7 @@ impl KernelNetFunc for NetNeedFunc { // if receiver.have_signal() { // return true; // } - let task = DRIVER_TASK.get().unwrap().get_task(); + let task = shim::current_task(); task.have_signal() } } diff --git a/subsystems/drivers/src/uart.rs b/subsystems/drivers/src/uart.rs index 27511770..38cfb0dd 100644 --- a/subsystems/drivers/src/uart.rs +++ b/subsystems/drivers/src/uart.rs @@ -1,11 +1,11 @@ pub use self::uart16550::Uart16550; pub use self::uart8250::Uart8250; -use crate::{DriverTask, DRIVER_TASK}; use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::sync::Arc; use device_interface::{DeviceBase, UartDevice}; use ksync::Mutex; +use shim::KTask; pub trait LowUartDriver: Send + Sync { fn _init(&mut self); @@ -98,7 +98,7 @@ pub struct Uart { struct UartInner { rx_buf: VecDeque, - wait_queue: VecDeque>, + wait_queue: VecDeque>, } impl Uart { @@ -124,13 +124,11 @@ impl UartDevice for Uart { loop { let mut inner = self.inner.lock(); if inner.1.rx_buf.is_empty() { - // let current_process = current_task().unwrap(); - // current_process.update_state(TaskState::Waiting); - let task = DRIVER_TASK.get().unwrap().get_task(); + let task = shim::current_task(); task.to_wait(); inner.1.wait_queue.push_back(task); drop(inner); - DRIVER_TASK.get().unwrap().suspend(); + shim::suspend(); } else { return inner.1.rx_buf.pop_front(); } @@ -163,10 +161,8 @@ impl DeviceBase for Uart { inner.1.rx_buf.push_back(c); if !inner.1.wait_queue.is_empty() { let task = inner.1.wait_queue.pop_front().unwrap(); - // task.update_state(TaskState::Ready); - // GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); task.to_wakeup(); - DRIVER_TASK.get().unwrap().put_task(task); + shim::put_task(task); } } else { break; diff --git a/subsystems/shim/Cargo.toml b/subsystems/shim/Cargo.toml new file mode 100644 index 00000000..b8e9605e --- /dev/null +++ b/subsystems/shim/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "shim" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +downcast-rs = { version = "1.2.0", default-features = false } +spin = { version = "0" } + + +[features] +kernel = [] +lib = [] diff --git a/subsystems/shim/src/lib.rs b/subsystems/shim/src/lib.rs new file mode 100644 index 00000000..ef11f2ce --- /dev/null +++ b/subsystems/shim/src/lib.rs @@ -0,0 +1,131 @@ +#![no_std] +extern crate alloc; + +use alloc::boxed::Box; +use alloc::sync::Arc; +use alloc::vec::Vec; +use downcast_rs::{impl_downcast, DowncastSync}; +use spin::Once; + +pub trait KTask: Send + Sync + DowncastSync { + fn to_wait(&self); + fn to_wakeup(&self); + fn have_signal(&self) -> bool; +} + +impl_downcast!(sync KTask); + +pub trait KTaskShim: Send + Sync { + fn get_task(&self) -> Arc; + fn put_task(&self, task: Arc); + fn suspend(&self); + fn transfer_ptr_raw(&self, ptr: usize) -> usize; + fn transfer_buf_raw(&self, src: usize, size: usize) -> Vec<&mut [u8]>; +} + +impl dyn KTaskShim { + fn copy_data_to_task(&self, src: *const T, dst: *mut T) { + let size = core::mem::size_of::(); + let bufs = self.transfer_buf_raw(dst as usize, size); + let src = unsafe { core::slice::from_raw_parts(src as *const u8, size) }; + let mut start = 0; + for buffer in bufs { + let len = if start + buffer.len() > size { + size - start + } else { + buffer.len() + }; + unsafe { + core::ptr::copy_nonoverlapping(src.as_ptr().add(start), buffer.as_mut_ptr(), len); + } + start += len; + } + } + fn copy_data_from_task(&self, src: *const T, dst: *mut T) { + let size = core::mem::size_of::(); + let bufs = self.transfer_buf_raw(src as usize, size); + let dst = unsafe { core::slice::from_raw_parts_mut(dst as *mut u8, size) }; + let mut start = 0; + for buffer in bufs { + let len = if start + buffer.len() > size { + size - start + } else { + buffer.len() + }; + unsafe { + core::ptr::copy_nonoverlapping(buffer.as_ptr(), dst.as_mut_ptr().add(start), len); + } + start += len; + } + } + fn transfer_ptr_mut(&self, ptr: *mut T) -> &'static mut T { + let ptr = ptr as usize; + let ptr = self.transfer_ptr_raw(ptr); + unsafe { &mut *(ptr as *mut T) } + } + fn transfer_ptr(&self, ptr: *const T) -> &'static T { + let ptr = ptr as usize; + let ptr = self.transfer_ptr_raw(ptr); + unsafe { &*(ptr as *const T) } + } +} + +static KTASK_SHIM: Once> = Once::new(); + +#[cfg(feature = "kernel")] +pub fn register_task_func(task_shim: Box) { + KTASK_SHIM.call_once(|| task_shim); +} + +#[cfg(feature = "lib")] +/// Get the current task. +pub fn current_task() -> Arc { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .get_task() +} +#[cfg(feature = "lib")] +/// Put the task back to the task queue. +pub fn put_task(task: Arc) { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .put_task(task); +} +#[cfg(feature = "lib")] +/// Suspend the current task. +pub fn suspend() { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .suspend(); +} +#[cfg(feature = "lib")] +pub fn copy_data_to_task(src: *const T, dst: *mut T) { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .copy_data_to_task(src, dst); +} +#[cfg(feature = "lib")] +pub fn copy_data_from_task(src: *const T, dst: *mut T) { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .copy_data_from_task(src, dst); +} +#[cfg(feature = "lib")] +pub fn transfer_ptr_mut(ptr: *mut T) -> &'static mut T { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .transfer_ptr_mut(ptr) +} +#[cfg(feature = "lib")] +pub fn transfer_ptr(ptr: *const T) -> &'static T { + KTASK_SHIM + .get() + .expect("ktask_shim not initialized") + .transfer_ptr(ptr) +}