spilt kernel thread from process

This commit is contained in:
Jianfeng Jiang 2023-03-07 14:24:29 +08:00 committed by Tate, Hongliang Tian
parent 8f8649bfc1
commit a084c3b687
16 changed files with 118 additions and 152 deletions

21
src/Cargo.lock generated
View File

@ -245,6 +245,7 @@ dependencies = [
"spin 0.9.4", "spin 0.9.4",
"uart_16550", "uart_16550",
"volatile", "volatile",
"x86",
"x86_64", "x86_64",
] ]
@ -459,6 +460,15 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "raw-cpuid"
version = "10.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "ringbuffer" name = "ringbuffer"
version = "0.10.0" version = "0.10.0"
@ -706,6 +716,17 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "x86"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385"
dependencies = [
"bit_field",
"bitflags",
"raw-cpuid",
]
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.14.10" version = "0.14.10"

View File

@ -20,6 +20,7 @@
use crate::{ use crate::{
prelude::*, prelude::*,
thread::{kernel_thread::KernelThreadExt, Thread},
user_apps::{get_all_apps, get_busybox_app, UserApp}, user_apps::{get_all_apps, get_busybox_app, UserApp},
}; };
use process::Process; use process::Process;
@ -60,34 +61,18 @@ pub fn init_thread() {
current_thread!().tid() current_thread!().tid()
); );
// driver::pci::virtio::block::block_device_test(); // driver::pci::virtio::block::block_device_test();
let process = Process::spawn_kernel_process(|| { let thread = Thread::spawn_kernel_thread(|| {
println!("[kernel] Hello world from kernel!"); println!("[kernel] Hello world from kernel!");
let current = current_thread!(); let current = current_thread!();
let pid = current.tid(); let tid = current.tid();
debug!("current pid = {}", pid); debug!("current tid = {}", tid);
}); });
thread.join();
info!( info!(
"[jinux-std/lib.rs] spawn kernel thread, tid = {}", "[jinux-std/lib.rs] spawn kernel thread, tid = {}",
process.pid() thread.tid()
); );
// FIXME: should be running this apps before we running shell?
println!("");
println!("[kernel] Running test programs");
println!("");
// Run test apps
for app in get_all_apps().unwrap().into_iter() {
let UserApp {
elf_path: app_name,
app_content,
argv,
envp,
} = app;
let app_content = app_content.into_boxed_slice();
println!("[jinux-std/lib.rs] spwan {:?} process", app_name);
Process::spawn_user_process(app_name.clone(), Box::leak(app_content), argv, Vec::new());
}
// Run busybox ash // Run busybox ash
let UserApp { let UserApp {
elf_path: app_name, elf_path: app_name,
@ -102,8 +87,8 @@ pub fn init_thread() {
loop { loop {
// We don't have preemptive scheduler now. // We don't have preemptive scheduler now.
// The long running init process should yield its own execution to allow other tasks to go on. // The long running init thread should yield its own execution to allow other tasks to go on.
let _ = wait_child_exit(ProcessFilter::Any, WaitOptions::empty()); Thread::yield_now();
} }
} }
@ -114,6 +99,6 @@ fn read_ramdisk_content() -> &'static [u8] {
/// first process never return /// first process never return
#[controlled] #[controlled]
pub fn run_first_process() -> ! { pub fn run_first_process() -> ! {
Process::spawn_kernel_process(init_thread); Thread::spawn_kernel_thread(init_thread);
unreachable!() unreachable!()
} }

View File

@ -169,7 +169,7 @@ fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Resu
let child_tid = allocate_tid(); let child_tid = allocate_tid();
// inherit sigmask from current thread // inherit sigmask from current thread
let current_thread = current_thread!(); let current_thread = current_thread!();
let current_posix_thread = current_thread.posix_thread(); let current_posix_thread = current_thread.as_posix_thread().unwrap();
let sig_mask = current_posix_thread.sig_mask().lock().clone(); let sig_mask = current_posix_thread.sig_mask().lock().clone();
let is_main_thread = child_tid == current.pid(); let is_main_thread = child_tid == current.pid();
let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space) let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space)
@ -177,7 +177,7 @@ fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Resu
.is_main_thread(is_main_thread); .is_main_thread(is_main_thread);
let child_thread = thread_builder.build(); let child_thread = thread_builder.build();
current.threads.lock().push(child_thread.clone()); current.threads.lock().push(child_thread.clone());
let child_posix_thread = child_thread.posix_thread(); 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)?;
clone_child_settid( clone_child_settid(
@ -191,6 +191,7 @@ fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Resu
fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Result<Arc<Process>> { fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Result<Arc<Process>> {
let current = current!(); let current = current!();
let parent = Arc::downgrade(&current);
let clone_flags = clone_args.clone_flags; let clone_flags = clone_args.clone_flags;
// clone vm // clone vm
@ -222,7 +223,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
// inherit parent's sig mask // inherit parent's sig mask
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let child_sig_mask = posix_thread.sig_mask().lock().clone(); let child_sig_mask = posix_thread.sig_mask().lock().clone();
let child_tid = allocate_tid(); let child_tid = allocate_tid();
@ -237,6 +238,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
let child_thread = child_thread_builder.build(); let child_thread = child_thread_builder.build();
Process::new( Process::new(
child_pid, child_pid,
parent,
vec![child_thread], vec![child_thread],
Some(child_elf_path), Some(child_elf_path),
child_user_vm, child_user_vm,
@ -256,7 +258,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
process_table::add_process(child.clone()); process_table::add_process(child.clone());
let child_thread = thread_table::tid_to_thread(child_tid).unwrap(); let child_thread = thread_table::tid_to_thread(child_tid).unwrap();
let child_posix_thread = child_thread.posix_thread(); 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)?;
clone_child_settid( clone_child_settid(

View File

@ -14,7 +14,6 @@ use crate::fs::file_table::FileTable;
use crate::fs::fs_resolver::FsResolver; use crate::fs::fs_resolver::FsResolver;
use crate::prelude::*; use crate::prelude::*;
use crate::rights::Full; use crate::rights::Full;
use crate::thread::kernel_thread::KernelThreadExt;
use crate::thread::{thread_table, Thread}; use crate::thread::{thread_table, Thread};
use crate::tty::get_n_tty; use crate::tty::get_n_tty;
use crate::vm::vmar::Vmar; use crate::vm::vmar::Vmar;
@ -38,6 +37,8 @@ pub type Pid = i32;
pub type Pgid = i32; pub type Pgid = i32;
pub type ExitCode = i32; pub type ExitCode = i32;
const INIT_PROCESS_PID: Pid = 1;
/// Process stands for a set of threads that shares the same userspace. /// Process stands for a set of threads that shares the same userspace.
/// Currently, we only support one thread inside a process. /// Currently, we only support one thread inside a process.
pub struct Process { pub struct Process {
@ -82,20 +83,17 @@ impl Process {
/// returns the current process /// returns the current process
pub fn current() -> Arc<Process> { pub fn current() -> Arc<Process> {
let current_thread = Thread::current(); let current_thread = Thread::current();
if current_thread.is_posix_thread() { if let Some(posix_thread) = current_thread.as_posix_thread() {
let posix_thread = current_thread.posix_thread();
posix_thread.process() posix_thread.process()
} else if current_thread.is_kernel_thread() {
let kernel_thread = current_thread.kernel_thread();
kernel_thread.process()
} else { } else {
panic!("[Internal error]The process is neither kernel process or user process"); panic!("[Internal error]The current thread does not belong to a process");
} }
} }
/// create a new process(not schedule it) /// create a new process(not schedule it)
pub fn new( pub fn new(
pid: Pid, pid: Pid,
parent: Weak<Process>,
threads: Vec<Arc<Thread>>, threads: Vec<Arc<Thread>>,
elf_path: Option<CString>, elf_path: Option<CString>,
user_vm: Option<UserVm>, user_vm: Option<UserVm>,
@ -105,12 +103,6 @@ impl Process {
fs: Arc<RwLock<FsResolver>>, fs: Arc<RwLock<FsResolver>>,
sig_dispositions: Arc<Mutex<SigDispositions>>, sig_dispositions: Arc<Mutex<SigDispositions>>,
) -> Self { ) -> Self {
let parent = if pid == 0 {
Weak::new()
} else {
let current_process = current!();
Arc::downgrade(&current_process)
};
let children = BTreeMap::new(); let children = BTreeMap::new();
let waiting_children = WaitQueue::new(); let waiting_children = WaitQueue::new();
let poll_queue = WaitQueue::new(); let poll_queue = WaitQueue::new();
@ -161,20 +153,6 @@ impl Process {
process process
} }
/// init a kernel process and run the process
pub fn spawn_kernel_process<F>(task_fn: F) -> Arc<Self>
where
F: Fn() + Send + Sync + 'static,
{
let process_fn = move || {
task_fn();
current!().exit_group(0);
};
let process = Process::create_kernel_process(process_fn);
process.run();
process
}
fn create_user_process( fn create_user_process(
elf_path: CString, elf_path: CString,
elf_file_content: &'static [u8], elf_file_content: &'static [u8],
@ -185,7 +163,12 @@ impl Process {
let weak_process = weak_process_ref.clone(); let weak_process = weak_process_ref.clone();
let cloned_filename = Some(elf_path.clone()); let cloned_filename = Some(elf_path.clone());
let root_vmar = Vmar::<Full>::new_root().unwrap(); let root_vmar = Vmar::<Full>::new_root().unwrap();
<<<<<<< HEAD
let thread = Thread::new_posix_thread_from_elf( let thread = Thread::new_posix_thread_from_elf(
=======
let fs = FsResolver::new();
let thread = Thread::new_posix_thread_from_executable(
>>>>>>> 0255134... fix
&root_vmar, &root_vmar,
elf_path, elf_path,
elf_file_content, elf_file_content,
@ -194,6 +177,8 @@ impl Process {
envp, envp,
); );
let pid = thread.tid(); let pid = thread.tid();
// spawn process will be called in a kernel thread, so the parent process is always none.
let parent = Weak::new();
let user_vm = UserVm::new(); let user_vm = UserVm::new();
let file_table = FileTable::new_with_stdio(); let file_table = FileTable::new_with_stdio();
let fs = FsResolver::new(); let fs = FsResolver::new();
@ -201,6 +186,7 @@ impl Process {
let process = Process::new( let process = Process::new(
pid, pid,
parent,
vec![thread], vec![thread],
cloned_filename, cloned_filename,
Some(user_vm), Some(user_vm),
@ -215,46 +201,12 @@ impl Process {
// Set process group // Set process group
user_process.create_and_set_process_group(); user_process.create_and_set_process_group();
process_table::add_process(user_process.clone()); process_table::add_process(user_process.clone());
let parent = user_process if let Some(parent) = user_process.parent() {
.parent()
.expect("[Internel error] User process should always have parent");
parent.add_child(user_process.clone()); parent.add_child(user_process.clone());
}
user_process user_process
} }
fn create_kernel_process<F>(task_fn: F) -> Arc<Self>
where
F: Fn() + Send + Sync + 'static,
{
let kernel_process = Arc::new_cyclic(|weak_process_ref| {
let weak_process = weak_process_ref.clone();
let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone());
let pid = thread.tid();
let file_table = FileTable::new();
let fs = FsResolver::new();
let sig_dispositions = SigDispositions::new();
// FIXME: kernel process does not need root vmar
let root_vmar = Vmar::<Full>::new_root().unwrap();
Process::new(
pid,
vec![thread],
None,
None,
Arc::new(root_vmar),
Weak::new(),
Arc::new(Mutex::new(file_table)),
Arc::new(RwLock::new(fs)),
Arc::new(Mutex::new(sig_dispositions)),
)
});
kernel_process.create_and_set_process_group();
process_table::add_process(kernel_process.clone());
if let Some(parent) = kernel_process.parent() {
parent.add_child(kernel_process.clone());
}
kernel_process
}
/// returns the pid of the process /// returns the pid of the process
pub fn pid(&self) -> Pid { pub fn pid(&self) -> Pid {
self.pid self.pid
@ -326,12 +278,13 @@ impl Process {
} }
// move children to the init process // move children to the init process
if !self.is_init_process() { if !self.is_init_process() {
let init_process = get_init_process(); if let Some(init_process) = get_init_process() {
for (_, child_process) in self.children.lock().drain_filter(|_, _| true) { for (_, child_process) in self.children.lock().drain_filter(|_, _| true) {
child_process.set_parent(Arc::downgrade(&init_process)); child_process.set_parent(Arc::downgrade(&init_process));
init_process.add_child(child_process); init_process.add_child(child_process);
} }
} }
}
if let Some(parent) = self.parent() { if let Some(parent) = self.parent() {
// set parent sig child // set parent sig child
@ -362,11 +315,6 @@ impl Process {
&self.threads &self.threads
} }
/// yield the current process to allow other processes to run
pub fn yield_now() {
Task::yield_now();
}
/// returns the user_vm /// returns the user_vm
pub fn user_vm(&self) -> Option<&UserVm> { pub fn user_vm(&self) -> Option<&UserVm> {
self.user_vm.as_ref() self.user_vm.as_ref()
@ -435,15 +383,6 @@ impl Process {
} }
/// Get the init process /// Get the init process
pub fn get_init_process() -> Arc<Process> { pub fn get_init_process() -> Option<Arc<Process>> {
let mut current_process = current!(); process_table::pid_to_process(INIT_PROCESS_PID)
while current_process.pid() != 0 {
let process = current_process
.parent
.lock()
.upgrade()
.expect("[Internal Error] init process cannot be None");
current_process = process;
}
current_process
} }

View File

@ -10,9 +10,8 @@ use crate::{
use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread}; use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread};
pub trait PosixThreadExt { pub trait PosixThreadExt {
fn is_posix_thread(&self) -> bool; fn as_posix_thread(&self) -> Option<&PosixThread>;
fn posix_thread(&self) -> &PosixThread; fn new_posix_thread_from_executable(
fn new_posix_thread_from_elf(
root_vmar: &Vmar<Full>, root_vmar: &Vmar<Full>,
elf_path: CString, elf_path: CString,
elf_file_content: &'static [u8], elf_file_content: &'static [u8],
@ -24,7 +23,7 @@ pub trait PosixThreadExt {
impl PosixThreadExt for Thread { impl PosixThreadExt for Thread {
/// This function should only be called when launch shell() /// This function should only be called when launch shell()
fn new_posix_thread_from_elf( fn new_posix_thread_from_executable(
root_vmar: &Vmar<Full>, root_vmar: &Vmar<Full>,
elf_path: CString, elf_path: CString,
elf_file_content: &'static [u8], elf_file_content: &'static [u8],
@ -47,11 +46,7 @@ impl PosixThreadExt for Thread {
thread_builder.build() thread_builder.build()
} }
fn is_posix_thread(&self) -> bool { fn as_posix_thread(&self) -> Option<&PosixThread> {
self.data().downcast_ref::<PosixThread>().is_some() self.data().downcast_ref::<PosixThread>()
}
fn posix_thread(&self) -> &PosixThread {
self.data().downcast_ref::<PosixThread>().unwrap()
} }
} }

View File

@ -29,7 +29,7 @@ use crate::{
pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> { pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> {
let current = current!(); let current = current!();
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let pid = current.pid(); let pid = current.pid();
let process_name = current.filename().unwrap(); let process_name = current.filename().unwrap();
let sig_mask = posix_thread.sig_mask().lock().clone(); let sig_mask = posix_thread.sig_mask().lock().clone();
@ -130,7 +130,7 @@ pub fn handle_user_signal(
mask.block(current_mask.as_u64()); mask.block(current_mask.as_u64());
} }
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
// block signals in sigmask when running signal handler // block signals in sigmask when running signal handler
posix_thread.sig_mask().lock().block(mask.as_u64()); posix_thread.sig_mask().lock().block(mask.as_u64());

View File

@ -27,7 +27,7 @@ pub fn sys_execve(
} }
// FIXME: should we set thread name in execve? // FIXME: should we set thread name in execve?
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let mut thread_name = posix_thread.thread_name().lock(); let mut thread_name = posix_thread.thread_name().lock();
let new_thread_name = ThreadName::new_from_elf_path(&elf_path)?; let new_thread_name = ThreadName::new_from_elf_path(&elf_path)?;
*thread_name = Some(new_thread_name); *thread_name = Some(new_thread_name);

View File

@ -11,7 +11,7 @@ pub fn sys_exit(exit_code: i32) -> Result<SyscallReturn> {
let current = current!(); let current = current!();
let pid = current.pid(); let pid = current.pid();
debug!("tid = {}, pid = {}", tid, pid); debug!("tid = {}, pid = {}", tid, pid);
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
current_thread.exit(); current_thread.exit();
posix_thread.exit(tid, exit_code)?; posix_thread.exit(tid, exit_code)?;

View File

@ -12,7 +12,7 @@ pub fn sys_prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> Res
let prctl_cmd = PrctlCmd::from_args(option, arg2, arg3, arg4, arg5)?; let prctl_cmd = PrctlCmd::from_args(option, arg2, arg3, arg4, arg5)?;
debug!("prctl cmd = {:?}", prctl_cmd); debug!("prctl cmd = {:?}", prctl_cmd);
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
match prctl_cmd { match prctl_cmd {
PrctlCmd::PR_GET_NAME(write_to_addr) => { PrctlCmd::PR_GET_NAME(write_to_addr) => {
let thread_name = posix_thread.thread_name().lock(); let thread_name = posix_thread.thread_name().lock();

View File

@ -36,7 +36,7 @@ fn do_rt_sigprocmask(
) -> Result<()> { ) -> Result<()> {
let current = current!(); let current = current!();
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let root_vmar = current.root_vmar(); let root_vmar = current.root_vmar();
let mut sig_mask = posix_thread.sig_mask().lock(); let mut sig_mask = posix_thread.sig_mask().lock();
let old_sig_mask_value = sig_mask.as_u64(); let old_sig_mask_value = sig_mask.as_u64();

View File

@ -11,7 +11,7 @@ use super::{SyscallReturn, SYS_RT_SIGRETRUN};
pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result<SyscallReturn> { pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_RT_SIGRETRUN); log_syscall_entry!(SYS_RT_SIGRETRUN);
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let mut sig_context = posix_thread.sig_context().lock(); let mut sig_context = posix_thread.sig_context().lock();
if None == *sig_context { if None == *sig_context {
return_errno_with_message!(Errno::EINVAL, "sigretrun should not been called"); return_errno_with_message!(Errno::EINVAL, "sigretrun should not been called");

View File

@ -1,11 +1,12 @@
use crate::thread::Thread;
use crate::{log_syscall_entry, prelude::*}; use crate::{log_syscall_entry, prelude::*};
use crate::{process::Process, syscall::SYS_SCHED_YIELD}; use crate::syscall::SYS_SCHED_YIELD;
use super::SyscallReturn; use super::SyscallReturn;
pub fn sys_sched_yield() -> Result<SyscallReturn> { pub fn sys_sched_yield() -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SCHED_YIELD); log_syscall_entry!(SYS_SCHED_YIELD);
Process::yield_now(); Thread::yield_now();
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))
} }

View File

@ -21,7 +21,7 @@ pub fn sys_set_robust_list(robust_list_head_ptr: Vaddr, len: usize) -> Result<Sy
let robust_list_head: RobustListHead = read_val_from_user(robust_list_head_ptr)?; let robust_list_head: RobustListHead = read_val_from_user(robust_list_head_ptr)?;
debug!("{:x?}", robust_list_head); debug!("{:x?}", robust_list_head);
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let mut robust_list = posix_thread.robust_list().lock(); let mut robust_list = posix_thread.robust_list().lock();
*robust_list = Some(robust_list_head); *robust_list = Some(robust_list_head);
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))

View File

@ -8,7 +8,7 @@ pub fn sys_set_tid_address(tidptr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SET_TID_ADDRESS); log_syscall_entry!(SYS_SET_TID_ADDRESS);
debug!("tidptr = 0x{:x}", tidptr); debug!("tidptr = 0x{:x}", tidptr);
let current_thread = current_thread!(); let current_thread = current_thread!();
let posix_thread = current_thread.posix_thread(); let posix_thread = current_thread.as_posix_thread().unwrap();
let mut clear_child_tid = posix_thread.clear_child_tid().lock(); let mut clear_child_tid = posix_thread.clear_child_tid().lock();
if *clear_child_tid != 0 { if *clear_child_tid != 0 {
// According to manuals at https://man7.org/linux/man-pages/man2/set_tid_address.2.html // According to manuals at https://man7.org/linux/man-pages/man2/set_tid_address.2.html

View File

@ -18,7 +18,7 @@ pub fn sys_tgkill(tgid: Pid, tid: Tid, sig_num: u8) -> Result<SyscallReturn> {
info!("tgid = {}, pid = {}, sig_num = {:?}", tgid, tid, sig_num); info!("tgid = {}, pid = {}, sig_num = {:?}", tgid, tid, sig_num);
let target_thread = thread_table::tid_to_thread(tid) let target_thread = thread_table::tid_to_thread(tid)
.ok_or(Error::with_message(Errno::EINVAL, "Invalid pid"))?; .ok_or(Error::with_message(Errno::EINVAL, "Invalid pid"))?;
let posix_thread = target_thread.posix_thread(); let posix_thread = target_thread.as_posix_thread().unwrap();
let pid = posix_thread.process().pid(); let pid = posix_thread.process().pid();
if pid != tgid { if pid != tgid {
return_errno_with_message!( return_errno_with_message!(

View File

@ -1,28 +1,32 @@
use jinux_frame::task::Task; use jinux_frame::task::Task;
use crate::{prelude::*, process::Process}; use crate::prelude::*;
use super::{allocate_tid, status::ThreadStatus, thread_table, Thread}; use super::{allocate_tid, status::ThreadStatus, thread_table, Thread};
pub struct KernelThread {
process: Weak<Process>,
}
impl KernelThread { /// This struct is used to mark a thread is a kernel thread
pub fn new(process: Weak<Process>) -> Self { pub struct KernelThread;
Self { process }
}
pub fn process(&self) -> Arc<Process> {
self.process.upgrade().unwrap()
}
}
pub trait KernelThreadExt { pub trait KernelThreadExt {
/// whether the thread is a kernel thread
fn is_kernel_thread(&self) -> bool; fn is_kernel_thread(&self) -> bool;
/// get the kernel_thread structure
fn kernel_thread(&self) -> &KernelThread; fn kernel_thread(&self) -> &KernelThread;
fn new_kernel_thread<F>(task_fn: F, process: Weak<Process>) -> Arc<Self> /// create a new kernel thread structure, **NOT** run the thread.
fn new_kernel_thread<F>(task_fn: F) -> Arc<Thread>
where where
F: Fn() + Send + Sync + 'static; F: Fn() + Send + Sync + 'static;
/// create a new kernel thread structure, and then run the thread.
fn spawn_kernel_thread<F>(task_fn: F) -> Arc<Thread>
where
F: Fn() + Send + Sync + 'static,
{
let thread = Self::new_kernel_thread(task_fn);
thread.run();
thread
}
/// join a kernel thread
fn join(&self);
} }
impl KernelThreadExt for Thread { impl KernelThreadExt for Thread {
@ -34,19 +38,38 @@ impl KernelThreadExt for Thread {
self.data().downcast_ref::<KernelThread>().unwrap() self.data().downcast_ref::<KernelThread>().unwrap()
} }
fn new_kernel_thread<F>(task_fn: F, process: Weak<Process>) -> Arc<Self> fn new_kernel_thread<F>(task_fn: F) -> Arc<Self>
where where
F: Fn() + Send + Sync + 'static, F: Fn() + Send + Sync + 'static,
{ {
let thread_fn = move || {
task_fn();
let current_thread = current_thread!();
// ensure the thread is exit
current_thread.exit();
};
let tid = allocate_tid(); 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 weal_thread = thread_ref.clone();
let task = Task::new(task_fn, weal_thread, None).unwrap(); let task = Task::new(thread_fn, weal_thread, None).unwrap();
let status = ThreadStatus::Init; let status = ThreadStatus::Init;
let kernel_thread = KernelThread::new(process); let kernel_thread = KernelThread;
Thread::new(tid, task, kernel_thread, status) Thread::new(tid, task, kernel_thread, status)
}); });
thread_table::add_thread(thread.clone()); thread_table::add_thread(thread.clone());
thread thread
} }
fn join(&self) {
loop {
let status = self.status.lock();
if status.is_exited() {
return;
} else {
drop(status);
Thread::yield_now();
}
}
}
} }