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!
#
# NB: Currently GCC's optimizer breaks rustrt (task-comm-1 hangs) on Darwin.
CFG_GCC_CFLAGS += -m32 -O0
CFG_CLANG_CFLAGS += -m32 -O0
CFG_GCC_CFLAGS += -m32 -O2
CFG_CLANG_CFLAGS += -m32 -O2
ifeq ($(CFG_CPUTYPE), x86_64)
CFG_GCCISH_CFLAGS += -arch i386
CFG_GCCISH_LINK_FLAGS += -arch i386

View File

@ -25,7 +25,6 @@ get_registers:
movl %ebp, 16(%eax)
movl %esi, 20(%eax)
movl %edi, 24(%eax)
movl %esp, 28(%eax)
movw %cs, 32(%eax)
movw %ds, 34(%eax)
movw %ss, 36(%eax)
@ -39,12 +38,14 @@ get_registers:
movl %ecx, 44(%eax)
// 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)
// return 0
xor %eax, %eax
ret
jmp *%ecx
.globl set_registers
set_registers:
@ -70,13 +71,9 @@ set_registers:
push %ecx
popf
// get ready to return back to the old eip
// We could write this directly to 0(%esp), but Valgrind on OS X
// complains.
pop %ecx
// get ready to return.
mov 48(%eax), %ecx
push %ecx
//movl %ecx, 0(%esp)
// okay, now we can restore ecx.
movl 8(%eax), %ecx
@ -84,3 +81,26 @@ set_registers:
// return 1 to the saved eip
movl $1, %eax
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 <stdlib.h>
extern "C" uint32_t CDECL get_registers(registers_t *regs)
asm ("get_registers");
extern "C" uint32_t CDECL set_registers(registers_t *regs)
asm ("set_registers");
//extern "C" uint32_t CDECL get_registers(registers_t *regs)
// asm ("get_registers");
extern "C" uint32_t CDECL swap_registers(registers_t *oregs,
registers_t *regs)
asm ("swap_registers");
context::context()
: next(NULL)
{
get_registers(&regs);
}
void context::set()
{
//printf("Activating %p...\n", this);
set_registers(&regs);
//get_registers(&regs);
swap_registers(&regs, &regs);
}
void context::swap(context &out)
{
//printf("Swapping to %p and saving in %p\n", this, &out);
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);
swap_registers(&out.regs, &regs);
}
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)arg;
*--sp = 0xdeadbeef;
*--sp = 0xca11ab1e;
regs.esp = (uint32_t)sp;
regs.eip = (uint32_t)f;

View File

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

View File

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