about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorRafael Ávila de Espíndola <respindola@mozilla.com>2011-05-24 18:23:39 -0400
committerRafael Ávila de Espíndola <respindola@mozilla.com>2011-05-24 18:29:08 -0400
commitac836dd79c2d7c631ca601dc468de13cb5c785da (patch)
treee3ef73e6cb624ba406ccff65035dd1a439bd7e1e /src/rt
parentb1292580b95ea4a2ab22682ff04a91004c44cd06 (diff)
downloadrust-ac836dd79c2d7c631ca601dc468de13cb5c785da.tar.gz
rust-ac836dd79c2d7c631ca601dc468de13cb5c785da.zip
There is only one yield glue.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_crate.cpp5
-rw-r--r--src/rt/rust_internal.h5
-rw-r--r--src/rt/rust_task.cpp4
-rw-r--r--src/rt/yield_glue.s42
4 files changed, 47 insertions, 9 deletions
diff --git a/src/rt/rust_crate.cpp b/src/rt/rust_crate.cpp
index 6783d43c04c..2e312c8c564 100644
--- a/src/rt/rust_crate.cpp
+++ b/src/rt/rust_crate.cpp
@@ -16,11 +16,6 @@ rust_crate::get_gc_glue() const {
   return ((uintptr_t)this + gc_glue_off);
 }
 
-uintptr_t
-rust_crate::get_yield_glue() const {
-  return ((uintptr_t)this + yield_glue_off);
-}
-
 rust_crate::mem_area::mem_area(rust_dom *dom, uintptr_t pos, size_t sz)
   : dom(dom),
     base(pos),
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index 6bd638ed469..03022812a09 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -232,10 +232,10 @@ class rust_crate {
     size_t debug_info_sz;         // Size of .debug_info.
 
     ptrdiff_t activate_glue_off;
-    ptrdiff_t yield_glue_off;
     ptrdiff_t pad;
-    ptrdiff_t gc_glue_off;
     ptrdiff_t pad2;
+    ptrdiff_t gc_glue_off;
+    ptrdiff_t pad3;
 
 public:
 
@@ -247,7 +247,6 @@ public:
 
     uintptr_t get_image_base() const;
     ptrdiff_t get_relocation_diff() const;
-    uintptr_t get_yield_glue() const;
     uintptr_t get_gc_glue() const;
 
     struct mem_area
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index db72be6d12d..bd57eb89cca 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -317,12 +317,14 @@ rust_task::yield(size_t nargs) {
     yield(nargs, 0);
 }
 
+extern "C" void new_rust_yield_glue(void) asm("new_rust_yield_glue");
+
 void
 rust_task::yield(size_t nargs, size_t time_in_us) {
     LOG(this, task, "task %s @0x%" PRIxPTR " yielding for %d us",
         name, this, time_in_us);
     yield_timer.reset(time_in_us);
-    run_after_return(nargs, dom->root_crate->get_yield_glue());
+    run_after_return(nargs, (uintptr_t) new_rust_yield_glue);
 }
 
 static inline uintptr_t
diff --git a/src/rt/yield_glue.s b/src/rt/yield_glue.s
new file mode 100644
index 00000000000..767c9c5cae6
--- /dev/null
+++ b/src/rt/yield_glue.s
@@ -0,0 +1,42 @@
+/* More glue code, this time the 'bottom half' of yielding.
+ *
+ * We arrived here because an native call decided to deschedule the
+ * running task. So the native call's return address got patched to the
+ * first instruction of this glue code.
+ *
+ * When the native call does 'ret' it will come here, and its esp will be
+ * pointing to the last argument pushed on the C stack before making
+ * the native call: the 0th argument to the native call, which is always
+ * the task ptr performing the native call. That's where we take over.
+ *
+ * Our goal is to complete the descheduling
+ *
+ *   - Switch over to the task stack temporarily.
+ *
+ *   - Save the task's callee-saves onto the task stack.
+ *     (the task is now 'descheduled', safe to set aside)
+ *
+ *   - Switch *back* to the C stack.
+ *
+ *   - Restore the C-stack callee-saves.
+ *
+ *   - Return to the caller on the C stack that activated the task.
+ *
+ */
+
+	.globl new_rust_yield_glue
+	.balign 4
+new_rust_yield_glue:
+	movl  0(%esp), %ecx    # ecx = rust_task
+	movl  16(%ecx), %esp
+	pushl %ebp
+	pushl %edi
+	pushl %esi
+	pushl %ebx
+	movl  %esp, 16(%ecx)
+	movl  12(%ecx), %esp
+	popl  %ebx
+	popl  %esi
+	popl  %edi
+	popl  %ebp
+	ret