Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "trace_event.h"
12 : #include "adiag_print.h"
13 : #include "adiag_utils.h"
14 : #include "tracer_core.h"
15 :
16 : #define TRACE_EVENT_THREAD_WAIT_INTERVAL 1000U // 1000ms
17 : typedef struct {
18 : mmMutex_t mutex;
19 : mmCond cond;
20 : mmThread tid;
21 : int32_t status;
22 : } ThreadCondInfo;
23 :
24 : typedef struct TraceEventsMgr {
25 : struct AdiagList eventList;
26 : struct AdiagList saveList;
27 : ThreadCondInfo eventProcessThread;
28 : } TraceEventsMgr;
29 :
30 : STATIC TraceEventsMgr* g_eventsMgr = NULL;
31 :
32 1444 : STATIC bool CheckEventNameValid(const char* name)
33 : {
34 1444 : if (name == NULL) {
35 44 : ADIAG_ERR("invalid name NULL");
36 44 : return false;
37 : }
38 1400 : if ((strlen(name) + 1U) > MAX_EVENT_NAME_LENGTH) {
39 44 : ADIAG_ERR("size of event name exceeds the upper limit of %u", MAX_EVENT_NAME_LENGTH);
40 44 : return false;
41 : }
42 1356 : return true;
43 : }
44 :
45 1446040 : STATIC bool CheckEventHandleValid(TraEventHandle eventHandle)
46 : {
47 1446040 : if (eventHandle <= 0) {
48 286 : ADIAG_ERR("invalid event handle %lld", eventHandle);
49 286 : return false;
50 : }
51 1445754 : void* data = AdiagListGetNode(&g_eventsMgr->eventList, (TraceEventNode*)eventHandle);
52 1445754 : if (data == NULL) {
53 22 : ADIAG_ERR("invalid event handle %lld", eventHandle);
54 22 : return false;
55 : }
56 1445732 : return true;
57 : }
58 :
59 132 : STATIC bool CheckEventAttrValid(const TraceEventAttr* attr)
60 : {
61 132 : if (attr == NULL) {
62 0 : ADIAG_ERR("invalid event attr NULL");
63 0 : return false;
64 : }
65 : // limitedNum is of type uint16_t with range [0, 65535], no need to check
66 132 : ADIAG_INF("limitedNum %u.", attr->limitedNum);
67 132 : return true;
68 : }
69 :
70 1442138 : STATIC INLINE bool TraceEventReportNumLimited(TraceEventNode* node)
71 : {
72 1442138 : if (node->attr.limitedNum == 0) {
73 214 : return false;
74 : }
75 1441924 : if (node->reportNum < node->attr.limitedNum) {
76 1441902 : return false;
77 : }
78 22 : return true;
79 : }
80 :
81 616 : STATIC TraStatus TraceEventCompareName(const void* nodeName, const void* name)
82 : {
83 616 : if (nodeName == NULL || name == NULL) {
84 0 : return TRACE_FAILURE;
85 : }
86 616 : if (strcmp((const char*)nodeName, (const char*)name) == 0) {
87 66 : return TRACE_SUCCESS;
88 : }
89 550 : return TRACE_FAILURE;
90 : }
91 :
92 346 : STATIC TraStatus TraceEventSave(void* arg)
93 : {
94 346 : if (arg == NULL) {
95 0 : return TRACE_SUCCESS;
96 : }
97 346 : TraceEventNode* node = (TraceEventNode*)arg;
98 346 : TracerObject* obj = NULL;
99 346 : TraStatus ret = TRACE_SUCCESS;
100 346 : if (node->relatedTracer != 0) {
101 : // process inner event
102 126 : if (TracerSaveTracer((Tracer*)node->relatedTracer) != TRACE_SUCCESS) {
103 48 : ADIAG_ERR("save trace for event %s failed", node->eventName);
104 48 : ret = TRACE_FAILURE;
105 : } else {
106 78 : ADIAG_DBG("save trace for event %s", node->eventName);
107 : }
108 : }
109 566 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
110 220 : obj = (TracerObject*)node->relatedTraceObj[i];
111 220 : if (TracerSaveObj(obj) != TRACE_SUCCESS) {
112 0 : ADIAG_ERR("save trace for event %s handle %s failed", node->eventName, obj->name);
113 0 : ret = TRACE_FAILURE;
114 : } else {
115 220 : ADIAG_DBG("save trace %s for event %s", obj->name, node->eventName);
116 : }
117 : }
118 346 : return ret;
119 : }
120 :
121 : /**
122 : * @brief init trace event
123 : * @return TraStatus
124 : */
125 1048 : TraStatus TraceEventInit(void)
126 : {
127 1048 : g_eventsMgr = (TraceEventsMgr*)AdiagMalloc(sizeof(TraceEventsMgr));
128 1048 : if (g_eventsMgr == NULL) {
129 22 : ADIAG_ERR("malloc g_eventsMgr failed, strerr=%s.", strerror(AdiagGetErrorCode()));
130 22 : return TRACE_FAILURE;
131 : }
132 1026 : TraStatus ret = AdiagListInit(&g_eventsMgr->eventList);
133 1026 : if (ret != TRACE_SUCCESS) {
134 22 : ADIAG_ERR("init event list failed, ret=%d.", ret);
135 22 : AdiagFree(g_eventsMgr);
136 22 : g_eventsMgr = NULL;
137 22 : return TRACE_FAILURE;
138 : }
139 1004 : ret = AdiagListInit(&g_eventsMgr->saveList);
140 1004 : if (ret != TRACE_SUCCESS) {
141 22 : ADIAG_ERR("init save list failed, ret=%d.", ret);
142 22 : (void)AdiagListDestroy(&g_eventsMgr->eventList);
143 22 : AdiagFree(g_eventsMgr);
144 22 : g_eventsMgr = NULL;
145 22 : return TRACE_FAILURE;
146 : }
147 982 : ADIAG_INF("init trace event successfully");
148 982 : return TRACE_SUCCESS;
149 : }
150 :
151 : /**
152 : * @brief exit trace event
153 : * @return NA
154 : */
155 1038 : void TraceEventExit(void)
156 : {
157 1038 : if (g_eventsMgr != NULL) {
158 976 : (void)AdiagListDestroy(&g_eventsMgr->saveList);
159 976 : (void)AdiagListDestroy(&g_eventsMgr->eventList);
160 976 : AdiagFree(g_eventsMgr);
161 976 : g_eventsMgr = NULL;
162 : }
163 1038 : return;
164 : }
165 :
166 : /**
167 : * @brief create trace event, add trace event node to eventList
168 : * @param [in] eventName: name of trace event
169 : * @return eventHandle if create success, TRACE_INVALID_HANDLE otherwise
170 : */
171 1378 : TraEventHandle TraceEventCreate(const char* eventName)
172 : {
173 1378 : if (!CheckEventNameValid(eventName)) {
174 44 : ADIAG_ERR("atrace create event failed");
175 44 : return TRACE_INVALID_HANDLE;
176 : }
177 1334 : if (g_eventsMgr == NULL) {
178 0 : ADIAG_ERR("g_eventsMgr has not been init successfully.");
179 0 : return TRACE_INVALID_HANDLE;
180 : }
181 1334 : void* data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
182 1334 : if (data != NULL) {
183 44 : ADIAG_ERR("duplicated trace event name %s", eventName);
184 44 : return TRACE_INVALID_HANDLE;
185 : }
186 1290 : TraceEventNode* node = (TraceEventNode*)AdiagMalloc(sizeof(TraceEventNode));
187 1290 : if (node == NULL) {
188 0 : ADIAG_ERR("malloc node failed, strerr=%s.", strerror(AdiagGetErrorCode()));
189 0 : return TRACE_INVALID_HANDLE;
190 : }
191 1290 : errno_t err = strcpy_s(node->eventName, sizeof(node->eventName), eventName);
192 1290 : if (err != EOK) {
193 0 : ADIAG_ERR("strcpy_s event_name [%s] failed, ret : %d", eventName, err);
194 0 : AdiagFree(node);
195 0 : return TRACE_INVALID_HANDLE;
196 : }
197 1290 : node->processFunc = TraceEventSave;
198 1290 : AdiagStatus ret = AdiagListInsert(&g_eventsMgr->eventList, node);
199 1290 : if (ret != ADIAG_SUCCESS) {
200 0 : ADIAG_ERR("insert node to event list failed, ret=%d.", ret);
201 0 : AdiagFree(node);
202 0 : return TRACE_INVALID_HANDLE;
203 : }
204 1290 : ADIAG_DBG("insert event %s to event list", node->eventName);
205 1290 : return (TraEventHandle)node;
206 : }
207 :
208 : /**
209 : * @brief get event handle by eventName
210 : * @param [in] eventName: name of trace event
211 : * @return eventHandle if found, TRACE_INVALID_HANDLE otherwise
212 : */
213 66 : TraEventHandle TraceEventGetHandle(const char* eventName)
214 : {
215 66 : if (!CheckEventNameValid(eventName)) {
216 44 : ADIAG_ERR("atrace get event handle failed");
217 44 : return TRACE_INVALID_HANDLE;
218 : }
219 22 : void* data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
220 22 : if (data == NULL) {
221 0 : return TRACE_INVALID_HANDLE;
222 : }
223 22 : return (TraEventHandle)data;
224 : }
225 :
226 : /**
227 : * @brief destroy event handle, process all event in saveList before destroy
228 : * @param [in] eventHandle: event handle, handle of event node
229 : * @return NA
230 : */
231 1306 : void TraceEventDestroy(TraEventHandle eventHandle)
232 : {
233 1306 : if (!CheckEventHandleValid(eventHandle)) {
234 66 : ADIAG_ERR("atrace destroy event failed");
235 66 : return;
236 : }
237 1240 : TraceEventNode* node = (TraceEventNode*)eventHandle;
238 1240 : ADIAG_CHK_EXPR_ACTION(node == NULL, return, "invalid param eventHandle %lld", eventHandle);
239 1416 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
240 176 : (void)TraceUnbindEvent(node->relatedTraceObj[i], eventHandle);
241 : }
242 1240 : (void)AdiagListRemoveAll(&g_eventsMgr->saveList, node, TraceEventSave);
243 1240 : AdiagStatus ret = AdiagListRemove(&g_eventsMgr->eventList, node);
244 1240 : if (ret != ADIAG_SUCCESS) {
245 0 : ADIAG_ERR("remove event from event list failed.");
246 : } else {
247 1240 : ADIAG_DBG("delete event %s from event list", node->eventName);
248 : }
249 1240 : ADIAG_SAFE_FREE(node);
250 : }
251 :
252 : /**
253 : * @brief bind tracer to trace event
254 : * @param [in] eventHandle: event handle, handle of event node
255 : * @param [in] tracer: tracer handle
256 : * @return TraStatus
257 : */
258 1004 : TraStatus TraceEventBindTracer(TraEventHandle eventHandle, TracerHandle tracer)
259 : {
260 1004 : if (!CheckEventHandleValid(eventHandle)) {
261 22 : ADIAG_ERR("atrace event bind tracer failed");
262 22 : return TRACE_INVALID_PARAM;
263 : }
264 982 : TraceEventNode* node = (TraceEventNode*)eventHandle;
265 982 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
266 :
267 982 : if (node->relatedTracer != 0) {
268 0 : ADIAG_ERR("event %s has been bound to tracer", node->eventName);
269 0 : return TRACE_FAILURE;
270 : }
271 982 : node->relatedTracer = tracer;
272 982 : return TRACE_SUCCESS;
273 : }
274 :
275 : /**
276 : * @brief unbind tracer with trace event
277 : * @param [in] eventHandle: event handle, handle of event node
278 : * @param [in] tracer: tracer handle
279 : * @return TraStatus
280 : */
281 998 : TraStatus TraceEventUnbindTracer(TraEventHandle eventHandle, TracerHandle tracer)
282 : {
283 998 : if (!CheckEventHandleValid(eventHandle)) {
284 22 : ADIAG_ERR("atrace event bind tracer failed");
285 22 : return TRACE_INVALID_PARAM;
286 : }
287 976 : TraceEventNode* node = (TraceEventNode*)eventHandle;
288 976 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
289 976 : if (node->relatedTracer != tracer) {
290 0 : ADIAG_ERR("event %s has not been bound to tracer", node->eventName);
291 0 : return TRACE_FAILURE;
292 : }
293 976 : node->relatedTracer = 0;
294 976 : return TRACE_SUCCESS;
295 : }
296 :
297 : /**
298 : * @brief bind trace object to trace event and bind trace event to trace object
299 : * @param [in] eventHandle: event handle, handle of event node
300 : * @param [in] handle: trace object handle
301 : * @return TraStatus
302 : */
303 308 : TraStatus TraceEventBindTrace(TraEventHandle eventHandle, TraHandle handle)
304 : {
305 308 : if (!CheckEventHandleValid(eventHandle)) {
306 88 : ADIAG_ERR("atrace event bind trace failed");
307 88 : return TRACE_INVALID_PARAM;
308 : }
309 220 : TraceEventNode* node = (TraceEventNode*)eventHandle;
310 220 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
311 220 : if (node->relatedTraceObjNum >= MAX_RELATED_TRACER_NUM) {
312 0 : ADIAG_ERR("trace bound to event exceeds the upper limit %u", MAX_RELATED_TRACER_NUM);
313 0 : return TRACE_FAILURE;
314 : }
315 220 : TraStatus ret = TraceBindEvent(handle, eventHandle);
316 220 : if (ret != TRACE_SUCCESS) {
317 0 : return ret;
318 : }
319 220 : node->relatedTraceObj[node->relatedTraceObjNum] = handle;
320 220 : node->relatedTraceObjNum++;
321 220 : return TRACE_SUCCESS;
322 : }
323 :
324 : /**
325 : * @brief unbind trace event with trace object
326 : * @param [in] eventHandle: event handle, handle of event node
327 : * @param [in] handle: trace object handle
328 : * @return TraStatus
329 : */
330 66 : TraStatus TraceEventUnbindTrace(TraEventHandle eventHandle, TraHandle handle)
331 : {
332 66 : if (!CheckEventHandleValid(eventHandle)) {
333 22 : ADIAG_ERR("atrace event unbind trace failed");
334 22 : return TRACE_INVALID_PARAM;
335 : }
336 44 : ADIAG_CHK_EXPR_ACTION(handle < 0, return TRACE_INVALID_PARAM, "invalid param handle %lld", eventHandle);
337 44 : TraceEventNode* node = (TraceEventNode*)eventHandle;
338 44 : uint8_t j = 0;
339 88 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
340 44 : if (node->relatedTraceObj[i] != handle) {
341 0 : node->relatedTraceObj[j] = node->relatedTraceObj[i];
342 0 : j++;
343 : }
344 : }
345 44 : node->relatedTraceObjNum = j;
346 44 : return TRACE_SUCCESS;
347 : }
348 :
349 : /**
350 : * @brief set event trace attr
351 : * @param [in] eventHandle: event handle, handle of event node
352 : * @param [in] attr: event attr
353 : * @return TraStatus
354 : */
355 198 : TraStatus TraceEventSetAttr(TraEventHandle eventHandle, const TraceEventAttr* attr)
356 : {
357 198 : if (!CheckEventHandleValid(eventHandle) || !CheckEventAttrValid(attr)) {
358 66 : ADIAG_ERR("atrace event report failed");
359 66 : return TRACE_INVALID_PARAM;
360 : }
361 132 : TraceEventNode* node = (TraceEventNode*)eventHandle;
362 132 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
363 132 : errno_t ret = memcpy_s(&node->attr, sizeof(TraceEventAttr), attr, sizeof(TraceEventAttr));
364 132 : if (ret != EOK) {
365 0 : ADIAG_ERR("memcpy attr failed, ret : %d", ret);
366 0 : return TRACE_FAILURE;
367 : }
368 132 : ADIAG_INF("set trace event attr limitedNum: %hu", node->attr.limitedNum);
369 132 : return TRACE_SUCCESS;
370 : }
371 :
372 : /**
373 : * @brief report trace event and process event
374 : * @param [in] eventHandle: event handle, handle of event node
375 : * @return TraStatus
376 : */
377 1442160 : TraStatus TraceEventReport(TraEventHandle eventHandle)
378 : {
379 1442160 : if (!CheckEventHandleValid(eventHandle)) {
380 22 : ADIAG_ERR("atrace event report failed");
381 22 : return TRACE_INVALID_HANDLE;
382 : }
383 1442138 : TraceEventNode* node = (TraceEventNode*)eventHandle;
384 1442138 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
385 1442138 : if (node->relatedTraceObjNum == 0 && node->relatedTracer == 0) {
386 0 : ADIAG_WAR("trace event [%s] has not been bound to tracer, ignored", node->eventName);
387 0 : return TRACE_SUCCESS;
388 : }
389 1442138 : if (TraceEventReportNumLimited(node)) {
390 22 : ADIAG_WAR(
391 : "the number of trace event[%s] reports has reached the upper limit %hu, ignored", node->eventName,
392 : node->attr.limitedNum);
393 22 : return TRACE_SUCCESS;
394 : }
395 1442116 : if (node->attr.limitedNum != 0) {
396 1441902 : node->reportNum++; // ensure reportNum will be no more than limitedNum
397 : }
398 1442116 : TraStatus ret = TraceEventSave(node);
399 1442116 : ADIAG_DBG("AtraceEventReport [%s], ret=%d.", node->eventName, ret);
400 1442116 : return ret;
401 : }
|