support returning Err when creating posix thread

This commit is contained in:
Jianfeng Jiang 2023-03-14 19:41:08 +08:00 committed by Tate, Hongliang Tian
parent 330e495560
commit 45427da50e
3 changed files with 47 additions and 53 deletions

View File

@ -86,7 +86,7 @@ pub fn run_first_process() -> ! {
unreachable!() unreachable!()
} }
fn run_busybox() -> Result<()> { fn run_busybox() -> Result<Arc<Process>> {
let executable_path = "/busybox/busybox"; let executable_path = "/busybox/busybox";
let argv = ["sh", "-l"]; let argv = ["sh", "-l"];
let envp = [ let envp = [
@ -108,6 +108,5 @@ fn run_busybox() -> Result<()> {
.collect(); .collect();
println!(""); println!("");
println!("BusyBox v1.35.0 built-in shell (ash)\n"); println!("BusyBox v1.35.0 built-in shell (ash)\n");
Process::spawn_user_process(executable_path, argv, envp); Process::spawn_user_process(executable_path, argv, envp)
Ok(())
} }

View File

@ -14,7 +14,7 @@ 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::{thread_table, Thread}; use crate::thread::{allocate_tid, 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;
use jinux_frame::sync::WaitQueue; use jinux_frame::sync::WaitQueue;
@ -140,63 +140,58 @@ impl Process {
executable_path: &str, executable_path: &str,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Arc<Self> { ) -> Result<Arc<Self>> {
let process = Process::create_user_process(executable_path, argv, envp); let process = Process::create_user_process(executable_path, argv, envp)?;
// FIXME: How to determine the fg process group? // FIXME: How to determine the fg process group?
let pgid = process.pgid(); let pgid = process.pgid();
// FIXME: tty should be a parameter? // FIXME: tty should be a parameter?
let tty = get_n_tty(); let tty = get_n_tty();
tty.set_fg(pgid); tty.set_fg(pgid);
process.run(); process.run();
process Ok(process)
} }
fn create_user_process( fn create_user_process(
executable_path: &str, executable_path: &str,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Arc<Self> { ) -> Result<Arc<Self>> {
let user_process = Arc::new_cyclic(|weak_process_ref| { let root_vmar = Vmar::<Full>::new_root()?;
let weak_process = weak_process_ref.clone(); let fs = FsResolver::new();
let root_vmar = Vmar::<Full>::new_root().unwrap(); let pid = allocate_tid();
let fs = FsResolver::new(); let parent = Weak::new();
let thread = Thread::new_posix_thread_from_executable( let process_group = Weak::new();
&root_vmar, let user_vm = UserVm::new();
&fs, let file_table = FileTable::new_with_stdio();
executable_path, let sig_dispositions = SigDispositions::new();
weak_process, let user_process = Arc::new(Process::new(
argv, pid,
envp, parent,
); vec![],
let pid = thread.tid(); Some(executable_path.to_string()),
// spawn process will be called in a kernel thread, so the parent process is always none. Some(user_vm),
let parent = Weak::new(); Arc::new(root_vmar),
let user_vm = UserVm::new(); process_group,
let file_table = FileTable::new_with_stdio(); Arc::new(Mutex::new(file_table)),
let fs = FsResolver::new(); Arc::new(RwLock::new(fs)),
let sig_dispositions = SigDispositions::new(); Arc::new(Mutex::new(sig_dispositions)),
));
let thread = Thread::new_posix_thread_from_executable(
pid,
&user_process.root_vmar(),
&user_process.fs().read(),
executable_path,
Arc::downgrade(&user_process),
argv,
envp,
)?;
user_process.threads().lock().push(thread);
let process = Process::new(
pid,
parent,
vec![thread],
Some(executable_path.to_string()),
Some(user_vm),
Arc::new(root_vmar),
Weak::new(),
Arc::new(Mutex::new(file_table)),
Arc::new(RwLock::new(fs)),
Arc::new(Mutex::new(sig_dispositions)),
);
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());
if let Some(parent) = user_process.parent() { Ok(user_process)
parent.add_child(user_process.clone());
}
user_process
} }
/// returns the pid of the process /// returns the pid of the process

View File

@ -5,7 +5,7 @@ use crate::{
prelude::*, prelude::*,
process::{program_loader::load_program_to_root_vmar, Process}, process::{program_loader::load_program_to_root_vmar, Process},
rights::Full, rights::Full,
thread::{allocate_tid, Thread}, thread::{Thread, Tid},
vm::vmar::Vmar, vm::vmar::Vmar,
}; };
@ -13,25 +13,27 @@ use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread};
pub trait PosixThreadExt { pub trait PosixThreadExt {
fn as_posix_thread(&self) -> Option<&PosixThread>; fn as_posix_thread(&self) -> Option<&PosixThread>;
fn new_posix_thread_from_executable( fn new_posix_thread_from_executable(
tid: Tid,
root_vmar: &Vmar<Full>, root_vmar: &Vmar<Full>,
fs_resolver: &FsResolver, fs_resolver: &FsResolver,
executable_path: &str, executable_path: &str,
process: Weak<Process>, process: Weak<Process>,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Arc<Self>; ) -> Result<Arc<Self>>;
} }
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_executable( fn new_posix_thread_from_executable(
tid: Tid,
root_vmar: &Vmar<Full>, root_vmar: &Vmar<Full>,
fs_resolver: &FsResolver, fs_resolver: &FsResolver,
executable_path: &str, executable_path: &str,
process: Weak<Process>, process: Weak<Process>,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Arc<Self> { ) -> Result<Arc<Self>> {
let elf_load_info = load_program_to_root_vmar( let elf_load_info = load_program_to_root_vmar(
root_vmar, root_vmar,
executable_path.to_string(), executable_path.to_string(),
@ -39,20 +41,18 @@ impl PosixThreadExt for Thread {
envp, envp,
fs_resolver, fs_resolver,
1, 1,
) )?;
.unwrap();
let vm_space = root_vmar.vm_space().clone(); let vm_space = root_vmar.vm_space().clone();
let mut cpu_ctx = CpuContext::default(); let mut cpu_ctx = CpuContext::default();
cpu_ctx.set_rip(elf_load_info.entry_point() as _); cpu_ctx.set_rip(elf_load_info.entry_point() as _);
cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _); cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _);
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx)); let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
let thread_name = Some(ThreadName::new_from_executable_path(executable_path).unwrap()); let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?);
let tid = allocate_tid();
let thread_builder = PosixThreadBuilder::new(tid, user_space) let thread_builder = PosixThreadBuilder::new(tid, user_space)
.thread_name(thread_name) .thread_name(thread_name)
.process(process); .process(process);
thread_builder.build() Ok(thread_builder.build())
} }
fn as_posix_thread(&self) -> Option<&PosixThread> { fn as_posix_thread(&self) -> Option<&PosixThread> {