mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-11 00:46:49 +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 //调用服务程序
|
callq *%rdx //调用服务程序
|
||||||
|
|
||||||
|
// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
|
||||||
|
movq %rsp, %rdi
|
||||||
|
callq do_signal
|
||||||
|
|
||||||
cli
|
cli
|
||||||
|
|
||||||
// === 恢复调用现场 ===
|
// === 恢复调用现场 ===
|
||||||
|
@ -495,7 +495,7 @@ impl SignalArch for X86_64SignalArch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64 {
|
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攻击)
|
// 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
|
||||||
if UserBufferWriter::new(frame, size_of::<SigFrame>(), true).is_err() {
|
if UserBufferWriter::new(frame, size_of::<SigFrame>(), true).is_err() {
|
||||||
|
@ -141,12 +141,7 @@ impl Signal {
|
|||||||
/// @param pt siginfo结构体中,pid字段代表的含义
|
/// @param pt siginfo结构体中,pid字段代表的含义
|
||||||
fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
|
fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
|
||||||
// kdebug!("complete_signal");
|
// 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);
|
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||||
// ===== 寻找需要wakeup的目标进程 =====
|
// ===== 寻找需要wakeup的目标进程 =====
|
||||||
// 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
|
// 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
|
||||||
@ -154,11 +149,17 @@ impl Signal {
|
|||||||
|
|
||||||
// let _signal = pcb.sig_struct();
|
// let _signal = pcb.sig_struct();
|
||||||
|
|
||||||
let mut _target: Option<Arc<ProcessControlBlock>> = None;
|
let target_pcb: Option<Arc<ProcessControlBlock>>;
|
||||||
|
|
||||||
// 判断目标进程是否想接收这个信号
|
// 判断目标进程是否想接收这个信号
|
||||||
if self.wants_signal(pcb.clone()) {
|
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 {
|
} else if pt == PidType::PID {
|
||||||
/*
|
/*
|
||||||
* There is just one thread and it does not need to be woken.
|
* There is just one thread and it does not need to be woken.
|
||||||
@ -176,9 +177,9 @@ impl Signal {
|
|||||||
// TODO:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
|
// TODO:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
|
||||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||||
// TODO: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
|
// TODO: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
|
||||||
if _target.is_some() {
|
if let Some(target_pcb) = target_pcb {
|
||||||
let guard = pcb.sig_struct();
|
let guard = target_pcb.sig_struct();
|
||||||
signal_wake_up(pcb.clone(), guard, *self == Signal::SIGKILL);
|
signal_wake_up(target_pcb.clone(), guard, *self == Signal::SIGKILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +202,9 @@ impl Signal {
|
|||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +212,6 @@ impl Signal {
|
|||||||
|
|
||||||
// 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
|
// 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
|
||||||
if pcb.sig_info().sig_pending().signal().bits() == 0 {
|
if pcb.sig_info().sig_pending().signal().bits() == 0 {
|
||||||
assert!(pcb.sig_info().sig_pending().queue().q.is_empty());
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -702,12 +702,6 @@ impl Syscall {
|
|||||||
Self::sigaction(sig, act, old_act, frame.from_user())
|
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_GETPID => Self::getpid().map(|pid| pid.into()),
|
||||||
|
|
||||||
SYS_SCHED => Self::sched(frame.from_user()),
|
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;
|
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.
|
/// A representation of an absolute time value.
|
||||||
///
|
///
|
||||||
/// The `Instant` type is a wrapper around a `i64` value that
|
/// 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},
|
include::bindings::bindings::{useconds_t, Cpu_tsc_freq},
|
||||||
process::ProcessManager,
|
process::ProcessManager,
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
|
time::timekeeping::getnstimeofday,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -27,8 +28,7 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
|
|||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
// 对于小于500us的时间,使用spin/rdtsc来进行定时
|
// 对于小于500us的时间,使用spin/rdtsc来进行定时
|
||||||
|
if sleep_time.tv_nsec < 500000 && sleep_time.tv_sec == 0 {
|
||||||
if sleep_time.tv_nsec < 500000 {
|
|
||||||
let expired_tsc: u64 = unsafe {
|
let expired_tsc: u64 = unsafe {
|
||||||
CurrentTimeArch::get_cycles() as u64
|
CurrentTimeArch::get_cycles() as u64
|
||||||
+ (sleep_time.tv_nsec as u64 * Cpu_tsc_freq) / 1000000000
|
+ (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,
|
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 handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::current_pcb());
|
||||||
let timer: Arc<Timer> = Timer::new(
|
let timer: Arc<Timer> = Timer::new(handler, next_n_us_timer_jiffies(total_sleep_time_us));
|
||||||
handler,
|
|
||||||
next_n_us_timer_jiffies((sleep_time.tv_nsec / 1000) as u64),
|
|
||||||
);
|
|
||||||
|
|
||||||
let irq_guard: crate::exception::IrqFlagsGuard =
|
let irq_guard: crate::exception::IrqFlagsGuard =
|
||||||
unsafe { CurrentIrqArch::save_and_disable_irq() };
|
unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||||
ProcessManager::mark_sleep(true).ok();
|
ProcessManager::mark_sleep(true).ok();
|
||||||
|
|
||||||
|
let start_time = getnstimeofday();
|
||||||
timer.activate();
|
timer.activate();
|
||||||
|
|
||||||
drop(irq_guard);
|
drop(irq_guard);
|
||||||
|
|
||||||
sched();
|
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 {
|
return Ok(rm_time);
|
||||||
tv_sec: 0,
|
|
||||||
tv_nsec: 0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 休眠指定时间(单位:微秒)
|
/// @brief 休眠指定时间(单位:微秒)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"BuildFromSource": {
|
"BuildFromSource": {
|
||||||
"Git": {
|
"Git": {
|
||||||
"url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git",
|
"url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git",
|
||||||
"revision": "95738b235f"
|
"revision": "4160a0a0de"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
"task_type": {
|
"task_type": {
|
||||||
"BuildFromSource": {
|
"BuildFromSource": {
|
||||||
"Git": {
|
"Git": {
|
||||||
"url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git",
|
"url": "https://git.mirrors.dragonos.org.cn/DragonOS-Community/relibc.git",
|
||||||
"revision": "3ef630632f"
|
"revision": "27e779dc23"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user