add Context::swap2, to allow distinct save/restore contexts

Fix #5

Context::swap is now implemented in terms of Context::swap2, and it
might make sense to remove Context::swap entirely at some point.
This commit is contained in:
edef 2016-03-22 07:50:50 +01:00
parent 2b23083455
commit 709dad1c4a
5 changed files with 25 additions and 11 deletions

View File

@ -32,10 +32,13 @@ impl Registers {
}
#[inline(always)]
pub unsafe fn swap(&mut self) {
pub unsafe fn swap2(out_regs: *mut Registers, in_regs: *const Registers) {
let out_espp = &mut (*out_regs).esp;
let in_espp = &(*in_regs).esp;
asm!(include_str!("swap.s")
:
: "{eax}" (&mut self.esp)
: "{eax}" (out_espp),
"{ebx}" (in_espp)
: "eax", "ebx", "ecx", "edx", "esi", "edi", //"ebp", "esp",
"mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",

View File

@ -4,7 +4,8 @@
//! switch to a new context
//! arguments:
//! * eax: stack pointer pointer
//! * eax: stack pointer out pointer
//! * ebx: stack pointer in pointer
// save the frame pointer
pushl %ebp
@ -21,11 +22,11 @@ jmp 2f
1:
// retrieve the new stack pointer
movl (%eax), %ebx
movl (%eax), %edx
// save the old stack pointer
movl %esp, (%eax)
movl %esp, (%ebx)
// switch to the new stack pointer
movl %ebx, %esp
movl %edx, %esp
// jump into the new context (return to the call point)
// doing this instead of a straight `ret` is 8ns slower,

View File

@ -31,10 +31,13 @@ impl Registers {
}
#[inline(always)]
pub unsafe fn swap(&mut self) {
pub unsafe fn swap2(out_regs: *mut Registers, in_regs: *const Registers) {
let out_rspp = &mut (*out_regs).rsp;
let in_rspp = &(*in_regs).rsp;
asm!(include_str!("swap.s")
:
: "{rdi}" (&mut self.rsp)
: "{rdi}" (out_rspp),
"{rdi}" (in_rspp)
: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", //"rbp", "rsp",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",

View File

@ -4,7 +4,8 @@
//! switch to a new context
//! arguments:
//! * rdi: stack pointer pointer
//! * rdi: stack pointer out pointer
//! * rsi: stack pointer in pointer
// make sure we leave the red zone alone
sub $$128, %rsp
@ -27,7 +28,7 @@ jmp 2f
1:
// retrieve the new stack pointer
movq (%rdi), %rax
movq (%rsi), %rax
// save the old stack pointer
movq %rsp, (%rdi)
// switch to the new stack pointer

View File

@ -46,7 +46,13 @@ impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
/// Switch to the context, saving the current thread of execution there.
#[inline(always)]
pub unsafe fn swap(&mut self) {
self.regs.swap()
Context::swap2(self, self)
}
/// Switch to in_ctx, saving the current thread of execution to out_ctx.
#[inline(always)]
pub unsafe fn swap2(out_ctx: *mut Context<'a, Stack>, in_ctx: *const Context<'a, Stack>) {
Registers::swap2(&mut (*out_ctx).regs, &(*in_ctx).regs)
}
/// Unwrap the context, returning the stack it contained.