mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
refactor process implementation
This commit is contained in:
@ -38,6 +38,21 @@ pub struct CpuContext {
|
|||||||
/// trap information, this field is all zero when it is syscall
|
/// trap information, this field is all zero when it is syscall
|
||||||
pub trap_information: TrapInformation,
|
pub trap_information: TrapInformation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CpuContext {
|
||||||
|
pub fn set_rax(&mut self, rax: u64) {
|
||||||
|
self.gp_regs.rax = rax;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_rsp(&mut self, rsp: u64) {
|
||||||
|
self.gp_regs.rsp = rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_rip(&mut self, rip: u64) {
|
||||||
|
self.gp_regs.rip = rip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Copy, Debug)]
|
#[derive(Clone, Default, Copy, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TrapInformation {
|
pub struct TrapInformation {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use super::{page_table::PageTable, *};
|
use super::{page_table::PageTable, *};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vm::VmIo;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::PAGE_SIZE,
|
config::PAGE_SIZE,
|
||||||
mm::address::is_aligned,
|
mm::address::is_aligned,
|
||||||
|
@ -5,7 +5,8 @@ mod scheduler;
|
|||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
mod task;
|
mod task;
|
||||||
|
|
||||||
pub(crate) use self::processor::{get_idle_task_cx_ptr, schedule};
|
pub(crate) use self::processor::get_idle_task_cx_ptr;
|
||||||
|
pub use self::processor::schedule;
|
||||||
pub use self::scheduler::{set_scheduler, Scheduler};
|
pub use self::scheduler::{set_scheduler, Scheduler};
|
||||||
pub(crate) use self::task::context_switch;
|
pub(crate) use self::task::context_switch;
|
||||||
pub(crate) use self::task::TaskContext;
|
pub(crate) use self::task::TaskContext;
|
||||||
|
@ -222,7 +222,7 @@ impl Task {
|
|||||||
Ok(Arc::new(result))
|
Ok(Arc::new(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_to_scheduler(self: &Arc<Self>) {
|
pub fn run(self: &Arc<Self>) {
|
||||||
switch_to_task(self.clone());
|
switch_to_task(self.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ use crate::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
user_apps::{get_busybox_app, UserApp},
|
user_apps::{get_busybox_app, UserApp},
|
||||||
};
|
};
|
||||||
use jinux_frame::{info, println};
|
|
||||||
use process::Process;
|
use process::Process;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -42,6 +41,7 @@ pub mod prelude;
|
|||||||
mod process;
|
mod process;
|
||||||
pub mod rights;
|
pub mod rights;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
pub mod thread;
|
||||||
pub mod tty;
|
pub mod tty;
|
||||||
mod user_apps;
|
mod user_apps;
|
||||||
mod util;
|
mod util;
|
||||||
@ -63,9 +63,9 @@ pub fn init_process() {
|
|||||||
println!("[kernel] Hello world from kernel!");
|
println!("[kernel] Hello world from kernel!");
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let pid = current.pid();
|
let pid = current.pid();
|
||||||
info!("current pid = {}", pid);
|
debug!("current pid = {}", pid);
|
||||||
let ppid = current.parent().unwrap().pid();
|
let ppid = current.parent().unwrap().pid();
|
||||||
info!("current ppid = {}", ppid);
|
debug!("current ppid = {}", ppid);
|
||||||
});
|
});
|
||||||
info!(
|
info!(
|
||||||
"[jinux-std/lib.rs] spawn kernel process, pid = {}",
|
"[jinux-std/lib.rs] spawn kernel process, pid = {}",
|
||||||
|
@ -6,7 +6,8 @@ use jinux_frame::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{new_pid, signal::sig_queues::SigQueues, table, task::create_new_task},
|
process::{new_pid, signal::sig_queues::SigQueues, table},
|
||||||
|
thread::Thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Process;
|
use super::Process;
|
||||||
@ -127,15 +128,17 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
|
|||||||
|
|
||||||
let child = Arc::new_cyclic(|child_process_ref| {
|
let child = Arc::new_cyclic(|child_process_ref| {
|
||||||
let weak_child_process = child_process_ref.clone();
|
let weak_child_process = child_process_ref.clone();
|
||||||
let child_task = create_new_task(child_user_space.clone(), weak_child_process);
|
let tid = child_pid;
|
||||||
|
let child_thread =
|
||||||
|
Thread::new_user_thread(tid, child_user_space.clone(), weak_child_process);
|
||||||
Process::new(
|
Process::new(
|
||||||
child_pid,
|
child_pid,
|
||||||
child_task,
|
vec![child_thread],
|
||||||
child_file_name,
|
child_file_name,
|
||||||
child_user_vm,
|
child_user_vm,
|
||||||
Some(child_user_space),
|
// Some(child_user_space),
|
||||||
Some(child_root_vmar),
|
Some(child_root_vmar),
|
||||||
None,
|
Weak::new(),
|
||||||
child_file_table,
|
child_file_table,
|
||||||
child_sig_dispositions,
|
child_sig_dispositions,
|
||||||
child_sig_queues,
|
child_sig_queues,
|
||||||
@ -143,13 +146,7 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
// Inherit parent's process group
|
// Inherit parent's process group
|
||||||
let parent_process_group = current
|
let parent_process_group = current.process_group().lock().upgrade().unwrap();
|
||||||
.process_group()
|
|
||||||
.lock()
|
|
||||||
.as_ref()
|
|
||||||
.map(|ppgrp| ppgrp.upgrade())
|
|
||||||
.flatten()
|
|
||||||
.unwrap();
|
|
||||||
parent_process_group.add_process(child.clone());
|
parent_process_group.add_process(child.clone());
|
||||||
child.set_process_group(Arc::downgrade(&parent_process_group));
|
child.set_process_group(Arc::downgrade(&parent_process_group));
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ use self::signal::sig_mask::SigMask;
|
|||||||
use self::signal::sig_queues::SigQueues;
|
use self::signal::sig_queues::SigQueues;
|
||||||
use self::signal::signals::kernel::KernelSignal;
|
use self::signal::signals::kernel::KernelSignal;
|
||||||
use self::status::ProcessStatus;
|
use self::status::ProcessStatus;
|
||||||
use self::task::create_user_task_from_elf;
|
|
||||||
use crate::fs::file_table::FileTable;
|
use crate::fs::file_table::FileTable;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
|
use crate::thread::Thread;
|
||||||
use crate::tty::get_console;
|
use crate::tty::get_console;
|
||||||
use crate::vm::vmar::Vmar;
|
use crate::vm::vmar::Vmar;
|
||||||
use jinux_frame::sync::WaitQueue;
|
use jinux_frame::sync::WaitQueue;
|
||||||
use jinux_frame::{task::Task, user::UserSpace};
|
use jinux_frame::task::Task;
|
||||||
|
|
||||||
pub mod clone;
|
pub mod clone;
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
@ -30,7 +30,6 @@ pub mod process_vm;
|
|||||||
pub mod signal;
|
pub mod signal;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod task;
|
|
||||||
pub mod wait;
|
pub mod wait;
|
||||||
|
|
||||||
static PID_ALLOCATOR: AtomicI32 = AtomicI32::new(0);
|
static PID_ALLOCATOR: AtomicI32 = AtomicI32::new(0);
|
||||||
@ -44,9 +43,9 @@ pub type ExitCode = i32;
|
|||||||
pub struct Process {
|
pub struct Process {
|
||||||
// Immutable Part
|
// Immutable Part
|
||||||
pid: Pid,
|
pid: Pid,
|
||||||
task: Arc<Task>,
|
threads: Vec<Arc<Thread>>,
|
||||||
filename: Option<CString>,
|
filename: Option<CString>,
|
||||||
user_space: Option<Arc<UserSpace>>,
|
// user_space: Option<Arc<UserSpace>>,
|
||||||
user_vm: Option<UserVm>,
|
user_vm: Option<UserVm>,
|
||||||
root_vmar: Option<Vmar<Full>>,
|
root_vmar: Option<Vmar<Full>>,
|
||||||
/// wait for child status changed
|
/// wait for child status changed
|
||||||
@ -60,11 +59,11 @@ pub struct Process {
|
|||||||
/// Process status
|
/// Process status
|
||||||
status: Mutex<ProcessStatus>,
|
status: Mutex<ProcessStatus>,
|
||||||
/// Parent process
|
/// Parent process
|
||||||
parent: Mutex<Option<Weak<Process>>>,
|
parent: Mutex<Weak<Process>>,
|
||||||
/// Children processes
|
/// Children processes
|
||||||
children: Mutex<BTreeMap<Pid, Arc<Process>>>,
|
children: Mutex<BTreeMap<Pid, Arc<Process>>>,
|
||||||
/// Process group
|
/// Process group
|
||||||
process_group: Mutex<Option<Weak<ProcessGroup>>>,
|
process_group: Mutex<Weak<ProcessGroup>>,
|
||||||
/// Process name
|
/// Process name
|
||||||
process_name: Mutex<Option<ProcessName>>,
|
process_name: Mutex<Option<ProcessName>>,
|
||||||
/// File table
|
/// File table
|
||||||
@ -82,35 +81,28 @@ pub struct Process {
|
|||||||
impl Process {
|
impl Process {
|
||||||
/// returns the current process
|
/// returns the current process
|
||||||
pub fn current() -> Arc<Process> {
|
pub fn current() -> Arc<Process> {
|
||||||
let task = Task::current();
|
let current_thread = Thread::current();
|
||||||
let process = task
|
current_thread.process()
|
||||||
.data()
|
|
||||||
.downcast_ref::<Weak<Process>>()
|
|
||||||
.expect("[Internal Error] task data should points to weak<process>");
|
|
||||||
process
|
|
||||||
.upgrade()
|
|
||||||
.expect("[Internal Error] current process cannot be None")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// create a new process(not schedule it)
|
/// create a new process(not schedule it)
|
||||||
pub fn new(
|
pub fn new(
|
||||||
pid: Pid,
|
pid: Pid,
|
||||||
task: Arc<Task>,
|
threads: Vec<Arc<Thread>>,
|
||||||
exec_filename: Option<CString>,
|
exec_filename: Option<CString>,
|
||||||
user_vm: Option<UserVm>,
|
user_vm: Option<UserVm>,
|
||||||
user_space: Option<Arc<UserSpace>>,
|
|
||||||
root_vmar: Option<Vmar<Full>>,
|
root_vmar: Option<Vmar<Full>>,
|
||||||
process_group: Option<Weak<ProcessGroup>>,
|
process_group: Weak<ProcessGroup>,
|
||||||
file_table: FileTable,
|
file_table: FileTable,
|
||||||
sig_dispositions: SigDispositions,
|
sig_dispositions: SigDispositions,
|
||||||
sig_queues: SigQueues,
|
sig_queues: SigQueues,
|
||||||
sig_mask: SigMask,
|
sig_mask: SigMask,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let parent = if pid == 0 {
|
let parent = if pid == 0 {
|
||||||
None
|
Weak::new()
|
||||||
} else {
|
} else {
|
||||||
let current_process = current!();
|
let current_process = current!();
|
||||||
Some(Arc::downgrade(¤t_process))
|
Arc::downgrade(¤t_process)
|
||||||
};
|
};
|
||||||
let children = BTreeMap::new();
|
let children = BTreeMap::new();
|
||||||
let waiting_children = WaitQueue::new();
|
let waiting_children = WaitQueue::new();
|
||||||
@ -122,9 +114,8 @@ impl Process {
|
|||||||
});
|
});
|
||||||
Self {
|
Self {
|
||||||
pid,
|
pid,
|
||||||
task,
|
threads,
|
||||||
filename: exec_filename,
|
filename: exec_filename,
|
||||||
user_space,
|
|
||||||
user_vm,
|
user_vm,
|
||||||
root_vmar,
|
root_vmar,
|
||||||
waiting_children,
|
waiting_children,
|
||||||
@ -162,7 +153,7 @@ impl Process {
|
|||||||
// FIXME: How to determine the fg process group?
|
// FIXME: How to determine the fg process group?
|
||||||
let pgid = process.pgid();
|
let pgid = process.pgid();
|
||||||
get_console().set_fg(pgid);
|
get_console().set_fg(pgid);
|
||||||
process.send_to_scheduler();
|
process.run();
|
||||||
process
|
process
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +167,7 @@ impl Process {
|
|||||||
current!().exit(0);
|
current!().exit(0);
|
||||||
};
|
};
|
||||||
let process = Process::create_kernel_process(process_fn);
|
let process = Process::create_kernel_process(process_fn);
|
||||||
process.send_to_scheduler();
|
process.run();
|
||||||
process
|
process
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,15 +183,16 @@ impl Process {
|
|||||||
let weak_process = weak_process_ref.clone();
|
let weak_process = weak_process_ref.clone();
|
||||||
let cloned_filename = Some(filename.clone());
|
let cloned_filename = Some(filename.clone());
|
||||||
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
let task = create_user_task_from_elf(
|
let tid = pid;
|
||||||
|
let thread = Thread::new_user_thread_from_elf(
|
||||||
&root_vmar,
|
&root_vmar,
|
||||||
filename,
|
filename,
|
||||||
elf_file_content,
|
elf_file_content,
|
||||||
weak_process,
|
weak_process,
|
||||||
|
tid,
|
||||||
argv,
|
argv,
|
||||||
envp,
|
envp,
|
||||||
);
|
);
|
||||||
let user_space = task.user_space().map(|user_space| user_space.clone());
|
|
||||||
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 sig_dispositions = SigDispositions::new();
|
let sig_dispositions = SigDispositions::new();
|
||||||
@ -208,12 +200,11 @@ impl Process {
|
|||||||
let sig_mask = SigMask::new_empty();
|
let sig_mask = SigMask::new_empty();
|
||||||
Process::new(
|
Process::new(
|
||||||
pid,
|
pid,
|
||||||
task,
|
vec![thread],
|
||||||
cloned_filename,
|
cloned_filename,
|
||||||
Some(user_vm),
|
Some(user_vm),
|
||||||
user_space,
|
|
||||||
Some(root_vmar),
|
Some(root_vmar),
|
||||||
None,
|
Weak::new(),
|
||||||
file_table,
|
file_table,
|
||||||
sig_dispositions,
|
sig_dispositions,
|
||||||
sig_queues,
|
sig_queues,
|
||||||
@ -237,19 +228,19 @@ impl Process {
|
|||||||
let pid = new_pid();
|
let pid = new_pid();
|
||||||
let kernel_process = Arc::new_cyclic(|weak_process_ref| {
|
let kernel_process = Arc::new_cyclic(|weak_process_ref| {
|
||||||
let weak_process = weak_process_ref.clone();
|
let weak_process = weak_process_ref.clone();
|
||||||
let task = Task::new(task_fn, weak_process, None).expect("spawn kernel task failed");
|
let tid = pid;
|
||||||
|
let thread = Thread::new_kernel_thread(tid, task_fn, weak_process);
|
||||||
let file_table = FileTable::new();
|
let file_table = FileTable::new();
|
||||||
let sig_dispositions = SigDispositions::new();
|
let sig_dispositions = SigDispositions::new();
|
||||||
let sig_queues = SigQueues::new();
|
let sig_queues = SigQueues::new();
|
||||||
let sig_mask = SigMask::new_empty();
|
let sig_mask = SigMask::new_empty();
|
||||||
Process::new(
|
Process::new(
|
||||||
pid,
|
pid,
|
||||||
task,
|
vec![thread],
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
Weak::new(),
|
||||||
file_table,
|
file_table,
|
||||||
sig_dispositions,
|
sig_dispositions,
|
||||||
sig_queues,
|
sig_queues,
|
||||||
@ -271,13 +262,7 @@ impl Process {
|
|||||||
|
|
||||||
/// returns the process group id of the process
|
/// returns the process group id of the process
|
||||||
pub fn pgid(&self) -> Pgid {
|
pub fn pgid(&self) -> Pgid {
|
||||||
if let Some(process_group) = self
|
if let Some(process_group) = self.process_group.lock().upgrade() {
|
||||||
.process_group
|
|
||||||
.lock()
|
|
||||||
.as_ref()
|
|
||||||
.map(|process_group| process_group.upgrade())
|
|
||||||
.flatten()
|
|
||||||
{
|
|
||||||
process_group.pgid()
|
process_group.pgid()
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
@ -288,7 +273,7 @@ impl Process {
|
|||||||
&self.process_name
|
&self.process_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_group(&self) -> &Mutex<Option<Weak<ProcessGroup>>> {
|
pub fn process_group(&self) -> &Mutex<Weak<ProcessGroup>> {
|
||||||
&self.process_group
|
&self.process_group
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,18 +288,16 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_parent(&self, parent: Weak<Process>) {
|
fn set_parent(&self, parent: Weak<Process>) {
|
||||||
let _ = self.parent.lock().insert(parent);
|
*self.parent.lock() = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set process group for current process. If old process group exists,
|
/// Set process group for current process. If old process group exists,
|
||||||
/// remove current process from old process group.
|
/// remove current process from old process group.
|
||||||
pub fn set_process_group(&self, process_group: Weak<ProcessGroup>) {
|
pub fn set_process_group(&self, process_group: Weak<ProcessGroup>) {
|
||||||
if let Some(old_process_group) = &*self.process_group().lock() {
|
if let Some(old_process_group) = self.process_group.lock().upgrade() {
|
||||||
if let Some(old_process_group) = old_process_group.upgrade() {
|
old_process_group.remove_process(self.pid());
|
||||||
old_process_group.remove_process(self.pid());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let _ = self.process_group.lock().insert(process_group);
|
*self.process_group.lock() = process_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_table(&self) -> &Mutex<FileTable> {
|
pub fn file_table(&self) -> &Mutex<FileTable> {
|
||||||
@ -331,11 +314,7 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent(&self) -> Option<Arc<Process>> {
|
pub fn parent(&self) -> Option<Arc<Process>> {
|
||||||
self.parent
|
self.parent.lock().upgrade()
|
||||||
.lock()
|
|
||||||
.as_ref()
|
|
||||||
.map(|parent| parent.upgrade())
|
|
||||||
.flatten()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exit process.
|
/// Exit process.
|
||||||
@ -369,8 +348,10 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// start to run current process
|
/// start to run current process
|
||||||
pub fn send_to_scheduler(self: &Arc<Self>) {
|
pub fn run(&self) {
|
||||||
self.task.send_to_scheduler();
|
for thread in &self.threads {
|
||||||
|
thread.run()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// yield the current process to allow other processes to run
|
/// yield the current process to allow other processes to run
|
||||||
@ -378,11 +359,6 @@ impl Process {
|
|||||||
Task::yield_now();
|
Task::yield_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the userspace
|
|
||||||
pub fn user_space(&self) -> Option<&Arc<UserSpace>> {
|
|
||||||
self.user_space.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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()
|
||||||
@ -407,10 +383,8 @@ impl Process {
|
|||||||
let child_process = self.children.lock().remove(&pid).unwrap();
|
let child_process = self.children.lock().remove(&pid).unwrap();
|
||||||
assert!(child_process.status().lock().is_zombie());
|
assert!(child_process.status().lock().is_zombie());
|
||||||
table::remove_process(child_process.pid());
|
table::remove_process(child_process.pid());
|
||||||
if let Some(process_group) = child_process.process_group().lock().as_ref() {
|
if let Some(process_group) = child_process.process_group().lock().upgrade() {
|
||||||
if let Some(process_group) = process_group.upgrade() {
|
process_group.remove_process(child_process.pid);
|
||||||
process_group.remove_process(child_process.pid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
child_process.exit_code()
|
child_process.exit_code()
|
||||||
}
|
}
|
||||||
@ -456,9 +430,7 @@ pub fn get_init_process() -> Arc<Process> {
|
|||||||
let process = current_process
|
let process = current_process
|
||||||
.parent
|
.parent
|
||||||
.lock()
|
.lock()
|
||||||
.as_ref()
|
.upgrade()
|
||||||
.map(|current| current.upgrade())
|
|
||||||
.flatten()
|
|
||||||
.expect("[Internal Error] init process cannot be None");
|
.expect("[Internal Error] init process cannot be None");
|
||||||
current_process = process;
|
current_process = process;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> {
|
|||||||
flags,
|
flags,
|
||||||
restorer_addr,
|
restorer_addr,
|
||||||
mask,
|
mask,
|
||||||
} => handle_user_signal_handler(
|
} => handle_user_signal(
|
||||||
sig_num,
|
sig_num,
|
||||||
handler_addr,
|
handler_addr,
|
||||||
flags,
|
flags,
|
||||||
@ -95,7 +95,7 @@ pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_user_signal_handler(
|
pub fn handle_user_signal(
|
||||||
sig_num: SigNum,
|
sig_num: SigNum,
|
||||||
handler_addr: Vaddr,
|
handler_addr: Vaddr,
|
||||||
flags: SigActionFlags,
|
flags: SigActionFlags,
|
||||||
|
@ -25,7 +25,7 @@ pub fn sys_clone(
|
|||||||
let child_pid = child_process.pid();
|
let child_pid = child_process.pid();
|
||||||
let pid = current!().pid();
|
let pid = current!().pid();
|
||||||
debug!("*********schedule child process, pid = {}**********", pid);
|
debug!("*********schedule child process, pid = {}**********", pid);
|
||||||
child_process.send_to_scheduler();
|
child_process.run();
|
||||||
debug!("*********return to parent process, pid = {}*********", pid);
|
debug!("*********return to parent process, pid = {}*********", pid);
|
||||||
Ok(SyscallReturn::Return(child_pid as _))
|
Ok(SyscallReturn::Return(child_pid as _))
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ fn fork(parent_context: CpuContext) -> Arc<Process> {
|
|||||||
let child = clone_child(parent_context, clone_args).unwrap();
|
let child = clone_child(parent_context, clone_args).unwrap();
|
||||||
let pid = current.pid();
|
let pid = current.pid();
|
||||||
debug!("*********schedule child process, pid = {}**********", pid);
|
debug!("*********schedule child process, pid = {}**********", pid);
|
||||||
child.send_to_scheduler();
|
child.run();
|
||||||
debug!("*********return to parent process, pid = {}*********", pid);
|
debug!("*********return to parent process, pid = {}*********", pid);
|
||||||
child
|
child
|
||||||
}
|
}
|
||||||
|
@ -210,13 +210,13 @@ pub fn handle_syscall(context: &mut CpuContext) {
|
|||||||
Ok(return_value) => {
|
Ok(return_value) => {
|
||||||
debug!("syscall return: {:?}", return_value);
|
debug!("syscall return: {:?}", return_value);
|
||||||
if let SyscallReturn::Return(return_value) = return_value {
|
if let SyscallReturn::Return(return_value) = return_value {
|
||||||
context.gp_regs.rax = return_value as u64;
|
context.set_rax(return_value as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!("syscall return error: {:?}", err);
|
debug!("syscall return error: {:?}", err);
|
||||||
let errno = err.error() as i32;
|
let errno = err.error() as i32;
|
||||||
context.gp_regs.rax = (-errno) as u64
|
context.set_rax((-errno) as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,13 @@ 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 = current!();
|
let current = current!();
|
||||||
let sig_context = current.sig_context().lock().pop_back().unwrap();
|
let sig_context_addr = current.sig_context().lock().pop_back().unwrap();
|
||||||
let ucontext = read_val_from_user::<ucontext_t>(sig_context)?;
|
println!("sig context address = 0x{:x}", sig_context_addr);
|
||||||
|
let stack_value = read_val_from_user::<Vaddr>((context.gp_regs.rsp) as usize)?;
|
||||||
|
println!("stack value = 0x{:x}", stack_value);
|
||||||
|
// debug_assert!(sig_context_addr == stack_value);
|
||||||
|
// println!("stack value = 0x{:x}", sig_context);
|
||||||
|
let ucontext = read_val_from_user::<ucontext_t>(sig_context_addr)?;
|
||||||
context.gp_regs = ucontext.uc_mcontext.inner.gp_regs;
|
context.gp_regs = ucontext.uc_mcontext.inner.gp_regs;
|
||||||
// unblock sig mask
|
// unblock sig mask
|
||||||
let sig_mask = ucontext.uc_sigmask;
|
let sig_mask = ucontext.uc_sigmask;
|
||||||
|
93
src/services/libs/jinux-std/src/thread/mod.rs
Normal file
93
src/services/libs/jinux-std/src/thread/mod.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//! Posix thread implementation
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
prelude::*,
|
||||||
|
process::{elf::load_elf_to_root_vmar, Process},
|
||||||
|
rights::Full,
|
||||||
|
vm::vmar::Vmar,
|
||||||
|
};
|
||||||
|
use jinux_frame::{cpu::CpuContext, task::Task, user::UserSpace};
|
||||||
|
|
||||||
|
use self::task::create_new_user_task;
|
||||||
|
|
||||||
|
pub mod task;
|
||||||
|
|
||||||
|
pub type Tid = i32;
|
||||||
|
|
||||||
|
/// A thread is a wrapper on top of task.
|
||||||
|
pub struct Thread {
|
||||||
|
/// Thread id
|
||||||
|
tid: Tid,
|
||||||
|
/// Low-level info
|
||||||
|
task: Arc<Task>,
|
||||||
|
/// The process. FIXME: should we store the process info here?
|
||||||
|
process: Weak<Process>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Thread {
|
||||||
|
pub fn new_user_thread_from_elf(
|
||||||
|
root_vmar: &Vmar<Full>,
|
||||||
|
filename: CString,
|
||||||
|
elf_file_content: &'static [u8],
|
||||||
|
process: Weak<Process>,
|
||||||
|
tid: Tid,
|
||||||
|
argv: Vec<CString>,
|
||||||
|
envp: Vec<CString>,
|
||||||
|
) -> Arc<Self> {
|
||||||
|
let elf_load_info =
|
||||||
|
load_elf_to_root_vmar(filename, elf_file_content, &root_vmar, argv, envp)
|
||||||
|
.expect("Load Elf failed");
|
||||||
|
let vm_space = root_vmar.vm_space().clone();
|
||||||
|
let mut cpu_ctx = CpuContext::default();
|
||||||
|
cpu_ctx.set_rip(elf_load_info.entry_point());
|
||||||
|
cpu_ctx.set_rsp(elf_load_info.user_stack_top());
|
||||||
|
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
|
||||||
|
Thread::new_user_thread(tid, user_space, process)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_user_thread(
|
||||||
|
tid: Tid,
|
||||||
|
user_space: Arc<UserSpace>,
|
||||||
|
process: Weak<Process>,
|
||||||
|
) -> Arc<Self> {
|
||||||
|
Arc::new_cyclic(|thread_ref| {
|
||||||
|
let task = create_new_user_task(user_space, thread_ref.clone());
|
||||||
|
Thread { tid, task, process }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_kernel_thread<F>(tid: Tid, task_fn: F, process: Weak<Process>) -> Arc<Self>
|
||||||
|
where
|
||||||
|
F: Fn() + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
Arc::new_cyclic(|thread_ref| {
|
||||||
|
let weal_thread = thread_ref.clone();
|
||||||
|
let task = Task::new(task_fn, weal_thread, None).unwrap();
|
||||||
|
Thread { tid, task, process }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current() -> Arc<Self> {
|
||||||
|
let task = Task::current();
|
||||||
|
let thread = task
|
||||||
|
.data()
|
||||||
|
.downcast_ref::<Weak<Thread>>()
|
||||||
|
.expect("[Internal Error] task data should points to weak<process>");
|
||||||
|
thread
|
||||||
|
.upgrade()
|
||||||
|
.expect("[Internal Error] current process cannot be None")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process(&self) -> Arc<Process> {
|
||||||
|
self.process.upgrade().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add inner task to the run queue of scheduler. Note this does not means the thread will run at once.
|
||||||
|
pub fn run(&self) {
|
||||||
|
self.task.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yield_now() {
|
||||||
|
Task::yield_now()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
use core::sync::atomic::AtomicUsize;
|
|
||||||
|
|
||||||
use jinux_frame::{
|
use jinux_frame::{
|
||||||
cpu::CpuContext,
|
cpu::CpuContext,
|
||||||
task::Task,
|
task::Task,
|
||||||
@ -9,46 +7,20 @@ use jinux_frame::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{exception::handle_exception, signal::handle_pending_signal},
|
process::{exception::handle_exception, signal::handle_pending_signal},
|
||||||
rights::Full,
|
syscall::handle_syscall,
|
||||||
vm::vmar::Vmar,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::syscall::handle_syscall;
|
use super::Thread;
|
||||||
|
|
||||||
use super::{elf::load_elf_to_root_vmar, Process};
|
|
||||||
|
|
||||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
|
|
||||||
pub fn create_user_task_from_elf(
|
|
||||||
root_vmar: &Vmar<Full>,
|
|
||||||
filename: CString,
|
|
||||||
elf_file_content: &'static [u8],
|
|
||||||
parent: Weak<Process>,
|
|
||||||
argv: Vec<CString>,
|
|
||||||
envp: Vec<CString>,
|
|
||||||
) -> Arc<Task> {
|
|
||||||
let elf_load_info = load_elf_to_root_vmar(filename, elf_file_content, &root_vmar, argv, envp)
|
|
||||||
.expect("Load Elf failed");
|
|
||||||
let vm_space = root_vmar.vm_space().clone();
|
|
||||||
let mut cpu_ctx = CpuContext::default();
|
|
||||||
// set entry point
|
|
||||||
cpu_ctx.gp_regs.rip = elf_load_info.entry_point();
|
|
||||||
// set user stack
|
|
||||||
cpu_ctx.gp_regs.rsp = elf_load_info.user_stack_top();
|
|
||||||
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
|
|
||||||
create_new_task(user_space, parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// create new task with userspace and parent process
|
/// create new task with userspace and parent process
|
||||||
pub fn create_new_task(userspace: Arc<UserSpace>, parent: Weak<Process>) -> Arc<Task> {
|
pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>) -> Arc<Task> {
|
||||||
fn user_task_entry() {
|
fn user_task_entry() {
|
||||||
let cur = Task::current();
|
let cur = Task::current();
|
||||||
let user_space = cur.user_space().expect("user task should have user space");
|
let user_space = cur.user_space().expect("user task should have user space");
|
||||||
let mut user_mode = UserMode::new(user_space);
|
let mut user_mode = UserMode::new(user_space);
|
||||||
debug!("In user task entry:");
|
debug!("[Task entry] rip = 0x{:x}", user_space.cpu_ctx.gp_regs.rip);
|
||||||
debug!("[new task] rip = 0x{:x}", user_space.cpu_ctx.gp_regs.rip);
|
debug!("[Task entry] rsp = 0x{:x}", user_space.cpu_ctx.gp_regs.rsp);
|
||||||
debug!("[new task] rsp = 0x{:x}", user_space.cpu_ctx.gp_regs.rsp);
|
debug!("[Task entry] rax = 0x{:x}", user_space.cpu_ctx.gp_regs.rax);
|
||||||
debug!("[new task] rax = 0x{:x}", user_space.cpu_ctx.gp_regs.rax);
|
|
||||||
loop {
|
loop {
|
||||||
let user_event = user_mode.execute();
|
let user_event = user_mode.execute();
|
||||||
let context = user_mode.context_mut();
|
let context = user_mode.context_mut();
|
||||||
@ -66,7 +38,7 @@ pub fn create_new_task(userspace: Arc<UserSpace>, parent: Weak<Process>) -> Arc<
|
|||||||
}
|
}
|
||||||
// If current is suspended, wait for a signal to wake up self
|
// If current is suspended, wait for a signal to wake up self
|
||||||
while current.status().lock().is_suspend() {
|
while current.status().lock().is_suspend() {
|
||||||
Process::yield_now();
|
Thread::yield_now();
|
||||||
debug!("{} is suspended.", current.pid());
|
debug!("{} is suspended.", current.pid());
|
||||||
handle_pending_signal(context).unwrap();
|
handle_pending_signal(context).unwrap();
|
||||||
}
|
}
|
||||||
@ -76,7 +48,7 @@ pub fn create_new_task(userspace: Arc<UserSpace>, parent: Weak<Process>) -> Arc<
|
|||||||
Task::current().exit();
|
Task::current().exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::new(user_task_entry, parent, Some(userspace)).expect("spawn task failed")
|
Task::new(user_task_entry, thread_ref, Some(user_space)).expect("spawn task failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) {
|
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) {
|
Reference in New Issue
Block a user