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_TRACE_H__
17 #define __FFRT_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 tasks.
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 void CountTrace(uint64_t label, const std::string& name, int64_t count);
75 #ifdef APP_USE_ARM
76 static const std::string TRACE_LIB_PATH = "/system/lib/chipset-pub-sdk/libhitrace_meter.so";
77 #else
78 static const std::string TRACE_LIB_PATH = "/system/lib64/chipset-pub-sdk/libhitrace_meter.so";
79 #endif
80 class TraceAdapter {
81 public:
TraceAdapter()82 TraceAdapter()
83 {
84 Load();
85 }
86
~TraceAdapter()87 ~TraceAdapter()
88 {
89 UnLoad();
90 }
91
Instance()92 static TraceAdapter* Instance()
93 {
94 static TraceAdapter instance;
95 return &instance;
96 }
97
98 #define REG_FUNC(func) using func##Type = decltype(func)*; func##Type func = nullptr
99 REG_FUNC(IsTagEnabled);
100 REG_FUNC(StartTrace);
101 REG_FUNC(FinishTrace);
102 REG_FUNC(StartAsyncTrace);
103 REG_FUNC(FinishAsyncTrace);
104 REG_FUNC(CountTrace);
105 #undef REG_FUNC
106
107 private:
Load()108 bool Load()
109 {
110 if (handle != nullptr) {
111 FFRT_LOGD("handle exits");
112 return true;
113 }
114
115 handle = dlopen(TRACE_LIB_PATH.c_str(), RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
116 if (handle == nullptr) {
117 FFRT_LOGE("load so[%s] fail", TRACE_LIB_PATH.c_str());
118 return false;
119 }
120
121 #define LOAD_FUNC(x) x = reinterpret_cast<x##Type>(dlsym(handle, #x)); \
122 if (x == nullptr) \
123 { \
124 FFRT_LOGE("load func %s from %s failed", #x, TRACE_LIB_PATH.c_str()); \
125 return false; \
126 }
127 LOAD_FUNC(IsTagEnabled);
128 LOAD_FUNC(StartTrace);
129 LOAD_FUNC(FinishTrace);
130 LOAD_FUNC(StartAsyncTrace);
131 LOAD_FUNC(FinishAsyncTrace);
132 LOAD_FUNC(CountTrace);
133 #undef LOAD_FUNC
134 return true;
135 }
136
UnLoad()137 bool UnLoad()
138 {
139 if (handle != nullptr) {
140 if (dlclose(handle) != 0) {
141 return false;
142 }
143 handle = nullptr;
144 return true;
145 }
146 return true;
147 }
148
149 void* handle = nullptr;
150 };
151
152 #define GET_TRACE_FUNC(x) (TraceAdapter::Instance()->x)
153
_IsTagEnabled(uint64_t label)154 static bool _IsTagEnabled(uint64_t label)
155 {
156 auto func = GET_TRACE_FUNC(IsTagEnabled);
157 if (func != nullptr) {
158 return func(label);
159 }
160 return false;
161 }
162 #define _StartTrace(label, tag, limit) \
163 do { \
164 auto func = GET_TRACE_FUNC(StartTrace); \
165 if (func != nullptr) { \
166 func(label, tag, limit); \
167 } \
168 } while (0)
169 #define _FinishTrace(label) \
170 do { \
171 auto func = GET_TRACE_FUNC(FinishTrace); \
172 if (func != nullptr) { \
173 func(label); \
174 } \
175 } while (0)
176 #define _StartAsyncTrace(label, tag, tid, limit) \
177 do { \
178 auto func = GET_TRACE_FUNC(StartAsyncTrace); \
179 if (func != nullptr) { \
180 func(label, tag, tid, limit); \
181 } \
182 } while (0)
183 #define _FinishAsyncTrace(label, tag, tid) \
184 do { \
185 auto func = GET_TRACE_FUNC(FinishAsyncTrace); \
186 if (func != nullptr) { \
187 func(label, tag, tid); \
188 } \
189 } while (0)
190 #define _TraceCount(label, tag, value) \
191 do { \
192 auto func = GET_TRACE_FUNC(CountTrace); \
193 if (func != nullptr) { \
194 func(label, tag, value); \
195 } \
196 } while (0)
197
198 #define FFRT_TRACE_BEGIN(tag) \
199 do { \
200 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
201 _StartTrace(HITRACE_TAG_FFRT, tag, -1); \
202 } while (false)
203 #define FFRT_TRACE_END() \
204 do { \
205 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
206 _FinishTrace(HITRACE_TAG_FFRT); \
207 } while (false)
208 #define FFRT_TRACE_ASYNC_BEGIN(tag, tid) \
209 do { \
210 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
211 _StartAsyncTrace(HITRACE_TAG_FFRT, tag, tid, -1); \
212 } while (false)
213 #define FFRT_TRACE_ASYNC_END(tag, tid) \
214 do { \
215 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
216 _FinishAsyncTrace(HITRACE_TAG_FFRT, tag, tid); \
217 } while (false)
218 #define FFRT_TRACE_COUNT(tag, value) \
219 do { \
220 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
221 _TraceCount(HITRACE_TAG_FFRT, tag, value); \
222 } while (false)
223 #define FFRT_TASK_BEGIN(tag, gid) \
224 do { \
225 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
226 _StartTrace(HITRACE_TAG_FFRT, ("FFRT" + (tag) + "|" + std::to_string(gid)).c_str(), -1); \
227 } while (false)
228 #define FFRT_BLOCK_TRACER(gid, tag) \
229 do { \
230 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
231 _StartTrace(HITRACE_TAG_FFRT, ("FFBK" #tag "|" + std::to_string(gid)).c_str(), -1); \
232 FFRT_TRACE_END(); \
233 } while (false)
234 #define FFRT_WAKE_TRACER(gid) \
235 do { \
236 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
237 _StartTrace(HITRACE_TAG_FFRT, ("FFWK|" + std::to_string(gid)).c_str(), -1); \
238 FFRT_TRACE_END(); \
239 } while (false)
240 #define FFRT_EXECUTOR_TASK_BEGIN(ptr) \
241 do { \
242 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
243 _StartTrace(HITRACE_TAG_FFRT, ("FFRTex_task|" + \
244 std::to_string(((reinterpret_cast<uintptr_t>(ptr)) & 0x11111111))).c_str(), -1); \
245 } while (false)
246 #define FFRT_SERIAL_QUEUE_TASK_SUBMIT_MARKER(qid, gid) \
247 do { \
248 if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
249 _StartTrace(HITRACE_TAG_FFRT, ("P[sq_" + \
250 std::to_string(qid) + "]|" + std::to_string(gid)).c_str(), -1); \
251 FFRT_TRACE_END(); \
252 } while (false)
253 #define FFRT_TRACE_SCOPE(level, tag) ffrt::ScopedTrace ___tracer##tag(level, #tag)
254 #else
255 #define FFRT_TRACE_BEGIN(tag)
256 #define FFRT_TRACE_END()
257 #define FFRT_TRACE_ASYNC_BEGIN(tag, tid)
258 #define FFRT_TRACE_ASYNC_END(tag, tid)
259 #define FFRT_TRACE_COUNT(tag, value)
260 #define FFRT_TRACE_SCOPE(level, tag)
261 #define FFRT_TASK_BEGIN(tag, gid)
262 #define FFRT_BLOCK_TRACER(gid, tag)
263 #define FFRT_WAKE_TRACER(gid)
264 #define FFRT_EXECUTOR_TASK_BEGIN(ptr)
265 #define FFRT_SERIAL_QUEUE_TASK_SUBMIT_MARKER(qid, gid)
266 #endif
267
268 // DFX Trace for FFRT Normal Task
269 #define FFRT_WORKER_IDLE_BEGIN_MARKER()
270 #define FFRT_WORKER_IDLE_END_MARKER()
271 #define FFRT_SUBMIT_MARKER(tag, gid) \
272 { \
273 FFRT_TRACE_ASYNC_END("P", gid); \
274 }
275 #define FFRT_READY_MARKER(gid) \
276 { \
277 FFRT_TRACE_ASYNC_END("R", gid); \
278 }
279 #define FFRT_BLOCK_MARKER(gid) \
280 { \
281 FFRT_TRACE_ASYNC_END("B", gid); \
282 }
283 #define FFRT_TASKDONE_MARKER(gid) \
284 { \
285 FFRT_TRACE_ASYNC_END("F", gid); \
286 }
287 #define FFRT_FAKE_TRACE_MARKER(gid) \
288 { \
289 FFRT_TRACE_ASYNC_END("Co", gid); \
290 }
291 #define FFRT_TASK_END() \
292 { \
293 FFRT_TRACE_END(); \
294 }
295
296 // DFX Trace for FFRT Executor Task
297 #define FFRT_EXECUTOR_TASK_SUBMIT_MARKER(ptr) \
298 { \
299 FFRT_TRACE_ASYNC_END("P", ((reinterpret_cast<uintptr_t>(ptr)) & 0x11111111)); \
300 }
301 #define FFRT_EXECUTOR_TASK_READY_MARKER(ptr) \
302 { \
303 FFRT_TRACE_ASYNC_END("R", ((reinterpret_cast<uintptr_t>(ptr)) & 0x11111111)); \
304 }
305 #define FFRT_EXECUTOR_TASK_BLOCK_MARKER(ptr) \
306 { \
307 FFRT_TRACE_ASYNC_END("B", ((reinterpret_cast<uintptr_t>(ptr)) & 0x11111111)); \
308 }
309 #define FFRT_EXECUTOR_TASK_FINISH_MARKER(ptr) \
310 { \
311 FFRT_TRACE_ASYNC_END("F", ((reinterpret_cast<uintptr_t>(ptr)) & 0x11111111)); \
312 }
313
314 #define FFRT_EXECUTOR_TASK_END() \
315 { \
316 FFRT_TRACE_END(); \
317 }
318
319 // DFX Trace for FFRT Serial Queue Task
320 #define FFRT_SERIAL_QUEUE_TASK_EXECUTE_MARKER(gid) \
321 { \
322 FFRT_TRACE_ASYNC_END("E", gid); \
323 }
324 #define FFRT_SERIAL_QUEUE_TASK_FINISH_MARKER(gid) \
325 { \
326 FFRT_TRACE_ASYNC_END("D", gid); \
327 }
328 #endif