Przeglądaj źródła

bugfix: 修复无法sleep的问题以及进程处于block(true)状态时无法被信号唤醒&唤醒后不处理信号的问题 (#470)

LoGin 1 rok temu
rodzic
commit
8612b6ce7a

+ 4 - 0
kernel/src/arch/x86_64/asm/entry.S

@@ -374,6 +374,10 @@ ENTRY(syscall_64)
 
     callq *%rdx //调用服务程序
 
+    // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
+    movq %rsp, %rdi
+    callq do_signal
+
     cli
     
     // === 恢复调用现场 ===

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

@@ -495,7 +495,7 @@ impl SignalArch for X86_64SignalArch {
     }
 
     fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64 {
-        let frame = (trap_frame.rsp as usize) as *mut SigFrame;
+        let frame = (trap_frame.rsp as usize - size_of::<u64>()) as *mut SigFrame;
 
         // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
         if UserBufferWriter::new(frame, size_of::<SigFrame>(), true).is_err() {

+ 15 - 13
kernel/src/ipc/signal.rs

@@ -141,12 +141,7 @@ impl Signal {
     /// @param pt siginfo结构体中,pid字段代表的含义
     fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
         // kdebug!("complete_signal");
-        // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
-        // 将这个信号加到目标进程的sig_pending中
-        pcb.sig_info_mut()
-            .sig_pending_mut()
-            .signal_mut()
-            .insert(self.clone().into());
+
         compiler_fence(core::sync::atomic::Ordering::SeqCst);
         // ===== 寻找需要wakeup的目标进程 =====
         // 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
@@ -154,11 +149,17 @@ impl Signal {
 
         // let _signal = pcb.sig_struct();
 
-        let mut _target: Option<Arc<ProcessControlBlock>> = None;
+        let target_pcb: Option<Arc<ProcessControlBlock>>;
 
         // 判断目标进程是否想接收这个信号
         if self.wants_signal(pcb.clone()) {
-            _target = Some(pcb.clone());
+            // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
+            // 将这个信号加到目标进程的sig_pending中
+            pcb.sig_info_mut()
+                .sig_pending_mut()
+                .signal_mut()
+                .insert(self.clone().into());
+            target_pcb = Some(pcb.clone());
         } else if pt == PidType::PID {
             /*
              * There is just one thread and it does not need to be woken.
@@ -176,9 +177,9 @@ impl Signal {
         // TODO:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
         compiler_fence(core::sync::atomic::Ordering::SeqCst);
         // TODO: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
-        if _target.is_some() {
-            let guard = pcb.sig_struct();
-            signal_wake_up(pcb.clone(), guard, *self == Signal::SIGKILL);
+        if let Some(target_pcb) = target_pcb {
+            let guard = target_pcb.sig_struct();
+            signal_wake_up(target_pcb.clone(), guard, *self == Signal::SIGKILL);
         }
     }
 
@@ -201,7 +202,9 @@ impl Signal {
             return true;
         }
 
-        if pcb.sched_info().state().is_blocked() {
+        if pcb.sched_info().state().is_blocked()
+            && (pcb.sched_info().state().is_blocked_interruptable() == false)
+        {
             return false;
         }
 
@@ -209,7 +212,6 @@ impl Signal {
 
         // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
         if pcb.sig_info().sig_pending().signal().bits() == 0 {
-            assert!(pcb.sig_info().sig_pending().queue().q.is_empty());
             return true;
         } else {
             return false;

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

@@ -702,12 +702,6 @@ impl Syscall {
                 Self::sigaction(sig, act, old_act, frame.from_user())
             }
 
-            SYS_RT_SIGRETURN => {
-                // 由于目前signal机制的实现,与x86_64强关联,因此暂时在arch/x86_64/syscall.rs中调用
-                // todo: 未来需要将signal机制与平台解耦
-                todo!()
-            }
-
             SYS_GETPID => Self::getpid().map(|pid| pid.into()),
 
             SYS_SCHED => Self::sched(frame.from_user()),

+ 28 - 1
kernel/src/time/mod.rs

@@ -1,4 +1,7 @@
-use core::{fmt, ops};
+use core::{
+    fmt,
+    ops::{self, Sub},
+};
 
 use self::timekeep::ktime_get_real_ns;
 
@@ -54,6 +57,30 @@ impl TimeSpec {
     }
 }
 
+impl Sub for TimeSpec {
+    type Output = Duration;
+    fn sub(self, rhs: Self) -> Self::Output {
+        let sec = self.tv_sec.checked_sub(rhs.tv_sec).unwrap_or(0);
+        let nsec = self.tv_nsec.checked_sub(rhs.tv_nsec).unwrap_or(0);
+        Duration::from_micros((sec * 1000000 + nsec / 1000) as u64)
+    }
+}
+
+impl From<Duration> for TimeSpec {
+    fn from(dur: Duration) -> Self {
+        TimeSpec {
+            tv_sec: dur.total_micros() as i64 / 1000000,
+            tv_nsec: (dur.total_micros() as i64 % 1000000) * 1000,
+        }
+    }
+}
+
+impl Into<Duration> for TimeSpec {
+    fn into(self) -> Duration {
+        Duration::from_micros(self.tv_sec as u64 * 1000000 + self.tv_nsec as u64 / 1000)
+    }
+}
+
 /// A representation of an absolute time value.
 ///
 /// The `Instant` type is a wrapper around a `i64` value that

+ 13 - 12
kernel/src/time/sleep.rs

@@ -8,6 +8,7 @@ use crate::{
     include::bindings::bindings::{useconds_t, Cpu_tsc_freq},
     process::ProcessManager,
     syscall::SystemError,
+    time::timekeeping::getnstimeofday,
 };
 
 use super::{
@@ -27,8 +28,7 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
         return Err(SystemError::EINVAL);
     }
     // 对于小于500us的时间,使用spin/rdtsc来进行定时
-
-    if sleep_time.tv_nsec < 500000 {
+    if sleep_time.tv_nsec < 500000 && sleep_time.tv_sec == 0 {
         let expired_tsc: u64 = unsafe {
             CurrentTimeArch::get_cycles() as u64
                 + (sleep_time.tv_nsec as u64 * Cpu_tsc_freq) / 1000000000
@@ -41,28 +41,29 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
             tv_nsec: 0,
         });
     }
+
+    let total_sleep_time_us: u64 =
+        sleep_time.tv_sec as u64 * 1000000 + sleep_time.tv_nsec as u64 / 1000;
     // 创建定时器
     let handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::current_pcb());
-    let timer: Arc<Timer> = Timer::new(
-        handler,
-        next_n_us_timer_jiffies((sleep_time.tv_nsec / 1000) as u64),
-    );
+    let timer: Arc<Timer> = Timer::new(handler, next_n_us_timer_jiffies(total_sleep_time_us));
 
     let irq_guard: crate::exception::IrqFlagsGuard =
         unsafe { CurrentIrqArch::save_and_disable_irq() };
     ProcessManager::mark_sleep(true).ok();
+
+    let start_time = getnstimeofday();
     timer.activate();
 
     drop(irq_guard);
-
     sched();
 
-    // TODO: 增加信号唤醒的功能后,返回正确的剩余时间
+    let end_time = getnstimeofday();
+    // 返回正确的剩余时间
+    let real_sleep_time = end_time - start_time;
+    let rm_time: TimeSpec = (sleep_time - real_sleep_time.into()).into();
 
-    return Ok(TimeSpec {
-        tv_sec: 0,
-        tv_nsec: 0,
-    });
+    return Ok(rm_time);
 }
 
 /// @brief 休眠指定时间(单位:微秒)

+ 1 - 1
user/dadk/config/nova_shell-0.1.0.dadk

@@ -6,7 +6,7 @@
     "BuildFromSource": {
       "Git": {
         "url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git",
-        "revision": "95738b235f"
+        "revision": "4160a0a0de"
       }
     }
   },

+ 2 - 2
user/dadk/config/relibc-0.1.0.dadk

@@ -5,8 +5,8 @@
   "task_type": {
     "BuildFromSource": {
       "Git": {
-        "url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git",
-        "revision": "3ef630632f"
+        "url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/relibc.git",
+        "revision": "27e779dc23"
       }
     }
   },