1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef __FFRT_HMOS_TRACE_H__
17 #define __FFRT_HMOS_TRACE_H__
18
19 #include <atomic>
20 #include <chrono>
21 #include "internal_inc/osal.h"
22 #include "dfx/log/ffrt_log_api.h"
23
24 #ifdef FFRT_OH_TRACE_ENABLE
25 #include <dlfcn.h>
26 #endif
27
28 namespace ffrt {
29 enum TraceLevel {
30 TRACE_LEVEL0 = 0,
31 TRACE_LEVEL1,
32 TRACE_LEVEL2,
33 TRACE_LEVEL3, // lowest level, trace all
34 TRACE_LEVEL_MAX,
35 };
36
37 class TraceLevelManager {
38 public:
39 TraceLevelManager();
40 ~TraceLevelManager() = default;
41
GetTraceLevel()42 uint64_t GetTraceLevel() const
43 {
44 return traceLevel_;
45 }
46
Instance()47 static inline TraceLevelManager* Instance()
48 {
49 static TraceLevelManager ins;
50 return &ins;
51 }
52
53 private:
54 uint8_t traceLevel_;
55 };
56
57 class ScopedTrace {
58 public:
59 ScopedTrace(uint64_t level, const char* name);
60 ~ScopedTrace();
61
62 private:
63 std::atomic<bool> isTraceEnable_;
64 };
65 } // namespace ffrt
66
67 #ifdef FFRT_OH_TRACE_ENABLE
68 constexpr uint64_t HITRACE_TAG_FFRT = (1ULL << 13); // ffrt task.
69 bool IsTagEnabled(uint64_t tag);
70 void StartTrace(uint64_t label, const std::string& value, float limit = -1);
71 void FinishTrace(uint64_t label);
72 void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit = -1);
73 void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId);
74 #ifdef APP_USE_ARM
75 static const std::string TRACE_LIB_PATH = "/system/lib/chipset-pub-sdk/libhitrace_meter.so";
76 #else
77 static const std::string TRACE_LIB_PATH = "/system/lib64/chipset-pub-sdk/libhitrace_meter.so";
78 #endif
79 class TraceAdapter {
80 public:
TraceAdapter()81 TraceAdapter()
82 {
83 Load();
84 }
85
~TraceAdapter()86 ~TraceAdapter()
87 {
88 UnLoad();
89 }
90
Instance()91 static TraceAdapter* Instance()
92 {
93 static TraceAdapter instance;
94 return &instance;
95 }
96
97 #define REG_FUNC(func) using func##Type = decltype(func)*; func##Type func = nullptr
98 REG_FUNC(IsTagEnabled);
99 REG_FUNC(StartTrace);
100 REG_FUNC(FinishTrace);
101 REG_FUNC(StartAsyncTrace);
102 REG_FUNC(FinishAsyncTrace);
103 #undef REG_FUNC
104
105 private:
Load()106 bool Load()
107 {
108 if (handle != nullptr) {
109 FFRT_LOGD("handle exits");
110 return true;
111 }
112
113 handle = dlopen(TRACE_LIB_PATH.c_str(), RTLD_NOW | RTLD_LOCAL);
114 if (handle == nullptr) {
115 FFRT_LOGE("load so[%s] fail", TRACE_LIB_PATH.c_str());
116 return false;
117 }
118
119 #define LOAD_FUNC(x) x = reinterpret_cast<x##Type>(dlsym(handle, #x)); \
120 if (x == nullptr) \
121 { \
122 FFRT_LOGE("load func %s from %s failed", #x, TRACE_LIB_PATH.c_str()); \
123 return false; \
124 }
125 LOAD_FUNC(IsTagEnabled);
126 LOAD_FUNC(StartTrace);
127 LOAD_FUNC(FinishTrace);
128 LOAD_FUNC(StartAsyncTrace);
129 LOAD_FUNC(FinishAsyncTrace);
130 #undef LOAD_FUNC
131 return true;
132 }
133
UnLoad()134 bool UnLoad()
135 {
136 if (handle != nullptr) {
137 if (dlclose(handle) != 0) {
138 return false;
139 }
140 handle = nullptr;
141 return true;
142 }
143 return true;
144 }
145
146 void* handle = nullptr;
147 };
148
149 #define GET_TRACE_FUNC(x) (TraceAdapter::Instance()->x)
150
_IsTagEnabled(uint64_t label)151 static bool _IsTagEnabled(uint64_t label)
152 {
153 auto func = GET_TRACE_FUNC(IsTagEnabled);
154 if (func != nullptr) {
155 return func(label);
156 }
157 return false;
158 }
159
160 #define _StartTrace(label, tag, limit) \
161 do { \
162 auto func = GET_TRACE_FUNC(StartTrace); \
163 if (func != nullptr) { \
164 func(label, tag, limit); \
165 } \
166 } while (0)
167 #define _FinishTrace(label) \
168 do { \
169 auto func = GET_TRACE_FUNC(FinishTrace); \
170 if (func != nullptr) { \
171 func(label); \
172 } \
173 } while (0)
174 #define _StartAsyncTrace(label, tag, tid, limit) \
175 do { \
176 auto func = GET_TRACE_FUNC(StartAsyncTrace); \
177 if (func != nullptr) { \
178 func(label, tag, tid, limit); \
179 } \
180 } while (0)
181 #define _FinishAsyncTrace(label, tag, tid) \
182 do { \
183 auto func = GET_TRACE_FUNC(FinishAsyncTrace); \
184 if (func != nullptr) { \
185 func(label, tag, tid); \
186 } \
187 } while (0)
188
189 #define FFRT_TRACE_BEGIN(tag) \
190 do { \
191 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
192 _StartTrace(HITRACE_TAG_FFRT, tag, -1); \
193 } while (false)
194 #define FFRT_TRACE_END() \
195 do { \
196 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
197 _FinishTrace(HITRACE_TAG_FFRT); \
198 } while (false)
199 #define FFRT_TRACE_ASYNC_BEGIN(tag, tid) \
200 do { \
201 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
202 _StartAsyncTrace(HITRACE_TAG_FFRT, tag, tid, -1); \
203 } while (false)
204 #define FFRT_TRACE_ASYNC_END(tag, tid) \
205 do { \
206 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
207 _FinishAsyncTrace(HITRACE_TAG_FFRT, tag, tid); \
208 } while (false)
209 #define FFRT_TRACE_SCOPE(level, tag) ffrt::ScopedTrace ___tracer##tag(level, #tag)
210 #else
211 #define FFRT_TRACE_BEGIN(tag)
212 #define FFRT_TRACE_END()
213 #define FFRT_TRACE_ASYNC_BEGIN(tag, tid)
214 #define FFRT_TRACE_ASYNC_END(tag, tid)
215 #define FFRT_TRACE_SCOPE(level, tag)
216 #endif
217
218 // DFX Trace for FFRT Normal Task
219 #define FFRT_WORKER_IDLE_BEGIN_MARKER()
220 #define FFRT_WORKER_IDLE_END_MARKER()
221 #define FFRT_SUBMIT_MARKER(tag, gid) \
222 do { \
223 FFRT_TRACE_BEGIN(("P[" + (tag) + "]|" + std::to_string(gid)).c_str()); \
224 FFRT_TRACE_END(); \
225 } while (false)
226 #define FFRT_READY_MARKER(gid) \
227 { \
228 FFRT_TRACE_ASYNC_END("R", gid); \
229 }
230 #define FFRT_BLOCK_MARKER(gid) \
231 { \
232 FFRT_TRACE_ASYNC_END("B", gid); \
233 }
234 #define FFRT_TASKDONE_MARKER(gid) \
235 { \
236 FFRT_TRACE_ASYNC_END("F", gid); \
237 }
238 #define FFRT_FAKE_TRACE_MARKER(gid) \
239 { \
240 FFRT_TRACE_ASYNC_END("Co", gid); \
241 }
242 #define FFRT_TASK_BEGIN(tag, gid) \
243 { \
244 FFRT_TRACE_BEGIN(("FFRT::[" + (tag) + "]|" + std::to_string(gid)).c_str()); \
245 }
246 #define FFRT_TASK_END() \
247 { \
248 FFRT_TRACE_END(); \
249 }
250 #define FFRT_BLOCK_TRACER(gid, tag) \
251 do { \
252 FFRT_TRACE_BEGIN(("FFBK[" #tag "]|" + std::to_string(gid)).c_str()); \
253 FFRT_TRACE_END(); \
254 } while (false)
255 #define FFRT_WAKE_TRACER(gid) \
256 do { \
257 FFRT_TRACE_BEGIN(("FFWK|" + std::to_string(gid)).c_str()); \
258 FFRT_TRACE_END(); \
259 } while (false)
260
261 // DFX Trace for FFRT Executor Task
262 #define FFRT_EXECUTOR_TASK_SUBMIT_MARKER(ptr) \
263 do { \
264 FFRT_TRACE_BEGIN(("P[executor_task]|" + std::to_string(((uintptr_t)(ptr) & 0x11111111))).c_str()); \
265 FFRT_TRACE_END(); \
266 } while (false)
267 #define FFRT_EXECUTOR_TASK_READY_MARKER(ptr) \
268 { \
269 FFRT_TRACE_ASYNC_END("R", ((uintptr_t)(ptr) & 0x11111111)); \
270 }
271 #define FFRT_EXECUTOR_TASK_BLOCK_MARKER(ptr) \
272 { \
273 FFRT_TRACE_ASYNC_END("B", ((uintptr_t)(ptr) & 0x11111111)); \
274 }
275 #define FFRT_EXECUTOR_TASK_FINISH_MARKER(ptr) \
276 { \
277 FFRT_TRACE_ASYNC_END("F", ((uintptr_t)(ptr) & 0x11111111)); \
278 }
279 #define FFRT_EXECUTOR_TASK_BEGIN(ptr) \
280 { \
281 FFRT_TRACE_BEGIN(("FFRT::[executor_task]|" + std::to_string(((uintptr_t)(ptr) & 0x11111111))).c_str()); \
282 }
283 #define FFRT_EXECUTOR_TASK_END() \
284 { \
285 FFRT_TRACE_END(); \
286 }
287
288 // DFX Trace for FFRT Serial Queue Task
289 #define FFRT_SERIAL_QUEUE_TASK_SUBMIT_MARKER(qid, gid) \
290 do { \
291 FFRT_TRACE_BEGIN(("P[sq_" + std::to_string(qid) + "]|" + std::to_string(gid)).c_str()); \
292 FFRT_TRACE_END(); \
293 } while (false)
294 #define FFRT_SERIAL_QUEUE_TASK_EXECUTE_MARKER(gid) \
295 { \
296 FFRT_TRACE_ASYNC_END("E", gid); \
297 }
298 #define FFRT_SERIAL_QUEUE_TASK_FINISH_MARKER(gid) \
299 { \
300 FFRT_TRACE_ASYNC_END("F", gid); \
301 }
302 #endif