1
0
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:
Jiajie Chen 2020-06-28 22:21:52 +08:00
parent 5165269f4b
commit 25382e211e
7 changed files with 77 additions and 72 deletions

View File

@ -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);

View File

@ -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>) {

View File

@ -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)]

View File

@ -20,6 +20,7 @@ bitflags! {
/// Process
const PROCESS_QUIT = 1 << 10;
const CHILD_PROCESS_QUIT = 1 << 11;
const RECEIVE_SIGNAL = 1 << 12;
}
}

View File

@ -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]),

View File

@ -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
}
}

View File

@ -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)
}