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",
"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"

View File

@ -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!()
}

View File

@ -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(&current);
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(

View File

@ -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(&current_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)
}

View File

@ -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>()
}
}

View File

@ -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());

View File

@ -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);

View File

@ -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)?;

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)?;
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();

View File

@ -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();

View File

@ -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");

View File

@ -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))
}

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)?;
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))

View File

@ -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

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);
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!(

View File

@ -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();
}
}
}
}