2014-12-24 14:28:21 +08:00
|
|
|
use core::prelude::*;
|
|
|
|
|
|
|
|
use core::mem::transmute;
|
|
|
|
use core::raw;
|
|
|
|
use alloc::boxed::Box;
|
2014-12-23 11:24:40 +08:00
|
|
|
use fn_box::FnBox;
|
|
|
|
|
2014-12-24 13:12:39 +08:00
|
|
|
use stack::Stack;
|
|
|
|
use arch::{mod, Registers};
|
|
|
|
|
2014-12-23 11:24:40 +08:00
|
|
|
pub struct Context {
|
|
|
|
regs: Registers,
|
|
|
|
stack: Stack
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type BoxedFn<Args, Result> = Box<FnBox<Args, Result> + Send + 'static>;
|
|
|
|
pub type StartFn<T, Args, Result> = fn(data: *mut T, f: BoxedFn<Args, Result>) -> !;
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub fn new<T, Args, Result>(init: StartFn<T, Args, Result>, data: *mut T,
|
|
|
|
f: BoxedFn<Args, Result>) -> Context {
|
2014-12-24 13:12:39 +08:00
|
|
|
let mut stack = Stack::new(4 << 20);
|
2014-12-23 11:24:40 +08:00
|
|
|
let f: raw::TraitObject = unsafe { transmute(f) };
|
|
|
|
|
|
|
|
Context {
|
2014-12-24 13:12:39 +08:00
|
|
|
regs: arch::initialise_call_frame(&mut stack,
|
2014-12-24 13:53:36 +08:00
|
|
|
init_ctx::<T, Args, Result> as arch::uintptr_t,
|
|
|
|
&[init as arch::uintptr_t,
|
|
|
|
data as arch::uintptr_t,
|
|
|
|
f.data as arch::uintptr_t,
|
|
|
|
f.vtable as arch::uintptr_t]),
|
2014-12-23 11:24:40 +08:00
|
|
|
stack: stack
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-24 13:12:39 +08:00
|
|
|
unsafe extern "C" fn init_ctx<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
|
|
|
|
f_data: *mut (), f_vtable: *mut ()) -> ! {
|
2014-12-23 11:24:40 +08:00
|
|
|
let f: BoxedFn<A, R> = transmute(raw::TraitObject {
|
|
|
|
data: f_data,
|
|
|
|
vtable: f_vtable
|
|
|
|
});
|
|
|
|
|
|
|
|
start(data, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub unsafe fn native() -> Context {
|
|
|
|
Context {
|
2014-12-24 13:12:39 +08:00
|
|
|
regs: Registers::new(),
|
|
|
|
stack: Stack::native(arch::get_sp_limit())
|
2014-12-23 11:24:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) {
|
2014-12-24 13:12:39 +08:00
|
|
|
arch::set_sp_limit(in_context.stack.limit());
|
|
|
|
arch::swapcontext(&mut out_context.regs, &mut in_context.regs);
|
2014-12-23 11:24:40 +08:00
|
|
|
}
|
|
|
|
}
|