Restore kernel parameters on sigreturn
This commit is contained in:
@@ -13,7 +13,7 @@ alloc_kernel = { path = "alloc_kernel" }
|
||||
bitflags = "0.7"
|
||||
spin = "0.4"
|
||||
raw-cpuid = { git = "https://github.com/gz/rust-cpuid", branch = "master" }
|
||||
redox_syscall = "0.1"
|
||||
redox_syscall = { version = "0.1", path = "/home/jeremy/Projects/syscall" }
|
||||
|
||||
[dependencies.goblin]
|
||||
version = "0.0.10"
|
||||
|
||||
@@ -65,6 +65,10 @@ pub struct Context {
|
||||
pub kfx: Option<Box<[u8]>>,
|
||||
/// Kernel stack
|
||||
pub kstack: Option<Box<[u8]>>,
|
||||
/// Kernel signal backup
|
||||
pub ksig: Option<(arch::Context, Box<[u8]>, Box<[u8]>)>,
|
||||
/// Restore ksig context on next switch
|
||||
pub ksig_restore: bool,
|
||||
/// Executable image
|
||||
pub image: Vec<SharedMemory>,
|
||||
/// User heap
|
||||
@@ -88,7 +92,7 @@ pub struct Context {
|
||||
/// The open files in the scheme
|
||||
pub files: Arc<Mutex<Vec<Option<File>>>>,
|
||||
/// Singal actions
|
||||
pub actions: Arc<Mutex<Vec<SigAction>>>,
|
||||
pub actions: Arc<Mutex<Vec<(SigAction, usize)>>>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@@ -112,6 +116,8 @@ impl Context {
|
||||
arch: arch::Context::new(),
|
||||
kfx: None,
|
||||
kstack: None,
|
||||
ksig: None,
|
||||
ksig_restore: false,
|
||||
image: Vec::new(),
|
||||
heap: None,
|
||||
stack: None,
|
||||
@@ -123,12 +129,14 @@ impl Context {
|
||||
events: Arc::new(WaitQueue::new()),
|
||||
env: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
files: Arc::new(Mutex::new(Vec::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])),
|
||||
actions: Arc::new(Mutex::new(vec![(
|
||||
SigAction {
|
||||
sa_handler: unsafe { mem::transmute(SIG_DFL) },
|
||||
sa_mask: [0; 2],
|
||||
sa_flags: 0,
|
||||
},
|
||||
0
|
||||
); 128])),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,29 @@ pub unsafe fn switch() -> bool {
|
||||
// println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock()));
|
||||
}
|
||||
|
||||
if context.ksig_restore {
|
||||
println!("Restore from ksig");
|
||||
|
||||
let ksig = context.ksig.take().expect("context::switch: ksig not set with ksig_restore");
|
||||
context.arch = ksig.0;
|
||||
if let Some(ref mut kfx) = context.kfx {
|
||||
kfx.clone_from_slice(&ksig.1);
|
||||
} else {
|
||||
panic!("context::switch: kfx not set with ksig_restore");
|
||||
}
|
||||
if let Some(ref mut kstack) = context.kstack {
|
||||
kstack.clone_from_slice(&ksig.2);
|
||||
} else {
|
||||
panic!("context::switch: kstack not set with ksig_restore");
|
||||
}
|
||||
context.ksig_restore = false;
|
||||
|
||||
//TODO: Interrupt
|
||||
if context.status == Status::Blocked {
|
||||
context.unblock();
|
||||
}
|
||||
}
|
||||
|
||||
if context.status == Status::Blocked && !context.pending.is_empty() {
|
||||
context.unblock();
|
||||
}
|
||||
@@ -112,6 +135,20 @@ pub unsafe fn switch() -> bool {
|
||||
arch::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
|
||||
|
||||
if let Some(sig) = to_sig {
|
||||
//TODO: Allow nested signals
|
||||
assert!((&mut *to_ptr).ksig.is_none());
|
||||
|
||||
let arch = (&mut *to_ptr).arch.clone();
|
||||
let kfx = match (&mut *to_ptr).kfx {
|
||||
Some(ref kfx) => kfx.clone(),
|
||||
None => panic!("context::switch: no kfx during signal")
|
||||
};
|
||||
let kstack = match (&mut *to_ptr).kstack {
|
||||
Some(ref kstack) => kstack.clone(),
|
||||
None => panic!("context::switch: no kstack during signal")
|
||||
};
|
||||
|
||||
(&mut *to_ptr).ksig = Some((arch, kfx, kstack));
|
||||
(&mut *to_ptr).arch.signal_stack(signal_handler, sig);
|
||||
}
|
||||
|
||||
@@ -121,7 +158,7 @@ pub unsafe fn switch() -> bool {
|
||||
}
|
||||
|
||||
extern "C" fn signal_handler(sig: usize) {
|
||||
let action = {
|
||||
let (action, restorer) = {
|
||||
let contexts = contexts();
|
||||
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
|
||||
let context = context_lock.read();
|
||||
@@ -132,7 +169,6 @@ extern "C" fn signal_handler(sig: usize) {
|
||||
println!("Signal handler: {:X}, {:?}", sig, action);
|
||||
|
||||
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);
|
||||
|
||||
@@ -112,8 +112,10 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
|
||||
None
|
||||
} else {
|
||||
Some(validate_slice_mut(d as *mut SigAction, 1).map(|oldact| &mut oldact[0])?)
|
||||
}
|
||||
},
|
||||
e
|
||||
),
|
||||
SYS_SIGRETURN => sigreturn(),
|
||||
SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
|
||||
SYS_PHYSALLOC => physalloc(b),
|
||||
SYS_PHYSFREE => physfree(b, c),
|
||||
|
||||
@@ -378,6 +378,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
|
||||
context.kstack = Some(stack);
|
||||
}
|
||||
|
||||
// TODO: Clone ksig?
|
||||
|
||||
// Setup heap
|
||||
if flags & CLONE_VM == CLONE_VM {
|
||||
// Copy user image mapping, if found
|
||||
@@ -772,12 +774,14 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||
let files = Arc::new(Mutex::new(context.files.lock().clone()));
|
||||
context.files = files.clone();
|
||||
|
||||
context.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]));
|
||||
context.actions = Arc::new(Mutex::new(vec![(
|
||||
SigAction {
|
||||
sa_handler: unsafe { mem::transmute(SIG_DFL) },
|
||||
sa_mask: [0; 2],
|
||||
sa_flags: 0,
|
||||
},
|
||||
0
|
||||
); 128]));
|
||||
|
||||
let vfork = context.vfork;
|
||||
context.vfork = false;
|
||||
@@ -1011,7 +1015,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>) -> Result<usize> {
|
||||
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>, restorer: usize) -> Result<usize> {
|
||||
if sig > 0 && sig <= 0x7F {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -1019,11 +1023,11 @@ pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mu
|
||||
let mut actions = context.actions.lock();
|
||||
|
||||
if let Some(oldact) = oldact_opt {
|
||||
*oldact = actions[sig];
|
||||
*oldact = actions[sig].0;
|
||||
}
|
||||
|
||||
if let Some(act) = act_opt {
|
||||
actions[sig] = *act;
|
||||
actions[sig] = (*act, restorer);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
@@ -1032,6 +1036,22 @@ pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mu
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sigreturn() -> Result<usize> {
|
||||
println!("Sigreturn");
|
||||
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
context.ksig_restore = true;
|
||||
context.block();
|
||||
}
|
||||
|
||||
unsafe { context::switch(); }
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn reap(pid: ContextId) -> Result<ContextId> {
|
||||
// Spin until not running
|
||||
let mut running = true;
|
||||
|
||||
Reference in New Issue
Block a user