mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
Support signal in sleep
This commit is contained in:
parent
5165269f4b
commit
25382e211e
@ -123,12 +123,7 @@ impl FileHandle {
|
||||
return Ok(read_len);
|
||||
}
|
||||
Err(FsError::Again) => {
|
||||
// TODO: signal
|
||||
self.async_poll().await?;
|
||||
//if has_signal_to_do() {
|
||||
//return Err(Interrupted);
|
||||
//}
|
||||
//thread::yield_now();
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
|
@ -35,6 +35,7 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use log::*;
|
||||
use num::FromPrimitive;
|
||||
use pc_keyboard::KeyCode::BackTick;
|
||||
use rcore_fs::vfs::INode;
|
||||
use rcore_memory::{Page, PAGE_SIZE};
|
||||
@ -441,6 +442,25 @@ impl Thread {
|
||||
pub fn end_running(&self, cx: Box<UserContext>) {
|
||||
self.inner.lock().context = Some(cx);
|
||||
}
|
||||
|
||||
/// this thread has signal to handle
|
||||
pub fn has_signal_to_handle(&self) -> bool {
|
||||
self.proc
|
||||
.lock()
|
||||
.sig_queue
|
||||
.iter()
|
||||
.find(|(info, tid)| {
|
||||
let tid = *tid;
|
||||
// targets me and not masked
|
||||
(tid == -1 || tid as usize == self.tid)
|
||||
&& !self
|
||||
.inner
|
||||
.lock()
|
||||
.sig_mask
|
||||
.contains(FromPrimitive::from_i32(info.signo).unwrap())
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn(thread: Arc<Thread>) {
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::arch::signal::MachineContext;
|
||||
use crate::arch::syscall::SYS_RT_SIGRETURN;
|
||||
use crate::process::{process, process_of, Process, Thread};
|
||||
use crate::sync::{MutexGuard, SpinNoIrq, SpinNoIrqLock as Mutex};
|
||||
use crate::sync::{Event, MutexGuard, SpinNoIrq, SpinNoIrqLock as Mutex};
|
||||
use alloc::sync::Arc;
|
||||
use bitflags::*;
|
||||
use num::FromPrimitive;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
mod action;
|
||||
|
||||
pub use self::action::*;
|
||||
use crate::arch::signal::MachineContext;
|
||||
use crate::arch::syscall::SYS_RT_SIGRETURN;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
#[derive(Eq, PartialEq, FromPrimitive, Debug, Copy, Clone)]
|
||||
pub enum Signal {
|
||||
@ -98,17 +98,7 @@ pub fn send_signal(process: Arc<Mutex<Process>>, tid: isize, info: Siginfo) {
|
||||
}
|
||||
process.sig_queue.push_back((info, tid));
|
||||
process.pending_sigset.add(signal);
|
||||
if tid == -1 {
|
||||
info!("send {:?} to process {}", signal, process.pid.get());
|
||||
for &tid in process.threads.iter() {
|
||||
// TODO: check mask here
|
||||
//thread_manager().wakeup(tid);
|
||||
}
|
||||
} else {
|
||||
info!("send {:?} to thread {}", signal, tid);
|
||||
// TODO: check mask here
|
||||
//thread_manager().wakeup(tid as usize);
|
||||
}
|
||||
process.eventbus.lock().set(Event::RECEIVE_SIGNAL);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -20,6 +20,7 @@ bitflags! {
|
||||
/// Process
|
||||
const PROCESS_QUIT = 1 << 10;
|
||||
const CHILD_PROCESS_QUIT = 1 << 11;
|
||||
const RECEIVE_SIGNAL = 1 << 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,12 +248,12 @@ impl Syscall<'_> {
|
||||
SYS_RT_SIGRETURN => self.sys_rt_sigreturn(),
|
||||
SYS_RT_SIGPROCMASK => self.sys_rt_sigprocmask(
|
||||
args[0],
|
||||
args[1] as *const Sigset,
|
||||
args[2] as *mut Sigset,
|
||||
UserInPtr::from(args[1]),
|
||||
UserOutPtr::from(args[2]),
|
||||
args[3],
|
||||
),
|
||||
SYS_SIGALTSTACK => {
|
||||
self.sys_sigaltstack(args[0] as *const SignalStack, args[1] as *mut SignalStack)
|
||||
self.sys_sigaltstack(UserInPtr::from(args[0]), UserOutPtr::from(args[1]))
|
||||
}
|
||||
SYS_KILL => self.sys_kill(args[0] as isize, args[1]),
|
||||
|
||||
|
@ -5,7 +5,7 @@ use crate::arch::timer::timer_now;
|
||||
use crate::fs::FileLike;
|
||||
use crate::signal::{send_signal, Signal};
|
||||
use crate::{
|
||||
sync::{wait_for_event, Event},
|
||||
sync::{wait_for_event, Event, EventBus, SpinNoIrqLock as Mutex},
|
||||
syscall::SysError::{EINTR, ESRCH},
|
||||
trap::NAIVE_TIMER,
|
||||
};
|
||||
@ -378,9 +378,8 @@ impl Syscall<'_> {
|
||||
let time = req.read()?;
|
||||
info!("nanosleep: time: {:#?},", time);
|
||||
if !time.is_zero() {
|
||||
// TODO: handle wakeup
|
||||
sleep_for(time.to_duration()).await;
|
||||
if self.has_signal_to_do() {
|
||||
self.sleep_for(time.to_duration()).await?;
|
||||
if self.thread.has_signal_to_handle() {
|
||||
return Err(EINTR);
|
||||
}
|
||||
}
|
||||
@ -396,13 +395,15 @@ impl Syscall<'_> {
|
||||
self.thread.inner.lock().clear_child_tid = tidptr as usize;
|
||||
Ok(self.thread.tid)
|
||||
}
|
||||
}
|
||||
|
||||
// sleeping
|
||||
pub fn sleep_for(duration: Duration) -> impl Future {
|
||||
SleepFuture {
|
||||
deadline: timer_now() + duration,
|
||||
duration,
|
||||
// sleeping
|
||||
pub fn sleep_for(&mut self, duration: Duration) -> impl Future<Output = SysResult> {
|
||||
SleepFuture {
|
||||
deadline: timer_now() + duration,
|
||||
duration,
|
||||
thread: self.thread.clone(),
|
||||
eventbus: self.thread.proc.lock().eventbus.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,22 +411,37 @@ pub fn sleep_for(duration: Duration) -> impl Future {
|
||||
pub struct SleepFuture {
|
||||
deadline: Duration,
|
||||
duration: Duration,
|
||||
thread: Arc<Thread>,
|
||||
eventbus: Arc<Mutex<EventBus>>,
|
||||
}
|
||||
|
||||
impl Future for SleepFuture {
|
||||
type Output = ();
|
||||
type Output = SysResult;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
// check
|
||||
if timer_now() >= self.deadline {
|
||||
return Poll::Ready(());
|
||||
return Poll::Ready(Ok(0));
|
||||
} else if self.thread.has_signal_to_handle() {
|
||||
return Poll::Ready(Err(EINTR));
|
||||
}
|
||||
// check infinity
|
||||
|
||||
// handle infinity
|
||||
if self.duration.as_nanos() < i64::max_value() as u128 {
|
||||
let waker = cx.waker().clone();
|
||||
NAIVE_TIMER
|
||||
.lock()
|
||||
.add(self.deadline, Box::new(move |_| waker.wake()));
|
||||
}
|
||||
|
||||
let waker = cx.waker().clone();
|
||||
let mut eventbus = self.eventbus.lock();
|
||||
eventbus.subscribe(Box::new({
|
||||
move |_| {
|
||||
waker.wake_by_ref();
|
||||
true
|
||||
}
|
||||
}));
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
@ -6,26 +6,6 @@ use crate::syscall::{SysResult, Syscall};
|
||||
use num::FromPrimitive;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn has_signal_to_do(&self) -> bool {
|
||||
self.thread
|
||||
.proc
|
||||
.lock()
|
||||
.sig_queue
|
||||
.iter()
|
||||
.find(|(info, tid)| {
|
||||
let tid = *tid;
|
||||
// targets me and not masked
|
||||
(tid == -1 || tid as usize == self.thread.tid)
|
||||
&& !self
|
||||
.thread
|
||||
.inner
|
||||
.lock()
|
||||
.sig_mask
|
||||
.contains(FromPrimitive::from_i32(info.signo).unwrap())
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn sys_rt_sigaction(
|
||||
&self,
|
||||
signum: usize,
|
||||
@ -51,7 +31,7 @@ impl Syscall<'_> {
|
||||
}
|
||||
if !act.is_null() {
|
||||
let act = act.read()?;
|
||||
info!("new action: {:x?}", act);
|
||||
info!("new action: {:?} -> {:x?}", signal, act);
|
||||
proc.dispositions[signum] = act;
|
||||
}
|
||||
Ok(0)
|
||||
@ -114,8 +94,8 @@ impl Syscall<'_> {
|
||||
pub fn sys_rt_sigprocmask(
|
||||
&mut self,
|
||||
how: usize,
|
||||
set: *const Sigset,
|
||||
oldset: *mut Sigset,
|
||||
set: UserInPtr<Sigset>,
|
||||
mut oldset: UserOutPtr<Sigset>,
|
||||
sigsetsize: usize,
|
||||
) -> SysResult {
|
||||
info!(
|
||||
@ -126,19 +106,19 @@ impl Syscall<'_> {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
if !oldset.is_null() {
|
||||
let oldset = unsafe { self.vm().check_write_ptr(oldset)? };
|
||||
*oldset = self.thread.inner.lock().sig_mask;
|
||||
oldset.write(self.thread.inner.lock().sig_mask)?;
|
||||
}
|
||||
if !set.is_null() {
|
||||
let set = unsafe { self.vm().check_read_ptr(set)? };
|
||||
let set = set.read()?;
|
||||
info!("rt_sigprocmask: set: {:?}", set);
|
||||
const BLOCK: usize = 0;
|
||||
const UNBLOCK: usize = 1;
|
||||
const SETMASK: usize = 2;
|
||||
let mut inner = self.thread.inner.lock();
|
||||
match how {
|
||||
BLOCK => self.thread.inner.lock().sig_mask.add_set(set),
|
||||
UNBLOCK => self.thread.inner.lock().sig_mask.remove_set(set),
|
||||
SETMASK => self.thread.inner.lock().sig_mask = *set,
|
||||
BLOCK => inner.sig_mask.add_set(&set),
|
||||
UNBLOCK => inner.sig_mask.remove_set(&set),
|
||||
SETMASK => inner.sig_mask = set,
|
||||
_ => return Err(EINVAL),
|
||||
}
|
||||
}
|
||||
@ -223,22 +203,25 @@ impl Syscall<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_sigaltstack(&self, ss: *const SignalStack, old_ss: *mut SignalStack) -> SysResult {
|
||||
pub fn sys_sigaltstack(
|
||||
&self,
|
||||
ss: UserInPtr<SignalStack>,
|
||||
mut old_ss: UserOutPtr<SignalStack>,
|
||||
) -> SysResult {
|
||||
info!("sigaltstack: ss: {:?}, old_ss: {:?}", ss, old_ss);
|
||||
const MINSIGSTKSZ: usize = 2048;
|
||||
if !old_ss.is_null() {
|
||||
let old_ss = unsafe { self.vm().check_write_ptr(old_ss)? };
|
||||
*old_ss = self.thread.inner.lock().signal_alternate_stack;
|
||||
old_ss.write(self.thread.inner.lock().signal_alternate_stack)?;
|
||||
}
|
||||
if !ss.is_null() {
|
||||
let ss = unsafe { self.vm().check_read_ptr(ss)? };
|
||||
let ss = ss.read()?;
|
||||
info!("new stack: {:?}", ss);
|
||||
|
||||
const MINSIGSTKSZ: usize = 2048;
|
||||
if ss.flags & 2 != 0 && ss.size < MINSIGSTKSZ {
|
||||
return Err(ENOMEM);
|
||||
}
|
||||
// only allow SS_AUTODISARM or SS_DISABLE
|
||||
if ss.flags ^ (ss.flags & 0x8000002) != 0 {
|
||||
if ss.flags != ss.flags & 0x8000002 {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
@ -248,7 +231,7 @@ impl Syscall<'_> {
|
||||
if flags.contains(SignalStackFlags::ONSTACK) {
|
||||
return Err(EPERM);
|
||||
}
|
||||
*old_ss = *ss;
|
||||
*old_ss = ss;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user