rt: More work on morestack
This commit is contained in:
parent
f4eb25e0d0
commit
e6c3c4e48c
3
mk/rt.mk
3
mk/rt.mk
@ -67,7 +67,8 @@ RUNTIME_CS_$(1) := \
|
|||||||
|
|
||||||
RUNTIME_S_$(1) := rt/arch/$$(HOST_$(1))/_context.S \
|
RUNTIME_S_$(1) := rt/arch/$$(HOST_$(1))/_context.S \
|
||||||
rt/arch/$$(HOST_$(1))/ccall.S \
|
rt/arch/$$(HOST_$(1))/ccall.S \
|
||||||
rt/arch/$$(HOST_$(1))/morestack.S
|
rt/arch/$$(HOST_$(1))/morestack.S \
|
||||||
|
rt/arch/$$(HOST_$(1))/record_sp.S
|
||||||
|
|
||||||
RUNTIME_HDR_$(1) := rt/globals.h \
|
RUNTIME_HDR_$(1) := rt/globals.h \
|
||||||
rt/rust.h \
|
rt/rust.h \
|
||||||
|
@ -2,40 +2,117 @@
|
|||||||
|
|
||||||
// __morestack
|
// __morestack
|
||||||
//
|
//
|
||||||
// LLVM generates a call to this to allocate more stack space in a functiono
|
// LLVM generates a call to this to allocate more stack space in a function
|
||||||
// prolog when we run out.
|
// prolog when we run out.
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(_WIN32)
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
#define RUST_NEW_STACK _rust_new_stack
|
#define RUST_NEW_STACK _rust_new_stack
|
||||||
#define RUST_DEL_STACK _rust_del_stack
|
#define RUST_DEL_STACK _rust_del_stack
|
||||||
|
#define RUST_GET_PREV_STACK _rust_get_prev_stack
|
||||||
|
#define RUST_GET_TASK _rust_get_task
|
||||||
|
#define UPCALL_ALLOC_C_STACK _upcall_alloc_c_stack
|
||||||
|
#define UPCALL_CALL_C_STACK _upcall_call_c_stack
|
||||||
#define MORESTACK ___morestack
|
#define MORESTACK ___morestack
|
||||||
#else
|
#else
|
||||||
#define RUST_NEW_STACK rust_new_stack
|
#define RUST_NEW_STACK rust_new_stack
|
||||||
#define RUST_DEL_STACK rust_del_stack
|
#define RUST_DEL_STACK rust_del_stack
|
||||||
|
#define RUST_GET_PREV_STACK rust_get_prev_stack
|
||||||
|
#define RUST_GET_TASK rust_get_task
|
||||||
|
#define UPCALL_ALLOC_C_STACK upcall_alloc_c_stack
|
||||||
|
#define UPCALL_CALL_C_STACK upcall_call_c_stack
|
||||||
#define MORESTACK __morestack
|
#define MORESTACK __morestack
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define ALIGNMENT 4
|
||||||
|
#else
|
||||||
|
#define ALIGNMENT 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RETURN_OFFSET 7
|
||||||
|
|
||||||
.globl RUST_NEW_STACK
|
.globl RUST_NEW_STACK
|
||||||
.globl RUST_DEL_STACK
|
.globl RUST_DEL_STACK
|
||||||
|
.globl RUST_GET_PREV_STACK
|
||||||
|
.globl RUST_GET_TASK
|
||||||
|
.globl UPCALL_ALLOC_C_STACK
|
||||||
|
.globl UPCALL_CALL_C_STACK
|
||||||
.globl MORESTACK
|
.globl MORESTACK
|
||||||
|
|
||||||
MORESTACK:
|
MORESTACK:
|
||||||
pushl 8(%esp) // argsz > ra stksz argsz x x ra args
|
|
||||||
leal 28(%esp),%eax // argsz ra stksz argsz x x ra args
|
|
||||||
pushl %eax // argp > argsz ra stksz argsz x x ra args
|
|
||||||
pushl 12(%esp) // stksz > argp argsz ra stksz argsz x x ra args
|
|
||||||
calll RUST_NEW_STACK
|
|
||||||
addl $12,%esp // ra stksz argsz x x ra args
|
|
||||||
|
|
||||||
movl (%esp),%edx // Grab the return pointer.
|
// Sanity check to make sure that there is a currently-running task.
|
||||||
incl %edx // Skip past the `ret`.
|
subl $12,%esp
|
||||||
movl %eax,%esp // Switch to the new stack.
|
calll RUST_GET_TASK
|
||||||
|
testl %eax,%eax
|
||||||
|
jz L$bail
|
||||||
|
|
||||||
|
subl $12,%esp
|
||||||
|
pushl $12
|
||||||
|
calll UPCALL_ALLOC_C_STACK
|
||||||
|
movl %eax,%edx
|
||||||
|
|
||||||
|
// C stack | esp+12
|
||||||
|
// ---------------------+-------------------------
|
||||||
|
movl 20(%esp),%eax // | ra stksz argsz x ra args
|
||||||
|
movl %eax,8(%edx) // argsz > | ra stksz argsz x ra args
|
||||||
|
leal 32(%esp),%eax // argsz | ra stksz argsz x ra args
|
||||||
|
movl %eax,4(%edx) // argp > argsz | ra stksz argsz x ra args
|
||||||
|
movl 16(%esp),%eax // argp argsz | ra stksz argsz x ra args
|
||||||
|
movl %eax,(%edx) // stksz > argp argsz | ra stksz argsz x ra args
|
||||||
|
|
||||||
|
calll L$pic_ref_pt_0
|
||||||
|
L$pic_ref_pt_0:
|
||||||
|
popl %eax
|
||||||
|
|
||||||
|
movl rust_new_stack_sym-L$pic_ref_pt_0(%eax),%eax
|
||||||
|
movl %eax,(%esp)
|
||||||
|
movl %edx,4(%esp)
|
||||||
|
calll UPCALL_CALL_C_STACK
|
||||||
|
|
||||||
|
movl 16(%esp),%edx // Grab the return pointer.
|
||||||
|
addl $RETURN_OFFSET,%edx // Skip past the `add esp,4` and the `ret`.
|
||||||
|
|
||||||
|
movl %eax,%esp // Switch stacks.
|
||||||
|
subl $12,%esp // Align the stack.
|
||||||
calll *%edx // Re-enter the function that called us.
|
calll *%edx // Re-enter the function that called us.
|
||||||
|
|
||||||
// Now the function that called us has returned, so we need to delete the
|
// Now the function that called us has returned, so we need to delete the
|
||||||
// old stack space.
|
// old stack space.
|
||||||
calll RUST_DEL_STACK
|
|
||||||
movl %eax,%esp
|
calll RUST_GET_PREV_STACK
|
||||||
retl $8 // ra stksz argsz x x ra args
|
movl %eax,%esp // Switch back to the old stack.
|
||||||
|
|
||||||
|
movl $0,(%esp)
|
||||||
|
calll UPCALL_ALLOC_C_STACK
|
||||||
|
|
||||||
|
calll L$pic_ref_pt_1
|
||||||
|
L$pic_ref_pt_1:
|
||||||
|
popl %edx
|
||||||
|
|
||||||
|
movl rust_del_stack_sym-L$pic_ref_pt_1(%edx),%edx
|
||||||
|
movl %edx,(%esp)
|
||||||
|
movl %eax,4(%esp)
|
||||||
|
calll UPCALL_CALL_C_STACK
|
||||||
|
|
||||||
|
addl $16,%esp
|
||||||
|
retl $16 + ALIGNMENT // ra stksz argsz x ra args
|
||||||
|
|
||||||
|
L$bail:
|
||||||
|
movl 12(%esp),%edx
|
||||||
|
addl $RETURN_OFFSET,%edx
|
||||||
|
addl $12+16,%esp
|
||||||
|
jmpl *%edx
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
.section __IMPORT,__pointers,non_lazy_symbol_pointers
|
||||||
|
rust_new_stack_sym:
|
||||||
|
.indirect_symbol RUST_NEW_STACK
|
||||||
|
.long 0
|
||||||
|
rust_del_stack_sym:
|
||||||
|
.indirect_symbol RUST_DEL_STACK
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "rust_internal.h"
|
#include "rust_internal.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
struct
|
struct
|
||||||
command_line_args : public kernel_owned<command_line_args>
|
command_line_args : public kernel_owned<command_line_args>
|
||||||
@ -75,6 +76,8 @@ int check_claims = 0;
|
|||||||
|
|
||||||
extern "C" CDECL int
|
extern "C" CDECL int
|
||||||
rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
|
rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
|
||||||
|
fprintf(stderr, "rust_start, argc=%d argv=%p\n", argc, argv);
|
||||||
|
|
||||||
rust_env *env = load_env();
|
rust_env *env = load_env();
|
||||||
|
|
||||||
update_log_settings(crate_map, env->logspec);
|
update_log_settings(crate_map, env->logspec);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <pthread.h>
|
||||||
#include "rust_internal.h"
|
#include "rust_internal.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
@ -12,6 +13,9 @@ DWORD rust_scheduler::task_key;
|
|||||||
|
|
||||||
bool rust_scheduler::tls_initialized = false;
|
bool rust_scheduler::tls_initialized = false;
|
||||||
|
|
||||||
|
// Defined in arch/*/record_sp.S.
|
||||||
|
extern "C" void rust_record_sp(uintptr_t sp);
|
||||||
|
|
||||||
rust_scheduler::rust_scheduler(rust_kernel *kernel,
|
rust_scheduler::rust_scheduler(rust_kernel *kernel,
|
||||||
rust_srv *srv,
|
rust_srv *srv,
|
||||||
int id) :
|
int id) :
|
||||||
@ -285,6 +289,8 @@ rust_scheduler::start_main_loop() {
|
|||||||
scheduled_task->state->name);
|
scheduled_task->state->name);
|
||||||
|
|
||||||
place_task_in_tls(scheduled_task);
|
place_task_in_tls(scheduled_task);
|
||||||
|
rust_record_sp(scheduled_task->stk->limit);
|
||||||
|
//pthread_setspecific(89, (void *)scheduled_task->stk->limit);
|
||||||
|
|
||||||
interrupt_flag = 0;
|
interrupt_flag = 0;
|
||||||
|
|
||||||
@ -374,6 +380,8 @@ rust_scheduler::place_task_in_tls(rust_task *task) {
|
|||||||
|
|
||||||
rust_task *
|
rust_task *
|
||||||
rust_scheduler::get_task() {
|
rust_scheduler::get_task() {
|
||||||
|
if (!tls_initialized)
|
||||||
|
return NULL;
|
||||||
rust_task *task = reinterpret_cast<rust_task *>
|
rust_task *task = reinterpret_cast<rust_task *>
|
||||||
(pthread_getspecific(task_key));
|
(pthread_getspecific(task_key));
|
||||||
assert(task && "Couldn't get the task from TLS!");
|
assert(task && "Couldn't get the task from TLS!");
|
||||||
@ -395,6 +403,8 @@ rust_scheduler::place_task_in_tls(rust_task *task) {
|
|||||||
|
|
||||||
rust_task *
|
rust_task *
|
||||||
rust_scheduler::get_task() {
|
rust_scheduler::get_task() {
|
||||||
|
if (!tls_initialized)
|
||||||
|
return NULL;
|
||||||
rust_task *task = reinterpret_cast<rust_task *>(TlsGetValue(task_key));
|
rust_task *task = reinterpret_cast<rust_task *>(TlsGetValue(task_key));
|
||||||
assert(task && "Couldn't get the task from TLS!");
|
assert(task && "Couldn't get the task from TLS!");
|
||||||
return task;
|
return task;
|
||||||
|
@ -8,11 +8,14 @@
|
|||||||
#ifndef __WIN32__
|
#ifndef __WIN32__
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <iostream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
|
#define RED_ZONE_SIZE 128
|
||||||
|
|
||||||
// Stack size
|
// Stack size
|
||||||
size_t g_custom_min_stack_size = 0;
|
size_t g_custom_min_stack_size = 0;
|
||||||
|
|
||||||
@ -34,16 +37,16 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t minsz)
|
|||||||
size_t min_stk_bytes = get_min_stk_size(sched->min_stack_size);
|
size_t min_stk_bytes = get_min_stk_size(sched->min_stack_size);
|
||||||
if (minsz < min_stk_bytes)
|
if (minsz < min_stk_bytes)
|
||||||
minsz = min_stk_bytes;
|
minsz = min_stk_bytes;
|
||||||
size_t sz = sizeof(stk_seg) + minsz;
|
size_t sz = sizeof(stk_seg) + minsz + RED_ZONE_SIZE;
|
||||||
stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
|
stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
|
||||||
LOGPTR(task->sched, "new stk", (uintptr_t)stk);
|
LOGPTR(task->sched, "new stk", (uintptr_t)stk);
|
||||||
memset(stk, 0, sizeof(stk_seg));
|
memset(stk, 0, sizeof(stk_seg));
|
||||||
stk->next = task->stk;
|
stk->next = task->stk;
|
||||||
stk->limit = (uintptr_t) &stk->data[minsz];
|
stk->limit = (uintptr_t) &stk->data[minsz + RED_ZONE_SIZE];
|
||||||
LOGPTR(task->sched, "stk limit", stk->limit);
|
LOGPTR(task->sched, "stk limit", stk->limit);
|
||||||
stk->valgrind_id =
|
stk->valgrind_id =
|
||||||
VALGRIND_STACK_REGISTER(&stk->data[0],
|
VALGRIND_STACK_REGISTER(&stk->data[0],
|
||||||
&stk->data[minsz]);
|
&stk->data[minsz + RED_ZONE_SIZE]);
|
||||||
task->stk = stk;
|
task->stk = stk;
|
||||||
return stk;
|
return stk;
|
||||||
}
|
}
|
||||||
@ -63,18 +66,32 @@ del_stk(rust_task *task, stk_seg *stk)
|
|||||||
// Entry points for `__morestack` (see arch/*/morestack.S).
|
// Entry points for `__morestack` (see arch/*/morestack.S).
|
||||||
extern "C" void *
|
extern "C" void *
|
||||||
rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
|
rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
|
||||||
|
std::cerr << "*** New stack!\n";
|
||||||
|
|
||||||
rust_task *task = rust_scheduler::get_task();
|
rust_task *task = rust_scheduler::get_task();
|
||||||
|
if (!task)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
stk_seg *stk_seg = new_stk(task->sched, task, stk_sz);
|
stk_seg *stk_seg = new_stk(task->sched, task, stk_sz);
|
||||||
memcpy(stk_seg->data, args_addr, args_sz);
|
memcpy(stk_seg->data, args_addr, args_sz);
|
||||||
return stk_seg->data;
|
return stk_seg->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void *
|
extern "C" void
|
||||||
rust_del_stack() {
|
rust_del_stack() {
|
||||||
rust_task *task = rust_scheduler::get_task();
|
rust_task *task = rust_scheduler::get_task();
|
||||||
stk_seg *next_seg = task->stk->next;
|
|
||||||
del_stk(task, task->stk);
|
del_stk(task, task->stk);
|
||||||
return next_seg->data;
|
}
|
||||||
|
|
||||||
|
extern "C" void *
|
||||||
|
rust_get_prev_stack() {
|
||||||
|
rust_task *task = rust_scheduler::get_task();
|
||||||
|
return task->stk->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" rust_task *
|
||||||
|
rust_get_task() {
|
||||||
|
return rust_scheduler::get_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
__morestack
|
||||||
align_of
|
align_of
|
||||||
chan_id_send
|
chan_id_send
|
||||||
check_claims
|
check_claims
|
||||||
@ -28,7 +29,10 @@ rand_free
|
|||||||
rand_new
|
rand_new
|
||||||
rand_next
|
rand_next
|
||||||
refcount
|
refcount
|
||||||
|
rust_del_stack
|
||||||
rust_file_is_dir
|
rust_file_is_dir
|
||||||
|
rust_getcwd
|
||||||
|
rust_get_prev_stack
|
||||||
rust_get_stdin
|
rust_get_stdin
|
||||||
rust_get_stdout
|
rust_get_stdout
|
||||||
rust_get_stderr
|
rust_get_stderr
|
||||||
@ -36,12 +40,14 @@ rust_str_push
|
|||||||
rust_list_files
|
rust_list_files
|
||||||
rust_port_detach
|
rust_port_detach
|
||||||
rust_port_size
|
rust_port_size
|
||||||
|
rust_new_stack
|
||||||
rust_process_wait
|
rust_process_wait
|
||||||
rust_ptr_eq
|
rust_ptr_eq
|
||||||
rust_run_program
|
rust_run_program
|
||||||
rust_start
|
rust_start
|
||||||
rust_getcwd
|
rust_getcwd
|
||||||
rust_task_sleep
|
rust_task_sleep
|
||||||
|
rust_get_task
|
||||||
set_min_stack
|
set_min_stack
|
||||||
sched_threads
|
sched_threads
|
||||||
size_of
|
size_of
|
||||||
@ -63,10 +69,10 @@ upcall_dynastack_mark
|
|||||||
upcall_fail
|
upcall_fail
|
||||||
upcall_free
|
upcall_free
|
||||||
upcall_get_type_desc
|
upcall_get_type_desc
|
||||||
upcall_vec_grow
|
|
||||||
upcall_vec_push
|
|
||||||
upcall_log_type
|
upcall_log_type
|
||||||
upcall_malloc
|
upcall_malloc
|
||||||
upcall_rust_personality
|
upcall_rust_personality
|
||||||
upcall_shared_malloc
|
upcall_shared_malloc
|
||||||
upcall_shared_free
|
upcall_shared_free
|
||||||
|
upcall_vec_grow
|
||||||
|
upcall_vec_push
|
||||||
|
Loading…
Reference in New Issue
Block a user