diff options
| author | Brian Anderson <banderson@mozilla.com> | 2011-11-21 18:52:12 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2011-11-22 18:02:10 -0800 |
| commit | 6bdf347418d04e48ef0fbbe0f4b2e940e9a24782 (patch) | |
| tree | 9e3977e8dbf8d31415edba20a38904d7dfcf0247 /src/rt/rust_task.cpp | |
| parent | a69c5617f02ff80dd7d39949004b386f9808b7d6 (diff) | |
| download | rust-6bdf347418d04e48ef0fbbe0f4b2e940e9a24782.tar.gz rust-6bdf347418d04e48ef0fbbe0f4b2e940e9a24782.zip | |
rt: Make __morestack (without unwinding) work on 32-bit linux
Diffstat (limited to 'src/rt/rust_task.cpp')
| -rw-r--r-- | src/rt/rust_task.cpp | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index fbaaebb8289..30489b1d669 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -14,7 +14,6 @@ #include "globals.h" -#define RED_ZONE_SIZE 128 // Stack size size_t g_custom_min_stack_size = 0; @@ -63,30 +62,41 @@ del_stk(rust_task *task, stk_seg *stk) task->free(stk); } +extern "C" CDECL void +record_sp(void *limit); + // Entry points for `__morestack` (see arch/*/morestack.S). extern "C" void * -rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) { - std::cerr << "*** New stack!\n"; - +rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz, + uintptr_t current_sp) { rust_task *task = rust_scheduler::get_task(); - if (!task) - return NULL; - stk_seg *stk_seg = new_stk(task->sched, task, stk_sz); - memcpy(stk_seg->data, args_addr, args_sz); - return stk_seg->data; + stk_seg *stk_seg = new_stk(task->sched, task, stk_sz + args_sz); + + // Save the previous stack pointer so it can be restored later + stk_seg->return_sp = current_sp; + uint8_t *new_sp = (uint8_t*)stk_seg->limit; + size_t sizeof_retaddr = sizeof(void*); + // Make enough room on the new stack to hold the old stack pointer + // in addition to the function arguments + new_sp = align_down(new_sp - (args_sz + sizeof_retaddr)); + new_sp += sizeof_retaddr; + memcpy(new_sp, args_addr, args_sz); + record_sp(stk_seg->data + RED_ZONE_SIZE); + return new_sp; } extern "C" void rust_del_stack() { rust_task *task = rust_scheduler::get_task(); del_stk(task, task->stk); + record_sp(task->stk->data + RED_ZONE_SIZE); } -extern "C" void * +extern "C" uintptr_t rust_get_prev_stack() { rust_task *task = rust_scheduler::get_task(); - return task->stk->next; + return task->stk->return_sp; } extern "C" rust_task * |
