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 1290 : STATIC bool CheckEventNameValid(const char *name)
33 : {
34 1290 : if (name == NULL) {
35 40 : ADIAG_ERR("invalid name NULL");
36 40 : return false;
37 : }
38 1250 : if ((strlen(name) + 1U) > MAX_EVENT_NAME_LENGTH) {
39 40 : ADIAG_ERR("size of event name exceeds the upper limit of %u", MAX_EVENT_NAME_LENGTH);
40 40 : return false;
41 : }
42 1210 : return true;
43 : }
44 :
45 1314514 : STATIC bool CheckEventHandleValid(TraEventHandle eventHandle)
46 : {
47 1314514 : if (eventHandle <= 0) {
48 260 : ADIAG_ERR("invalid event handle %lld", eventHandle);
49 260 : return false;
50 : }
51 1314254 : void *data = AdiagListGetNode(&g_eventsMgr->eventList, (TraceEventNode *)eventHandle);
52 1314254 : if (data == NULL) {
53 20 : ADIAG_ERR("invalid event handle %lld", eventHandle);
54 20 : return false;
55 : }
56 1314234 : return true;
57 : }
58 :
59 120 : STATIC bool CheckEventAttrValid(const TraceEventAttr *attr)
60 : {
61 120 : 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 120 : ADIAG_INF("limitedNum %u.", attr->limitedNum);
67 120 : return true;
68 : }
69 :
70 1311036 : STATIC INLINE bool TraceEventReportNumLimited(TraceEventNode *node)
71 : {
72 1311036 : if (node->attr.limitedNum == 0) {
73 196 : return false;
74 : }
75 1310840 : if (node->reportNum < node->attr.limitedNum) {
76 1310820 : return false;
77 : }
78 20 : return true;
79 : }
80 :
81 560 : STATIC TraStatus TraceEventCompareName(const void *nodeName, const void *name)
82 : {
83 560 : if (nodeName == NULL || name == NULL) {
84 0 : return TRACE_FAILURE;
85 : }
86 560 : if (strcmp((const char *)nodeName, (const char *)name) == 0) {
87 60 : return TRACE_SUCCESS;
88 : }
89 500 : return TRACE_FAILURE;
90 : }
91 :
92 316 : STATIC TraStatus TraceEventSave(void *arg)
93 : {
94 316 : if (arg == NULL) {
95 0 : return TRACE_SUCCESS;
96 : }
97 316 : TraceEventNode *node = (TraceEventNode *)arg;
98 316 : TracerObject *obj = NULL;
99 316 : TraStatus ret = TRACE_SUCCESS;
100 316 : if (node->relatedTracer != 0) {
101 : // process inner event
102 116 : if (TracerSaveTracer((Tracer *)node->relatedTracer) != TRACE_SUCCESS) {
103 44 : ADIAG_ERR("save trace for event %s failed", node->eventName);
104 44 : ret = TRACE_FAILURE;
105 : } else {
106 72 : ADIAG_DBG("save trace for event %s", node->eventName);
107 : }
108 : }
109 516 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
110 200 : obj = (TracerObject *)node->relatedTraceObj[i];
111 200 : 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 200 : ADIAG_DBG("save trace %s for event %s", obj->name, node->eventName);
116 : }
117 : }
118 316 : return ret;
119 : }
120 :
121 : /**
122 : * @brief init trace event
123 : * @return TraStatus
124 : */
125 930 : TraStatus TraceEventInit(void)
126 : {
127 930 : g_eventsMgr = (TraceEventsMgr *)AdiagMalloc(sizeof(TraceEventsMgr));
128 930 : if (g_eventsMgr == NULL) {
129 20 : ADIAG_ERR("malloc g_eventsMgr failed, strerr=%s.", strerror(AdiagGetErrorCode()));
130 20 : return TRACE_FAILURE;
131 : }
132 910 : TraStatus ret = AdiagListInit(&g_eventsMgr->eventList);
133 910 : if (ret != TRACE_SUCCESS) {
134 20 : ADIAG_ERR("init event list failed, ret=%d.", ret);
135 20 : AdiagFree(g_eventsMgr);
136 20 : g_eventsMgr = NULL;
137 20 : return TRACE_FAILURE;
138 : }
139 890 : ret = AdiagListInit(&g_eventsMgr->saveList);
140 890 : if (ret != TRACE_SUCCESS) {
141 20 : ADIAG_ERR("init save list failed, ret=%d.", ret);
142 20 : (void)AdiagListDestroy(&g_eventsMgr->eventList);
143 20 : AdiagFree(g_eventsMgr);
144 20 : g_eventsMgr = NULL;
145 20 : return TRACE_FAILURE;
146 : }
147 870 : ADIAG_INF("init trace event successfully");
148 870 : return TRACE_SUCCESS;
149 : }
150 :
151 : /**
152 : * @brief exit trace event
153 : * @return NA
154 : */
155 920 : void TraceEventExit(void)
156 : {
157 920 : if (g_eventsMgr != NULL) {
158 864 : (void)AdiagListDestroy(&g_eventsMgr->saveList);
159 864 : (void)AdiagListDestroy(&g_eventsMgr->eventList);
160 864 : AdiagFree(g_eventsMgr);
161 864 : g_eventsMgr = NULL;
162 : }
163 920 : 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 1230 : TraEventHandle TraceEventCreate(const char *eventName)
172 : {
173 1230 : if (!CheckEventNameValid(eventName)) {
174 40 : ADIAG_ERR("atrace create event failed");
175 40 : return TRACE_INVALID_HANDLE;
176 : }
177 1190 : if (g_eventsMgr == NULL) {
178 0 : ADIAG_ERR("g_eventsMgr has not been init successfully.");
179 0 : return TRACE_INVALID_HANDLE;
180 : }
181 1190 : void *data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
182 1190 : if (data != NULL) {
183 40 : ADIAG_ERR("duplicated trace event name %s", eventName);
184 40 : return TRACE_INVALID_HANDLE;
185 : }
186 1150 : TraceEventNode *node = (TraceEventNode *)AdiagMalloc(sizeof(TraceEventNode));
187 1150 : if (node == NULL) {
188 0 : ADIAG_ERR("malloc node failed, strerr=%s.", strerror(AdiagGetErrorCode()));
189 0 : return TRACE_INVALID_HANDLE;
190 : }
191 1150 : errno_t err = strcpy_s(node->eventName, sizeof(node->eventName), eventName);
192 1150 : 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 1150 : node->processFunc = TraceEventSave;
198 1150 : AdiagStatus ret = AdiagListInsert(&g_eventsMgr->eventList, node);
199 1150 : 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 1150 : ADIAG_DBG("insert event %s to event list", node->eventName);
205 1150 : 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 60 : TraEventHandle TraceEventGetHandle(const char *eventName)
214 : {
215 60 : if (!CheckEventNameValid(eventName)) {
216 40 : ADIAG_ERR("atrace get event handle failed");
217 40 : return TRACE_INVALID_HANDLE;
218 : }
219 20 : void *data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
220 20 : if (data == NULL) {
221 0 : return TRACE_INVALID_HANDLE;
222 : }
223 20 : 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 1164 : void TraceEventDestroy(TraEventHandle eventHandle)
232 : {
233 1164 : if (!CheckEventHandleValid(eventHandle)) {
234 60 : ADIAG_ERR("atrace destroy event failed");
235 60 : return;
236 : }
237 1104 : TraceEventNode *node = (TraceEventNode *)eventHandle;
238 1104 : ADIAG_CHK_EXPR_ACTION(node == NULL, return, "invalid param eventHandle %lld", eventHandle);
239 1264 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
240 160 : (void)TraceUnbindEvent(node->relatedTraceObj[i], eventHandle);
241 : }
242 1104 : (void)AdiagListRemoveAll(&g_eventsMgr->saveList, node, TraceEventSave);
243 1104 : AdiagStatus ret = AdiagListRemove(&g_eventsMgr->eventList, node);
244 1104 : if (ret != ADIAG_SUCCESS) {
245 0 : ADIAG_ERR("remove event from event list failed.");
246 : } else {
247 1104 : ADIAG_DBG("delete event %s from event list", node->eventName);
248 : }
249 1104 : 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 890 : TraStatus TraceEventBindTracer(TraEventHandle eventHandle, TracerHandle tracer)
259 : {
260 890 : if (!CheckEventHandleValid(eventHandle)) {
261 20 : ADIAG_ERR("atrace event bind tracer failed");
262 20 : return TRACE_INVALID_PARAM;
263 : }
264 870 : TraceEventNode *node = (TraceEventNode *)eventHandle;
265 870 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
266 :
267 870 : if (node->relatedTracer != 0) {
268 0 : ADIAG_ERR("event %s has been bound to tracer", node->eventName);
269 0 : return TRACE_FAILURE;
270 : }
271 870 : node->relatedTracer = tracer;
272 870 : 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 884 : TraStatus TraceEventUnbindTracer(TraEventHandle eventHandle, TracerHandle tracer)
282 : {
283 884 : if (!CheckEventHandleValid(eventHandle)) {
284 20 : ADIAG_ERR("atrace event bind tracer failed");
285 20 : return TRACE_INVALID_PARAM;
286 : }
287 864 : TraceEventNode *node = (TraceEventNode *)eventHandle;
288 864 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
289 864 : 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 864 : node->relatedTracer = 0;
294 864 : 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 280 : TraStatus TraceEventBindTrace(TraEventHandle eventHandle, TraHandle handle)
304 : {
305 280 : if (!CheckEventHandleValid(eventHandle)) {
306 80 : ADIAG_ERR("atrace event bind trace failed");
307 80 : return TRACE_INVALID_PARAM;
308 : }
309 200 : TraceEventNode *node = (TraceEventNode *)eventHandle;
310 200 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
311 200 : 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 200 : TraStatus ret = TraceBindEvent(handle, eventHandle);
316 200 : if (ret != TRACE_SUCCESS) {
317 0 : return ret;
318 : }
319 200 : node->relatedTraceObj[node->relatedTraceObjNum] = handle;
320 200 : node->relatedTraceObjNum++;
321 200 : 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 60 : TraStatus TraceEventUnbindTrace(TraEventHandle eventHandle, TraHandle handle)
331 : {
332 60 : if (!CheckEventHandleValid(eventHandle)) {
333 20 : ADIAG_ERR("atrace event unbind trace failed");
334 20 : return TRACE_INVALID_PARAM;
335 : }
336 40 : ADIAG_CHK_EXPR_ACTION(handle < 0, return TRACE_INVALID_PARAM, "invalid param handle %lld", eventHandle);
337 40 : TraceEventNode *node = (TraceEventNode *)eventHandle;
338 40 : uint8_t j = 0;
339 80 : for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
340 40 : if (node->relatedTraceObj[i] != handle) {
341 0 : node->relatedTraceObj[j] = node->relatedTraceObj[i];
342 0 : j++;
343 : }
344 : }
345 40 : node->relatedTraceObjNum = j;
346 40 : 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 180 : TraStatus TraceEventSetAttr(TraEventHandle eventHandle, const TraceEventAttr *attr)
356 : {
357 180 : if (!CheckEventHandleValid(eventHandle) || !CheckEventAttrValid(attr)) {
358 60 : ADIAG_ERR("atrace event report failed");
359 60 : return TRACE_INVALID_PARAM;
360 : }
361 120 : TraceEventNode *node = (TraceEventNode *)eventHandle;
362 120 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
363 120 : errno_t ret = memcpy_s(&node->attr, sizeof(TraceEventAttr), attr, sizeof(TraceEventAttr));
364 120 : if (ret != EOK) {
365 0 : ADIAG_ERR("memcpy attr failed, ret : %d", ret);
366 0 : return TRACE_FAILURE;
367 : }
368 120 : ADIAG_INF("set trace event attr limitedNum: %hu", node->attr.limitedNum);
369 120 : 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 1311056 : TraStatus TraceEventReport(TraEventHandle eventHandle)
378 : {
379 1311056 : if (!CheckEventHandleValid(eventHandle)) {
380 20 : ADIAG_ERR("atrace event report failed");
381 20 : return TRACE_INVALID_HANDLE;
382 : }
383 1311036 : TraceEventNode *node = (TraceEventNode *)eventHandle;
384 1311036 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
385 1311036 : 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 1311036 : if (TraceEventReportNumLimited(node)) {
390 20 : ADIAG_WAR("the number of trace event[%s] reports has reached the upper limit %hu, ignored",
391 : node->eventName, node->attr.limitedNum);
392 20 : return TRACE_SUCCESS;
393 : }
394 1311016 : if (node->attr.limitedNum != 0) {
395 1310820 : node->reportNum++; // ensure reportNum will be no more than limitedNum
396 : }
397 1311016 : TraStatus ret = TraceEventSave(node);
398 1311016 : ADIAG_DBG("AtraceEventReport [%s], ret=%d.", node->eventName, ret);
399 1311016 : return ret;
400 : }
|