• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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