use super::{Core, Handle, Shared}; use crate::loom::sync::Arc; use crate::runtime::scheduler::multi_thread_alt::Stats; use crate::runtime::task::trace::trace_multi_thread; use crate::runtime::{dump, WorkerMetrics}; use std::time::Duration; impl Handle { pub(super) fn trace_core(&self, mut core: Box) -> Box { core.is_traced = false; if core.is_shutdown { return core; } // wait for other workers, or timeout without tracing let timeout = Duration::from_millis(250); // a _very_ generous timeout let barrier = if let Some(barrier) = self.shared.trace_status.trace_start.wait_timeout(timeout) { barrier } else { // don't attempt to trace return core; }; if !barrier.is_leader() { // wait for leader to finish tracing self.shared.trace_status.trace_end.wait(); return core; } // trace let owned = &self.shared.owned; let mut local = self.shared.steal_all(); let synced = &self.shared.synced; let injection = &self.shared.inject; // safety: `trace_multi_thread` is invoked with the same `synced` that `injection` // was created with. let traces = unsafe { trace_multi_thread(owned, &mut local, synced, injection) } .into_iter() .map(dump::Task::new) .collect(); let result = dump::Dump::new(traces); // stash the result self.shared.trace_status.stash_result(result); // allow other workers to proceed self.shared.trace_status.trace_end.wait(); core } } impl Shared { /// Steal all tasks from remotes into a single local queue. pub(super) fn steal_all(&self) -> super::queue::Local> { let (_steal, mut local) = super::queue::local(); let worker_metrics = WorkerMetrics::new(); let mut stats = Stats::new(&worker_metrics); for remote in self.remotes.iter() { let steal = &remote.steal; while !steal.is_empty() { if let Some(task) = steal.steal_into(&mut local, &mut stats) { local.push_back([task].into_iter()); } } } local } }