forked from M-Labs/libfringe
parent
52325b07c0
commit
418c53797e
|
@ -6,6 +6,7 @@
|
||||||
extern crate test;
|
extern crate test;
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[bench]
|
#[bench]
|
||||||
fn kernel_swap(b: &mut Bencher) {
|
fn kernel_swap(b: &mut Bencher) {
|
||||||
b.iter(|| unsafe {
|
b.iter(|| unsafe {
|
||||||
|
@ -17,3 +18,16 @@ fn kernel_swap(b: &mut Bencher) {
|
||||||
: "volatile");
|
: "volatile");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
#[bench]
|
||||||
|
fn kernel_swap(b: &mut Bencher) {
|
||||||
|
b.iter(|| unsafe {
|
||||||
|
asm!("mov $$24, %eax\n\
|
||||||
|
int $$0x80"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
: "eax"
|
||||||
|
: "volatile");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -11,3 +11,7 @@ mod common;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[path = "x86_64/mod.rs"]
|
#[path = "x86_64/mod.rs"]
|
||||||
mod imp;
|
mod imp;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
#[path = "x86/mod.rs"]
|
||||||
|
mod imp;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
--32
|
|
@ -0,0 +1,44 @@
|
||||||
|
// This file is part of libfringe, a low-level green threading library.
|
||||||
|
// Copyright (c) 2015, edef <edef@edef.eu>
|
||||||
|
// See the LICENSE file included in this distribution.
|
||||||
|
|
||||||
|
//! initialise a new context
|
||||||
|
//! arguments:
|
||||||
|
//! * eax: stack pointer
|
||||||
|
//! * ebx: function pointer
|
||||||
|
//! * ecx: data pointer
|
||||||
|
//! * edx: stack limit
|
||||||
|
//!
|
||||||
|
//! return values:
|
||||||
|
//! * eax: new stack pointer
|
||||||
|
|
||||||
|
// switch to the fresh stack
|
||||||
|
xchg %esp, %eax
|
||||||
|
|
||||||
|
// save the data pointer, function pointer, and stack limit, respectively
|
||||||
|
pushl %ecx
|
||||||
|
pushl %ebx
|
||||||
|
pushl %edx
|
||||||
|
|
||||||
|
// save the return address, control flow continues at label 1
|
||||||
|
call 1f
|
||||||
|
// we arrive here once this context is reactivated (see swap.s)
|
||||||
|
|
||||||
|
// restore the stack limit, data pointer, and function pointer, respectively
|
||||||
|
// TODO: this stack limit location is specific to Linux/FreeBSD.
|
||||||
|
popl %gs:0x30
|
||||||
|
popl %eax
|
||||||
|
|
||||||
|
// initialise the frame pointer
|
||||||
|
movl $$0, %ebp
|
||||||
|
|
||||||
|
// call the function pointer with the data pointer (top of the stack is the first argument)
|
||||||
|
call *%eax
|
||||||
|
|
||||||
|
// crash if it ever returns
|
||||||
|
ud2
|
||||||
|
|
||||||
|
1:
|
||||||
|
// save our neatly-setup new stack
|
||||||
|
xchg %esp, %eax
|
||||||
|
// back into Rust-land we go
|
|
@ -0,0 +1,47 @@
|
||||||
|
// This file is part of libfringe, a low-level green threading library.
|
||||||
|
// Copyright (c) 2015, edef <edef@edef.eu>
|
||||||
|
// See the LICENSE file included in this distribution.
|
||||||
|
use core::prelude::*;
|
||||||
|
|
||||||
|
use stack::Stack;
|
||||||
|
use super::common::{push, rust_trampoline};
|
||||||
|
|
||||||
|
pub const STACK_ALIGN: usize = 16;
|
||||||
|
|
||||||
|
#[allow(raw_pointer_derive)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Registers {
|
||||||
|
esp: *mut usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Registers {
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
|
||||||
|
let sp_limit = stack.limit();
|
||||||
|
let mut sp = stack.top() as *mut usize;
|
||||||
|
let f_ptr = push(&mut sp, f);
|
||||||
|
|
||||||
|
asm!(include_str!("init.s")
|
||||||
|
: "={eax}"(sp)
|
||||||
|
: "{eax}" (sp),
|
||||||
|
"{ebx}" (rust_trampoline::<F>),
|
||||||
|
"{ecx}" (f_ptr),
|
||||||
|
"{edx}" (sp_limit)
|
||||||
|
:
|
||||||
|
: "volatile");
|
||||||
|
|
||||||
|
Registers { esp: sp }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn swap(&mut self) {
|
||||||
|
asm!(include_str!("swap.s")
|
||||||
|
:
|
||||||
|
: "{eax}" (&mut self.esp)
|
||||||
|
: "eax", "ebx", "ecx", "edx", "esi", "edi", //"ebp", "esp",
|
||||||
|
"mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7",
|
||||||
|
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
|
||||||
|
"cc"
|
||||||
|
: "volatile");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// This file is part of libfringe, a low-level green threading library.
|
||||||
|
// Copyright (c) 2015, edef <edef@edef.eu>
|
||||||
|
// See the LICENSE file included in this distribution.
|
||||||
|
|
||||||
|
//! switch to a new context
|
||||||
|
//! arguments:
|
||||||
|
//! * eax: stack pointer pointer
|
||||||
|
|
||||||
|
// save the Rust stack limit and the frame pointer, respectively
|
||||||
|
// TODO: this stack limit location is specific to Linux/FreeBSD.
|
||||||
|
pushl %gs:0x30
|
||||||
|
pushl %ebp
|
||||||
|
|
||||||
|
// save the return address to the stack, control flow continues at label 1
|
||||||
|
call 1f
|
||||||
|
// we arrive here once this context is reactivated
|
||||||
|
|
||||||
|
// restore the frame pointer and the Rust stack limit, respectively
|
||||||
|
popl %ebp
|
||||||
|
// TODO: this stack limit location is specific to Linux/FreeBSD.
|
||||||
|
popl %gs:0x30
|
||||||
|
|
||||||
|
// and we merrily go on our way, back into Rust-land
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1:
|
||||||
|
// retrieve the new stack pointer
|
||||||
|
movl (%eax), %ebx
|
||||||
|
// save the old stack pointer
|
||||||
|
movl %esp, (%eax)
|
||||||
|
// switch to the new stack pointer
|
||||||
|
movl %ebx, %esp
|
||||||
|
|
||||||
|
// jump into the new context (return to the call point)
|
||||||
|
// doing this instead of a straight `ret` is 8ns slower,
|
||||||
|
// presumably because the branch predictor tries to be clever about it
|
||||||
|
popl %eax
|
||||||
|
jmpl *%eax
|
||||||
|
|
||||||
|
2:
|
Loading…
Reference in New Issue