From d7f5e437a28dd85b8a7523af9212a9a1100ea725 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 21 Apr 2013 19:03:52 -0700 Subject: [PATCH] core::rt: Add the local heap to newsched tasks Reusing the existing boxed_region implementation from the runtime --- src/libcore/rt/local_heap.rs | 81 ++++++++++++++++++++++++++++++++ src/libcore/rt/local_services.rs | 19 +++++++- src/libcore/rt/mod.rs | 1 + src/libcore/unstable/lang.rs | 26 +++++++++- src/rt/boxed_region.cpp | 12 ++--- src/rt/rust_builtin.cpp | 35 ++++++++++++++ src/rt/rustrt.def.in | 6 +++ 7 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 src/libcore/rt/local_heap.rs diff --git a/src/libcore/rt/local_heap.rs b/src/libcore/rt/local_heap.rs new file mode 100644 index 0000000000000..fbd4a77d79b98 --- /dev/null +++ b/src/libcore/rt/local_heap.rs @@ -0,0 +1,81 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The local, garbage collected heap + +use libc::{c_void, uintptr_t, size_t}; +use ops::Drop; + +type MemoryRegion = c_void; +type BoxedRegion = c_void; + +pub type OpaqueBox = c_void; +pub type TypeDesc = c_void; + +pub struct LocalHeap { + memory_region: *MemoryRegion, + boxed_region: *BoxedRegion +} + +impl LocalHeap { + pub fn new() -> LocalHeap { + unsafe { + // Don't need synchronization for the single-threaded local heap + let synchronized = false as uintptr_t; + // XXX: These usually come from the environment + let detailed_leaks = false as uintptr_t; + let poison_on_free = false as uintptr_t; + let region = rust_new_memory_region(synchronized, detailed_leaks, poison_on_free); + assert!(region.is_not_null()); + let boxed = rust_new_boxed_region(region, poison_on_free); + assert!(boxed.is_not_null()); + LocalHeap { + memory_region: region, + boxed_region: boxed + } + } + } + + pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox { + unsafe { + return rust_boxed_region_malloc(self.boxed_region, td, size as size_t); + } + } + + pub fn free(&mut self, box: *OpaqueBox) { + unsafe { + return rust_boxed_region_free(self.boxed_region, box); + } + } +} + +impl Drop for LocalHeap { + fn finalize(&self) { + unsafe { + rust_delete_boxed_region(self.boxed_region); + rust_delete_memory_region(self.memory_region); + } + } +} + +extern { + fn rust_new_memory_region(synchronized: uintptr_t, + detailed_leaks: uintptr_t, + poison_on_free: uintptr_t) -> *MemoryRegion; + fn rust_delete_memory_region(region: *MemoryRegion); + fn rust_new_boxed_region(region: *MemoryRegion, + poison_on_free: uintptr_t) -> *BoxedRegion; + fn rust_delete_boxed_region(region: *BoxedRegion); + fn rust_boxed_region_malloc(region: *BoxedRegion, + td: *TypeDesc, + size: size_t) -> *OpaqueBox; + fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox); +} + diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/local_services.rs index 8e386f80b77d7..b9d99283e14f2 100644 --- a/src/libcore/rt/local_services.rs +++ b/src/libcore/rt/local_services.rs @@ -20,6 +20,7 @@ use prelude::*; use super::sched::{Task, local_sched}; +use super::local_heap::LocalHeap; pub struct LocalServices { heap: LocalHeap, @@ -29,7 +30,6 @@ pub struct LocalServices { unwinder: Unwinder } -pub struct LocalHeap; pub struct GarbageCollector; pub struct LocalStorage; pub struct Logger; @@ -38,7 +38,7 @@ pub struct Unwinder; impl LocalServices { pub fn new() -> LocalServices { LocalServices { - heap: LocalHeap, + heap: LocalHeap::new(), gc: GarbageCollector, storage: LocalStorage, logger: Logger, @@ -61,3 +61,18 @@ pub fn borrow_local_services(f: &fn(&mut LocalServices)) { } } } + +#[cfg(test)] +mod test { + use rt::test::*; + + #[test] + fn local_heap() { + do run_in_newsched_task() { + let a = @5; + let b = a; + assert!(*a == 5); + assert!(*b == 5); + } + } +} \ No newline at end of file diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index e0190418b132b..4a767d61f7444 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -49,6 +49,7 @@ mod context; mod thread; pub mod env; pub mod local_services; +mod local_heap; /// Tools for testing the runtime #[cfg(test)] diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index be776a39742f0..0bf1ad36a1faf 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -17,6 +17,8 @@ use str; use sys; use unstable::exchange_alloc; use cast::transmute; +use rt::{context, OldTaskContext}; +use rt::local_services::borrow_local_services; #[allow(non_camel_case_types)] pub type rust_task = c_void; @@ -81,7 +83,18 @@ pub unsafe fn exchange_free(ptr: *c_char) { #[lang="malloc"] #[inline(always)] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { - return rustrt::rust_upcall_malloc(td, size); + match context() { + OldTaskContext => { + return rustrt::rust_upcall_malloc(td, size); + } + _ => { + let mut alloc = ::ptr::null(); + do borrow_local_services |srv| { + alloc = srv.heap.alloc(td as *c_void, size as uint) as *c_char; + } + return alloc; + } + } } // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from @@ -90,7 +103,16 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[lang="free"] #[inline(always)] pub unsafe fn local_free(ptr: *c_char) { - rustrt::rust_upcall_free(ptr); + match context() { + OldTaskContext => { + rustrt::rust_upcall_free(ptr); + } + _ => { + do borrow_local_services |srv| { + srv.heap.free(ptr as *c_void); + } + } + } } #[lang="borrow_as_imm"] diff --git a/src/rt/boxed_region.cpp b/src/rt/boxed_region.cpp index e8ddb53148c1a..a49b52bffe153 100644 --- a/src/rt/boxed_region.cpp +++ b/src/rt/boxed_region.cpp @@ -27,11 +27,11 @@ rust_opaque_box *boxed_region::malloc(type_desc *td, size_t body_size) { if (live_allocs) live_allocs->prev = box; live_allocs = box; - LOG(rust_get_current_task(), box, + /*LOG(rust_get_current_task(), box, "@malloc()=%p with td %p, size %lu==%lu+%lu, " "align %lu, prev %p, next %p\n", box, td, total_size, sizeof(rust_opaque_box), body_size, - td->align, box->prev, box->next); + td->align, box->prev, box->next);*/ return box; } @@ -50,9 +50,9 @@ rust_opaque_box *boxed_region::realloc(rust_opaque_box *box, if (new_box->next) new_box->next->prev = new_box; if (live_allocs == box) live_allocs = new_box; - LOG(rust_get_current_task(), box, + /*LOG(rust_get_current_task(), box, "@realloc()=%p with orig=%p, size %lu==%lu+%lu", - new_box, box, total_size, sizeof(rust_opaque_box), new_size); + new_box, box, total_size, sizeof(rust_opaque_box), new_size);*/ return new_box; } @@ -74,9 +74,9 @@ void boxed_region::free(rust_opaque_box *box) { // double frees (kind of). assert(box->td != NULL); - LOG(rust_get_current_task(), box, + /*LOG(rust_get_current_task(), box, "@free(%p) with td %p, prev %p, next %p\n", - box, box->td, box->prev, box->next); + box, box->td, box->prev, box->next);*/ if (box->prev) box->prev->next = box->next; if (box->next) box->next->prev = box->prev; diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index a0db6f64f69fc..b8749b8f73d81 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -851,6 +851,41 @@ rust_initialize_global_state() { } } +extern "C" CDECL memory_region* +rust_new_memory_region(uintptr_t synchronized, + uintptr_t detailed_leaks, + uintptr_t poison_on_free) { + return new memory_region((bool)synchronized, + (bool)detailed_leaks, + (bool)poison_on_free); +} + +extern "C" CDECL void +rust_delete_memory_region(memory_region *region) { + delete region; +} + +extern "C" CDECL boxed_region* +rust_new_boxed_region(memory_region *region, + uintptr_t poison_on_free) { + return new boxed_region(region, poison_on_free); +} + +extern "C" CDECL void +rust_delete_boxed_region(boxed_region *region) { + delete region; +} + +extern "C" CDECL rust_opaque_box* +rust_boxed_region_malloc(boxed_region *region, type_desc *td, size_t size) { + return region->malloc(td, size); +} + +extern "C" CDECL void +rust_boxed_region_free(boxed_region *region, rust_opaque_box *box) { + region->free(box); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index f84a73a394b6c..9aa8015678360 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -222,3 +222,9 @@ rust_uv_free_ip6_addr rust_call_nullary_fn rust_initialize_global_state rust_dbg_next_port +rust_new_memory_region +rust_delete_memory_region +rust_new_boxed_region +rust_delete_boxed_region +rust_boxed_region_malloc +rust_boxed_region_free