diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index c8f1e1bb7..42390338c 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -133,10 +133,7 @@ fn ap_init() -> ! { } fn init_thread() { - println!( - "[kernel] Spawn init thread, tid = {}", - current_thread!().tid() - ); + println!("[kernel] Spawn init thread"); // Work queue should be initialized before interrupt is enabled, // in case any irq handler uses work queue as bottom half thread::work_queue::init(); @@ -146,15 +143,8 @@ fn init_thread() { // driver::pci::virtio::block::block_device_test(); let thread = Thread::spawn_kernel_thread(ThreadOptions::new(|| { println!("[kernel] Hello world from kernel!"); - let current = current_thread!(); - let tid = current.tid(); - debug!("current tid = {}", tid); })); thread.join(); - info!( - "[aster-nix/lib.rs] spawn kernel thread, tid = {}", - thread.tid() - ); print_banner(); diff --git a/kernel/src/process/clone.rs b/kernel/src/process/clone.rs index 29a23f07f..c4aaf33b5 100644 --- a/kernel/src/process/clone.rs +++ b/kernel/src/process/clone.rs @@ -18,7 +18,8 @@ use crate::{ cpu::LinuxAbi, fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask}, prelude::*, - thread::{allocate_tid, thread_table, Thread, Tid}, + process::posix_thread::allocate_posix_tid, + thread::{thread_table, Thread, Tid}, }; bitflags! { @@ -180,7 +181,7 @@ fn clone_child_thread( // Inherit sigmask from current thread let sig_mask = posix_thread.sig_mask().load(Ordering::Relaxed).into(); - let child_tid = allocate_tid(); + let child_tid = allocate_posix_tid(); let child_thread = { let credentials = { let credentials = ctx.posix_thread.credentials(); @@ -262,7 +263,7 @@ fn clone_child_process( // inherit parent's nice value let child_nice = process.nice().load(Ordering::Relaxed); - let child_tid = allocate_tid(); + let child_tid = allocate_posix_tid(); let child = { let child_elf_path = process.executable_path(); @@ -295,7 +296,7 @@ fn clone_child_process( }; // Deals with clone flags - let child_thread = thread_table::get_thread(child_tid).unwrap(); + let child_thread = thread_table::get_posix_thread(child_tid).unwrap(); 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)?; diff --git a/kernel/src/process/exit.rs b/kernel/src/process/exit.rs index 8580e49fc..8d74f44cc 100644 --- a/kernel/src/process/exit.rs +++ b/kernel/src/process/exit.rs @@ -4,7 +4,7 @@ use super::{process_table, Pid, Process, TermStatus}; use crate::{ prelude::*, process::{ - posix_thread::do_exit, + posix_thread::{do_exit, PosixThreadExt}, signal::{constants::SIGCHLD, signals::kernel::KernelSignal}, }, }; @@ -20,7 +20,7 @@ pub fn do_exit_group(term_status: TermStatus) { // Exit all threads let threads = current.threads().lock().clone(); for thread in threads { - if let Err(e) = do_exit(thread, term_status) { + if let Err(e) = do_exit(&thread, thread.as_posix_thread().unwrap(), term_status) { debug!("Ignore error when call exit: {:?}", e); } } diff --git a/kernel/src/process/kill.rs b/kernel/src/process/kill.rs index 3ed3f5e4b..af734fbff 100644 --- a/kernel/src/process/kill.rs +++ b/kernel/src/process/kill.rs @@ -71,7 +71,7 @@ pub fn kill_group(pgid: Pgid, signal: Option, ctx: &Context) -> Resu /// If `signal` is `None`, this method will only check permission without sending /// any signal. pub fn tgkill(tid: Tid, tgid: Pid, signal: Option, ctx: &Context) -> Result<()> { - let thread = thread_table::get_thread(tid) + let thread = thread_table::get_posix_thread(tid) .ok_or_else(|| Error::with_message(Errno::ESRCH, "target thread does not exist"))?; if thread.status().is_exited() { diff --git a/kernel/src/process/posix_thread/builder.rs b/kernel/src/process/posix_thread/builder.rs index b7ae0d676..ae5c76200 100644 --- a/kernel/src/process/posix_thread/builder.rs +++ b/kernel/src/process/posix_thread/builder.rs @@ -95,6 +95,7 @@ impl PosixThreadBuilder { let posix_thread = PosixThread { process, + tid, name: Mutex::new(thread_name), set_child_tid: Mutex::new(set_child_tid), clear_child_tid: Mutex::new(clear_child_tid), @@ -110,9 +111,9 @@ impl PosixThreadBuilder { prof_timer_manager, }; - Thread::new(tid, task, posix_thread, status) + Thread::new(task, posix_thread, status) }); - thread_table::add_thread(thread.clone()); + thread_table::add_posix_thread(tid, thread.clone()); thread } } diff --git a/kernel/src/process/posix_thread/exit.rs b/kernel/src/process/posix_thread/exit.rs index 64a1d9d85..8828a8f41 100644 --- a/kernel/src/process/posix_thread/exit.rs +++ b/kernel/src/process/posix_thread/exit.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use super::{futex::futex_wake, robust_list::wake_robust_futex, PosixThread, PosixThreadExt}; +use super::{futex::futex_wake, robust_list::wake_robust_futex, PosixThread}; use crate::{ prelude::*, process::{do_exit_group, TermStatus}, @@ -12,15 +12,13 @@ use crate::{ /// # Panics /// /// If the thread is not a POSIX thread, this method will panic. -pub fn do_exit(thread: Arc, term_status: TermStatus) -> Result<()> { +pub fn do_exit(thread: &Thread, posix_thread: &PosixThread, term_status: TermStatus) -> Result<()> { if thread.status().is_exited() { return Ok(()); } thread.exit(); - let tid = thread.tid(); - - let posix_thread = thread.as_posix_thread().unwrap(); + let tid = posix_thread.tid; let mut clear_ctid = posix_thread.clear_child_tid().lock(); // If clear_ctid !=0 ,do a futex wake and write zero to the clear_ctid addr. @@ -38,7 +36,7 @@ pub fn do_exit(thread: Arc, term_status: TermStatus) -> Result<()> { if tid != posix_thread.process().pid() { // We don't remove main thread. // The main thread is removed when the process is reaped. - thread_table::remove_thread(tid); + thread_table::remove_posix_thread(tid); } if posix_thread.is_main_thread(tid) || posix_thread.is_last_thread() { diff --git a/kernel/src/process/posix_thread/mod.rs b/kernel/src/process/posix_thread/mod.rs index 49f70f55f..9c202792e 100644 --- a/kernel/src/process/posix_thread/mod.rs +++ b/kernel/src/process/posix_thread/mod.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] -use core::sync::atomic::Ordering; +use core::sync::atomic::{AtomicU32, Ordering}; use aster_rights::{ReadOp, WriteOp}; use ostd::sync::Waker; @@ -42,6 +42,8 @@ pub use robust_list::RobustListHead; pub struct PosixThread { // Immutable part process: Weak, + tid: Tid, + // Mutable part name: Mutex>, @@ -87,6 +89,11 @@ impl PosixThread { Weak::clone(&self.process) } + /// Returns the thread id + pub fn tid(&self) -> Tid { + self.tid + } + pub fn thread_name(&self) -> &Mutex> { &self.name } @@ -292,3 +299,10 @@ impl PosixThread { self.credentials.dup().restrict() } } + +static POSIX_TID_ALLOCATOR: AtomicU32 = AtomicU32::new(0); + +/// Allocates a new tid for the new posix thread +pub fn allocate_posix_tid() -> Tid { + POSIX_TID_ALLOCATOR.fetch_add(1, Ordering::SeqCst) +} diff --git a/kernel/src/process/posix_thread/posix_thread_ext.rs b/kernel/src/process/posix_thread/posix_thread_ext.rs index 012da1225..eb9a4316d 100644 --- a/kernel/src/process/posix_thread/posix_thread_ext.rs +++ b/kernel/src/process/posix_thread/posix_thread_ext.rs @@ -13,6 +13,14 @@ use crate::{ thread::{Thread, Tid}, }; pub trait PosixThreadExt { + /// Returns the thread id. + /// + /// # Panics + /// + /// If the thread is not posix thread, this method will panic. + fn tid(&self) -> Tid { + self.as_posix_thread().unwrap().tid() + } fn as_posix_thread(&self) -> Option<&PosixThread>; #[allow(clippy::too_many_arguments)] fn new_posix_thread_from_executable( diff --git a/kernel/src/process/process/mod.rs b/kernel/src/process/process/mod.rs index 68381cf6c..d9b368653 100644 --- a/kernel/src/process/process/mod.rs +++ b/kernel/src/process/process/mod.rs @@ -4,7 +4,7 @@ use core::sync::atomic::Ordering; use self::timer_manager::PosixTimerManager; use super::{ - posix_thread::PosixThreadExt, + posix_thread::{allocate_posix_tid, PosixThreadExt}, process_table, process_vm::{Heap, InitStackReader, ProcessVm}, rlimit::ResourceLimits, @@ -21,7 +21,7 @@ use crate::{ fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask}, prelude::*, sched::nice::Nice, - thread::{allocate_tid, Thread}, + thread::Thread, time::clocks::ProfClock, vm::vmar::Vmar, }; @@ -236,7 +236,7 @@ impl Process { envp: Vec, ) -> Result> { let process_builder = { - let pid = allocate_tid(); + let pid = allocate_posix_tid(); let parent = Weak::new(); let credentials = Credentials::new_root(); @@ -710,7 +710,7 @@ mod test { fn new_process(parent: Option>) -> Arc { crate::util::random::init(); crate::fs::rootfs::init_root_mount(); - let pid = allocate_tid(); + let pid = allocate_posix_tid(); let parent = if let Some(parent) = parent { Arc::downgrade(&parent) } else { diff --git a/kernel/src/process/wait.rs b/kernel/src/process/wait.rs index 668c340bc..d89724de6 100644 --- a/kernel/src/process/wait.rs +++ b/kernel/src/process/wait.rs @@ -2,12 +2,12 @@ #![allow(dead_code)] -use super::{ - process_filter::ProcessFilter, - signal::{constants::SIGCHLD, with_signal_blocked}, - ExitCode, Pid, Process, +use super::{process_filter::ProcessFilter, signal::constants::SIGCHLD, ExitCode, Pid, Process}; +use crate::{ + prelude::*, + process::{posix_thread::PosixThreadExt, process_table, signal::with_signal_blocked}, + thread::thread_table, }; -use crate::{prelude::*, process::process_table, thread::thread_table}; // The definition of WaitOptions is from Occlum bitflags! { @@ -86,7 +86,7 @@ fn reap_zombie_child(process: &Process, pid: Pid) -> ExitCode { let child_process = process.children().lock().remove(&pid).unwrap(); assert!(child_process.is_zombie()); for thread in &*child_process.threads().lock() { - thread_table::remove_thread(thread.tid()); + thread_table::remove_posix_thread(thread.tid()); } // Lock order: session table -> group table -> process table -> group of process diff --git a/kernel/src/syscall/clock_gettime.rs b/kernel/src/syscall/clock_gettime.rs index c4a6031df..d15247977 100644 --- a/kernel/src/syscall/clock_gettime.rs +++ b/kernel/src/syscall/clock_gettime.rs @@ -136,7 +136,7 @@ pub fn read_clock(clockid: clockid_t, ctx: &Context) -> Result { } } DynamicClockIdInfo::Tid(tid, clock_type) => { - let thread = thread_table::get_thread(tid) + let thread = thread_table::get_posix_thread(tid) .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid clock ID"))?; let posix_thread = thread.as_posix_thread().unwrap(); match clock_type { diff --git a/kernel/src/syscall/exit.rs b/kernel/src/syscall/exit.rs index 48917479f..d8c1805a1 100644 --- a/kernel/src/syscall/exit.rs +++ b/kernel/src/syscall/exit.rs @@ -6,12 +6,11 @@ use crate::{ syscall::SyscallReturn, }; -pub fn sys_exit(exit_code: i32, _ctx: &Context) -> Result { +pub fn sys_exit(exit_code: i32, ctx: &Context) -> Result { debug!("exid code = {}", exit_code); - let current_thread = current_thread!(); let term_status = TermStatus::Exited(exit_code as _); - do_exit(current_thread, term_status)?; + do_exit(ctx.thread, ctx.posix_thread, term_status)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/futex.rs b/kernel/src/syscall/futex.rs index b9fbcb888..5e28a9879 100644 --- a/kernel/src/syscall/futex.rs +++ b/kernel/src/syscall/futex.rs @@ -71,6 +71,6 @@ pub fn sys_futex( _ => panic!("Unsupported futex operations"), }?; - debug!("futex returns, tid= {} ", ctx.thread.tid()); + debug!("futex returns, tid= {} ", ctx.posix_thread.tid()); Ok(SyscallReturn::Return(res as _)) } diff --git a/kernel/src/syscall/gettid.rs b/kernel/src/syscall/gettid.rs index b51f992c9..18f67c147 100644 --- a/kernel/src/syscall/gettid.rs +++ b/kernel/src/syscall/gettid.rs @@ -4,6 +4,6 @@ use super::SyscallReturn; use crate::prelude::*; pub fn sys_gettid(ctx: &Context) -> Result { - let tid = ctx.thread.tid(); + let tid = ctx.posix_thread.tid(); Ok(SyscallReturn::Return(tid as _)) } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index fbe453d1a..9d96c9097 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -345,7 +345,10 @@ macro_rules! log_syscall_entry { if log::log_enabled!(log::Level::Info) { let syscall_name_str = stringify!($syscall_name); let pid = $crate::current!().pid(); - let tid = $crate::current_thread!().tid(); + let tid = { + use $crate::process::posix_thread::PosixThreadExt; + $crate::current_thread!().tid() + }; log::info!( "[pid={}][tid={}][id={}][{}]", pid, diff --git a/kernel/src/syscall/set_tid_address.rs b/kernel/src/syscall/set_tid_address.rs index cc7e5df39..d682d4cc8 100644 --- a/kernel/src/syscall/set_tid_address.rs +++ b/kernel/src/syscall/set_tid_address.rs @@ -13,6 +13,6 @@ pub fn sys_set_tid_address(tidptr: Vaddr, ctx: &Context) -> Result { let tid = sig_event.sigev_un.read_tid() as u32; - let thread = thread_table::get_thread(tid).ok_or_else(|| { + let thread = thread_table::get_posix_thread(tid).ok_or_else(|| { Error::with_message(Errno::EINVAL, "target thread does not exist") })?; let posix_thread = thread.as_posix_thread().unwrap(); @@ -132,7 +132,7 @@ pub fn sys_timer_create( } } DynamicClockIdInfo::Tid(tid, clock_type) => { - let thread = thread_table::get_thread(tid) + let thread = thread_table::get_posix_thread(tid) .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid clock id"))?; let posix_thread = thread.as_posix_thread().unwrap(); match clock_type { diff --git a/kernel/src/thread/kernel_thread.rs b/kernel/src/thread/kernel_thread.rs index 461e22827..332c04771 100644 --- a/kernel/src/thread/kernel_thread.rs +++ b/kernel/src/thread/kernel_thread.rs @@ -5,7 +5,7 @@ use ostd::{ task::{Priority, TaskOptions}, }; -use super::{allocate_tid, status::ThreadStatus, thread_table, Thread}; +use super::{status::ThreadStatus, thread_table, Thread}; use crate::prelude::*; /// The inner data of a kernel thread @@ -38,21 +38,21 @@ impl KernelThreadExt for Thread { let current_thread = current_thread!(); // ensure the thread is exit current_thread.exit(); + thread_table::remove_kernel_thread(current_thread); }; - let tid = allocate_tid(); let thread = Arc::new_cyclic(|thread_ref| { - let weal_thread = thread_ref.clone(); + let weak_thread = thread_ref.clone(); let task = TaskOptions::new(thread_fn) - .data(weal_thread) + .data(weak_thread) .priority(thread_options.priority) .cpu_affinity(thread_options.cpu_affinity) .build() .unwrap(); let status = ThreadStatus::Init; let kernel_thread = KernelThread; - Thread::new(tid, task, kernel_thread, status) + Thread::new(task, kernel_thread, status) }); - thread_table::add_thread(thread.clone()); + thread_table::add_kernel_thread(thread.clone()); thread } diff --git a/kernel/src/thread/mod.rs b/kernel/src/thread/mod.rs index cb7249fe7..177eaf109 100644 --- a/kernel/src/thread/mod.rs +++ b/kernel/src/thread/mod.rs @@ -2,7 +2,7 @@ //! Posix thread implementation -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::Ordering; use ostd::task::Task; @@ -18,13 +18,9 @@ pub mod work_queue; pub type Tid = u32; -static TID_ALLOCATOR: AtomicU32 = AtomicU32::new(0); - /// A thread is a wrapper on top of task. pub struct Thread { // immutable part - /// Thread id - tid: Tid, /// Low-level info task: Arc, /// Data: Posix thread info/Kernel thread Info @@ -36,14 +32,8 @@ pub struct Thread { impl Thread { /// Never call these function directly - pub fn new( - tid: Tid, - task: Arc, - data: impl Send + Sync + Any, - status: ThreadStatus, - ) -> Self { + pub fn new(task: Arc, data: impl Send + Sync + Any, status: ThreadStatus) -> Self { Thread { - tid, task, data: Box::new(data), status: AtomicThreadStatus::new(status), @@ -94,10 +84,6 @@ impl Thread { Task::yield_now() } - pub fn tid(&self) -> Tid { - self.tid - } - /// Returns the associated data. /// /// The return type must be borrowed box, otherwise the `downcast_ref` will fail. @@ -106,8 +92,3 @@ impl Thread { &self.data } } - -/// Allocates a new tid for the new thread -pub fn allocate_tid() -> Tid { - TID_ALLOCATOR.fetch_add(1, Ordering::SeqCst) -} diff --git a/kernel/src/thread/task.rs b/kernel/src/thread/task.rs index d7b6ed3c4..35ffa0e66 100644 --- a/kernel/src/thread/task.rs +++ b/kernel/src/thread/task.rs @@ -47,7 +47,7 @@ pub fn create_new_user_task(user_space: Arc, thread_ref: Weak // in the child process. if is_userspace_vaddr(child_tid_ptr) { CurrentUserSpace::get() - .write_val(child_tid_ptr, ¤t_thread.tid()) + .write_val(child_tid_ptr, ¤t_posix_thread.tid()) .unwrap(); } @@ -77,7 +77,7 @@ pub fn create_new_user_task(user_space: Arc, thread_ref: Weak // If current is suspended, wait for a signal to wake up self while current_thread.status().is_stopped() { Thread::yield_now(); - debug!("{} is suspended.", current_thread.tid()); + debug!("{} is suspended.", current_posix_thread.tid()); handle_pending_signal(user_ctx, ¤t_thread).unwrap(); } if current_thread.status().is_exited() { diff --git a/kernel/src/thread/thread_table.rs b/kernel/src/thread/thread_table.rs index 8f92a3340..2dcb68d34 100644 --- a/kernel/src/thread/thread_table.rs +++ b/kernel/src/thread/thread_table.rs @@ -1,21 +1,30 @@ // SPDX-License-Identifier: MPL-2.0 +use keyable_arc::KeyableArc; + use super::{Thread, Tid}; -use crate::prelude::*; +use crate::{prelude::*, process::posix_thread::PosixThreadExt}; -lazy_static! { - static ref THREAD_TABLE: SpinLock>> = SpinLock::new(BTreeMap::new()); +static POSIX_THREAD_TABLE: SpinLock>> = SpinLock::new(BTreeMap::new()); +static KERNEL_THREAD_TABLE: SpinLock>> = SpinLock::new(BTreeSet::new()); + +pub fn add_posix_thread(tid: Tid, thread: Arc) { + debug_assert_eq!(tid, thread.tid()); + POSIX_THREAD_TABLE.lock().insert(tid, thread); } -pub fn add_thread(thread: Arc) { - let tid = thread.tid(); - THREAD_TABLE.lock().insert(tid, thread); +pub fn remove_posix_thread(tid: Tid) { + POSIX_THREAD_TABLE.lock().remove(&tid); } -pub fn remove_thread(tid: Tid) { - THREAD_TABLE.lock().remove(&tid); +pub fn get_posix_thread(tid: Tid) -> Option> { + POSIX_THREAD_TABLE.lock().get(&tid).cloned() } -pub fn get_thread(tid: Tid) -> Option> { - THREAD_TABLE.lock().get(&tid).cloned() +pub(super) fn add_kernel_thread(thread: Arc) { + KERNEL_THREAD_TABLE.lock().insert(KeyableArc::from(thread)); +} + +pub(super) fn remove_kernel_thread(thread: Arc) { + KERNEL_THREAD_TABLE.lock().remove(&KeyableArc::from(thread)); }