From f540345bfdee8eb372c8926603beddb25d793e58 Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Wed, 6 Sep 2023 17:32:25 +0800 Subject: [PATCH] Use builder pattern to refactor the process module --- services/libs/jinux-std/src/device/pty/pty.rs | 4 +- .../src/device/tty/line_discipline.rs | 2 +- services/libs/jinux-std/src/device/tty/mod.rs | 8 +- .../libs/jinux-std/src/fs/procfs/pid/comm.rs | 2 +- .../libs/jinux-std/src/fs/procfs/pid/exe.rs | 2 +- services/libs/jinux-std/src/lib.rs | 2 +- services/libs/jinux-std/src/prelude.rs | 2 +- services/libs/jinux-std/src/process/clone.rs | 190 ++++---- services/libs/jinux-std/src/process/exit.rs | 64 +++ services/libs/jinux-std/src/process/mod.rs | 415 +----------------- .../jinux-std/src/process/posix_thread/mod.rs | 34 +- .../src/process/posix_thread/robust_list.rs | 2 +- .../jinux-std/src/process/process/builder.rs | 212 +++++++++ .../libs/jinux-std/src/process/process/mod.rs | 299 +++++++++++++ .../jinux-std/src/process/process_filter.rs | 5 +- .../src/process/process_vm/mmap_options.rs | 69 --- .../jinux-std/src/process/process_vm/mod.rs | 10 +- .../process/program_loader/elf/load_elf.rs | 5 +- .../libs/jinux-std/src/process/signal/mod.rs | 14 +- .../src/process/signal/sig_queues.rs | 4 +- services/libs/jinux-std/src/process/status.rs | 10 + services/libs/jinux-std/src/process/wait.rs | 25 +- services/libs/jinux-std/src/syscall/clone.rs | 2 +- services/libs/jinux-std/src/syscall/execve.rs | 9 +- services/libs/jinux-std/src/syscall/exit.rs | 2 +- .../libs/jinux-std/src/syscall/exit_group.rs | 4 +- services/libs/jinux-std/src/syscall/fork.rs | 2 +- services/libs/jinux-std/src/syscall/kill.rs | 2 +- services/libs/jinux-std/src/syscall/mmap.rs | 68 ++- services/libs/jinux-std/src/syscall/pause.rs | 4 +- services/libs/jinux-std/src/syscall/prctl.rs | 4 +- .../libs/jinux-std/src/syscall/prlimit64.rs | 2 +- .../jinux-std/src/syscall/rt_sigprocmask.rs | 2 +- .../jinux-std/src/syscall/rt_sigreturn.rs | 2 +- .../jinux-std/src/syscall/set_robust_list.rs | 2 +- .../jinux-std/src/syscall/set_tid_address.rs | 5 +- .../libs/jinux-std/src/syscall/setpgid.rs | 10 +- services/libs/jinux-std/src/syscall/tgkill.rs | 5 +- services/libs/jinux-std/src/syscall/wait4.rs | 4 +- services/libs/jinux-std/src/syscall/waitid.rs | 4 +- .../libs/jinux-std/src/thread/exception.rs | 2 +- services/libs/jinux-std/src/thread/mod.rs | 6 +- 42 files changed, 878 insertions(+), 643 deletions(-) create mode 100644 services/libs/jinux-std/src/process/exit.rs create mode 100644 services/libs/jinux-std/src/process/process/builder.rs create mode 100644 services/libs/jinux-std/src/process/process/mod.rs delete mode 100644 services/libs/jinux-std/src/process/process_vm/mmap_options.rs diff --git a/services/libs/jinux-std/src/device/pty/pty.rs b/services/libs/jinux-std/src/device/pty/pty.rs index e7ecd1164..b55462dd7 100644 --- a/services/libs/jinux-std/src/device/pty/pty.rs +++ b/services/libs/jinux-std/src/device/pty/pty.rs @@ -194,8 +194,8 @@ impl FileLike for PtyMaster { // TODO: reimplement when adding session. let foreground = { let current = current!(); - let process_group = current.process_group().lock(); - process_group.clone() + let process_group = current.process_group().unwrap(); + Arc::downgrade(&process_group) }; self.output.set_fg(foreground); Ok(0) diff --git a/services/libs/jinux-std/src/device/tty/line_discipline.rs b/services/libs/jinux-std/src/device/tty/line_discipline.rs index 233798f30..208cc3ffd 100644 --- a/services/libs/jinux-std/src/device/tty/line_discipline.rs +++ b/services/libs/jinux-std/src/device/tty/line_discipline.rs @@ -1,6 +1,6 @@ use crate::fs::utils::{IoEvents, Pollee, Poller}; -use crate::process::process_group::ProcessGroup; use crate::process::signal::constants::{SIGINT, SIGQUIT}; +use crate::process::ProcessGroup; use crate::{ prelude::*, process::{signal::signals::kernel::KernelSignal, Pgid}, diff --git a/services/libs/jinux-std/src/device/tty/mod.rs b/services/libs/jinux-std/src/device/tty/mod.rs index 1564266bf..729d4868a 100644 --- a/services/libs/jinux-std/src/device/tty/mod.rs +++ b/services/libs/jinux-std/src/device/tty/mod.rs @@ -5,8 +5,7 @@ use self::line_discipline::LineDiscipline; use super::*; use crate::fs::utils::{IoEvents, IoctlCmd, Poller}; use crate::prelude::*; -use crate::process::process_group::ProcessGroup; -use crate::process::process_table; +use crate::process::{process_table, ProcessGroup}; use crate::util::{read_val_from_user, write_val_to_user}; pub mod driver; @@ -101,7 +100,10 @@ impl Device for Tty { IoctlCmd::TIOCSPGRP => { // Set the process group id of fg progress group let pgid = read_val_from_user::(arg)?; - match process_table::pgid_to_process_group(pgid) { + if pgid < 0 { + return_errno_with_message!(Errno::EINVAL, "invalid pgid"); + } + match process_table::pgid_to_process_group(pgid as u32) { None => self.ldisc.set_fg(Weak::new()), Some(process_group) => self.ldisc.set_fg(Arc::downgrade(&process_group)), } diff --git a/services/libs/jinux-std/src/fs/procfs/pid/comm.rs b/services/libs/jinux-std/src/fs/procfs/pid/comm.rs index 24d65dd2b..20b1e3533 100644 --- a/services/libs/jinux-std/src/fs/procfs/pid/comm.rs +++ b/services/libs/jinux-std/src/fs/procfs/pid/comm.rs @@ -15,7 +15,7 @@ impl CommFileOps { impl FileOps for CommFileOps { fn data(&self) -> Result> { let mut comm_output = { - let exe_path = self.0.executable_path().read(); + let exe_path = self.0.executable_path(); let last_component = exe_path.rsplit('/').next().unwrap_or(&exe_path); let mut comm = last_component.as_bytes().to_vec(); comm.push(b'\0'); diff --git a/services/libs/jinux-std/src/fs/procfs/pid/exe.rs b/services/libs/jinux-std/src/fs/procfs/pid/exe.rs index 5818586f8..22a9f42f9 100644 --- a/services/libs/jinux-std/src/fs/procfs/pid/exe.rs +++ b/services/libs/jinux-std/src/fs/procfs/pid/exe.rs @@ -14,6 +14,6 @@ impl ExeSymOps { impl SymOps for ExeSymOps { fn read_link(&self) -> Result { - Ok(self.0.executable_path().read().clone()) + Ok(self.0.executable_path()) } } diff --git a/services/libs/jinux-std/src/lib.rs b/services/libs/jinux-std/src/lib.rs index 65114b7c0..b9e4ad2ca 100644 --- a/services/libs/jinux-std/src/lib.rs +++ b/services/libs/jinux-std/src/lib.rs @@ -85,7 +85,7 @@ fn init_thread() { .expect("Run init process failed."); // Wait till initproc become zombie. - while !initproc.status().lock().is_zombie() { + while !initproc.is_zombie() { // We don't have preemptive scheduler now. // The long running init thread should yield its own execution to allow other tasks to go on. Thread::yield_now(); diff --git a/services/libs/jinux-std/src/prelude.rs b/services/libs/jinux-std/src/prelude.rs index 4be03973b..8ef99bba1 100644 --- a/services/libs/jinux-std/src/prelude.rs +++ b/services/libs/jinux-std/src/prelude.rs @@ -28,7 +28,7 @@ pub(crate) use pod::Pod; #[macro_export] macro_rules! current { () => { - $crate::process::Process::current() + $crate::process::current() }; } diff --git a/services/libs/jinux-std/src/process/clone.rs b/services/libs/jinux-std/src/process/clone.rs index db35bfe25..ca62feb63 100644 --- a/services/libs/jinux-std/src/process/clone.rs +++ b/services/libs/jinux-std/src/process/clone.rs @@ -1,8 +1,4 @@ -use jinux_frame::{ - cpu::UserContext, - user::UserSpace, - vm::{VmIo, VmSpace}, -}; +use jinux_frame::{cpu::UserContext, user::UserSpace, vm::VmIo}; use jinux_rights::Full; @@ -12,9 +8,7 @@ use crate::{ fs::{fs_resolver::FsResolver, utils::FileCreationMask}, prelude::*, process::{ - posix_thread::{ - builder::PosixThreadBuilder, name::ThreadName, posix_thread_ext::PosixThreadExt, - }, + posix_thread::{PosixThreadBuilder, PosixThreadExt, ThreadName}, process_table, }, thread::{allocate_tid, thread_table, Thread, Tid}, @@ -24,7 +18,7 @@ use crate::{ use super::{ posix_thread::PosixThread, process_vm::ProcessVm, signal::sig_disposition::SigDispositions, - Process, + Process, ProcessBuilder, }; bitflags! { @@ -164,27 +158,39 @@ fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Res debug_assert!(clone_flags.contains(CloneFlags::CLONE_FILES)); debug_assert!(clone_flags.contains(CloneFlags::CLONE_SIGHAND)); let child_root_vmar = current.root_vmar(); - let child_vm_space = child_root_vmar.vm_space().clone(); - let child_cpu_context = clone_cpu_context( - parent_context, - clone_args.new_sp, - clone_args.tls, - clone_flags, - ); - let child_user_space = Arc::new(UserSpace::new(child_vm_space, child_cpu_context)); + + let child_user_space = { + let child_vm_space = child_root_vmar.vm_space().clone(); + let child_cpu_context = clone_cpu_context( + parent_context, + clone_args.new_sp, + clone_args.tls, + clone_flags, + ); + Arc::new(UserSpace::new(child_vm_space, child_cpu_context)) + }; clone_sysvsem(clone_flags)?; + // Inherit sigmask from current thread + let sig_mask = { + let current_thread = current_thread!(); + let current_posix_thread = current_thread.as_posix_thread().unwrap(); + let sigmask = current_posix_thread.sig_mask().lock(); + *sigmask + }; + let child_tid = allocate_tid(); - // inherit sigmask from current thread - let current_thread = current_thread!(); - let current_posix_thread = current_thread.as_posix_thread().unwrap(); - let sig_mask = *current_posix_thread.sig_mask().lock(); - let is_main_thread = child_tid == current.pid(); - let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space) - .process(Arc::downgrade(¤t)) - .is_main_thread(is_main_thread); - let child_thread = thread_builder.build(); - current.threads.lock().push(child_thread.clone()); + let child_thread = { + let is_main_thread = child_tid == current.pid(); + let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space) + .process(Arc::downgrade(¤t)) + .sig_mask(sig_mask) + .is_main_thread(is_main_thread); + thread_builder.build() + }; + + current.threads().lock().push(child_thread.clone()); + let child_posix_thread = child_thread.as_posix_thread().unwrap(); clone_parent_settid(child_tid, clone_args.parent_tidptr, clone_flags)?; clone_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?; @@ -203,73 +209,77 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re let clone_flags = clone_args.clone_flags; // clone vm - let child_root_vmar = { - let parent_root_vmar = current.root_vmar(); - clone_vm(parent_root_vmar, clone_flags)? - }; - let child_process_vm = { - let child_user_heap = current.user_heap().clone(); - ProcessVm::new(child_user_heap, child_root_vmar.dup()?) + let parent_process_vm = current.vm(); + clone_vm(parent_process_vm, clone_flags)? }; // clone user space - let child_cpu_context = clone_cpu_context( - parent_context, - clone_args.new_sp, - clone_args.tls, - clone_flags, - ); - let child_vm_space = child_root_vmar.vm_space().clone(); - let child_user_space = Arc::new(UserSpace::new(child_vm_space, child_cpu_context)); + let child_user_space = { + let child_cpu_context = clone_cpu_context( + parent_context, + clone_args.new_sp, + clone_args.tls, + clone_flags, + ); + let child_vm_space = { + let child_root_vmar = child_process_vm.root_vmar(); + child_root_vmar.vm_space().clone() + }; + Arc::new(UserSpace::new(child_vm_space, child_cpu_context)) + }; // clone file table let child_file_table = clone_files(current.file_table(), clone_flags); + // clone fs let child_fs = clone_fs(current.fs(), clone_flags); + // clone umask - let parent_umask = current.umask.read().get(); - let child_umask = Arc::new(RwLock::new(FileCreationMask::new(parent_umask))); + let child_umask = { + let parent_umask = current.umask().read().get(); + Arc::new(RwLock::new(FileCreationMask::new(parent_umask))) + }; + // clone sig dispositions let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags); + // clone system V semaphore clone_sysvsem(clone_flags)?; - let child_elf_path = current.executable_path().read().clone(); - let child_thread_name = ThreadName::new_from_executable_path(&child_elf_path)?; - // inherit parent's sig mask - let current_thread = current_thread!(); - let posix_thread = current_thread.as_posix_thread().unwrap(); - let child_sig_mask = *posix_thread.sig_mask().lock(); + let child_sig_mask = { + let current_thread = current_thread!(); + let posix_thread = current_thread.as_posix_thread().unwrap(); + let sigmask = posix_thread.sig_mask().lock(); + *sigmask + }; let child_tid = allocate_tid(); - let mut child_thread_builder = PosixThreadBuilder::new(child_tid, child_user_space) - .thread_name(Some(child_thread_name)) - .sig_mask(child_sig_mask); - let child = Arc::new_cyclic(|child_process_ref| { - let weak_child_process = child_process_ref.clone(); - let child_pid = child_tid; - child_thread_builder = child_thread_builder.process(weak_child_process); - let child_thread = child_thread_builder.build(); - Process::new( - child_pid, - parent, - vec![child_thread], - child_elf_path, - child_process_vm, - Weak::new(), - child_file_table, - child_fs, - child_umask, - child_sig_dispositions, - ) - }); - // Inherit parent's process group - let parent_process_group = current.process_group().lock().upgrade().unwrap(); - parent_process_group.add_process(child.clone()); - child.set_process_group(Arc::downgrade(&parent_process_group)); + let child = { + let child_elf_path = current.executable_path(); + let child_thread_builder = { + let child_thread_name = ThreadName::new_from_executable_path(&child_elf_path)?; + PosixThreadBuilder::new(child_tid, child_user_space) + .thread_name(Some(child_thread_name)) + .sig_mask(child_sig_mask) + }; + + let mut process_builder = + ProcessBuilder::new(child_tid, &child_elf_path, Arc::downgrade(¤t)); + + process_builder + .main_thread_builder(child_thread_builder) + .process_vm(child_process_vm) + .file_table(child_file_table) + .fs(child_fs) + .umask(child_umask) + .sig_dispositions(child_sig_dispositions) + .process_group(current.process_group().unwrap()); + + process_builder.build()? + }; current!().add_child(child.clone()); process_table::add_process(child.clone()); @@ -278,8 +288,10 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re let child_posix_thread = child_thread.as_posix_thread().unwrap(); clone_parent_settid(child_tid, clone_args.parent_tidptr, clone_flags)?; clone_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?; + + let child_root_vmar = child.root_vmar(); clone_child_settid( - &child_root_vmar, + child_root_vmar, child_tid, clone_args.child_tidptr, clone_flags, @@ -322,13 +334,15 @@ fn clone_parent_settid( Ok(()) } -/// clone child vmar. If CLONE_VM is set, both threads share the same root vmar. +/// Clone child process vm. If CLONE_VM is set, both threads share the same root vmar. /// Otherwise, fork a new copy-on-write vmar. -fn clone_vm(parent_root_vmar: &Vmar, clone_flags: CloneFlags) -> Result> { +fn clone_vm(parent_process_vm: &ProcessVm, clone_flags: CloneFlags) -> Result { if clone_flags.contains(CloneFlags::CLONE_VM) { - Ok(parent_root_vmar.dup()?) + Ok(parent_process_vm.clone()) } else { - Ok(parent_root_vmar.fork_vmar()?) + let root_vmar = parent_process_vm.root_vmar().fork_vmar()?; + let user_heap = parent_process_vm.user_heap().clone(); + Ok(ProcessVm::new(user_heap, root_vmar)) } } @@ -400,19 +414,3 @@ fn clone_sysvsem(clone_flags: CloneFlags) -> Result<()> { } Ok(()) } - -/// debug use. check clone vm space corrent. -fn debug_check_clone_vm_space(parent_vm_space: &VmSpace, child_vm_space: &VmSpace) { - let mut buffer1 = vec![0u8; 0x78]; - let mut buffer2 = vec![0u8; 0x78]; - parent_vm_space - .read_bytes(0x401000, &mut buffer1) - .expect("read buffer1 failed"); - child_vm_space - .read_bytes(0x401000, &mut buffer2) - .expect("read buffer1 failed"); - for len in 0..buffer1.len() { - assert_eq!(buffer1[len], buffer2[len]); - } - debug!("check clone vm space succeed."); -} diff --git a/services/libs/jinux-std/src/process/exit.rs b/services/libs/jinux-std/src/process/exit.rs new file mode 100644 index 000000000..d82d4c142 --- /dev/null +++ b/services/libs/jinux-std/src/process/exit.rs @@ -0,0 +1,64 @@ +use crate::process::posix_thread::PosixThreadExt; +use crate::process::signal::signals::kernel::KernelSignal; +use crate::{prelude::*, process::signal::constants::SIGCHLD}; + +use super::{process_table, Pid, Process, TermStatus}; + +pub fn do_exit_group(term_status: TermStatus) { + let current = current!(); + debug!("exit group was called"); + if current.is_zombie() { + return; + } + current.set_zombie(term_status); + + // Exit all threads + let threads = current.threads().lock().clone(); + for thread in threads { + if thread.is_exited() { + continue; + } + + thread.exit(); + if let Some(posix_thread) = thread.as_posix_thread() { + let tid = thread.tid(); + if let Err(e) = posix_thread.exit(tid, term_status) { + debug!("Ignore error when call exit: {:?}", e); + } + } + } + + // Close all files then exit the process + let files = current.file_table().lock().close_all(); + for file in files { + let _ = file.clean_for_close(); + } + + // Move children to the init process + if !is_init_process(¤t) { + if let Some(init_process) = get_init_process() { + for (_, child_process) in current.children().lock().extract_if(|_, _| true) { + child_process.set_parent(Arc::downgrade(&init_process)); + init_process.add_child(child_process); + } + } + } + + if let Some(parent) = current.parent() { + // Notify parent + let signal = Box::new(KernelSignal::new(SIGCHLD)); + parent.enqueue_signal(signal); + parent.waiting_children().wake_all(); + } +} + +const INIT_PROCESS_PID: Pid = 1; + +/// Get the init process +fn get_init_process() -> Option> { + process_table::pid_to_process(INIT_PROCESS_PID) +} + +fn is_init_process(process: &Process) -> bool { + process.pid() == INIT_PROCESS_PID +} diff --git a/services/libs/jinux-std/src/process/mod.rs b/services/libs/jinux-std/src/process/mod.rs index 18ad42f9d..de1452817 100644 --- a/services/libs/jinux-std/src/process/mod.rs +++ b/services/libs/jinux-std/src/process/mod.rs @@ -1,402 +1,27 @@ -use self::posix_thread::posix_thread_ext::PosixThreadExt; -use self::process_group::ProcessGroup; -use self::process_vm::user_heap::UserHeap; -use self::process_vm::ProcessVm; -use self::rlimit::ResourceLimits; -use self::signal::constants::SIGCHLD; -use self::signal::sig_disposition::SigDispositions; -use self::signal::sig_queues::SigQueues; -use self::signal::signals::kernel::KernelSignal; -use self::signal::signals::Signal; -use self::status::ProcessStatus; -use crate::device::tty::get_n_tty; -use crate::fs::file_table::FileTable; -use crate::fs::fs_resolver::FsResolver; -use crate::fs::utils::FileCreationMask; -use crate::prelude::*; -use crate::thread::{allocate_tid, thread_table, Thread}; -use crate::vm::vmar::Vmar; -use jinux_frame::sync::WaitQueue; -use jinux_rights::Full; - -pub mod clone; +mod clone; +mod exit; pub mod fifo_scheduler; pub mod posix_thread; -pub mod process_filter; -pub mod process_group; +#[allow(clippy::module_inception)] +mod process; +mod process_filter; +mod process_group; pub mod process_table; -pub mod process_vm; -pub mod program_loader; -pub mod rlimit; +mod process_vm; +mod program_loader; +mod rlimit; pub mod signal; -pub mod status; +mod status; mod term_status; -pub mod wait; +mod wait; +pub use clone::{clone_child, CloneArgs, CloneFlags}; +pub use exit::do_exit_group; +pub use process::ProcessBuilder; +pub use process::{current, ExitCode, Pgid, Pid, Process}; +pub use process_filter::ProcessFilter; +pub use process_group::ProcessGroup; +pub use program_loader::{check_executable_file, load_program_to_vm}; +pub use rlimit::ResourceType; pub use term_status::TermStatus; - -pub type Pid = i32; -pub type Pgid = i32; -pub type ExitCode = i32; - -const INIT_PROCESS_PID: Pid = 1; - -/// Process stands for a set of threads that shares the same userspace. -pub struct Process { - // Immutable Part - pid: Pid, - - process_vm: ProcessVm, - /// wait for child status changed - waiting_children: WaitQueue, - - // Mutable Part - /// The executable path. - executable_path: RwLock, - /// The threads - threads: Mutex>>, - /// Process status - status: Mutex, - /// Parent process - parent: Mutex>, - /// Children processes - children: Mutex>>, - /// Process group - process_group: Mutex>, - /// File table - file_table: Arc>, - /// FsResolver - fs: Arc>, - /// umask - umask: Arc>, - /// resource limits - resource_limits: Mutex, - - // Signal - /// sig dispositions - sig_dispositions: Arc>, - /// Process-level signal queues - sig_queues: Mutex, -} - -impl Process { - /// returns the current process - pub fn current() -> Arc { - let current_thread = Thread::current(); - if let Some(posix_thread) = current_thread.as_posix_thread() { - posix_thread.process() - } else { - panic!("[Internal error]The current thread does not belong to a process"); - } - } - - /// create a new process(not schedule it) - #[allow(clippy::too_many_arguments)] - pub fn new( - pid: Pid, - parent: Weak, - threads: Vec>, - executable_path: String, - process_vm: ProcessVm, - process_group: Weak, - file_table: Arc>, - fs: Arc>, - umask: Arc>, - sig_dispositions: Arc>, - ) -> Self { - let children = BTreeMap::new(); - let waiting_children = WaitQueue::new(); - let resource_limits = ResourceLimits::default(); - Self { - pid, - threads: Mutex::new(threads), - executable_path: RwLock::new(executable_path), - process_vm, - waiting_children, - status: Mutex::new(ProcessStatus::Runnable), - parent: Mutex::new(parent), - children: Mutex::new(children), - process_group: Mutex::new(process_group), - file_table, - fs, - umask, - sig_dispositions, - sig_queues: Mutex::new(SigQueues::new()), - resource_limits: Mutex::new(resource_limits), - } - } - - pub fn waiting_children(&self) -> &WaitQueue { - &self.waiting_children - } - - /// init a user process and run the process - pub fn spawn_user_process( - executable_path: &str, - argv: Vec, - envp: Vec, - ) -> Result> { - // spawn user process should give an absolute path - debug_assert!(executable_path.starts_with('/')); - let process = Process::create_user_process(executable_path, argv, envp)?; - // FIXME: How to determine the fg process group? - let process_group = Weak::clone(&process.process_group.lock()); - // FIXME: tty should be a parameter? - let tty = get_n_tty(); - tty.set_fg(process_group); - process.run(); - Ok(process) - } - - fn create_user_process( - executable_path: &str, - argv: Vec, - envp: Vec, - ) -> Result> { - let fs = FsResolver::new(); - let umask = FileCreationMask::default(); - let pid = allocate_tid(); - let parent = Weak::new(); - let process_group = Weak::new(); - let process_vm = ProcessVm::alloc()?; - let file_table = FileTable::new_with_stdio(); - let sig_dispositions = SigDispositions::new(); - let user_process = Arc::new(Process::new( - pid, - parent, - vec![], - executable_path.to_string(), - process_vm, - process_group, - Arc::new(Mutex::new(file_table)), - Arc::new(RwLock::new(fs)), - Arc::new(RwLock::new(umask)), - Arc::new(Mutex::new(sig_dispositions)), - )); - - let thread = Thread::new_posix_thread_from_executable( - pid, - &user_process.process_vm, - &user_process.fs().read(), - executable_path, - Arc::downgrade(&user_process), - argv, - envp, - )?; - user_process.threads().lock().push(thread); - - // Set process group - user_process.create_and_set_process_group(); - process_table::add_process(user_process.clone()); - Ok(user_process) - } - - /// returns the pid of the process - pub fn pid(&self) -> Pid { - self.pid - } - - /// returns the process group id of the process - pub fn pgid(&self) -> Pgid { - if let Some(process_group) = self.process_group.lock().upgrade() { - process_group.pgid() - } else { - 0 - } - } - - pub fn process_group(&self) -> &Mutex> { - &self.process_group - } - - /// add a child process - pub fn add_child(&self, child: Arc) { - let child_pid = child.pid(); - self.children.lock().insert(child_pid, child); - } - - pub fn set_parent(&self, parent: Weak) { - *self.parent.lock() = parent; - } - - /// Set process group for current process. If old process group exists, - /// remove current process from old process group. - pub fn set_process_group(&self, process_group: Weak) { - if let Some(old_process_group) = self.process_group.lock().upgrade() { - old_process_group.remove_process(self.pid()); - } - *self.process_group.lock() = process_group; - } - - pub fn file_table(&self) -> &Arc> { - &self.file_table - } - - pub fn fs(&self) -> &Arc> { - &self.fs - } - - pub fn umask(&self) -> &Arc> { - &self.umask - } - - /// create a new process group for the process and add it to globle table. - /// Then set the process group for current process. - fn create_and_set_process_group(self: &Arc) { - let process_group = Arc::new(ProcessGroup::new(self.clone())); - let pgid = process_group.pgid(); - self.set_process_group(Arc::downgrade(&process_group)); - process_table::add_process_group(process_group); - } - - pub fn parent(&self) -> Option> { - self.parent.lock().upgrade() - } - - /// Exit thread group(the process). - /// Set the status of the process as Zombie and set exit code. - /// Move all children to init process. - /// Wake up the parent wait queue if parent is waiting for self. - pub fn exit_group(&self, term_status: TermStatus) { - debug!("exit group was called"); - if self.status.lock().is_zombie() { - return; - } - self.status.lock().set_zombie(term_status); - - let threads = self.threads.lock().clone(); - for thread in threads { - if thread.is_exited() { - continue; - } - - thread.exit(); - if let Some(posix_thread) = thread.as_posix_thread() { - let tid = thread.tid(); - if let Err(e) = posix_thread.exit(tid, term_status) { - debug!("Ignore error when call exit: {:?}", e); - } - } - } - // close all files then exit the process - let files = self.file_table().lock().close_all(); - for file in files { - let _ = file.clean_for_close(); - } - // move children to the init process - if !self.is_init_process() { - if let Some(init_process) = get_init_process() { - for (_, child_process) in self.children.lock().extract_if(|_, _| true) { - child_process.set_parent(Arc::downgrade(&init_process)); - init_process.add_child(child_process); - } - } - } - - if let Some(parent) = self.parent() { - // set parent sig child - let signal = Box::new(KernelSignal::new(SIGCHLD)); - parent.sig_queues().lock().enqueue(signal); - // wake up parent waiting children, if any - parent.waiting_children().wake_all(); - } - } - - /// if the current process is init process - pub fn is_init_process(&self) -> bool { - self.pid == 0 - } - - /// start to run current process - pub fn run(&self) { - let threads = self.threads.lock(); - // when run the process, the process should has only one thread - debug_assert!(threads.len() == 1); - let thread = threads[0].clone(); - // should not hold the lock when run thread - drop(threads); - thread.run(); - } - - pub fn threads(&self) -> &Mutex>> { - &self.threads - } - - /// returns the user_vm - pub fn process_vm(&self) -> &ProcessVm { - &self.process_vm - } - - /// returns the root vmar - pub fn root_vmar(&self) -> &Vmar { - self.process_vm.root_vmar() - } - - /// returns the user heap if the process does have, otherwise None - pub fn user_heap(&self) -> &UserHeap { - self.process_vm.user_heap() - } - - /// free zombie child with pid, returns the exit code of child process. - /// remove process from process group. - pub fn reap_zombie_child(&self, pid: Pid) -> u32 { - let child_process = self.children.lock().remove(&pid).unwrap(); - assert!(child_process.status().lock().is_zombie()); - child_process.root_vmar().destroy_all().unwrap(); - for thread in &*child_process.threads.lock() { - thread_table::remove_thread(thread.tid()); - } - process_table::remove_process(child_process.pid()); - if let Some(process_group) = child_process.process_group().lock().upgrade() { - process_group.remove_process(child_process.pid); - } - child_process.exit_code().unwrap() - } - - pub fn children(&self) -> &Mutex>> { - &self.children - } - - pub fn exit_code(&self) -> Option { - match &*self.status.lock() { - ProcessStatus::Runnable => None, - ProcessStatus::Zombie(term_status) => Some(term_status.as_u32()), - } - } - - /// whether the process has child process - pub fn has_child(&self) -> bool { - self.children.lock().len() != 0 - } - - pub fn executable_path(&self) -> &RwLock { - &self.executable_path - } - - pub fn status(&self) -> &Mutex { - &self.status - } - - pub fn resource_limits(&self) -> &Mutex { - &self.resource_limits - } - - pub fn sig_dispositions(&self) -> &Arc> { - &self.sig_dispositions - } - - pub fn sig_queues(&self) -> &Mutex { - &self.sig_queues - } - - pub fn enqueue_signal(&self, signal: Box) { - if !self.status().lock().is_zombie() { - self.sig_queues.lock().enqueue(signal); - } - } -} - -/// Get the init process -pub fn get_init_process() -> Option> { - process_table::pid_to_process(INIT_PROCESS_PID) -} +pub use wait::{wait_child_exit, WaitOptions}; diff --git a/services/libs/jinux-std/src/process/posix_thread/mod.rs b/services/libs/jinux-std/src/process/posix_thread/mod.rs index 04254e484..fc4b8ece7 100644 --- a/services/libs/jinux-std/src/process/posix_thread/mod.rs +++ b/services/libs/jinux-std/src/process/posix_thread/mod.rs @@ -1,6 +1,7 @@ use crate::{ prelude::*, process::{ + do_exit_group, posix_thread::{futex::futex_wake, robust_list::wake_robust_futex}, TermStatus, }, @@ -8,18 +9,21 @@ use crate::{ util::write_val_to_user, }; -use self::{name::ThreadName, robust_list::RobustListHead}; - use super::{ - signal::{sig_mask::SigMask, sig_queues::SigQueues}, + signal::{sig_mask::SigMask, sig_queues::SigQueues, signals::Signal}, Process, }; -pub mod builder; +mod builder; pub mod futex; -pub mod name; -pub mod posix_thread_ext; -pub mod robust_list; +mod name; +mod posix_thread_ext; +mod robust_list; + +pub use builder::PosixThreadBuilder; +pub use name::{ThreadName, MAX_THREAD_NAME_LEN}; +pub use posix_thread_ext::PosixThreadExt; +pub use robust_list::RobustListHead; pub struct PosixThread { // Immutable part @@ -71,6 +75,18 @@ impl PosixThread { &self.sig_queues } + pub fn has_pending_signal(&self) -> bool { + self.sig_queues.lock().is_empty() + } + + pub fn enqueue_signal(&self, signal: Box) { + self.sig_queues.lock().enqueue(signal); + } + + pub fn dequeue_signal(&self, mask: &SigMask) -> Option> { + self.sig_queues.lock().dequeue(mask) + } + pub fn sig_context(&self) -> &Mutex> { &self.sig_context } @@ -133,7 +149,7 @@ impl PosixThread { // exit the robust list: walk the robust list; mark futex words as dead and do futex wake self.wake_robust_list(tid); - if tid != self.process().pid { + if tid != self.process().pid() { // If the thread is not main thread. We don't remove main thread. // Main thread are removed when the whole process is reaped. thread_table::remove_thread(tid); @@ -144,7 +160,7 @@ impl PosixThread { debug!("self is main thread or last thread"); debug!("main thread: {}", self.is_main_thread()); debug!("last thread: {}", self.is_last_thread()); - current!().exit_group(term_status); + do_exit_group(term_status); } debug!("perform futex wake"); futex_wake(Arc::as_ptr(&self.process()) as Vaddr, 1)?; diff --git a/services/libs/jinux-std/src/process/posix_thread/robust_list.rs b/services/libs/jinux-std/src/process/posix_thread/robust_list.rs index dd923015a..f4b5057e2 100644 --- a/services/libs/jinux-std/src/process/posix_thread/robust_list.rs +++ b/services/libs/jinux-std/src/process/posix_thread/robust_list.rs @@ -132,7 +132,7 @@ pub fn wake_robust_futex(futex_addr: Vaddr, tid: Pid) -> Result<()> { let mut old_val = futex_val; loop { // This futex may held by another thread, do nothing - if old_val & FUTEX_TID_MASK != tid as u32 { + if old_val & FUTEX_TID_MASK != tid { break; } let new_val = (old_val & FUTEX_WAITERS) | FUTEX_OWNER_DIED; diff --git a/services/libs/jinux-std/src/process/process/builder.rs b/services/libs/jinux-std/src/process/process/builder.rs new file mode 100644 index 000000000..3d48cb2dd --- /dev/null +++ b/services/libs/jinux-std/src/process/process/builder.rs @@ -0,0 +1,212 @@ +use crate::fs::file_table::FileTable; +use crate::fs::fs_resolver::FsResolver; +use crate::fs::utils::FileCreationMask; +use crate::process::posix_thread::PosixThreadBuilder; +use crate::process::process_group::ProcessGroup; +use crate::process::process_table; +use crate::process::process_vm::ProcessVm; +use crate::process::rlimit::ResourceLimits; +use crate::process::{posix_thread::PosixThreadExt, signal::sig_disposition::SigDispositions}; +use crate::thread::Thread; + +use super::{Pid, Process}; +use crate::prelude::*; + +pub struct ProcessBuilder<'a> { + // Essential parts + pid: Pid, + executable_path: &'a str, + parent: Weak, + + // Optional parts + main_thread_builder: Option, + argv: Option>, + envp: Option>, + process_vm: Option, + process_group: Option>, + file_table: Option>>, + fs: Option>>, + umask: Option>>, + resource_limits: Option, + sig_dispositions: Option>>, +} + +impl<'a> ProcessBuilder<'a> { + pub fn new(pid: Pid, executable_path: &'a str, parent: Weak) -> Self { + ProcessBuilder { + pid, + executable_path, + parent, + main_thread_builder: None, + argv: None, + envp: None, + process_vm: None, + process_group: None, + file_table: None, + fs: None, + umask: None, + resource_limits: None, + sig_dispositions: None, + } + } + + pub fn main_thread_builder(&mut self, builder: PosixThreadBuilder) -> &mut Self { + self.main_thread_builder = Some(builder); + self + } + + pub fn process_vm(&mut self, process_vm: ProcessVm) -> &mut Self { + self.process_vm = Some(process_vm); + self + } + + pub fn process_group(&mut self, process_group: Arc) -> &mut Self { + self.process_group = Some(process_group); + self + } + + pub fn file_table(&mut self, file_table: Arc>) -> &mut Self { + self.file_table = Some(file_table); + self + } + + pub fn fs(&mut self, fs: Arc>) -> &mut Self { + self.fs = Some(fs); + self + } + + pub fn umask(&mut self, umask: Arc>) -> &mut Self { + self.umask = Some(umask); + self + } + + pub fn resource_limits(&mut self, resource_limits: ResourceLimits) -> &mut Self { + self.resource_limits = Some(resource_limits); + self + } + + pub fn sig_dispositions(&mut self, sig_dispositions: Arc>) -> &mut Self { + self.sig_dispositions = Some(sig_dispositions); + self + } + + pub fn argv(&mut self, argv: Vec) -> &mut Self { + self.argv = Some(argv); + self + } + + pub fn envp(&mut self, envp: Vec) -> &mut Self { + self.envp = Some(envp); + self + } + + fn check_build(&self) -> Result<()> { + if self.main_thread_builder.is_some() { + debug_assert!(self.parent.upgrade().is_some()); + debug_assert!(self.argv.is_none()); + debug_assert!(self.envp.is_none()); + } + + if self.main_thread_builder.is_none() { + debug_assert!(self.parent.upgrade().is_none()); + debug_assert!(self.argv.is_some()); + debug_assert!(self.envp.is_some()); + } + + Ok(()) + } + + pub fn build(self) -> Result> { + self.check_build()?; + let Self { + pid, + executable_path, + parent, + main_thread_builder, + argv, + envp, + process_vm, + process_group, + file_table, + fs, + umask, + resource_limits, + sig_dispositions, + } = self; + + let process_vm = process_vm + .or_else(|| Some(ProcessVm::alloc().unwrap())) + .unwrap(); + + let process_group_ref = process_group + .as_ref() + .map_or_else(Weak::new, Arc::downgrade); + + let file_table = file_table + .or_else(|| Some(Arc::new(Mutex::new(FileTable::new_with_stdio())))) + .unwrap(); + + let fs = fs + .or_else(|| Some(Arc::new(RwLock::new(FsResolver::new())))) + .unwrap(); + + let umask = umask + .or_else(|| Some(Arc::new(RwLock::new(FileCreationMask::default())))) + .unwrap(); + + let resource_limits = resource_limits + .or_else(|| Some(ResourceLimits::default())) + .unwrap(); + + let sig_dispositions = sig_dispositions + .or_else(|| Some(Arc::new(Mutex::new(SigDispositions::new())))) + .unwrap(); + + let process = { + let threads = Vec::new(); + Arc::new(Process::new( + pid, + parent, + threads, + executable_path.to_string(), + process_vm, + process_group_ref, + file_table, + fs, + umask, + sig_dispositions, + resource_limits, + )) + }; + + let thread = if let Some(thread_builder) = main_thread_builder { + let builder = thread_builder.process(Arc::downgrade(&process)); + builder.build() + } else { + Thread::new_posix_thread_from_executable( + pid, + process.vm(), + &process.fs().read(), + executable_path, + Arc::downgrade(&process), + argv.unwrap(), + envp.unwrap(), + )? + }; + + process.threads().lock().push(thread); + + if let Some(process_group) = process_group { + process_group.add_process(process.clone()); + } else { + let new_process_group = Arc::new(ProcessGroup::new(process.clone())); + let pgid = new_process_group.pgid(); + process.set_process_group(Arc::downgrade(&new_process_group)); + process_table::add_process_group(new_process_group); + } + + process.set_runnable(); + + Ok(process) + } +} diff --git a/services/libs/jinux-std/src/process/process/mod.rs b/services/libs/jinux-std/src/process/process/mod.rs new file mode 100644 index 000000000..bcc5e6007 --- /dev/null +++ b/services/libs/jinux-std/src/process/process/mod.rs @@ -0,0 +1,299 @@ +mod builder; + +use super::posix_thread::PosixThreadExt; +use super::process_group::ProcessGroup; +use super::process_vm::user_heap::UserHeap; +use super::process_vm::ProcessVm; +use super::rlimit::ResourceLimits; +use super::signal::sig_disposition::SigDispositions; +use super::signal::sig_mask::SigMask; +use super::signal::sig_queues::SigQueues; +use super::signal::signals::Signal; +use super::status::ProcessStatus; +use super::{process_table, TermStatus}; +use crate::device::tty::get_n_tty; +use crate::fs::file_table::FileTable; +use crate::fs::fs_resolver::FsResolver; +use crate::fs::utils::FileCreationMask; +use crate::prelude::*; +use crate::thread::{allocate_tid, Thread}; +use crate::vm::vmar::Vmar; +use jinux_frame::sync::WaitQueue; +use jinux_rights::Full; + +pub use builder::ProcessBuilder; + +pub type Pid = u32; +pub type Pgid = u32; +pub type ExitCode = i32; + +/// Process stands for a set of threads that shares the same userspace. +pub struct Process { + // Immutable Part + pid: Pid, + + process_vm: ProcessVm, + /// wait for child status changed + waiting_children: WaitQueue, + + // Mutable Part + /// The executable path. + executable_path: RwLock, + /// The threads + threads: Mutex>>, + /// Process status + status: Mutex, + /// Parent process + parent: Mutex>, + /// Children processes + children: Mutex>>, + /// Process group + process_group: Mutex>, + /// File table + file_table: Arc>, + /// FsResolver + fs: Arc>, + /// umask + umask: Arc>, + /// resource limits + resource_limits: Mutex, + + // Signal + /// sig dispositions + sig_dispositions: Arc>, + /// Process-level signal queues + sig_queues: Mutex, +} + +impl Process { + #[allow(clippy::too_many_arguments)] + fn new( + pid: Pid, + parent: Weak, + threads: Vec>, + executable_path: String, + process_vm: ProcessVm, + process_group: Weak, + file_table: Arc>, + fs: Arc>, + umask: Arc>, + sig_dispositions: Arc>, + resource_limits: ResourceLimits, + ) -> Self { + Self { + pid, + threads: Mutex::new(threads), + executable_path: RwLock::new(executable_path), + process_vm, + waiting_children: WaitQueue::new(), + status: Mutex::new(ProcessStatus::Uninit), + parent: Mutex::new(parent), + children: Mutex::new(BTreeMap::new()), + process_group: Mutex::new(process_group), + file_table, + fs, + umask, + sig_dispositions, + sig_queues: Mutex::new(SigQueues::new()), + resource_limits: Mutex::new(resource_limits), + } + } + + /// init a user process and run the process + pub fn spawn_user_process( + executable_path: &str, + argv: Vec, + envp: Vec, + ) -> Result> { + // spawn user process should give an absolute path + debug_assert!(executable_path.starts_with('/')); + let process = Process::create_user_process(executable_path, argv, envp)?; + // FIXME: How to determine the fg process group? + let process_group = Weak::clone(&process.process_group.lock()); + // FIXME: tty should be a parameter? + let tty = get_n_tty(); + tty.set_fg(process_group); + process.run(); + Ok(process) + } + + fn create_user_process( + executable_path: &str, + argv: Vec, + envp: Vec, + ) -> Result> { + let process_builder = { + let pid = allocate_tid(); + let parent = Weak::new(); + let mut builder = ProcessBuilder::new(pid, executable_path, parent); + builder.argv(argv).envp(envp); + builder + }; + + let process = process_builder.build()?; + process_table::add_process(process.clone()); + Ok(process) + } + + /// start to run current process + pub fn run(&self) { + let threads = self.threads.lock(); + // when run the process, the process should has only one thread + debug_assert!(threads.len() == 1); + debug_assert!(self.is_runnable()); + let thread = threads[0].clone(); + // should not hold the lock when run thread + drop(threads); + thread.run(); + } + + // *********** Basic structures *********** + + pub fn pid(&self) -> Pid { + self.pid + } + + pub fn threads(&self) -> &Mutex>> { + &self.threads + } + + pub fn executable_path(&self) -> String { + self.executable_path.read().clone() + } + + pub fn set_executable_path(&self, executable_path: String) { + *self.executable_path.write() = executable_path; + } + + pub fn resource_limits(&self) -> &Mutex { + &self.resource_limits + } + + // *********** Parent and child *********** + + pub fn add_child(&self, child: Arc) { + let child_pid = child.pid(); + self.children.lock().insert(child_pid, child); + } + + pub fn set_parent(&self, parent: Weak) { + *self.parent.lock() = parent; + } + + pub fn parent(&self) -> Option> { + self.parent.lock().upgrade() + } + + pub fn children(&self) -> &Mutex>> { + &self.children + } + + pub fn waiting_children(&self) -> &WaitQueue { + &self.waiting_children + } + + // *********** Process group *********** + + pub fn pgid(&self) -> Pgid { + if let Some(process_group) = self.process_group.lock().upgrade() { + process_group.pgid() + } else { + 0 + } + } + + /// Set process group for current process. If old process group exists, + /// remove current process from old process group. + pub fn set_process_group(&self, process_group: Weak) { + if let Some(old_process_group) = self.process_group() { + old_process_group.remove_process(self.pid()); + } + *self.process_group.lock() = process_group; + } + + pub fn process_group(&self) -> Option> { + self.process_group.lock().upgrade() + } + + // ************** Virtual Memory ************* + + pub fn vm(&self) -> &ProcessVm { + &self.process_vm + } + + pub fn root_vmar(&self) -> &Vmar { + self.process_vm.root_vmar() + } + + pub fn user_heap(&self) -> &UserHeap { + self.process_vm.user_heap() + } + + // ************** File system **************** + + pub fn file_table(&self) -> &Arc> { + &self.file_table + } + + pub fn fs(&self) -> &Arc> { + &self.fs + } + + pub fn umask(&self) -> &Arc> { + &self.umask + } + + // ****************** Signal ****************** + + pub fn sig_dispositions(&self) -> &Arc> { + &self.sig_dispositions + } + + pub fn has_pending_signal(&self) -> bool { + self.sig_queues.lock().is_empty() + } + + pub fn enqueue_signal(&self, signal: Box) { + if !self.is_zombie() { + self.sig_queues.lock().enqueue(signal); + } + } + + pub fn dequeue_signal(&self, mask: &SigMask) -> Option> { + self.sig_queues.lock().dequeue(mask) + } + + // ******************* Status ******************** + + fn set_runnable(&self) { + self.status.lock().set_runnable(); + } + + fn is_runnable(&self) -> bool { + self.status.lock().is_runnable() + } + + pub fn is_zombie(&self) -> bool { + self.status.lock().is_zombie() + } + + pub fn set_zombie(&self, term_status: TermStatus) { + *self.status.lock() = ProcessStatus::Zombie(term_status); + } + + pub fn exit_code(&self) -> Option { + match &*self.status.lock() { + ProcessStatus::Runnable | ProcessStatus::Uninit => None, + ProcessStatus::Zombie(term_status) => Some(term_status.as_u32()), + } + } +} + +pub fn current() -> Arc { + let current_thread = Thread::current(); + if let Some(posix_thread) = current_thread.as_posix_thread() { + posix_thread.process() + } else { + panic!("[Internal error]The current thread does not belong to a process"); + } +} diff --git a/services/libs/jinux-std/src/process/process_filter.rs b/services/libs/jinux-std/src/process/process_filter.rs index 968f50d16..a3f4c494b 100644 --- a/services/libs/jinux-std/src/process/process_filter.rs +++ b/services/libs/jinux-std/src/process/process_filter.rs @@ -1,4 +1,5 @@ -use super::{Pgid, Pid, Process}; +use super::{Pgid, Pid}; +use crate::prelude::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ProcessFilter { @@ -32,7 +33,7 @@ impl ProcessFilter { ProcessFilter::Any } else if wait_pid == 0 { // wait for any child process with same process group ID - let pgid = Process::current().pgid(); + let pgid = current!().pgid(); ProcessFilter::WithPgid(pgid) } else { // pid > 0. wait for the child whose process ID is equal to the value of pid. diff --git a/services/libs/jinux-std/src/process/process_vm/mmap_options.rs b/services/libs/jinux-std/src/process/process_vm/mmap_options.rs deleted file mode 100644 index 50295c57e..000000000 --- a/services/libs/jinux-std/src/process/process_vm/mmap_options.rs +++ /dev/null @@ -1,69 +0,0 @@ -//! Definition of MMap flags, conforming to the linux mmap interface: -//! https://man7.org/linux/man-pages/man2/mmap.2.html -//! -//! The first 4 bits of the flag value represents the type of memory map, -//! while other bits are used as memory map flags. -//! - -use crate::prelude::*; - -// The map type mask -const MAP_TYPE: u32 = 0xf; - -#[derive(Copy, Clone, PartialEq, Debug, TryFromInt)] -#[repr(u8)] -pub enum MMapType { - File = 0x0, // Invalid - Shared = 0x1, - Private = 0x2, - SharedValidate = 0x3, -} - -bitflags! { - pub struct MMapFlags : u32 { - const MAP_FIXED = 0x10; - const MAP_ANONYMOUS = 0x20; - const MAP_GROWSDOWN = 0x100; - const MAP_DENYWRITE = 0x800; - const MAP_EXECUTABLE = 0x1000; - const MAP_LOCKED = 0x2000; - const MAP_NORESERVE = 0x4000; - const MAP_POPULATE = 0x8000; - const MAP_NONBLOCK = 0x10000; - const MAP_STACK = 0x20000; - const MAP_HUGETLB = 0x40000; - const MAP_SYNC = 0x80000; - const MAP_FIXED_NOREPLACE = 0x100000; - } -} - -#[derive(Debug)] -pub struct MMapOptions { - typ: MMapType, - flags: MMapFlags, -} - -impl TryFrom for MMapOptions { - type Error = Error; - - fn try_from(value: u32) -> Result { - let typ_raw = (value & MAP_TYPE) as u8; - let typ = MMapType::try_from(typ_raw)?; - - let flags_raw = value & !MAP_TYPE; - let Some(flags) = MMapFlags::from_bits(flags_raw) else { - return Err(Error::with_message(Errno::EINVAL, "unknown mmap flags")); - }; - Ok(MMapOptions { typ, flags }) - } -} - -impl MMapOptions { - pub fn typ(&self) -> MMapType { - self.typ - } - - pub fn flags(&self) -> MMapFlags { - self.flags - } -} diff --git a/services/libs/jinux-std/src/process/process_vm/mod.rs b/services/libs/jinux-std/src/process/process_vm/mod.rs index e530a9159..dd07d1fa2 100644 --- a/services/libs/jinux-std/src/process/process_vm/mod.rs +++ b/services/libs/jinux-std/src/process/process_vm/mod.rs @@ -4,7 +4,6 @@ //! So we define a UserVm struct to store such infomation. //! Briefly, it contains the exact usage of each segment of virtual spaces. -pub mod mmap_options; pub mod user_heap; use crate::prelude::*; @@ -46,6 +45,15 @@ pub struct ProcessVm { root_vmar: Vmar, } +impl Clone for ProcessVm { + fn clone(&self) -> Self { + Self { + root_vmar: self.root_vmar.dup().unwrap(), + user_heap: self.user_heap.clone(), + } + } +} + impl ProcessVm { pub fn alloc() -> Result { let root_vmar = Vmar::::new_root()?; diff --git a/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs b/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs index 12b2f5984..750fbcbf6 100644 --- a/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs +++ b/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs @@ -5,7 +5,7 @@ use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD}; use crate::fs::utils::Dentry; use crate::process::process_vm::ProcessVm; use crate::process::program_loader::elf::init_stack::{init_aux_vec, InitStack}; -use crate::process::TermStatus; +use crate::process::{do_exit_group, TermStatus}; use crate::vm::perms::VmPerms; use crate::vm::vmo::{VmoOptions, VmoRightsOp}; use crate::{ @@ -50,9 +50,8 @@ pub fn load_elf_to_vm( // FIXME: if `current` macro is used when creating the init process, // the macro will panic. This corner case should be handled later. - let current = current!(); // FIXME: how to set the correct exit status? - current.exit_group(TermStatus::Exited(1)); + do_exit_group(TermStatus::Exited(1)); Task::current().exit(); } } diff --git a/services/libs/jinux-std/src/process/signal/mod.rs b/services/libs/jinux-std/src/process/signal/mod.rs index 4564536a0..ad6dbbb6b 100644 --- a/services/libs/jinux-std/src/process/signal/mod.rs +++ b/services/libs/jinux-std/src/process/signal/mod.rs @@ -16,10 +16,10 @@ use self::c_types::siginfo_t; use self::sig_mask::SigMask; use self::sig_num::SigNum; use crate::current_thread; -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; +use crate::process::posix_thread::PosixThreadExt; use crate::process::signal::c_types::ucontext_t; use crate::process::signal::sig_action::SigActionFlags; -use crate::process::TermStatus; +use crate::process::{do_exit_group, TermStatus}; use crate::util::{write_bytes_to_user, write_val_to_user}; use crate::{ prelude::*, @@ -33,13 +33,11 @@ pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> { let posix_thread = current_thread.as_posix_thread().unwrap(); let pid = current.pid(); let sig_mask = *posix_thread.sig_mask().lock(); - let mut thread_sig_queues = posix_thread.sig_queues().lock(); - let mut proc_sig_queues = current.sig_queues().lock(); // We first deal with signal in current thread, then signal in current process. - let signal = if let Some(signal) = thread_sig_queues.dequeue(&sig_mask) { + let signal = if let Some(signal) = posix_thread.dequeue_signal(&sig_mask) { Some(signal) } else { - proc_sig_queues.dequeue(&sig_mask) + current.dequeue_signal(&sig_mask) }; if let Some(signal) = signal { let sig_num = signal.num(); @@ -71,10 +69,10 @@ pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> { SigDefaultAction::Core | SigDefaultAction::Term => { warn!( "{:?}: terminating on signal {}", - &*current.executable_path().read(), + current.executable_path(), sig_num.sig_name() ); - current.exit_group(TermStatus::Killed(sig_num)); + do_exit_group(TermStatus::Killed(sig_num)); // We should exit current here, since we cannot restore a valid status from trap now. Task::current().exit(); } diff --git a/services/libs/jinux-std/src/process/signal/sig_queues.rs b/services/libs/jinux-std/src/process/signal/sig_queues.rs index 7918daa8f..4850930af 100644 --- a/services/libs/jinux-std/src/process/signal/sig_queues.rs +++ b/services/libs/jinux-std/src/process/signal/sig_queues.rs @@ -24,7 +24,7 @@ impl SigQueues { } } - pub fn empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.count == 0 } @@ -63,7 +63,7 @@ impl SigQueues { pub fn dequeue(&mut self, blocked: &SigMask) -> Option> { // Fast path for the common case of no pending signals - if self.empty() { + if self.is_empty() { return None; } diff --git a/services/libs/jinux-std/src/process/status.rs b/services/libs/jinux-std/src/process/status.rs index c84e25913..6b172d061 100644 --- a/services/libs/jinux-std/src/process/status.rs +++ b/services/libs/jinux-std/src/process/status.rs @@ -4,6 +4,8 @@ use super::TermStatus; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ProcessStatus { + // Not ready to run + Uninit, /// Can be scheduled to run Runnable, /// Exit while not reaped by parent @@ -18,4 +20,12 @@ impl ProcessStatus { pub fn is_zombie(&self) -> bool { matches!(self, ProcessStatus::Zombie(_)) } + + pub fn set_runnable(&mut self) { + *self = ProcessStatus::Runnable; + } + + pub fn is_runnable(&self) -> bool { + *self == ProcessStatus::Runnable + } } diff --git a/services/libs/jinux-std/src/process/wait.rs b/services/libs/jinux-std/src/process/wait.rs index 519cb1b78..2634e53dc 100644 --- a/services/libs/jinux-std/src/process/wait.rs +++ b/services/libs/jinux-std/src/process/wait.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use crate::{prelude::*, process::process_table, thread::thread_table}; -use super::{process_filter::ProcessFilter, ExitCode, Pid}; +use super::{process_filter::ProcessFilter, ExitCode, Pid, Process}; // The definition of WaitOptions is from Occlum bitflags! { @@ -45,9 +45,7 @@ pub fn wait_child_exit( } // return immediately if we find a zombie child - let zombie_child = unwaited_children - .iter() - .find(|child| child.status().lock().is_zombie()); + let zombie_child = unwaited_children.iter().find(|child| child.is_zombie()); if let Some(zombie_child) = zombie_child { let zombie_pid = zombie_child.pid(); @@ -56,7 +54,7 @@ pub fn wait_child_exit( // does not reap child, directly return return Some(Ok((zombie_pid, exit_code))); } else { - let exit_code = current.reap_zombie_child(zombie_pid); + let exit_code = reap_zombie_child(¤t, zombie_pid); return Some(Ok((zombie_pid, exit_code))); } } @@ -71,3 +69,18 @@ pub fn wait_child_exit( Ok((pid, exit_code as _)) } + +/// Free zombie child with pid, returns the exit code of child process. +fn reap_zombie_child(process: &Process, pid: Pid) -> u32 { + let child_process = process.children().lock().remove(&pid).unwrap(); + assert!(child_process.is_zombie()); + child_process.root_vmar().destroy_all().unwrap(); + for thread in &*child_process.threads().lock() { + thread_table::remove_thread(thread.tid()); + } + process_table::remove_process(child_process.pid()); + if let Some(process_group) = child_process.process_group() { + process_group.remove_process(child_process.pid()); + } + child_process.exit_code().unwrap() +} diff --git a/services/libs/jinux-std/src/syscall/clone.rs b/services/libs/jinux-std/src/syscall/clone.rs index db944fafc..655715b64 100644 --- a/services/libs/jinux-std/src/syscall/clone.rs +++ b/services/libs/jinux-std/src/syscall/clone.rs @@ -1,7 +1,7 @@ use jinux_frame::cpu::UserContext; use crate::log_syscall_entry; -use crate::process::clone::{clone_child, CloneArgs, CloneFlags}; +use crate::process::{clone_child, CloneArgs, CloneFlags}; use crate::{prelude::*, syscall::SYS_CLONE}; use super::SyscallReturn; diff --git a/services/libs/jinux-std/src/syscall/execve.rs b/services/libs/jinux-std/src/syscall/execve.rs index dda220fc2..d67c3e865 100644 --- a/services/libs/jinux-std/src/syscall/execve.rs +++ b/services/libs/jinux-std/src/syscall/execve.rs @@ -6,9 +6,8 @@ use crate::fs::fs_resolver::{FsPath, AT_FDCWD}; use crate::fs::utils::{Dentry, InodeType}; use crate::log_syscall_entry; use crate::prelude::*; -use crate::process::posix_thread::name::ThreadName; -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; -use crate::process::program_loader::{check_executable_file, load_program_to_vm}; +use crate::process::posix_thread::{PosixThreadExt, ThreadName}; +use crate::process::{check_executable_file, load_program_to_vm}; use crate::syscall::{SYS_EXECVE, SYS_EXECVEAT}; use crate::util::{read_cstring_from_user, read_val_from_user}; @@ -100,12 +99,12 @@ fn do_execve( debug!("load program to root vmar"); let (new_executable_path, elf_load_info) = { let fs_resolver = &*current.fs().read(); - let process_vm = current.process_vm(); + let process_vm = current.vm(); load_program_to_vm(process_vm, elf_file, argv, envp, fs_resolver, 1)? }; debug!("load elf in execve succeeds"); // set executable path - *current.executable_path().write() = new_executable_path; + current.set_executable_path(new_executable_path); // set signal disposition to default current.sig_dispositions().lock().inherit(); // set cpu context to default diff --git a/services/libs/jinux-std/src/syscall/exit.rs b/services/libs/jinux-std/src/syscall/exit.rs index 2de623725..b1eb00a16 100644 --- a/services/libs/jinux-std/src/syscall/exit.rs +++ b/services/libs/jinux-std/src/syscall/exit.rs @@ -1,4 +1,4 @@ -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; +use crate::process::posix_thread::PosixThreadExt; use crate::process::TermStatus; use crate::{log_syscall_entry, prelude::*}; diff --git a/services/libs/jinux-std/src/syscall/exit_group.rs b/services/libs/jinux-std/src/syscall/exit_group.rs index f67ff12bb..aca5c0939 100644 --- a/services/libs/jinux-std/src/syscall/exit_group.rs +++ b/services/libs/jinux-std/src/syscall/exit_group.rs @@ -1,4 +1,4 @@ -use crate::process::TermStatus; +use crate::process::{do_exit_group, TermStatus}; use crate::{log_syscall_entry, prelude::*}; use crate::syscall::{SyscallReturn, SYS_EXIT_GROUP}; @@ -8,6 +8,6 @@ pub fn sys_exit_group(exit_code: u64) -> Result { log_syscall_entry!(SYS_EXIT_GROUP); // Exit all thread in current process let term_status = TermStatus::Exited(exit_code as _); - current!().exit_group(term_status); + do_exit_group(term_status); Ok(SyscallReturn::Return(0)) } diff --git a/services/libs/jinux-std/src/syscall/fork.rs b/services/libs/jinux-std/src/syscall/fork.rs index 54635a4c1..11f2a365b 100644 --- a/services/libs/jinux-std/src/syscall/fork.rs +++ b/services/libs/jinux-std/src/syscall/fork.rs @@ -1,7 +1,7 @@ use crate::{ log_syscall_entry, prelude::*, - process::clone::{clone_child, CloneArgs}, + process::{clone_child, CloneArgs}, }; use jinux_frame::cpu::UserContext; diff --git a/services/libs/jinux-std/src/syscall/kill.rs b/services/libs/jinux-std/src/syscall/kill.rs index a61b191fc..d9a4070e8 100644 --- a/services/libs/jinux-std/src/syscall/kill.rs +++ b/services/libs/jinux-std/src/syscall/kill.rs @@ -3,7 +3,7 @@ use crate::{log_syscall_entry, prelude::*}; use crate::process::process_table; use crate::process::signal::signals::user::{UserSignal, UserSignalKind}; use crate::{ - process::{process_filter::ProcessFilter, signal::sig_num::SigNum}, + process::{signal::sig_num::SigNum, ProcessFilter}, syscall::SYS_KILL, }; diff --git a/services/libs/jinux-std/src/syscall/mmap.rs b/services/libs/jinux-std/src/syscall/mmap.rs index dbaef70a3..ace8d0fd4 100644 --- a/services/libs/jinux-std/src/syscall/mmap.rs +++ b/services/libs/jinux-std/src/syscall/mmap.rs @@ -1,7 +1,6 @@ //! This mod defines mmap flags and the handler to syscall mmap use crate::fs::file_table::FileDescripter; -use crate::process::process_vm::mmap_options::{MMapFlags, MMapOptions, MMapType}; use crate::vm::perms::VmPerms; use crate::vm::vmo::{VmoChildOptions, VmoOptions, VmoRightsOp}; use crate::{log_syscall_entry, prelude::*}; @@ -131,3 +130,70 @@ fn mmap_filebacked_vmo( trace!("map range = 0x{:x} - 0x{:x}", map_addr, map_addr + len); Ok(map_addr) } + +// Definition of MMap flags, conforming to the linux mmap interface: +// https://man7.org/linux/man-pages/man2/mmap.2.html +// +// The first 4 bits of the flag value represents the type of memory map, +// while other bits are used as memory map flags. + +// The map type mask +const MAP_TYPE: u32 = 0xf; + +#[derive(Copy, Clone, PartialEq, Debug, TryFromInt)] +#[repr(u8)] +pub enum MMapType { + File = 0x0, // Invalid + Shared = 0x1, + Private = 0x2, + SharedValidate = 0x3, +} + +bitflags! { + pub struct MMapFlags : u32 { + const MAP_FIXED = 0x10; + const MAP_ANONYMOUS = 0x20; + const MAP_GROWSDOWN = 0x100; + const MAP_DENYWRITE = 0x800; + const MAP_EXECUTABLE = 0x1000; + const MAP_LOCKED = 0x2000; + const MAP_NORESERVE = 0x4000; + const MAP_POPULATE = 0x8000; + const MAP_NONBLOCK = 0x10000; + const MAP_STACK = 0x20000; + const MAP_HUGETLB = 0x40000; + const MAP_SYNC = 0x80000; + const MAP_FIXED_NOREPLACE = 0x100000; + } +} + +#[derive(Debug)] +pub struct MMapOptions { + typ: MMapType, + flags: MMapFlags, +} + +impl TryFrom for MMapOptions { + type Error = Error; + + fn try_from(value: u32) -> Result { + let typ_raw = (value & MAP_TYPE) as u8; + let typ = MMapType::try_from(typ_raw)?; + + let flags_raw = value & !MAP_TYPE; + let Some(flags) = MMapFlags::from_bits(flags_raw) else { + return Err(Error::with_message(Errno::EINVAL, "unknown mmap flags")); + }; + Ok(MMapOptions { typ, flags }) + } +} + +impl MMapOptions { + pub fn typ(&self) -> MMapType { + self.typ + } + + pub fn flags(&self) -> MMapFlags { + self.flags + } +} diff --git a/services/libs/jinux-std/src/syscall/pause.rs b/services/libs/jinux-std/src/syscall/pause.rs index ab5ce360f..01c014352 100644 --- a/services/libs/jinux-std/src/syscall/pause.rs +++ b/services/libs/jinux-std/src/syscall/pause.rs @@ -1,4 +1,4 @@ -use crate::{prelude::*, process::posix_thread::posix_thread_ext::PosixThreadExt, thread::Thread}; +use crate::{prelude::*, process::posix_thread::PosixThreadExt, thread::Thread}; use super::SyscallReturn; @@ -8,7 +8,7 @@ pub fn sys_pause() -> Result { // check sig_queue of current thread and process, // if there's any pending signal, break loop let posix_thread = current_thread.as_posix_thread().unwrap(); - if !posix_thread.sig_queues().lock().empty() || !current!().sig_queues().lock().empty() { + if posix_thread.has_pending_signal() || current!().has_pending_signal() { break; } // there's no pending signal, yield execution diff --git a/services/libs/jinux-std/src/syscall/prctl.rs b/services/libs/jinux-std/src/syscall/prctl.rs index 9b3c0761a..5ab582f6e 100644 --- a/services/libs/jinux-std/src/syscall/prctl.rs +++ b/services/libs/jinux-std/src/syscall/prctl.rs @@ -1,7 +1,7 @@ use crate::log_syscall_entry; use crate::prelude::*; -use crate::process::posix_thread::name::MAX_THREAD_NAME_LEN; -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; +use crate::process::posix_thread::PosixThreadExt; +use crate::process::posix_thread::MAX_THREAD_NAME_LEN; use crate::util::read_cstring_from_user; use crate::util::write_bytes_to_user; diff --git a/services/libs/jinux-std/src/syscall/prlimit64.rs b/services/libs/jinux-std/src/syscall/prlimit64.rs index 7e1266fe8..6ec5da219 100644 --- a/services/libs/jinux-std/src/syscall/prlimit64.rs +++ b/services/libs/jinux-std/src/syscall/prlimit64.rs @@ -1,4 +1,4 @@ -use crate::process::rlimit::ResourceType; +use crate::process::ResourceType; use crate::util::{read_val_from_user, write_val_to_user}; use crate::{log_syscall_entry, prelude::*, process::Pid}; diff --git a/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs b/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs index bd7acb08f..b49689d51 100644 --- a/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs +++ b/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs @@ -1,6 +1,6 @@ use jinux_frame::vm::VmIo; -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; +use crate::process::posix_thread::PosixThreadExt; use crate::process::signal::constants::{SIGKILL, SIGSTOP}; use crate::{ log_syscall_entry, diff --git a/services/libs/jinux-std/src/syscall/rt_sigreturn.rs b/services/libs/jinux-std/src/syscall/rt_sigreturn.rs index a42eb4ff6..8774ffac9 100644 --- a/services/libs/jinux-std/src/syscall/rt_sigreturn.rs +++ b/services/libs/jinux-std/src/syscall/rt_sigreturn.rs @@ -1,7 +1,7 @@ use crate::{ log_syscall_entry, prelude::*, - process::{posix_thread::posix_thread_ext::PosixThreadExt, signal::c_types::ucontext_t}, + process::{posix_thread::PosixThreadExt, signal::c_types::ucontext_t}, util::read_val_from_user, }; use jinux_frame::cpu::UserContext; diff --git a/services/libs/jinux-std/src/syscall/set_robust_list.rs b/services/libs/jinux-std/src/syscall/set_robust_list.rs index 6b303db0b..277fa78a5 100644 --- a/services/libs/jinux-std/src/syscall/set_robust_list.rs +++ b/services/libs/jinux-std/src/syscall/set_robust_list.rs @@ -2,7 +2,7 @@ use super::{SyscallReturn, SYS_SET_ROBUST_LIST}; use crate::{ log_syscall_entry, prelude::*, - process::posix_thread::{posix_thread_ext::PosixThreadExt, robust_list::RobustListHead}, + process::posix_thread::{PosixThreadExt, RobustListHead}, util::read_val_from_user, }; diff --git a/services/libs/jinux-std/src/syscall/set_tid_address.rs b/services/libs/jinux-std/src/syscall/set_tid_address.rs index 21500d9ca..b98e07461 100644 --- a/services/libs/jinux-std/src/syscall/set_tid_address.rs +++ b/services/libs/jinux-std/src/syscall/set_tid_address.rs @@ -1,8 +1,7 @@ -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; -use crate::{log_syscall_entry, prelude::*}; - use super::SyscallReturn; use super::SYS_SET_TID_ADDRESS; +use crate::process::posix_thread::PosixThreadExt; +use crate::{log_syscall_entry, prelude::*}; pub fn sys_set_tid_address(tidptr: Vaddr) -> Result { log_syscall_entry!(SYS_SET_TID_ADDRESS); diff --git a/services/libs/jinux-std/src/syscall/setpgid.rs b/services/libs/jinux-std/src/syscall/setpgid.rs index 60f2a2b93..86244b93d 100644 --- a/services/libs/jinux-std/src/syscall/setpgid.rs +++ b/services/libs/jinux-std/src/syscall/setpgid.rs @@ -1,11 +1,7 @@ use crate::{ log_syscall_entry, prelude::*, - process::{ - process_group::ProcessGroup, - process_table::{self, pid_to_process}, - Pgid, Pid, - }, + process::{process_table, Pgid, Pid, ProcessGroup}, }; use super::{SyscallReturn, SYS_SETPGID}; @@ -33,8 +29,8 @@ pub fn sys_setpgid(pid: Pid, pgid: Pgid) -> Result { return_errno_with_message!(Errno::EPERM, "process group must exist"); } - let process = - pid_to_process(pid).ok_or(Error::with_message(Errno::ESRCH, "process does not exist"))?; + let process = process_table::pid_to_process(pid) + .ok_or(Error::with_message(Errno::ESRCH, "process does not exist"))?; // if the process already belongs to the process group if process.pgid() == pgid { diff --git a/services/libs/jinux-std/src/syscall/tgkill.rs b/services/libs/jinux-std/src/syscall/tgkill.rs index cf68c0eec..c02236dd8 100644 --- a/services/libs/jinux-std/src/syscall/tgkill.rs +++ b/services/libs/jinux-std/src/syscall/tgkill.rs @@ -1,4 +1,4 @@ -use crate::process::posix_thread::posix_thread_ext::PosixThreadExt; +use crate::process::posix_thread::PosixThreadExt; use crate::thread::{thread_table, Tid}; use crate::{log_syscall_entry, prelude::*}; @@ -39,7 +39,6 @@ pub fn sys_tgkill(tgid: Pid, tid: Tid, sig_num: u8) -> Result { src_uid, )) }; - let mut sig_queue = posix_thread.sig_queues().lock(); - sig_queue.enqueue(signal); + posix_thread.enqueue_signal(signal); Ok(SyscallReturn::Return(0)) } diff --git a/services/libs/jinux-std/src/syscall/wait4.rs b/services/libs/jinux-std/src/syscall/wait4.rs index ebbfbe7db..6cfaba6c6 100644 --- a/services/libs/jinux-std/src/syscall/wait4.rs +++ b/services/libs/jinux-std/src/syscall/wait4.rs @@ -1,12 +1,12 @@ use crate::{ log_syscall_entry, - process::{process_filter::ProcessFilter, wait::wait_child_exit}, + process::{wait_child_exit, ProcessFilter}, syscall::SYS_WAIT4, util::write_val_to_user, }; use crate::prelude::*; -use crate::process::wait::WaitOptions; +use crate::process::WaitOptions; use super::SyscallReturn; diff --git a/services/libs/jinux-std/src/syscall/waitid.rs b/services/libs/jinux-std/src/syscall/waitid.rs index 63d154911..b3d612cc4 100644 --- a/services/libs/jinux-std/src/syscall/waitid.rs +++ b/services/libs/jinux-std/src/syscall/waitid.rs @@ -1,7 +1,7 @@ -use crate::process::{process_filter::ProcessFilter, wait::wait_child_exit}; +use crate::process::{wait_child_exit, ProcessFilter}; use crate::{log_syscall_entry, prelude::*}; -use crate::process::wait::WaitOptions; +use crate::process::WaitOptions; use super::SyscallReturn; use super::SYS_WAITID; diff --git a/services/libs/jinux-std/src/thread/exception.rs b/services/libs/jinux-std/src/thread/exception.rs index 9768d75f7..ff3f58347 100644 --- a/services/libs/jinux-std/src/thread/exception.rs +++ b/services/libs/jinux-std/src/thread/exception.rs @@ -57,7 +57,7 @@ fn handle_page_fault(trap_info: &TrapInformation) { fn generate_fault_signal(trap_info: &TrapInformation) { let current = current!(); let signal = Box::new(FaultSignal::new(trap_info)); - current.sig_queues().lock().enqueue(signal); + current.enqueue_signal(signal); } macro_rules! log_trap_common { diff --git a/services/libs/jinux-std/src/thread/mod.rs b/services/libs/jinux-std/src/thread/mod.rs index 34c5a692c..c83bae97a 100644 --- a/services/libs/jinux-std/src/thread/mod.rs +++ b/services/libs/jinux-std/src/thread/mod.rs @@ -2,7 +2,7 @@ use core::{ any::Any, - sync::atomic::{AtomicI32, Ordering}, + sync::atomic::{AtomicU32, Ordering}, }; use jinux_frame::task::Task; @@ -17,9 +17,9 @@ pub mod status; pub mod task; pub mod thread_table; -pub type Tid = i32; +pub type Tid = u32; -static TID_ALLOCATOR: AtomicI32 = AtomicI32::new(0); +static TID_ALLOCATOR: AtomicU32 = AtomicU32::new(0); /// A thread is a wrapper on top of task. pub struct Thread {