void boxed_region::free(rust_opaque_box *box) { // This turns out to not be true in various situations, // like when we are unwinding after a failure. // // assert(box->ref_count == 0); // This however should always be true. Helps to detect // double frees (kind of). assert(box->td != NULL); LOG(rust_get_current_task(), box, "@free(%p) with td %p, prev %p, next %p\n", box, box->td, box->prev, box->next); if (box->prev) box->prev->next = box->next; if (box->next) box->next->prev = box->prev; if (live_allocs == box) live_allocs = box->next; if (env->poison_on_free) { memset(box_body(box), 0xab, box->td->size); } box->prev = NULL; box->next = NULL; box->td = NULL; backing_region->free(box); }
extern "C" CDECL void debug_box(type_desc *t, rust_opaque_box *box) { rust_task *task = rust_get_current_task(); LOG(task, stdlib, "debug_box(0x%" PRIxPTR ")", box); debug_tydesc_helper(t); LOG(task, stdlib, " refcount %" PRIdPTR, box->ref_count - 1); // -1 because we ref'ed for this call uint8_t *data = (uint8_t *)box_body(box); for (uintptr_t i = 0; i < t->size; ++i) { LOG(task, stdlib, " byte %" PRIdPTR ": 0x%" PRIx8, i, data[i]); } }
extern "C" CDECL void upcall_s_malloc(s_malloc_args *args) { rust_task *task = args->task; LOG_UPCALL_ENTRY(task); LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td); rust_opaque_box *box = task->boxed.malloc(args->td, args->size); void *body = box_body(box); debug::maybe_track_origin(task, box); LOG(task, mem, "upcall malloc(0x%" PRIxPTR ") = box 0x%" PRIxPTR " with body 0x%" PRIxPTR, args->td, (uintptr_t)box, (uintptr_t)body); args->retval = (uintptr_t)box; }
extern "C" CDECL void upcall_s_malloc(s_malloc_args *args) { rust_task *task = rust_task_thread::get_task(); LOG_UPCALL_ENTRY(task); LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td); cc::maybe_cc(task); // FIXME--does this have to be calloc? rust_opaque_box *box = task->boxed.calloc(args->td); void *body = box_body(box); debug::maybe_track_origin(task, box); LOG(task, mem, "upcall malloc(0x%" PRIxPTR ") = box 0x%" PRIxPTR " with body 0x%" PRIxPTR, args->td, (uintptr_t)box, (uintptr_t)body); args->retval = (uintptr_t) box; }
// This runs on the Rust stack void task_start_wrapper(spawn_args *a) { rust_task *task = a->task; bool threw_exception = false; try { // The first argument is the return pointer; as the task fn // must have void return type, we can safely pass 0. a->f(0, a->envptr, a->argptr); } catch (rust_task *ex) { A(task->thread, ex == task, "Expected this task to be thrown for unwinding"); threw_exception = true; if (task->c_stack) { task->return_c_stack(); } // Since we call glue code below we need to make sure we // have the stack limit set up correctly task->reset_stack_limit(); } // We should have returned any C stack by now I(task->thread, task->c_stack == NULL); rust_opaque_box* env = a->envptr; if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; td->drop_glue(NULL, NULL, td->first_param, box_body(env)); upcall_shared_free(env); } // The cleanup work needs lots of stack cleanup_args ca = {a, threw_exception}; task->call_on_c_stack(&ca, (void*)cleanup_task); task->ctx.next->swap(task->ctx); }
// This runs on the Rust stack void task_start_wrapper(spawn_args *a) { rust_task *task = a->task; bool threw_exception = false; try { a->f(a->envptr, a->argptr); } catch (rust_task *ex) { assert(ex == task && "Expected this task to be thrown for unwinding"); threw_exception = true; if (task->c_stack) { task->return_c_stack(); } // Since we call glue code below we need to make sure we // have the stack limit set up correctly task->reset_stack_limit(); } // We should have returned any C stack by now assert(task->c_stack == NULL); rust_opaque_box* env = a->envptr; if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; td->drop_glue(NULL, box_body(env)); task->kernel->region()->free(env); } // The cleanup work needs lots of stack cleanup_args ca = {a, threw_exception}; task->call_on_c_stack(&ca, (void*)cleanup_task); task->ctx.next->swap(task->ctx); }
rust_opaque_box *boxed_region::calloc(type_desc *td, size_t body_size) { rust_opaque_box *box = malloc(td, body_size); memset(box_body(box), 0, td->size); return box; }