Move Tid from Thread to PosixThread

This commit is contained in:
Jianfeng Jiang
2024-09-12 04:48:33 +00:00
committed by Tate, Hongliang Tian
parent ceb6e2b242
commit 81b0f265b5
21 changed files with 90 additions and 86 deletions

View File

@ -133,10 +133,7 @@ fn ap_init() -> ! {
} }
fn init_thread() { fn init_thread() {
println!( println!("[kernel] Spawn init thread");
"[kernel] Spawn init thread, tid = {}",
current_thread!().tid()
);
// Work queue should be initialized before interrupt is enabled, // Work queue should be initialized before interrupt is enabled,
// in case any irq handler uses work queue as bottom half // in case any irq handler uses work queue as bottom half
thread::work_queue::init(); thread::work_queue::init();
@ -146,15 +143,8 @@ fn init_thread() {
// driver::pci::virtio::block::block_device_test(); // driver::pci::virtio::block::block_device_test();
let thread = Thread::spawn_kernel_thread(ThreadOptions::new(|| { let thread = Thread::spawn_kernel_thread(ThreadOptions::new(|| {
println!("[kernel] Hello world from kernel!"); println!("[kernel] Hello world from kernel!");
let current = current_thread!();
let tid = current.tid();
debug!("current tid = {}", tid);
})); }));
thread.join(); thread.join();
info!(
"[aster-nix/lib.rs] spawn kernel thread, tid = {}",
thread.tid()
);
print_banner(); print_banner();

View File

@ -18,7 +18,8 @@ use crate::{
cpu::LinuxAbi, cpu::LinuxAbi,
fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask}, fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask},
prelude::*, prelude::*,
thread::{allocate_tid, thread_table, Thread, Tid}, process::posix_thread::allocate_posix_tid,
thread::{thread_table, Thread, Tid},
}; };
bitflags! { bitflags! {
@ -180,7 +181,7 @@ fn clone_child_thread(
// Inherit sigmask from current thread // Inherit sigmask from current thread
let sig_mask = posix_thread.sig_mask().load(Ordering::Relaxed).into(); 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 child_thread = {
let credentials = { let credentials = {
let credentials = ctx.posix_thread.credentials(); let credentials = ctx.posix_thread.credentials();
@ -262,7 +263,7 @@ fn clone_child_process(
// inherit parent's nice value // inherit parent's nice value
let child_nice = process.nice().load(Ordering::Relaxed); let child_nice = process.nice().load(Ordering::Relaxed);
let child_tid = allocate_tid(); let child_tid = allocate_posix_tid();
let child = { let child = {
let child_elf_path = process.executable_path(); let child_elf_path = process.executable_path();
@ -295,7 +296,7 @@ fn clone_child_process(
}; };
// Deals with clone flags // 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(); let child_posix_thread = child_thread.as_posix_thread().unwrap();
clone_parent_settid(child_tid, clone_args.parent_tidptr, clone_flags)?; clone_parent_settid(child_tid, clone_args.parent_tidptr, clone_flags)?;
clone_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?; clone_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?;

View File

@ -4,7 +4,7 @@ use super::{process_table, Pid, Process, TermStatus};
use crate::{ use crate::{
prelude::*, prelude::*,
process::{ process::{
posix_thread::do_exit, posix_thread::{do_exit, PosixThreadExt},
signal::{constants::SIGCHLD, signals::kernel::KernelSignal}, signal::{constants::SIGCHLD, signals::kernel::KernelSignal},
}, },
}; };
@ -20,7 +20,7 @@ pub fn do_exit_group(term_status: TermStatus) {
// Exit all threads // Exit all threads
let threads = current.threads().lock().clone(); let threads = current.threads().lock().clone();
for thread in threads { 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); debug!("Ignore error when call exit: {:?}", e);
} }
} }

View File

@ -71,7 +71,7 @@ pub fn kill_group(pgid: Pgid, signal: Option<UserSignal>, ctx: &Context) -> Resu
/// If `signal` is `None`, this method will only check permission without sending /// If `signal` is `None`, this method will only check permission without sending
/// any signal. /// any signal.
pub fn tgkill(tid: Tid, tgid: Pid, signal: Option<UserSignal>, ctx: &Context) -> Result<()> { pub fn tgkill(tid: Tid, tgid: Pid, signal: Option<UserSignal>, 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"))?; .ok_or_else(|| Error::with_message(Errno::ESRCH, "target thread does not exist"))?;
if thread.status().is_exited() { if thread.status().is_exited() {

View File

@ -95,6 +95,7 @@ impl PosixThreadBuilder {
let posix_thread = PosixThread { let posix_thread = PosixThread {
process, process,
tid,
name: Mutex::new(thread_name), name: Mutex::new(thread_name),
set_child_tid: Mutex::new(set_child_tid), set_child_tid: Mutex::new(set_child_tid),
clear_child_tid: Mutex::new(clear_child_tid), clear_child_tid: Mutex::new(clear_child_tid),
@ -110,9 +111,9 @@ impl PosixThreadBuilder {
prof_timer_manager, 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 thread
} }
} }

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0 // 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::{ use crate::{
prelude::*, prelude::*,
process::{do_exit_group, TermStatus}, process::{do_exit_group, TermStatus},
@ -12,15 +12,13 @@ use crate::{
/// # Panics /// # Panics
/// ///
/// If the thread is not a POSIX thread, this method will panic. /// If the thread is not a POSIX thread, this method will panic.
pub fn do_exit(thread: Arc<Thread>, term_status: TermStatus) -> Result<()> { pub fn do_exit(thread: &Thread, posix_thread: &PosixThread, term_status: TermStatus) -> Result<()> {
if thread.status().is_exited() { if thread.status().is_exited() {
return Ok(()); return Ok(());
} }
thread.exit(); thread.exit();
let tid = thread.tid(); let tid = posix_thread.tid;
let posix_thread = thread.as_posix_thread().unwrap();
let mut clear_ctid = posix_thread.clear_child_tid().lock(); 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. // 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<Thread>, term_status: TermStatus) -> Result<()> {
if tid != posix_thread.process().pid() { if tid != posix_thread.process().pid() {
// We don't remove main thread. // We don't remove main thread.
// The main thread is removed when the process is reaped. // 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() { if posix_thread.is_main_thread(tid) || posix_thread.is_last_thread() {

View File

@ -2,7 +2,7 @@
#![allow(dead_code)] #![allow(dead_code)]
use core::sync::atomic::Ordering; use core::sync::atomic::{AtomicU32, Ordering};
use aster_rights::{ReadOp, WriteOp}; use aster_rights::{ReadOp, WriteOp};
use ostd::sync::Waker; use ostd::sync::Waker;
@ -42,6 +42,8 @@ pub use robust_list::RobustListHead;
pub struct PosixThread { pub struct PosixThread {
// Immutable part // Immutable part
process: Weak<Process>, process: Weak<Process>,
tid: Tid,
// Mutable part // Mutable part
name: Mutex<Option<ThreadName>>, name: Mutex<Option<ThreadName>>,
@ -87,6 +89,11 @@ impl PosixThread {
Weak::clone(&self.process) Weak::clone(&self.process)
} }
/// Returns the thread id
pub fn tid(&self) -> Tid {
self.tid
}
pub fn thread_name(&self) -> &Mutex<Option<ThreadName>> { pub fn thread_name(&self) -> &Mutex<Option<ThreadName>> {
&self.name &self.name
} }
@ -292,3 +299,10 @@ impl PosixThread {
self.credentials.dup().restrict() 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)
}

View File

@ -13,6 +13,14 @@ use crate::{
thread::{Thread, Tid}, thread::{Thread, Tid},
}; };
pub trait PosixThreadExt { 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>; fn as_posix_thread(&self) -> Option<&PosixThread>;
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn new_posix_thread_from_executable( fn new_posix_thread_from_executable(

View File

@ -4,7 +4,7 @@ use core::sync::atomic::Ordering;
use self::timer_manager::PosixTimerManager; use self::timer_manager::PosixTimerManager;
use super::{ use super::{
posix_thread::PosixThreadExt, posix_thread::{allocate_posix_tid, PosixThreadExt},
process_table, process_table,
process_vm::{Heap, InitStackReader, ProcessVm}, process_vm::{Heap, InitStackReader, ProcessVm},
rlimit::ResourceLimits, rlimit::ResourceLimits,
@ -21,7 +21,7 @@ use crate::{
fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask}, fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask},
prelude::*, prelude::*,
sched::nice::Nice, sched::nice::Nice,
thread::{allocate_tid, Thread}, thread::Thread,
time::clocks::ProfClock, time::clocks::ProfClock,
vm::vmar::Vmar, vm::vmar::Vmar,
}; };
@ -236,7 +236,7 @@ impl Process {
envp: Vec<CString>, envp: Vec<CString>,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
let process_builder = { let process_builder = {
let pid = allocate_tid(); let pid = allocate_posix_tid();
let parent = Weak::new(); let parent = Weak::new();
let credentials = Credentials::new_root(); let credentials = Credentials::new_root();
@ -710,7 +710,7 @@ mod test {
fn new_process(parent: Option<Arc<Process>>) -> Arc<Process> { fn new_process(parent: Option<Arc<Process>>) -> Arc<Process> {
crate::util::random::init(); crate::util::random::init();
crate::fs::rootfs::init_root_mount(); crate::fs::rootfs::init_root_mount();
let pid = allocate_tid(); let pid = allocate_posix_tid();
let parent = if let Some(parent) = parent { let parent = if let Some(parent) = parent {
Arc::downgrade(&parent) Arc::downgrade(&parent)
} else { } else {

View File

@ -2,12 +2,12 @@
#![allow(dead_code)] #![allow(dead_code)]
use super::{ use super::{process_filter::ProcessFilter, signal::constants::SIGCHLD, ExitCode, Pid, Process};
process_filter::ProcessFilter, use crate::{
signal::{constants::SIGCHLD, with_signal_blocked}, prelude::*,
ExitCode, Pid, Process, 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 // The definition of WaitOptions is from Occlum
bitflags! { bitflags! {
@ -86,7 +86,7 @@ fn reap_zombie_child(process: &Process, pid: Pid) -> ExitCode {
let child_process = process.children().lock().remove(&pid).unwrap(); let child_process = process.children().lock().remove(&pid).unwrap();
assert!(child_process.is_zombie()); assert!(child_process.is_zombie());
for thread in &*child_process.threads().lock() { 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 // Lock order: session table -> group table -> process table -> group of process

View File

@ -136,7 +136,7 @@ pub fn read_clock(clockid: clockid_t, ctx: &Context) -> Result<Duration> {
} }
} }
DynamicClockIdInfo::Tid(tid, clock_type) => { 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"))?; .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid clock ID"))?;
let posix_thread = thread.as_posix_thread().unwrap(); let posix_thread = thread.as_posix_thread().unwrap();
match clock_type { match clock_type {

View File

@ -6,12 +6,11 @@ use crate::{
syscall::SyscallReturn, syscall::SyscallReturn,
}; };
pub fn sys_exit(exit_code: i32, _ctx: &Context) -> Result<SyscallReturn> { pub fn sys_exit(exit_code: i32, ctx: &Context) -> Result<SyscallReturn> {
debug!("exid code = {}", exit_code); debug!("exid code = {}", exit_code);
let current_thread = current_thread!();
let term_status = TermStatus::Exited(exit_code as _); 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)) Ok(SyscallReturn::Return(0))
} }

View File

@ -71,6 +71,6 @@ pub fn sys_futex(
_ => panic!("Unsupported futex operations"), _ => panic!("Unsupported futex operations"),
}?; }?;
debug!("futex returns, tid= {} ", ctx.thread.tid()); debug!("futex returns, tid= {} ", ctx.posix_thread.tid());
Ok(SyscallReturn::Return(res as _)) Ok(SyscallReturn::Return(res as _))
} }

View File

@ -4,6 +4,6 @@ use super::SyscallReturn;
use crate::prelude::*; use crate::prelude::*;
pub fn sys_gettid(ctx: &Context) -> Result<SyscallReturn> { pub fn sys_gettid(ctx: &Context) -> Result<SyscallReturn> {
let tid = ctx.thread.tid(); let tid = ctx.posix_thread.tid();
Ok(SyscallReturn::Return(tid as _)) Ok(SyscallReturn::Return(tid as _))
} }

View File

@ -345,7 +345,10 @@ macro_rules! log_syscall_entry {
if log::log_enabled!(log::Level::Info) { if log::log_enabled!(log::Level::Info) {
let syscall_name_str = stringify!($syscall_name); let syscall_name_str = stringify!($syscall_name);
let pid = $crate::current!().pid(); 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!( log::info!(
"[pid={}][tid={}][id={}][{}]", "[pid={}][tid={}][id={}][{}]",
pid, pid,

View File

@ -13,6 +13,6 @@ pub fn sys_set_tid_address(tidptr: Vaddr, ctx: &Context) -> Result<SyscallReturn
} else { } else {
*clear_child_tid = tidptr; *clear_child_tid = tidptr;
} }
let tid = ctx.thread.tid(); let tid = ctx.posix_thread.tid();
Ok(SyscallReturn::Return(tid as _)) Ok(SyscallReturn::Return(tid as _))
} }

View File

@ -76,7 +76,7 @@ pub fn sys_timer_create(
// Send a signal to the specified thread when the timer is expired. // Send a signal to the specified thread when the timer is expired.
SigNotify::SIGEV_THREAD_ID => { SigNotify::SIGEV_THREAD_ID => {
let tid = sig_event.sigev_un.read_tid() as u32; 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") Error::with_message(Errno::EINVAL, "target thread does not exist")
})?; })?;
let posix_thread = thread.as_posix_thread().unwrap(); let posix_thread = thread.as_posix_thread().unwrap();
@ -132,7 +132,7 @@ pub fn sys_timer_create(
} }
} }
DynamicClockIdInfo::Tid(tid, clock_type) => { 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"))?; .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid clock id"))?;
let posix_thread = thread.as_posix_thread().unwrap(); let posix_thread = thread.as_posix_thread().unwrap();
match clock_type { match clock_type {

View File

@ -5,7 +5,7 @@ use ostd::{
task::{Priority, TaskOptions}, task::{Priority, TaskOptions},
}; };
use super::{allocate_tid, status::ThreadStatus, thread_table, Thread}; use super::{status::ThreadStatus, thread_table, Thread};
use crate::prelude::*; use crate::prelude::*;
/// The inner data of a kernel thread /// The inner data of a kernel thread
@ -38,21 +38,21 @@ impl KernelThreadExt for Thread {
let current_thread = current_thread!(); let current_thread = current_thread!();
// ensure the thread is exit // ensure the thread is exit
current_thread.exit(); current_thread.exit();
thread_table::remove_kernel_thread(current_thread);
}; };
let tid = allocate_tid();
let thread = Arc::new_cyclic(|thread_ref| { 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) let task = TaskOptions::new(thread_fn)
.data(weal_thread) .data(weak_thread)
.priority(thread_options.priority) .priority(thread_options.priority)
.cpu_affinity(thread_options.cpu_affinity) .cpu_affinity(thread_options.cpu_affinity)
.build() .build()
.unwrap(); .unwrap();
let status = ThreadStatus::Init; let status = ThreadStatus::Init;
let kernel_thread = KernelThread; 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 thread
} }

View File

@ -2,7 +2,7 @@
//! Posix thread implementation //! Posix thread implementation
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::Ordering;
use ostd::task::Task; use ostd::task::Task;
@ -18,13 +18,9 @@ pub mod work_queue;
pub type Tid = u32; pub type Tid = u32;
static TID_ALLOCATOR: AtomicU32 = AtomicU32::new(0);
/// A thread is a wrapper on top of task. /// A thread is a wrapper on top of task.
pub struct Thread { pub struct Thread {
// immutable part // immutable part
/// Thread id
tid: Tid,
/// Low-level info /// Low-level info
task: Arc<Task>, task: Arc<Task>,
/// Data: Posix thread info/Kernel thread Info /// Data: Posix thread info/Kernel thread Info
@ -36,14 +32,8 @@ pub struct Thread {
impl Thread { impl Thread {
/// Never call these function directly /// Never call these function directly
pub fn new( pub fn new(task: Arc<Task>, data: impl Send + Sync + Any, status: ThreadStatus) -> Self {
tid: Tid,
task: Arc<Task>,
data: impl Send + Sync + Any,
status: ThreadStatus,
) -> Self {
Thread { Thread {
tid,
task, task,
data: Box::new(data), data: Box::new(data),
status: AtomicThreadStatus::new(status), status: AtomicThreadStatus::new(status),
@ -94,10 +84,6 @@ impl Thread {
Task::yield_now() Task::yield_now()
} }
pub fn tid(&self) -> Tid {
self.tid
}
/// Returns the associated data. /// Returns the associated data.
/// ///
/// The return type must be borrowed box, otherwise the `downcast_ref` will fail. /// The return type must be borrowed box, otherwise the `downcast_ref` will fail.
@ -106,8 +92,3 @@ impl Thread {
&self.data &self.data
} }
} }
/// Allocates a new tid for the new thread
pub fn allocate_tid() -> Tid {
TID_ALLOCATOR.fetch_add(1, Ordering::SeqCst)
}

View File

@ -47,7 +47,7 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
// in the child process. // in the child process.
if is_userspace_vaddr(child_tid_ptr) { if is_userspace_vaddr(child_tid_ptr) {
CurrentUserSpace::get() CurrentUserSpace::get()
.write_val(child_tid_ptr, &current_thread.tid()) .write_val(child_tid_ptr, &current_posix_thread.tid())
.unwrap(); .unwrap();
} }
@ -77,7 +77,7 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
// If current is suspended, wait for a signal to wake up self // If current is suspended, wait for a signal to wake up self
while current_thread.status().is_stopped() { while current_thread.status().is_stopped() {
Thread::yield_now(); Thread::yield_now();
debug!("{} is suspended.", current_thread.tid()); debug!("{} is suspended.", current_posix_thread.tid());
handle_pending_signal(user_ctx, &current_thread).unwrap(); handle_pending_signal(user_ctx, &current_thread).unwrap();
} }
if current_thread.status().is_exited() { if current_thread.status().is_exited() {

View File

@ -1,21 +1,30 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use keyable_arc::KeyableArc;
use super::{Thread, Tid}; use super::{Thread, Tid};
use crate::prelude::*; use crate::{prelude::*, process::posix_thread::PosixThreadExt};
lazy_static! { static POSIX_THREAD_TABLE: SpinLock<BTreeMap<Tid, Arc<Thread>>> = SpinLock::new(BTreeMap::new());
static ref THREAD_TABLE: SpinLock<BTreeMap<Tid, Arc<Thread>>> = SpinLock::new(BTreeMap::new()); static KERNEL_THREAD_TABLE: SpinLock<BTreeSet<KeyableArc<Thread>>> = SpinLock::new(BTreeSet::new());
pub fn add_posix_thread(tid: Tid, thread: Arc<Thread>) {
debug_assert_eq!(tid, thread.tid());
POSIX_THREAD_TABLE.lock().insert(tid, thread);
} }
pub fn add_thread(thread: Arc<Thread>) { pub fn remove_posix_thread(tid: Tid) {
let tid = thread.tid(); POSIX_THREAD_TABLE.lock().remove(&tid);
THREAD_TABLE.lock().insert(tid, thread);
} }
pub fn remove_thread(tid: Tid) { pub fn get_posix_thread(tid: Tid) -> Option<Arc<Thread>> {
THREAD_TABLE.lock().remove(&tid); POSIX_THREAD_TABLE.lock().get(&tid).cloned()
} }
pub fn get_thread(tid: Tid) -> Option<Arc<Thread>> { pub(super) fn add_kernel_thread(thread: Arc<Thread>) {
THREAD_TABLE.lock().get(&tid).cloned() KERNEL_THREAD_TABLE.lock().insert(KeyableArc::from(thread));
}
pub(super) fn remove_kernel_thread(thread: Arc<Thread>) {
KERNEL_THREAD_TABLE.lock().remove(&KeyableArc::from(thread));
} }