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:
parent
3c534b2bef
commit
98dee91f25
@ -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
|
||||||
|
@ -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
|
@ -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(®s);
|
//get_registers(®s);
|
||||||
}
|
swap_registers(®s, ®s);
|
||||||
|
|
||||||
void context::set()
|
|
||||||
{
|
|
||||||
//printf("Activating %p...\n", this);
|
|
||||||
set_registers(®s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ®s);
|
||||||
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;
|
||||||
|
@ -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);
|
||||||
|
@ -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.";
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user