1
Fork 0

core::rt: Add the local heap to newsched tasks

Reusing the existing boxed_region implementation from the runtime
This commit is contained in:
Brian Anderson 2013-04-21 19:03:52 -07:00
parent 2fe118b26f
commit d7f5e437a2
7 changed files with 170 additions and 10 deletions

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
}

View file

@ -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);
}
}
}

View file

@ -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)]

View file

@ -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"]

View file

@ -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;

View file

@ -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++

View file

@ -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