tokio/runtime/scheduler/multi_thread/
trace.rs1use crate::loom::sync::atomic::{AtomicBool, Ordering};
2use crate::loom::sync::{Barrier, Mutex};
3use crate::runtime::dump::Dump;
4use crate::runtime::scheduler::multi_thread::Handle;
5use crate::sync::notify::Notify;
6
7pub(super) struct TraceStatus {
9 pub(super) trace_requested: AtomicBool,
10 pub(super) trace_start: Barrier,
11 pub(super) trace_end: Barrier,
12 pub(super) result_ready: Notify,
13 pub(super) trace_result: Mutex<Option<Dump>>,
14}
15
16impl TraceStatus {
17 pub(super) fn new(remotes_len: usize) -> Self {
18 Self {
19 trace_requested: AtomicBool::new(false),
20 trace_start: Barrier::new(remotes_len),
21 trace_end: Barrier::new(remotes_len),
22 result_ready: Notify::new(),
23 trace_result: Mutex::new(None),
24 }
25 }
26
27 pub(super) fn trace_requested(&self) -> bool {
28 self.trace_requested.load(Ordering::Relaxed)
29 }
30
31 pub(super) async fn start_trace_request(&self, handle: &Handle) {
32 while self
33 .trace_requested
34 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
35 .is_err()
36 {
37 handle.notify_all();
38 crate::task::yield_now().await;
39 }
40 }
41
42 pub(super) fn stash_result(&self, dump: Dump) {
43 let _ = self.trace_result.lock().insert(dump);
44 self.result_ready.notify_one();
45 }
46
47 pub(super) fn take_result(&self) -> Option<Dump> {
48 self.trace_result.lock().take()
49 }
50
51 pub(super) async fn end_trace_request(&self, handle: &Handle) {
52 while self
53 .trace_requested
54 .compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
55 .is_err()
56 {
57 handle.notify_all();
58 crate::task::yield_now().await;
59 }
60 }
61}