diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-06-22 01:09:06 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-06-24 17:07:03 -0700 |
| commit | 5e7c5d6c3d532e7b536b76044cd47b72b8eadaad (patch) | |
| tree | 4293df31a4276cc3d477ece661fe30debc7da63a /src/libstd | |
| parent | a09972db3545344048b90e90d1f1821b621a38b9 (diff) | |
| download | rust-5e7c5d6c3d532e7b536b76044cd47b72b8eadaad.tar.gz rust-5e7c5d6c3d532e7b536b76044cd47b72b8eadaad.zip | |
std: Make box annihilator work with newsched
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/cleanup.rs | 116 | ||||
| -rw-r--r-- | src/libstd/rt/comm.rs | 12 | ||||
| -rw-r--r-- | src/libstd/rt/local_heap.rs | 50 | ||||
| -rw-r--r-- | src/libstd/rt/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 21 | ||||
| -rw-r--r-- | src/libstd/sys.rs | 5 | ||||
| -rw-r--r-- | src/libstd/unstable/lang.rs | 19 |
7 files changed, 94 insertions, 131 deletions
diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index dd7e85ce7e1..36c1fdf781b 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -13,107 +13,14 @@ use libc::{c_char, c_void, intptr_t, uintptr_t}; use ptr::mut_null; use repr::BoxRepr; +use rt; +use rt::OldTaskContext; use sys::TypeDesc; use cast::transmute; -#[cfg(not(test))] use rt::borrowck::clear_task_borrow_list; #[cfg(not(test))] use ptr::to_unsafe_ptr; -/** - * Runtime structures - * - * NB: These must match the representation in the C++ runtime. - */ - type DropGlue<'self> = &'self fn(**TypeDesc, *c_void); -type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void); - -type TaskID = uintptr_t; - -struct StackSegment { priv opaque: () } -struct Scheduler { priv opaque: () } -struct SchedulerLoop { priv opaque: () } -struct Kernel { priv opaque: () } -struct Env { priv opaque: () } -struct AllocHeader { priv opaque: () } -struct MemoryRegion { priv opaque: () } - -#[cfg(target_arch="x86")] -struct Registers { - data: [u32, ..16] -} - -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Registers { - data: [u32, ..32] -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Context { - regs: Registers, - next: *Context, - pad: [u32, ..3] -} - -#[cfg(target_arch="x86_64")] -struct Registers { - data: [u64, ..22] -} - -#[cfg(target_arch="x86_64")] -struct Context { - regs: Registers, - next: *Context, - pad: uintptr_t -} - -struct BoxedRegion { - env: *Env, - backing_region: *MemoryRegion, - live_allocs: *BoxRepr -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Task { - // Public fields - refcount: intptr_t, // 0 - id: TaskID, // 4 - pad: [u32, ..2], // 8 - ctx: Context, // 16 - stack_segment: *StackSegment, // 96 - runtime_sp: uintptr_t, // 100 - scheduler: *Scheduler, // 104 - scheduler_loop: *SchedulerLoop, // 108 - - // Fields known only to the runtime - kernel: *Kernel, // 112 - name: *c_char, // 116 - list_index: i32, // 120 - boxed_region: BoxedRegion // 128 -} - -#[cfg(target_arch="x86_64")] -struct Task { - // Public fields - refcount: intptr_t, - id: TaskID, - ctx: Context, - stack_segment: *StackSegment, - runtime_sp: uintptr_t, - scheduler: *Scheduler, - scheduler_loop: *SchedulerLoop, - - // Fields known only to the runtime - kernel: *Kernel, - name: *c_char, - list_index: i32, - boxed_region: BoxedRegion -} /* * Box annihilation @@ -132,9 +39,9 @@ unsafe fn each_live_alloc(read_next_before: bool, //! Walks the internal list of allocations use managed; + use rt::local_heap; - let task: *Task = transmute(rustrt::rust_get_task()); - let box = (*task).boxed_region.live_allocs; + let box = local_heap::live_allocs(); let mut box: *mut BoxRepr = transmute(copy box); while box != mut_null() { let next_before = transmute(copy (*box).header.next); @@ -156,7 +63,11 @@ unsafe fn each_live_alloc(read_next_before: bool, #[cfg(unix)] fn debug_mem() -> bool { - ::rt::env::get().debug_mem + // XXX: Need to port the environment struct to newsched + match rt::context() { + OldTaskContext => ::rt::env::get().debug_mem, + _ => false + } } #[cfg(windows)] @@ -165,13 +76,12 @@ fn debug_mem() -> bool { } /// Destroys all managed memory (i.e. @ boxes) held by the current task. -#[cfg(not(test))] -#[lang="annihilate"] pub unsafe fn annihilate() { - use unstable::lang::local_free; + use rt::local_heap::local_free; use io::WriterUtil; use io; use libc; + use rt::borrowck; use sys; use managed; @@ -183,7 +93,7 @@ pub unsafe fn annihilate() { // Quick hack: we need to free this list upon task exit, and this // is a convenient place to do it. - clear_task_borrow_list(); + borrowck::clear_task_borrow_list(); // Pass 1: Make all boxes immortal. // @@ -207,7 +117,7 @@ pub unsafe fn annihilate() { if !uniq { let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc); let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0)); - drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data)); + drop_glue(&tydesc, transmute(&(*box).data)); } } diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 82e6d44fe62..dd27c03ff51 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -399,12 +399,6 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> { } impl<T: Owned> GenericSmartChan<T> for SharedChan<T> { - #[cfg(stage0)] // odd type checking errors - fn try_send(&self, _val: T) -> bool { - fail!() - } - - #[cfg(not(stage0))] fn try_send(&self, val: T) -> bool { unsafe { let (next_pone, next_cone) = oneshot(); @@ -448,12 +442,6 @@ impl<T: Owned> GenericPort<T> for SharedPort<T> { } } - #[cfg(stage0)] // odd type checking errors - fn try_recv(&self) -> Option<T> { - fail!() - } - - #[cfg(not(stage0))] fn try_recv(&self) -> Option<T> { unsafe { let (next_link_port, next_link_chan) = oneshot(); diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 38cd25f9da5..f62c9fb2c66 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -10,11 +10,24 @@ //! The local, garbage collected heap +use libc; use libc::{c_void, uintptr_t, size_t}; use ops::Drop; +use repr::BoxRepr; +use rt; +use rt::OldTaskContext; +use rt::local::Local; +use rt::task::Task; type MemoryRegion = c_void; -type BoxedRegion = c_void; + +struct Env { priv opaque: () } + +struct BoxedRegion { + env: *Env, + backing_region: *MemoryRegion, + live_allocs: *BoxRepr +} pub type OpaqueBox = c_void; pub type TypeDesc = c_void; @@ -71,6 +84,40 @@ impl Drop for LocalHeap { } } +// A little compatibility function +pub unsafe fn local_free(ptr: *libc::c_char) { + match rt::context() { + OldTaskContext => { + rust_upcall_free_noswitch(ptr); + + extern { + #[fast_ffi] + unsafe fn rust_upcall_free_noswitch(ptr: *libc::c_char); + } + } + _ => { + do Local::borrow::<Task,()> |task| { + task.heap.free(ptr as *libc::c_void); + } + } + } +} + +pub fn live_allocs() -> *BoxRepr { + let region = match rt::context() { + OldTaskContext => { + unsafe { rust_current_boxed_region() } + } + _ => { + do Local::borrow::<Task, *BoxedRegion> |task| { + task.heap.boxed_region + } + } + }; + + return unsafe { (*region).live_allocs }; +} + extern { fn rust_new_memory_region(synchronized: uintptr_t, detailed_leaks: uintptr_t, @@ -86,4 +133,5 @@ extern { ptr: *OpaqueBox, size: size_t) -> *OpaqueBox; fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox); + fn rust_current_boxed_region() -> *BoxedRegion; } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 6c4e5742eb3..fec555e8afd 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -124,7 +124,7 @@ mod thread; pub mod env; /// The local, managed heap -mod local_heap; +pub mod local_heap; /// The Logger trait and implementations pub mod logging; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 833f25b253c..68f7eb659b0 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -15,6 +15,7 @@ use borrow; use cast::transmute; +use cleanup; use libc::{c_void, uintptr_t}; use ptr; use prelude::*; @@ -118,6 +119,10 @@ impl Task { } _ => () } + + // Destroy remaining boxes + unsafe { cleanup::annihilate(); } + self.destroyed = true; } } @@ -269,4 +274,20 @@ mod test { assert!(res.is_err()); } } + + #[test] + fn heap_cycles() { + use option::{Option, Some, None}; + + do run_in_newsched_task { + struct List { + next: Option<@mut List>, + } + + let a = @mut List { next: None }; + let b = @mut List { next: Some(a) }; + + a.next = Some(b); + } + } } diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index 8ac60ffb979..523c5d633cf 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -216,12 +216,15 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { task.logger.log(Left(outmsg.take())); } } else { - rtdebug!("%s", outmsg); + rterrln!("%s", outmsg); } gc::cleanup_stack_for_failure(); let task = Local::unsafe_borrow::<Task>(); + if (*task).unwinder.unwinding { + rtabort!("unwinding again"); + } (*task).unwinder.begin_unwind(); } } diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index d71a672eb35..f750b31a466 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -43,9 +43,6 @@ pub mod rustrt { size: uintptr_t) -> *c_char; - #[fast_ffi] - unsafe fn rust_upcall_free_noswitch(ptr: *c_char); - #[rust_stack] fn rust_try_get_task() -> *rust_task; @@ -105,16 +102,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { // problem occurs, call exit instead. #[lang="free"] pub unsafe fn local_free(ptr: *c_char) { - match context() { - OldTaskContext => { - rustrt::rust_upcall_free_noswitch(ptr); - } - _ => { - do Local::borrow::<Task,()> |task| { - task.heap.free(ptr as *c_void); - } - } - } + ::rt::local_heap::local_free(ptr); } #[lang="borrow_as_imm"] @@ -162,6 +150,11 @@ pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { str::raw::from_buf_len(ptr, len) } +#[lang="annihilate"] +pub unsafe fn annihilate() { + ::cleanup::annihilate() +} + #[lang="start"] pub fn start(main: *u8, argc: int, argv: **c_char, crate_map: *u8) -> int { |
