From 98dee91f2568522bc129f8cffcaa2879b43646c3 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 23 Jun 2011 18:49:29 -0700 Subject: [PATCH] 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. --- mk/platform.mk | 4 ++-- src/rt/arch/i386/_context.s | 36 +++++++++++++++++++++++++------- src/rt/arch/i386/context.cpp | 27 +++++++----------------- src/rt/arch/i386/context.h | 2 -- src/test/run-pass/task-comm-1.rs | 11 ++++++---- 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/mk/platform.mk b/mk/platform.mk index fb50285bbd2..e56b45ee6fc 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -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 diff --git a/src/rt/arch/i386/_context.s b/src/rt/arch/i386/_context.s index 8b49d35de1b..2b45aef3c4c 100644 --- a/src/rt/arch/i386/_context.s +++ b/src/rt/arch/i386/_context.s @@ -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 \ No newline at end of file diff --git a/src/rt/arch/i386/context.cpp b/src/rt/arch/i386/context.cpp index c1c8ba2167b..0d33376935c 100644 --- a/src/rt/arch/i386/context.cpp +++ b/src/rt/arch/i386/context.cpp @@ -5,32 +5,22 @@ #include #include -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(®s); -} - -void context::set() -{ - //printf("Activating %p...\n", this); - set_registers(®s); + //get_registers(®s); + swap_registers(®s, ®s); } 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, ®s); } 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; diff --git a/src/rt/arch/i386/context.h b/src/rt/arch/i386/context.h index 5329016450a..cf14ffe0753 100644 --- a/src/rt/arch/i386/context.h +++ b/src/rt/arch/i386/context.h @@ -25,8 +25,6 @@ public: context *next; - void set(); - void swap(context &out); void call(void *f, void *arg, void *sp); diff --git a/src/test/run-pass/task-comm-1.rs b/src/test/run-pass/task-comm-1.rs index 8adab6e9f0f..0c321022fa9 100644 --- a/src/test/run-pass/task-comm-1.rs +++ b/src/test/run-pass/task-comm-1.rs @@ -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."; } \ No newline at end of file