about summary refs log tree commit diff
path: root/src/libstd/rt/context.rs
diff options
context:
space:
mode:
authorklutzy <klutzytheklutzy@gmail.com>2013-08-26 22:01:55 +0900
committerklutzy <klutzytheklutzy@gmail.com>2013-08-26 22:16:54 +0900
commit442f4a5f2ca6f7f4082c09968e0fd83601a50d2a (patch)
tree9ad67e23fcc2987c6500414796a36b4c454e7499 /src/libstd/rt/context.rs
parent63e53b8af2f37f9eb8eda0087b02f8deba252c2f (diff)
downloadrust-442f4a5f2ca6f7f4082c09968e0fd83601a50d2a.tar.gz
rust-442f4a5f2ca6f7f4082c09968e0fd83601a50d2a.zip
Support Win64 context switching
This patch saves and restores win64's nonvolatile registers.
This patch also saves stack information of thread environment
block (TEB), which is at %gs:0x08 and %gs:0x10.
Diffstat (limited to 'src/libstd/rt/context.rs')
-rw-r--r--src/libstd/rt/context.rs38
1 files changed, 31 insertions, 7 deletions
diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs
index 5aaddc68383..476554bf7f7 100644
--- a/src/libstd/rt/context.rs
+++ b/src/libstd/rt/context.rs
@@ -47,6 +47,7 @@ impl Context {
 
         let fp: *c_void = task_start_wrapper as *c_void;
         let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) };
+        let stack_base: *uint = stack.start();
         let sp: *uint = stack.end();
         let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
         // Save and then immediately load the current context,
@@ -56,7 +57,7 @@ impl Context {
             swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs));
         };
 
-        initialize_call_frame(&mut *regs, fp, argp, sp);
+        initialize_call_frame(&mut *regs, fp, argp, sp, stack_base);
 
         return Context {
             start: Some(start),
@@ -107,7 +108,8 @@ fn new_regs() -> ~Registers {
 }
 
 #[cfg(target_arch = "x86")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+                         sp: *mut uint, _stack_base: *uint) {
 
     let sp = align_down(sp);
     let sp = mut_offset(sp, -4);
@@ -123,14 +125,19 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp:
     regs.ebp = 0;
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(windows, target_arch = "x86_64")]
+type Registers = [uint, ..34];
+#[cfg(not(windows), target_arch = "x86_64")]
 type Registers = [uint, ..22];
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(windows, target_arch = "x86_64")]
+fn new_regs() -> ~Registers { ~([0, .. 34]) }
+#[cfg(not(windows), target_arch = "x86_64")]
 fn new_regs() -> ~Registers { ~([0, .. 22]) }
 
 #[cfg(target_arch = "x86_64")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+                         sp: *mut uint, stack_base: *uint) {
 
     // Redefinitions from regs.h
     static RUSTRT_ARG0: uint = 3;
@@ -138,6 +145,21 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp:
     static RUSTRT_IP: uint = 8;
     static RUSTRT_RBP: uint = 2;
 
+    #[cfg(windows)]
+    fn initialize_tib(regs: &mut Registers, sp: *mut uint, stack_base: *uint) {
+        // Redefinitions from regs.h
+        static RUSTRT_ST1: uint = 11; // stack bottom
+        static RUSTRT_ST2: uint = 12; // stack top
+        regs[RUSTRT_ST1] = sp as uint;
+        regs[RUSTRT_ST2] = stack_base as uint;
+    }
+    #[cfg(not(windows))]
+    fn initialize_tib(_: &mut Registers, _: *mut uint, _: *uint) {
+    }
+
+    // Win64 manages stack range at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
+    initialize_tib(regs, sp, stack_base);
+
     let sp = align_down(sp);
     let sp = mut_offset(sp, -1);
 
@@ -164,7 +186,8 @@ type Registers = [uint, ..32];
 fn new_regs() -> ~Registers { ~([0, .. 32]) }
 
 #[cfg(target_arch = "arm")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+                         sp: *mut uint, _stack_base: *uint) {
     let sp = align_down(sp);
     // sp of arm eabi is 8-byte aligned
     let sp = mut_offset(sp, -2);
@@ -184,7 +207,8 @@ type Registers = [uint, ..32];
 fn new_regs() -> ~Registers { ~([0, .. 32]) }
 
 #[cfg(target_arch = "mips")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+                         sp: *mut uint, _stack_base: *uint) {
     let sp = align_down(sp);
     // sp of mips o32 is 8-byte aligned
     let sp = mut_offset(sp, -2);