refactoring!
This commit is contained in:
parent
555a3d73c0
commit
791173fd97
|
@ -0,0 +1,119 @@
|
||||||
|
use std::simd::u64x2;
|
||||||
|
use std::mem::{size_of, zeroed};
|
||||||
|
|
||||||
|
use stack::Stack;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "lwut_bootstrap"]
|
||||||
|
pub fn bootstrap();
|
||||||
|
#[link_name = "lwut_swapcontext"]
|
||||||
|
pub fn swapcontext(save: *mut Registers, restore: *mut Registers);
|
||||||
|
#[link_name = "lwut_get_sp_limit"]
|
||||||
|
pub fn get_sp_limit() -> *const u8;
|
||||||
|
#[link_name = "lwut_set_sp_limit"]
|
||||||
|
pub fn set_sp_limit(limit: *const u8);
|
||||||
|
#[link_name = "lwut_abort"]
|
||||||
|
pub fn abort() -> !;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type uintptr_t = u64;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Registers {
|
||||||
|
rbx: u64,
|
||||||
|
rsp: u64,
|
||||||
|
rbp: u64,
|
||||||
|
rdi: u64,
|
||||||
|
r12: u64,
|
||||||
|
r13: u64,
|
||||||
|
r14: u64,
|
||||||
|
r15: u64,
|
||||||
|
ip: u64,
|
||||||
|
xmm0: u64x2,
|
||||||
|
xmm1: u64x2,
|
||||||
|
xmm2: u64x2,
|
||||||
|
xmm3: u64x2,
|
||||||
|
xmm4: u64x2,
|
||||||
|
xmm5: u64x2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Registers {
|
||||||
|
pub fn new() -> Registers {
|
||||||
|
unsafe {
|
||||||
|
Registers {
|
||||||
|
ip: abort as u64,
|
||||||
|
.. zeroed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! into_regs_ {
|
||||||
|
($regs:ident { $reg:ident } <- $iter:ident) => {
|
||||||
|
match $iter.next() {
|
||||||
|
Some(value) => {
|
||||||
|
$regs.$reg = *value;
|
||||||
|
Some($iter)
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($regs:ident { $reg:ident, $($regs_rest:ident),* } <- $iter:ident) => {
|
||||||
|
match $iter.next() {
|
||||||
|
Some(value) => {
|
||||||
|
$regs.$reg = *value;
|
||||||
|
into_regs_!($regs { $($regs_rest),* } <- $iter)
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! into_regs {
|
||||||
|
($regs:ident { $($regs_rest:ident),* } <- $iter:expr) => {
|
||||||
|
{
|
||||||
|
let mut iter = $iter;
|
||||||
|
into_regs_!($regs { $($regs_rest),* } <- iter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialise_call_frame(stack: &mut Stack, init: uintptr_t, args: &[uintptr_t]) -> Registers {
|
||||||
|
let sp = stack.top() as *mut uintptr_t;
|
||||||
|
let sp = align_down_mut(sp, 16);
|
||||||
|
let sp = offset_mut(sp, -1);
|
||||||
|
unsafe {
|
||||||
|
*sp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut regs = Registers {
|
||||||
|
rbp: 0,
|
||||||
|
rsp: sp as uintptr_t,
|
||||||
|
ip: bootstrap as uintptr_t,
|
||||||
|
r12: init,
|
||||||
|
.. Registers::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
match into_regs!(regs { rdi, r13, r14, r15 } <- args.iter()) {
|
||||||
|
Some(mut args) => if args.next().is_some() {
|
||||||
|
panic!("too many arguments")
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn align_down_mut<T>(sp: *mut T, n: uint) -> *mut T {
|
||||||
|
let sp = (sp as uint) & !(n - 1);
|
||||||
|
sp as *mut T
|
||||||
|
}
|
||||||
|
|
||||||
|
// ptr::offset_mmut is positive ints only
|
||||||
|
#[inline]
|
||||||
|
pub fn offset_mut<T>(ptr: *mut T, count: int) -> *mut T {
|
||||||
|
(ptr as int + count * (size_of::<T>() as int)) as *mut T
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
BITS 64
|
BITS 64
|
||||||
|
|
||||||
;; the structure containing every register that is saved on context switches.
|
;; the structure containing every register that is saved on context switches.
|
||||||
;; this needs to match the struct in context.rs, or shit will break badly.
|
;; this needs to match the struct in arch.rs, or shit will break badly.
|
||||||
struc context
|
struc context
|
||||||
ctx_rbx resq 1
|
ctx_rbx resq 1
|
||||||
ctx_rsp resq 1
|
ctx_rsp resq 1
|
||||||
|
|
|
@ -1,85 +1,39 @@
|
||||||
use libc;
|
use libc;
|
||||||
use stack::Stack;
|
use std::mem::transmute;
|
||||||
use std::simd::u64x2;
|
|
||||||
use std::mem::{zeroed, size_of, transmute};
|
|
||||||
use std::raw;
|
use std::raw;
|
||||||
use fn_box::FnBox;
|
use fn_box::FnBox;
|
||||||
|
|
||||||
|
use stack::Stack;
|
||||||
|
use arch::{mod, Registers};
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
regs: Registers,
|
regs: Registers,
|
||||||
stack: Stack
|
stack: Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
struct Registers {
|
|
||||||
rbx: u64,
|
|
||||||
rsp: u64,
|
|
||||||
rbp: u64,
|
|
||||||
rdi: u64,
|
|
||||||
r12: u64,
|
|
||||||
r13: u64,
|
|
||||||
r14: u64,
|
|
||||||
r15: u64,
|
|
||||||
ip: u64,
|
|
||||||
xmm0: u64x2,
|
|
||||||
xmm1: u64x2,
|
|
||||||
xmm2: u64x2,
|
|
||||||
xmm3: u64x2,
|
|
||||||
xmm4: u64x2,
|
|
||||||
xmm5: u64x2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Registers {
|
|
||||||
fn zeroed() -> Registers { unsafe { zeroed() } }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn lwut_bootstrap();
|
|
||||||
fn lwut_swapcontext(save: *mut Registers, restore: *mut Registers);
|
|
||||||
fn lwut_get_sp_limit() -> *const u8;
|
|
||||||
fn lwut_set_sp_limit(limit: *const u8);
|
|
||||||
fn lwut_abort() -> !;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type BoxedFn<Args, Result> = Box<FnBox<Args, Result> + Send + 'static>;
|
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>) -> !;
|
pub type StartFn<T, Args, Result> = fn(data: *mut T, f: BoxedFn<Args, Result>) -> !;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new<T, Args, Result>(init: StartFn<T, Args, Result>, data: *mut T,
|
pub fn new<T, Args, Result>(init: StartFn<T, Args, Result>, data: *mut T,
|
||||||
f: BoxedFn<Args, Result>) -> Context {
|
f: BoxedFn<Args, Result>) -> Context {
|
||||||
let stack = Stack::new(4 << 20);
|
let mut stack = Stack::new(4 << 20);
|
||||||
|
|
||||||
let sp = stack.top() as *mut uint;
|
|
||||||
let sp = align_down_mut(sp, 16);
|
|
||||||
let sp = offset_mut(sp, -1);
|
|
||||||
unsafe {
|
|
||||||
*sp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let f: raw::TraitObject = unsafe { transmute(f) };
|
let f: raw::TraitObject = unsafe { transmute(f) };
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
regs: Registers {
|
regs: arch::initialise_call_frame(&mut stack,
|
||||||
rbp: 0,
|
init_ctx::<T, Args, Result> as libc::uintptr_t,
|
||||||
rsp: sp as libc::uintptr_t,
|
&[init as libc::uintptr_t,
|
||||||
ip: lwut_bootstrap as libc::uintptr_t,
|
data as libc::uintptr_t,
|
||||||
r12: lwut_init::<T, Args, Result> as libc::uintptr_t,
|
f.data as libc::uintptr_t,
|
||||||
rdi: init as libc::uintptr_t,
|
f.vtable as libc::uintptr_t]),
|
||||||
r13: data as libc::uintptr_t,
|
|
||||||
r14: f.data as libc::uintptr_t,
|
|
||||||
r15: f.vtable as libc::uintptr_t,
|
|
||||||
// r8: …,
|
|
||||||
// r9: …,
|
|
||||||
.. Registers::zeroed()
|
|
||||||
},
|
|
||||||
stack: stack
|
stack: stack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn lwut_init<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
|
unsafe extern "C" fn init_ctx<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
|
||||||
f_data: *mut (), f_vtable: *mut ()) -> ! {
|
f_data: *mut (), f_vtable: *mut ()) -> ! {
|
||||||
let f: BoxedFn<A, R> = transmute(raw::TraitObject {
|
let f: BoxedFn<A, R> = transmute(raw::TraitObject {
|
||||||
data: f_data,
|
data: f_data,
|
||||||
vtable: f_vtable
|
vtable: f_vtable
|
||||||
|
@ -91,30 +45,15 @@ unsafe extern "C" fn lwut_init<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
|
||||||
impl Context {
|
impl Context {
|
||||||
pub unsafe fn native() -> Context {
|
pub unsafe fn native() -> Context {
|
||||||
Context {
|
Context {
|
||||||
regs: Registers {
|
regs: Registers::new(),
|
||||||
ip: lwut_abort as libc::uintptr_t,
|
stack: Stack::native(arch::get_sp_limit())
|
||||||
.. Registers::zeroed()
|
|
||||||
},
|
|
||||||
stack: Stack::native(lwut_get_sp_limit())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) {
|
pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) {
|
||||||
lwut_set_sp_limit(in_context.stack.limit());
|
arch::set_sp_limit(in_context.stack.limit());
|
||||||
lwut_swapcontext(&mut out_context.regs, &mut in_context.regs);
|
arch::swapcontext(&mut out_context.regs, &mut in_context.regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn align_down_mut<T>(sp: *mut T, n: uint) -> *mut T {
|
|
||||||
let sp = (sp as uint) & !(n - 1);
|
|
||||||
sp as *mut T
|
|
||||||
}
|
|
||||||
|
|
||||||
// ptr::offset_mmut is positive ints only
|
|
||||||
#[inline]
|
|
||||||
pub fn offset_mut<T>(ptr: *mut T, count: int) -> *mut T {
|
|
||||||
(ptr as int + count * (size_of::<T>() as int)) as *mut T
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(default_type_params)]
|
#![feature(default_type_params, macro_rules)]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate fn_box;
|
extern crate fn_box;
|
||||||
|
|
||||||
|
@ -6,3 +6,6 @@ pub use context::Context;
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
mod stack;
|
mod stack;
|
||||||
|
|
||||||
|
mod arch;
|
||||||
|
mod platform;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
use libc;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "lwut_stack_register"]
|
||||||
|
pub fn stack_register(start: *const u8, end: *const u8) -> libc::c_uint;
|
||||||
|
#[link_name = "lwut_stack_deregister"]
|
||||||
|
pub fn stack_deregister(id: libc::c_uint);
|
||||||
|
}
|
12
src/stack.rs
12
src/stack.rs
|
@ -1,4 +1,5 @@
|
||||||
use libc;
|
use libc;
|
||||||
|
use platform;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
|
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
|
||||||
MapNonStandardFlags};
|
MapNonStandardFlags};
|
||||||
|
@ -17,11 +18,6 @@ pub enum Stack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn lwut_stack_register(start: *const u8, end: *const u8) -> libc::c_uint;
|
|
||||||
fn lwut_stack_deregister(id: libc::c_uint);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
pub fn new(size: uint) -> Stack {
|
pub fn new(size: uint) -> Stack {
|
||||||
let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
|
let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
|
||||||
|
@ -36,8 +32,8 @@ impl Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
let valgrind_id = unsafe {
|
let valgrind_id = unsafe {
|
||||||
lwut_stack_register(buf.data().offset(buf.len() as int) as *const _,
|
platform::stack_register(buf.data().offset(buf.len() as int) as *const _,
|
||||||
buf.data() as *const _)
|
buf.data() as *const _)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +87,7 @@ impl Drop for Stack {
|
||||||
match *self {
|
match *self {
|
||||||
Stack::Native { .. } => {},
|
Stack::Native { .. } => {},
|
||||||
Stack::Managed { valgrind_id, .. } => unsafe {
|
Stack::Managed { valgrind_id, .. } => unsafe {
|
||||||
lwut_stack_deregister(valgrind_id);
|
platform::stack_deregister(valgrind_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue