diff --git a/mk/tests.mk b/mk/tests.mk index e9b407b8d795b..db72a2277050e 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -746,9 +746,6 @@ $(3)/test/$$(FT_DRIVER)-$(2).out: \ --logfile tmp/$$(FT_DRIVER)-$(2).log check-fast-T-$(2)-H-$(3): \ - check-stage2-T-$(2)-H-$(3)-rustc \ - check-stage2-T-$(2)-H-$(3)-core \ - check-stage2-T-$(2)-H-$(3)-std \ $(3)/test/$$(FT_DRIVER)-$(2).out endef diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 0e6df8e14a451..ea3961467558d 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -45,6 +45,8 @@ call_upcall_on_c_stack(rust_task *task, void *args, void *fn_ptr) { task->call_on_c_stack(args, fn_ptr); } +typedef void (*CDECL stack_switch_shim)(void*); + /********************************************************************** * 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 @@ -54,13 +56,20 @@ call_upcall_on_c_stack(rust_task *task, void *args, void *fn_ptr) { */ extern "C" CDECL void upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { - rust_task *task = rust_get_current_task(); - - try { - task->call_on_c_stack(args, fn_ptr); - } catch (...) { - // Logging here is not reliable - assert(false && "Foreign code threw an exception"); + 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); } } @@ -70,15 +79,22 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { */ extern "C" CDECL void upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) { - rust_task *task = rust_get_current_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"); + 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); } } diff --git a/src/test/run-pass/foreign-call-no-runtime.rs b/src/test/run-pass/foreign-call-no-runtime.rs new file mode 100644 index 0000000000000..865aa77536284 --- /dev/null +++ b/src/test/run-pass/foreign-call-no-runtime.rs @@ -0,0 +1,24 @@ +use core::private::run_in_bare_thread; + +extern { + pub fn rust_dbg_call(cb: *u8, + data: libc::uintptr_t) -> libc::uintptr_t; +} + +pub fn main() { + unsafe { + do run_in_bare_thread() { + unsafe { + let i = &100; + rust_dbg_call(callback, cast::transmute(i)); + } + } + } +} + +extern fn callback(data: libc::uintptr_t) { + unsafe { + let data: *int = cast::transmute(data); + assert *data == 100; + } +} \ No newline at end of file