Last active
July 2, 2019 23:08
-
-
Save cfsamson/52beafe2d75da54234233b49d439a358 to your computer and use it in GitHub Desktop.
Trying to create the minimal example needed for the problem with Crystals windows context switch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
STACK_SIZE = 1024*1024*8 | |
class Test | |
property value : UInt64 = 0 | |
property stack = Array(UInt8).new(STACK_SIZE) | |
property func : Proc(Void) = ->{} | |
property rsp : UInt64 = 0 | |
def makecontext(proc : Proc) | |
@func = proc | |
s_ptr = @stack.to_unsafe | |
s_start = s_ptr + (STACK_SIZE - 32) | |
@rsp = (s_start - 1*8).as(Void*).address | |
# Our entry | |
s_start_ptr = s_start.as(UInt64*) | |
s_start_ptr.value = ->start(Test).pointer.address | |
# First parameter | |
first_param = (s_start - 8).as(UInt64*) | |
first_param.value = self.as(Void*).address | |
end | |
def run | |
@func.call | |
Process.exit(0) | |
end | |
end | |
def start(f : Test) | |
f.run | |
end | |
@[NoInline] | |
@[Naked] | |
def swap(data) | |
{% if flag?(:win32) %} | |
asm(" | |
pushq %rcx | |
movq $0, %rsp | |
popq %rcx | |
" | |
:: "r"(data) ) | |
{% else %} | |
asm(" | |
pushq %rdi | |
movq $0, %rsp | |
popq %rdi | |
" | |
:: "r"(data)) | |
{% end %} | |
end | |
test = Test.new | |
test.makecontext(->{ puts "Hello from new stack" }) | |
swap(test.rsp) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(asm)] | |
#![feature(naked_functions)] | |
// # How to build this in Rust | |
// 1. Install Rust: https://www.rust-lang.org/tools/install | |
// 2. Install the nightly compiler: `rustup toolchain install nightly` | |
// 3. Create a new directory and run `cargo init` | |
// 4. Make sure you use the nightly by running `rustup override set nightly` in the project folder | |
// 5. Copy this code over to `main.rs` | |
// 6. Run the program: `cargo run` | |
const STACK_SIZE: isize = 1024 * 1024 * 8; | |
struct Test { | |
stack: Vec<u8>, | |
func: fn(), | |
rsp: Option<*const u64>, | |
} | |
impl Test { | |
fn new() -> Self { | |
Test { | |
stack: vec![0_u8; STACK_SIZE as usize], | |
func: || {}, | |
rsp: None, | |
} | |
} | |
fn makecontext(&mut self, proc: fn()) { | |
self.func = proc; | |
let s_ptr = self.stack.as_ptr(); | |
let mut s_start = unsafe { s_ptr.offset(STACK_SIZE - 32) as *mut u8 }; | |
self.rsp = Some(unsafe { s_start.offset(-1 * 8) as *const u64 }); | |
unsafe { | |
// Our entry | |
std::ptr::write(s_start as *mut u64, start as u64); | |
// first parameter | |
let mut first_param = s_start.offset(-8) as *mut u64; | |
// this hurts to write... | |
let this = Box::new(self); | |
std::ptr::write(first_param, Box::into_raw(this) as u64); | |
} | |
} | |
fn run(&self) { | |
(self.func)(); | |
} | |
} | |
fn start(f: *const *const Test) { | |
unsafe { | |
(**f).run(); | |
} | |
std::process::exit(0); | |
} | |
#[cfg(target_os = "windows")] | |
#[inline(never)] | |
#[naked] | |
fn swap(data: *const u64) { | |
unsafe { | |
asm!(" | |
pushq %rcx | |
movq $0, %rsp | |
popq %rcx | |
" | |
:: "r"(data) :: "volatile", "alignstack"); | |
} | |
} | |
#[cfg(not(target_os = "windows"))] | |
#[inline(never)] | |
#[naked] | |
fn swap(data: *const u64) { | |
unsafe { | |
asm!(" | |
pushq %rdi | |
movq $0, %rsp | |
popq %rdi | |
" | |
:: "r"(data)); | |
} | |
} | |
fn main() { | |
let mut test = Test::new(); | |
test.makecontext(|| println!("Hello from new stack")); | |
swap(test.rsp.unwrap()); | |
println!("BEFORE: {:?}", test.rsp.unwrap()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
STACK_SIZE = 1024*1024*8 | |
class Test | |
property value : UInt64 = 0 | |
property stack = Array(UInt8).new(STACK_SIZE) | |
property func : Proc(Void) = ->{} | |
property rsp : UInt64 = 0 | |
property first_param : UInt64 = 0 | |
def makecontext(proc : Proc) | |
@func = proc | |
s_ptr = @stack.to_unsafe | |
s_start = s_ptr + (STACK_SIZE - 32) | |
@rsp = s_start.as(Void*).address | |
# Our entry | |
s_start_ptr = s_start.as(UInt64*) | |
s_start_ptr.value = ->(f : Test) { f.run }.pointer.address | |
# First parameter | |
@first_param = self.as(Void*).address | |
end | |
def run | |
@func.call | |
Process.exit(0) | |
end | |
end | |
@[NoInline] | |
@[Naked] | |
def swap(data, first_param) | |
{% if flag?(:win32) %} | |
asm(" | |
movq $0, %rsp | |
movq $1, %rcx | |
#movq %rcx, $1 | |
" | |
:: "r"(data), "r"(first_param)) | |
{% else %} | |
asm(" | |
movq $0, %rsp | |
movq $1, %rdi | |
#movq %rdi, $1 | |
" | |
:: "r"(data), "r"(first_param)) | |
{% end %} | |
end | |
test = Test.new | |
test.makecontext(->{puts "Hello from new stack"}) | |
swap(test.rsp, test.@first_param) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment