mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
spilt kernel thread from process
This commit is contained in:
parent
8f8649bfc1
commit
a084c3b687
21
src/Cargo.lock
generated
21
src/Cargo.lock
generated
@ -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"
|
||||||
|
@ -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!()
|
||||||
}
|
}
|
||||||
|
@ -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(¤t);
|
||||||
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(
|
||||||
|
@ -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(¤t_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
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)?;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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");
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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!(
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user