浏览代码

增加gettid以及线程组group leader相关的逻辑 (#430)

* 增加gettid以及线程组group leader相关的逻辑
LoGin 1 年之前
父节点
当前提交
393f691574

+ 2 - 1
kernel/src/arch/x86_64/ipc/signal.rs

@@ -24,9 +24,10 @@ pub const STACK_ALIGN: u64 = 16;
 /// 信号最大值
 pub const MAX_SIG_NUM: usize = 64;
 #[allow(dead_code)]
-#[derive(Debug, Clone, Copy, Eq)]
+#[derive(Eq)]
 #[repr(usize)]
 #[allow(non_camel_case_types)]
+#[atomic_enum]
 pub enum Signal {
     INVALID = 0,
     SIGHUP = 1,

+ 2 - 0
kernel/src/lib.rs

@@ -57,6 +57,8 @@ mod virt;
 #[macro_use]
 extern crate alloc;
 #[macro_use]
+extern crate atomic_enum;
+#[macro_use]
 extern crate bitflags;
 extern crate elf;
 #[macro_use]

+ 1 - 1
kernel/src/net/mod.rs

@@ -197,7 +197,7 @@ pub trait Socket: Sync + Send + Debug {
         _optval: &[u8],
     ) -> Result<(), SystemError> {
         kwarn!("setsockopt is not implemented");
-        return Err(SystemError::ENOSYS);
+        return Ok(());
     }
 }
 

+ 59 - 4
kernel/src/process/fork.rs

@@ -1,7 +1,9 @@
+use core::{intrinsics::unlikely, sync::atomic::Ordering};
+
 use alloc::{string::ToString, sync::Arc};
 
 use crate::{
-    arch::interrupt::TrapFrame,
+    arch::{interrupt::TrapFrame, ipc::signal::Signal},
     filesystem::procfs::procfs_register_pid,
     ipc::signal::flush_signal_handlers,
     libs::rwlock::RwLock,
@@ -88,7 +90,8 @@ pub struct KernelCloneArgs {
     pub parent_tid: VirtAddr,
     pub set_tid: VirtAddr,
 
-    pub exit_signal: i32,
+    /// 进程退出时发送的信号
+    pub exit_signal: Signal,
 
     pub stack: usize,
     // clone3用到
@@ -115,7 +118,7 @@ impl KernelCloneArgs {
             child_tid: null_addr,
             parent_tid: null_addr,
             set_tid: null_addr,
-            exit_signal: 0,
+            exit_signal: Signal::SIGCHLD,
             stack: 0,
             stack_size: 0,
             tls: 0,
@@ -157,6 +160,8 @@ impl ProcessManager {
 
         let mut args = KernelCloneArgs::new();
         args.flags = clone_flags;
+        args.exit_signal = Signal::SIGCHLD;
+
         Self::copy_process(&current_pcb, &pcb, args, current_trapframe)?;
 
         ProcessManager::add_pcb(pcb.clone());
@@ -394,7 +399,13 @@ impl ProcessManager {
             )
         });
 
-        // todo: 拷贝信号相关数据
+        // 拷贝信号相关数据
+        Self::copy_sighand(&clone_flags, &current_pcb, &pcb).map_err(|e| {
+            panic!(
+                "fork: Failed to copy sighand from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
+                current_pcb.pid(), pcb.pid(), e
+            )
+        })?;
 
         // 拷贝线程
         Self::copy_thread(&current_pcb, &pcb, clone_args,&current_trapframe).unwrap_or_else(|e| {
@@ -404,6 +415,50 @@ impl ProcessManager {
             )
         });
 
+        // 设置线程组id、组长
+        if clone_flags.contains(CloneFlags::CLONE_THREAD) {
+            pcb.thread.write().group_leader = current_pcb.thread.read().group_leader.clone();
+            unsafe {
+                let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
+                (*ptr).tgid = current_pcb.tgid;
+            }
+        } else {
+            pcb.thread.write().group_leader = Arc::downgrade(&pcb);
+            unsafe {
+                let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
+                (*ptr).tgid = pcb.tgid;
+            }
+        }
+
+        // CLONE_PARENT re-uses the old parent
+        if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) {
+            *pcb.real_parent_pcb.write() = current_pcb.real_parent_pcb.read().clone();
+
+            if clone_flags.contains(CloneFlags::CLONE_THREAD) {
+                pcb.exit_signal.store(Signal::INVALID, Ordering::SeqCst);
+            } else {
+                let leader = current_pcb.thread.read().group_leader();
+                if unlikely(leader.is_none()) {
+                    panic!(
+                        "fork: Failed to get leader of current process, current pid: [{:?}]",
+                        current_pcb.pid()
+                    );
+                }
+
+                pcb.exit_signal.store(
+                    leader.unwrap().exit_signal.load(Ordering::SeqCst),
+                    Ordering::SeqCst,
+                );
+            }
+        } else {
+            // 新创建的进程,设置其父进程为当前进程
+            *pcb.real_parent_pcb.write() = Arc::downgrade(&current_pcb);
+            pcb.exit_signal
+                .store(clone_args.exit_signal, Ordering::SeqCst);
+        }
+
+        // todo: 增加线程组相关的逻辑。 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/fork.c#2437
+
         Ok(())
     }
 }

+ 25 - 3
kernel/src/process/mod.rs

@@ -15,7 +15,7 @@ use hashbrown::HashMap;
 
 use crate::{
     arch::{
-        ipc::signal::{SigSet, Signal},
+        ipc::signal::{AtomicSignal, SigSet, Signal},
         process::ArchPCBInfo,
         sched::sched,
         CurrentIrqArch,
@@ -308,7 +308,8 @@ impl ProcessManager {
                     parent_pcb.pid()
                 );
             }
-            // todo: 当信号机制重写后,这里需要向父进程发送SIGCHLD信号
+            // todo: 这里需要向父进程发送SIGCHLD信号
+            // todo: 这里还需要根据线程组的信息,决定信号的发送
         }
     }
 
@@ -511,6 +512,8 @@ bitflags! {
 pub struct ProcessControlBlock {
     /// 当前进程的pid
     pid: Pid,
+    /// 当前进程的线程组id(这个值在同一个线程组内永远不变)
+    tgid: Pid,
 
     basic: RwLock<ProcessBasicInfo>,
     /// 当前进程的自旋锁持有计数
@@ -532,9 +535,13 @@ pub struct ProcessControlBlock {
     sig_info: RwLock<ProcessSignalInfo>,
     /// 信号处理结构体
     sig_struct: SpinLock<SignalStruct>,
+    /// 退出信号S
+    exit_signal: AtomicSignal,
 
     /// 父进程指针
     parent_pcb: RwLock<Weak<ProcessControlBlock>>,
+    /// 真实父进程指针
+    real_parent_pcb: RwLock<Weak<ProcessControlBlock>>,
 
     /// 子进程链表
     children: RwLock<Vec<Pid>>,
@@ -593,6 +600,7 @@ impl ProcessControlBlock {
 
         let pcb = Self {
             pid,
+            tgid: pid,
             basic: basic_info,
             preempt_count,
             flags,
@@ -603,7 +611,9 @@ impl ProcessControlBlock {
             arch_info,
             sig_info: RwLock::new(ProcessSignalInfo::default()),
             sig_struct: SpinLock::new(SignalStruct::default()),
-            parent_pcb: RwLock::new(ppcb),
+            exit_signal: AtomicSignal::new(Signal::SIGCHLD),
+            parent_pcb: RwLock::new(ppcb.clone()),
+            real_parent_pcb: RwLock::new(ppcb),
             children: RwLock::new(Vec::new()),
             wait_queue: WaitQueue::INIT,
             thread: RwLock::new(ThreadInfo::new()),
@@ -768,6 +778,11 @@ impl ProcessControlBlock {
         return self.pid;
     }
 
+    #[inline(always)]
+    pub fn tgid(&self) -> Pid {
+        return self.tgid;
+    }
+
     /// 获取文件描述符表的Arc指针
     #[inline(always)]
     pub fn fd_table(&self) -> Arc<RwLock<FileDescriptorVec>> {
@@ -895,6 +910,8 @@ pub struct ThreadInfo {
     set_child_tid: Option<VirtAddr>,
 
     vfork_done: Option<Arc<Completion>>,
+    /// 线程组的组长
+    group_leader: Weak<ProcessControlBlock>,
 }
 
 impl ThreadInfo {
@@ -903,8 +920,13 @@ impl ThreadInfo {
             clear_child_tid: None,
             set_child_tid: None,
             vfork_done: None,
+            group_leader: Weak::default(),
         }
     }
+
+    pub fn group_leader(&self) -> Option<Arc<ProcessControlBlock>> {
+        return self.group_leader.upgrade();
+    }
 }
 
 /// 进程的基本信息

+ 6 - 1
kernel/src/process/syscall.rs

@@ -202,7 +202,7 @@ impl Syscall {
     /// @brief 获取当前进程的pid
     pub fn getpid() -> Result<Pid, SystemError> {
         let current_pcb = ProcessManager::current_pcb();
-        return Ok(current_pcb.pid());
+        return Ok(current_pcb.tgid());
     }
 
     /// @brief 获取指定进程的pgid
@@ -295,4 +295,9 @@ impl Syscall {
         pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr));
         Ok(pcb.pid.0)
     }
+
+    pub fn gettid() -> Result<Pid, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        Ok(pcb.pid)
+    }
 }

+ 3 - 0
kernel/src/syscall/mod.rs

@@ -415,6 +415,8 @@ pub const SYS_REBOOT: usize = 169;
 pub const SYS_GETPPID: usize = 110;
 pub const SYS_GETPGID: usize = 121;
 
+pub const SYS_GETTID: usize = 186;
+
 pub const SYS_MKNOD: usize = 133;
 
 #[allow(dead_code)]
@@ -1134,6 +1136,7 @@ impl Syscall {
                 kwarn!("SYS_MADVISE has not yet been implemented");
                 Ok(0)
             }
+            SYS_GETTID => Self::gettid().map(|tid| tid.into()),
 
             _ => panic!("Unsupported syscall ID: {}", syscall_num),
         };

+ 1 - 1
tools/run-qemu.sh

@@ -77,7 +77,7 @@ QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev
 # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " 
 QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} "
 
-QEMU_ARGUMENT+="-s -S ${QEMU_MACHINE} -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}"
+QEMU_ARGUMENT+="-s ${QEMU_MACHINE} -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}"
 QEMU_ARGUMENT+=" ${QEMU_SHM_OBJECT} "
 QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} "