Skip to content

Commit

Permalink
Wrote swap_context in assembly. Closes #548. This also allows us to r…
Browse files Browse the repository at this point in the history
…e-enable optimization on OSX for both gcc and clang. Also, re-enamed task-comm-1.rs, which was previously broken by optimization.
  • Loading branch information
Eric Holk committed Jun 24, 2011
1 parent 3c534b2 commit 98dee91
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 35 deletions.
4 changes: 2 additions & 2 deletions mk/platform.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 28 additions & 8 deletions src/rt/arch/i386/_context.s
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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:
Expand All @@ -70,17 +71,36 @@ 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

// 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
27 changes: 8 additions & 19 deletions src/rt/arch/i386/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions src/rt/arch/i386/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class context {

context *next;

void set();

void swap(context &out);

void call(void *f, void *arg, void *sp);
Expand Down
11 changes: 7 additions & 4 deletions src/test/run-pass/task-comm-1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// xfail-stage0
// xfail-stage1
// xfail-stage2

use std;

import std::task::join;

fn main() -> () {
test00();
}
Expand All @@ -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.";
}

0 comments on commit 98dee91

Please sign in to comment.