mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
bugfix: 修复无法sleep的问题以及进程处于block(true)状态时无法被信号唤醒&唤醒后不处理信号的问题 (#470)
This commit is contained in:
parent
24ff1faffb
commit
8612b6ce7a
@ -374,6 +374,10 @@ ENTRY(syscall_64)
|
||||
|
||||
callq *%rdx //调用服务程序
|
||||
|
||||
// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
|
||||
movq %rsp, %rdi
|
||||
callq do_signal
|
||||
|
||||
cli
|
||||
|
||||
// === 恢复调用现场 ===
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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()),
|
||||
|
@ -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
|
||||
|
@ -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 休眠指定时间(单位:微秒)
|
||||
|
@ -6,7 +6,7 @@
|
||||
"BuildFromSource": {
|
||||
"Git": {
|
||||
"url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git",
|
||||
"revision": "95738b235f"
|
||||
"revision": "4160a0a0de"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user