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 "tracer_core.h"
12 : #include "adiag_print.h"
13 : #include "stacktrace_signal.h"
14 : #include "tracer_schedule.h"
15 : #include "trace_rb_log.h"
16 : #include "adiag_utils.h"
17 : #include "trace_system_api.h"
18 :
19 : STATIC Tracer g_tracers[TRACER_TYPE_MAX] = {
20 : {TRACER_SCHEDULE_NAME, TracerScheduleRegister, TracerScheduleUnregister, NULL},
21 : {"progress", NULL, NULL, NULL},
22 : {"statistics", NULL, NULL, NULL},
23 : };
24 :
25 83154 : TraStatus TracerObjSubmit(TraHandle handle, uint8_t bufferType, const void *buffer, uint32_t bufSize)
26 : {
27 83154 : if (handle < 0) {
28 22 : return TRACE_FAILURE;
29 : }
30 83132 : TracerObject *obj = (TracerObject *)handle;
31 83132 : if (obj == NULL) {
32 0 : return TRACE_FAILURE;
33 : }
34 83132 : if (obj->status != (int32_t)OBJ_STATUS_WORKING) {
35 0 : ADIAG_ERR("object[%s] is not working, status=%d.", obj->name, obj->status);
36 0 : return TRACE_FAILURE;
37 : }
38 83132 : if (obj->noLock == TRACE_LOCK_FREE) {
39 24 : return TraceRbLogWriteRbMsgNoLock((RbLog *)obj->data, bufferType, (const char *)buffer, bufSize);
40 : } else {
41 83108 : return TraceRbLogWriteRbMsg((RbLog *)obj->data, bufferType, (const char *)buffer, bufSize);
42 : }
43 : }
44 :
45 842 : TraHandle TracerObjCreate(TracerType tracerType, const char *objName, const TraceAttr *attr)
46 : {
47 842 : ADIAG_CHK_NULL_PTR(attr, return TRACE_INVALID_HANDLE);
48 :
49 842 : if ((g_tracers[tracerType].mgr != NULL) && (g_tracers[tracerType].mgr->op.tracerCreateFunc != NULL)) {
50 842 : TraObjHandle hdl = g_tracers[tracerType].mgr->op.tracerCreateFunc(&g_tracers[tracerType], objName, attr);
51 842 : return hdl;
52 : }
53 0 : ADIAG_ERR("%d, g_tracers[tracerType].mgr %p", tracerType, g_tracers[tracerType].mgr);
54 0 : return TRACE_INVALID_HANDLE;
55 : }
56 :
57 66 : TraHandle TracerObjGet(TracerType tracerType, const char *objName)
58 : {
59 66 : ADIAG_CHK_EXPR_ACTION(tracerType >= TRACER_TYPE_MAX, return TRACE_INVALID_HANDLE,
60 : "tracer type %d is invalid.", (int32_t)tracerType);
61 66 : ADIAG_CHK_NULL_PTR(objName, return TRACE_INVALID_HANDLE);
62 :
63 66 : if ((g_tracers[tracerType].mgr != NULL) && (g_tracers[tracerType].mgr->op.tracerGetFunc != NULL)) {
64 66 : TraObjHandle hdl = g_tracers[tracerType].mgr->op.tracerGetFunc(&g_tracers[tracerType], objName);
65 66 : return hdl;
66 : }
67 :
68 0 : return TRACE_INVALID_HANDLE;
69 : }
70 :
71 884 : void TracerObjDestroy(TraHandle handle)
72 : {
73 884 : if (handle < 0) {
74 66 : ADIAG_ERR("handle %ld is invalid.", (long)handle);
75 66 : return;
76 : }
77 818 : TracerObject *obj = (TracerObject *)handle;
78 818 : if (obj == NULL) {
79 22 : ADIAG_ERR("handle is null.");
80 22 : return;
81 : }
82 :
83 836 : for (uint8_t i = 0; i < obj->relatedEventNum; i++) {
84 40 : (void)TraceEventUnbindTrace(obj->relatedEvent[i], handle);
85 : }
86 796 : obj->relatedEventNum = 0;
87 :
88 796 : int32_t tracerType = obj->tracerType;
89 796 : ADIAG_CHK_EXPR_ACTION(tracerType >= (int32_t)TRACER_TYPE_MAX, return, "handle %ld is invalid.", (long)handle);
90 796 : ADIAG_DBG("AtraceDestroy [%s].", obj->name);
91 796 : if ((g_tracers[tracerType].mgr != NULL) && (g_tracers[tracerType].mgr->op.tracerDestroyFunc != NULL)) {
92 796 : (void)g_tracers[tracerType].mgr->op.tracerDestroyFunc(&g_tracers[tracerType], handle);
93 : }
94 : }
95 :
96 116 : TraStatus TracerSave(TracerType tracerType, bool syncFlag)
97 : {
98 116 : ADIAG_CHK_EXPR_ACTION(tracerType >= TRACER_TYPE_MAX, return TRACE_INVALID_PARAM,
99 : "tracer type %d is invalid.", (int32_t)tracerType);
100 116 : TracerMgr *mgr = g_tracers[tracerType].mgr;
101 116 : if ((mgr == NULL) || mgr->op.tracerSaveFunc == NULL || mgr->op.tracerReportFunc == NULL) {
102 0 : ADIAG_ERR("tracer manager has not been initialized or has been finalized");
103 0 : return TRACE_FAILURE;
104 : }
105 : (void)syncFlag;
106 116 : return TraceEventReport(mgr->innerEvent);
107 : }
108 :
109 116 : TraStatus TracerSaveTracer(Tracer *tracer)
110 : {
111 116 : if ((tracer->mgr == NULL) || tracer->mgr->op.tracerSaveFunc == NULL) {
112 0 : ADIAG_ERR("tracer manager has not been initialized or has been finalized");
113 0 : return TRACE_FAILURE;
114 : }
115 116 : return (tracer->mgr->op.tracerSaveFunc)(tracer, NULL);
116 : }
117 :
118 200 : TraStatus TracerSaveObj(TracerObject *obj)
119 : {
120 200 : ADIAG_CHK_NULL_PTR(obj, return TRACE_FAILURE);
121 :
122 200 : Tracer *tracer = &g_tracers[obj->tracerType];
123 200 : if ((tracer->mgr == NULL) || tracer->mgr->op.tracerSaveFunc == NULL) {
124 0 : ADIAG_ERR("tracer manager has not been initialized or has been finalized");
125 0 : return TRACE_FAILURE;
126 : }
127 200 : return (tracer->mgr->op.tracerSaveFunc)(tracer, obj);
128 : }
129 :
130 870 : TraStatus TracerInit(void)
131 : {
132 3480 : for (int32_t i = 0; i < (int32_t)TRACER_TYPE_MAX; i++) {
133 2610 : if (g_tracers[i].tracerRegisterFunc != NULL) {
134 870 : TraStatus ret = g_tracers[i].tracerRegisterFunc(&g_tracers[i]);
135 870 : if (ret != TRACE_SUCCESS) {
136 0 : ADIAG_ERR("%s tracer register failed.", g_tracers[i].name);
137 0 : return TRACE_FAILURE;
138 : }
139 : }
140 :
141 2610 : if ((g_tracers[i].mgr != NULL) && (g_tracers[i].mgr->op.tracerInitFunc != NULL)) {
142 870 : TraStatus ret = g_tracers[i].mgr->op.tracerInitFunc(&g_tracers[i]);
143 870 : if (ret != TRACE_SUCCESS) {
144 0 : ADIAG_ERR("%s tracer init failed.", g_tracers[i].name);
145 0 : return TRACE_FAILURE;
146 : }
147 : }
148 : }
149 :
150 870 : return TRACE_SUCCESS;
151 : }
152 :
153 940 : void TracerExit(void)
154 : {
155 3760 : for (int32_t i = 0; i < (int32_t)TRACER_TYPE_MAX; i++) {
156 2820 : if ((g_tracers[i].mgr != NULL) && (g_tracers[i].mgr->op.tracerExitFunc != NULL)) {
157 864 : TraStatus ret = g_tracers[i].mgr->op.tracerExitFunc(&g_tracers[i]);
158 864 : if (ret != TRACE_SUCCESS) {
159 0 : ADIAG_ERR("%s tracer exit failed.", g_tracers[i].name);
160 : }
161 : }
162 :
163 2820 : if (g_tracers[i].tracerUnregisterFunc != NULL) {
164 940 : TraStatus ret = g_tracers[i].tracerUnregisterFunc(&g_tracers[i]);
165 940 : if (ret != TRACE_SUCCESS) {
166 0 : ADIAG_ERR("%s tracer unregister failed.", g_tracers[i].name);
167 : }
168 : }
169 : }
170 940 : }
171 :
172 276 : void *TracerStructEntryListInit(void)
173 : {
174 276 : void *list = AdiagMalloc(sizeof(struct AdiagList));
175 276 : if (list == NULL) {
176 22 : ADIAG_ERR("malloc for struct entry failed.");
177 22 : return NULL;
178 : }
179 254 : if (AdiagListInit((struct AdiagList *)list) != TRACE_SUCCESS) {
180 20 : ADIAG_ERR("init trace list failed.");
181 20 : ADIAG_SAFE_FREE(list);
182 20 : return NULL;
183 : }
184 234 : return list;
185 : }
186 :
187 256 : void TracerStructEntryName(TraceStructEntry *entry, const char *name)
188 : {
189 256 : if ((entry == NULL) || (name == NULL)) {
190 0 : return;
191 : }
192 256 : errno_t ret = strcpy_s(entry->name, TRACE_NAME_LENGTH, name);
193 256 : if (ret != EOK) {
194 22 : ADIAG_WAR("[%s]entry name is invalid.", name);
195 22 : (void)memset_s(entry->name, TRACE_NAME_LENGTH, 0, TRACE_NAME_LENGTH);
196 : }
197 : }
198 :
199 :
200 858 : STATIC TraStatus TracerStructParamCheck(TraceStructEntry *entry, const char *name, uint8_t type, uint8_t mode)
201 : {
202 858 : if ((entry == NULL) || (entry->list == NULL)) {
203 22 : ADIAG_ERR("entry is invalid, please init entry first.");
204 22 : return TRACE_FAILURE;
205 : }
206 836 : if (name == NULL) {
207 0 : ADIAG_ERR("field name is invalid.");
208 0 : return TRACE_FAILURE;
209 : }
210 :
211 836 : if (((type > TRACE_STRUCT_FIELD_TYPE_UINT64) && (type < TRACE_STRUCT_ARRAY_TYPE_CHAR)) ||
212 : (type > TRACE_STRUCT_ARRAY_TYPE_UINT64)) {
213 0 : ADIAG_ERR("struct type[%u] is invalid.", (uint32_t)type);
214 0 : return TRACE_FAILURE;
215 : }
216 836 : if (mode > TRACE_STRUCT_SHOW_MODE_CHAR) {
217 0 : ADIAG_ERR("struct mode[%u] is invalid.", (uint32_t)mode);
218 0 : return TRACE_FAILURE;
219 : }
220 836 : return TRACE_SUCCESS;
221 : }
222 :
223 858 : void TracerStructItemSet(TraceStructEntry *entry, const char *name, uint8_t type, uint8_t mode, uint16_t length)
224 : {
225 858 : if (TracerStructParamCheck(entry, name, type, mode) != TRACE_SUCCESS) {
226 22 : ADIAG_ERR("input is invalid, add atrace struct item failed.");
227 22 : return;
228 : }
229 836 : TraceStructField *item = (TraceStructField *)AdiagMalloc(sizeof(TraceStructField));
230 836 : if (item == NULL) {
231 20 : ADIAG_ERR("[%s]malloc for struct field failed, field name = %s.", entry->name, name);
232 20 : return;
233 : }
234 816 : errno_t ret = strcpy_s(item->name, TRACE_NAME_LENGTH, name);
235 816 : if (ret != EOK) {
236 22 : ADIAG_ERR("[%s]memcpy for struct field failed, field name = %s.", entry->name, name);
237 22 : ADIAG_SAFE_FREE(item);
238 22 : return;
239 : }
240 794 : item->type = type;
241 794 : item->mode = mode;
242 794 : item->length = length;
243 794 : if (AdiagListInsert((struct AdiagList *)(entry->list), item) != ADIAG_SUCCESS) {
244 0 : ADIAG_ERR("[%s]trace struct insert to list failed, field name = %s.", entry->name, name);
245 0 : ADIAG_SAFE_FREE(item);
246 : }
247 : }
248 :
249 275 : STATIC INLINE void TraceStructEntryListExit(struct AdiagList *list)
250 : {
251 275 : if (list != NULL) {
252 42 : (void)AdiagListDestroy(list);
253 42 : ADIAG_SAFE_FREE(list);
254 : }
255 275 : }
256 :
257 275 : void TracerStructEntryExit(TraceStructEntry *entry)
258 : {
259 275 : if (entry != NULL) {
260 275 : (void)TraceStructEntryListExit((struct AdiagList *)entry->list);
261 275 : entry->list = NULL;
262 : }
263 275 : }
264 :
265 20 : TraceStructEntry *TraceStructEntryCreate(const char *name)
266 : {
267 20 : TraceStructEntry *en = AdiagMalloc(sizeof(TraceStructEntry));
268 20 : if (en == NULL) {
269 0 : return NULL;
270 : }
271 20 : struct AdiagList *list = TracerStructEntryListInit();
272 20 : en->list = (void *)list;
273 20 : TracerStructEntryName(en, name);
274 20 : return en;
275 : }
276 :
277 20 : void TraceStructEntryDestroy(TraceStructEntry *en)
278 : {
279 20 : if (en != NULL) {
280 20 : TracerStructEntryExit(en);
281 20 : ADIAG_SAFE_FREE(en);
282 : }
283 20 : }
284 :
285 140 : void TraceStructItemFieldSet(TraceStructEntry *en, const char *item, uint8_t type, uint8_t mode, uint16_t len)
286 : {
287 140 : TracerStructItemSet(en, item, type, mode, len);
288 140 : }
289 :
290 60 : void TraceStructItemArraySet(TraceStructEntry *en, const char *item, uint8_t type, uint8_t mode, uint16_t len)
291 : {
292 60 : TracerStructItemSet(en, item, type, mode, len);
293 60 : }
294 :
295 20 : void TraceStructSetAttr(TraceStructEntry *en, uint8_t type, TraceAttr *attr)
296 : {
297 20 : if ((attr != NULL) && (en != NULL) && (type < TRACE_STRUCT_ENTRY_MAX_NUM)) {
298 20 : attr->handle[type] = en;
299 : }
300 20 : }
301 :
302 400 : STATIC bool CheckHandleValid(TraHandle handle)
303 : {
304 400 : if (handle <= 0) {
305 40 : ADIAG_ERR("invalid handle %lld", handle);
306 40 : return false;
307 : }
308 360 : return true;
309 : }
310 :
311 220 : TraStatus TraceBindEvent(TraHandle handle, TraEventHandle eventHandle)
312 : {
313 220 : if (!CheckHandleValid(handle)) {
314 20 : ADIAG_ERR("trace bind event failed");
315 20 : return TRACE_INVALID_PARAM;
316 : }
317 200 : TracerObject *tracer = (TracerObject *)handle;
318 200 : ADIAG_CHK_EXPR_ACTION(tracer == NULL, return TRACE_INVALID_PARAM, "invalid param handle %lld", handle);
319 200 : if (tracer->relatedEventNum >= MAX_RELATED_EVENT_NUM) {
320 0 : ADIAG_ERR("event bound to tracer exceeds the upper limit %u", MAX_RELATED_EVENT_NUM);
321 0 : return TRACE_FAILURE;
322 : }
323 200 : tracer->relatedEvent[tracer->relatedEventNum] = eventHandle;
324 200 : tracer->relatedEventNum++;
325 200 : return TRACE_SUCCESS;
326 : }
327 :
328 180 : TraStatus TraceUnbindEvent(TraHandle handle, TraEventHandle eventHandle)
329 : {
330 180 : if (!CheckHandleValid(handle)) {
331 20 : ADIAG_ERR("trace bind event failed");
332 20 : return TRACE_INVALID_PARAM;
333 : }
334 160 : TracerObject *tracer = (TracerObject *)handle;
335 160 : ADIAG_CHK_EXPR_ACTION(tracer == NULL, return TRACE_INVALID_PARAM, "invalid param handle %lld", handle);
336 160 : if (tracer->relatedEventNum == 0) {
337 0 : ADIAG_ERR("tracer has no related event");
338 0 : return TRACE_FAILURE;
339 : }
340 160 : for (uint8_t i = 0; i < tracer->relatedEventNum; i++) {
341 160 : if (tracer->relatedEvent[i] == eventHandle) {
342 160 : tracer->relatedEvent[i] = tracer->relatedEvent[tracer->relatedEventNum - 1U];
343 160 : tracer->relatedEventNum--;
344 160 : return TRACE_SUCCESS;
345 : }
346 : }
347 0 : ADIAG_ERR("event %lld has not been bound to handle %lld", eventHandle, handle);
348 0 : return TRACE_FAILURE;
349 : }
|