1 use super::{Core, Handle, Shared}; 2 3 use crate::loom::sync::Arc; 4 use crate::runtime::scheduler::multi_thread_alt::Stats; 5 use crate::runtime::task::trace::trace_multi_thread; 6 use crate::runtime::{dump, WorkerMetrics}; 7 8 use std::time::Duration; 9 10 impl Handle { trace_core(&self, mut core: Box<Core>) -> Box<Core>11 pub(super) fn trace_core(&self, mut core: Box<Core>) -> Box<Core> { 12 core.is_traced = false; 13 14 if core.is_shutdown { 15 return core; 16 } 17 18 // wait for other workers, or timeout without tracing 19 let timeout = Duration::from_millis(250); // a _very_ generous timeout 20 let barrier = 21 if let Some(barrier) = self.shared.trace_status.trace_start.wait_timeout(timeout) { 22 barrier 23 } else { 24 // don't attempt to trace 25 return core; 26 }; 27 28 if !barrier.is_leader() { 29 // wait for leader to finish tracing 30 self.shared.trace_status.trace_end.wait(); 31 return core; 32 } 33 34 // trace 35 36 let owned = &self.shared.owned; 37 let mut local = self.shared.steal_all(); 38 let synced = &self.shared.synced; 39 let injection = &self.shared.inject; 40 41 // safety: `trace_multi_thread` is invoked with the same `synced` that `injection` 42 // was created with. 43 let traces = unsafe { trace_multi_thread(owned, &mut local, synced, injection) } 44 .into_iter() 45 .map(dump::Task::new) 46 .collect(); 47 48 let result = dump::Dump::new(traces); 49 50 // stash the result 51 self.shared.trace_status.stash_result(result); 52 53 // allow other workers to proceed 54 self.shared.trace_status.trace_end.wait(); 55 56 core 57 } 58 } 59 60 impl Shared { 61 /// Steal all tasks from remotes into a single local queue. steal_all(&self) -> super::queue::Local<Arc<Handle>>62 pub(super) fn steal_all(&self) -> super::queue::Local<Arc<Handle>> { 63 let (_steal, mut local) = super::queue::local(); 64 65 let worker_metrics = WorkerMetrics::new(); 66 let mut stats = Stats::new(&worker_metrics); 67 68 for remote in self.remotes.iter() { 69 let steal = &remote.steal; 70 while !steal.is_empty() { 71 if let Some(task) = steal.steal_into(&mut local, &mut stats) { 72 local.push_back([task].into_iter()); 73 } 74 } 75 } 76 77 local 78 } 79 } 80