use core::prelude::*; use core::mem::transmute; use core::raw; use alloc::boxed::Box; use fn_box::FnBox; use stack::Stack; use arch::{self, Registers}; pub struct Context { regs: Registers, stack: Stack } pub type BoxedFn = Box + Send + 'static>; pub type StartFn = fn(data: *mut T, f: BoxedFn) -> !; impl Context { pub fn new(init: StartFn, data: *mut T, f: BoxedFn) -> Context { let mut stack = Stack::new(4 << 20); let f: raw::TraitObject = unsafe { transmute(f) }; Context { regs: arch::initialise_call_frame(&mut stack, init_ctx:: 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]), stack: stack } } } unsafe extern "C" fn init_ctx(start: StartFn, data: *mut T, f_data: *mut (), f_vtable: *mut ()) -> ! { let f: BoxedFn = transmute(raw::TraitObject { data: f_data, vtable: f_vtable }); start(data, f) } impl Context { pub unsafe fn native() -> Context { Context { regs: Registers::new(), stack: Stack::native(arch::get_sp_limit()) } } #[inline(always)] pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) { arch::set_sp_limit(in_context.stack.limit()); arch::swapcontext(&mut out_context.regs, &mut in_context.regs); } }