spilt kernel thread from process
This commit is contained in:
parent
8f8649bfc1
commit
a084c3b687
|
@ -245,6 +245,7 @@ dependencies = [
|
|||
"spin 0.9.4",
|
||||
"uart_16550",
|
||||
"volatile",
|
||||
"x86",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
|
@ -459,6 +460,15 @@ dependencies = [
|
|||
"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]]
|
||||
name = "ringbuffer"
|
||||
version = "0.10.0"
|
||||
|
@ -706,6 +716,17 @@ dependencies = [
|
|||
"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]]
|
||||
name = "x86_64"
|
||||
version = "0.14.10"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
use crate::{
|
||||
prelude::*,
|
||||
thread::{kernel_thread::KernelThreadExt, Thread},
|
||||
user_apps::{get_all_apps, get_busybox_app, UserApp},
|
||||
};
|
||||
use process::Process;
|
||||
|
@ -60,34 +61,18 @@ pub fn init_thread() {
|
|||
current_thread!().tid()
|
||||
);
|
||||
// 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!");
|
||||
let current = current_thread!();
|
||||
let pid = current.tid();
|
||||
debug!("current pid = {}", pid);
|
||||
let tid = current.tid();
|
||||
debug!("current tid = {}", tid);
|
||||
});
|
||||
thread.join();
|
||||
info!(
|
||||
"[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
|
||||
let UserApp {
|
||||
elf_path: app_name,
|
||||
|
@ -102,8 +87,8 @@ pub fn init_thread() {
|
|||
|
||||
loop {
|
||||
// We don't have preemptive scheduler now.
|
||||
// The long running init process should yield its own execution to allow other tasks to go on.
|
||||
let _ = wait_child_exit(ProcessFilter::Any, WaitOptions::empty());
|
||||
// The long running init thread should yield its own execution to allow other tasks to go on.
|
||||
Thread::yield_now();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +99,6 @@ fn read_ramdisk_content() -> &'static [u8] {
|
|||
/// first process never return
|
||||
#[controlled]
|
||||
pub fn run_first_process() -> ! {
|
||||
Process::spawn_kernel_process(init_thread);
|
||||
Thread::spawn_kernel_thread(init_thread);
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Resu
|
|||
let child_tid = allocate_tid();
|
||||
// inherit sigmask from 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 is_main_thread = child_tid == current.pid();
|
||||
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);
|
||||
let child_thread = thread_builder.build();
|
||||
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_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?;
|
||||
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>> {
|
||||
let current = current!();
|
||||
let parent = Arc::downgrade(¤t);
|
||||
let clone_flags = clone_args.clone_flags;
|
||||
|
||||
// clone vm
|
||||
|
@ -222,7 +223,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
|
|||
|
||||
// inherit parent's sig mask
|
||||
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_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();
|
||||
Process::new(
|
||||
child_pid,
|
||||
parent,
|
||||
vec![child_thread],
|
||||
Some(child_elf_path),
|
||||
child_user_vm,
|
||||
|
@ -256,7 +258,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
|
|||
process_table::add_process(child.clone());
|
||||
|
||||
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_child_cleartid(child_posix_thread, clone_args.child_tidptr, clone_flags)?;
|
||||
clone_child_settid(
|
||||
|
|
|
@ -14,7 +14,6 @@ use crate::fs::file_table::FileTable;
|
|||
use crate::fs::fs_resolver::FsResolver;
|
||||
use crate::prelude::*;
|
||||
use crate::rights::Full;
|
||||
use crate::thread::kernel_thread::KernelThreadExt;
|
||||
use crate::thread::{thread_table, Thread};
|
||||
use crate::tty::get_n_tty;
|
||||
use crate::vm::vmar::Vmar;
|
||||
|
@ -38,6 +37,8 @@ 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.
|
||||
/// Currently, we only support one thread inside a process.
|
||||
pub struct Process {
|
||||
|
@ -82,20 +83,17 @@ impl Process {
|
|||
/// returns the current process
|
||||
pub fn current() -> Arc<Process> {
|
||||
let current_thread = Thread::current();
|
||||
if current_thread.is_posix_thread() {
|
||||
let posix_thread = current_thread.posix_thread();
|
||||
if let Some(posix_thread) = current_thread.as_posix_thread() {
|
||||
posix_thread.process()
|
||||
} else if current_thread.is_kernel_thread() {
|
||||
let kernel_thread = current_thread.kernel_thread();
|
||||
kernel_thread.process()
|
||||
} 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)
|
||||
pub fn new(
|
||||
pid: Pid,
|
||||
parent: Weak<Process>,
|
||||
threads: Vec<Arc<Thread>>,
|
||||
elf_path: Option<CString>,
|
||||
user_vm: Option<UserVm>,
|
||||
|
@ -105,12 +103,6 @@ impl Process {
|
|||
fs: Arc<RwLock<FsResolver>>,
|
||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||
) -> Self {
|
||||
let parent = if pid == 0 {
|
||||
Weak::new()
|
||||
} else {
|
||||
let current_process = current!();
|
||||
Arc::downgrade(¤t_process)
|
||||
};
|
||||
let children = BTreeMap::new();
|
||||
let waiting_children = WaitQueue::new();
|
||||
let poll_queue = WaitQueue::new();
|
||||
|
@ -161,20 +153,6 @@ impl 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(
|
||||
elf_path: CString,
|
||||
elf_file_content: &'static [u8],
|
||||
|
@ -185,7 +163,12 @@ impl Process {
|
|||
let weak_process = weak_process_ref.clone();
|
||||
let cloned_filename = Some(elf_path.clone());
|
||||
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||
<<<<<<< HEAD
|
||||
let thread = Thread::new_posix_thread_from_elf(
|
||||
=======
|
||||
let fs = FsResolver::new();
|
||||
let thread = Thread::new_posix_thread_from_executable(
|
||||
>>>>>>> 0255134... fix
|
||||
&root_vmar,
|
||||
elf_path,
|
||||
elf_file_content,
|
||||
|
@ -194,6 +177,8 @@ impl Process {
|
|||
envp,
|
||||
);
|
||||
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 file_table = FileTable::new_with_stdio();
|
||||
let fs = FsResolver::new();
|
||||
|
@ -201,6 +186,7 @@ impl Process {
|
|||
|
||||
let process = Process::new(
|
||||
pid,
|
||||
parent,
|
||||
vec![thread],
|
||||
cloned_filename,
|
||||
Some(user_vm),
|
||||
|
@ -215,44 +201,10 @@ impl Process {
|
|||
// Set process group
|
||||
user_process.create_and_set_process_group();
|
||||
process_table::add_process(user_process.clone());
|
||||
let parent = user_process
|
||||
.parent()
|
||||
.expect("[Internel error] User process should always have parent");
|
||||
parent.add_child(user_process.clone());
|
||||
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());
|
||||
if let Some(parent) = user_process.parent() {
|
||||
parent.add_child(user_process.clone());
|
||||
}
|
||||
kernel_process
|
||||
user_process
|
||||
}
|
||||
|
||||
/// returns the pid of the process
|
||||
|
@ -326,10 +278,11 @@ impl Process {
|
|||
}
|
||||
// move children to the init process
|
||||
if !self.is_init_process() {
|
||||
let init_process = get_init_process();
|
||||
for (_, child_process) in self.children.lock().drain_filter(|_, _| true) {
|
||||
child_process.set_parent(Arc::downgrade(&init_process));
|
||||
init_process.add_child(child_process);
|
||||
if let Some(init_process) = get_init_process() {
|
||||
for (_, child_process) in self.children.lock().drain_filter(|_, _| true) {
|
||||
child_process.set_parent(Arc::downgrade(&init_process));
|
||||
init_process.add_child(child_process);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,11 +315,6 @@ impl Process {
|
|||
&self.threads
|
||||
}
|
||||
|
||||
/// yield the current process to allow other processes to run
|
||||
pub fn yield_now() {
|
||||
Task::yield_now();
|
||||
}
|
||||
|
||||
/// returns the user_vm
|
||||
pub fn user_vm(&self) -> Option<&UserVm> {
|
||||
self.user_vm.as_ref()
|
||||
|
@ -435,15 +383,6 @@ impl Process {
|
|||
}
|
||||
|
||||
/// Get the init process
|
||||
pub fn get_init_process() -> Arc<Process> {
|
||||
let mut current_process = current!();
|
||||
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
|
||||
pub fn get_init_process() -> Option<Arc<Process>> {
|
||||
process_table::pid_to_process(INIT_PROCESS_PID)
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ use crate::{
|
|||
|
||||
use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread};
|
||||
pub trait PosixThreadExt {
|
||||
fn is_posix_thread(&self) -> bool;
|
||||
fn posix_thread(&self) -> &PosixThread;
|
||||
fn new_posix_thread_from_elf(
|
||||
fn as_posix_thread(&self) -> Option<&PosixThread>;
|
||||
fn new_posix_thread_from_executable(
|
||||
root_vmar: &Vmar<Full>,
|
||||
elf_path: CString,
|
||||
elf_file_content: &'static [u8],
|
||||
|
@ -24,7 +23,7 @@ pub trait PosixThreadExt {
|
|||
|
||||
impl PosixThreadExt for Thread {
|
||||
/// 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>,
|
||||
elf_path: CString,
|
||||
elf_file_content: &'static [u8],
|
||||
|
@ -47,11 +46,7 @@ impl PosixThreadExt for Thread {
|
|||
thread_builder.build()
|
||||
}
|
||||
|
||||
fn is_posix_thread(&self) -> bool {
|
||||
self.data().downcast_ref::<PosixThread>().is_some()
|
||||
}
|
||||
|
||||
fn posix_thread(&self) -> &PosixThread {
|
||||
self.data().downcast_ref::<PosixThread>().unwrap()
|
||||
fn as_posix_thread(&self) -> Option<&PosixThread> {
|
||||
self.data().downcast_ref::<PosixThread>()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ use crate::{
|
|||
pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> {
|
||||
let current = current!();
|
||||
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 process_name = current.filename().unwrap();
|
||||
let sig_mask = posix_thread.sig_mask().lock().clone();
|
||||
|
@ -130,7 +130,7 @@ pub fn handle_user_signal(
|
|||
mask.block(current_mask.as_u64());
|
||||
}
|
||||
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
|
||||
posix_thread.sig_mask().lock().block(mask.as_u64());
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn sys_execve(
|
|||
}
|
||||
// FIXME: should we set thread name in execve?
|
||||
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 new_thread_name = ThreadName::new_from_elf_path(&elf_path)?;
|
||||
*thread_name = Some(new_thread_name);
|
||||
|
|
|
@ -11,7 +11,7 @@ pub fn sys_exit(exit_code: i32) -> Result<SyscallReturn> {
|
|||
let current = current!();
|
||||
let pid = current.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();
|
||||
posix_thread.exit(tid, exit_code)?;
|
||||
|
||||
|
|
|
@ -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)?;
|
||||
debug!("prctl cmd = {:?}", prctl_cmd);
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.posix_thread();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
match prctl_cmd {
|
||||
PrctlCmd::PR_GET_NAME(write_to_addr) => {
|
||||
let thread_name = posix_thread.thread_name().lock();
|
||||
|
|
|
@ -36,7 +36,7 @@ fn do_rt_sigprocmask(
|
|||
) -> Result<()> {
|
||||
let current = current!();
|
||||
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 mut sig_mask = posix_thread.sig_mask().lock();
|
||||
let old_sig_mask_value = sig_mask.as_u64();
|
||||
|
|
|
@ -11,7 +11,7 @@ use super::{SyscallReturn, SYS_RT_SIGRETRUN};
|
|||
pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_RT_SIGRETRUN);
|
||||
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();
|
||||
if None == *sig_context {
|
||||
return_errno_with_message!(Errno::EINVAL, "sigretrun should not been called");
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::thread::Thread;
|
||||
use crate::{log_syscall_entry, prelude::*};
|
||||
|
||||
use crate::{process::Process, syscall::SYS_SCHED_YIELD};
|
||||
use crate::syscall::SYS_SCHED_YIELD;
|
||||
|
||||
use super::SyscallReturn;
|
||||
|
||||
pub fn sys_sched_yield() -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SCHED_YIELD);
|
||||
Process::yield_now();
|
||||
Thread::yield_now();
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
|
|
@ -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)?;
|
||||
debug!("{:x?}", robust_list_head);
|
||||
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();
|
||||
*robust_list = Some(robust_list_head);
|
||||
Ok(SyscallReturn::Return(0))
|
||||
|
|
|
@ -8,7 +8,7 @@ pub fn sys_set_tid_address(tidptr: Vaddr) -> Result<SyscallReturn> {
|
|||
log_syscall_entry!(SYS_SET_TID_ADDRESS);
|
||||
debug!("tidptr = 0x{:x}", tidptr);
|
||||
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();
|
||||
if *clear_child_tid != 0 {
|
||||
// According to manuals at https://man7.org/linux/man-pages/man2/set_tid_address.2.html
|
||||
|
|
|
@ -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);
|
||||
let target_thread = thread_table::tid_to_thread(tid)
|
||||
.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();
|
||||
if pid != tgid {
|
||||
return_errno_with_message!(
|
||||
|
|
|
@ -1,28 +1,32 @@
|
|||
use jinux_frame::task::Task;
|
||||
|
||||
use crate::{prelude::*, process::Process};
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::{allocate_tid, status::ThreadStatus, thread_table, Thread};
|
||||
pub struct KernelThread {
|
||||
process: Weak<Process>,
|
||||
}
|
||||
|
||||
impl KernelThread {
|
||||
pub fn new(process: Weak<Process>) -> Self {
|
||||
Self { process }
|
||||
}
|
||||
|
||||
pub fn process(&self) -> Arc<Process> {
|
||||
self.process.upgrade().unwrap()
|
||||
}
|
||||
}
|
||||
/// This struct is used to mark a thread is a kernel thread
|
||||
pub struct KernelThread;
|
||||
|
||||
pub trait KernelThreadExt {
|
||||
/// whether the thread is a kernel thread
|
||||
fn is_kernel_thread(&self) -> bool;
|
||||
/// get the kernel_thread structure
|
||||
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
|
||||
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 {
|
||||
|
@ -34,19 +38,38 @@ impl KernelThreadExt for Thread {
|
|||
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
|
||||
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 thread = Arc::new_cyclic(|thread_ref| {
|
||||
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 kernel_thread = KernelThread::new(process);
|
||||
let kernel_thread = KernelThread;
|
||||
Thread::new(tid, task, kernel_thread, status)
|
||||
});
|
||||
thread_table::add_thread(thread.clone());
|
||||
thread
|
||||
}
|
||||
|
||||
fn join(&self) {
|
||||
loop {
|
||||
let status = self.status.lock();
|
||||
if status.is_exited() {
|
||||
return;
|
||||
} else {
|
||||
drop(status);
|
||||
Thread::yield_now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue