添加thread和futex机制 (#411)

* 初步实现clone系统调用

* 实现了线程,初步实现futex机制,添加了几个小的系统调用

* 更改pcb引用计数问题

* 解决死锁bug

---------

Co-authored-by: LoGin <longjin@DragonOS.org>
This commit is contained in:
GnoCiYeH
2023-11-01 20:55:57 +08:00
committed by GitHub
parent 665f4a7707
commit 971462be94
25 changed files with 1643 additions and 149 deletions

View File

@ -36,16 +36,25 @@ pub extern "C" fn rs_current_pcb_pid() -> u32 {
#[no_mangle]
pub extern "C" fn rs_current_pcb_preempt_count() -> u32 {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return 0;
}
return ProcessManager::current_pcb().preempt_count() as u32;
}
#[no_mangle]
pub extern "C" fn rs_current_pcb_flags() -> u32 {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return 0;
}
return ProcessManager::current_pcb().flags().bits() as u32;
}
#[no_mangle]
pub extern "C" fn rs_current_pcb_thread_rbp() -> u64 {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return 0;
}
return ProcessManager::current_pcb().arch_info_irqsave().rbp() as u64;
}
@ -61,5 +70,8 @@ pub extern "C" fn rs_preempt_enable() {
#[no_mangle]
pub extern "C" fn rs_process_do_exit(exit_code: usize) -> usize {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return 0;
}
ProcessManager::exit(exit_code);
}

View File

@ -1,9 +1,13 @@
use alloc::{string::ToString, sync::Arc};
use crate::{
arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid,
ipc::signal::flush_signal_handlers, libs::rwlock::RwLock, process::ProcessFlags,
syscall::SystemError,
arch::interrupt::TrapFrame,
filesystem::procfs::procfs_register_pid,
ipc::signal::flush_signal_handlers,
libs::rwlock::RwLock,
mm::VirtAddr,
process::ProcessFlags,
syscall::{user_access::UserBufferWriter, SystemError},
};
use super::{
@ -13,21 +17,116 @@ use super::{
bitflags! {
/// 进程克隆标志
pub struct CloneFlags: u32 {
/// 在进程间共享文件系统信息
const CLONE_FS = (1 << 0);
/// 克隆时,与父进程共享信号结构体
const CLONE_SIGNAL = (1 << 1);
/// 克隆时,与父进程共享信号处理结构体
const CLONE_SIGHAND = (1 << 2);
/// 克隆时将原本被设置为SIG_IGNORE的信号设置回SIG_DEFAULT
const CLONE_CLEAR_SIGHAND = (1 << 3);
pub struct CloneFlags: u64 {
/// 在进程间共享虚拟内存空间
const CLONE_VM = (1 << 4);
/// 拷贝线程
const CLONE_THREAD = (1 << 5);
const CLONE_VM = 0x00000100;
/// 在进程间共享文件系统信息
const CLONE_FS = 0x00000200;
/// 共享打开的文件
const CLONE_FILES = (1 << 6);
const CLONE_FILES = 0x00000400;
/// 克隆时,与父进程共享信号处理结构体
const CLONE_SIGHAND = 0x00000800;
/// 返回进程的文件描述符
const CLONE_PIDFD = 0x00001000;
/// 使克隆对象成为父进程的跟踪对象
const CLONE_PTRACE = 0x00002000;
/// 在执行 exec() 或 _exit() 之前挂起父进程的执行
const CLONE_VFORK = 0x00004000;
/// 使克隆对象的父进程为调用进程的父进程
const CLONE_PARENT = 0x00008000;
/// 拷贝线程
const CLONE_THREAD = 0x00010000;
/// 创建一个新的命名空间,其中包含独立的文件系统挂载点层次结构。
const CLONE_NEWNS = 0x00020000;
/// 与父进程共享 System V 信号量。
const CLONE_SYSVSEM = 0x00040000;
/// 设置其线程本地存储
const CLONE_SETTLS = 0x00080000;
/// 设置partent_tid地址为子进程线程 ID
const CLONE_PARENT_SETTID = 0x00100000;
/// 在子进程中设置一个清除线程 ID 的用户空间地址
const CLONE_CHILD_CLEARTID = 0x00200000;
/// 创建一个新线程,将其设置为分离状态
const CLONE_DETACHED = 0x00400000;
/// 使其在创建者进程或线程视角下成为无法跟踪的。
const CLONE_UNTRACED = 0x00800000;
/// 设置其子进程线程 ID
const CLONE_CHILD_SETTID = 0x01000000;
/// 将其放置在一个新的 cgroup 命名空间中
const CLONE_NEWCGROUP = 0x02000000;
/// 将其放置在一个新的 UTS 命名空间中
const CLONE_NEWUTS = 0x04000000;
/// 将其放置在一个新的 IPC 命名空间中
const CLONE_NEWIPC = 0x08000000;
/// 将其放置在一个新的用户命名空间中
const CLONE_NEWUSER = 0x10000000;
/// 将其放置在一个新的 PID 命名空间中
const CLONE_NEWPID = 0x20000000;
/// 将其放置在一个新的网络命名空间中
const CLONE_NEWNET = 0x40000000;
/// 在新的 I/O 上下文中运行它
const CLONE_IO = 0x80000000;
/// 克隆时,与父进程共享信号结构体
const CLONE_SIGNAL = 0x00010000 | 0x00000800;
/// 克隆时将原本被设置为SIG_IGNORE的信号设置回SIG_DEFAULT
const CLONE_CLEAR_SIGHAND = 0x100000000;
}
}
/// ## clone与clone3系统调用的参数载体
///
/// 因为这两个系统调用的参数很多,所以有这样一个载体更灵活
///
/// 仅仅作为参数传递
#[derive(Debug, Clone, Copy)]
pub struct KernelCloneArgs {
pub flags: CloneFlags,
// 下列属性均来自用户空间
pub pidfd: VirtAddr,
pub child_tid: VirtAddr,
pub parent_tid: VirtAddr,
pub set_tid: VirtAddr,
pub exit_signal: i32,
pub stack: usize,
// clone3用到
pub stack_size: usize,
pub tls: usize,
pub set_tid_size: usize,
pub cgroup: i32,
pub io_thread: bool,
pub kthread: bool,
pub idle: bool,
pub func: VirtAddr,
pub fn_arg: VirtAddr,
// cgrp 和 cset?
}
impl KernelCloneArgs {
pub fn new() -> Self {
let null_addr = VirtAddr::new(0);
Self {
flags: unsafe { CloneFlags::from_bits_unchecked(0) },
pidfd: null_addr,
child_tid: null_addr,
parent_tid: null_addr,
set_tid: null_addr,
exit_signal: 0,
stack: 0,
stack_size: 0,
tls: 0,
set_tid_size: 0,
cgroup: 0,
io_thread: false,
kthread: false,
idle: false,
func: null_addr,
fn_arg: null_addr,
}
}
}
@ -56,53 +155,9 @@ impl ProcessManager {
let name = current_pcb.basic().name().to_string();
let pcb = ProcessControlBlock::new(name, new_kstack);
// 克隆架构相关信息
*pcb.arch_info() = current_pcb.arch_info_irqsave().clone();
// 为内核线程设置worker private字段。也许由内核线程机制去做会更好
if current_pcb.flags().contains(ProcessFlags::KTHREAD) {
*pcb.worker_private() = Some(WorkerPrivate::KernelThread(KernelThreadPcbPrivate::new()))
}
// 拷贝标志位
ProcessManager::copy_flags(&clone_flags, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy flags from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝用户地址空间
ProcessManager::copy_mm(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy mm from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝文件描述符表
ProcessManager::copy_files(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy files from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
//拷贝信号相关数据
ProcessManager::copy_sighand(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy sighands from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝线程
ProcessManager::copy_thread(&clone_flags, &current_pcb, &pcb, &current_trapframe).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy thread from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
let mut args = KernelCloneArgs::new();
args.flags = clone_flags;
Self::copy_process(&current_pcb, &pcb, args, current_trapframe)?;
ProcessManager::add_pcb(pcb.clone());
@ -168,7 +223,6 @@ impl ProcessManager {
unsafe { new_pcb.basic_mut().set_user_vm(Some(old_address_space)) };
return Ok(());
}
let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| {
panic!(
"copy_mm: Failed to clone address space of current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
@ -215,4 +269,139 @@ impl ProcessManager {
}
return Ok(());
}
/// 拷贝进程信息
///
/// ## panic:
/// 某一步拷贝失败时会引发panic
/// 例如copy_mm等失败时会触发panic
///
/// ## 参数
///
/// - clone_flags 标志位
/// - des_pcb 目标pcb
/// - src_pcb 拷贝源pcb
///
/// ## return
/// - 发生错误时返回Err(SystemError)
pub fn copy_process(
current_pcb: &Arc<ProcessControlBlock>,
pcb: &Arc<ProcessControlBlock>,
clone_args: KernelCloneArgs,
current_trapframe: &mut TrapFrame,
) -> Result<(), SystemError> {
let clone_flags = clone_args.flags;
// 不允许与不同namespace的进程共享根目录
if (clone_flags == (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS))
|| clone_flags == (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_FS)
{
return Err(SystemError::EINVAL);
}
// 线程组必须共享信号,分离线程只能在线程组内启动。
if clone_flags.contains(CloneFlags::CLONE_THREAD)
&& !clone_flags.contains(CloneFlags::CLONE_SIGHAND)
{
return Err(SystemError::EINVAL);
}
// 共享信号处理器意味着共享vm。
// 线程组也意味着共享vm。阻止这种情况可以简化其他代码。
if clone_flags.contains(CloneFlags::CLONE_SIGHAND)
&& !clone_flags.contains(CloneFlags::CLONE_VM)
{
return Err(SystemError::EINVAL);
}
// TODO: 处理CLONE_PARENT 与 SIGNAL_UNKILLABLE的情况
// 如果新进程使用不同的 pid 或 namespace
// 则不允许它与分叉任务共享线程组。
if clone_flags.contains(CloneFlags::CLONE_THREAD) {
if clone_flags.contains(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWPID) {
return Err(SystemError::EINVAL);
}
// TODO: 判断新进程与当前进程namespace是否相同不同则返回错误
}
// 如果新进程将处于不同的time namespace
// 则不能让它共享vm或线程组。
if clone_flags.contains(CloneFlags::CLONE_THREAD | CloneFlags::CLONE_VM) {
// TODO: 判断time namespace不同则返回错误
}
if clone_flags.contains(CloneFlags::CLONE_PIDFD)
&& clone_flags.contains(CloneFlags::CLONE_DETACHED | CloneFlags::CLONE_THREAD)
{
return Err(SystemError::EINVAL);
}
// TODO: 克隆前应该锁信号处理,等待克隆完成后再处理
// 克隆架构相关
*pcb.arch_info() = current_pcb.arch_info_irqsave().clone();
// 为内核线程设置WorkerPrivate
if current_pcb.flags().contains(ProcessFlags::KTHREAD) {
*pcb.worker_private() =
Some(WorkerPrivate::KernelThread(KernelThreadPcbPrivate::new()));
}
// 设置clear_child_tid在线程结束时将其置0以通知父进程
if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) {
pcb.thread.write().clear_child_tid = Some(clone_args.child_tid);
}
// 设置child_tid意味着子线程能够知道自己的id
if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) {
pcb.thread.write().set_child_tid = Some(clone_args.child_tid);
}
// 将子进程/线程的id存储在用户态传进的地址中
if clone_flags.contains(CloneFlags::CLONE_PARENT_SETTID) {
let mut writer = UserBufferWriter::new(
clone_args.parent_tid.data() as *mut i32,
core::mem::size_of::<i32>(),
true,
)?;
writer.copy_one_to_user(&(pcb.pid().0 as i32), 0)?;
}
// 拷贝标志位
Self::copy_flags(&clone_flags, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy flags from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝用户地址空间
Self::copy_mm(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy mm from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝文件描述符表
Self::copy_files(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy files from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// todo: 拷贝信号相关数据
// 拷贝线程
Self::copy_thread(&current_pcb, &pcb, clone_args,&current_trapframe).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy thread from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
Ok(())
}
}

View File

@ -282,9 +282,11 @@ impl KernelThreadMechanism {
// 初始化kthreadd
let closure = KernelThreadClosure::EmptyClosure((Box::new(Self::kthread_daemon), ()));
let info = KernelThreadCreateInfo::new(closure, "kthreadd".to_string());
let kthreadd_pid: Pid =
Self::__inner_create(&info, CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL)
.expect("Failed to create kthread daemon");
let kthreadd_pid: Pid = Self::__inner_create(
&info,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
)
.expect("Failed to create kthread daemon");
let pcb = ProcessManager::find(kthreadd_pid).unwrap();
ProcessManager::wakeup(&pcb).expect("Failed to wakeup kthread daemon");

View File

@ -1,5 +1,6 @@
use core::{
hash::{Hash, Hasher},
hint::spin_loop,
intrinsics::{likely, unlikely},
mem::ManuallyDrop,
sync::atomic::{compiler_fence, AtomicBool, AtomicI32, AtomicIsize, AtomicUsize, Ordering},
@ -29,6 +30,10 @@ use crate::{
libs::{
align::AlignedBox,
casting::DowncastArc,
futex::{
constant::{FutexFlag, FUTEX_BITSET_MATCH_ANY},
futex::Futex,
},
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
wait_queue::WaitQueue,
@ -36,11 +41,12 @@ use crate::{
mm::{percpu::PerCpuVar, set_INITIAL_PROCESS_ADDRESS_SPACE, ucontext::AddressSpace, VirtAddr},
net::socket::SocketInode,
sched::{
completion::Completion,
core::{sched_enqueue, CPU_EXECUTING},
SchedPolicy, SchedPriority,
},
smp::kick_cpu,
syscall::{Syscall, SystemError},
syscall::{user_access::clear_user, Syscall, SystemError},
};
use self::kthread::WorkerPrivate;
@ -116,6 +122,12 @@ impl ProcessManager {
/// 获取当前进程的pcb
pub fn current_pcb() -> Arc<ProcessControlBlock> {
if unlikely(unsafe { !__PROCESS_MANAGEMENT_INIT_DONE }) {
kerror!("unsafe__PROCESS_MANAGEMENT_INIT_DONE == false");
loop {
spin_loop();
}
}
return ProcessControlBlock::arch_current_pcb();
}
@ -252,7 +264,7 @@ impl ProcessManager {
assert_eq!(
CurrentIrqArch::is_irq_enabled(),
false,
"interrupt must be disabled before enter ProcessManager::mark_sleep()"
"interrupt must be disabled before enter ProcessManager::mark_stop()"
);
let pcb = ProcessManager::current_pcb();
@ -306,9 +318,31 @@ impl ProcessManager {
.write()
.set_state(ProcessState::Exited(exit_code));
pcb.wait_queue.wakeup(Some(ProcessState::Blocked(true)));
// 进行进程退出后的工作
let thread = pcb.thread.write();
if let Some(addr) = thread.set_child_tid {
unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
}
if let Some(addr) = thread.clear_child_tid {
if Arc::strong_count(&pcb.basic().user_vm().expect("User VM Not found")) > 1 {
let _ =
Futex::futex_wake(addr, FutexFlag::FLAGS_MATCH_NONE, 1, FUTEX_BITSET_MATCH_ANY);
}
unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
}
// 如果是vfork出来的进程则需要处理completion
if thread.vfork_done.is_some() {
thread.vfork_done.as_ref().unwrap().complete_all();
}
drop(thread);
unsafe { pcb.basic_mut().set_user_vm(None) };
drop(pcb);
ProcessManager::exit_notify();
drop(irq_guard);
sched();
loop {}
}
@ -316,15 +350,21 @@ impl ProcessManager {
pub unsafe fn release(pid: Pid) {
let pcb = ProcessManager::find(pid);
if !pcb.is_none() {
let pcb = pcb.unwrap();
// let pcb = pcb.unwrap();
// 判断该pcb是否在全局没有任何引用
if Arc::strong_count(&pcb) <= 1 {
drop(pcb);
ALL_PROCESS.lock().as_mut().unwrap().remove(&pid);
} else {
// 如果不为1就panic
panic!("pcb is still referenced");
}
// TODO: 当前pcb的Arc指针存在泄露问题引用计数不正确打算在接下来实现debug专用的Arc方便调试然后解决这个bug。
// 因此目前暂时注释掉,使得能跑
// if Arc::strong_count(&pcb) <= 2 {
// drop(pcb);
// ALL_PROCESS.lock().as_mut().unwrap().remove(&pid);
// } else {
// // 如果不为1就panic
// let msg = format!("pcb '{:?}' is still referenced, strong count={}",pcb.pid(), Arc::strong_count(&pcb));
// kerror!("{}", msg);
// panic!()
// }
ALL_PROCESS.lock().as_mut().unwrap().remove(&pid);
}
}
@ -482,10 +522,13 @@ pub struct ProcessControlBlock {
parent_pcb: RwLock<Weak<ProcessControlBlock>>,
/// 子进程链表
children: RwLock<HashMap<Pid, Arc<ProcessControlBlock>>>,
children: RwLock<Vec<Pid>>,
/// 等待队列
wait_queue: WaitQueue,
/// 线程信息
thread: RwLock<ThreadInfo>,
}
impl ProcessControlBlock {
@ -545,20 +588,26 @@ impl ProcessControlBlock {
sig_info: RwLock::new(ProcessSignalInfo::default()),
sig_struct: SpinLock::new(SignalStruct::default()),
parent_pcb: RwLock::new(ppcb),
children: RwLock::new(HashMap::new()),
children: RwLock::new(Vec::new()),
wait_queue: WaitQueue::INIT,
thread: RwLock::new(ThreadInfo::new()),
};
let pcb = Arc::new(pcb);
// 设置进程的arc指针到内核栈的最低地址处
unsafe { pcb.kernel_stack.write().set_pcb(Arc::clone(&pcb)).unwrap() };
unsafe {
pcb.kernel_stack
.write()
.set_pcb(Arc::downgrade(&pcb))
.unwrap()
};
// 将当前pcb加入父进程的子进程哈希表中
if pcb.pid() > Pid(1) {
if let Some(ppcb_arc) = pcb.parent_pcb.read().upgrade() {
let mut children = ppcb_arc.children.write();
children.insert(pcb.pid(), pcb.clone());
children.push(pcb.pid());
} else {
panic!("parent pcb is None");
}
@ -700,11 +749,11 @@ impl ProcessControlBlock {
unsafe fn adopt_childen(&self) -> Result<(), SystemError> {
match ProcessManager::find(Pid(1)) {
Some(init_pcb) => {
let mut childen_guard = self.children.write();
let childen_guard = self.children.write();
let mut init_childen_guard = init_pcb.children.write();
childen_guard.drain().for_each(|(pid, child)| {
init_childen_guard.insert(pid, child);
childen_guard.iter().for_each(|pid| {
init_childen_guard.push(*pid);
});
return Ok(());
@ -747,12 +796,31 @@ impl Drop for ProcessControlBlock {
.unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}"));
if let Some(ppcb) = self.parent_pcb.read().upgrade() {
ppcb.children.write().remove(&self.pid());
ppcb.children.write().drain_filter(|pid| *pid == self.pid());
}
unsafe { ProcessManager::release(self.pid()) };
}
}
/// 线程信息
#[derive(Debug)]
pub struct ThreadInfo {
// 来自用户空间记录用户线程id的地址在该线程结束时将该地址置0以通知父进程
clear_child_tid: Option<VirtAddr>,
set_child_tid: Option<VirtAddr>,
vfork_done: Option<Arc<Completion>>,
}
impl ThreadInfo {
pub fn new() -> Self {
Self {
clear_child_tid: None,
set_child_tid: None,
vfork_done: None,
}
}
}
/// 进程的基本信息
///
/// 这个结构体保存进程的基本信息,主要是那些不会随着进程的运行而经常改变的信息。
@ -994,9 +1062,9 @@ impl KernelStack {
return VirtAddr::new(self.stack.as_ref().unwrap().as_ptr() as usize + Self::SIZE);
}
pub unsafe fn set_pcb(&mut self, pcb: Arc<ProcessControlBlock>) -> Result<(), SystemError> {
// 将一个Arc<ProcessControlBlock>放到内核栈的最低地址处
let p: *const ProcessControlBlock = Arc::into_raw(pcb);
pub unsafe fn set_pcb(&mut self, pcb: Weak<ProcessControlBlock>) -> Result<(), SystemError> {
// 将一个Weak<ProcessControlBlock>放到内核栈的最低地址处
let p: *const ProcessControlBlock = Weak::into_raw(pcb);
let stack_bottom_ptr = self.start_address().data() as *mut *const ProcessControlBlock;
// 如果内核栈的最低地址处已经有了一个pcb那么这里就不再设置,直接返回错误
@ -1021,10 +1089,10 @@ impl KernelStack {
}
// 为了防止内核栈的pcb指针被释放这里需要将其包装一下使得Arc的drop不会被调用
let arc_wrapper: ManuallyDrop<Arc<ProcessControlBlock>> =
ManuallyDrop::new(Arc::from_raw(p));
let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
ManuallyDrop::new(Weak::from_raw(p));
let new_arc: Arc<ProcessControlBlock> = Arc::clone(&arc_wrapper);
let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade()?;
return Some(new_arc);
}
}
@ -1032,8 +1100,8 @@ impl KernelStack {
impl Drop for KernelStack {
fn drop(&mut self) {
if !self.stack.is_none() {
let pcb_ptr: Arc<ProcessControlBlock> = unsafe {
Arc::from_raw(self.stack.as_ref().unwrap().as_ptr() as *const ProcessControlBlock)
let pcb_ptr: Weak<ProcessControlBlock> = unsafe {
Weak::from_raw(self.stack.as_ref().unwrap().as_ptr() as *const ProcessControlBlock)
};
drop(pcb_ptr);
}

View File

@ -1,13 +1,24 @@
use core::ffi::c_void;
use alloc::{string::String, vec::Vec};
use alloc::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use super::{abi::WaitOption, fork::CloneFlags, Pid, ProcessManager, ProcessState};
use super::{
abi::WaitOption,
fork::{CloneFlags, KernelCloneArgs},
KernelStack, Pid, ProcessManager, ProcessState,
};
use crate::{
arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch},
exception::InterruptArch,
filesystem::vfs::MAX_PATHLEN,
filesystem::{procfs::procfs_register_pid, vfs::MAX_PATHLEN},
include::bindings::bindings::verify_area,
mm::VirtAddr,
process::ProcessControlBlock,
sched::completion::Completion,
syscall::{
user_access::{
check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter,
@ -42,6 +53,11 @@ impl Syscall {
// argv,
// envp
// );
// kdebug!(
// "before execve: strong count: {}",
// Arc::strong_count(&ProcessManager::current_pcb())
// );
if path.is_null() {
return Err(SystemError::EINVAL);
}
@ -66,6 +82,10 @@ impl Syscall {
// 关闭设置了O_CLOEXEC的文件描述符
let fd_table = ProcessManager::current_pcb().fd_table();
fd_table.write().close_on_exec();
// kdebug!(
// "after execve: strong count: {}",
// Arc::strong_count(&ProcessManager::current_pcb())
// );
return Ok(());
}
@ -95,12 +115,13 @@ impl Syscall {
if pid > 0 {
let pid = Pid(pid as usize);
let child_pcb = rd_childen.get(&pid).ok_or(SystemError::ECHILD)?.clone();
let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?;
drop(rd_childen);
loop {
let state = child_pcb.sched_info().state();
// 获取退出码
match child_pcb.sched_info().state() {
match state {
ProcessState::Runnable => {
if options.contains(WaitOption::WNOHANG)
|| options.contains(WaitOption::WNOWAIT)
@ -123,12 +144,16 @@ impl Syscall {
}
}
ProcessState::Exited(status) => {
// kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
if !wstatus.is_null() {
wstatus_buf.copy_one_to_user(
&(status | WaitOption::WEXITED.bits() as usize),
&(status as u32 | WaitOption::WEXITED.bits()),
0,
)?;
}
drop(child_pcb);
// kdebug!("wait4: to release {pid:?}");
unsafe { ProcessManager::release(pid) };
return Ok(pid.into());
}
};
@ -147,7 +172,8 @@ impl Syscall {
} else {
// 等待任意子进程(这两)
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
for (pid, pcb) in rd_childen.iter() {
for pid in rd_childen.iter() {
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
if pcb.sched_info().state().is_exited() {
if !wstatus.is_null() {
wstatus_buf.copy_one_to_user(&0, 0)?;
@ -200,4 +226,73 @@ impl Syscall {
let current_pcb = ProcessManager::current_pcb();
return Ok(current_pcb.basic().ppid());
}
pub fn clone(
current_trapframe: &mut TrapFrame,
clone_args: KernelCloneArgs,
) -> Result<usize, SystemError> {
let flags = clone_args.flags;
let vfork = Arc::new(Completion::new());
if flags.contains(CloneFlags::CLONE_PIDFD)
&& flags.contains(CloneFlags::CLONE_PARENT_SETTID)
{
return Err(SystemError::EINVAL);
}
let current_pcb = ProcessManager::current_pcb();
let new_kstack = KernelStack::new()?;
let name = current_pcb.basic().name().to_string();
let pcb = ProcessControlBlock::new(name, new_kstack);
// 克隆pcb
ProcessManager::copy_process(&current_pcb, &pcb, clone_args, current_trapframe)?;
ProcessManager::add_pcb(pcb.clone());
// 向procfs注册进程
procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
panic!(
"fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
pcb.pid(),
e
)
});
if flags.contains(CloneFlags::CLONE_VFORK) {
pcb.thread.write().vfork_done = Some(vfork.clone());
}
if pcb.thread.read().set_child_tid.is_some() {
let addr = pcb.thread.read().set_child_tid.unwrap();
let mut writer =
UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
}
ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
pcb.pid(),
e
)
});
if flags.contains(CloneFlags::CLONE_VFORK) {
// 等待子进程结束或者exec;
vfork.wait_for_completion_interruptible()?;
}
return Ok(pcb.pid().0);
}
/// 设置线程地址
pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> {
if !unsafe { verify_area(ptr as u64, core::mem::size_of::<i32>() as u64) } {
return Err(SystemError::EFAULT);
}
let pcb = ProcessManager::current_pcb();
pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr));
Ok(pcb.pid.0)
}
}