Skip to main content

rustc_thread_pool/
registry.rs

1use std::cell::Cell;
2use std::collections::hash_map::DefaultHasher;
3use std::hash::Hasher;
4use std::sync::atomic::{AtomicUsize, Ordering};
5use std::sync::{Arc, Mutex, Once};
6use std::{fmt, io, mem, ptr, thread};
7
8use crossbeam_deque::{Injector, Steal, Stealer, Worker};
9use smallvec::SmallVec;
10
11use crate::job::{JobFifo, JobRef, StackJob};
12use crate::latch::{AsCoreLatch, CoreLatch, Latch, LatchRef, LockLatch, OnceLatch, SpinLatch};
13use crate::sleep::Sleep;
14use crate::tlv::Tlv;
15use crate::{
16    AcquireThreadHandler, DeadlockHandler, ErrorKind, ExitHandler, PanicHandler,
17    ReleaseThreadHandler, StartHandler, ThreadPoolBuildError, ThreadPoolBuilder, Yield, unwind,
18};
19
20/// Thread builder used for customization via
21/// [`ThreadPoolBuilder::spawn_handler`](struct.ThreadPoolBuilder.html#method.spawn_handler).
22pub struct ThreadBuilder {
23    name: Option<String>,
24    stack_size: Option<usize>,
25    worker: Worker<JobRef>,
26    stealer: Stealer<JobRef>,
27    registry: Arc<Registry>,
28    index: usize,
29}
30
31impl ThreadBuilder {
32    /// Gets the index of this thread in the pool, within `0..num_threads`.
33    pub fn index(&self) -> usize {
34        self.index
35    }
36
37    /// Gets the string that was specified by `ThreadPoolBuilder::name()`.
38    pub fn name(&self) -> Option<&str> {
39        self.name.as_deref()
40    }
41
42    /// Gets the value that was specified by `ThreadPoolBuilder::stack_size()`.
43    pub fn stack_size(&self) -> Option<usize> {
44        self.stack_size
45    }
46
47    /// Executes the main loop for this thread. This will not return until the
48    /// thread pool is dropped.
49    pub fn run(self) {
50        unsafe { main_loop(self) }
51    }
52}
53
54impl fmt::Debug for ThreadBuilder {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        f.debug_struct("ThreadBuilder")
57            .field("pool", &self.registry.id())
58            .field("index", &self.index)
59            .field("name", &self.name)
60            .field("stack_size", &self.stack_size)
61            .finish()
62    }
63}
64
65/// Generalized trait for spawning a thread in the `Registry`.
66///
67/// This trait is pub-in-private -- E0445 forces us to make it public,
68/// but we don't actually want to expose these details in the API.
69pub trait ThreadSpawn {
70    /// This trait is private; this method exists to make it
/// impossible to implement outside the crate.
#[doc(hidden)]
fn __rayon_private__(&self) -> crate::private::PrivateMarker;private_decl! {}
71
72    /// Spawn a thread with the `ThreadBuilder` parameters, and then
73    /// call `ThreadBuilder::run()`.
74    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()>;
75}
76
77/// Spawns a thread in the "normal" way with `std::thread::Builder`.
78///
79/// This type is pub-in-private -- E0445 forces us to make it public,
80/// but we don't actually want to expose these details in the API.
81#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DefaultSpawn {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "DefaultSpawn")
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for DefaultSpawn {
    #[inline]
    fn default() -> DefaultSpawn { DefaultSpawn {} }
}Default)]
82pub struct DefaultSpawn;
83
84impl ThreadSpawn for DefaultSpawn {
85    fn __rayon_private__(&self) -> crate::private::PrivateMarker {
    crate::private::PrivateMarker
}private_impl! {}
86
87    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
88        let mut b = thread::Builder::new();
89        if let Some(name) = thread.name() {
90            b = b.name(name.to_owned());
91        }
92        if let Some(stack_size) = thread.stack_size() {
93            b = b.stack_size(stack_size);
94        }
95        b.spawn(|| thread.run())?;
96        Ok(())
97    }
98}
99
100/// Spawns a thread with a user's custom callback.
101///
102/// This type is pub-in-private -- E0445 forces us to make it public,
103/// but we don't actually want to expose these details in the API.
104#[derive(#[automatically_derived]
impl<F: ::core::fmt::Debug> ::core::fmt::Debug for CustomSpawn<F> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "CustomSpawn",
            &&self.0)
    }
}Debug)]
105pub struct CustomSpawn<F>(F);
106
107impl<F> CustomSpawn<F>
108where
109    F: FnMut(ThreadBuilder) -> io::Result<()>,
110{
111    pub(super) fn new(spawn: F) -> Self {
112        CustomSpawn(spawn)
113    }
114}
115
116impl<F> ThreadSpawn for CustomSpawn<F>
117where
118    F: FnMut(ThreadBuilder) -> io::Result<()>,
119{
120    fn __rayon_private__(&self) -> crate::private::PrivateMarker {
    crate::private::PrivateMarker
}private_impl! {}
121
122    #[inline]
123    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
124        (self.0)(thread)
125    }
126}
127
128pub struct Registry {
129    thread_infos: Vec<ThreadInfo>,
130    sleep: Sleep,
131    injected_jobs: Injector<JobRef>,
132    broadcasts: Mutex<Vec<Worker<JobRef>>>,
133    panic_handler: Option<Box<PanicHandler>>,
134    pub(crate) deadlock_handler: Option<Box<DeadlockHandler>>,
135    start_handler: Option<Box<StartHandler>>,
136    exit_handler: Option<Box<ExitHandler>>,
137    pub(crate) acquire_thread_handler: Option<Box<AcquireThreadHandler>>,
138    pub(crate) release_thread_handler: Option<Box<ReleaseThreadHandler>>,
139
140    // When this latch reaches 0, it means that all work on this
141    // registry must be complete. This is ensured in the following ways:
142    //
143    // - if this is the global registry, there is a ref-count that never
144    //   gets released.
145    // - if this is a user-created thread-pool, then so long as the thread-pool
146    //   exists, it holds a reference.
147    // - when we inject a "blocking job" into the registry with `ThreadPool::install()`,
148    //   no adjustment is needed; the `ThreadPool` holds the reference, and since we won't
149    //   return until the blocking job is complete, that ref will continue to be held.
150    // - when `join()` or `scope()` is invoked, similarly, no adjustments are needed.
151    //   These are always owned by some other job (e.g., one injected by `ThreadPool::install()`)
152    //   and that job will keep the pool alive.
153    terminate_count: AtomicUsize,
154}
155
156///////////////////////////////////////////////////////////////////////////
157// Initialization
158
159static mut THE_REGISTRY: Option<Arc<Registry>> = None;
160static THE_REGISTRY_SET: Once = Once::new();
161
162/// Starts the worker threads (if that has not already happened). If
163/// initialization has not already occurred, use the default
164/// configuration.
165pub(super) fn global_registry() -> &'static Arc<Registry> {
166    set_global_registry(default_global_registry)
167        .or_else(|err| {
168            // SAFETY: we only create a shared reference to `THE_REGISTRY` after the `call_once`
169            // that initializes it, and there will be no more mutable accesses at all.
170            if true {
    if !THE_REGISTRY_SET.is_completed() {
        ::core::panicking::panic("assertion failed: THE_REGISTRY_SET.is_completed()")
    };
};debug_assert!(THE_REGISTRY_SET.is_completed());
171            let the_registry = unsafe { &*&raw const THE_REGISTRYptr::addr_of!(THE_REGISTRY) };
172            the_registry.as_ref().ok_or(err)
173        })
174        .expect("The global thread pool has not been initialized.")
175}
176
177/// Starts the worker threads (if that has not already happened) with
178/// the given builder.
179pub(super) fn init_global_registry<S>(
180    builder: ThreadPoolBuilder<S>,
181) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>
182where
183    S: ThreadSpawn,
184{
185    set_global_registry(|| Registry::new(builder))
186}
187
188/// Starts the worker threads (if that has not already happened)
189/// by creating a registry with the given callback.
190fn set_global_registry<F>(registry: F) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>
191where
192    F: FnOnce() -> Result<Arc<Registry>, ThreadPoolBuildError>,
193{
194    let mut result = Err(ThreadPoolBuildError::new(ErrorKind::GlobalPoolAlreadyInitialized));
195
196    THE_REGISTRY_SET.call_once(|| {
197        result = registry().map(|registry: Arc<Registry>| {
198            // SAFETY: this is the only mutable access to `THE_REGISTRY`, thanks to `Once`, and
199            // `global_registry()` only takes a shared reference **after** this `call_once`.
200            unsafe {
201                &raw mut THE_REGISTRYptr::addr_of_mut!(THE_REGISTRY).write(Some(registry));
202                (*&raw const THE_REGISTRYptr::addr_of!(THE_REGISTRY)).as_ref().unwrap_unchecked()
203            }
204        })
205    });
206
207    result
208}
209
210fn default_global_registry() -> Result<Arc<Registry>, ThreadPoolBuildError> {
211    let result = Registry::new(ThreadPoolBuilder::new());
212
213    // If we're running in an environment that doesn't support threads at all, we can fall back to
214    // using the current thread alone. This is crude, and probably won't work for non-blocking
215    // calls like `spawn` or `broadcast_spawn`, but a lot of stuff does work fine.
216    //
217    // Notably, this allows current WebAssembly targets to work even though their threading support
218    // is stubbed out, and we won't have to change anything if they do add real threading.
219    let unsupported = #[allow(non_exhaustive_omitted_patterns)] match &result {
    Err(e) if e.is_unsupported() => true,
    _ => false,
}matches!(&result, Err(e) if e.is_unsupported());
220    if unsupported && WorkerThread::current().is_null() {
221        let builder = ThreadPoolBuilder::new().num_threads(1).spawn_handler(|thread| {
222            // Rather than starting a new thread, we're just taking over the current thread
223            // *without* running the main loop, so we can still return from here.
224            // The WorkerThread is leaked, but we never shutdown the global pool anyway.
225            let worker_thread = Box::leak(Box::new(WorkerThread::from(thread)));
226            let registry = &*worker_thread.registry;
227            let index = worker_thread.index;
228
229            unsafe {
230                WorkerThread::set_current(worker_thread);
231
232                // let registry know we are ready to do work
233                Latch::set(&registry.thread_infos[index].primed);
234            }
235
236            Ok(())
237        });
238
239        let fallback_result = Registry::new(builder);
240        if fallback_result.is_ok() {
241            return fallback_result;
242        }
243    }
244
245    result
246}
247
248struct Terminator<'a>(&'a Arc<Registry>);
249
250impl<'a> Drop for Terminator<'a> {
251    fn drop(&mut self) {
252        self.0.terminate()
253    }
254}
255
256impl Registry {
257    pub(super) fn new<S>(
258        mut builder: ThreadPoolBuilder<S>,
259    ) -> Result<Arc<Self>, ThreadPoolBuildError>
260    where
261        S: ThreadSpawn,
262    {
263        // Soft-limit the number of threads that we can actually support.
264        let n_threads = Ord::min(builder.get_num_threads(), crate::max_num_threads());
265
266        let breadth_first = builder.get_breadth_first();
267
268        let (workers, stealers): (Vec<_>, Vec<_>) = (0..n_threads)
269            .map(|_| {
270                let worker = if breadth_first { Worker::new_fifo() } else { Worker::new_lifo() };
271
272                let stealer = worker.stealer();
273                (worker, stealer)
274            })
275            .unzip();
276
277        let (broadcasts, broadcast_stealers): (Vec<_>, Vec<_>) = (0..n_threads)
278            .map(|_| {
279                let worker = Worker::new_fifo();
280                let stealer = worker.stealer();
281                (worker, stealer)
282            })
283            .unzip();
284
285        let registry = Arc::new(Registry {
286            thread_infos: stealers.into_iter().map(ThreadInfo::new).collect(),
287            sleep: Sleep::new(n_threads),
288            injected_jobs: Injector::new(),
289            broadcasts: Mutex::new(broadcasts),
290            terminate_count: AtomicUsize::new(1),
291            panic_handler: builder.take_panic_handler(),
292            deadlock_handler: builder.take_deadlock_handler(),
293            start_handler: builder.take_start_handler(),
294            exit_handler: builder.take_exit_handler(),
295            acquire_thread_handler: builder.take_acquire_thread_handler(),
296            release_thread_handler: builder.take_release_thread_handler(),
297        });
298
299        // If we return early or panic, make sure to terminate existing threads.
300        let t1000 = Terminator(&registry);
301
302        for (index, (worker, stealer)) in workers.into_iter().zip(broadcast_stealers).enumerate() {
303            let thread = ThreadBuilder {
304                name: builder.get_thread_name(index),
305                stack_size: builder.get_stack_size(),
306                registry: Arc::clone(&registry),
307                worker,
308                stealer,
309                index,
310            };
311            if let Err(e) = builder.get_spawn_handler().spawn(thread) {
312                return Err(ThreadPoolBuildError::new(ErrorKind::IOError(e)));
313            }
314        }
315
316        // Returning normally now, without termination.
317        mem::forget(t1000);
318
319        Ok(registry)
320    }
321
322    pub fn current() -> Arc<Registry> {
323        unsafe {
324            let worker_thread = WorkerThread::current();
325            let registry = if worker_thread.is_null() {
326                global_registry()
327            } else {
328                &(*worker_thread).registry
329            };
330            Arc::clone(registry)
331        }
332    }
333
334    /// Returns the number of threads in the current registry. This
335    /// is better than `Registry::current().num_threads()` because it
336    /// avoids incrementing the `Arc`.
337    pub(super) fn current_num_threads() -> usize {
338        unsafe {
339            let worker_thread = WorkerThread::current();
340            if worker_thread.is_null() {
341                global_registry().num_threads()
342            } else {
343                (*worker_thread).registry.num_threads()
344            }
345        }
346    }
347
348    /// Returns the current `WorkerThread` if it's part of this `Registry`.
349    pub(super) fn current_thread(&self) -> Option<&WorkerThread> {
350        unsafe {
351            let worker = WorkerThread::current().as_ref()?;
352            if worker.registry().id() == self.id() { Some(worker) } else { None }
353        }
354    }
355
356    /// Returns an opaque identifier for this registry.
357    pub(super) fn id(&self) -> RegistryId {
358        // We can rely on `self` not to change since we only ever create
359        // registries that are boxed up in an `Arc` (see `new()` above).
360        RegistryId { addr: self as *const Self as usize }
361    }
362
363    pub(super) fn num_threads(&self) -> usize {
364        self.thread_infos.len()
365    }
366
367    pub(super) fn catch_unwind(&self, f: impl FnOnce()) {
368        if let Err(err) = unwind::halt_unwinding(f) {
369            // If there is no handler, or if that handler itself panics, then we abort.
370            let abort_guard = unwind::AbortIfPanic;
371            if let Some(ref handler) = self.panic_handler {
372                handler(err);
373                mem::forget(abort_guard);
374            }
375        }
376    }
377
378    /// Waits for the worker threads to get up and running. This is
379    /// meant to be used for benchmarking purposes, primarily, so that
380    /// you can get more consistent numbers by having everything
381    /// "ready to go".
382    pub(super) fn wait_until_primed(&self) {
383        for info in &self.thread_infos {
384            info.primed.wait();
385        }
386    }
387
388    /// Waits for the worker threads to stop. This is used for testing
389    /// -- so we can check that termination actually works.
390    pub(super) fn wait_until_stopped(&self) {
391        self.release_thread();
392        for info in &self.thread_infos {
393            info.stopped.wait();
394        }
395        self.acquire_thread();
396    }
397
398    pub(crate) fn acquire_thread(&self) {
399        if let Some(ref acquire_thread_handler) = self.acquire_thread_handler {
400            acquire_thread_handler();
401        }
402    }
403
404    pub(crate) fn release_thread(&self) {
405        if let Some(ref release_thread_handler) = self.release_thread_handler {
406            release_thread_handler();
407        }
408    }
409
410    ///////////////////////////////////////////////////////////////////////////
411    /// MAIN LOOP
412    ///
413    /// So long as all of the worker threads are hanging out in their
414    /// top-level loop, there is no work to be done.
415    ///
416    /// Push a job into the given `registry`. If we are running on a
417    /// worker thread for the registry, this will push onto the
418    /// deque. Else, it will inject from the outside (which is slower).
419    pub(super) fn inject_or_push(&self, job_ref: JobRef) {
420        let worker_thread = WorkerThread::current();
421        unsafe {
422            if !worker_thread.is_null() && (*worker_thread).registry().id() == self.id() {
423                (*worker_thread).push(job_ref);
424            } else {
425                self.inject(job_ref);
426            }
427        }
428    }
429
430    /// Push a job into the "external jobs" queue; it will be taken by
431    /// whatever worker has nothing to do. Use this if you know that
432    /// you are not on a worker of this registry.
433    pub(super) fn inject(&self, injected_job: JobRef) {
434        // It should not be possible for `state.terminate` to be true
435        // here. It is only set to true when the user creates (and
436        // drops) a `ThreadPool`; and, in that case, they cannot be
437        // calling `inject()` later, since they dropped their
438        // `ThreadPool`.
439        if true {
    {
        match (&(self.terminate_count.load(Ordering::Acquire)), &(0)) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("inject() sees state.terminate as true")));
                }
            }
        }
    };
};debug_assert_ne!(
440            self.terminate_count.load(Ordering::Acquire),
441            0,
442            "inject() sees state.terminate as true"
443        );
444
445        let queue_was_empty = self.injected_jobs.is_empty();
446
447        self.injected_jobs.push(injected_job);
448        self.sleep.new_injected_jobs(1, queue_was_empty);
449    }
450
451    pub(crate) fn has_injected_job(&self) -> bool {
452        !self.injected_jobs.is_empty()
453    }
454
455    fn pop_injected_job(&self) -> Option<JobRef> {
456        loop {
457            match self.injected_jobs.steal() {
458                Steal::Success(job) => return Some(job),
459                Steal::Empty => return None,
460                Steal::Retry => {}
461            }
462        }
463    }
464
465    /// Push a job into each thread's own "external jobs" queue; it will be
466    /// executed only on that thread, when it has nothing else to do locally,
467    /// before it tries to steal other work.
468    ///
469    /// **Panics** if not given exactly as many jobs as there are threads.
470    pub(super) fn inject_broadcast(&self, injected_jobs: impl ExactSizeIterator<Item = JobRef>) {
471        {
    match (&self.num_threads(), &injected_jobs.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(self.num_threads(), injected_jobs.len());
472        {
473            let broadcasts = self.broadcasts.lock().unwrap();
474
475            // It should not be possible for `state.terminate` to be true
476            // here. It is only set to true when the user creates (and
477            // drops) a `ThreadPool`; and, in that case, they cannot be
478            // calling `inject_broadcast()` later, since they dropped their
479            // `ThreadPool`.
480            if true {
    {
        match (&(self.terminate_count.load(Ordering::Acquire)), &(0)) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("inject_broadcast() sees state.terminate as true")));
                }
            }
        }
    };
};debug_assert_ne!(
481                self.terminate_count.load(Ordering::Acquire),
482                0,
483                "inject_broadcast() sees state.terminate as true"
484            );
485
486            {
    match (&broadcasts.len(), &injected_jobs.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(broadcasts.len(), injected_jobs.len());
487            for (worker, job_ref) in broadcasts.iter().zip(injected_jobs) {
488                worker.push(job_ref);
489            }
490        }
491        for i in 0..self.num_threads() {
492            self.sleep.notify_worker_latch_is_set(i);
493        }
494    }
495
496    /// If already in a worker-thread of this registry, just execute `op`.
497    /// Otherwise, inject `op` in this thread-pool. Either way, block until `op`
498    /// completes and return its return value. If `op` panics, that panic will
499    /// be propagated as well. The second argument indicates `true` if injection
500    /// was performed, `false` if executed directly.
501    pub(super) fn in_worker<OP, R>(&self, op: OP) -> R
502    where
503        OP: FnOnce(&WorkerThread, bool) -> R + Send,
504        R: Send,
505    {
506        unsafe {
507            let worker_thread = WorkerThread::current();
508            if worker_thread.is_null() {
509                self.in_worker_cold(op)
510            } else if (*worker_thread).registry().id() != self.id() {
511                self.in_worker_cross(&*worker_thread, op)
512            } else {
513                // Perfectly valid to give them a `&T`: this is the
514                // current thread, so we know the data structure won't be
515                // invalidated until we return.
516                op(&*worker_thread, false)
517            }
518        }
519    }
520
521    #[cold]
522    unsafe fn in_worker_cold<OP, R>(&self, op: OP) -> R
523    where
524        OP: FnOnce(&WorkerThread, bool) -> R + Send,
525        R: Send,
526    {
527        const LOCK_LATCH: ::std::thread::LocalKey<LockLatch> =
    {
        const __RUST_STD_INTERNAL_INIT: LockLatch = { LockLatch::new() };
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<LockLatch>() {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL:
                                        ::std::thread::local_impl::EagerStorage<LockLatch> =
                                        ::std::thread::local_impl::EagerStorage::new(__RUST_STD_INTERNAL_INIT);
                                    __RUST_STD_INTERNAL_VAL.get()
                                }
                        } else {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL: LockLatch =
                                        __RUST_STD_INTERNAL_INIT;
                                    &__RUST_STD_INTERNAL_VAL
                                }
                        }
                    })
        }
    };thread_local!(static LOCK_LATCH: LockLatch = const { LockLatch::new() });
528
529        LOCK_LATCH.with(|l| {
530            // This thread isn't a member of *any* thread pool, so just block.
531            if true {
    if !WorkerThread::current().is_null() {
        ::core::panicking::panic("assertion failed: WorkerThread::current().is_null()")
    };
};debug_assert!(WorkerThread::current().is_null());
532            let job = StackJob::new(
533                Tlv::null(),
534                |injected| {
535                    let worker_thread = WorkerThread::current();
536                    if !(injected && !worker_thread.is_null()) {
    ::core::panicking::panic("assertion failed: injected && !worker_thread.is_null()")
};assert!(injected && !worker_thread.is_null());
537                    op(unsafe { &*worker_thread }, true)
538                },
539                LatchRef::new(l),
540            );
541            self.inject(unsafe { job.as_job_ref() });
542            self.release_thread();
543            job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.
544            self.acquire_thread();
545
546            unsafe { job.into_result() }
547        })
548    }
549
550    #[cold]
551    unsafe fn in_worker_cross<OP, R>(&self, current_thread: &WorkerThread, op: OP) -> R
552    where
553        OP: FnOnce(&WorkerThread, bool) -> R + Send,
554        R: Send,
555    {
556        // This thread is a member of a different pool, so let it process
557        // other work while waiting for this `op` to complete.
558        if true {
    if !(current_thread.registry().id() != self.id()) {
        ::core::panicking::panic("assertion failed: current_thread.registry().id() != self.id()")
    };
};debug_assert!(current_thread.registry().id() != self.id());
559        let latch = SpinLatch::cross(current_thread);
560        let job = StackJob::new(
561            Tlv::null(),
562            |injected| {
563                let worker_thread = WorkerThread::current();
564                if !(injected && !worker_thread.is_null()) {
    ::core::panicking::panic("assertion failed: injected && !worker_thread.is_null()")
};assert!(injected && !worker_thread.is_null());
565                op(unsafe { &*worker_thread }, true)
566            },
567            latch,
568        );
569        self.inject(unsafe { job.as_job_ref() });
570        unsafe { current_thread.wait_until(&job.latch) };
571        unsafe { job.into_result() }
572    }
573
574    /// Increments the terminate counter. This increment should be
575    /// balanced by a call to `terminate`, which will decrement. This
576    /// is used when spawning asynchronous work, which needs to
577    /// prevent the registry from terminating so long as it is active.
578    ///
579    /// Note that blocking functions such as `join` and `scope` do not
580    /// need to concern themselves with this fn; their context is
581    /// responsible for ensuring the current thread-pool will not
582    /// terminate until they return.
583    ///
584    /// The global thread-pool always has an outstanding reference
585    /// (the initial one). Custom thread-pools have one outstanding
586    /// reference that is dropped when the `ThreadPool` is dropped:
587    /// since installing the thread-pool blocks until any joins/scopes
588    /// complete, this ensures that joins/scopes are covered.
589    ///
590    /// The exception is `::spawn()`, which can create a job outside
591    /// of any blocking scope. In that case, the job itself holds a
592    /// terminate count and is responsible for invoking `terminate()`
593    /// when finished.
594    pub(super) fn increment_terminate_count(&self) {
595        let previous = self.terminate_count.fetch_add(1, Ordering::AcqRel);
596        if true {
    if !(previous != 0) {
        {
            ::core::panicking::panic_fmt(format_args!("registry ref count incremented from zero"));
        }
    };
};debug_assert!(previous != 0, "registry ref count incremented from zero");
597        if !(previous != usize::MAX) {
    {
        ::core::panicking::panic_fmt(format_args!("overflow in registry ref count"));
    }
};assert!(previous != usize::MAX, "overflow in registry ref count");
598    }
599
600    /// Signals that the thread-pool which owns this registry has been
601    /// dropped. The worker threads will gradually terminate, once any
602    /// extant work is completed.
603    pub(super) fn terminate(&self) {
604        if self.terminate_count.fetch_sub(1, Ordering::AcqRel) == 1 {
605            for (i, thread_info) in self.thread_infos.iter().enumerate() {
606                unsafe { OnceLatch::set_and_tickle_one(&thread_info.terminate, self, i) };
607            }
608        }
609    }
610
611    /// Notify the worker that the latch they are sleeping on has been "set".
612    pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: usize) {
613        self.sleep.notify_worker_latch_is_set(target_worker_index);
614    }
615}
616
617/// Mark a Rayon worker thread as blocked. This triggers the deadlock handler
618/// if no other worker thread is active. Then wait for the user-specified condition.
619#[inline]
620pub fn mark_blocked_and_wait(wait: impl FnOnce()) {
621    let worker_thread = WorkerThread::current();
622    if !!worker_thread.is_null() {
    ::core::panicking::panic("assertion failed: !worker_thread.is_null()")
};assert!(!worker_thread.is_null());
623    unsafe {
624        let registry = &(*worker_thread).registry;
625        registry.sleep.mark_blocked(&registry.deadlock_handler);
626        registry.release_thread();
627        wait();
628        registry.acquire_thread();
629    }
630}
631
632/// Mark a previously blocked Rayon worker thread as unblocked
633#[inline]
634pub fn mark_unblocked(registry: &Registry) {
635    registry.sleep.mark_unblocked()
636}
637
638#[derive(#[automatically_derived]
impl ::core::marker::Copy for RegistryId { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RegistryId {
    #[inline]
    fn clone(&self) -> RegistryId {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RegistryId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "RegistryId",
            "addr", &&self.addr)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for RegistryId {
    #[inline]
    fn eq(&self, other: &RegistryId) -> bool { self.addr == other.addr }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RegistryId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for RegistryId {
    #[inline]
    fn partial_cmp(&self, other: &RegistryId)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for RegistryId {
    #[inline]
    fn cmp(&self, other: &RegistryId) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.addr, &other.addr)
    }
}Ord)]
639pub(super) struct RegistryId {
640    addr: usize,
641}
642
643struct ThreadInfo {
644    /// Latch set once thread has started and we are entering into the
645    /// main loop. Used to wait for worker threads to become primed,
646    /// primarily of interest for benchmarking.
647    primed: LockLatch,
648
649    /// Latch is set once worker thread has completed. Used to wait
650    /// until workers have stopped; only used for tests.
651    stopped: LockLatch,
652
653    /// The latch used to signal that terminated has been requested.
654    /// This latch is *set* by the `terminate` method on the
655    /// `Registry`, once the registry's main "terminate" counter
656    /// reaches zero.
657    terminate: OnceLatch,
658
659    /// the "stealer" half of the worker's deque
660    stealer: Stealer<JobRef>,
661}
662
663impl ThreadInfo {
664    fn new(stealer: Stealer<JobRef>) -> ThreadInfo {
665        ThreadInfo {
666            primed: LockLatch::new(),
667            stopped: LockLatch::new(),
668            terminate: OnceLatch::new(),
669            stealer,
670        }
671    }
672}
673
674///////////////////////////////////////////////////////////////////////////
675// WorkerThread identifiers
676
677pub(super) struct WorkerThread {
678    /// the "worker" half of our local deque
679    worker: Worker<JobRef>,
680
681    /// the "stealer" half of the worker's broadcast deque
682    stealer: Stealer<JobRef>,
683
684    /// local queue used for `spawn_fifo` indirection
685    fifo: JobFifo,
686
687    pub(crate) index: usize,
688
689    /// A weak random number generator.
690    rng: XorShift64Star,
691
692    pub(crate) registry: Arc<Registry>,
693}
694
695// This is a bit sketchy, but basically: the WorkerThread is
696// allocated on the stack of the worker on entry and stored into this
697// thread local variable. So it will remain valid at least until the
698// worker is fully unwound. Using an unsafe pointer avoids the need
699// for a RefCell<T> etc.
700const WORKER_THREAD_STATE: ::std::thread::LocalKey<Cell<*const WorkerThread>>
    =
    {
        const __RUST_STD_INTERNAL_INIT: Cell<*const WorkerThread> =
            { Cell::new(ptr::null()) };
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<Cell<*const WorkerThread>>() {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL:
                                        ::std::thread::local_impl::EagerStorage<Cell<*const WorkerThread>>
                                        =
                                        ::std::thread::local_impl::EagerStorage::new(__RUST_STD_INTERNAL_INIT);
                                    __RUST_STD_INTERNAL_VAL.get()
                                }
                        } else {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL: Cell<*const WorkerThread> =
                                        __RUST_STD_INTERNAL_INIT;
                                    &__RUST_STD_INTERNAL_VAL
                                }
                        }
                    })
        }
    };thread_local! {
701    static WORKER_THREAD_STATE: Cell<*const WorkerThread> = const { Cell::new(ptr::null()) };
702}
703
704impl From<ThreadBuilder> for WorkerThread {
705    fn from(thread: ThreadBuilder) -> Self {
706        Self {
707            worker: thread.worker,
708            stealer: thread.stealer,
709            fifo: JobFifo::new(),
710            index: thread.index,
711            rng: XorShift64Star::new(),
712            registry: thread.registry,
713        }
714    }
715}
716
717impl Drop for WorkerThread {
718    fn drop(&mut self) {
719        // Undo `set_current`
720        WORKER_THREAD_STATE.with(|t| {
721            if !t.get().eq(&(self as *const _)) {
    ::core::panicking::panic("assertion failed: t.get().eq(&(self as *const _))")
};assert!(t.get().eq(&(self as *const _)));
722            t.set(ptr::null());
723        });
724    }
725}
726
727impl WorkerThread {
728    /// Gets the `WorkerThread` index for the current thread; returns
729    /// NULL if this is not a worker thread. This pointer is valid
730    /// anywhere on the current thread.
731    #[inline]
732    pub(super) fn current() -> *const WorkerThread {
733        WORKER_THREAD_STATE.with(Cell::get)
734    }
735
736    /// Sets `self` as the worker thread index for the current thread.
737    /// This is done during worker thread startup.
738    unsafe fn set_current(thread: *const WorkerThread) {
739        WORKER_THREAD_STATE.with(|t| {
740            if !t.get().is_null() {
    ::core::panicking::panic("assertion failed: t.get().is_null()")
};assert!(t.get().is_null());
741            t.set(thread);
742        });
743    }
744
745    /// Returns the registry that owns this worker thread.
746    #[inline]
747    pub(super) fn registry(&self) -> &Arc<Registry> {
748        &self.registry
749    }
750
751    /// Our index amongst the worker threads (ranges from `0..self.num_threads()`).
752    #[inline]
753    pub(super) fn index(&self) -> usize {
754        self.index
755    }
756
757    #[inline]
758    pub(super) unsafe fn push(&self, job: JobRef) {
759        let queue_was_empty = self.worker.is_empty();
760        self.worker.push(job);
761        self.registry.sleep.new_internal_jobs(1, queue_was_empty);
762    }
763
764    #[inline]
765    pub(super) unsafe fn push_fifo(&self, job: JobRef) {
766        unsafe { self.push(self.fifo.push(job)) };
767    }
768
769    #[inline]
770    pub(super) fn local_deque_is_empty(&self) -> bool {
771        self.worker.is_empty()
772    }
773
774    /// Attempts to obtain a "local" job -- typically this means
775    /// popping from the top of the stack, though if we are configured
776    /// for breadth-first execution, it would mean dequeuing from the
777    /// bottom.
778    #[inline]
779    pub(super) fn take_local_job(&self) -> Option<JobRef> {
780        let popped_job = self.worker.pop();
781
782        if popped_job.is_some() {
783            return popped_job;
784        }
785
786        loop {
787            match self.stealer.steal() {
788                Steal::Success(job) => return Some(job),
789                Steal::Empty => return None,
790                Steal::Retry => {}
791            }
792        }
793    }
794
795    pub(super) fn has_injected_job(&self) -> bool {
796        !self.stealer.is_empty() || self.registry.has_injected_job()
797    }
798
799    /// Wait until the latch is set. Try to keep busy by popping and
800    /// stealing tasks as necessary.
801    #[inline]
802    pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch: &L) {
803        unsafe { self.wait_or_steal_until(latch, false) };
804    }
805
806    /// Wait until the latch is set. Executes local jobs if `is_job` is true for them and
807    /// `all_jobs_started` still returns false.
808    #[inline]
809    pub(super) unsafe fn wait_for_jobs<L: AsCoreLatch + ?Sized, const BROADCAST_JOBS: bool>(
810        &self,
811        latch: &L,
812        mut all_jobs_started: impl FnMut() -> bool,
813        mut is_job: impl FnMut(&JobRef) -> bool,
814        mut execute_job: impl FnMut(JobRef),
815    ) {
816        let mut jobs = SmallVec::<[JobRef; 8]>::new();
817        let mut broadcast_jobs = SmallVec::<[JobRef; 8]>::new();
818
819        while !all_jobs_started() {
820            if let Some(job) = self.worker.pop() {
821                if is_job(&job) {
822                    execute_job(job);
823                } else {
824                    jobs.push(job);
825                }
826            } else {
827                if BROADCAST_JOBS {
828                    let broadcast_job = loop {
829                        match self.stealer.steal() {
830                            Steal::Success(job) => break Some(job),
831                            Steal::Empty => break None,
832                            Steal::Retry => continue,
833                        }
834                    };
835                    if let Some(job) = broadcast_job {
836                        if is_job(&job) {
837                            execute_job(job);
838                        } else {
839                            broadcast_jobs.push(job);
840                        }
841                    }
842                }
843                break;
844            }
845        }
846
847        // Restore the jobs that we weren't looking for.
848        for job in jobs {
849            self.worker.push(job);
850        }
851        if BROADCAST_JOBS {
852            let broadcasts = self.registry.broadcasts.lock().unwrap();
853            for job in broadcast_jobs {
854                broadcasts[self.index].push(job);
855            }
856        }
857
858        // Wait for the jobs to finish.
859        unsafe { self.wait_until(latch) };
860        if true {
    if !latch.as_core_latch().probe() {
        ::core::panicking::panic("assertion failed: latch.as_core_latch().probe()")
    };
};debug_assert!(latch.as_core_latch().probe());
861    }
862
863    pub(super) unsafe fn wait_or_steal_until<L: AsCoreLatch + ?Sized>(
864        &self,
865        latch: &L,
866        steal: bool,
867    ) {
868        let latch = latch.as_core_latch();
869        if !latch.probe() {
870            if steal {
871                unsafe { self.wait_or_steal_until_cold(latch) };
872            } else {
873                unsafe { self.wait_until_cold(latch) };
874            }
875        }
876    }
877
878    #[cold]
879    unsafe fn wait_or_steal_until_cold(&self, latch: &CoreLatch) {
880        // the code below should swallow all panics and hence never
881        // unwind; but if something does wrong, we want to abort,
882        // because otherwise other code in rayon may assume that the
883        // latch has been signaled, and that can lead to random memory
884        // accesses, which would be *very bad*
885        let abort_guard = unwind::AbortIfPanic;
886
887        'outer: while !latch.probe() {
888            // Check for local work *before* we start marking ourself idle,
889            // especially to avoid modifying shared sleep state.
890            if let Some(job) = self.take_local_job() {
891                unsafe { self.execute(job) };
892                continue;
893            }
894
895            let mut idle_state = self.registry.sleep.start_looking(self.index);
896            while !latch.probe() {
897                if let Some(job) = self.find_work() {
898                    self.registry.sleep.work_found();
899                    unsafe { self.execute(job) };
900                    // The job might have injected local work, so go back to the outer loop.
901                    continue 'outer;
902                } else {
903                    self.registry.sleep.no_work_found(&mut idle_state, latch, &self, true)
904                }
905            }
906
907            // If we were sleepy, we are not anymore. We "found work" --
908            // whatever the surrounding thread was doing before it had to wait.
909            self.registry.sleep.work_found();
910            break;
911        }
912
913        mem::forget(abort_guard); // successful execution, do not abort
914    }
915
916    #[cold]
917    unsafe fn wait_until_cold(&self, latch: &CoreLatch) {
918        // the code below should swallow all panics and hence never
919        // unwind; but if something does wrong, we want to abort,
920        // because otherwise other code in rayon may assume that the
921        // latch has been signaled, and that can lead to random memory
922        // accesses, which would be *very bad*
923        let abort_guard = unwind::AbortIfPanic;
924
925        let mut idle_state = self.registry.sleep.start_looking(self.index);
926        while !latch.probe() {
927            self.registry.sleep.no_work_found(&mut idle_state, latch, &self, false);
928        }
929
930        // If we were sleepy, we are not anymore. We "found work" --
931        // whatever the surrounding thread was doing before it had to wait.
932        self.registry.sleep.work_found();
933
934        mem::forget(abort_guard); // successful execution, do not abort
935    }
936
937    unsafe fn wait_until_out_of_work(&self) {
938        if true {
    {
        match (&(self as *const _), &WorkerThread::current()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(self as *const _, WorkerThread::current());
939        let registry = &*self.registry;
940        let index = self.index;
941
942        registry.acquire_thread();
943        unsafe { self.wait_or_steal_until(&registry.thread_infos[index].terminate, true) };
944
945        // Should not be any work left in our queue.
946        if true {
    if !self.take_local_job().is_none() {
        ::core::panicking::panic("assertion failed: self.take_local_job().is_none()")
    };
};debug_assert!(self.take_local_job().is_none());
947
948        // Let registry know we are done
949        unsafe { Latch::set(&registry.thread_infos[index].stopped) };
950    }
951
952    fn find_work(&self) -> Option<JobRef> {
953        // Try to find some work to do. We give preference first
954        // to things in our local deque, then in other workers
955        // deques, and finally to injected jobs from the
956        // outside. The idea is to finish what we started before
957        // we take on something new.
958        self.take_local_job().or_else(|| self.steal()).or_else(|| self.registry.pop_injected_job())
959    }
960
961    pub(super) fn yield_now(&self) -> Yield {
962        match self.find_work() {
963            Some(job) => unsafe {
964                self.execute(job);
965                Yield::Executed
966            },
967            None => Yield::Idle,
968        }
969    }
970
971    pub(super) fn yield_local(&self) -> Yield {
972        match self.take_local_job() {
973            Some(job) => unsafe {
974                self.execute(job);
975                Yield::Executed
976            },
977            None => Yield::Idle,
978        }
979    }
980
981    #[inline]
982    pub(super) unsafe fn execute(&self, job: JobRef) {
983        unsafe { job.execute() };
984    }
985
986    /// Try to steal a single job and return it.
987    ///
988    /// This should only be done as a last resort, when there is no
989    /// local work to do.
990    fn steal(&self) -> Option<JobRef> {
991        // we only steal when we don't have any work to do locally
992        if true {
    if !self.local_deque_is_empty() {
        ::core::panicking::panic("assertion failed: self.local_deque_is_empty()")
    };
};debug_assert!(self.local_deque_is_empty());
993
994        // otherwise, try to steal
995        let thread_infos = &self.registry.thread_infos.as_slice();
996        let num_threads = thread_infos.len();
997        if num_threads <= 1 {
998            return None;
999        }
1000
1001        loop {
1002            let mut retry = false;
1003            let start = self.rng.next_usize(num_threads);
1004            let job = (start..num_threads)
1005                .chain(0..start)
1006                .filter(move |&i| i != self.index)
1007                .find_map(|victim_index| {
1008                    let victim = &thread_infos[victim_index];
1009                    match victim.stealer.steal() {
1010                        Steal::Success(job) => Some(job),
1011                        Steal::Empty => None,
1012                        Steal::Retry => {
1013                            retry = true;
1014                            None
1015                        }
1016                    }
1017                });
1018            if job.is_some() || !retry {
1019                return job;
1020            }
1021        }
1022    }
1023}
1024
1025unsafe fn main_loop(thread: ThreadBuilder) {
1026    let worker_thread = &WorkerThread::from(thread);
1027    unsafe { WorkerThread::set_current(worker_thread) };
1028    let registry = &*worker_thread.registry;
1029    let index = worker_thread.index;
1030
1031    // let registry know we are ready to do work
1032    unsafe { Latch::set(&registry.thread_infos[index].primed) };
1033
1034    // Worker threads should not panic. If they do, just abort, as the
1035    // internal state of the threadpool is corrupted. Note that if
1036    // **user code** panics, we should catch that and redirect.
1037    let abort_guard = unwind::AbortIfPanic;
1038
1039    // Inform a user callback that we started a thread.
1040    if let Some(ref handler) = registry.start_handler {
1041        registry.catch_unwind(|| handler(index));
1042    }
1043
1044    unsafe { worker_thread.wait_until_out_of_work() };
1045
1046    // Normal termination, do not abort.
1047    mem::forget(abort_guard);
1048
1049    // Inform a user callback that we exited a thread.
1050    if let Some(ref handler) = registry.exit_handler {
1051        registry.catch_unwind(|| handler(index));
1052        // We're already exiting the thread, there's nothing else to do.
1053    }
1054
1055    registry.release_thread();
1056}
1057
1058/// If already in a worker-thread, just execute `op`. Otherwise,
1059/// execute `op` in the default thread-pool. Either way, block until
1060/// `op` completes and return its return value. If `op` panics, that
1061/// panic will be propagated as well. The second argument indicates
1062/// `true` if injection was performed, `false` if executed directly.
1063pub(super) fn in_worker<OP, R>(op: OP) -> R
1064where
1065    OP: FnOnce(&WorkerThread, bool) -> R + Send,
1066    R: Send,
1067{
1068    unsafe {
1069        let owner_thread = WorkerThread::current();
1070        if !owner_thread.is_null() {
1071            // Perfectly valid to give them a `&T`: this is the
1072            // current thread, so we know the data structure won't be
1073            // invalidated until we return.
1074            op(&*owner_thread, false)
1075        } else {
1076            global_registry().in_worker(op)
1077        }
1078    }
1079}
1080
1081/// [xorshift*] is a fast pseudorandom number generator which will
1082/// even tolerate weak seeding, as long as it's not zero.
1083///
1084/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift*
1085struct XorShift64Star {
1086    state: Cell<u64>,
1087}
1088
1089impl XorShift64Star {
1090    fn new() -> Self {
1091        // Any non-zero seed will do -- this uses the hash of a global counter.
1092        let mut seed = 0;
1093        while seed == 0 {
1094            let mut hasher = DefaultHasher::new();
1095            static COUNTER: AtomicUsize = AtomicUsize::new(0);
1096            hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed));
1097            seed = hasher.finish();
1098        }
1099
1100        XorShift64Star { state: Cell::new(seed) }
1101    }
1102
1103    fn next(&self) -> u64 {
1104        let mut x = self.state.get();
1105        if true {
    {
        match (&x, &0) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(x, 0);
1106        x ^= x >> 12;
1107        x ^= x << 25;
1108        x ^= x >> 27;
1109        self.state.set(x);
1110        x.wrapping_mul(0x2545_f491_4f6c_dd1d)
1111    }
1112
1113    /// Return a value from `0..n`.
1114    fn next_usize(&self, n: usize) -> usize {
1115        (self.next() % n as u64) as usize
1116    }
1117}