WIP: Signal handling

This commit is contained in:
Jeremy Soller
2017-07-09 21:34:38 -06:00
parent 7e52541f39
commit b5ff0aabd5
7 changed files with 151 additions and 47 deletions
+14 -4
View File
@@ -1,6 +1,7 @@
use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::{BTreeMap, Vec, VecDeque};
use core::mem;
use spin::Mutex;
use context::arch;
@@ -8,7 +9,8 @@ use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls};
use device;
use scheme::{SchemeNamespace, FileHandle};
use syscall::data::Event;
use syscall::data::{Event, SigAction};
use syscall::flag::SIG_DFL;
use sync::{WaitMap, WaitQueue};
/// Unique identifier for a context (i.e. `pid`).
@@ -69,6 +71,8 @@ pub struct Context {
pub heap: Option<SharedMemory>,
/// User stack
pub stack: Option<Memory>,
/// User signal stack
pub sigstack: Option<Memory>,
/// User Thread local storage
pub tls: Option<Tls>,
/// User grants
@@ -83,8 +87,8 @@ pub struct Context {
pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
/// The open files in the scheme
pub files: Arc<Mutex<Vec<Option<File>>>>,
/// Singal handlers
pub handlers: Arc<Mutex<BTreeMap<u8, usize>>>,
/// Singal actions
pub actions: Arc<Mutex<Vec<SigAction>>>,
}
impl Context {
@@ -111,6 +115,7 @@ impl Context {
image: Vec::new(),
heap: None,
stack: None,
sigstack: None,
tls: None,
grants: Arc::new(Mutex::new(Vec::new())),
name: Arc::new(Mutex::new(Vec::new())),
@@ -118,7 +123,12 @@ impl Context {
events: Arc::new(WaitQueue::new()),
env: Arc::new(Mutex::new(BTreeMap::new())),
files: Arc::new(Mutex::new(Vec::new())),
handlers: Arc::new(Mutex::new(BTreeMap::new())),
actions: Arc::new(Mutex::new(vec![SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: 0,
sa_restorer: unsafe { mem::transmute(0usize) },
}; 128])),
}
}
+26 -7
View File
@@ -1,9 +1,12 @@
use core::mem;
use core::sync::atomic::Ordering;
use context::{arch, contexts, Context, Status, CONTEXT_ID};
use interrupt::irq::PIT_TICKS;
use start::usermode;
use syscall::flag::{SIG_DFL, SIG_IGN};
use gdt;
use interrupt;
use interrupt::irq::PIT_TICKS;
use syscall;
use time;
@@ -118,19 +121,35 @@ pub unsafe fn switch() -> bool {
}
extern "C" fn signal_handler(sig: usize) {
let handler = {
let action = {
let contexts = contexts();
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
let context = context_lock.read();
let handlers = context.handlers.lock();
handlers.get(&(sig as u8)).map_or(0, |sig| *sig)
let actions = context.actions.lock();
actions[sig]
};
println!("Signal handler: {}, {:X}", sig, handler);
println!("Signal handler: {:X}, {:?}", sig, action);
if handler == 0 {
let handler = action.sa_handler as usize;
let restorer = action.sa_restorer as usize;
if handler == SIG_DFL {
println!("Exit {:X}", sig);
syscall::exit(sig);
} else if handler == SIG_IGN {
println!("Ignore");
} else {
// TODO: Call handler
println!("Call {:X}", handler);
unsafe {
let mut sp = ::USER_SIGSTACK_OFFSET + ::USER_SIGSTACK_SIZE - 256;
sp = (sp / 16) * 16;
sp -= mem::size_of::<usize>();
*(sp as *mut usize) = restorer;
usermode(handler, sp, sig);
}
}
}