core::rt: Add the local heap to newsched tasks
Reusing the existing boxed_region implementation from the runtime
This commit is contained in:
parent
2fe118b26f
commit
d7f5e437a2
7 changed files with 170 additions and 10 deletions
81
src/libcore/rt/local_heap.rs
Normal file
81
src/libcore/rt/local_heap.rs
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)]
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue