Ejemplo n.º 1
0
/**
   The exception handling personality function. It figures
   out what to do with each landing pad. Just a stack-switching
   wrapper around the C++ personality function.
*/
extern "C" _Unwind_Reason_Code
upcall_rust_personality(int version,
                        _Unwind_Action actions,
                        uint64_t exception_class,
                        _Unwind_Exception *ue_header,
                        _Unwind_Context *context) {
    s_rust_personality_args args = {(_Unwind_Reason_Code)0,
                                    version, actions, exception_class,
                                    ue_header, context};
    rust_task *task = rust_try_get_current_task();

    if (task == NULL) {
        // Assuming we're running with the new scheduler
        upcall_s_rust_personality(&args);
        return args.retval;
    }

    // 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(task, &args, upcall_s_rust_personality);
    } else {
        upcall_s_rust_personality(&args);
    }
    return args.retval;
}
Ejemplo n.º 2
0
// Landing pads need to call this to insert the
// correct limit into TLS.
// NB: This must run on the Rust stack because it
// needs to acquire the value of the stack pointer
extern "C" CDECL void
upcall_reset_stack_limit() {
    rust_task *task = rust_try_get_current_task();
    if (task != NULL) {
        task->reset_stack_limit();
    } else {
        // We must be in a newsched task
    }
}
Ejemplo n.º 3
0
extern "C" CDECL void
upcall_fail(char const *expr,
            char const *file,
            size_t line) {
    rust_task *task = rust_try_get_current_task();
    if (task == NULL) {
        // FIXME #5161: Need to think about what to do here
        printf("failure outside of a task");
        abort();
    }
    s_fail_args args = {task,expr,file,line};
    UPCALL_SWITCH_STACK(task, &args, upcall_s_fail);
}
Ejemplo n.º 4
0
/**********************************************************************
 * Switches to the C-stack and invokes |fn_ptr|, passing |args| as argument.
 * This is used by the C compiler to call foreign functions and by other
 * upcalls to switch to the C stack.  The return value is passed through a
 * field in the args parameter. This upcall is specifically for switching
 * to the shim functions generated by rustc.
 */
extern "C" CDECL void
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
    rust_task *task = rust_try_get_current_task();

    if (task) {
        // We're running in task context, do a stack switch
        try {
            task->call_on_c_stack(args, fn_ptr);
        } catch (...) {
            // Logging here is not reliable
            assert(false && "Foreign code threw an exception");
        }
    } else {
        // There's no task. Call the function and hope for the best
        stack_switch_shim f = (stack_switch_shim)fn_ptr;
        f(args);
    }
}
Ejemplo n.º 5
0
/*
 * The opposite of above. Starts on a C stack and switches to the Rust
 * stack. This is the only upcall that runs from the C stack.
 */
extern "C" CDECL void
upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) {
    rust_task *task = rust_try_get_current_task();

    if (task) {
        try {
            task->call_on_rust_stack(args, fn_ptr);
        } catch (...) {
            // We can't count on being able to unwind through arbitrary
            // code. Our best option is to just fail hard.
            // Logging here is not reliable
            assert(false
                   && "Rust task failed after reentering the Rust stack");
        }
    } else {
        // There's no task. Call the function and hope for the best
        stack_switch_shim f = (stack_switch_shim)fn_ptr;
        f(args);
    }
}
Ejemplo n.º 6
0
extern "C" rust_task *
rust_try_get_task() {
    return rust_try_get_current_task();
}