From 31e51ad2adb85698e70a2d64291d98bff7394b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Sun, 15 Feb 2026 22:59:23 +0800 Subject: [PATCH 1/2] refactor: merge starry-core & starry-api into starry-kernel --- Cargo.lock | 82 ++---- Cargo.toml | 21 +- api/src/lib.rs | 35 --- api/src/signal.rs | 66 ----- api/src/syscall/ipc/shm.rs | 228 ---------------- api/src/task.rs | 220 --------------- core/Cargo.toml | 53 ---- core/src/lib.rs | 20 -- core/src/vfs/mod.rs | 40 --- {api => kernel}/Cargo.toml | 19 +- {core => kernel}/src/config/aarch64.rs | 0 {core => kernel}/src/config/loongarch64.rs | 0 {core => kernel}/src/config/mod.rs | 0 {core => kernel}/src/config/riscv64.rs | 0 {core => kernel}/src/config/x86_64.rs | 0 {api => kernel}/src/file/epoll.rs | 0 {api => kernel}/src/file/event.rs | 0 {api => kernel}/src/file/fs.rs | 0 {api => kernel}/src/file/mod.rs | 2 +- {api => kernel}/src/file/net.rs | 0 {api => kernel}/src/file/pidfd.rs | 3 +- {api => kernel}/src/file/pipe.rs | 6 +- {api => kernel}/src/file/signalfd.rs | 6 +- kernel/src/lib.rs | 30 +++ api/src/mm.rs => kernel/src/mm/aspace.rs | 70 ++++- {api/src => kernel/src/mm}/io.rs | 0 core/src/mm.rs => kernel/src/mm/loader.rs | 76 +----- kernel/src/mm/mod.rs | 7 + .../vfs => kernel/src/pseudofs}/dev/event.rs | 6 +- .../src/vfs => kernel/src/pseudofs}/dev/fb.rs | 3 +- .../vfs => kernel/src/pseudofs}/dev/log.rs | 0 .../vfs => kernel/src/pseudofs}/dev/loop.rs | 6 +- .../src/pseudofs}/dev/memtrack.rs | 6 +- .../vfs => kernel/src/pseudofs}/dev/mod.rs | 5 +- .../vfs => kernel/src/pseudofs}/dev/rtc.rs | 2 +- .../src/pseudofs/dev/tty/mod.rs | 36 +-- .../src/pseudofs}/dev/tty/ntty.rs | 6 +- .../src/pseudofs}/dev/tty/ptm.rs | 3 +- .../src/pseudofs}/dev/tty/pts.rs | 3 +- .../src/pseudofs}/dev/tty/pty.rs | 10 +- .../src/pseudofs/dev/tty}/terminal/job.rs | 3 +- .../src/pseudofs/dev/tty}/terminal/ldisc.rs | 4 +- .../src/pseudofs/dev/tty}/terminal/mod.rs | 0 .../src/pseudofs/dev/tty}/terminal/termios.rs | 2 + .../dev.rs => kernel/src/pseudofs/device.rs | 0 {core/src/vfs => kernel/src/pseudofs}/dir.rs | 0 {core/src/vfs => kernel/src/pseudofs}/file.rs | 0 {core/src/vfs => kernel/src/pseudofs}/fs.rs | 0 {api/src/vfs => kernel/src/pseudofs}/mod.rs | 39 ++- {api/src/vfs => kernel/src/pseudofs}/proc.rs | 36 ++- {api/src/vfs => kernel/src/pseudofs}/tmp.rs | 3 +- {api => kernel}/src/syscall/fs/ctl.rs | 2 +- {api => kernel}/src/syscall/fs/event.rs | 0 {api => kernel}/src/syscall/fs/fd_ops.rs | 4 +- {api => kernel}/src/syscall/fs/io.rs | 3 +- {api => kernel}/src/syscall/fs/memfd.rs | 0 {api => kernel}/src/syscall/fs/mod.rs | 0 {api => kernel}/src/syscall/fs/mount.rs | 2 +- {api => kernel}/src/syscall/fs/pidfd.rs | 2 +- {api => kernel}/src/syscall/fs/pipe.rs | 0 {api => kernel}/src/syscall/fs/signalfd.rs | 0 {api => kernel}/src/syscall/fs/stat.rs | 0 {api => kernel}/src/syscall/io_mpx/epoll.rs | 4 +- {api => kernel}/src/syscall/io_mpx/mod.rs | 0 {api => kernel}/src/syscall/io_mpx/poll.rs | 4 +- {api => kernel}/src/syscall/io_mpx/select.rs | 4 +- {api => kernel}/src/syscall/ipc/mod.rs | 40 ++- {api => kernel}/src/syscall/ipc/msg.rs | 13 +- {core/src => kernel/src/syscall/ipc}/shm.rs | 254 +++++++++++++++--- {api => kernel}/src/syscall/mm/brk.rs | 3 +- {api => kernel}/src/syscall/mm/mincore.rs | 3 +- {api => kernel}/src/syscall/mm/mmap.rs | 10 +- {api => kernel}/src/syscall/mm/mod.rs | 0 {api => kernel}/src/syscall/mod.rs | 2 +- .../src/syscall/net/addr.rs | 1 + {api => kernel}/src/syscall/net/cmsg.rs | 0 {api => kernel}/src/syscall/net/io.rs | 5 +- {api => kernel}/src/syscall/net/mod.rs | 1 + {api => kernel}/src/syscall/net/name.rs | 2 +- {api => kernel}/src/syscall/net/opt.rs | 0 {api => kernel}/src/syscall/net/socket.rs | 4 +- {api => kernel}/src/syscall/resources.rs | 6 +- {api => kernel}/src/syscall/signal.rs | 9 +- {api => kernel}/src/syscall/sync/futex.rs | 16 +- .../src/syscall/sync/membarrier.rs | 0 {api => kernel}/src/syscall/sync/mod.rs | 0 {api => kernel}/src/syscall/sys.rs | 3 +- {api => kernel}/src/syscall/task/clone.rs | 7 +- {api => kernel}/src/syscall/task/ctl.rs | 6 +- {api => kernel}/src/syscall/task/execve.rs | 8 +- {api => kernel}/src/syscall/task/exit.rs | 0 {api => kernel}/src/syscall/task/job.rs | 3 +- {api => kernel}/src/syscall/task/mod.rs | 0 {api => kernel}/src/syscall/task/schedule.rs | 6 +- {api => kernel}/src/syscall/task/thread.rs | 3 +- {api => kernel}/src/syscall/task/wait.rs | 3 +- {api => kernel}/src/syscall/time.rs | 6 +- {core/src => kernel/src/task}/futex.rs | 44 ++- core/src/task.rs => kernel/src/task/mod.rs | 246 +---------------- kernel/src/task/ops.rs | 248 +++++++++++++++++ {core/src => kernel/src/task}/resources.rs | 0 kernel/src/task/signal.rs | 138 ++++++++++ {core => kernel}/src/task/stat.rs | 0 core/src/time.rs => kernel/src/task/timer.rs | 0 kernel/src/task/user.rs | 79 ++++++ {api => kernel}/src/time.rs | 12 - src/entry.rs | 9 +- src/main.rs | 2 +- 108 files changed, 1139 insertions(+), 1235 deletions(-) delete mode 100644 api/src/lib.rs delete mode 100644 api/src/signal.rs delete mode 100644 api/src/syscall/ipc/shm.rs delete mode 100644 api/src/task.rs delete mode 100644 core/Cargo.toml delete mode 100644 core/src/lib.rs delete mode 100644 core/src/vfs/mod.rs rename {api => kernel}/Cargo.toml (78%) rename {core => kernel}/src/config/aarch64.rs (100%) rename {core => kernel}/src/config/loongarch64.rs (100%) rename {core => kernel}/src/config/mod.rs (100%) rename {core => kernel}/src/config/riscv64.rs (100%) rename {core => kernel}/src/config/x86_64.rs (100%) rename {api => kernel}/src/file/epoll.rs (100%) rename {api => kernel}/src/file/event.rs (100%) rename {api => kernel}/src/file/fs.rs (100%) rename {api => kernel}/src/file/mod.rs (99%) rename {api => kernel}/src/file/net.rs (100%) rename {api => kernel}/src/file/pidfd.rs (94%) rename {api => kernel}/src/file/pipe.rs (98%) rename {api => kernel}/src/file/signalfd.rs (98%) create mode 100644 kernel/src/lib.rs rename api/src/mm.rs => kernel/src/mm/aspace.rs (82%) rename {api/src => kernel/src/mm}/io.rs (100%) rename core/src/mm.rs => kernel/src/mm/loader.rs (83%) create mode 100644 kernel/src/mm/mod.rs rename {api/src/vfs => kernel/src/pseudofs}/dev/event.rs (99%) rename {api/src/vfs => kernel/src/pseudofs}/dev/fb.rs (99%) rename {api/src/vfs => kernel/src/pseudofs}/dev/log.rs (100%) rename {api/src/vfs => kernel/src/pseudofs}/dev/loop.rs (98%) rename {api/src/vfs => kernel/src/pseudofs}/dev/memtrack.rs (99%) rename {api/src/vfs => kernel/src/pseudofs}/dev/mod.rs (97%) rename {api/src/vfs => kernel/src/pseudofs}/dev/rtc.rs (98%) rename api/src/vfs/dev/tty.rs => kernel/src/pseudofs/dev/tty/mod.rs (95%) rename {api/src/vfs => kernel/src/pseudofs}/dev/tty/ntty.rs (91%) rename {api/src/vfs => kernel/src/pseudofs}/dev/tty/ptm.rs (95%) rename {api/src/vfs => kernel/src/pseudofs}/dev/tty/pts.rs (93%) rename {api/src/vfs => kernel/src/pseudofs}/dev/tty/pty.rs (94%) rename {api/src => kernel/src/pseudofs/dev/tty}/terminal/job.rs (98%) rename {api/src => kernel/src/pseudofs/dev/tty}/terminal/ldisc.rs (99%) rename {api/src => kernel/src/pseudofs/dev/tty}/terminal/mod.rs (100%) rename {api/src => kernel/src/pseudofs/dev/tty}/terminal/termios.rs (99%) rename core/src/vfs/dev.rs => kernel/src/pseudofs/device.rs (100%) rename {core/src/vfs => kernel/src/pseudofs}/dir.rs (100%) rename {core/src/vfs => kernel/src/pseudofs}/file.rs (100%) rename {core/src/vfs => kernel/src/pseudofs}/fs.rs (100%) rename {api/src/vfs => kernel/src/pseudofs}/mod.rs (60%) rename {api/src/vfs => kernel/src/pseudofs}/proc.rs (96%) rename {api/src/vfs => kernel/src/pseudofs}/tmp.rs (99%) rename {api => kernel}/src/syscall/fs/ctl.rs (99%) rename {api => kernel}/src/syscall/fs/event.rs (100%) rename {api => kernel}/src/syscall/fs/fd_ops.rs (99%) rename {api => kernel}/src/syscall/fs/io.rs (99%) rename {api => kernel}/src/syscall/fs/memfd.rs (100%) rename {api => kernel}/src/syscall/fs/mod.rs (100%) rename {api => kernel}/src/syscall/fs/mount.rs (94%) rename {api => kernel}/src/syscall/fs/pidfd.rs (95%) rename {api => kernel}/src/syscall/fs/pipe.rs (100%) rename {api => kernel}/src/syscall/fs/signalfd.rs (100%) rename {api => kernel}/src/syscall/fs/stat.rs (100%) rename {api => kernel}/src/syscall/io_mpx/epoll.rs (98%) rename {api => kernel}/src/syscall/io_mpx/mod.rs (100%) rename {api => kernel}/src/syscall/io_mpx/poll.rs (97%) rename {api => kernel}/src/syscall/io_mpx/select.rs (98%) rename {api => kernel}/src/syscall/ipc/mod.rs (59%) rename {api => kernel}/src/syscall/ipc/msg.rs (99%) rename {core/src => kernel/src/syscall/ipc}/shm.rs (59%) rename {api => kernel}/src/syscall/mm/brk.rs (99%) rename {api => kernel}/src/syscall/mm/mincore.rs (99%) rename {api => kernel}/src/syscall/mm/mmap.rs (99%) rename {api => kernel}/src/syscall/mm/mod.rs (100%) rename {api => kernel}/src/syscall/mod.rs (99%) rename api/src/socket.rs => kernel/src/syscall/net/addr.rs (99%) rename {api => kernel}/src/syscall/net/cmsg.rs (100%) rename {api => kernel}/src/syscall/net/io.rs (97%) rename {api => kernel}/src/syscall/net/mod.rs (91%) rename {api => kernel}/src/syscall/net/name.rs (96%) rename {api => kernel}/src/syscall/net/opt.rs (100%) rename {api => kernel}/src/syscall/net/socket.rs (98%) rename {api => kernel}/src/syscall/resources.rs (97%) rename {api => kernel}/src/syscall/signal.rs (97%) rename {api => kernel}/src/syscall/sync/futex.rs (92%) rename {api => kernel}/src/syscall/sync/membarrier.rs (100%) rename {api => kernel}/src/syscall/sync/mod.rs (100%) rename {api => kernel}/src/syscall/sys.rs (98%) rename {api => kernel}/src/syscall/task/clone.rs (98%) rename {api => kernel}/src/syscall/task/ctl.rs (97%) rename {api => kernel}/src/syscall/task/execve.rs (94%) rename {api => kernel}/src/syscall/task/exit.rs (100%) rename {api => kernel}/src/syscall/task/job.rs (93%) rename {api => kernel}/src/syscall/task/mod.rs (100%) rename {api => kernel}/src/syscall/task/schedule.rs (97%) rename {api => kernel}/src/syscall/task/thread.rs (98%) rename {api => kernel}/src/syscall/task/wait.rs (99%) rename {api => kernel}/src/syscall/time.rs (97%) rename {core/src => kernel/src/task}/futex.rs (83%) rename core/src/task.rs => kernel/src/task/mod.rs (52%) create mode 100644 kernel/src/task/ops.rs rename {core/src => kernel/src/task}/resources.rs (100%) create mode 100644 kernel/src/task/signal.rs rename {core => kernel}/src/task/stat.rs (100%) rename core/src/time.rs => kernel/src/task/timer.rs (100%) create mode 100644 kernel/src/task/user.rs rename {api => kernel}/src/time.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index a530567c..5c93b6fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "cpp_demangle", - "gimli 0.32.3", + "gimli", "rustc-demangle", ] @@ -195,7 +195,7 @@ checksum = "bf9566516f5d799b2f791a6ec5af57eec87d17624346f7c876fa006b922c99e6" dependencies = [ "addr2line", "cfg-if", - "gimli 0.32.3", + "gimli", "log", "paste", "spin 0.10.0", @@ -1328,12 +1328,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" - [[package]] name = "glob" version = "0.3.3" @@ -2189,30 +2183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "starry" -version = "0.1.0" -dependencies = [ - "axdriver", - "axerrno 0.2.2", - "axfeat", - "axfs", - "axhal", - "axlog", - "axplat-riscv64-visionfive2", - "axruntime", - "axsync", - "axtask", - "cfg-if", - "linkme", - "linux-raw-sys", - "starry-api", - "starry-core", - "starry-process", - "starry-signal", -] - -[[package]] -name = "starry-api" +name = "starry-kernel" version = "0.1.0" dependencies = [ "axalloc", @@ -2240,76 +2211,61 @@ dependencies = [ "chrono", "downcast-rs", "event-listener", + "extern-trait", "flatten_objects", - "gimli 0.33.0", + "gimli", "hashbrown 0.16.1", "indoc", "inherit-methods-macro", + "kernel-elf-parser", + "kernel_guard", "kspin", "lazy_static", "linkme", "linux-raw-sys", + "lock_api", "memory_addr", "num_enum", + "ouroboros", + "percpu", "rand", "ringbuf", "riscv 0.16.0", "scope-local", "slab", "spin 0.10.0", - "starry-core", "starry-process", "starry-signal", "starry-vm", + "strum", "syscalls", + "uluru", + "weak-map", "x86", + "xmas-elf", "zerocopy 0.8.39", ] [[package]] -name = "starry-core" +name = "starry-main" version = "0.1.0" dependencies = [ - "axbacktrace", - "axconfig", + "axdriver", "axerrno 0.2.2", "axfeat", "axfs", - "axfs-ng-vfs", "axhal", - "axio", "axlog", - "axmm", - "axpoll", + "axplat-riscv64-visionfive2", + "axruntime", "axsync", "axtask", - "bitflags 2.10.0", - "bytemuck", "cfg-if", - "event-listener", - "extern-trait", - "hashbrown 0.16.1", - "inherit-methods-macro", - "kernel-elf-parser", - "kernel_guard", - "kspin", - "lazy_static", "linkme", "linux-raw-sys", - "lock_api", - "memory_addr", - "ouroboros", - "percpu", - "scope-local", - "slab", - "spin 0.10.0", + "starry-kernel", "starry-process", "starry-signal", - "starry-vm", - "strum", - "uluru", - "weak-map", - "xmas-elf", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c04695bb..f38bb280 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["api", "core"] +members = ["kernel"] exclude = ["arceos"] [workspace.package] @@ -15,8 +15,8 @@ authors = [ "朝倉水希 ", "Mivik ", ] -homepage = "https://github.com/arceos-org/arceos" -repository = "https://github.com/arceos-org/starry-next" +homepage = "https://github.com/Starry-OS" +repository = "https://github.com/Starry-OS/StarryOS" [workspace.dependencies] axfeat = { path = "arceos/api/axfeat", features = [ @@ -76,11 +76,10 @@ starry-process = "0.2" starry-signal = "0.3" starry-vm = "0.3" -starry-core = { path = "./core" } -starry-api = { path = "./api" } +starry-kernel = { path = "./kernel" } [package] -name = "starry" +name = "starry-main" version.workspace = true edition.workspace = true authors.workspace = true @@ -93,17 +92,17 @@ default = [] qemu = [ "axfeat/display", "axfeat/input", - "starry-api/input", + "starry-kernel/input", "axfeat/vsock", - "starry-api/vsock", + "starry-kernel/vsock", "axfeat/defplat", "axfeat/bus-pci", # auxilary features "axfeat/fs-times", - "starry-api/dev-log", + "starry-kernel/dev-log", ] smp = ["axfeat/smp", "axplat-riscv64-visionfive2?/smp"] @@ -122,12 +121,10 @@ axtask.workspace = true cfg-if.workspace = true linkme.workspace = true linux-raw-sys.workspace = true +starry-kernel.workspace = true starry-process.workspace = true starry-signal.workspace = true -starry-core.workspace = true -starry-api.workspace = true - [dependencies.axplat-riscv64-visionfive2] version = "0.1.0-pre.1" features = ["fp-simd", "irq", "rtc"] diff --git a/api/src/lib.rs b/api/src/lib.rs deleted file mode 100644 index e6ec362e..00000000 --- a/api/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![no_std] -#![feature(likely_unlikely)] -#![feature(bstr)] -#![allow(missing_docs)] -#![allow(clippy::not_unsafe_ptr_arg_deref)] - -#[macro_use] -extern crate axlog; - -extern crate alloc; - -pub mod file; -pub mod io; -pub mod mm; -pub mod signal; -pub mod socket; -pub mod syscall; -pub mod task; -pub mod terminal; -pub mod time; -pub mod vfs; - -/// Initialize. -pub fn init() { - info!("Initialize VFS..."); - vfs::mount_all().expect("Failed to mount vfs"); - - info!("Initialize /proc/interrupts..."); - axtask::register_timer_callback(|_| { - time::inc_irq_cnt(); - }); - - info!("Initialize alarm..."); - starry_core::time::spawn_alarm_task(); -} diff --git a/api/src/signal.rs b/api/src/signal.rs deleted file mode 100644 index 9aa064cb..00000000 --- a/api/src/signal.rs +++ /dev/null @@ -1,66 +0,0 @@ -use core::sync::atomic::{AtomicBool, Ordering}; - -use axerrno::AxResult; -use axhal::uspace::UserContext; -use axtask::current; -use starry_core::task::{AsThread, Thread}; -use starry_signal::{SignalOSAction, SignalSet}; - -use crate::task::do_exit; - -pub fn check_signals( - thr: &Thread, - uctx: &mut UserContext, - restore_blocked: Option, -) -> bool { - let Some((sig, os_action)) = thr.signal.check_signals(uctx, restore_blocked) else { - return false; - }; - - let signo = sig.signo(); - match os_action { - SignalOSAction::Terminate => { - do_exit(signo as i32, true); - } - SignalOSAction::CoreDump => { - // TODO: implement core dump - do_exit(128 + signo as i32, true); - } - SignalOSAction::Stop => { - // TODO: implement stop - do_exit(1, true); - } - SignalOSAction::Continue => { - // TODO: implement continue - } - SignalOSAction::Handler => { - // do nothing - } - } - true -} - -static BLOCK_NEXT_SIGNAL_CHECK: AtomicBool = AtomicBool::new(false); - -pub fn block_next_signal() { - BLOCK_NEXT_SIGNAL_CHECK.store(true, Ordering::SeqCst); -} - -pub fn unblock_next_signal() -> bool { - BLOCK_NEXT_SIGNAL_CHECK.swap(false, Ordering::SeqCst) -} - -pub fn with_replacen_blocked( - blocked: Option, - f: impl FnOnce() -> AxResult, -) -> AxResult { - let curr = current(); - let sig = &curr.as_thread().signal; - - let old_blocked = blocked.map(|set| sig.set_blocked(set)); - f().inspect(|_| { - if let Some(old) = old_blocked { - sig.set_blocked(old); - } - }) -} diff --git a/api/src/syscall/ipc/shm.rs b/api/src/syscall/ipc/shm.rs deleted file mode 100644 index 936d6880..00000000 --- a/api/src/syscall/ipc/shm.rs +++ /dev/null @@ -1,228 +0,0 @@ -use alloc::sync::Arc; - -use axerrno::{AxError, AxResult}; -use axhal::{ - paging::{MappingFlags, PageSize}, - time::monotonic_time_nanos, -}; -use axmm::backend::{Backend, SharedPages}; -use axsync::Mutex; -use axtask::current; -use linux_raw_sys::general::*; -use memory_addr::{PAGE_SIZE_4K, VirtAddr, VirtAddrRange}; -use starry_core::{ - shm::{SHM_MANAGER, ShmInner, ShmidDs}, - task::AsThread, -}; - -use super::{IPC_PRIVATE, IPC_RMID, IPC_SET, IPC_STAT, next_ipc_id}; -use crate::mm::{UserPtr, nullable}; - -bitflags::bitflags! { - /// flags for sys_shmat - #[derive(Debug)] - struct ShmAtFlags: u32 { - /* attach read-only else read-write */ - const SHM_RDONLY = 0o10000; - /* round attach address to SHMLBA */ - const SHM_RND = 0o20000; - /* take-over region on attach */ - const SHM_REMAP = 0o40000; - } -} - -pub fn sys_shmget(key: i32, size: usize, shmflg: usize) -> AxResult { - let page_num = memory_addr::align_up_4k(size) / PAGE_SIZE_4K; - if page_num == 0 { - return Err(AxError::InvalidInput); - } - - let mut mapping_flags = MappingFlags::from_name("USER").unwrap(); - if shmflg & 0o400 != 0 { - mapping_flags.insert(MappingFlags::READ); - } - if shmflg & 0o200 != 0 { - mapping_flags.insert(MappingFlags::WRITE); - } - if shmflg & 0o100 != 0 { - mapping_flags.insert(MappingFlags::EXECUTE); - } - - let cur_pid = current().as_thread().proc_data.proc.pid(); - let mut shm_manager = SHM_MANAGER.lock(); - - if key != IPC_PRIVATE { - // This process has already created a shared memory segment with the same key - if let Some(shmid) = shm_manager.get_shmid_by_key(key) { - let shm_inner = shm_manager - .get_inner_by_shmid(shmid) - .ok_or(AxError::InvalidInput)?; - let mut shm_inner = shm_inner.lock(); - return shm_inner.try_update(size, mapping_flags, cur_pid); - } - } - - // Create a new shm_inner - let shmid = next_ipc_id(); - let shm_inner = Arc::new(Mutex::new(ShmInner::new( - key, - shmid, - size, - mapping_flags, - cur_pid, - ))); - shm_manager.insert_key_shmid(key, shmid); - shm_manager.insert_shmid_inner(shmid, shm_inner); - - Ok(shmid as isize) -} - -pub fn sys_shmat(shmid: i32, addr: usize, shmflg: u32) -> AxResult { - let shm_inner = { - let shm_manager = SHM_MANAGER.lock(); - shm_manager.get_inner_by_shmid(shmid).unwrap() - }; - let mut shm_inner = shm_inner.lock(); - let mut mapping_flags = shm_inner.mapping_flags; - let shm_flg = ShmAtFlags::from_bits_truncate(shmflg); - - if shm_flg.contains(ShmAtFlags::SHM_RDONLY) { - mapping_flags.remove(MappingFlags::WRITE); - } - - // TODO: solve shmflg: SHM_RND and SHM_REMAP - - let curr = current(); - let proc_data = &curr.as_thread().proc_data; - let pid = proc_data.proc.pid(); - let mut aspace = proc_data.aspace.lock(); - - let start_aligned = memory_addr::align_down_4k(addr); - let length = shm_inner.page_num * PAGE_SIZE_4K; - - // alloc the virtual address range - assert!(shm_inner.get_addr_range(pid).is_none()); - let start_addr = aspace - .find_free_area( - VirtAddr::from(start_aligned), - length, - VirtAddrRange::new(aspace.base(), aspace.end()), - PAGE_SIZE_4K, - ) - .or_else(|| { - aspace.find_free_area( - aspace.base(), - length, - VirtAddrRange::new(aspace.base(), aspace.end()), - PAGE_SIZE_4K, - ) - }) - .ok_or(AxError::NoMemory)?; - let end_addr = VirtAddr::from(start_addr.as_usize() + length); - let va_range = VirtAddrRange::new(start_addr, end_addr); - - let mut shm_manager = SHM_MANAGER.lock(); - shm_manager.insert_shmid_vaddr(pid, shm_inner.shmid, start_addr); - info!( - "Process {} alloc shm virt addr start: {:#x}, size: {}, mapping_flags: {:#x?}", - pid, - start_addr.as_usize(), - length, - mapping_flags - ); - - // map the virtual address range to the physical address - if let Some(phys_pages) = shm_inner.phys_pages.clone() { - // Another proccess has attached the shared memory - // TODO(mivik): shm page size - let backend = Backend::new_shared(start_addr, phys_pages); - aspace.map(start_addr, length, mapping_flags, false, backend)?; - } else { - // This is the first process to attach the shared memory - let pages = Arc::new(SharedPages::new(length, PageSize::Size4K)?); - let backend = Backend::new_shared(start_addr, pages.clone()); - aspace.map(start_addr, length, mapping_flags, false, backend)?; - - shm_inner.map_to_phys(pages); - } - - shm_inner.attach_process(pid, va_range); - Ok(start_addr.as_usize() as isize) -} - -pub fn sys_shmctl(shmid: i32, cmd: u32, buf: UserPtr) -> AxResult { - let shm_inner = { - let shm_manager = SHM_MANAGER.lock(); - shm_manager - .get_inner_by_shmid(shmid) - .ok_or(AxError::InvalidInput)? - }; - let mut shm_inner = shm_inner.lock(); - - let cmd = cmd as i32; - if cmd == IPC_SET { - shm_inner.shmid_ds = *buf.get_as_mut()?; - } else if cmd == IPC_STAT { - if let Some(shmid_ds) = nullable!(buf.get_as_mut())? { - *shmid_ds = shm_inner.shmid_ds; - } - } else if cmd == IPC_RMID { - shm_inner.rmid = true; - } else { - return Err(AxError::InvalidInput); - } - - shm_inner.shmid_ds.shm_ctime = monotonic_time_nanos() as __kernel_time_t; - Ok(0) -} - -// Garbage collection for shared memory: -// 1. when the process call sys_shmdt, delete everything related to shmaddr, -// including map 'shmid_vaddr'; -// 2. when the last process detach the shared memory and this shared memory was -// specified with IPC_RMID, delete everything related to this shared memory, -// including all the 3 maps; -// 3. when a process exit, delete everything related to this process, including -// 2 maps: 'shmid_vaddr' and 'shmid_inner'; -// -// The attach between the process and the shared memory occurs in sys_shmat, -// and the detach occurs in sys_shmdt, or when the process exits. - -// Note: all the below delete functions only delete the mapping between the -// shm_id and the shm_inner, but the shm_inner is not deleted or modifyed! -pub fn sys_shmdt(shmaddr: usize) -> AxResult { - let shmaddr = VirtAddr::from(shmaddr); - - let curr = current(); - let proc_data = &curr.as_thread().proc_data; - - let pid = proc_data.proc.pid(); - let shmid = { - let shm_manager = SHM_MANAGER.lock(); - shm_manager - .get_shmid_by_vaddr(pid, shmaddr) - .ok_or(AxError::InvalidInput)? - }; - - let shm_inner = { - let shm_manager = SHM_MANAGER.lock(); - shm_manager - .get_inner_by_shmid(shmid) - .ok_or(AxError::InvalidInput)? - }; - let mut shm_inner = shm_inner.lock(); - let va_range = shm_inner.get_addr_range(pid).ok_or(AxError::InvalidInput)?; - - let mut aspace = proc_data.aspace.lock(); - aspace.unmap(va_range.start, va_range.size())?; - - let mut shm_manager = SHM_MANAGER.lock(); - shm_manager.remove_shmaddr(pid, shmaddr); - shm_inner.detach_process(pid); - - if shm_inner.rmid && shm_inner.attach_count() == 0 { - shm_manager.remove_shmid(shmid); - } - - Ok(0) -} diff --git a/api/src/task.rs b/api/src/task.rs deleted file mode 100644 index aaadb6c3..00000000 --- a/api/src/task.rs +++ /dev/null @@ -1,220 +0,0 @@ -use core::{ffi::c_long, sync::atomic::Ordering}; - -use axerrno::{AxError, AxResult}; -use axhal::uspace::{ExceptionKind, ReturnReason, UserContext}; -use axtask::{TaskInner, current}; -use bytemuck::AnyBitPattern; -use linux_raw_sys::general::ROBUST_LIST_LIMIT; -use starry_core::{ - futex::FutexKey, - shm::SHM_MANAGER, - task::{ - AsThread, get_process_data, get_task, send_signal_to_process, send_signal_to_thread, - set_timer_state, - }, - time::TimerState, -}; -use starry_process::Pid; -use starry_signal::{SignalInfo, Signo}; -use starry_vm::{VmMutPtr, VmPtr}; - -use crate::{ - signal::{check_signals, unblock_next_signal}, - syscall::handle_syscall, -}; - -/// Create a new user task. -pub fn new_user_task(name: &str, mut uctx: UserContext, set_child_tid: usize) -> TaskInner { - TaskInner::new( - move || { - let curr = axtask::current(); - - if let Some(tid) = (set_child_tid as *mut Pid).nullable() { - tid.vm_write(curr.id().as_u64() as Pid).ok(); - } - - info!("Enter user space: ip={:#x}, sp={:#x}", uctx.ip(), uctx.sp()); - - let thr = curr.as_thread(); - while !thr.pending_exit() { - let reason = uctx.run(); - - set_timer_state(&curr, TimerState::Kernel); - - match reason { - ReturnReason::Syscall => handle_syscall(&mut uctx), - ReturnReason::PageFault(addr, flags) => { - if !thr.proc_data.aspace.lock().handle_page_fault(addr, flags) { - info!( - "{:?}: segmentation fault at {:#x} {:?}", - thr.proc_data.proc, addr, flags - ); - raise_signal_fatal(SignalInfo::new_kernel(Signo::SIGSEGV)) - .expect("Failed to send SIGSEGV"); - } - } - ReturnReason::Interrupt => {} - #[allow(unused_labels)] - ReturnReason::Exception(exc_info) => 'exc: { - // TODO: detailed handling - let signo = match exc_info.kind() { - ExceptionKind::Misaligned => { - #[cfg(target_arch = "loongarch64")] - if unsafe { uctx.emulate_unaligned() }.is_ok() { - break 'exc; - } - Signo::SIGBUS - } - ExceptionKind::Breakpoint => Signo::SIGTRAP, - ExceptionKind::IllegalInstruction => Signo::SIGILL, - _ => Signo::SIGTRAP, - }; - raise_signal_fatal(SignalInfo::new_kernel(signo)) - .expect("Failed to send SIGTRAP"); - } - r => { - warn!("Unexpected return reason: {r:?}"); - raise_signal_fatal(SignalInfo::new_kernel(Signo::SIGSEGV)) - .expect("Failed to send SIGSEGV"); - } - } - - if !unblock_next_signal() { - while check_signals(thr, &mut uctx, None) {} - } - - set_timer_state(&curr, TimerState::User); - curr.clear_interrupt(); - } - }, - name.into(), - starry_core::config::KERNEL_STACK_SIZE, - ) -} - -#[repr(C)] -#[derive(Debug, Copy, Clone, AnyBitPattern)] -pub struct RobustList { - pub next: *mut RobustList, -} - -#[repr(C)] -#[derive(Debug, Copy, Clone, AnyBitPattern)] -pub struct RobustListHead { - pub list: RobustList, - pub futex_offset: c_long, - pub list_op_pending: *mut RobustList, -} - -fn handle_futex_death(entry: *mut RobustList, offset: i64) -> AxResult<()> { - let address = (entry as u64) - .checked_add_signed(offset) - .ok_or(AxError::InvalidInput)?; - let address: usize = address.try_into().map_err(|_| AxError::InvalidInput)?; - let key = FutexKey::new_current(address); - - let curr = current(); - let futex_table = curr.as_thread().proc_data.futex_table_for(&key); - - let Some(futex) = futex_table.get(&key) else { - return Ok(()); - }; - futex.owner_dead.store(true, Ordering::SeqCst); - futex.wq.wake(1, u32::MAX); - Ok(()) -} - -pub fn exit_robust_list(head: *const RobustListHead) -> AxResult<()> { - // Reference: https://elixir.bootlin.com/linux/v6.13.6/source/kernel/futex/core.c#L777 - - let mut limit = ROBUST_LIST_LIMIT; - - let end_ptr = unsafe { &raw const (*head).list }; - let head = head.vm_read()?; - let mut entry = head.list.next; - let offset = head.futex_offset; - let pending = head.list_op_pending; - - while !core::ptr::eq(entry, end_ptr) { - let next_entry = entry.vm_read()?.next; - if entry != pending { - handle_futex_death(entry, offset)?; - } - entry = next_entry; - - limit -= 1; - if limit == 0 { - return Err(AxError::FilesystemLoop); - } - axtask::yield_now(); - } - - Ok(()) -} - -pub fn do_exit(exit_code: i32, group_exit: bool) { - let curr = current(); - let thr = curr.as_thread(); - - info!("{} exit with code: {}", curr.id_name(), exit_code); - - let clear_child_tid = thr.clear_child_tid() as *mut u32; - if clear_child_tid.vm_write(0).is_ok() { - let key = FutexKey::new_current(clear_child_tid as usize); - let table = thr.proc_data.futex_table_for(&key); - let guard = table.get(&key); - if let Some(futex) = guard { - futex.wq.wake(1, u32::MAX); - } - axtask::yield_now(); - } - let head = thr.robust_list_head() as *const RobustListHead; - if !head.is_null() - && let Err(err) = exit_robust_list(head) - { - warn!("exit robust list failed: {err:?}"); - } - - let process = &thr.proc_data.proc; - if process.exit_thread(curr.id().as_u64() as Pid, exit_code) { - process.exit(); - if let Some(parent) = process.parent() { - if let Some(signo) = thr.proc_data.exit_signal { - let _ = send_signal_to_process(parent.pid(), Some(SignalInfo::new_kernel(signo))); - } - if let Ok(data) = get_process_data(parent.pid()) { - data.child_exit_event.wake(); - } - } - thr.proc_data.exit_event.wake(); - - SHM_MANAGER.lock().clear_proc_shm(process.pid()); - } - if group_exit && !process.is_group_exited() { - process.group_exit(); - let sig = SignalInfo::new_kernel(Signo::SIGKILL); - for tid in process.threads() { - let _ = send_signal_to_thread(None, tid, Some(sig.clone())); - } - } - thr.set_exit(); -} - -/// Sends a fatal signal to the current process. -pub fn raise_signal_fatal(sig: SignalInfo) -> AxResult<()> { - let curr = current(); - let proc_data = &curr.as_thread().proc_data; - - let signo = sig.signo(); - info!("Send fatal signal {signo:?} to the current process"); - if let Some(tid) = proc_data.signal.send_signal(sig) - && let Ok(task) = get_task(tid) - { - task.interrupt(); - } else { - // No task wants to handle the signal, abort the task - do_exit(signo as i32, true); - } - - Ok(()) -} diff --git a/core/Cargo.toml b/core/Cargo.toml deleted file mode 100644 index a4beff17..00000000 --- a/core/Cargo.toml +++ /dev/null @@ -1,53 +0,0 @@ -[package] -name = "starry-core" -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true -homepage.workspace = true -repository.workspace = true - -[dependencies] -axbacktrace.workspace = true -axconfig.workspace = true -axerrno.workspace = true -axfeat.workspace = true -axfs-ng-vfs.workspace = true -axfs.workspace = true -axhal.workspace = true -axio.workspace = true -axlog.workspace = true -axmm.workspace = true -axpoll.workspace = true -axsync.workspace = true -axtask.workspace = true -bitflags.workspace = true -bytemuck = { workspace = true, features = ["derive"] } -cfg-if.workspace = true -event-listener.workspace = true -extern-trait.workspace = true -hashbrown = { workspace = true } -inherit-methods-macro = "0.1.0" -kernel_guard = "0.1" -kernel-elf-parser = "0.3.4" -kspin.workspace = true -lazy_static = { workspace = true } -linkme.workspace = true -linux-raw-sys.workspace = true -lock_api = { version = "0.4.13", features = ["arc_lock"] } -memory_addr.workspace = true -ouroboros = { version = "0.18.5", default-features = false } -percpu = "0.2.0" -scope-local.workspace = true -slab.workspace = true -spin.workspace = true -starry-process.workspace = true -starry-signal.workspace = true -starry-vm.workspace = true -strum = { version = "0.27.2", default-features = false, features = ["derive"] } -uluru = "3.1.0" -weak-map = "0.1.1" -xmas-elf = "0.9" - -[target.'cfg(not(any(target_arch = "aarch64", target_arch = "loongarch64")))'.dependencies] -axmm = { workspace = true, features = ["copy"] } diff --git a/core/src/lib.rs b/core/src/lib.rs deleted file mode 100644 index c4e8e09c..00000000 --- a/core/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! The core functionality of a monolithic kernel, including loading user -//! programs and managing processes. - -#![no_std] -#![feature(likely_unlikely)] -#![warn(missing_docs)] - -extern crate alloc; - -#[macro_use] -extern crate axlog; - -pub mod config; -pub mod futex; -pub mod mm; -pub mod resources; -pub mod shm; -pub mod task; -pub mod time; -pub mod vfs; diff --git a/core/src/vfs/mod.rs b/core/src/vfs/mod.rs deleted file mode 100644 index ce3557ab..00000000 --- a/core/src/vfs/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Basic virtual filesystem support - -mod dev; -mod dir; -mod file; -mod fs; - -use alloc::sync::Arc; - -use axfs_ng_vfs::{DirNodeOps, FileNodeOps, WeakDirEntry}; -pub use dev::*; -pub use dir::*; -pub use file::*; -pub use fs::*; - -/// A callback that builds a `Arc` for a given -/// `WeakDirEntry`. -pub type DirMaker = Arc Arc + Send + Sync>; - -/// An enum containing either a directory ([`DirMaker`]) or a file (`Arc`). -#[derive(Clone)] -pub enum NodeOpsMux { - /// A directory node. - Dir(DirMaker), - /// A file node. - File(Arc), -} - -impl From for NodeOpsMux { - fn from(maker: DirMaker) -> Self { - Self::Dir(maker) - } -} - -impl From> for NodeOpsMux { - fn from(ops: Arc) -> Self { - Self::File(ops) - } -} diff --git a/api/Cargo.toml b/kernel/Cargo.toml similarity index 78% rename from api/Cargo.toml rename to kernel/Cargo.toml index 73fa91ef..7e410ec2 100644 --- a/api/Cargo.toml +++ b/kernel/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "starry-api" +name = "starry-kernel" version.workspace = true edition.workspace = true authors.workspace = true @@ -34,22 +34,28 @@ axsync.workspace = true axtask.workspace = true bitflags.workspace = true bitmaps = { version = "3.2.1", default-features = false } -bytemuck.workspace = true +bytemuck = { workspace = true, features = ["derive"] } cfg-if.workspace = true chrono = { version = "0.4.41", default-features = false } downcast-rs = { version = "2.0", default-features = false, features = ["sync"] } event-listener.workspace = true +extern-trait.workspace = true flatten_objects = "0.2.4" gimli = { version = "*", default-features = false, optional = true } hashbrown = { workspace = true } indoc = "2" inherit-methods-macro = "0.1.0" +kernel_guard = "0.1" +kernel-elf-parser = "0.3.4" kspin.workspace = true lazy_static = { workspace = true } linkme.workspace = true linux-raw-sys = { workspace = true, features = ["ioctl", "loop_device"] } +lock_api = { version = "0.4.13", features = ["arc_lock"] } memory_addr.workspace = true num_enum = { version = "0.7", default-features = false } +ouroboros = { version = "0.18.5", default-features = false } +percpu = "0.2.0" rand = { version = "0.10", default-features = false, features = ["alloc"] } ringbuf = { version = "0.4.8", default-features = false, features = ["alloc"] } scope-local.workspace = true @@ -58,13 +64,18 @@ spin.workspace = true starry-process.workspace = true starry-signal.workspace = true starry-vm.workspace = true +strum = { version = "0.27.2", default-features = false, features = ["derive"] } syscalls = { version = "0.8.1", default-features = false } +uluru = "3.1.0" +weak-map = "0.1.1" +xmas-elf = "0.9" zerocopy = { version = "0.8.26", features = ["derive"] } -starry-core.workspace = true - [target.'cfg(target_arch = "x86_64")'.dependencies] x86 = "0.52" [target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] riscv = "0.16" + +[target.'cfg(not(any(target_arch = "aarch64", target_arch = "loongarch64")))'.dependencies] +axmm = { workspace = true, features = ["copy"] } diff --git a/core/src/config/aarch64.rs b/kernel/src/config/aarch64.rs similarity index 100% rename from core/src/config/aarch64.rs rename to kernel/src/config/aarch64.rs diff --git a/core/src/config/loongarch64.rs b/kernel/src/config/loongarch64.rs similarity index 100% rename from core/src/config/loongarch64.rs rename to kernel/src/config/loongarch64.rs diff --git a/core/src/config/mod.rs b/kernel/src/config/mod.rs similarity index 100% rename from core/src/config/mod.rs rename to kernel/src/config/mod.rs diff --git a/core/src/config/riscv64.rs b/kernel/src/config/riscv64.rs similarity index 100% rename from core/src/config/riscv64.rs rename to kernel/src/config/riscv64.rs diff --git a/core/src/config/x86_64.rs b/kernel/src/config/x86_64.rs similarity index 100% rename from core/src/config/x86_64.rs rename to kernel/src/config/x86_64.rs diff --git a/api/src/file/epoll.rs b/kernel/src/file/epoll.rs similarity index 100% rename from api/src/file/epoll.rs rename to kernel/src/file/epoll.rs diff --git a/api/src/file/event.rs b/kernel/src/file/event.rs similarity index 100% rename from api/src/file/event.rs rename to kernel/src/file/event.rs diff --git a/api/src/file/fs.rs b/kernel/src/file/fs.rs similarity index 100% rename from api/src/file/fs.rs rename to kernel/src/file/fs.rs diff --git a/api/src/file/mod.rs b/kernel/src/file/mod.rs similarity index 99% rename from api/src/file/mod.rs rename to kernel/src/file/mod.rs index 54def198..33d0c4df 100644 --- a/api/src/file/mod.rs +++ b/kernel/src/file/mod.rs @@ -19,7 +19,6 @@ use downcast_rs::{DowncastSync, impl_downcast}; use flatten_objects::FlattenObjects; use linux_raw_sys::general::{RLIMIT_NOFILE, stat, statx, statx_timestamp}; use spin::RwLock; -use starry_core::{resources::AX_FILE_LIMIT, task::AsThread}; pub use self::{ fs::{Directory, File, ResolveAtResult, metadata_to_kstat, resolve_at, with_fs}, @@ -27,6 +26,7 @@ pub use self::{ pidfd::PidFd, pipe::Pipe, }; +use crate::task::{AX_FILE_LIMIT, AsThread}; #[derive(Debug, Clone, Copy)] pub struct Kstat { diff --git a/api/src/file/net.rs b/kernel/src/file/net.rs similarity index 100% rename from api/src/file/net.rs rename to kernel/src/file/net.rs diff --git a/api/src/file/pidfd.rs b/kernel/src/file/pidfd.rs similarity index 94% rename from api/src/file/pidfd.rs rename to kernel/src/file/pidfd.rs index 3b72ffc2..1debab76 100644 --- a/api/src/file/pidfd.rs +++ b/kernel/src/file/pidfd.rs @@ -6,9 +6,8 @@ use core::task::Context; use axerrno::{AxError, AxResult}; use axpoll::{IoEvents, PollSet, Pollable}; -use starry_core::task::ProcessData; -use crate::file::FileLike; +use crate::{file::FileLike, task::ProcessData}; pub struct PidFd { proc_data: Weak, diff --git a/api/src/file/pipe.rs b/kernel/src/file/pipe.rs similarity index 98% rename from api/src/file/pipe.rs rename to kernel/src/file/pipe.rs index 8edcde71..e8517073 100644 --- a/api/src/file/pipe.rs +++ b/kernel/src/file/pipe.rs @@ -18,12 +18,14 @@ use ringbuf::{ HeapRb, traits::{Consumer, Observer, Producer}, }; -use starry_core::task::{AsThread, send_signal_to_process}; use starry_signal::{SignalInfo, Signo}; use starry_vm::VmMutPtr; use super::{FileLike, Kstat}; -use crate::file::{IoDst, IoSrc}; +use crate::{ + file::{IoDst, IoSrc}, + task::{AsThread, send_signal_to_process}, +}; const RING_BUFFER_INIT_SIZE: usize = 65536; // 64 KiB diff --git a/api/src/file/signalfd.rs b/kernel/src/file/signalfd.rs similarity index 98% rename from api/src/file/signalfd.rs rename to kernel/src/file/signalfd.rs index c6308c82..08c36807 100644 --- a/api/src/file/signalfd.rs +++ b/kernel/src/file/signalfd.rs @@ -12,11 +12,13 @@ use axtask::{ future::{block_on, poll_io}, }; use spin::RwLock; -use starry_core::task::AsThread; use starry_signal::{SignalInfo, SignalSet}; use zerocopy::{Immutable, IntoBytes}; -use crate::file::{FileLike, IoDst, IoSrc}; +use crate::{ + file::{FileLike, IoDst, IoSrc}, + task::AsThread, +}; /// The size of signalfd_siginfo structure (128 bytes as per Linux /// specification) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs new file mode 100644 index 00000000..042fdd97 --- /dev/null +++ b/kernel/src/lib.rs @@ -0,0 +1,30 @@ +//! The core functionality of a monolithic kernel, including loading user +//! programs and managing processes. + +#![no_std] +#![feature(likely_unlikely)] +#![feature(bstr)] +#![allow(missing_docs)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +extern crate alloc; + +#[macro_use] +extern crate axlog; + +pub mod config; +pub mod file; +pub mod mm; +pub mod pseudofs; +pub mod syscall; +pub mod task; +pub mod time; + +/// Initialize. +pub fn init() { + info!("Initialize pseudofs..."); + pseudofs::mount_all().expect("Failed to mount pseudofs"); + + info!("Initialize alarm..."); + task::spawn_alarm_task(); +} diff --git a/api/src/mm.rs b/kernel/src/mm/aspace.rs similarity index 82% rename from api/src/mm.rs rename to kernel/src/mm/aspace.rs index a6c8c695..313e04ce 100644 --- a/api/src/mm.rs +++ b/kernel/src/mm/aspace.rs @@ -9,14 +9,35 @@ use core::{ use axerrno::{AxError, AxResult}; use axhal::{ + asm::user_copy, paging::MappingFlags, trap::{PAGE_FAULT, register_trap_handler}, }; use axio::prelude::*; use axtask::current; +use extern_trait::extern_trait; +use kernel_guard::IrqSave; use memory_addr::{MemoryAddr, PAGE_SIZE_4K, VirtAddr}; -use starry_core::{mm::access_user_memory, task::AsThread}; -use starry_vm::{vm_load_until_nul, vm_read_slice, vm_write_slice}; +use starry_vm::{VmError, VmIo, VmResult, vm_load_until_nul, vm_read_slice, vm_write_slice}; + +use crate::{ + config::{USER_SPACE_BASE, USER_SPACE_SIZE}, + task::AsThread, +}; + +/// Enables scoped access into user memory, allowing page faults to occur inside +/// kernel. +pub fn access_user_memory(f: impl FnOnce() -> R) -> R { + let curr = current(); + let Some(thr) = curr.try_as_thread() else { + panic!("access_user_memory called outside of thread context"); + }; + + thr.set_accessing_user_memory(true); + let result = f(); + thr.set_accessing_user_memory(false); + result +} fn check_region(start: VirtAddr, layout: Layout, access_flags: MappingFlags) -> AxResult<()> { let align = layout.align(); @@ -259,6 +280,51 @@ pub fn vm_load_string(ptr: *const c_char) -> AxResult { String::from_utf8(bytes).map_err(|_| AxError::IllegalBytes) } +#[allow(dead_code)] +struct Vm(IrqSave); + +/// Briefly checks if the given memory region is valid user memory. +pub fn check_access(start: usize, len: usize) -> VmResult { + const USER_SPACE_END: usize = USER_SPACE_BASE + USER_SPACE_SIZE; + let ok = (USER_SPACE_BASE..USER_SPACE_END).contains(&start) && (USER_SPACE_END - start) >= len; + if unlikely(!ok) { + Err(VmError::AccessDenied) + } else { + Ok(()) + } +} + +#[extern_trait] +unsafe impl VmIo for Vm { + fn new() -> Self { + Self(IrqSave::new()) + } + + fn read(&mut self, start: usize, buf: &mut [MaybeUninit]) -> VmResult { + check_access(start, buf.len())?; + let failed_at = access_user_memory(|| unsafe { + user_copy(buf.as_mut_ptr() as *mut _, start as _, buf.len()) + }); + if unlikely(failed_at != 0) { + Err(VmError::AccessDenied) + } else { + Ok(()) + } + } + + fn write(&mut self, start: usize, buf: &[u8]) -> VmResult { + check_access(start, buf.len())?; + let failed_at = access_user_memory(|| unsafe { + user_copy(start as _, buf.as_ptr() as *const _, buf.len()) + }); + if unlikely(failed_at != 0) { + Err(VmError::AccessDenied) + } else { + Ok(()) + } + } +} + /// A read-only buffer in the VM's memory. /// /// It implements the `axio::Read` trait, allowing it to be used with other I/O diff --git a/api/src/io.rs b/kernel/src/mm/io.rs similarity index 100% rename from api/src/io.rs rename to kernel/src/mm/io.rs diff --git a/core/src/mm.rs b/kernel/src/mm/loader.rs similarity index 83% rename from core/src/mm.rs rename to kernel/src/mm/loader.rs index 6672a81a..77d87907 100644 --- a/core/src/mm.rs +++ b/kernel/src/mm/loader.rs @@ -1,38 +1,27 @@ //! User address space management. use alloc::{borrow::ToOwned, string::String, vec, vec::Vec}; -use core::{ffi::CStr, hint::unlikely, iter, mem::MaybeUninit}; +use core::{ffi::CStr, iter}; use axerrno::{AxError, AxResult}; use axfs::{CachedFile, FS_CONTEXT, FileBackend}; use axfs_ng_vfs::Location; use axhal::{ - asm::user_copy, mem::virt_to_phys, paging::{MappingFlags, PageSize}, }; use axmm::{AddrSpace, backend::Backend}; use axsync::Mutex; -use axtask::current; -use extern_trait::extern_trait; use kernel_elf_parser::{AuxEntry, ELFHeaders, ELFHeadersBuilder, ELFParser, app_stack_region}; -use kernel_guard::IrqSave; use memory_addr::{MemoryAddr, PAGE_SIZE_4K, VirtAddr}; use ouroboros::self_referencing; -use starry_vm::{VmError, VmIo, VmResult}; use uluru::LRUCache; -use crate::{ - config::{USER_SPACE_BASE, USER_SPACE_SIZE}, - task::AsThread, -}; +use crate::config::{USER_SPACE_BASE, USER_SPACE_SIZE}; /// Creates a new empty user address space. pub fn new_user_aspace_empty() -> AxResult { - AddrSpace::new_empty( - VirtAddr::from_usize(crate::config::USER_SPACE_BASE), - crate::config::USER_SPACE_SIZE, - ) + AddrSpace::new_empty(VirtAddr::from_usize(USER_SPACE_BASE), USER_SPACE_SIZE) } /// If the target architecture requires it, the kernel portion of the address @@ -347,62 +336,3 @@ pub fn load_user_app( Ok((entry, user_sp)) } - -/// Enables scoped access into user memory, allowing page faults to occur inside -/// kernel. -pub fn access_user_memory(f: impl FnOnce() -> R) -> R { - let curr = current(); - let Some(thr) = curr.try_as_thread() else { - panic!("access_user_memory called outside of thread context"); - }; - - thr.set_accessing_user_memory(true); - let result = f(); - thr.set_accessing_user_memory(false); - result -} - -#[allow(dead_code)] -struct Vm(IrqSave); - -/// Briefly checks if the given memory region is valid user memory. -pub fn check_access(start: usize, len: usize) -> VmResult { - const USER_SPACE_END: usize = USER_SPACE_BASE + USER_SPACE_SIZE; - let ok = (USER_SPACE_BASE..USER_SPACE_END).contains(&start) && (USER_SPACE_END - start) >= len; - if unlikely(!ok) { - Err(VmError::AccessDenied) - } else { - Ok(()) - } -} - -#[extern_trait] -unsafe impl VmIo for Vm { - fn new() -> Self { - Self(IrqSave::new()) - } - - fn read(&mut self, start: usize, buf: &mut [MaybeUninit]) -> VmResult { - check_access(start, buf.len())?; - let failed_at = access_user_memory(|| unsafe { - user_copy(buf.as_mut_ptr() as *mut _, start as _, buf.len()) - }); - if unlikely(failed_at != 0) { - Err(VmError::AccessDenied) - } else { - Ok(()) - } - } - - fn write(&mut self, start: usize, buf: &[u8]) -> VmResult { - check_access(start, buf.len())?; - let failed_at = access_user_memory(|| unsafe { - user_copy(start as _, buf.as_ptr() as *const _, buf.len()) - }); - if unlikely(failed_at != 0) { - Err(VmError::AccessDenied) - } else { - Ok(()) - } - } -} diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs new file mode 100644 index 00000000..97e957ea --- /dev/null +++ b/kernel/src/mm/mod.rs @@ -0,0 +1,7 @@ +//! User address space management and user-space memory access. + +mod aspace; +mod io; +mod loader; + +pub use self::{aspace::*, io::*, loader::*}; diff --git a/api/src/vfs/dev/event.rs b/kernel/src/pseudofs/dev/event.rs similarity index 99% rename from api/src/vfs/dev/event.rs rename to kernel/src/pseudofs/dev/event.rs index 389ede1e..683874a7 100644 --- a/api/src/vfs/dev/event.rs +++ b/kernel/src/pseudofs/dev/event.rs @@ -15,10 +15,12 @@ use linux_raw_sys::{ general::{__kernel_old_time_t, __kernel_suseconds_t}, ioctl::{EVIOCGID, EVIOCGRAB, EVIOCGVERSION}, }; -use starry_core::vfs::{Device, DeviceOps, DirMapping, SimpleFs}; use zerocopy::{FromBytes, Immutable, IntoBytes}; -use crate::mm::UserPtr; +use crate::{ + mm::UserPtr, + pseudofs::{Device, DeviceOps, DirMapping, SimpleFs}, +}; const KEY_CNT: usize = EventType::Key.bits_count(); struct Inner { diff --git a/api/src/vfs/dev/fb.rs b/kernel/src/pseudofs/dev/fb.rs similarity index 99% rename from api/src/vfs/dev/fb.rs rename to kernel/src/pseudofs/dev/fb.rs index 27069dea..2ca919d0 100644 --- a/api/src/vfs/dev/fb.rs +++ b/kernel/src/pseudofs/dev/fb.rs @@ -6,9 +6,10 @@ use axerrno::AxError; use axfs_ng_vfs::{NodeFlags, VfsError, VfsResult}; use axhal::mem::virt_to_phys; use memory_addr::{PhysAddrRange, VirtAddr}; -use starry_core::vfs::{DeviceMmap, DeviceOps}; use starry_vm::VmMutPtr; +use crate::pseudofs::{DeviceMmap, DeviceOps}; + // Types from https://github.com/Tangzh33/asterinas #[repr(C)] diff --git a/api/src/vfs/dev/log.rs b/kernel/src/pseudofs/dev/log.rs similarity index 100% rename from api/src/vfs/dev/log.rs rename to kernel/src/pseudofs/dev/log.rs diff --git a/api/src/vfs/dev/loop.rs b/kernel/src/pseudofs/dev/loop.rs similarity index 98% rename from api/src/vfs/dev/loop.rs rename to kernel/src/pseudofs/dev/loop.rs index fc4d5d74..679387c7 100644 --- a/api/src/vfs/dev/loop.rs +++ b/kernel/src/pseudofs/dev/loop.rs @@ -11,10 +11,12 @@ use linux_raw_sys::{ ioctl::{BLKGETSIZE, BLKGETSIZE64, BLKRAGET, BLKRASET, BLKROGET, BLKROSET}, loop_device::{LOOP_CLR_FD, LOOP_GET_STATUS, LOOP_SET_FD, LOOP_SET_STATUS, loop_info}, }; -use starry_core::vfs::{DeviceMmap, DeviceOps}; use starry_vm::{VmMutPtr, VmPtr}; -use crate::file::get_file_like; +use crate::{ + file::get_file_like, + pseudofs::{DeviceMmap, DeviceOps}, +}; /// /dev/loopX devices pub struct LoopDevice { diff --git a/api/src/vfs/dev/memtrack.rs b/kernel/src/pseudofs/dev/memtrack.rs similarity index 99% rename from api/src/vfs/dev/memtrack.rs rename to kernel/src/pseudofs/dev/memtrack.rs index c1b99a2d..9eb7c477 100644 --- a/api/src/vfs/dev/memtrack.rs +++ b/kernel/src/pseudofs/dev/memtrack.rs @@ -8,13 +8,13 @@ use core::{ use axbacktrace::Backtrace; use axfs_ng_vfs::{NodeFlags, VfsResult}; -use starry_core::{ + +use crate::{ mm::clear_elf_cache, task::{cleanup_task_tables, tasks}, + vfs::DeviceOps, }; -use crate::vfs::DeviceOps; - static STAMPED_GENERATION: AtomicU64 = AtomicU64::new(0); #[derive(PartialEq, Eq, PartialOrd, Ord)] diff --git a/api/src/vfs/dev/mod.rs b/kernel/src/pseudofs/dev/mod.rs similarity index 97% rename from api/src/vfs/dev/mod.rs rename to kernel/src/pseudofs/dev/mod.rs index dbd0c8d4..68410e1a 100644 --- a/api/src/vfs/dev/mod.rs +++ b/kernel/src/pseudofs/dev/mod.rs @@ -20,7 +20,8 @@ use axsync::Mutex; #[cfg(feature = "dev-log")] pub use log::bind_dev_log; use rand::{Rng, SeedableRng, rngs::SmallRng}; -use starry_core::vfs::{Device, DeviceOps, DirMaker, DirMapping, SimpleDir, SimpleFs}; + +use crate::pseudofs::{Device, DeviceOps, DirMaker, DirMapping, SimpleDir, SimpleFs}; const RANDOM_SEED: &[u8; 32] = b"0123456789abcdef0123456789abcdef"; @@ -244,7 +245,7 @@ fn builder(fs: Arc) -> DirMaker { #[cfg(feature = "dev-log")] root.add( "log", - starry_core::vfs::SimpleFile::new(fs.clone(), NodeType::Socket, || Ok(b"")), + crate::pseudofs::SimpleFile::new(fs.clone(), NodeType::Socket, || Ok(b"")), ); #[cfg(feature = "memtrack")] diff --git a/api/src/vfs/dev/rtc.rs b/kernel/src/pseudofs/dev/rtc.rs similarity index 98% rename from api/src/vfs/dev/rtc.rs rename to kernel/src/pseudofs/dev/rtc.rs index 6eefe2bd..1131dbb3 100644 --- a/api/src/vfs/dev/rtc.rs +++ b/kernel/src/pseudofs/dev/rtc.rs @@ -5,7 +5,7 @@ use chrono::{Datelike, Timelike}; use linux_raw_sys::ioctl::RTC_RD_TIME; use starry_vm::VmMutPtr; -use crate::vfs::DeviceOps; +use crate::pseudofs::DeviceOps; /// The device ID for /dev/rtc0 pub const RTC0_DEVICE_ID: DeviceId = DeviceId::new(250, 0); diff --git a/api/src/vfs/dev/tty.rs b/kernel/src/pseudofs/dev/tty/mod.rs similarity index 95% rename from api/src/vfs/dev/tty.rs rename to kernel/src/pseudofs/dev/tty/mod.rs index a26dfc32..fa8c1971 100644 --- a/api/src/vfs/dev/tty.rs +++ b/kernel/src/pseudofs/dev/tty/mod.rs @@ -1,3 +1,9 @@ +mod ntty; +mod ptm; +mod pts; +mod pty; +mod terminal; + use alloc::sync::{Arc, Weak}; use core::{any::Any, ops::Deref, sync::atomic::Ordering, task::Context}; @@ -9,29 +15,25 @@ use axtask::{ current, future::{block_on, poll_io}, }; -use starry_core::{task::AsThread, vfs::SimpleFs}; use starry_process::Process; use starry_vm::{VmMutPtr, VmPtr}; +use self::terminal::{ + Terminal, WindowSize, + ldisc::{LineDiscipline, ProcessMode, TtyConfig, TtyRead, TtyWrite}, + termios::{Termios, Termios2}, +}; +pub use self::{ + ntty::{N_TTY, NTtyDriver}, + ptm::Ptmx, + pts::PtsDir, + pty::PtyDriver, +}; use crate::{ - terminal::{ - Terminal, WindowSize, - ldisc::{LineDiscipline, ProcessMode, TtyConfig, TtyRead, TtyWrite}, - termios::{Termios, Termios2}, - }, - vfs::DeviceOps, + pseudofs::{DeviceOps, SimpleFs}, + task::AsThread, }; -mod ntty; -mod ptm; -mod pts; -mod pty; - -pub use ntty::{N_TTY, NTtyDriver}; -pub use ptm::Ptmx; -pub use pts::PtsDir; -pub use pty::PtyDriver; - pub fn create_pty_master(fs: Arc) -> AxResult> { let (master, slave) = pty::create_pty_pair(); pts::add_slave(fs, slave)?; diff --git a/api/src/vfs/dev/tty/ntty.rs b/kernel/src/pseudofs/dev/tty/ntty.rs similarity index 91% rename from api/src/vfs/dev/tty/ntty.rs rename to kernel/src/pseudofs/dev/tty/ntty.rs index a4a1d55b..2b3e6eb6 100644 --- a/api/src/vfs/dev/tty/ntty.rs +++ b/kernel/src/pseudofs/dev/tty/ntty.rs @@ -3,8 +3,10 @@ use alloc::{boxed::Box, sync::Arc}; use axtask::future::register_irq_waker; use lazy_static::lazy_static; -use super::Tty; -use crate::terminal::ldisc::{ProcessMode, TtyConfig, TtyRead, TtyWrite}; +use super::{ + Tty, + terminal::ldisc::{ProcessMode, TtyConfig, TtyRead, TtyWrite}, +}; pub type NTtyDriver = Tty; diff --git a/api/src/vfs/dev/tty/ptm.rs b/kernel/src/pseudofs/dev/tty/ptm.rs similarity index 95% rename from api/src/vfs/dev/tty/ptm.rs rename to kernel/src/pseudofs/dev/tty/ptm.rs index 37f538cf..1c3f0c0c 100644 --- a/api/src/vfs/dev/tty/ptm.rs +++ b/kernel/src/pseudofs/dev/tty/ptm.rs @@ -3,7 +3,8 @@ use core::any::Any; use axerrno::AxResult; use axfs_ng_vfs::{DeviceId, NodeType}; -use starry_core::vfs::{Device, DeviceOps, SimpleFs}; + +use crate::pseudofs::{Device, DeviceOps, SimpleFs}; pub struct Ptmx(pub Arc); impl Ptmx { diff --git a/api/src/vfs/dev/tty/pts.rs b/kernel/src/pseudofs/dev/tty/pts.rs similarity index 93% rename from api/src/vfs/dev/tty/pts.rs rename to kernel/src/pseudofs/dev/tty/pts.rs index fe927891..f3c4b47b 100644 --- a/api/src/vfs/dev/tty/pts.rs +++ b/kernel/src/pseudofs/dev/tty/pts.rs @@ -5,9 +5,8 @@ use axerrno::{AxError, AxResult}; use axfs_ng_vfs::{DeviceId, NodeType, VfsResult}; use flatten_objects::FlattenObjects; use kspin::SpinNoIrq; -use starry_core::vfs::{Device, NodeOpsMux, SimpleDirOps, SimpleFs}; -use crate::vfs::dev::tty::pty::PtyDriver; +use crate::pseudofs::{Device, NodeOpsMux, SimpleDirOps, SimpleFs, dev::tty::pty::PtyDriver}; static PTS_TABLE: SpinNoIrq, 16>> = SpinNoIrq::new(FlattenObjects::new()); diff --git a/api/src/vfs/dev/tty/pty.rs b/kernel/src/pseudofs/dev/tty/pty.rs similarity index 94% rename from api/src/vfs/dev/tty/pty.rs rename to kernel/src/pseudofs/dev/tty/pty.rs index 821f5a9c..7114b933 100644 --- a/api/src/vfs/dev/tty/pty.rs +++ b/kernel/src/pseudofs/dev/tty/pty.rs @@ -7,10 +7,12 @@ use ringbuf::{ traits::{Consumer, Producer}, }; -use super::Tty; -use crate::terminal::{ - Terminal, - ldisc::{ProcessMode, TtyConfig, TtyRead, TtyWrite}, +use super::{ + Tty, + terminal::{ + Terminal, + ldisc::{ProcessMode, TtyConfig, TtyRead, TtyWrite}, + }, }; const PTY_BUF_SIZE: usize = 4096; diff --git a/api/src/terminal/job.rs b/kernel/src/pseudofs/dev/tty/terminal/job.rs similarity index 98% rename from api/src/terminal/job.rs rename to kernel/src/pseudofs/dev/tty/terminal/job.rs index b0757c63..0b3d6156 100644 --- a/api/src/terminal/job.rs +++ b/kernel/src/pseudofs/dev/tty/terminal/job.rs @@ -5,9 +5,10 @@ use axerrno::{AxResult, ax_bail}; use axpoll::{IoEvents, PollSet, Pollable}; use axtask::current; use kspin::SpinNoIrq; -use starry_core::task::AsThread; use starry_process::{ProcessGroup, Session}; +use crate::task::AsThread; + pub struct JobControl { foreground: SpinNoIrq>, session: SpinNoIrq>, diff --git a/api/src/terminal/ldisc.rs b/kernel/src/pseudofs/dev/tty/terminal/ldisc.rs similarity index 99% rename from api/src/terminal/ldisc.rs rename to kernel/src/pseudofs/dev/tty/terminal/ldisc.rs index 06cf6be5..a6af02f5 100644 --- a/api/src/terminal/ldisc.rs +++ b/kernel/src/pseudofs/dev/tty/terminal/ldisc.rs @@ -16,10 +16,10 @@ use ringbuf::{ CachingCons, CachingProd, traits::{Consumer, Observer, Producer, Split}, }; -use starry_core::task::send_signal_to_process_group; use starry_signal::SignalInfo; -use crate::terminal::{Terminal, termios::Termios2}; +use super::{Terminal, termios::Termios2}; +use crate::task::send_signal_to_process_group; const BUF_SIZE: usize = 80; diff --git a/api/src/terminal/mod.rs b/kernel/src/pseudofs/dev/tty/terminal/mod.rs similarity index 100% rename from api/src/terminal/mod.rs rename to kernel/src/pseudofs/dev/tty/terminal/mod.rs diff --git a/api/src/terminal/termios.rs b/kernel/src/pseudofs/dev/tty/terminal/termios.rs similarity index 99% rename from api/src/terminal/termios.rs rename to kernel/src/pseudofs/dev/tty/terminal/termios.rs index 94532eb1..9064fd6c 100644 --- a/api/src/terminal/termios.rs +++ b/kernel/src/pseudofs/dev/tty/terminal/termios.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use core::ops::{Deref, DerefMut}; use bytemuck::AnyBitPattern; diff --git a/core/src/vfs/dev.rs b/kernel/src/pseudofs/device.rs similarity index 100% rename from core/src/vfs/dev.rs rename to kernel/src/pseudofs/device.rs diff --git a/core/src/vfs/dir.rs b/kernel/src/pseudofs/dir.rs similarity index 100% rename from core/src/vfs/dir.rs rename to kernel/src/pseudofs/dir.rs diff --git a/core/src/vfs/file.rs b/kernel/src/pseudofs/file.rs similarity index 100% rename from core/src/vfs/file.rs rename to kernel/src/pseudofs/file.rs diff --git a/core/src/vfs/fs.rs b/kernel/src/pseudofs/fs.rs similarity index 100% rename from core/src/vfs/fs.rs rename to kernel/src/pseudofs/fs.rs diff --git a/api/src/vfs/mod.rs b/kernel/src/pseudofs/mod.rs similarity index 60% rename from api/src/vfs/mod.rs rename to kernel/src/pseudofs/mod.rs index 60ffd35a..40fcec4e 100644 --- a/api/src/vfs/mod.rs +++ b/kernel/src/pseudofs/mod.rs @@ -1,18 +1,51 @@ -//! Virtual filesystems +//! Basic virtual filesystem support pub mod dev; +mod device; +mod dir; +mod file; +mod fs; mod proc; mod tmp; +use alloc::sync::Arc; + use axerrno::LinuxResult; use axfs::{FS_CONTEXT, FsContext}; use axfs_ng_vfs::{ - Filesystem, NodePermission, + DirNodeOps, FileNodeOps, Filesystem, NodePermission, WeakDirEntry, path::{Path, PathBuf}, }; -pub use starry_core::vfs::{Device, DeviceOps, DirMapping, SimpleFs}; pub use tmp::MemoryFs; +pub use self::{device::*, dir::*, file::*, fs::*}; + +/// A callback that builds a `Arc` for a given +/// `WeakDirEntry`. +pub type DirMaker = Arc Arc + Send + Sync>; + +/// An enum containing either a directory ([`DirMaker`]) or a file (`Arc`). +#[derive(Clone)] +pub enum NodeOpsMux { + /// A directory node. + Dir(DirMaker), + /// A file node. + File(Arc), +} + +impl From for NodeOpsMux { + fn from(maker: DirMaker) -> Self { + Self::Dir(maker) + } +} + +impl From> for NodeOpsMux { + fn from(ops: Arc) -> Self { + Self::File(ops) + } +} + const DIR_PERMISSION: NodePermission = NodePermission::from_bits_truncate(0o755); fn mount_at(fs: &FsContext, path: &str, mount_fs: Filesystem) -> LinuxResult<()> { diff --git a/api/src/vfs/proc.rs b/kernel/src/pseudofs/proc.rs similarity index 96% rename from api/src/vfs/proc.rs rename to kernel/src/pseudofs/proc.rs index 8635d89e..0f988464 100644 --- a/api/src/vfs/proc.rs +++ b/kernel/src/pseudofs/proc.rs @@ -7,21 +7,25 @@ use alloc::{ vec, vec::Vec, }; -use core::{ffi::CStr, iter}; +use core::{ + ffi::CStr, + iter, + sync::atomic::{AtomicUsize, Ordering}, +}; use axfs_ng_vfs::{Filesystem, NodeType, VfsError, VfsResult}; use axtask::{AxTaskRef, WeakAxTaskRef, current}; use indoc::indoc; -use starry_core::{ - task::{AsThread, TaskStat, get_task, tasks}, - vfs::{ +use starry_process::Process; + +use crate::{ + file::FD_TABLE, + pseudofs::{ DirMaker, DirMapping, NodeOpsMux, RwFile, SimpleDir, SimpleDirOps, SimpleFile, SimpleFileOperation, SimpleFs, }, + task::{AsThread, TaskStat, get_task, tasks}, }; -use starry_process::Process; - -use crate::file::FD_TABLE; const DUMMY_MEMINFO: &str = indoc! {" MemTotal: 32536204 kB @@ -384,10 +388,20 @@ fn builder(fs: Arc) -> DirMaker { } }), ); - root.add( - "interrupts", - SimpleFile::new_regular(fs.clone(), || Ok(format!("0: {}", crate::time::irq_cnt()))), - ); + { + static IRQ_CNT: AtomicUsize = AtomicUsize::new(0); + + axtask::register_timer_callback(|_| { + IRQ_CNT.fetch_add(1, Ordering::Relaxed); + }); + + root.add( + "interrupts", + SimpleFile::new_regular(fs.clone(), || { + Ok(format!("0: {}", IRQ_CNT.load(Ordering::Relaxed))) + }), + ); + } root.add("sys", { let mut sys = DirMapping::new(); diff --git a/api/src/vfs/tmp.rs b/kernel/src/pseudofs/tmp.rs similarity index 99% rename from api/src/vfs/tmp.rs rename to kernel/src/pseudofs/tmp.rs index 09c454db..2a2798a3 100644 --- a/api/src/vfs/tmp.rs +++ b/kernel/src/pseudofs/tmp.rs @@ -10,7 +10,8 @@ use axpoll::{IoEvents, Pollable}; use axsync::Mutex; use hashbrown::HashMap; use slab::Slab; -use starry_core::vfs::dummy_stat_fs; + +use crate::pseudofs::dummy_stat_fs; #[derive(PartialEq, Eq, Hash, Clone)] struct FileName(String); diff --git a/api/src/syscall/fs/ctl.rs b/kernel/src/syscall/fs/ctl.rs similarity index 99% rename from api/src/syscall/fs/ctl.rs rename to kernel/src/syscall/fs/ctl.rs index ef8cd9cb..32179b92 100644 --- a/api/src/syscall/fs/ctl.rs +++ b/kernel/src/syscall/fs/ctl.rs @@ -14,12 +14,12 @@ use linux_raw_sys::{ general::*, ioctl::{FIONBIO, TIOCGWINSZ}, }; -use starry_core::task::AsThread; use starry_vm::{VmPtr, vm_write_slice}; use crate::{ file::{Directory, FileLike, get_file_like, resolve_at, with_fs}, mm::vm_load_string, + task::AsThread, time::TimeValueLike, }; diff --git a/api/src/syscall/fs/event.rs b/kernel/src/syscall/fs/event.rs similarity index 100% rename from api/src/syscall/fs/event.rs rename to kernel/src/syscall/fs/event.rs diff --git a/api/src/syscall/fs/fd_ops.rs b/kernel/src/syscall/fs/fd_ops.rs similarity index 99% rename from api/src/syscall/fs/fd_ops.rs rename to kernel/src/syscall/fs/fd_ops.rs index 825ee48b..44f0090d 100644 --- a/api/src/syscall/fs/fd_ops.rs +++ b/kernel/src/syscall/fs/fd_ops.rs @@ -11,7 +11,6 @@ use axfs_ng_vfs::{DirEntry, FileNode, Location, NodePermission, NodeType, Refere use axtask::current; use bitflags::bitflags; use linux_raw_sys::general::*; -use starry_core::{task::AsThread, vfs::Device}; use crate::{ file::{ @@ -20,7 +19,8 @@ use crate::{ }, mm::{UserPtr, vm_load_string}, syscall::sys::{sys_getegid, sys_geteuid}, - vfs::dev::tty, + task::AsThread, + pseudofs::{Device, dev::tty}, }; /// Convert open flags to [`OpenOptions`]. diff --git a/api/src/syscall/fs/io.rs b/kernel/src/syscall/fs/io.rs similarity index 99% rename from api/src/syscall/fs/io.rs rename to kernel/src/syscall/fs/io.rs index a3be9d4a..30b0ed14 100644 --- a/api/src/syscall/fs/io.rs +++ b/kernel/src/syscall/fs/io.rs @@ -15,8 +15,7 @@ use syscalls::Sysno; use crate::{ file::{File, FileLike, Pipe, get_file_like}, - io::{IoVec, IoVectorBuf}, - mm::{UserConstPtr, VmBytes, VmBytesMut}, + mm::{IoVec, IoVectorBuf, UserConstPtr, VmBytes, VmBytesMut}, }; struct DummyFd; diff --git a/api/src/syscall/fs/memfd.rs b/kernel/src/syscall/fs/memfd.rs similarity index 100% rename from api/src/syscall/fs/memfd.rs rename to kernel/src/syscall/fs/memfd.rs diff --git a/api/src/syscall/fs/mod.rs b/kernel/src/syscall/fs/mod.rs similarity index 100% rename from api/src/syscall/fs/mod.rs rename to kernel/src/syscall/fs/mod.rs diff --git a/api/src/syscall/fs/mount.rs b/kernel/src/syscall/fs/mount.rs similarity index 94% rename from api/src/syscall/fs/mount.rs rename to kernel/src/syscall/fs/mount.rs index 9efb5c31..057662b2 100644 --- a/api/src/syscall/fs/mount.rs +++ b/kernel/src/syscall/fs/mount.rs @@ -3,7 +3,7 @@ use core::ffi::{c_char, c_void}; use axerrno::{AxError, AxResult}; use axfs::FS_CONTEXT; -use crate::{mm::vm_load_string, vfs::MemoryFs}; +use crate::{mm::vm_load_string, pseudofs::MemoryFs}; pub fn sys_mount( source: *const c_char, diff --git a/api/src/syscall/fs/pidfd.rs b/kernel/src/syscall/fs/pidfd.rs similarity index 95% rename from api/src/syscall/fs/pidfd.rs rename to kernel/src/syscall/fs/pidfd.rs index 05804aa5..2d3d924f 100644 --- a/api/src/syscall/fs/pidfd.rs +++ b/kernel/src/syscall/fs/pidfd.rs @@ -1,10 +1,10 @@ use axerrno::{AxError, AxResult}; -use starry_core::task::{get_process_data, send_signal_to_process}; use starry_signal::SignalInfo; use crate::{ file::{FD_TABLE, FileLike, PidFd, add_file_like}, syscall::signal::make_queue_signal_info, + task::{get_process_data, send_signal_to_process}, }; pub fn sys_pidfd_open(pid: u32, flags: u32) -> AxResult { diff --git a/api/src/syscall/fs/pipe.rs b/kernel/src/syscall/fs/pipe.rs similarity index 100% rename from api/src/syscall/fs/pipe.rs rename to kernel/src/syscall/fs/pipe.rs diff --git a/api/src/syscall/fs/signalfd.rs b/kernel/src/syscall/fs/signalfd.rs similarity index 100% rename from api/src/syscall/fs/signalfd.rs rename to kernel/src/syscall/fs/signalfd.rs diff --git a/api/src/syscall/fs/stat.rs b/kernel/src/syscall/fs/stat.rs similarity index 100% rename from api/src/syscall/fs/stat.rs rename to kernel/src/syscall/fs/stat.rs diff --git a/api/src/syscall/io_mpx/epoll.rs b/kernel/src/syscall/io_mpx/epoll.rs similarity index 98% rename from api/src/syscall/io_mpx/epoll.rs rename to kernel/src/syscall/io_mpx/epoll.rs index 05b76286..5243f0ee 100644 --- a/api/src/syscall/io_mpx/epoll.rs +++ b/kernel/src/syscall/io_mpx/epoll.rs @@ -15,8 +15,8 @@ use crate::{ epoll::{Epoll, EpollEvent, EpollFlags}, }, mm::{UserConstPtr, UserPtr, nullable}, - signal::with_replacen_blocked, syscall::signal::check_sigset_size, + task::with_blocked_signals, time::TimeValueLike, }; @@ -93,7 +93,7 @@ fn do_epoll_wait( } let events = events.get_as_mut_slice(maxevents as usize)?; - with_replacen_blocked( + with_blocked_signals( nullable!(sigmask.get_as_ref())?.copied(), || match block_on(future::timeout( timeout, diff --git a/api/src/syscall/io_mpx/mod.rs b/kernel/src/syscall/io_mpx/mod.rs similarity index 100% rename from api/src/syscall/io_mpx/mod.rs rename to kernel/src/syscall/io_mpx/mod.rs diff --git a/api/src/syscall/io_mpx/poll.rs b/kernel/src/syscall/io_mpx/poll.rs similarity index 97% rename from api/src/syscall/io_mpx/poll.rs rename to kernel/src/syscall/io_mpx/poll.rs index 30fae238..58f0d7f3 100644 --- a/api/src/syscall/io_mpx/poll.rs +++ b/kernel/src/syscall/io_mpx/poll.rs @@ -11,8 +11,8 @@ use super::FdPollSet; use crate::{ file::get_file_like, mm::{UserConstPtr, UserPtr, nullable}, - signal::with_replacen_blocked, syscall::signal::check_sigset_size, + task::with_blocked_signals, time::TimeValueLike, }; @@ -52,7 +52,7 @@ fn do_poll( } let fds = FdPollSet(fds); - with_replacen_blocked(sigmask, || { + with_blocked_signals(sigmask, || { match block_on(future::timeout( timeout, poll_io(&fds, IoEvents::empty(), false, || { diff --git a/api/src/syscall/io_mpx/select.rs b/kernel/src/syscall/io_mpx/select.rs similarity index 98% rename from api/src/syscall/io_mpx/select.rs rename to kernel/src/syscall/io_mpx/select.rs index 3ff65f99..e05b592b 100644 --- a/api/src/syscall/io_mpx/select.rs +++ b/kernel/src/syscall/io_mpx/select.rs @@ -15,8 +15,8 @@ use super::FdPollSet; use crate::{ file::FD_TABLE, mm::{UserConstPtr, UserPtr, nullable}, - signal::with_replacen_blocked, syscall::signal::check_sigset_size, + task::with_blocked_signals, time::TimeValueLike, }; @@ -107,7 +107,7 @@ fn do_select( if let Some(exceptfds) = exceptfds.as_deref_mut() { unsafe { FD_ZERO(exceptfds) }; } - with_replacen_blocked(sigmask.copied(), || { + with_blocked_signals(sigmask.copied(), || { match block_on(future::timeout( timeout, poll_io(&fds, IoEvents::empty(), false, || { diff --git a/api/src/syscall/ipc/mod.rs b/kernel/src/syscall/ipc/mod.rs similarity index 59% rename from api/src/syscall/ipc/mod.rs rename to kernel/src/syscall/ipc/mod.rs index fe56b504..52a41039 100644 --- a/api/src/syscall/ipc/mod.rs +++ b/kernel/src/syscall/ipc/mod.rs @@ -1,6 +1,14 @@ use core::sync::atomic::{AtomicI32, Ordering}; -use starry_core::shm::IpcPerm; +mod msg; +mod shm; +use bytemuck::AnyBitPattern; +use linux_raw_sys::{ + ctypes::{c_long, c_ushort}, + general::*, +}; + +pub use self::{msg::*, shm::*}; static IPC_ID: AtomicI32 = AtomicI32::new(0); @@ -8,10 +16,6 @@ fn next_ipc_id() -> i32 { IPC_ID.fetch_add(1, Ordering::Relaxed) } -mod msg; -mod shm; -pub use self::{msg::*, shm::*}; - // IPC command constants const IPC_PRIVATE: i32 = 0; const IPC_CREAT: i32 = 0o1000; @@ -31,6 +35,32 @@ const GROUP_WRITE: u32 = 0o020; const OTHER_READ: u32 = 0o004; const OTHER_WRITE: u32 = 0o002; +/// Data structure used to pass permission information to IPC operations. +#[repr(C)] +#[derive(Clone, Copy, AnyBitPattern)] +pub struct IpcPerm { + /// Key supplied to msgget(2) + pub key: __kernel_key_t, + /// Effective UID of owner + pub uid: __kernel_uid_t, + /// Effective GID of owner + pub gid: __kernel_gid_t, + /// Effective UID of creator + pub cuid: __kernel_uid_t, + /// Effective GID of creator + pub cgid: __kernel_gid_t, + /// Permissions (least significant 9 bits define access permissions) + pub mode: __kernel_mode_t, + /// Sequence number + pub seq: c_ushort, + /// Padding + pub pad: c_ushort, + /// Unused field + pub unused0: c_long, + /// Unused field + pub unused1: c_long, +} + // add a helper function to check IPC permissions fn has_ipc_permission(perm: &IpcPerm, current_uid: u32, current_gid: u32, is_write: bool) -> bool { // root user has all permissions diff --git a/api/src/syscall/ipc/msg.rs b/kernel/src/syscall/ipc/msg.rs similarity index 99% rename from api/src/syscall/ipc/msg.rs rename to kernel/src/syscall/ipc/msg.rs index 367732fc..9aed4b6d 100644 --- a/api/src/syscall/ipc/msg.rs +++ b/kernel/src/syscall/ipc/msg.rs @@ -6,19 +6,22 @@ use axsync::Mutex; use axtask::current; use bytemuck::AnyBitPattern; use linux_raw_sys::general::*; -use starry_core::{shm::IpcPerm, task::AsThread}; use starry_process::Pid; use starry_vm::{VmMutPtr, VmPtr, vm_load, vm_write_slice}; use super::{ - IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_PRIVATE, IPC_RMID, IPC_SET, IPC_STAT, MSG_INFO, MSG_STAT, - has_ipc_permission, next_ipc_id, + IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_PRIVATE, IPC_RMID, IPC_SET, IPC_STAT, IpcPerm, MSG_INFO, + MSG_STAT, has_ipc_permission, next_ipc_id, +}; +use crate::{ + syscall::{sys_getgid, sys_getuid}, + task::AsThread, }; -use crate::syscall::{sys_getgid, sys_getuid}; /// Data structure describing a message queue. #[repr(C)] #[derive(Clone, Copy, AnyBitPattern)] +#[allow(non_camel_case_types)] pub struct msqid_ds { /// operation permission struct pub msg_perm: IpcPerm, @@ -718,7 +721,7 @@ pub fn sys_msgctl(msqid: i32, cmd: i32, buf: usize) -> AxResult { if cmd == MSG_INFO { let msg_manager = MSG_MANAGER.lock(); // Manually create IpcPerm - let msg_perm = starry_core::shm::IpcPerm { + let msg_perm = IpcPerm { key: 0, uid: current_uid, gid: current_gid, diff --git a/core/src/shm.rs b/kernel/src/syscall/ipc/shm.rs similarity index 59% rename from core/src/shm.rs rename to kernel/src/syscall/ipc/shm.rs index caae12ff..aba3f705 100644 --- a/core/src/shm.rs +++ b/kernel/src/syscall/ipc/shm.rs @@ -1,42 +1,34 @@ -//! Shared memory management. - use alloc::{collections::btree_map::BTreeMap, sync::Arc, vec::Vec}; use axerrno::{AxError, AxResult}; -use axhal::{paging::MappingFlags, time::monotonic_time_nanos}; -use axmm::backend::SharedPages; -use axsync::Mutex; -use bytemuck::AnyBitPattern; -use linux_raw_sys::{ - ctypes::{c_long, c_ushort}, - general::*, +use axhal::{ + paging::{MappingFlags, PageSize}, + time::monotonic_time_nanos, }; +use axmm::backend::{Backend, SharedPages}; +use axsync::Mutex; +use axtask::current; +use linux_raw_sys::{ctypes::c_ushort, general::*}; use memory_addr::{PAGE_SIZE_4K, VirtAddr, VirtAddrRange}; use starry_process::Pid; -/// Data structure used to pass permission information to IPC operations. -#[repr(C)] -#[derive(Clone, Copy, AnyBitPattern)] -pub struct IpcPerm { - /// Key supplied to msgget(2) - pub key: __kernel_key_t, - /// Effective UID of owner - pub uid: __kernel_uid_t, - /// Effective GID of owner - pub gid: __kernel_gid_t, - /// Effective UID of creator - pub cuid: __kernel_uid_t, - /// Effective GID of creator - pub cgid: __kernel_gid_t, - /// Permissions (least significant 9 bits define access permissions) - pub mode: __kernel_mode_t, - /// Sequence number - pub seq: c_ushort, - /// Padding - pub pad: c_ushort, - /// Unused field - pub unused0: c_long, - /// Unused field - pub unused1: c_long, + +use super::{IPC_PRIVATE, IPC_RMID, IPC_SET, IPC_STAT, IpcPerm, next_ipc_id}; +use crate::{ + mm::{UserPtr, nullable}, + task::AsThread, +}; + +bitflags::bitflags! { + /// flags for sys_shmat + #[derive(Debug)] + struct ShmAtFlags: u32 { + /* attach read-only else read-write */ + const SHM_RDONLY = 0o10000; + /* round attach address to SHMLBA */ + const SHM_RND = 0o20000; + /* take-over region on attach */ + const SHM_REMAP = 0o40000; + } } /// Data structure describing a shared memory segment. @@ -379,3 +371,199 @@ impl ShmManager { /// Global shared memory manager. pub static SHM_MANAGER: Mutex = Mutex::new(ShmManager::new()); + +pub fn sys_shmget(key: i32, size: usize, shmflg: usize) -> AxResult { + let page_num = memory_addr::align_up_4k(size) / PAGE_SIZE_4K; + if page_num == 0 { + return Err(AxError::InvalidInput); + } + + let mut mapping_flags = MappingFlags::from_name("USER").unwrap(); + if shmflg & 0o400 != 0 { + mapping_flags.insert(MappingFlags::READ); + } + if shmflg & 0o200 != 0 { + mapping_flags.insert(MappingFlags::WRITE); + } + if shmflg & 0o100 != 0 { + mapping_flags.insert(MappingFlags::EXECUTE); + } + + let cur_pid = current().as_thread().proc_data.proc.pid(); + let mut shm_manager = SHM_MANAGER.lock(); + + if key != IPC_PRIVATE { + // This process has already created a shared memory segment with the same key + if let Some(shmid) = shm_manager.get_shmid_by_key(key) { + let shm_inner = shm_manager + .get_inner_by_shmid(shmid) + .ok_or(AxError::InvalidInput)?; + let mut shm_inner = shm_inner.lock(); + return shm_inner.try_update(size, mapping_flags, cur_pid); + } + } + + // Create a new shm_inner + let shmid = next_ipc_id(); + let shm_inner = Arc::new(Mutex::new(ShmInner::new( + key, + shmid, + size, + mapping_flags, + cur_pid, + ))); + shm_manager.insert_key_shmid(key, shmid); + shm_manager.insert_shmid_inner(shmid, shm_inner); + + Ok(shmid as isize) +} + +pub fn sys_shmat(shmid: i32, addr: usize, shmflg: u32) -> AxResult { + let shm_inner = { + let shm_manager = SHM_MANAGER.lock(); + shm_manager.get_inner_by_shmid(shmid).unwrap() + }; + let mut shm_inner = shm_inner.lock(); + let mut mapping_flags = shm_inner.mapping_flags; + let shm_flg = ShmAtFlags::from_bits_truncate(shmflg); + + if shm_flg.contains(ShmAtFlags::SHM_RDONLY) { + mapping_flags.remove(MappingFlags::WRITE); + } + + // TODO: solve shmflg: SHM_RND and SHM_REMAP + + let curr = current(); + let proc_data = &curr.as_thread().proc_data; + let pid = proc_data.proc.pid(); + let mut aspace = proc_data.aspace.lock(); + + let start_aligned = memory_addr::align_down_4k(addr); + let length = shm_inner.page_num * PAGE_SIZE_4K; + + // alloc the virtual address range + assert!(shm_inner.get_addr_range(pid).is_none()); + let start_addr = aspace + .find_free_area( + VirtAddr::from(start_aligned), + length, + VirtAddrRange::new(aspace.base(), aspace.end()), + PAGE_SIZE_4K, + ) + .or_else(|| { + aspace.find_free_area( + aspace.base(), + length, + VirtAddrRange::new(aspace.base(), aspace.end()), + PAGE_SIZE_4K, + ) + }) + .ok_or(AxError::NoMemory)?; + let end_addr = VirtAddr::from(start_addr.as_usize() + length); + let va_range = VirtAddrRange::new(start_addr, end_addr); + + let mut shm_manager = SHM_MANAGER.lock(); + shm_manager.insert_shmid_vaddr(pid, shm_inner.shmid, start_addr); + info!( + "Process {} alloc shm virt addr start: {:#x}, size: {}, mapping_flags: {:#x?}", + pid, + start_addr.as_usize(), + length, + mapping_flags + ); + + // map the virtual address range to the physical address + if let Some(phys_pages) = shm_inner.phys_pages.clone() { + // Another proccess has attached the shared memory + // TODO(mivik): shm page size + let backend = Backend::new_shared(start_addr, phys_pages); + aspace.map(start_addr, length, mapping_flags, false, backend)?; + } else { + // This is the first process to attach the shared memory + let pages = Arc::new(SharedPages::new(length, PageSize::Size4K)?); + let backend = Backend::new_shared(start_addr, pages.clone()); + aspace.map(start_addr, length, mapping_flags, false, backend)?; + + shm_inner.map_to_phys(pages); + } + + shm_inner.attach_process(pid, va_range); + Ok(start_addr.as_usize() as isize) +} + +pub fn sys_shmctl(shmid: i32, cmd: u32, buf: UserPtr) -> AxResult { + let shm_inner = { + let shm_manager = SHM_MANAGER.lock(); + shm_manager + .get_inner_by_shmid(shmid) + .ok_or(AxError::InvalidInput)? + }; + let mut shm_inner = shm_inner.lock(); + + let cmd = cmd as i32; + if cmd == IPC_SET { + shm_inner.shmid_ds = *buf.get_as_mut()?; + } else if cmd == IPC_STAT { + if let Some(shmid_ds) = nullable!(buf.get_as_mut())? { + *shmid_ds = shm_inner.shmid_ds; + } + } else if cmd == IPC_RMID { + shm_inner.rmid = true; + } else { + return Err(AxError::InvalidInput); + } + + shm_inner.shmid_ds.shm_ctime = monotonic_time_nanos() as __kernel_time_t; + Ok(0) +} + +// Garbage collection for shared memory: +// 1. when the process call sys_shmdt, delete everything related to shmaddr, +// including map 'shmid_vaddr'; +// 2. when the last process detach the shared memory and this shared memory was +// specified with IPC_RMID, delete everything related to this shared memory, +// including all the 3 maps; +// 3. when a process exit, delete everything related to this process, including +// 2 maps: 'shmid_vaddr' and 'shmid_inner'; +// +// The attach between the process and the shared memory occurs in sys_shmat, +// and the detach occurs in sys_shmdt, or when the process exits. + +// Note: all the below delete functions only delete the mapping between the +// shm_id and the shm_inner, but the shm_inner is not deleted or modifyed! +pub fn sys_shmdt(shmaddr: usize) -> AxResult { + let shmaddr = VirtAddr::from(shmaddr); + + let curr = current(); + let proc_data = &curr.as_thread().proc_data; + + let pid = proc_data.proc.pid(); + let shmid = { + let shm_manager = SHM_MANAGER.lock(); + shm_manager + .get_shmid_by_vaddr(pid, shmaddr) + .ok_or(AxError::InvalidInput)? + }; + + let shm_inner = { + let shm_manager = SHM_MANAGER.lock(); + shm_manager + .get_inner_by_shmid(shmid) + .ok_or(AxError::InvalidInput)? + }; + let mut shm_inner = shm_inner.lock(); + let va_range = shm_inner.get_addr_range(pid).ok_or(AxError::InvalidInput)?; + + let mut aspace = proc_data.aspace.lock(); + aspace.unmap(va_range.start, va_range.size())?; + + let mut shm_manager = SHM_MANAGER.lock(); + shm_manager.remove_shmaddr(pid, shmaddr); + shm_inner.detach_process(pid); + + if shm_inner.rmid && shm_inner.attach_count() == 0 { + shm_manager.remove_shmid(shmid); + } + + Ok(0) +} diff --git a/api/src/syscall/mm/brk.rs b/kernel/src/syscall/mm/brk.rs similarity index 99% rename from api/src/syscall/mm/brk.rs rename to kernel/src/syscall/mm/brk.rs index 178d57d7..55720ede 100644 --- a/api/src/syscall/mm/brk.rs +++ b/kernel/src/syscall/mm/brk.rs @@ -3,7 +3,8 @@ use axhal::paging::{MappingFlags, PageSize}; use axmm::backend::Backend; use axtask::current; use memory_addr::{VirtAddr, align_up_4k}; -use starry_core::{ + +use crate::{ config::{USER_HEAP_BASE, USER_HEAP_SIZE, USER_HEAP_SIZE_MAX}, task::AsThread, }; diff --git a/api/src/syscall/mm/mincore.rs b/kernel/src/syscall/mm/mincore.rs similarity index 99% rename from api/src/syscall/mm/mincore.rs rename to kernel/src/syscall/mm/mincore.rs index 6a6c112e..eea343d4 100644 --- a/api/src/syscall/mm/mincore.rs +++ b/kernel/src/syscall/mm/mincore.rs @@ -12,9 +12,10 @@ use axerrno::{AxError, AxResult}; use axhal::paging::MappingFlags; use axtask::current; use memory_addr::{MemoryAddr, PAGE_SIZE_4K, VirtAddr}; -use starry_core::task::AsThread; use starry_vm::vm_write_slice; +use crate::task::AsThread; + /// Check whether pages are resident in memory. /// /// The mincore() system call determines whether pages of the calling process's diff --git a/api/src/syscall/mm/mmap.rs b/kernel/src/syscall/mm/mmap.rs similarity index 99% rename from api/src/syscall/mm/mmap.rs rename to kernel/src/syscall/mm/mmap.rs index 94793882..dbb56ec6 100644 --- a/api/src/syscall/mm/mmap.rs +++ b/kernel/src/syscall/mm/mmap.rs @@ -7,13 +7,13 @@ use axmm::backend::{Backend, SharedPages}; use axtask::current; use linux_raw_sys::general::*; use memory_addr::{MemoryAddr, VirtAddr, VirtAddrRange, align_up_4k}; -use starry_core::{ - task::AsThread, - vfs::{Device, DeviceMmap}, -}; use starry_vm::{vm_load, vm_write_slice}; -use crate::file::{File, FileLike}; +use crate::{ + file::{File, FileLike}, + task::AsThread, + pseudofs::{Device, DeviceMmap}, +}; bitflags::bitflags! { /// `PROT_*` flags for use with [`sys_mmap`]. diff --git a/api/src/syscall/mm/mod.rs b/kernel/src/syscall/mm/mod.rs similarity index 100% rename from api/src/syscall/mm/mod.rs rename to kernel/src/syscall/mm/mod.rs diff --git a/api/src/syscall/mod.rs b/kernel/src/syscall/mod.rs similarity index 99% rename from api/src/syscall/mod.rs rename to kernel/src/syscall/mod.rs index 29c13b51..08cfde2c 100644 --- a/api/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -14,7 +14,7 @@ use axerrno::{AxError, LinuxError}; use axhal::uspace::UserContext; use syscalls::Sysno; -use self::{ +pub use self::{ fs::*, io_mpx::*, ipc::*, mm::*, net::*, resources::*, signal::*, sync::*, sys::*, task::*, time::*, }; diff --git a/api/src/socket.rs b/kernel/src/syscall/net/addr.rs similarity index 99% rename from api/src/socket.rs rename to kernel/src/syscall/net/addr.rs index 6c502fa7..4a3a5e0a 100644 --- a/api/src/socket.rs +++ b/kernel/src/syscall/net/addr.rs @@ -27,6 +27,7 @@ pub trait SocketAddrExt: Sized { fn write_to_user(&self, addr: UserPtr, addrlen: &mut socklen_t) -> AxResult<()>; /// Gets the address family of the socket address. + #[allow(dead_code)] fn family(&self) -> u16; } diff --git a/api/src/syscall/net/cmsg.rs b/kernel/src/syscall/net/cmsg.rs similarity index 100% rename from api/src/syscall/net/cmsg.rs rename to kernel/src/syscall/net/cmsg.rs diff --git a/api/src/syscall/net/io.rs b/kernel/src/syscall/net/io.rs similarity index 97% rename from api/src/syscall/net/io.rs rename to kernel/src/syscall/net/io.rs index 8ab55e45..b8949da9 100644 --- a/api/src/syscall/net/io.rs +++ b/kernel/src/syscall/net/io.rs @@ -8,11 +8,10 @@ use linux_raw_sys::net::{ MSG_PEEK, MSG_TRUNC, SCM_RIGHTS, SOL_SOCKET, cmsghdr, msghdr, sockaddr, socklen_t, }; +use super::addr::SocketAddrExt; use crate::{ file::{FileLike, Socket, add_file_like}, - io::{IoVec, IoVectorBuf}, - mm::{UserConstPtr, UserPtr, VmBytes, VmBytesMut}, - socket::SocketAddrExt, + mm::{IoVec, IoVectorBuf, UserConstPtr, UserPtr, VmBytes, VmBytesMut}, syscall::net::{CMsg, CMsgBuilder}, }; diff --git a/api/src/syscall/net/mod.rs b/kernel/src/syscall/net/mod.rs similarity index 91% rename from api/src/syscall/net/mod.rs rename to kernel/src/syscall/net/mod.rs index eaa3ae59..1e2c43ce 100644 --- a/api/src/syscall/net/mod.rs +++ b/kernel/src/syscall/net/mod.rs @@ -1,3 +1,4 @@ +mod addr; mod cmsg; mod io; mod name; diff --git a/api/src/syscall/net/name.rs b/kernel/src/syscall/net/name.rs similarity index 96% rename from api/src/syscall/net/name.rs rename to kernel/src/syscall/net/name.rs index 411b14cd..71bc7d1a 100644 --- a/api/src/syscall/net/name.rs +++ b/kernel/src/syscall/net/name.rs @@ -2,10 +2,10 @@ use axerrno::AxResult; use axnet::SocketOps; use linux_raw_sys::net::{sockaddr, socklen_t}; +use super::addr::SocketAddrExt; use crate::{ file::{FileLike, Socket}, mm::UserPtr, - socket::SocketAddrExt, }; pub fn sys_getsockname( diff --git a/api/src/syscall/net/opt.rs b/kernel/src/syscall/net/opt.rs similarity index 100% rename from api/src/syscall/net/opt.rs rename to kernel/src/syscall/net/opt.rs diff --git a/api/src/syscall/net/socket.rs b/kernel/src/syscall/net/socket.rs similarity index 98% rename from api/src/syscall/net/socket.rs rename to kernel/src/syscall/net/socket.rs index b8ebc904..26ba477f 100644 --- a/api/src/syscall/net/socket.rs +++ b/kernel/src/syscall/net/socket.rs @@ -15,12 +15,12 @@ use linux_raw_sys::{ SOCK_DGRAM, SOCK_SEQPACKET, SOCK_STREAM, sockaddr, socklen_t, }, }; -use starry_core::task::AsThread; +use super::addr::SocketAddrExt; use crate::{ file::{FileLike, Socket}, mm::{UserConstPtr, UserPtr}, - socket::SocketAddrExt, + task::AsThread, }; pub fn sys_socket(domain: u32, raw_ty: u32, proto: u32) -> AxResult { diff --git a/api/src/syscall/resources.rs b/kernel/src/syscall/resources.rs similarity index 97% rename from api/src/syscall/resources.rs rename to kernel/src/syscall/resources.rs index 8bf4ce35..3c9f4fed 100644 --- a/api/src/syscall/resources.rs +++ b/kernel/src/syscall/resources.rs @@ -2,11 +2,13 @@ use axerrno::{AxError, AxResult}; use axhal::time::TimeValue; use axtask::current; use linux_raw_sys::general::{__kernel_old_timeval, RLIM_NLIMITS, rlimit64, rusage}; -use starry_core::task::{AsThread, Thread, get_process_data, get_task}; use starry_process::Pid; use starry_vm::{VmMutPtr, VmPtr}; -use crate::time::TimeValueLike; +use crate::{ + task::{AsThread, Thread, get_process_data, get_task}, + time::TimeValueLike, +}; pub fn sys_prlimit64( pid: Pid, diff --git a/api/src/syscall/signal.rs b/kernel/src/syscall/signal.rs similarity index 97% rename from api/src/syscall/signal.rs rename to kernel/src/syscall/signal.rs index 3914be97..bccdbb70 100644 --- a/api/src/syscall/signal.rs +++ b/kernel/src/syscall/signal.rs @@ -10,16 +10,15 @@ use linux_raw_sys::general::{ MINSIGSTKSZ, SI_TKILL, SI_USER, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK, kernel_sigaction, siginfo, timespec, }; -use starry_core::task::{ - AsThread, processes, send_signal_to_process, send_signal_to_process_group, - send_signal_to_thread, -}; use starry_process::Pid; use starry_signal::{SignalInfo, SignalSet, SignalStack, Signo}; use starry_vm::{VmMutPtr, VmPtr}; use crate::{ - signal::{block_next_signal, check_signals}, + task::{ + AsThread, block_next_signal, check_signals, processes, send_signal_to_process, + send_signal_to_process_group, send_signal_to_thread, + }, time::TimeValueLike, }; diff --git a/api/src/syscall/sync/futex.rs b/kernel/src/syscall/sync/futex.rs similarity index 92% rename from api/src/syscall/sync/futex.rs rename to kernel/src/syscall/sync/futex.rs index 30ec6107..129abbcc 100644 --- a/api/src/syscall/sync/futex.rs +++ b/kernel/src/syscall/sync/futex.rs @@ -6,13 +6,12 @@ use linux_raw_sys::general::{ FUTEX_CMD_MASK, FUTEX_CMP_REQUEUE, FUTEX_REQUEUE, FUTEX_WAIT, FUTEX_WAIT_BITSET, FUTEX_WAKE, FUTEX_WAKE_BITSET, robust_list_head, timespec, }; -use starry_core::{ - futex::FutexKey, - task::{AsThread, get_task}, -}; use starry_vm::{VmMutPtr, VmPtr}; -use crate::time::TimeValueLike; +use crate::{ + task::{AsThread, FutexKey, futex_table_for, get_task}, + time::TimeValueLike, +}; fn assert_unsigned(value: u32) -> AxResult { if (value as i32) < 0 { @@ -37,10 +36,7 @@ pub fn sys_futex( let key = FutexKey::new_current(uaddr.addr()); - let curr = current(); - let thr = curr.as_thread(); - let proc_data = &thr.proc_data; - let futex_table = proc_data.futex_table_for(&key); + let futex_table = futex_table_for(&key); let command = futex_op & (FUTEX_CMD_MASK as u32); match command { @@ -102,7 +98,7 @@ pub fn sys_futex( let futex = futex_table.get(&key); let key2 = FutexKey::new_current(uaddr2.addr()); - let table2 = proc_data.futex_table_for(&key2); + let table2 = futex_table_for(&key2); let futex2 = table2.get_or_insert(&key2); let mut count = 0; diff --git a/api/src/syscall/sync/membarrier.rs b/kernel/src/syscall/sync/membarrier.rs similarity index 100% rename from api/src/syscall/sync/membarrier.rs rename to kernel/src/syscall/sync/membarrier.rs diff --git a/api/src/syscall/sync/mod.rs b/kernel/src/syscall/sync/mod.rs similarity index 100% rename from api/src/syscall/sync/mod.rs rename to kernel/src/syscall/sync/mod.rs diff --git a/api/src/syscall/sys.rs b/kernel/src/syscall/sys.rs similarity index 98% rename from api/src/syscall/sys.rs rename to kernel/src/syscall/sys.rs index 12e3cbba..572054b1 100644 --- a/api/src/syscall/sys.rs +++ b/kernel/src/syscall/sys.rs @@ -8,9 +8,10 @@ use linux_raw_sys::{ general::{GRND_INSECURE, GRND_NONBLOCK, GRND_RANDOM}, system::{new_utsname, sysinfo}, }; -use starry_core::task::processes; use starry_vm::{VmMutPtr, vm_write_slice}; +use crate::task::processes; + pub fn sys_getuid() -> AxResult { Ok(0) } diff --git a/api/src/syscall/task/clone.rs b/kernel/src/syscall/task/clone.rs similarity index 98% rename from api/src/syscall/task/clone.rs rename to kernel/src/syscall/task/clone.rs index af91a761..250aa195 100644 --- a/api/src/syscall/task/clone.rs +++ b/kernel/src/syscall/task/clone.rs @@ -7,17 +7,14 @@ use axtask::{AxTaskExt, current, spawn_task}; use bitflags::bitflags; use kspin::SpinNoIrq; use linux_raw_sys::general::*; -use starry_core::{ - mm::copy_from_kernel, - task::{AsThread, ProcessData, Thread, add_task_to_table}, -}; use starry_process::Pid; use starry_signal::Signo; use starry_vm::VmMutPtr; use crate::{ file::{FD_TABLE, FileLike, PidFd}, - task::new_user_task, + mm::copy_from_kernel, + task::{AsThread, ProcessData, Thread, add_task_to_table, new_user_task}, }; bitflags! { diff --git a/api/src/syscall/task/ctl.rs b/kernel/src/syscall/task/ctl.rs similarity index 97% rename from api/src/syscall/task/ctl.rs rename to kernel/src/syscall/task/ctl.rs index 5142097c..25d08872 100644 --- a/api/src/syscall/task/ctl.rs +++ b/kernel/src/syscall/task/ctl.rs @@ -3,10 +3,12 @@ use core::ffi::c_char; use axerrno::{AxError, AxResult}; use axtask::current; use linux_raw_sys::general::{__user_cap_data_struct, __user_cap_header_struct}; -use starry_core::task::{AsThread, get_process_data}; use starry_vm::{VmMutPtr, VmPtr, vm_write_slice}; -use crate::mm::vm_load_string; +use crate::{ + mm::vm_load_string, + task::{AsThread, get_process_data}, +}; const CAPABILITY_VERSION_3: u32 = 0x20080522; diff --git a/api/src/syscall/task/execve.rs b/kernel/src/syscall/task/execve.rs similarity index 94% rename from api/src/syscall/task/execve.rs rename to kernel/src/syscall/task/execve.rs index ba81dac1..bda86ab2 100644 --- a/api/src/syscall/task/execve.rs +++ b/kernel/src/syscall/task/execve.rs @@ -5,10 +5,14 @@ use axerrno::{AxError, AxResult}; use axfs::FS_CONTEXT; use axhal::uspace::UserContext; use axtask::current; -use starry_core::{config::USER_HEAP_BASE, mm::load_user_app, task::AsThread}; use starry_vm::vm_load_until_nul; -use crate::{file::FD_TABLE, mm::vm_load_string}; +use crate::{ + config::USER_HEAP_BASE, + file::FD_TABLE, + mm::{load_user_app, vm_load_string}, + task::AsThread, +}; pub fn sys_execve( uctx: &mut UserContext, diff --git a/api/src/syscall/task/exit.rs b/kernel/src/syscall/task/exit.rs similarity index 100% rename from api/src/syscall/task/exit.rs rename to kernel/src/syscall/task/exit.rs diff --git a/api/src/syscall/task/job.rs b/kernel/src/syscall/task/job.rs similarity index 93% rename from api/src/syscall/task/job.rs rename to kernel/src/syscall/task/job.rs index bf267a85..db71aaf6 100644 --- a/api/src/syscall/task/job.rs +++ b/kernel/src/syscall/task/job.rs @@ -1,8 +1,9 @@ use axerrno::{AxError, AxResult}; use axtask::current; -use starry_core::task::{AsThread, get_process_data, get_process_group}; use starry_process::Pid; +use crate::task::{AsThread, get_process_data, get_process_group}; + pub fn sys_getsid(pid: Pid) -> AxResult { Ok(get_process_data(pid)?.proc.group().session().sid() as _) } diff --git a/api/src/syscall/task/mod.rs b/kernel/src/syscall/task/mod.rs similarity index 100% rename from api/src/syscall/task/mod.rs rename to kernel/src/syscall/task/mod.rs diff --git a/api/src/syscall/task/schedule.rs b/kernel/src/syscall/task/schedule.rs similarity index 97% rename from api/src/syscall/task/schedule.rs rename to kernel/src/syscall/task/schedule.rs index a7643585..6ccf647d 100644 --- a/api/src/syscall/task/schedule.rs +++ b/kernel/src/syscall/task/schedule.rs @@ -8,10 +8,12 @@ use linux_raw_sys::general::{ __kernel_clockid_t, CLOCK_MONOTONIC, CLOCK_REALTIME, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, SCHED_RR, TIMER_ABSTIME, timespec, }; -use starry_core::task::{get_process_data, get_process_group}; use starry_vm::{VmMutPtr, VmPtr, vm_load, vm_write_slice}; -use crate::time::TimeValueLike; +use crate::{ + task::{get_process_data, get_process_group}, + time::TimeValueLike, +}; pub fn sys_sched_yield() -> AxResult { axtask::yield_now(); diff --git a/api/src/syscall/task/thread.rs b/kernel/src/syscall/task/thread.rs similarity index 98% rename from api/src/syscall/task/thread.rs rename to kernel/src/syscall/task/thread.rs index 7d360fc2..fdfec9dc 100644 --- a/api/src/syscall/task/thread.rs +++ b/kernel/src/syscall/task/thread.rs @@ -1,6 +1,7 @@ use axerrno::{AxError, AxResult}; use axtask::current; -use starry_core::task::AsThread; + +use crate::task::AsThread; pub fn sys_getpid() -> AxResult { Ok(current().as_thread().proc_data.proc.pid() as _) diff --git a/api/src/syscall/task/wait.rs b/kernel/src/syscall/task/wait.rs similarity index 99% rename from api/src/syscall/task/wait.rs rename to kernel/src/syscall/task/wait.rs index 589c17bf..bf7fa8d1 100644 --- a/api/src/syscall/task/wait.rs +++ b/kernel/src/syscall/task/wait.rs @@ -10,10 +10,11 @@ use bitflags::bitflags; use linux_raw_sys::general::{ __WALL, __WCLONE, __WNOTHREAD, WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WUNTRACED, }; -use starry_core::task::AsThread; use starry_process::{Pid, Process}; use starry_vm::{VmMutPtr, VmPtr}; +use crate::task::AsThread; + bitflags! { #[derive(Debug)] struct WaitOptions: u32 { diff --git a/api/src/syscall/time.rs b/kernel/src/syscall/time.rs similarity index 97% rename from api/src/syscall/time.rs rename to kernel/src/syscall/time.rs index 8ddf9a4d..289ab815 100644 --- a/api/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -6,10 +6,12 @@ use linux_raw_sys::general::{ CLOCK_MONOTONIC_RAW, CLOCK_PROCESS_CPUTIME_ID, CLOCK_REALTIME, CLOCK_REALTIME_COARSE, CLOCK_THREAD_CPUTIME_ID, itimerval, timespec, timeval, }; -use starry_core::{task::AsThread, time::ITimerType}; use starry_vm::{VmMutPtr, VmPtr}; -use crate::time::TimeValueLike; +use crate::{ + task::{AsThread, ITimerType}, + time::TimeValueLike, +}; pub fn sys_clock_gettime(clock_id: __kernel_clockid_t, ts: *mut timespec) -> AxResult { let now = match clock_id as u32 { diff --git a/core/src/futex.rs b/kernel/src/task/futex.rs similarity index 83% rename from core/src/futex.rs rename to kernel/src/task/futex.rs index 7fed925b..f43647df 100644 --- a/core/src/futex.rs +++ b/kernel/src/task/futex.rs @@ -1,7 +1,7 @@ //! Futex implementation. use alloc::{ - collections::vec_deque::VecDeque, + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, sync::{Arc, Weak}, vec::Vec, }; @@ -240,3 +240,45 @@ impl Drop for FutexGuard<'_> { } } } + +struct FutexTables { + map: BTreeMap>, + operations: usize, +} +impl FutexTables { + const fn new() -> Self { + Self { + map: BTreeMap::new(), + operations: 0, + } + } + + fn get_or_insert(&mut self, key: usize) -> Arc { + self.operations += 1; + if self.operations == 100 { + self.operations = 0; + self.map + .retain(|_, table| Arc::strong_count(table) > 1 || !table.is_empty()); + } + self.map + .entry(key) + .or_insert_with(|| Arc::new(FutexTable::new())) + .clone() + } +} + +static SHARED_FUTEX_TABLES: Mutex = Mutex::new(FutexTables::new()); + +/// Returns the futex table for the given key. +pub fn futex_table_for(key: &FutexKey) -> Arc { + match key { + FutexKey::Private { .. } => current().as_thread().proc_data.futex_table.clone(), + FutexKey::Shared { region, .. } => { + let ptr = match region { + Ok(pages) => Weak::as_ptr(pages) as usize, + Err(key) => Weak::as_ptr(key) as usize, + }; + SHARED_FUTEX_TABLES.lock().get_or_insert(ptr) + } + } +} diff --git a/core/src/task.rs b/kernel/src/task/mod.rs similarity index 52% rename from core/src/task.rs rename to kernel/src/task/mod.rs index 9b36b781..800cc1c7 100644 --- a/core/src/task.rs +++ b/kernel/src/task/mod.rs @@ -1,42 +1,34 @@ //! User task management. +mod futex; +mod ops; +mod resources; +mod signal; mod stat; +mod timer; +mod user; -use alloc::{ - boxed::Box, - string::String, - sync::{Arc, Weak}, - vec::Vec, -}; +use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec}; use core::{ cell::RefCell, ops::Deref, sync::atomic::{AtomicBool, AtomicI32, AtomicU32, AtomicUsize, Ordering}, }; -use axerrno::{AxError, AxResult}; use axmm::AddrSpace; use axpoll::PollSet; use axsync::{Mutex, spin::SpinNoIrq}; -use axtask::{AxTaskRef, TaskExt, TaskInner, WeakAxTaskRef, current}; +use axtask::{TaskExt, TaskInner}; use extern_trait::extern_trait; -use hashbrown::HashMap; -use lazy_static::lazy_static; use scope_local::{ActiveScope, Scope}; use spin::RwLock; -use starry_process::{Pid, Process, ProcessGroup, Session}; +use starry_process::Process; use starry_signal::{ - SignalInfo, Signo, + Signo, api::{ProcessSignalManager, SignalActions, ThreadSignalManager}, }; -use weak_map::WeakMap; -pub use self::stat::TaskStat; -use crate::{ - futex::{FutexKey, FutexTable}, - resources::Rlimits, - time::{TimeManager, TimerState}, -}; +pub use self::{futex::*, ops::*, resources::*, signal::*, stat::*, timer::*, user::*}; /// A wrapper type that assumes the inner type is `Sync`. #[repr(transparent)] @@ -275,20 +267,6 @@ impl ProcessData { self.exit_signal != Some(Signo::SIGCHLD) } - /// Returns the futex table for the given key. - pub fn futex_table_for(&self, key: &FutexKey) -> Arc { - match key { - FutexKey::Private { .. } => self.futex_table.clone(), - FutexKey::Shared { region, .. } => { - let ptr = match region { - Ok(pages) => Weak::as_ptr(pages) as usize, - Err(key) => Weak::as_ptr(key) as usize, - }; - SHARED_FUTEX_TABLES.lock().get_or_insert(ptr) - } - } - } - /// Get the umask. pub fn umask(&self) -> u32 { self.umask.load(Ordering::SeqCst) @@ -304,205 +282,3 @@ impl ProcessData { self.umask.swap(umask, Ordering::SeqCst) } } - -struct FutexTables { - map: HashMap>, - operations: usize, -} -impl FutexTables { - fn new() -> Self { - Self { - map: HashMap::new(), - operations: 0, - } - } - - fn get_or_insert(&mut self, key: usize) -> Arc { - self.operations += 1; - if self.operations == 100 { - self.operations = 0; - self.map - .retain(|_, table| Arc::strong_count(table) > 1 || !table.is_empty()); - } - self.map - .entry(key) - .or_insert_with(|| Arc::new(FutexTable::new())) - .clone() - } -} - -lazy_static! { - static ref SHARED_FUTEX_TABLES: Mutex = Mutex::new(FutexTables::new()); -} - -static TASK_TABLE: RwLock> = RwLock::new(WeakMap::new()); - -static PROCESS_TABLE: RwLock>> = RwLock::new(WeakMap::new()); - -static PROCESS_GROUP_TABLE: RwLock>> = RwLock::new(WeakMap::new()); - -static SESSION_TABLE: RwLock>> = RwLock::new(WeakMap::new()); - -/// Cleanup expired entries in the task tables. -/// -/// This function is intended to be used during memory leak analysis to remove -/// possible noise caused by expired entries in the [`WeakMap`]. -pub fn cleanup_task_tables() { - TASK_TABLE.write().cleanup(); - PROCESS_TABLE.write().cleanup(); - PROCESS_GROUP_TABLE.write().cleanup(); - SESSION_TABLE.write().cleanup(); -} - -/// Add the task, the thread and possibly its process, process group and session -/// to the corresponding tables. -pub fn add_task_to_table(task: &AxTaskRef) { - let tid = task.id().as_u64() as Pid; - - let mut task_table = TASK_TABLE.write(); - task_table.insert(tid, task); - - let proc_data = &task.as_thread().proc_data; - let proc = &proc_data.proc; - let pid = proc.pid(); - let mut proc_table = PROCESS_TABLE.write(); - if proc_table.contains_key(&pid) { - return; - } - proc_table.insert(pid, proc_data); - - let pg = proc.group(); - let mut pg_table = PROCESS_GROUP_TABLE.write(); - if pg_table.contains_key(&pg.pgid()) { - return; - } - pg_table.insert(pg.pgid(), &pg); - - let session = pg.session(); - let mut session_table = SESSION_TABLE.write(); - if session_table.contains_key(&session.sid()) { - return; - } - session_table.insert(session.sid(), &session); -} - -/// Lists all tasks. -pub fn tasks() -> Vec { - TASK_TABLE.read().values().collect() -} - -/// Finds the task with the given TID. -pub fn get_task(tid: Pid) -> AxResult { - if tid == 0 { - return Ok(current().clone()); - } - TASK_TABLE.read().get(&tid).ok_or(AxError::NoSuchProcess) -} - -/// Lists all processes. -pub fn processes() -> Vec> { - PROCESS_TABLE.read().values().collect() -} - -/// Finds the process with the given PID. -pub fn get_process_data(pid: Pid) -> AxResult> { - if pid == 0 { - return Ok(current().as_thread().proc_data.clone()); - } - PROCESS_TABLE.read().get(&pid).ok_or(AxError::NoSuchProcess) -} - -/// Finds the process group with the given PGID. -pub fn get_process_group(pgid: Pid) -> AxResult> { - PROCESS_GROUP_TABLE - .read() - .get(&pgid) - .ok_or(AxError::NoSuchProcess) -} - -/// Finds the session with the given SID. -pub fn get_session(sid: Pid) -> AxResult> { - SESSION_TABLE.read().get(&sid).ok_or(AxError::NoSuchProcess) -} - -/// Poll the timer -pub fn poll_timer(task: &TaskInner) { - let Some(thr) = task.try_as_thread() else { - return; - }; - let Ok(mut time) = thr.time.try_borrow_mut() else { - // reentrant borrow, likely IRQ - return; - }; - time.poll(|signo| { - send_signal_thread_inner(task, thr, SignalInfo::new_kernel(signo)); - }); -} - -/// Sets the timer state. -pub fn set_timer_state(task: &TaskInner, state: TimerState) { - let Some(thr) = task.try_as_thread() else { - return; - }; - let Ok(mut time) = thr.time.try_borrow_mut() else { - // reentrant borrow, likely IRQ - return; - }; - time.poll(|signo| { - send_signal_thread_inner(task, thr, SignalInfo::new_kernel(signo)); - }); - time.set_state(state); -} - -fn send_signal_thread_inner(task: &TaskInner, thr: &Thread, sig: SignalInfo) { - if thr.signal.send_signal(sig) { - task.interrupt(); - } -} - -/// Sends a signal to a thread. -pub fn send_signal_to_thread(tgid: Option, tid: Pid, sig: Option) -> AxResult<()> { - let task = get_task(tid)?; - let thread = task.try_as_thread().ok_or(AxError::OperationNotPermitted)?; - if tgid.is_some_and(|tgid| thread.proc_data.proc.pid() != tgid) { - return Err(AxError::NoSuchProcess); - } - - if let Some(sig) = sig { - info!("Send signal {:?} to thread {}", sig.signo(), tid); - send_signal_thread_inner(&task, thread, sig); - } - - Ok(()) -} - -/// Sends a signal to a process. -pub fn send_signal_to_process(pid: Pid, sig: Option) -> AxResult<()> { - let proc_data = get_process_data(pid)?; - - if let Some(sig) = sig { - let signo = sig.signo(); - info!("Send signal {signo:?} to process {pid}"); - if let Some(tid) = proc_data.signal.send_signal(sig) - && let Ok(task) = get_task(tid) - { - task.interrupt(); - } - } - - Ok(()) -} - -/// Sends a signal to a process group. -pub fn send_signal_to_process_group(pgid: Pid, sig: Option) -> AxResult<()> { - let pg = get_process_group(pgid)?; - - if let Some(sig) = sig { - info!("Send signal {:?} to process group {}", sig.signo(), pgid); - for proc in pg.processes() { - send_signal_to_process(proc.pid(), Some(sig.clone()))?; - } - } - - Ok(()) -} diff --git a/kernel/src/task/ops.rs b/kernel/src/task/ops.rs new file mode 100644 index 00000000..81e9286a --- /dev/null +++ b/kernel/src/task/ops.rs @@ -0,0 +1,248 @@ +use alloc::{ + sync::{Arc, Weak}, + vec::Vec, +}; +use core::{ffi::c_long, sync::atomic::Ordering}; + +use axerrno::{AxError, AxResult}; +use axtask::{AxTaskRef, TaskInner, WeakAxTaskRef, current}; +use bytemuck::AnyBitPattern; +use linux_raw_sys::general::ROBUST_LIST_LIMIT; +use spin::RwLock; +use starry_process::{Pid, ProcessGroup, Session}; +use starry_signal::{SignalInfo, Signo}; +use starry_vm::{VmMutPtr, VmPtr}; +use weak_map::WeakMap; + +use super::{ + AsThread, FutexKey, ProcessData, TimerState, futex_table_for, send_signal_thread_inner, + send_signal_to_process, send_signal_to_thread, +}; + +static TASK_TABLE: RwLock> = RwLock::new(WeakMap::new()); + +static PROCESS_TABLE: RwLock>> = RwLock::new(WeakMap::new()); + +static PROCESS_GROUP_TABLE: RwLock>> = RwLock::new(WeakMap::new()); + +static SESSION_TABLE: RwLock>> = RwLock::new(WeakMap::new()); + +/// Cleanup expired entries in the task tables. +/// +/// This function is intended to be used during memory leak analysis to remove +/// possible noise caused by expired entries in the [`WeakMap`]. +pub fn cleanup_task_tables() { + TASK_TABLE.write().cleanup(); + PROCESS_TABLE.write().cleanup(); + PROCESS_GROUP_TABLE.write().cleanup(); + SESSION_TABLE.write().cleanup(); +} + +/// Add the task, the thread and possibly its process, process group and session +/// to the corresponding tables. +pub fn add_task_to_table(task: &AxTaskRef) { + let tid = task.id().as_u64() as Pid; + + let mut task_table = TASK_TABLE.write(); + task_table.insert(tid, task); + + let proc_data = &task.as_thread().proc_data; + let proc = &proc_data.proc; + let pid = proc.pid(); + let mut proc_table = PROCESS_TABLE.write(); + if proc_table.contains_key(&pid) { + return; + } + proc_table.insert(pid, proc_data); + + let pg = proc.group(); + let mut pg_table = PROCESS_GROUP_TABLE.write(); + if pg_table.contains_key(&pg.pgid()) { + return; + } + pg_table.insert(pg.pgid(), &pg); + + let session = pg.session(); + let mut session_table = SESSION_TABLE.write(); + if session_table.contains_key(&session.sid()) { + return; + } + session_table.insert(session.sid(), &session); +} + +/// Lists all tasks. +pub fn tasks() -> Vec { + TASK_TABLE.read().values().collect() +} + +/// Finds the task with the given TID. +pub fn get_task(tid: Pid) -> AxResult { + if tid == 0 { + return Ok(current().clone()); + } + TASK_TABLE.read().get(&tid).ok_or(AxError::NoSuchProcess) +} + +/// Lists all processes. +pub fn processes() -> Vec> { + PROCESS_TABLE.read().values().collect() +} + +/// Finds the process with the given PID. +pub fn get_process_data(pid: Pid) -> AxResult> { + if pid == 0 { + return Ok(current().as_thread().proc_data.clone()); + } + PROCESS_TABLE.read().get(&pid).ok_or(AxError::NoSuchProcess) +} + +/// Finds the process group with the given PGID. +pub fn get_process_group(pgid: Pid) -> AxResult> { + PROCESS_GROUP_TABLE + .read() + .get(&pgid) + .ok_or(AxError::NoSuchProcess) +} + +/// Finds the session with the given SID. +pub fn get_session(sid: Pid) -> AxResult> { + SESSION_TABLE.read().get(&sid).ok_or(AxError::NoSuchProcess) +} + +/// Poll the timer +pub fn poll_timer(task: &TaskInner) { + let Some(thr) = task.try_as_thread() else { + return; + }; + let Ok(mut time) = thr.time.try_borrow_mut() else { + // reentrant borrow, likely IRQ + return; + }; + time.poll(|signo| { + send_signal_thread_inner(task, thr, SignalInfo::new_kernel(signo)); + }); +} + +/// Sets the timer state. +pub fn set_timer_state(task: &TaskInner, state: TimerState) { + let Some(thr) = task.try_as_thread() else { + return; + }; + let Ok(mut time) = thr.time.try_borrow_mut() else { + // reentrant borrow, likely IRQ + return; + }; + time.poll(|signo| { + send_signal_thread_inner(task, thr, SignalInfo::new_kernel(signo)); + }); + time.set_state(state); +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, AnyBitPattern)] +pub struct RobustList { + pub next: *mut RobustList, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, AnyBitPattern)] +pub struct RobustListHead { + pub list: RobustList, + pub futex_offset: c_long, + pub list_op_pending: *mut RobustList, +} + +fn handle_futex_death(entry: *mut RobustList, offset: i64) -> AxResult<()> { + let address = (entry as u64) + .checked_add_signed(offset) + .ok_or(AxError::InvalidInput)?; + let address: usize = address.try_into().map_err(|_| AxError::InvalidInput)?; + let key = FutexKey::new_current(address); + + let futex_table = futex_table_for(&key); + + let Some(futex) = futex_table.get(&key) else { + return Ok(()); + }; + futex.owner_dead.store(true, Ordering::SeqCst); + futex.wq.wake(1, u32::MAX); + Ok(()) +} + +pub fn exit_robust_list(head: *const RobustListHead) -> AxResult<()> { + // Reference: https://elixir.bootlin.com/linux/v6.13.6/source/kernel/futex/core.c#L777 + + let mut limit = ROBUST_LIST_LIMIT; + + let end_ptr = unsafe { &raw const (*head).list }; + let head = head.vm_read()?; + let mut entry = head.list.next; + let offset = head.futex_offset; + let pending = head.list_op_pending; + + while !core::ptr::eq(entry, end_ptr) { + let next_entry = entry.vm_read()?.next; + if entry != pending { + handle_futex_death(entry, offset)?; + } + entry = next_entry; + + limit -= 1; + if limit == 0 { + return Err(AxError::FilesystemLoop); + } + axtask::yield_now(); + } + + Ok(()) +} + +pub fn do_exit(exit_code: i32, group_exit: bool) { + let curr = current(); + let thr = curr.as_thread(); + + info!("{} exit with code: {}", curr.id_name(), exit_code); + + let clear_child_tid = thr.clear_child_tid() as *mut u32; + if clear_child_tid.vm_write(0).is_ok() { + let key = FutexKey::new_current(clear_child_tid as usize); + let table = futex_table_for(&key); + let guard = table.get(&key); + if let Some(futex) = guard { + futex.wq.wake(1, u32::MAX); + } + axtask::yield_now(); + } + let head = thr.robust_list_head() as *const RobustListHead; + if !head.is_null() + && let Err(err) = exit_robust_list(head) + { + warn!("exit robust list failed: {err:?}"); + } + + let process = &thr.proc_data.proc; + if process.exit_thread(curr.id().as_u64() as Pid, exit_code) { + process.exit(); + if let Some(parent) = process.parent() { + if let Some(signo) = thr.proc_data.exit_signal { + let _ = send_signal_to_process(parent.pid(), Some(SignalInfo::new_kernel(signo))); + } + if let Ok(data) = get_process_data(parent.pid()) { + data.child_exit_event.wake(); + } + } + thr.proc_data.exit_event.wake(); + + crate::syscall::SHM_MANAGER + .lock() + .clear_proc_shm(process.pid()); + } + if group_exit && !process.is_group_exited() { + process.group_exit(); + let sig = SignalInfo::new_kernel(Signo::SIGKILL); + for tid in process.threads() { + let _ = send_signal_to_thread(None, tid, Some(sig.clone())); + } + } + thr.set_exit(); +} diff --git a/core/src/resources.rs b/kernel/src/task/resources.rs similarity index 100% rename from core/src/resources.rs rename to kernel/src/task/resources.rs diff --git a/kernel/src/task/signal.rs b/kernel/src/task/signal.rs new file mode 100644 index 00000000..f0f15ade --- /dev/null +++ b/kernel/src/task/signal.rs @@ -0,0 +1,138 @@ +use core::sync::atomic::{AtomicBool, Ordering}; + +use axerrno::{AxError, AxResult}; +use axhal::uspace::UserContext; +use axtask::{TaskInner, current}; +use starry_process::Pid; +use starry_signal::{SignalInfo, SignalOSAction, SignalSet}; + +use super::{AsThread, Thread, do_exit, get_process_data, get_process_group, get_task}; + +pub fn check_signals( + thr: &Thread, + uctx: &mut UserContext, + restore_blocked: Option, +) -> bool { + let Some((sig, os_action)) = thr.signal.check_signals(uctx, restore_blocked) else { + return false; + }; + + let signo = sig.signo(); + match os_action { + SignalOSAction::Terminate => { + do_exit(signo as i32, true); + } + SignalOSAction::CoreDump => { + // TODO: implement core dump + do_exit(128 + signo as i32, true); + } + SignalOSAction::Stop => { + // TODO: implement stop + do_exit(1, true); + } + SignalOSAction::Continue => { + // TODO: implement continue + } + SignalOSAction::Handler => { + // do nothing + } + } + true +} + +static BLOCK_NEXT_SIGNAL_CHECK: AtomicBool = AtomicBool::new(false); + +pub fn block_next_signal() { + BLOCK_NEXT_SIGNAL_CHECK.store(true, Ordering::SeqCst); +} + +pub fn unblock_next_signal() -> bool { + BLOCK_NEXT_SIGNAL_CHECK.swap(false, Ordering::SeqCst) +} + +pub fn with_blocked_signals( + blocked: Option, + f: impl FnOnce() -> AxResult, +) -> AxResult { + let curr = current(); + let sig = &curr.as_thread().signal; + + let old_blocked = blocked.map(|set| sig.set_blocked(set)); + f().inspect(|_| { + if let Some(old) = old_blocked { + sig.set_blocked(old); + } + }) +} + +pub(super) fn send_signal_thread_inner(task: &TaskInner, thr: &Thread, sig: SignalInfo) { + if thr.signal.send_signal(sig) { + task.interrupt(); + } +} + +/// Sends a signal to a thread. +pub fn send_signal_to_thread(tgid: Option, tid: Pid, sig: Option) -> AxResult<()> { + let task = get_task(tid)?; + let thread = task.try_as_thread().ok_or(AxError::OperationNotPermitted)?; + if tgid.is_some_and(|tgid| thread.proc_data.proc.pid() != tgid) { + return Err(AxError::NoSuchProcess); + } + + if let Some(sig) = sig { + info!("Send signal {:?} to thread {}", sig.signo(), tid); + send_signal_thread_inner(&task, thread, sig); + } + + Ok(()) +} + +/// Sends a signal to a process. +pub fn send_signal_to_process(pid: Pid, sig: Option) -> AxResult<()> { + let proc_data = get_process_data(pid)?; + + if let Some(sig) = sig { + let signo = sig.signo(); + info!("Send signal {signo:?} to process {pid}"); + if let Some(tid) = proc_data.signal.send_signal(sig) + && let Ok(task) = get_task(tid) + { + task.interrupt(); + } + } + + Ok(()) +} + +/// Sends a signal to a process group. +pub fn send_signal_to_process_group(pgid: Pid, sig: Option) -> AxResult<()> { + let pg = get_process_group(pgid)?; + + if let Some(sig) = sig { + info!("Send signal {:?} to process group {}", sig.signo(), pgid); + for proc in pg.processes() { + send_signal_to_process(proc.pid(), Some(sig.clone()))?; + } + } + + Ok(()) +} + +/// Sends a fatal signal to the current process. +pub fn raise_signal_fatal(sig: SignalInfo) -> AxResult<()> { + let curr = current(); + let proc_data = &curr.as_thread().proc_data; + + let signo = sig.signo(); + info!("Send fatal signal {signo:?} to the current process"); + if let Some(tid) = proc_data.signal.send_signal(sig) + && let Ok(task) = get_task(tid) + { + task.interrupt(); + } else { + // No task wants to handle the signal, abort the task + do_exit(signo as i32, true); + } + + Ok(()) +} diff --git a/core/src/task/stat.rs b/kernel/src/task/stat.rs similarity index 100% rename from core/src/task/stat.rs rename to kernel/src/task/stat.rs diff --git a/core/src/time.rs b/kernel/src/task/timer.rs similarity index 100% rename from core/src/time.rs rename to kernel/src/task/timer.rs diff --git a/kernel/src/task/user.rs b/kernel/src/task/user.rs new file mode 100644 index 00000000..7b08673a --- /dev/null +++ b/kernel/src/task/user.rs @@ -0,0 +1,79 @@ +use axhal::uspace::{ExceptionKind, ReturnReason, UserContext}; +use axtask::TaskInner; +use starry_process::Pid; +use starry_signal::{SignalInfo, Signo}; +use starry_vm::{VmMutPtr, VmPtr}; + +use super::{ + AsThread, TimerState, check_signals, raise_signal_fatal, set_timer_state, unblock_next_signal, +}; +use crate::syscall::handle_syscall; + +/// Create a new user task. +pub fn new_user_task(name: &str, mut uctx: UserContext, set_child_tid: usize) -> TaskInner { + TaskInner::new( + move || { + let curr = axtask::current(); + + if let Some(tid) = (set_child_tid as *mut Pid).nullable() { + tid.vm_write(curr.id().as_u64() as Pid).ok(); + } + + info!("Enter user space: ip={:#x}, sp={:#x}", uctx.ip(), uctx.sp()); + + let thr = curr.as_thread(); + while !thr.pending_exit() { + let reason = uctx.run(); + + set_timer_state(&curr, TimerState::Kernel); + + match reason { + ReturnReason::Syscall => handle_syscall(&mut uctx), + ReturnReason::PageFault(addr, flags) => { + if !thr.proc_data.aspace.lock().handle_page_fault(addr, flags) { + info!( + "{:?}: segmentation fault at {:#x} {:?}", + thr.proc_data.proc, addr, flags + ); + raise_signal_fatal(SignalInfo::new_kernel(Signo::SIGSEGV)) + .expect("Failed to send SIGSEGV"); + } + } + ReturnReason::Interrupt => {} + #[allow(unused_labels)] + ReturnReason::Exception(exc_info) => 'exc: { + // TODO: detailed handling + let signo = match exc_info.kind() { + ExceptionKind::Misaligned => { + #[cfg(target_arch = "loongarch64")] + if unsafe { uctx.emulate_unaligned() }.is_ok() { + break 'exc; + } + Signo::SIGBUS + } + ExceptionKind::Breakpoint => Signo::SIGTRAP, + ExceptionKind::IllegalInstruction => Signo::SIGILL, + _ => Signo::SIGTRAP, + }; + raise_signal_fatal(SignalInfo::new_kernel(signo)) + .expect("Failed to send SIGTRAP"); + } + r => { + warn!("Unexpected return reason: {r:?}"); + raise_signal_fatal(SignalInfo::new_kernel(Signo::SIGSEGV)) + .expect("Failed to send SIGSEGV"); + } + } + + if !unblock_next_signal() { + while check_signals(thr, &mut uctx, None) {} + } + + set_timer_state(&curr, TimerState::User); + curr.clear_interrupt(); + } + }, + name.into(), + crate::config::KERNEL_STACK_SIZE, + ) +} diff --git a/api/src/time.rs b/kernel/src/time.rs similarity index 93% rename from api/src/time.rs rename to kernel/src/time.rs index 80164ee4..3d054f4d 100644 --- a/api/src/time.rs +++ b/kernel/src/time.rs @@ -1,5 +1,3 @@ -use core::sync::atomic::{AtomicUsize, Ordering}; - use axerrno::{AxError, AxResult}; use axhal::time::TimeValue; use linux_raw_sys::general::{ @@ -130,13 +128,3 @@ impl TimeValueLike for __kernel_sock_timeval { )) } } - -static IRQ_CNT: AtomicUsize = AtomicUsize::new(0); - -pub(crate) fn inc_irq_cnt() { - IRQ_CNT.fetch_add(1, Ordering::Relaxed); -} - -pub(crate) fn irq_cnt() -> usize { - IRQ_CNT.load(Ordering::Relaxed) -} diff --git a/src/entry.rs b/src/entry.rs index 86fba54f..7dc7fd9c 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -7,10 +7,11 @@ use axfs::FS_CONTEXT; use axhal::uspace::UserContext; use axsync::Mutex; use axtask::{AxTaskExt, spawn_task}; -use starry_api::{file::FD_TABLE, task::new_user_task, vfs::dev::tty::N_TTY}; -use starry_core::{ +use starry_kernel::{ + file::FD_TABLE, mm::{copy_from_kernel, load_user_app, new_user_aspace_empty}, - task::{ProcessData, Thread, add_task_to_table}, + pseudofs::dev::tty::N_TTY, + task::{ProcessData, Thread, add_task_to_table, new_user_task}, }; use starry_process::{Pid, Process}; @@ -55,7 +56,7 @@ pub fn run_initproc(args: &[String], envs: &[String]) -> i32 { ); { let mut scope = proc_data.scope.write(); - starry_api::file::add_stdio(&mut FD_TABLE.scope_mut(&mut scope).write()) + starry_kernel::file::add_stdio(&mut FD_TABLE.scope_mut(&mut scope).write()) .expect("Failed to add stdio"); } let thr = Thread::new(pid, proc_data); diff --git a/src/main.rs b/src/main.rs index b88237cc..38dc2237 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ pub const CMDLINE: &[&str] = &["/bin/sh", "-c", include_str!("init.sh")]; #[unsafe(no_mangle)] fn main() { - starry_api::init(); + starry_kernel::init(); let args = CMDLINE .iter() From 9dd35dde486e6906d0411e3042bde1e442fc47a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Sun, 15 Feb 2026 23:03:34 +0800 Subject: [PATCH 2/2] style: format --- kernel/src/syscall/fs/fd_ops.rs | 2 +- kernel/src/syscall/mm/mmap.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/syscall/fs/fd_ops.rs b/kernel/src/syscall/fs/fd_ops.rs index 44f0090d..32e6e7b7 100644 --- a/kernel/src/syscall/fs/fd_ops.rs +++ b/kernel/src/syscall/fs/fd_ops.rs @@ -18,9 +18,9 @@ use crate::{ with_fs, }, mm::{UserPtr, vm_load_string}, + pseudofs::{Device, dev::tty}, syscall::sys::{sys_getegid, sys_geteuid}, task::AsThread, - pseudofs::{Device, dev::tty}, }; /// Convert open flags to [`OpenOptions`]. diff --git a/kernel/src/syscall/mm/mmap.rs b/kernel/src/syscall/mm/mmap.rs index dbb56ec6..48574524 100644 --- a/kernel/src/syscall/mm/mmap.rs +++ b/kernel/src/syscall/mm/mmap.rs @@ -11,8 +11,8 @@ use starry_vm::{vm_load, vm_write_slice}; use crate::{ file::{File, FileLike}, - task::AsThread, pseudofs::{Device, DeviceMmap}, + task::AsThread, }; bitflags::bitflags! {