extern "C" uintptr_t get_sp();
+static bool
+sp_in_stk_seg(uintptr_t sp, stk_seg *stk) {
+ // Not positive these bounds for sp are correct. I think that the first
+ // possible value for esp on a new stack is stk->end, which points to the
+ // address before the first value to be pushed onto a new stack. The last
+ // possible address we can push data to is stk->data. Regardless, there's
+ // so much slop at either end that we should never hit one of these
+ // boundaries.
+ return (uintptr_t)stk->data <= sp && sp <= stk->end;
+}
+
/*
Called by landing pads during unwinding to figure out which
stack segment we are currently running on, delete the others,
void
rust_task::reset_stack_limit() {
uintptr_t sp = get_sp();
- // Not positive these bounds for sp are correct.
- // I think that the first possible value for esp on a new
- // stack is stk->end, which points one word in front of
- // the first work to be pushed onto a new stack.
- while (sp <= (uintptr_t)stk->data || stk->end < sp) {
+ while (!sp_in_stk_seg(sp, stk)) {
del_stk(this, stk);
A(sched, stk != NULL, "Failed to find the current stack");
}
record_stack_limit();
}
+/*
+Returns true if we're currently running on the Rust stack
+ */
+bool
+rust_task::on_rust_stack() {
+ return sp_in_stk_seg(get_sp(), stk);
+}
+
//
// Local Variables:
// mode: C++
upcall_fail(char const *expr,
char const *file,
size_t line) {
- try {
- s_fail_args args = {expr,file,line};
- UPCALL_SWITCH_STACK(&args, upcall_s_fail);
- } catch (rust_task*) {
- throw;
- }
+ s_fail_args args = {expr,file,line};
+ UPCALL_SWITCH_STACK(&args, upcall_s_fail);
}
/**********************************************************************
s_rust_personality_args args = {(_Unwind_Reason_Code)0,
version, actions, exception_class,
ue_header, context};
- UPCALL_SWITCH_STACK(&args, upcall_s_rust_personality);
+ rust_task *task = rust_scheduler::get_task();
+
+ // The personality function is run on the stack of the
+ // last function that threw or landed, which is going
+ // to sometimes be the C stack. If we're on the Rust stack
+ // then switch to the C stack.
+
+ if (task->on_rust_stack()) {
+ UPCALL_SWITCH_STACK(&args, upcall_s_rust_personality);
+ } else {
+ upcall_s_rust_personality(&args);
+ }
return args.retval;
}