diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 9ad1f3a5e4d..55d7fc489ad 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -151,6 +151,61 @@ upcall_trace(char const *msg, UPCALL_SWITCH_STACK(&args, upcall_s_trace); } +/********************************************************************** + * Allocate an object in the exchange heap + */ + +struct s_exchange_malloc_args { + uintptr_t retval; + type_desc *td; +}; + +extern "C" CDECL void +upcall_s_exchange_malloc(s_exchange_malloc_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + + LOG(task, mem, "upcall exchange malloc(0x%" PRIxPTR ")", args->td); + + // Copied from boxed_region + size_t header_size = sizeof(rust_opaque_box); + size_t body_size = args->td->size; + size_t body_align = args->td->align; + size_t total_size = align_to(header_size, body_align) + body_size; + + void *p = task->kernel->malloc(total_size, "exchange malloc"); + memset(p, '\0', total_size); + + rust_opaque_box *header = static_cast(p); + header->td = args->td; + + args->retval = (uintptr_t)header; +} + +extern "C" CDECL uintptr_t +upcall_exchange_malloc(type_desc *td) { + s_exchange_malloc_args args = {0, td}; + UPCALL_SWITCH_STACK(&args, upcall_s_exchange_malloc); + return args.retval; +} + +struct s_exchange_free_args { + void *ptr; +}; + +extern "C" CDECL void +upcall_s_exchange_free(s_exchange_free_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + task->kernel->free(args->ptr); +} + +extern "C" CDECL void +upcall_exchange_free(void *ptr) { + s_exchange_free_args args = {ptr}; + UPCALL_SWITCH_STACK(&args, upcall_s_exchange_free); +} + /********************************************************************** * Allocate an object in the task-local heap. */ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index d982110bb99..aaa4fcd8cec 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -88,6 +88,8 @@ upcall_call_shim_on_rust_stack upcall_new_stack upcall_del_stack upcall_reset_stack_limit +upcall_exchange_malloc +upcall_exchange_free rust_uv_loop_new rust_uv_loop_delete rust_uv_loop_refcount @@ -161,4 +163,4 @@ rust_port_take rust_port_drop rust_port_task rust_task_inhibit_kill -rust_task_allow_kill \ No newline at end of file +rust_task_allow_kill diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index 7cc71fca0b2..ec78b5bb946 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -12,6 +12,8 @@ type upcalls = trace: ValueRef, malloc: ValueRef, free: ValueRef, + exchange_malloc: ValueRef, + exchange_free: ValueRef, validate_box: ValueRef, shared_malloc: ValueRef, shared_free: ValueRef, @@ -62,6 +64,11 @@ fn declare_upcalls(targ_cfg: @session::config, T_ptr(T_i8()))), free: nothrow(dv("free", [T_ptr(T_i8())])), + exchange_malloc: + nothrow(d("exchange_malloc", [T_ptr(tydesc_type)], + T_ptr(T_i8()))), + exchange_free: + nothrow(dv("exchange_free", [T_ptr(T_i8())])), validate_box: nothrow(dv("validate_box", [T_ptr(T_i8())])), shared_malloc: