Skip to content

Commit 98dee91

Browse files
author
Eric Holk
committed
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.
1 parent 3c534b2 commit 98dee91

File tree

5 files changed

+45
-35
lines changed

5 files changed

+45
-35
lines changed

mk/platform.mk

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ ifeq ($(CFG_OSTYPE), Darwin)
4848
# approaches welcome!
4949
#
5050
# NB: Currently GCC's optimizer breaks rustrt (task-comm-1 hangs) on Darwin.
51-
CFG_GCC_CFLAGS += -m32 -O0
52-
CFG_CLANG_CFLAGS += -m32 -O0
51+
CFG_GCC_CFLAGS += -m32 -O2
52+
CFG_CLANG_CFLAGS += -m32 -O2
5353
ifeq ($(CFG_CPUTYPE), x86_64)
5454
CFG_GCCISH_CFLAGS += -arch i386
5555
CFG_GCCISH_LINK_FLAGS += -arch i386

src/rt/arch/i386/_context.s

+28-8
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ get_registers:
2525
movl %ebp, 16(%eax)
2626
movl %esi, 20(%eax)
2727
movl %edi, 24(%eax)
28-
movl %esp, 28(%eax)
2928
movw %cs, 32(%eax)
3029
movw %ds, 34(%eax)
3130
movw %ss, 36(%eax)
@@ -39,12 +38,14 @@ get_registers:
3938
movl %ecx, 44(%eax)
4039

4140
// save the return address as the instruction pointer
42-
movl 0(%esp), %ecx
41+
// and save the stack pointer of the caller
42+
popl %ecx
43+
movl %esp, 28(%eax)
4344
movl %ecx, 48(%eax)
4445

4546
// return 0
4647
xor %eax, %eax
47-
ret
48+
jmp *%ecx
4849

4950
.globl set_registers
5051
set_registers:
@@ -70,17 +71,36 @@ set_registers:
7071
push %ecx
7172
popf
7273

73-
// get ready to return back to the old eip
74-
// We could write this directly to 0(%esp), but Valgrind on OS X
75-
// complains.
76-
pop %ecx
74+
// get ready to return.
7775
mov 48(%eax), %ecx
7876
push %ecx
79-
//movl %ecx, 0(%esp)
8077

8178
// okay, now we can restore ecx.
8279
movl 8(%eax), %ecx
8380

8481
// return 1 to the saved eip
8582
movl $1, %eax
8683
ret
84+
85+
// swap_registers(registers_t *oregs, registers_t *regs)
86+
.globl swap_registers
87+
swap_registers:
88+
// %eax = get_registers(oregs);
89+
movl 4(%esp), %eax
90+
push %eax
91+
call get_registers
92+
93+
// if(!%eax) goto call_set
94+
test %eax, %eax
95+
jz call_set
96+
97+
// else
98+
addl $4, %esp
99+
ret
100+
101+
call_set:
102+
// set_registers(regs)
103+
movl 12(%esp), %eax
104+
movl %eax, 0(%esp)
105+
call set_registers
106+
// set_registers never returns

src/rt/arch/i386/context.cpp

+8-19
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,22 @@
55
#include <stdio.h>
66
#include <stdlib.h>
77

8-
extern "C" uint32_t CDECL get_registers(registers_t *regs)
9-
asm ("get_registers");
10-
extern "C" uint32_t CDECL set_registers(registers_t *regs)
11-
asm ("set_registers");
8+
//extern "C" uint32_t CDECL get_registers(registers_t *regs)
9+
// asm ("get_registers");
10+
extern "C" uint32_t CDECL swap_registers(registers_t *oregs,
11+
registers_t *regs)
12+
asm ("swap_registers");
1213

1314
context::context()
1415
: next(NULL)
1516
{
16-
get_registers(&regs);
17-
}
18-
19-
void context::set()
20-
{
21-
//printf("Activating %p...\n", this);
22-
set_registers(&regs);
17+
//get_registers(&regs);
18+
swap_registers(&regs, &regs);
2319
}
2420

2521
void context::swap(context &out)
2622
{
27-
//printf("Swapping to %p and saving in %p\n", this, &out);
28-
uint32_t r = get_registers(&out.regs);
29-
//printf("get_registers = %d, sp = 0x%x\n", r, out.regs.esp);
30-
if(!r) {
31-
set();
32-
}
33-
//printf("Resumed %p...\n", &out);
23+
swap_registers(&out.regs, &regs);
3424
}
3525

3626
void context::call(void *f, void *arg, void *stack) {
@@ -43,7 +33,6 @@ void context::call(void *f, void *arg, void *stack) {
4333
*--sp = (uint32_t)this;
4434
*--sp = (uint32_t)arg;
4535
*--sp = 0xdeadbeef;
46-
*--sp = 0xca11ab1e;
4736

4837
regs.esp = (uint32_t)sp;
4938
regs.eip = (uint32_t)f;

src/rt/arch/i386/context.h

-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ class context {
2525

2626
context *next;
2727

28-
void set();
29-
3028
void swap(context &out);
3129

3230
void call(void *f, void *arg, void *sp);

src/test/run-pass/task-comm-1.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// xfail-stage0
2-
// xfail-stage1
3-
// xfail-stage2
2+
3+
use std;
4+
5+
import std::task::join;
6+
47
fn main() -> () {
58
test00();
69
}
@@ -10,7 +13,7 @@ fn start() {
1013
}
1114

1215
fn test00() {
13-
let task t = spawn thread start();
14-
join t;
16+
let task t = spawn start();
17+
join(t);
1518
log "Completing.";
1619
}

0 commit comments

Comments
 (0)