1 // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved.
2 //
3 // StratoVirt is licensed under Mulan PSL v2.
4 // You can use this software according to the terms and conditions of the Mulan
5 // PSL v2.
6 // You may obtain a copy of Mulan PSL v2 at:
7 //         http://license.coscl.org.cn/MulanPSL2
8 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
9 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
10 // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 // See the Mulan PSL v2 for more details.
12 
13 use lazy_static::lazy_static;
14 use std::sync::atomic::{AtomicI32, Ordering};
15 
16 #[cfg(all(target_env = "ohos", feature = "trace_to_hitrace"))]
17 use crate::hitrace::{finish_trace, finish_trace_async, start_trace, start_trace_async};
18 
19 #[cfg(feature = "trace_to_ftrace")]
20 use crate::ftrace::write_trace_marker;
21 
22 lazy_static! {
23     static ref TRACE_SCOPE_COUNTER: AtomicI32 = AtomicI32::new(i32::MIN);
24 }
25 
26 #[derive(Clone)]
27 pub enum Scope {
28     Common(TraceScope),
29     Asyn(TraceScopeAsyn),
30     None,
31 }
32 
33 #[derive(Clone)]
34 pub struct TraceScope {}
35 
36 impl TraceScope {
new(value: String) -> Self37     pub fn new(value: String) -> Self {
38         #[cfg(feature = "trace_to_logger")]
39         {
40             log::trace!("[SCOPE_START]{}", value);
41         }
42         #[cfg(feature = "trace_to_ftrace")]
43         {
44             write_trace_marker(&format!("[SCOPE_START]{}", value));
45         }
46         #[cfg(all(target_env = "ohos", feature = "trace_to_hitrace"))]
47         {
48             start_trace(&value);
49         }
50         TraceScope {}
51     }
52 }
53 
54 impl Drop for TraceScope {
drop(&mut self)55     fn drop(&mut self) {
56         #[cfg(feature = "trace_to_logger")]
57         {
58             log::trace!("[SCOPE_END]");
59         }
60         #[cfg(feature = "trace_to_ftrace")]
61         {
62             write_trace_marker("[SCOPE_END]");
63         }
64         #[cfg(all(target_env = "ohos", feature = "trace_to_hitrace"))]
65         {
66             finish_trace()
67         }
68     }
69 }
70 
71 #[derive(Clone)]
72 pub struct TraceScopeAsyn {
73     value: String,
74     id: i32,
75 }
76 
77 impl TraceScopeAsyn {
78     #[allow(unused_variables)]
new(value: String) -> Self79     pub fn new(value: String) -> Self {
80         // SAFETY: AtomicI32 can be safely shared between threads.
81         let id = TRACE_SCOPE_COUNTER
82             .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
83                 Some(x.wrapping_add(1))
84             })
85             .unwrap();
86         #[cfg(feature = "trace_to_logger")]
87         {
88             log::trace!("[SCOPE_START(id={})]{}", id, value);
89         }
90         #[cfg(feature = "trace_to_ftrace")]
91         {
92             write_trace_marker(&format!("[SCOPE_START(id={})]{}", id, value));
93         }
94         #[cfg(all(target_env = "ohos", feature = "trace_to_hitrace"))]
95         {
96             start_trace_async(&value, id);
97         }
98         TraceScopeAsyn { value, id }
99     }
100 }
101 
102 impl Drop for TraceScopeAsyn {
drop(&mut self)103     fn drop(&mut self) {
104         #[cfg(feature = "trace_to_logger")]
105         {
106             log::trace!("[SCOPE_END(id={})]{}", self.id, self.value);
107         }
108         #[cfg(feature = "trace_to_ftrace")]
109         {
110             write_trace_marker(&format!("[SCOPE_END(id={})]{}", self.id, self.value));
111         }
112         #[cfg(all(target_env = "ohos", feature = "trace_to_hitrace"))]
113         {
114             finish_trace_async(&self.value, self.id);
115         }
116     }
117 }
118