use raw::Closure;
use libc::c_void;
-use rt::local::Local;
-use rt::task::Task;
-
+use sys_common::thread_info;
use rt::libunwind as uw;
-#[allow(missing_copy_implementations)]
-pub struct Unwinder {
- unwinding: bool,
-}
-
struct Exception {
uwe: uw::_Unwind_Exception,
cause: Option<Box<Any + Send>>,
atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT];
static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
-impl Unwinder {
- pub fn new() -> Unwinder {
- Unwinder {
- unwinding: false,
- }
- }
-
- pub fn unwinding(&self) -> bool {
- self.unwinding
- }
-}
-
/// Invoke a closure, capturing the cause of panic if one occurs.
///
/// This function will return `None` if the closure did not panic, and will
/// we need the `Any` object anyway, we're not just creating it to
/// avoid being generic.)
///
-/// Do this split took the LLVM IR line counts of `fn main() { panic!()
+/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
/// }` from ~1900/3700 (-O/no opts) to 180/590.
#[inline(never)] #[cold] // this is the slow path, please never inline this
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
};
// Now that we've run all the necessary unwind callbacks, we actually
- // perform the unwinding. If we don't have a task, then it's time to die
- // (hopefully someone printed something about this).
- let mut task: Box<Task> = match Local::try_take() {
- Some(task) => task,
- None => rust_panic(msg),
- };
-
- if task.unwinder.unwinding {
- // If a task panics while it's already unwinding then we
+ // perform the unwinding.
+ if thread_info::unwinding() {
+ // If a thread panics while it's already unwinding then we
// have limited options. Currently our preference is to
// just abort. In the future we may consider resuming
// unwinding or otherwise exiting the task cleanly.
rterrln!("task failed during unwinding. aborting.");
unsafe { intrinsics::abort() }
}
- task.unwinder.unwinding = true;
-
- // Put the task back in TLS because the unwinding process may run code which
- // requires the task. We need a handle to its unwinder, however, so after
- // this we unsafely extract it and continue along.
- Local::put(task);
+ thread_info::set_unwinding(true);
rust_panic(msg);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use thread::Thread;
+use cell::RefCell;
+use string::String;
+
struct ThreadInfo {
// This field holds the known bounds of the stack in (lo, hi)
// form. Not all threads necessarily know their precise bounds,
// hence this is optional.
stack_bounds: (uint, uint),
stack_guard: uint,
- unwinder: Unwinder,
+ unwinding: bool,
thread: Thread,
}
-thread_local!(static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None));
+thread_local!(static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None))
impl ThreadInfo {
- fn with<R>(f: |&ThreadInfo| -> R) -> R {
+ fn with<R>(f: |&mut ThreadInfo| -> R) -> R {
THREAD_INFO.with(|c| {
if c.borrow().is_none() {
*c.borrow_mut() = Some(ThreadInfo {
stack_bounds: (0, 0),
stack_guard: 0,
- unwinder: Unwinder::new(),
+ unwinder: false,
thread: Thread::new(None),
})
}
- f(c.borrow().as_ref().unwrap())
+ f(c.borrow_mut().as_ref().unwrap())
})
}
}
ThreadInfo::with(|info| info.unwinder.unwinding())
}
+pub fn stack_guard() -> uint {
+ ThreadInfo::with(|info| info.stack_guard)
+}
+
+pub fn unwinding() -> bool {
+ ThreadInfo::with(|info| info.unwinder.unwinding)
+}
+
+pub fn set_unwinding(unwinding: bool) {
+ ThreadInfo::with(|info| info.unwinding = unwinding)
+}
+
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(|c| *c.borrow_mut() = Some(ThreadInfo{
stack_bounds: stack_bounds,
stack_guard: stack_guard,
- unwinder: Unwinder::new(),
+ unwinding: false,
thread: thread,
}));
}