Wrote swap_context in assembly. Closes #548. This also allows us to re-enable optimization on OSX for both gcc and clang. Also, re-enamed task-comm-1.rs, which was previously broken by optimization.

This commit is contained in:
Eric Holk 2011-06-23 18:49:29 -07:00
parent 3c534b2bef
commit 98dee91f25
5 changed files with 45 additions and 35 deletions

View File

@ -48,8 +48,8 @@ ifeq ($(CFG_OSTYPE), Darwin)
# approaches welcome! # approaches welcome!
# #
# NB: Currently GCC's optimizer breaks rustrt (task-comm-1 hangs) on Darwin. # NB: Currently GCC's optimizer breaks rustrt (task-comm-1 hangs) on Darwin.
CFG_GCC_CFLAGS += -m32 -O0 CFG_GCC_CFLAGS += -m32 -O2
CFG_CLANG_CFLAGS += -m32 -O0 CFG_CLANG_CFLAGS += -m32 -O2
ifeq ($(CFG_CPUTYPE), x86_64) ifeq ($(CFG_CPUTYPE), x86_64)
CFG_GCCISH_CFLAGS += -arch i386 CFG_GCCISH_CFLAGS += -arch i386
CFG_GCCISH_LINK_FLAGS += -arch i386 CFG_GCCISH_LINK_FLAGS += -arch i386

View File

@ -25,7 +25,6 @@ get_registers:
movl %ebp, 16(%eax) movl %ebp, 16(%eax)
movl %esi, 20(%eax) movl %esi, 20(%eax)
movl %edi, 24(%eax) movl %edi, 24(%eax)
movl %esp, 28(%eax)
movw %cs, 32(%eax) movw %cs, 32(%eax)
movw %ds, 34(%eax) movw %ds, 34(%eax)
movw %ss, 36(%eax) movw %ss, 36(%eax)
@ -39,12 +38,14 @@ get_registers:
movl %ecx, 44(%eax) movl %ecx, 44(%eax)
// save the return address as the instruction pointer // save the return address as the instruction pointer
movl 0(%esp), %ecx // and save the stack pointer of the caller
popl %ecx
movl %esp, 28(%eax)
movl %ecx, 48(%eax) movl %ecx, 48(%eax)
// return 0 // return 0
xor %eax, %eax xor %eax, %eax
ret jmp *%ecx
.globl set_registers .globl set_registers
set_registers: set_registers:
@ -70,13 +71,9 @@ set_registers:
push %ecx push %ecx
popf popf
// get ready to return back to the old eip // get ready to return.
// We could write this directly to 0(%esp), but Valgrind on OS X
// complains.
pop %ecx
mov 48(%eax), %ecx mov 48(%eax), %ecx
push %ecx push %ecx
//movl %ecx, 0(%esp)
// okay, now we can restore ecx. // okay, now we can restore ecx.
movl 8(%eax), %ecx movl 8(%eax), %ecx
@ -84,3 +81,26 @@ set_registers:
// return 1 to the saved eip // return 1 to the saved eip
movl $1, %eax movl $1, %eax
ret ret
// swap_registers(registers_t *oregs, registers_t *regs)
.globl swap_registers
swap_registers:
// %eax = get_registers(oregs);
movl 4(%esp), %eax
push %eax
call get_registers
// if(!%eax) goto call_set
test %eax, %eax
jz call_set
// else
addl $4, %esp
ret
call_set:
// set_registers(regs)
movl 12(%esp), %eax
movl %eax, 0(%esp)
call set_registers
// set_registers never returns

View File

@ -5,32 +5,22 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
extern "C" uint32_t CDECL get_registers(registers_t *regs) //extern "C" uint32_t CDECL get_registers(registers_t *regs)
asm ("get_registers"); // asm ("get_registers");
extern "C" uint32_t CDECL set_registers(registers_t *regs) extern "C" uint32_t CDECL swap_registers(registers_t *oregs,
asm ("set_registers"); registers_t *regs)
asm ("swap_registers");
context::context() context::context()
: next(NULL) : next(NULL)
{ {
get_registers(&regs); //get_registers(&regs);
} swap_registers(&regs, &regs);
void context::set()
{
//printf("Activating %p...\n", this);
set_registers(&regs);
} }
void context::swap(context &out) void context::swap(context &out)
{ {
//printf("Swapping to %p and saving in %p\n", this, &out); swap_registers(&out.regs, &regs);
uint32_t r = get_registers(&out.regs);
//printf("get_registers = %d, sp = 0x%x\n", r, out.regs.esp);
if(!r) {
set();
}
//printf("Resumed %p...\n", &out);
} }
void context::call(void *f, void *arg, void *stack) { void context::call(void *f, void *arg, void *stack) {
@ -43,7 +33,6 @@ void context::call(void *f, void *arg, void *stack) {
*--sp = (uint32_t)this; *--sp = (uint32_t)this;
*--sp = (uint32_t)arg; *--sp = (uint32_t)arg;
*--sp = 0xdeadbeef; *--sp = 0xdeadbeef;
*--sp = 0xca11ab1e;
regs.esp = (uint32_t)sp; regs.esp = (uint32_t)sp;
regs.eip = (uint32_t)f; regs.eip = (uint32_t)f;

View File

@ -25,8 +25,6 @@ public:
context *next; context *next;
void set();
void swap(context &out); void swap(context &out);
void call(void *f, void *arg, void *sp); void call(void *f, void *arg, void *sp);

View File

@ -1,6 +1,9 @@
// xfail-stage0 // xfail-stage0
// xfail-stage1
// xfail-stage2 use std;
import std::task::join;
fn main() -> () { fn main() -> () {
test00(); test00();
} }
@ -10,7 +13,7 @@ fn start() {
} }
fn test00() { fn test00() {
let task t = spawn thread start(); let task t = spawn start();
join t; join(t);
log "Completing."; log "Completing.";
} }