1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub use fuchsia_trace::Scope as TraceScope;

// This needs to be available to the macros in this module without clients having to depend on
// fuchsia_trace themselves.
#[doc(hidden)]
pub use fuchsia_trace as __fuchsia_trace;

use std::ffi::CStr;

// The trace category used for starnix-related traces.
pub const CATEGORY_STARNIX: &'static CStr = c"starnix";

// The trace category used for memory manager related traces.
pub const CATEGORY_STARNIX_MM: &'static CStr = c"starnix:mm";

// The name used to track the duration in Starnix while executing a task.
pub const NAME_RUN_TASK: &'static CStr = c"RunTask";

// The trace category used for atrace events generated within starnix.
pub const CATEGORY_ATRACE: &'static CStr = c"starnix:atrace";

// The name used to identify blob records from the container's Perfetto daemon.
pub const NAME_PERFETTO_BLOB: &'static CStr = c"starnix_perfetto";

// The name used to track the duration of a syscall.
pub const NAME_EXECUTE_SYSCALL: &'static CStr = c"ExecuteSyscall";

// The name used to track the duration of creating a container.
pub const NAME_CREATE_CONTAINER: &'static CStr = c"CreateContainer";

// The name used to track the start time of the starnix kernel.
pub const NAME_START_KERNEL: &'static CStr = c"StartKernel";

// The name used to track when a thread was kicked.
pub const NAME_RESTRICTED_KICK: &'static CStr = c"RestrictedKick";

// The name used to track the duration for inline exception handling.
pub const NAME_HANDLE_EXCEPTION: &'static CStr = c"HandleException";

// The names used to track durations for restricted state I/O.
pub const NAME_READ_RESTRICTED_STATE: &'static CStr = c"ReadRestrictedState";
pub const NAME_WRITE_RESTRICTED_STATE: &'static CStr = c"WriteRestrictedState";

// The name used to track the duration of checking whether the task loop should exit.
pub const NAME_CHECK_TASK_EXIT: &'static CStr = c"CheckTaskExit";

pub const ARG_NAME: &'static str = "name";

#[inline]
pub const fn regular_tracing_enabled() -> bool {
    cfg!(feature = "tracing")
}

#[inline]
pub const fn firehose_tracing_enabled() -> bool {
    cfg!(feature = "tracing_firehose")
}

#[macro_export]
macro_rules! trace_instant {
    ($category:expr, $name:expr, $scope:expr $(, $key:expr => $val:expr)*) => {
        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::instant!($category, $name, $scope $(, $key => $val)*);
        }
    };
}

#[macro_export]
macro_rules! firehose_trace_instant {
    ($category:expr, $name:expr, $scope:expr $(, $key:expr => $val:expr)*) => {
        if $crate::firehose_tracing_enabled() {
            $crate::trace_instant!($category, $name, $scope $(, $key => $val)*);
        }
    }
}

// The `trace_duration` macro defines a `_scope` instead of executing a statement because the
// lifetime of the `_scope` variable corresponds to the duration.
#[macro_export]
macro_rules! trace_duration {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        let _args = if $crate::regular_tracing_enabled() {
            Some([$($crate::__fuchsia_trace::ArgValue::of($key, $val)),*])
        } else {
            None
        };
        let _scope = if $crate::regular_tracing_enabled() {
            Some($crate::__fuchsia_trace::duration(
                $category,
                $name,
                _args.as_ref().unwrap()
            ))
        } else {
            None
        };
    }
}

#[macro_export]
macro_rules! firehose_trace_duration {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        if $crate::firehose_tracing_enabled() {
            $crate::trace_duration!($category, $name $(, $key => $val)*);
        }
    }
}

#[macro_export]
macro_rules! trace_duration_begin {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::duration_begin!($category, $name $(, $key => $val)*);
        }
    };
}

#[macro_export]
macro_rules! firehose_trace_duration_begin {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        if $crate::firehose_tracing_enabled() {
            $crate::trace_duration_begin!($category, $name $(, $key => $val)*);
        }
    }
}

#[macro_export]
macro_rules! trace_duration_end {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::duration_end!($category, $name $(, $key => $val)*);
        }
    };
}

#[macro_export]
macro_rules! firehose_trace_duration_end {
    ($category:expr, $name:expr $(, $key:expr => $val:expr)*) => {
        if $crate::firehose_tracing_enabled() {
            $crate::trace_duration_end!($category, $name $(, $key => $val)*);
        }
    }
}

#[macro_export]
macro_rules! trace_flow_begin {
    ($category:expr, $name:expr, $flow_id:expr $(, $key:expr => $val:expr)*) => {
        let _flow_id: $crate::__fuchsia_trace::Id = $flow_id;
        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::flow_begin!($category, $name, _flow_id $(, $key => $val)*);
        }
    };
}

#[macro_export]
macro_rules! trace_flow_step {
    ($category:expr, $name:expr, $flow_id:expr $(, $key:expr => $val:expr)*) => {
        let _flow_id: $crate::__fuchsia_trace::Id = $flow_id;

        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::flow_step!($category, $name, _flow_id $(, $key => $val)*);
        }
    };
}

#[macro_export]
macro_rules! trace_flow_end {
    ($category:expr, $name:expr, $flow_id:expr $(, $key:expr => $val:expr)*) => {
        let _flow_id: $crate::__fuchsia_trace::Id = $flow_id;
        if $crate::regular_tracing_enabled() {
            $crate::__fuchsia_trace::flow_end!($category, $name, _flow_id $(, $key => $val)*);
        }
    };
}