mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-25 17:33:28 +04:00
fix bug
This commit is contained in:
parent
98d3f83a12
commit
bee5a77e2b
@ -69,6 +69,8 @@ use super::TrapFrame;
|
||||
use crate::drivers::IRQ_MANAGER;
|
||||
use bitflags::*;
|
||||
use log::*;
|
||||
use crate::process::current_thread;
|
||||
use crate::processor;
|
||||
|
||||
global_asm!(include_str!("trap.asm"));
|
||||
global_asm!(include_str!("vector.asm"));
|
||||
@ -81,6 +83,9 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
|
||||
tf.trap_num,
|
||||
super::super::cpu::id()
|
||||
);
|
||||
if processor().tid_option().is_some() {
|
||||
unsafe { current_thread().ustack_top = tf.rsp; }
|
||||
}
|
||||
// Dispatch
|
||||
match tf.trap_num as u8 {
|
||||
Breakpoint => breakpoint(),
|
||||
|
@ -5,6 +5,7 @@ use num::FromPrimitive;
|
||||
use rcore_thread::std_thread::current;
|
||||
use crate::signal::*;
|
||||
use alloc::vec::Vec;
|
||||
use crate::arch::get_sp;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
@ -160,27 +161,44 @@ impl Context {
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
"::::"intel" "volatile");
|
||||
|
||||
asm!("
|
||||
// save page table
|
||||
mov r15, cr3
|
||||
push r15
|
||||
push r15"::::"intel" "volatile"
|
||||
);
|
||||
|
||||
asm!(
|
||||
"
|
||||
// Switch stacks
|
||||
mov [rdi], rsp // rdi = from_rsp
|
||||
mov rsp, [rsi] // rsi = to_rsp
|
||||
"::::"intel" "volatile");
|
||||
|
||||
asm!("mov r15, cr3"::::"intel" "volatile"); // debug
|
||||
|
||||
asm!(
|
||||
"
|
||||
// restore page table
|
||||
pop r15
|
||||
mov cr3, r15
|
||||
"::::"intel" "volatile");
|
||||
|
||||
asm!("
|
||||
// restore old callee-save registers
|
||||
pop r15
|
||||
": : : : "intel" "volatile"
|
||||
);
|
||||
asm!("
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r12": : : : "intel" "volatile");
|
||||
asm!("
|
||||
pop rbp
|
||||
pop rbx
|
||||
": : : : "intel" "volatile");
|
||||
// info!("wang!");
|
||||
|
||||
handle_signal();
|
||||
}
|
||||
|
@ -92,3 +92,19 @@ fn other_start() -> ! {
|
||||
// call the first main function in kernel.
|
||||
crate::kmain();
|
||||
}
|
||||
|
||||
pub fn get_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
asm!("mov %rsp, $0" : "=r"(sp));
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
pub fn set_sp(sp: usize) {
|
||||
unsafe {
|
||||
asm!("mov $0, %rsp" :: "r" (sp) : "memory");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@ use crate::signal::{send_signal, Signal};
|
||||
use crate::sync::Condvar;
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
use spin::RwLock;
|
||||
use crate::processor;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Stdin {
|
||||
@ -31,8 +32,12 @@ impl Stdin {
|
||||
match c as i32 {
|
||||
// INTR
|
||||
0o3 => {
|
||||
for proc in foregroud_processes {
|
||||
send_signal(proc, -1, SIGINT);
|
||||
if processor().tid_option().is_none() {
|
||||
for proc in foregroud_processes {
|
||||
send_signal(proc, -1, SIGINT);
|
||||
}
|
||||
} else {
|
||||
info!("ignored");
|
||||
}
|
||||
}
|
||||
_ => warn!("special char {} is unimplented", c),
|
||||
|
@ -25,7 +25,7 @@ use crate::sync::{Condvar, SpinLock, SpinNoIrqLock as Mutex};
|
||||
|
||||
use super::abi::{self, ProcInitInfo};
|
||||
use crate::process::thread_manager;
|
||||
use crate::signal::{SIGRTMAX, SigAction, Sigset};
|
||||
use crate::signal::{SIGRTMAX, SignalAction, SigSet, SignalStack};
|
||||
use bitflags::_core::cell::Ref;
|
||||
use core::mem::MaybeUninit;
|
||||
use pc_keyboard::KeyCode::BackTick;
|
||||
@ -42,9 +42,11 @@ pub struct Thread {
|
||||
// This is same as `proc.vm`
|
||||
pub vm: Arc<Mutex<MemorySet>>,
|
||||
pub proc: Arc<Mutex<Process>>,
|
||||
pub sig_mask: Sigset,
|
||||
pub sig_mask: SigSet,
|
||||
// if syscall or library function was interrupted by a signal
|
||||
pub int: bool,
|
||||
// this field is set from trap for convenience
|
||||
pub ustack_top: usize,
|
||||
}
|
||||
|
||||
/// Pid type
|
||||
@ -94,7 +96,8 @@ pub struct Process {
|
||||
|
||||
// delivered signals, tid specified thread, -1 stands for any thread
|
||||
pub signals: [Option<isize>; SIGRTMAX + 1],
|
||||
pub dispositions: [SigAction; SIGRTMAX + 1],
|
||||
pub dispositions: [SignalAction; SIGRTMAX + 1],
|
||||
pub sigaltstack: SignalStack,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
@ -193,11 +196,13 @@ impl Thread {
|
||||
child_exit: Arc::new(Condvar::new()),
|
||||
child_exit_code: BTreeMap::new(),
|
||||
signals: [None; SIGRTMAX + 1],
|
||||
dispositions: [SigAction::default(); SIGRTMAX + 1],
|
||||
dispositions: [SignalAction::default(); SIGRTMAX + 1],
|
||||
sigaltstack: SignalStack::default(),
|
||||
}
|
||||
.add_to_table(),
|
||||
sig_mask: Sigset::default(),
|
||||
sig_mask: SigSet::default(),
|
||||
int: false,
|
||||
ustack_top: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@ -388,11 +393,13 @@ impl Thread {
|
||||
child_exit: Arc::new(Condvar::new()),
|
||||
child_exit_code: BTreeMap::new(),
|
||||
signals: [None; SIGRTMAX + 1],
|
||||
dispositions: [SigAction::default(); SIGRTMAX + 1],
|
||||
dispositions: [SignalAction::default(); SIGRTMAX + 1],
|
||||
sigaltstack: SignalStack::default(),
|
||||
}
|
||||
.add_to_table(),
|
||||
sig_mask: Sigset::default(),
|
||||
sig_mask: SigSet::default(),
|
||||
int: false,
|
||||
ustack_top: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@ -422,6 +429,7 @@ impl Thread {
|
||||
child_exit_code: BTreeMap::new(),
|
||||
signals: [None; SIGRTMAX + 1],
|
||||
dispositions: proc.dispositions.clone(),
|
||||
sigaltstack: SignalStack::default(),
|
||||
}
|
||||
.add_to_table();
|
||||
// link to parent
|
||||
@ -440,6 +448,7 @@ impl Thread {
|
||||
proc: new_proc,
|
||||
sig_mask: self.sig_mask,
|
||||
int: false,
|
||||
ustack_top: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@ -461,6 +470,7 @@ impl Thread {
|
||||
proc: self.proc.clone(),
|
||||
sig_mask: self.sig_mask,
|
||||
int: false,
|
||||
ustack_top: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -5,26 +5,52 @@ pub const SIG_DFL: usize = 0;
|
||||
pub const SIG_IGN: usize = 1;
|
||||
|
||||
// yet there's a bug because of mismatching bits: https://sourceware.org/bugzilla/show_bug.cgi?id=25657
|
||||
pub type Sigset = u64; // just support 64bits size sigset
|
||||
pub type SigSet = u64; // just support 64bits size sigset
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct SigAction {
|
||||
pub struct SignalAction {
|
||||
pub handler: usize, // this field may be an union
|
||||
pub mask: Sigset,
|
||||
pub mask: SigSet,
|
||||
pub flags: u32,
|
||||
pub _restorer: usize,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Flags : u32 {
|
||||
const SA_NOCLDSTOP = 1;
|
||||
const SA_NOCLDWAIT = 2;
|
||||
const SA_SIGINFO = 4;
|
||||
const SA_ONSTACK = 0x08000000;
|
||||
const SA_RESTART = 0x10000000;
|
||||
const SA_NODEFER = 0x40000000;
|
||||
const SA_RESETHAND = 0x80000000;
|
||||
const SA_RESTORER = 0x04000000;
|
||||
#[repr(C)]
|
||||
pub union SigInfoFields {
|
||||
pad: [u8; Self::PAD_SIZE],
|
||||
// TODO: fill this union
|
||||
}
|
||||
|
||||
impl SigInfoFields {
|
||||
const PAD_SIZE: usize = 128 - 2 * core::mem::size_of::<i32>() - core::mem::size_of::<usize>();
|
||||
}
|
||||
|
||||
impl Default for SigInfoFields {
|
||||
fn default() -> Self {
|
||||
SigInfoFields {
|
||||
pad: [0; Self::PAD_SIZE]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SigInfo {
|
||||
pub signo: i32,
|
||||
pub errno: i32,
|
||||
pub code: i32,
|
||||
pub field: SigInfoFields,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SignalActionFlags : u32 {
|
||||
const NOCLDSTOP = 1;
|
||||
const NOCLDWAIT = 2;
|
||||
const SIGINFO = 4;
|
||||
const ONSTACK = 0x08000000;
|
||||
const RESTART = 0x10000000;
|
||||
const NODEFER = 0x40000000;
|
||||
const RESETHAND = 0x80000000;
|
||||
const RESTORER = 0x04000000;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ use rcore_thread::std_thread::{current, yield_now};
|
||||
use alloc::vec::Vec;
|
||||
use crate::processor;
|
||||
use crate::syscall::{SysError, SysResult};
|
||||
use crate::arch::{get_sp, set_sp};
|
||||
use crate::signal::SigInfo;
|
||||
use alloc::alloc::handle_alloc_error;
|
||||
|
||||
#[derive(Eq, PartialEq, FromPrimitive, Debug, Copy, Clone)]
|
||||
pub enum Signal {
|
||||
@ -108,6 +111,8 @@ pub fn send_signal(process: Arc<Mutex<Process>>, tid: isize, signal: Signal) {
|
||||
}
|
||||
}
|
||||
|
||||
// must be called with = user stack
|
||||
// FIXME: set user mode?
|
||||
#[inline(never)]
|
||||
pub(crate) fn handle_signal() {
|
||||
let signals = unsafe { current_thread() }.proc.lock().signals.iter().enumerate().filter_map(|(signum, tid)| {
|
||||
@ -123,28 +128,29 @@ pub(crate) fn handle_signal() {
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
unsafe { current_thread() }.int = false;
|
||||
unsafe { current_thread().int = false; }
|
||||
for signum in signals {
|
||||
use crate::signal::Flags;
|
||||
use crate::signal::SignalActionFlags;
|
||||
use Signal::*;
|
||||
|
||||
let signal = <Signal as num::FromPrimitive>::from_usize(signum).unwrap();
|
||||
info!("received signal: {:?}", signal);
|
||||
let action = {
|
||||
let mut process = unsafe { current_thread() }.proc.lock();
|
||||
let mut process = unsafe { current_thread().proc.lock() };
|
||||
process.signals[signum] = None;
|
||||
process.dispositions[signum]
|
||||
};
|
||||
let flags = Flags::from_bits_truncate(action.flags);
|
||||
let action_flags = SignalActionFlags::from_bits_truncate(action.flags);
|
||||
|
||||
// enter signal handler
|
||||
match action.handler {
|
||||
// TODO: complete default actions
|
||||
x if x == SIG_DFL => {
|
||||
match signal {
|
||||
SIGALRM | SIGHUP | SIGINT => {
|
||||
info!("default action: Term");
|
||||
// FIXME: exit code ref please?
|
||||
unsafe { current_thread() }.proc.lock().exit(signum + 128);
|
||||
unsafe { current_thread().proc.lock().exit(signum + 128); }
|
||||
yield_now();
|
||||
}
|
||||
_ => (),
|
||||
@ -156,21 +162,82 @@ pub(crate) fn handle_signal() {
|
||||
unimplemented!();
|
||||
}
|
||||
_ => {
|
||||
unsafe { current_thread() }.int = true;
|
||||
if flags.contains(Flags::SA_SIGINFO) {
|
||||
// TODO
|
||||
unimplemented!();
|
||||
unsafe { current_thread().int = true; }
|
||||
let sig_sp = {
|
||||
if action_flags.contains(SignalActionFlags::ONSTACK) {
|
||||
let stack = unsafe { current_thread().proc.lock().sigaltstack };
|
||||
let stack_flags = SignalStackFlags::from_bits_truncate(stack.flags);
|
||||
if !stack_flags.contains(SignalStackFlags::DISABLE) {
|
||||
stack.sp + stack.size
|
||||
} else {
|
||||
unsafe {
|
||||
current_thread().ustack_top
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
current_thread().ustack_top
|
||||
}
|
||||
}
|
||||
};
|
||||
if action_flags.contains(SignalActionFlags::SIGINFO) {
|
||||
unsafe {
|
||||
let action: extern "C" fn(i32, *mut SigInfo, usize) = core::mem::transmute(action.handler);
|
||||
// TODO: complete info
|
||||
let mut info = SigInfo {
|
||||
signo: signum as i32,
|
||||
errno: 0,
|
||||
code: 0,
|
||||
field: Default::default(),
|
||||
};
|
||||
// TODO: complete ucontext
|
||||
// let mut sp = get_sp();
|
||||
// sp = get_sp();
|
||||
// set_sp(sig_sp);
|
||||
action(signum as i32, &mut info as *mut SigInfo, 0);
|
||||
// set_sp(sp);
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
let handler: extern "C" fn(i32) = core::mem::transmute(action.handler);
|
||||
let mut sp = get_sp();
|
||||
sp = get_sp(); // get stack pointer after local variable `sp` is allocated
|
||||
set_sp(sig_sp);
|
||||
handler(signum as i32);
|
||||
set_sp(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if flags.contains(Flags::SA_RESTART) {
|
||||
if action_flags.contains(SignalActionFlags::RESTART) {
|
||||
// TODO: restart the syscall
|
||||
warn!("unsupported flag: {:?}", Flags::SA_RESTART);
|
||||
warn!("unsupported flag: {:?}", SignalActionFlags::RESTART);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SignalStackFlags : u32 {
|
||||
const ONSTACK = 1;
|
||||
const DISABLE = 2;
|
||||
const AUTODISARM = 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SignalStack {
|
||||
pub sp: usize,
|
||||
pub flags: u32,
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
impl Default for SignalStack {
|
||||
fn default() -> Self {
|
||||
SignalStack {
|
||||
sp: 0,
|
||||
flags: SignalStackFlags::DISABLE.bits,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ use alloc::collections::BTreeMap;
|
||||
use rcore_thread::std_thread::yield_now;
|
||||
#[cfg(feature = "profile")]
|
||||
use spin::Mutex;
|
||||
use crate::signal::{SigAction, Sigset};
|
||||
use crate::signal::{SignalAction, SigSet, SignalStack, Signal};
|
||||
|
||||
#[cfg(feature = "profile")]
|
||||
lazy_static! {
|
||||
@ -53,14 +53,15 @@ lazy_static! {
|
||||
|
||||
/// System call dispatcher
|
||||
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
||||
// let thread = unsafe { current_thread() };
|
||||
let mut syscall = Syscall { tf };
|
||||
syscall.syscall(id, args)
|
||||
let thread = unsafe { current_thread() };
|
||||
let mut syscall = Syscall { thread, tf };
|
||||
let ret = syscall.syscall(id, args);
|
||||
ret
|
||||
}
|
||||
|
||||
/// All context needed for syscall
|
||||
struct Syscall<'a> {
|
||||
// thread: &'a mut Thread,
|
||||
thread: &'a mut Thread,
|
||||
tf: &'a mut TrapFrame,
|
||||
}
|
||||
|
||||
@ -68,14 +69,12 @@ impl Syscall<'_> {
|
||||
/// Get current process
|
||||
/// spinlock is tend to deadlock, use busy waiting
|
||||
pub fn process(&self) -> MutexGuard<'_, Process, SpinNoIrq> {
|
||||
unsafe { current_thread() }.proc.busy_lock()
|
||||
// self.thread.proc.busy_lock()
|
||||
self.thread.proc.busy_lock()
|
||||
}
|
||||
|
||||
/// Get current virtual memory
|
||||
pub fn vm(&self) -> MutexGuard<'_, MemorySet, SpinNoIrq> {
|
||||
// self.thread.vm.lock()
|
||||
unsafe { current_thread() }.vm.lock()
|
||||
self.thread.vm.lock()
|
||||
}
|
||||
|
||||
/// System call dispatcher
|
||||
@ -213,17 +212,17 @@ impl Syscall<'_> {
|
||||
// signal
|
||||
SYS_RT_SIGACTION => self.sys_rt_sigaction(
|
||||
args[0],
|
||||
args[1] as *const SigAction,
|
||||
args[2] as *mut SigAction,
|
||||
args[1] as *const SignalAction,
|
||||
args[2] as *mut SignalAction,
|
||||
args[3],
|
||||
),
|
||||
SYS_RT_SIGPROCMASK => self.sys_rt_sigprocmask(
|
||||
args[0],
|
||||
args[1] as *const Sigset,
|
||||
args[2] as *mut Sigset,
|
||||
args[1] as *const SigSet,
|
||||
args[2] as *mut SigSet,
|
||||
args[3],
|
||||
),
|
||||
SYS_SIGALTSTACK => self.unimplemented("sigaltstack", Ok(0)),
|
||||
SYS_SIGALTSTACK => self.sys_sigaltstack(args[0] as *const SignalStack, args[1] as *mut SignalStack),
|
||||
SYS_KILL => self.sys_kill(args[0] as isize, args[1]),
|
||||
|
||||
// schedule
|
||||
|
@ -267,13 +267,13 @@ impl Syscall<'_> {
|
||||
}
|
||||
info!("setpgid: set pgid of process {} to {}", pid, pgid);
|
||||
let process_table = PROCESSES.read();
|
||||
// let process_table: BTreeMap<usize, Weak<Mutex<Process>>> = BTreeMap::new();
|
||||
let proc = process_table.get(&pid);
|
||||
if (proc.is_some()) {
|
||||
// TODO: check process pid is the child of calling process
|
||||
let lock = proc.unwrap().upgrade().unwrap();
|
||||
let mut proc = lock.lock();
|
||||
proc.pgid = pgid as i32;
|
||||
if let Some(proc) = proc.unwrap().upgrade() {
|
||||
let mut proc = proc.lock();
|
||||
proc.pgid = pgid as i32;
|
||||
}
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ESRCH)
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::process::{PROCESSES, thread_manager, process_of, current_thread};
|
||||
use crate::process::{process, process_group};
|
||||
use crate::signal::*;
|
||||
use crate::syscall::SysError::{EINVAL, ESRCH};
|
||||
use crate::syscall::SysError::{EINVAL, ESRCH, ENOMEM, EPERM};
|
||||
use crate::syscall::{SysResult, Syscall};
|
||||
use crate::thread;
|
||||
use num::FromPrimitive;
|
||||
@ -10,8 +10,8 @@ impl Syscall<'_> {
|
||||
pub fn sys_rt_sigaction(
|
||||
&self,
|
||||
signum: usize,
|
||||
act: *const SigAction,
|
||||
oldact: *mut SigAction,
|
||||
act: *const SignalAction,
|
||||
oldact: *mut SignalAction,
|
||||
sigsetsize: usize,
|
||||
) -> SysResult {
|
||||
if let Some(signal) = <Signal as FromPrimitive>::from_usize(signum) {
|
||||
@ -47,8 +47,8 @@ impl Syscall<'_> {
|
||||
pub fn sys_rt_sigprocmask(
|
||||
&mut self,
|
||||
how: usize,
|
||||
set: *const Sigset,
|
||||
oldset: *mut Sigset,
|
||||
set: *const SigSet,
|
||||
oldset: *mut SigSet,
|
||||
sigsetsize: usize,
|
||||
) -> SysResult {
|
||||
info!(
|
||||
@ -144,4 +144,31 @@ impl Syscall<'_> {
|
||||
Err(EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_sigaltstack(&self, ss: *const SignalStack, old_ss: *mut SignalStack) -> SysResult {
|
||||
const MINSIGSTKSZ: usize = 2048;
|
||||
if !old_ss.is_null() {
|
||||
let old_ss = unsafe { self.vm().check_write_ptr(old_ss)? };
|
||||
*old_ss = self.process().sigaltstack;
|
||||
}
|
||||
if !ss.is_null() {
|
||||
let ss = unsafe { self.vm().check_read_ptr(ss)? };
|
||||
|
||||
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 {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
let old_ss = &mut self.process().sigaltstack;
|
||||
let flags = SignalStackFlags::from_bits_truncate(old_ss.flags);
|
||||
if flags.contains(SignalStackFlags::ONSTACK) {
|
||||
return Err(EPERM);
|
||||
}
|
||||
*old_ss = *ss;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user