diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-01-02 09:19:00 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-01-02 09:19:00 -0800 |
| commit | 009ec5d2b0c4ab0e7dc7ab2f6b15754b4da14caf (patch) | |
| tree | 8b441fd58860857f2e7bf5eabbf2226b92bf13c7 /src/libstd/rt | |
| parent | 0101bbe7acb38e8113c0cafeb7d5ae0be6448e5b (diff) | |
| parent | f3a7ec7028c76b3a1c6051131328f372b068e33a (diff) | |
| download | rust-009ec5d2b0c4ab0e7dc7ab2f6b15754b4da14caf.tar.gz rust-009ec5d2b0c4ab0e7dc7ab2f6b15754b4da14caf.zip | |
rollup merge of #20315: alexcrichton/std-sync
Conflicts: src/libstd/rt/exclusive.rs src/libstd/sync/barrier.rs src/libstd/sys/unix/pipe.rs src/test/bench/shootout-binarytrees.rs src/test/bench/shootout-fannkuch-redux.rs
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/backtrace.rs | 2 | ||||
| -rw-r--r-- | src/libstd/rt/exclusive.rs | 119 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 554 | ||||
| -rw-r--r-- | src/libstd/rt/unwind.rs | 20 | ||||
| -rw-r--r-- | src/libstd/rt/util.rs | 2 |
5 files changed, 12 insertions, 685 deletions
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 4abef6ee910..ae405e9400b 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -22,7 +22,7 @@ pub use sys::backtrace::write; // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. pub fn log_enabled() -> bool { - static ENABLED: atomic::AtomicInt = atomic::INIT_ATOMIC_INT; + static ENABLED: atomic::AtomicInt = atomic::ATOMIC_INT_INIT; match ENABLED.load(atomic::SeqCst) { 1 => return false, 2 => return true, diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs deleted file mode 100644 index eb6b3655444..00000000000 --- a/src/libstd/rt/exclusive.rs +++ /dev/null @@ -1,119 +0,0 @@ -// 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. - -use core::prelude::*; - -use cell::UnsafeCell; -use rt::mutex; - -/// An OS mutex over some data. -/// -/// This is not a safe primitive to use, it is unaware of the libgreen -/// scheduler, as well as being easily susceptible to misuse due to the usage of -/// the inner NativeMutex. -/// -/// > **Note**: This type is not recommended for general use. The mutex provided -/// > as part of `libsync` should almost always be favored. -pub struct Exclusive<T> { - lock: mutex::NativeMutex, - data: UnsafeCell<T>, -} - -unsafe impl<T:Send> Send for Exclusive<T> { } - -unsafe impl<T:Send> Sync for Exclusive<T> { } - -/// An RAII guard returned via `lock` -pub struct ExclusiveGuard<'a, T:'a> { - // FIXME #12808: strange name to try to avoid interfering with - // field accesses of the contained type via Deref - _data: &'a mut T, - _guard: mutex::LockGuard<'a>, -} - -impl<T: Send> Exclusive<T> { - /// Creates a new `Exclusive` which will protect the data provided. - pub fn new(user_data: T) -> Exclusive<T> { - Exclusive { - lock: unsafe { mutex::NativeMutex::new() }, - data: UnsafeCell::new(user_data), - } - } - - /// Acquires this lock, returning a guard which the data is accessed through - /// and from which that lock will be unlocked. - /// - /// This method is unsafe due to many of the same reasons that the - /// NativeMutex itself is unsafe. - pub unsafe fn lock<'a>(&'a self) -> ExclusiveGuard<'a, T> { - let guard = self.lock.lock(); - let data = &mut *self.data.get(); - - ExclusiveGuard { - _data: data, - _guard: guard, - } - } -} - -impl<'a, T: Send> ExclusiveGuard<'a, T> { - // The unsafety here should be ok because our loan guarantees that the lock - // itself is not moving - pub fn signal(&self) { - unsafe { self._guard.signal() } - } - pub fn wait(&self) { - unsafe { self._guard.wait() } - } -} - -impl<'a, T: Send> Deref<T> for ExclusiveGuard<'a, T> { - fn deref(&self) -> &T { &*self._data } -} -impl<'a, T: Send> DerefMut<T> for ExclusiveGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { &mut *self._data } -} - -#[cfg(test)] -mod tests { - use prelude::v1::*; - use sync::Arc; - use super::Exclusive; - use task; - - #[test] - fn exclusive_new_arc() { - unsafe { - let mut futures = Vec::new(); - - let num_tasks = 10; - let count = 10; - - let total = Arc::new(Exclusive::new(box 0)); - - for _ in range(0u, num_tasks) { - let total = total.clone(); - let (tx, rx) = channel(); - futures.push(rx); - - task::spawn(move || { - for _ in range(0u, count) { - **total.lock() += 1; - } - tx.send(()); - }); - }; - - for f in futures.iter_mut() { f.recv() } - - assert_eq!(**total.lock(), num_tasks * count); - } - } -} diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs deleted file mode 100644 index 48cdfc20a35..00000000000 --- a/src/libstd/rt/task.rs +++ /dev/null @@ -1,554 +0,0 @@ -// Copyright 2013-2014 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. - -//! Language-level runtime services that should reasonably expected -//! to be available 'everywhere'. Unwinding, local storage, and logging. -//! Even a 'freestanding' Rust would likely want to implement this. - -pub use self::BlockedTask::*; -use self::TaskState::*; - -use any::Any; -use boxed::Box; -use sync::Arc; -use sync::atomic::{AtomicUint, SeqCst}; -use iter::{IteratorExt, Take}; -use kinds::marker; -use mem; -use ops::FnMut; -use core::prelude::{Clone, Drop, Err, Iterator, None, Ok, Option, Send, Some}; -use core::prelude::{drop}; -use str::SendStr; -use thunk::Thunk; - -use rt; -use rt::mutex::NativeMutex; -use rt::local::Local; -use rt::thread::{mod, Thread}; -use sys_common::stack; -use rt::unwind; -use rt::unwind::Unwinder; - -/// State associated with Rust threads -/// -/// This structure is currently undergoing major changes, and is -/// likely to be move/be merged with a `Thread` structure. -pub struct Task { - pub unwinder: Unwinder, - pub death: Death, - pub name: Option<SendStr>, - - state: TaskState, - lock: NativeMutex, // native synchronization - awoken: bool, // used to prevent spurious wakeups - - // This field holds the known bounds of the stack in (lo, hi) form. Not all - // native threads necessarily know their precise bounds, hence this is - // optional. - stack_bounds: (uint, uint), - - stack_guard: uint -} - -// Once a thread has entered the `Armed` state it must be destroyed via `drop`, -// and no other method. This state is used to track this transition. -#[deriving(PartialEq)] -enum TaskState { - New, - Armed, - Destroyed, -} - -pub struct TaskOpts { - /// Invoke this procedure with the result of the thread when it finishes. - pub on_exit: Option<Thunk<Result>>, - /// A name for the thread-to-be, for identification in panic messages - pub name: Option<SendStr>, - /// The size of the stack for the spawned thread - pub stack_size: Option<uint>, -} - -/// Indicates the manner in which a thread exited. -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// If you wish for this result's delivery to block until all -/// children threads complete, recommend using a result future. -pub type Result = ::core::result::Result<(), Box<Any + Send>>; - -/// A handle to a blocked thread. Usually this means having the Box<Task> -/// pointer by ownership, but if the thread is killable, a killer can steal it -/// at any time. -pub enum BlockedTask { - Owned(Box<Task>), - Shared(Arc<AtomicUint>), -} - -/// Per-thread state related to thread death, killing, panic, etc. -pub struct Death { - pub on_exit: Option<Thunk<Result>>, -} - -pub struct BlockedTasks { - inner: Arc<AtomicUint>, -} - -impl Task { - /// Creates a new uninitialized thread. - pub fn new(stack_bounds: Option<(uint, uint)>, stack_guard: Option<uint>) -> Task { - Task { - unwinder: Unwinder::new(), - death: Death::new(), - state: New, - name: None, - lock: unsafe { NativeMutex::new() }, - awoken: false, - // these *should* get overwritten - stack_bounds: stack_bounds.unwrap_or((0, 0)), - stack_guard: stack_guard.unwrap_or(0) - } - } - - pub fn spawn<F>(opts: TaskOpts, f: F) - where F : FnOnce(), F : Send - { - Task::spawn_thunk(opts, Thunk::new(f)) - } - - fn spawn_thunk(opts: TaskOpts, f: Thunk) { - let TaskOpts { name, stack_size, on_exit } = opts; - - let mut task = box Task::new(None, None); - task.name = name; - task.death.on_exit = on_exit; - - let stack = stack_size.unwrap_or(rt::min_stack()); - - // Spawning a new OS thread guarantees that __morestack will never get - // triggered, but we must manually set up the actual stack bounds once - // this function starts executing. This raises the lower limit by a bit - // because by the time that this function is executing we've already - // consumed at least a little bit of stack (we don't know the exact byte - // address at which our stack started). - Thread::spawn_stack(stack, move|| { - let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *const int; - let my_stack = addr as uint; - unsafe { - stack::record_os_managed_stack_bounds(my_stack - stack + 1024, - my_stack); - } - task.stack_guard = thread::current_guard_page(); - task.stack_bounds = (my_stack - stack + 1024, my_stack); - - let mut f = Some(f); - drop(task.run(|| { f.take().unwrap().invoke(()) }).destroy()); - }) - } - - /// Consumes ownership of a thread, runs some code, and returns the thread back. - /// - /// This function can be used as an emulated "try/catch" to interoperate - /// with the rust runtime at the outermost boundary. It is not possible to - /// use this function in a nested fashion (a try/catch inside of another - /// try/catch). Invoking this function is quite cheap. - /// - /// If the closure `f` succeeds, then the returned thread can be used again - /// for another invocation of `run`. If the closure `f` panics then `self` - /// will be internally destroyed along with all of the other associated - /// resources of this thread. The `on_exit` callback is invoked with the - /// cause of panic (not returned here). This can be discovered by querying - /// `is_destroyed()`. - /// - /// Note that it is possible to view partial execution of the closure `f` - /// because it is not guaranteed to run to completion, but this function is - /// guaranteed to return if it panicks. Care should be taken to ensure that - /// stack references made by `f` are handled appropriately. - /// - /// It is invalid to call this function with a thread that has been previously - /// destroyed via a failed call to `run`. - pub fn run<F>(mut self: Box<Task>, f: F) -> Box<Task> where F: FnOnce() { - assert!(!self.is_destroyed(), "cannot re-use a destroyed thread"); - - // First, make sure that no one else is in TLS. This does not allow - // recursive invocations of run(). If there's no one else, then - // relinquish ownership of ourselves back into TLS. - if Local::exists(None::<Task>) { - panic!("cannot run a thread recursively inside another"); - } - self.state = Armed; - Local::put(self); - - // There are two primary reasons that general try/catch is unsafe. The - // first is that we do not support nested try/catch. The above check for - // an existing thread in TLS is sufficient for this invariant to be - // upheld. The second is that unwinding while unwinding is not defined. - // We take care of that by having an 'unwinding' flag in the thread - // itself. For these reasons, this unsafety should be ok. - let result = unsafe { unwind::try(f) }; - - // After running the closure given return the thread back out if it ran - // successfully, or clean up the thread if it panicked. - let task: Box<Task> = Local::take(); - match result { - Ok(()) => task, - Err(cause) => { task.cleanup(Err(cause)) } - } - } - - /// Destroy all associated resources of this thread. - /// - /// This function will perform any necessary clean up to prepare the thread - /// for destruction. It is required that this is called before a `Task` - /// falls out of scope. - /// - /// The returned thread cannot be used for running any more code, but it may - /// be used to extract the runtime as necessary. - pub fn destroy(self: Box<Task>) -> Box<Task> { - if self.is_destroyed() { - self - } else { - self.cleanup(Ok(())) - } - } - - /// Cleans up a thread, processing the result of the thread as appropriate. - /// - /// This function consumes ownership of the thread, deallocating it once it's - /// done being processed. It is assumed that TLD and the local heap have - /// already been destroyed and/or annihilated. - fn cleanup(mut self: Box<Task>, result: Result) -> Box<Task> { - // After taking care of the data above, we need to transmit the result - // of this thread. - let what_to_do = self.death.on_exit.take(); - Local::put(self); - - // FIXME: this is running in a seriously constrained context. If this - // allocates TLD then it will likely abort the runtime. Similarly, - // if this panics, this will also likely abort the runtime. - // - // This closure is currently limited to a channel send via the - // standard library's thread interface, but this needs - // reconsideration to whether it's a reasonable thing to let a - // thread to do or not. - match what_to_do { - Some(f) => { f.invoke(result) } - None => { drop(result) } - } - - // Now that we're done, we remove the thread from TLS and flag it for - // destruction. - let mut task: Box<Task> = Local::take(); - task.state = Destroyed; - return task; - } - - /// Queries whether this can be destroyed or not. - pub fn is_destroyed(&self) -> bool { self.state == Destroyed } - - /// Deschedules the current thread, invoking `f` `amt` times. It is not - /// recommended to use this function directly, but rather communication - /// primitives in `std::comm` should be used. - // - // This function gets a little interesting. There are a few safety and - // ownership violations going on here, but this is all done in the name of - // shared state. Additionally, all of the violations are protected with a - // mutex, so in theory there are no races. - // - // The first thing we need to do is to get a pointer to the thread's internal - // mutex. This address will not be changing (because the thread is allocated - // on the heap). We must have this handle separately because the thread will - // have its ownership transferred to the given closure. We're guaranteed, - // however, that this memory will remain valid because *this* is the current - // thread's execution thread. - // - // The next weird part is where ownership of the thread actually goes. We - // relinquish it to the `f` blocking function, but upon returning this - // function needs to replace the thread back in TLS. There is no communication - // from the wakeup thread back to this thread about the thread pointer, and - // there's really no need to. In order to get around this, we cast the thread - // to a `uint` which is then used at the end of this function to cast back - // to a `Box<Task>` object. Naturally, this looks like it violates - // ownership semantics in that there may be two `Box<Task>` objects. - // - // The fun part is that the wakeup half of this implementation knows to - // "forget" the thread on the other end. This means that the awakening half of - // things silently relinquishes ownership back to this thread, but not in a - // way that the compiler can understand. The thread's memory is always valid - // for both threads because these operations are all done inside of a mutex. - // - // You'll also find that if blocking fails (the `f` function hands the - // BlockedTask back to us), we will `mem::forget` the handles. The - // reasoning for this is the same logic as above in that the thread silently - // transfers ownership via the `uint`, not through normal compiler - // semantics. - // - // On a mildly unrelated note, it should also be pointed out that OS - // condition variables are susceptible to spurious wakeups, which we need to - // be ready for. In order to accommodate for this fact, we have an extra - // `awoken` field which indicates whether we were actually woken up via some - // invocation of `reawaken`. This flag is only ever accessed inside the - // lock, so there's no need to make it atomic. - pub fn deschedule<F>(mut self: Box<Task>, times: uint, mut f: F) where - F: FnMut(BlockedTask) -> ::core::result::Result<(), BlockedTask>, - { - unsafe { - let me = &mut *self as *mut Task; - let task = BlockedTask::block(self); - - if times == 1 { - let guard = (*me).lock.lock(); - (*me).awoken = false; - match f(task) { - Ok(()) => { - while !(*me).awoken { - guard.wait(); - } - } - Err(task) => { mem::forget(task.wake()); } - } - } else { - let iter = task.make_selectable(times); - let guard = (*me).lock.lock(); - (*me).awoken = false; - - // Apply the given closure to all of the "selectable threads", - // bailing on the first one that produces an error. Note that - // care must be taken such that when an error is occurred, we - // may not own the thread, so we may still have to wait for the - // thread to become available. In other words, if thread.wake() - // returns `None`, then someone else has ownership and we must - // wait for their signal. - match iter.map(f).filter_map(|a| a.err()).next() { - None => {} - Some(task) => { - match task.wake() { - Some(task) => { - mem::forget(task); - (*me).awoken = true; - } - None => {} - } - } - } - while !(*me).awoken { - guard.wait(); - } - } - // put the thread back in TLS, and everything is as it once was. - Local::put(mem::transmute(me)); - } - } - - /// Wakes up a previously blocked thread. This function can only be - /// called on threads that were previously blocked in `deschedule`. - // - // See the comments on `deschedule` for why the thread is forgotten here, and - // why it's valid to do so. - pub fn reawaken(mut self: Box<Task>) { - unsafe { - let me = &mut *self as *mut Task; - mem::forget(self); - let guard = (*me).lock.lock(); - (*me).awoken = true; - guard.signal(); - } - } - - /// Yields control of this thread to another thread. This function will - /// eventually return, but possibly not immediately. This is used as an - /// opportunity to allow other threads a chance to run. - pub fn yield_now() { - Thread::yield_now(); - } - - /// Returns the stack bounds for this thread in (lo, hi) format. The stack - /// bounds may not be known for all threads, so the return value may be - /// `None`. - pub fn stack_bounds(&self) -> (uint, uint) { - self.stack_bounds - } - - /// Returns the stack guard for this thread, if known. - pub fn stack_guard(&self) -> Option<uint> { - if self.stack_guard != 0 { - Some(self.stack_guard) - } else { - None - } - } - - /// Consume this thread, flagging it as a candidate for destruction. - /// - /// This function is required to be invoked to destroy a thread. A thread - /// destroyed through a normal drop will abort. - pub fn drop(mut self) { - self.state = Destroyed; - } -} - -impl Drop for Task { - fn drop(&mut self) { - rtdebug!("called drop for a thread: {}", self as *mut Task as uint); - rtassert!(self.state != Armed); - } -} - -impl TaskOpts { - pub fn new() -> TaskOpts { - TaskOpts { on_exit: None, name: None, stack_size: None } - } -} - -impl Iterator<BlockedTask> for BlockedTasks { - fn next(&mut self) -> Option<BlockedTask> { - Some(Shared(self.inner.clone())) - } -} - -impl BlockedTask { - /// Returns Some if the thread was successfully woken; None if already killed. - pub fn wake(self) -> Option<Box<Task>> { - match self { - Owned(task) => Some(task), - Shared(arc) => { - match arc.swap(0, SeqCst) { - 0 => None, - n => Some(unsafe { mem::transmute(n) }), - } - } - } - } - - /// Reawakens this thread if ownership is acquired. If finer-grained control - /// is desired, use `wake` instead. - pub fn reawaken(self) { - self.wake().map(|t| t.reawaken()); - } - - // This assertion has two flavours because the wake involves an atomic op. - // In the faster version, destructors will panic dramatically instead. - #[cfg(not(test))] pub fn trash(self) { } - #[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); } - - /// Create a blocked thread, unless the thread was already killed. - pub fn block(task: Box<Task>) -> BlockedTask { - Owned(task) - } - - /// Converts one blocked thread handle to a list of many handles to the same. - pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> { - let arc = match self { - Owned(task) => { - let flag = unsafe { AtomicUint::new(mem::transmute(task)) }; - Arc::new(flag) - } - Shared(arc) => arc.clone(), - }; - BlockedTasks{ inner: arc }.take(num_handles) - } - - /// Convert to an unsafe uint value. Useful for storing in a pipe's state - /// flag. - #[inline] - pub unsafe fn cast_to_uint(self) -> uint { - match self { - Owned(task) => { - let blocked_task_ptr: uint = mem::transmute(task); - rtassert!(blocked_task_ptr & 0x1 == 0); - blocked_task_ptr - } - Shared(arc) => { - let blocked_task_ptr: uint = mem::transmute(box arc); - rtassert!(blocked_task_ptr & 0x1 == 0); - blocked_task_ptr | 0x1 - } - } - } - - /// Convert from an unsafe uint value. Useful for retrieving a pipe's state - /// flag. - #[inline] - pub unsafe fn cast_from_uint(blocked_task_ptr: uint) -> BlockedTask { - if blocked_task_ptr & 0x1 == 0 { - Owned(mem::transmute(blocked_task_ptr)) - } else { - let ptr: Box<Arc<AtomicUint>> = - mem::transmute(blocked_task_ptr & !1); - Shared(*ptr) - } - } -} - -impl Death { - pub fn new() -> Death { - Death { on_exit: None } - } -} - -#[cfg(test)] -mod test { - use super::*; - use prelude::v1::*; - use task; - use rt::unwind; - - #[test] - fn unwind() { - let result = task::try(move|| ()); - rtdebug!("trying first assert"); - assert!(result.is_ok()); - let result = task::try(move|| -> () panic!()); - rtdebug!("trying second assert"); - assert!(result.is_err()); - } - - #[test] - fn rng() { - use rand::{StdRng, Rng}; - let mut r = StdRng::new().ok().unwrap(); - let _ = r.next_u32(); - } - - #[test] - fn comm_stream() { - let (tx, rx) = channel(); - tx.send(10i); - assert!(rx.recv() == 10); - } - - #[test] - fn comm_shared_chan() { - let (tx, rx) = channel(); - tx.send(10i); - assert!(rx.recv() == 10); - } - - #[test] - #[should_fail] - fn test_begin_unwind() { - use rt::unwind::begin_unwind; - begin_unwind("cause", &(file!(), line!())) - } - - #[test] - fn drop_new_task_ok() { - drop(Task::new(None, None)); - } - - // Thread blocking tests - - #[test] - fn block_and_wake() { - let task = box Task::new(None, None); - let task = BlockedTask::block(task).wake().unwrap(); - task.drop(); - } -} diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index d5a7c9aba9d..6f6be2e111d 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -84,15 +84,15 @@ pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); // For more information, see below. const MAX_CALLBACKS: uint = 16; static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] = - [atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT]; -static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + [atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT]; +static CALLBACK_CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; thread_local! { static PANICKING: Cell<bool> = Cell::new(false) } @@ -533,7 +533,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> // Make sure the default failure handler is registered before we look at the // callbacks. static INIT: Once = ONCE_INIT; - INIT.doit(|| unsafe { register(failure::on_fail); }); + INIT.call_once(|| unsafe { register(failure::on_fail); }); // First, invoke call the user-defined callbacks triggered on thread panic. // diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 384783221df..09859cab536 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -46,7 +46,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { } pub fn min_stack() -> uint { - static MIN: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; match MIN.load(atomic::SeqCst) { 0 => {} n => return n - 1, |
