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_mgr_operate.h"
12 : #include "tracer_mgr_operate_inner.h"
13 : #include "trace_attr.h"
14 : #include "stacktrace_dumper.h"
15 : #include "adiag_utils.h"
16 : #include "trace_recorder.h"
17 : #include "adiag_print.h"
18 : #include "trace_system_api.h"
19 :
20 : #define SCHEDULE_RB_SIZE 1024U
21 : #define SCHEDULE_SIGNAL_NUM 12U
22 : #define TRACE_INNER_EVENT_NAME "trace_inner_event"
23 :
24 : typedef struct TracerDeleteNode {
25 : uint64_t interval;
26 : intptr_t handle;
27 : } TracerDeleteNode;
28 :
29 : typedef struct TracerExitNode {
30 : char objName[MAX_OBJECT_NAME_LENGTH];
31 : void* data;
32 : } TracerExitNode;
33 :
34 922 : TraObjHandle TracerScheduleObjCreate(Tracer* tracer, const char* name, const TraceAttr* attr)
35 : {
36 922 : (void)AdiagLockGet(&tracer->mgr->lock);
37 1146 : for (int32_t i = 0; i < MAX_OBJECT_NUM; i++) {
38 1146 : TracerObject* obj = &tracer->mgr->obj[i];
39 1146 : if (obj->status == (int32_t)OBJ_STATUS_INIT) {
40 922 : RbLog* data = TraceRbLogCreate(name, attr);
41 922 : if (data == NULL) {
42 48 : (void)AdiagLockRelease(&tracer->mgr->lock);
43 48 : return TRACE_INVALID_HANDLE;
44 : }
45 874 : size_t len = strlen(name);
46 874 : if (len >= MAX_OBJECT_NAME_LENGTH) {
47 24 : ADIAG_ERR("name len(%zu bytes) is invalid, must less then %u bytes", len, MAX_OBJECT_NAME_LENGTH);
48 24 : (void)AdiagLockRelease(&tracer->mgr->lock);
49 24 : TraceRbLogDestroy(data);
50 24 : return TRACE_INVALID_HANDLE;
51 : }
52 850 : int32_t ret = strncpy_s(obj->name, MAX_OBJECT_NAME_LENGTH, name, len);
53 850 : if (ret != 0) {
54 0 : (void)AdiagLockRelease(&tracer->mgr->lock);
55 0 : TraceRbLogDestroy(data);
56 0 : return TRACE_INVALID_HANDLE;
57 : }
58 850 : obj->data = (void*)data;
59 850 : obj->status = OBJ_STATUS_WORKING;
60 850 : obj->pid = TraceGetPid();
61 850 : obj->exitSave = attr->exitSave;
62 850 : obj->tracerType = TRACER_TYPE_SCHEDULE;
63 850 : obj->noLock = attr->noLock;
64 850 : (void)AdiagLockRelease(&tracer->mgr->lock);
65 850 : ADIAG_RUN_INF(
66 : "create object %s successfully, exitSave(%s), noLock(%s).", name, (attr->exitSave) ? "true" : "false",
67 : (attr->noLock == TRACE_LOCK_FREE) ? "true" : "false");
68 850 : return (TraObjHandle)obj;
69 : }
70 : }
71 0 : (void)AdiagLockRelease(&tracer->mgr->lock);
72 0 : return TRACE_INVALID_HANDLE;
73 : }
74 :
75 72 : TraObjHandle TracerScheduleObjGet(Tracer* tracer, const char* name)
76 : {
77 72 : (void)AdiagLockGet(&tracer->mgr->lock);
78 2472 : for (int32_t i = 0; i < MAX_OBJECT_NUM; i++) {
79 2448 : if ((strncmp(name, tracer->mgr->obj[i].name, MAX_OBJECT_NAME_LENGTH) == 0) &&
80 48 : (tracer->mgr->obj[i].status == (int32_t)OBJ_STATUS_WORKING)) {
81 48 : (void)AdiagLockRelease(&tracer->mgr->lock);
82 48 : return (TraObjHandle)&tracer->mgr->obj[i];
83 : }
84 : }
85 24 : (void)AdiagLockRelease(&tracer->mgr->lock);
86 24 : return TRACE_INVALID_HANDLE;
87 : }
88 :
89 0 : TraStatus TracerScheduleObjSubmit(
90 : Tracer* tracer, TraObjHandle handle, uint8_t bufferType, const void* buffer, uint32_t bufSize)
91 : {
92 0 : TracerObject* obj = &tracer->mgr->obj[handle];
93 0 : int32_t status = obj->status;
94 0 : if (status != (int32_t)OBJ_STATUS_WORKING) {
95 0 : ADIAG_ERR("object is not working, status=%d.", status);
96 0 : return TRACE_FAILURE;
97 : }
98 0 : TraStatus ret = TraceRbLogWriteRbMsg((RbLog*)obj->data, bufferType, (const char*)buffer, bufSize);
99 0 : return ret;
100 : }
101 :
102 302 : STATIC TraStatus TraceExitCompareName(const void* nodeName, const void* name)
103 : {
104 302 : if (nodeName == NULL || name == NULL) {
105 0 : return TRACE_FAILURE;
106 : }
107 302 : if (strcmp((const char*)nodeName, (const char*)name) == 0) {
108 162 : return TRACE_SUCCESS;
109 : }
110 140 : return TRACE_FAILURE;
111 : }
112 :
113 : /**
114 : * @brief push node to exit list
115 : * @param [in] tracer: pointer of tracer
116 : * @param [in] obj: pointer of object
117 : * @return TraStatus
118 : */
119 264 : STATIC TraStatus TracerSchedulePushExitList(Tracer* tracer, TracerObject* obj)
120 : {
121 264 : if (obj->pid != TraceGetPid()) {
122 0 : return TRACE_FAILURE;
123 : }
124 264 : ADIAG_CHK_EXPR_ACTION(obj->data == NULL, return TRACE_FAILURE, "object is invalid.");
125 :
126 264 : TracerExitNode* node = (TracerExitNode*)AdiagMalloc(sizeof(TracerExitNode));
127 264 : ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_FAILURE, "malloc exit node failed.");
128 :
129 264 : errno_t err = strncpy_s(node->objName, MAX_OBJECT_NAME_LENGTH, obj->name, strlen(obj->name));
130 264 : if (err != 0) {
131 0 : AdiagFree(node);
132 0 : return TRACE_FAILURE;
133 : }
134 :
135 264 : node->data = obj->data;
136 264 : void* data = AdiagListForEach(&tracer->mgr->exitList, TraceExitCompareName, (const void*)node->objName);
137 264 : if (data != NULL) {
138 162 : ADIAG_INF("object[%s] has been inserted to exit list.", node->objName);
139 162 : TracerExitNode* oldNode = (TracerExitNode*)data;
140 162 : (void)AdiagListRemove(&tracer->mgr->exitList, data);
141 162 : TraceRbLogDestroy((RbLog*)oldNode->data);
142 162 : AdiagFree(data);
143 : }
144 264 : AdiagStatus ret = AdiagListInsert(&tracer->mgr->exitList, (void*)node);
145 264 : if (ret != ADIAG_SUCCESS) {
146 0 : AdiagFree(node);
147 0 : ADIAG_ERR("insert node to exit list failed, ret=%d.", ret);
148 0 : return TRACE_FAILURE;
149 : }
150 264 : obj->data = NULL;
151 264 : return TRACE_SUCCESS;
152 : }
153 :
154 : /**
155 : * @brief save data to exit file
156 : * @param [in] objName: object name
157 : * @param [in] data: data
158 : * @param [in] timeStamp: exit dir time
159 : * @return TraStatus
160 : */
161 100 : STATIC TraStatus TracerScheduleExitSave(const char* objName, void* data, uint64_t timeStamp)
162 : {
163 100 : char dirTime[TIMESTAMP_MAX_LENGTH] = {0};
164 100 : TraStatus ret = TimestampToFileStr(timeStamp, dirTime, TIMESTAMP_MAX_LENGTH);
165 100 : ADIAG_CHK_EXPR_ACTION(
166 : ret != TRACE_SUCCESS, return TRACE_FAILURE, "get time string failed, ret=%d, strerr=%s.", ret,
167 : strerror(AdiagGetErrorCode()));
168 :
169 100 : struct RbLog* newRb = NULL;
170 100 : ret = TraceRbLogGetCopyOfRingBuffer(&newRb, (RbLog*)data);
171 100 : ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return TRACE_FAILURE, "get copy of ring buffer failed.");
172 :
173 98 : if (TracerScheduleCheckListEmpty(newRb)) {
174 49 : TracerScheduleSaveObjData(newRb, dirTime, TRACER_EVENT_EXIT, objName);
175 : } else {
176 49 : TracerScheduleSaveObjBinData(newRb, dirTime, TRACER_EVENT_EXIT, objName);
177 539 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
178 490 : (void)AdiagListDestroy(newRb->entry[i].list);
179 490 : ADIAG_SAFE_FREE(newRb->entry[i].list);
180 : }
181 : }
182 98 : ADIAG_SAFE_FREE(newRb);
183 98 : return TRACE_SUCCESS;
184 : }
185 :
186 : /**
187 : * @brief pop node from exit list
188 : * @param [in] tracer: pointer of tracer
189 : * @return NA
190 : */
191 976 : STATIC void TracerSchedulePopExitList(Tracer* tracer)
192 : {
193 976 : uint64_t exitTime = GetRealTime();
194 976 : TracerExitNode* node = (TracerExitNode*)AdiagListTakeOut(&tracer->mgr->exitList);
195 1076 : while (node != NULL) {
196 100 : TraStatus ret = TracerScheduleExitSave(node->objName, node->data, exitTime);
197 100 : if (ret != TRACE_SUCCESS) {
198 2 : ADIAG_WAR("can not save obj[%s] when exit, ret=%d.", node->objName, ret);
199 : }
200 100 : TraceRbLogDestroy((RbLog*)node->data);
201 100 : node->data = NULL;
202 100 : ADIAG_SAFE_FREE(node);
203 100 : node = (TracerExitNode*)AdiagListTakeOut(&tracer->mgr->exitList);
204 : }
205 976 : }
206 :
207 824 : STATIC TraStatus TracerScheduleObjProbe(Tracer* tracer)
208 : {
209 : // 获取超时的时间的obj
210 824 : (void)AdiagLockGet(&tracer->mgr->lock);
211 824 : TracerDeleteNode* node = (TracerDeleteNode*)AdiagListTakeOut(&tracer->mgr->deleteList);
212 824 : if (node != NULL) {
213 824 : TracerObject* obj = (TracerObject*)(node->handle);
214 824 : (void)memset_s(obj->name, MAX_OBJECT_NAME_LENGTH, 0, MAX_OBJECT_NAME_LENGTH);
215 824 : obj->status = OBJ_STATUS_INIT;
216 824 : TraceRbLogDestroy((RbLog*)obj->data);
217 824 : obj->data = NULL;
218 824 : ADIAG_SAFE_FREE(node);
219 : }
220 824 : (void)AdiagLockRelease(&tracer->mgr->lock);
221 824 : return TRACE_SUCCESS;
222 : }
223 :
224 872 : TraStatus TracerScheduleObjDestroy(Tracer* tracer, TraObjHandle handle)
225 : {
226 872 : TracerObject* obj = (TracerObject*)handle;
227 872 : if (obj == NULL) {
228 0 : return TRACE_FAILURE;
229 : }
230 872 : (void)AdiagLockGet(&tracer->mgr->lock);
231 872 : obj->status = OBJ_STATUS_IDLE;
232 872 : if (obj->exitSave) {
233 264 : (void)TracerSchedulePushExitList(tracer, obj);
234 : }
235 872 : TracerDeleteNode* node = (TracerDeleteNode*)AdiagMalloc(sizeof(TracerDeleteNode));
236 872 : if (node == NULL) {
237 24 : ADIAG_ERR("malloc delete node failed.");
238 24 : (void)AdiagLockRelease(&tracer->mgr->lock);
239 24 : return TRACE_FAILURE;
240 : }
241 848 : node->interval = 0; // get time stamp to calculate the time difference
242 848 : node->handle = handle;
243 848 : AdiagStatus ret = AdiagListInsert(&(tracer->mgr->deleteList), (void*)node);
244 848 : if (ret != ADIAG_SUCCESS) {
245 24 : AdiagFree(node);
246 24 : ADIAG_ERR("insert node to list failed.");
247 24 : (void)AdiagLockRelease(&tracer->mgr->lock);
248 24 : return TRACE_FAILURE;
249 : }
250 824 : ADIAG_RUN_INF("destroy object %s, exitSave(%s).", obj->name, (obj->exitSave) ? "true" : "false");
251 824 : (void)AdiagLockRelease(&tracer->mgr->lock);
252 :
253 : // create thread to execute probe
254 824 : (void)TracerScheduleObjProbe(tracer);
255 :
256 824 : return TRACE_SUCCESS;
257 : }
258 :
259 489 : bool TracerScheduleCheckListEmpty(struct RbLog* newRb)
260 : {
261 489 : if (newRb == NULL) {
262 0 : return true;
263 : }
264 489 : bool isListNull = true;
265 4629 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
266 4215 : if ((newRb->entry[i].list != NULL) && (!ListEmpty(&((struct AdiagList*)newRb->entry[i].list)->list))) {
267 75 : isListNull = false;
268 75 : break;
269 : }
270 : }
271 489 : return isListNull;
272 : }
273 :
274 8068 : STATIC TraStatus TracerScheduleSaveObject(TracerObject* obj, const char* timestamp)
275 : {
276 8068 : if ((obj->status != (int32_t)OBJ_STATUS_WORKING) || (obj->pid != TraceGetPid())) {
277 7697 : return TRACE_SUCCESS;
278 : }
279 :
280 371 : struct RbLog* newRb = NULL;
281 371 : TraStatus ret = TraceRbLogGetCopyOfRingBuffer(&newRb, (RbLog*)obj->data);
282 371 : if (ret != TRACE_SUCCESS) {
283 48 : ADIAG_ERR("get copy of ring buffer failed.");
284 48 : return TRACE_FAILURE;
285 : }
286 323 : if (TracerScheduleCheckListEmpty(newRb)) {
287 320 : TracerScheduleSaveObjData(newRb, timestamp, TRACER_SCHEDULE_NAME, obj->name);
288 : } else {
289 3 : TracerScheduleSaveObjBinData(newRb, timestamp, TRACER_SCHEDULE_NAME, obj->name);
290 33 : for (uint32_t entryIndex = 0; entryIndex < TRACE_STRUCT_ENTRY_MAX_NUM; entryIndex++) {
291 30 : (void)AdiagListDestroy(newRb->entry[entryIndex].list);
292 30 : ADIAG_SAFE_FREE(newRb->entry[entryIndex].list);
293 : }
294 : }
295 323 : ADIAG_SAFE_FREE(newRb);
296 323 : return TRACE_SUCCESS;
297 : }
298 :
299 346 : TraStatus TracerScheduleSave(Tracer* tracer, TracerObject* obj)
300 : {
301 346 : char timestamp[TIMESTAMP_MAX_LENGTH] = {0};
302 346 : TraStatus ret = TimestampToFileStr(GetRealTime(), timestamp, TIMESTAMP_MAX_LENGTH);
303 346 : ADIAG_CHK_EXPR_ACTION(
304 : ret != TRACE_SUCCESS, return TRACE_FAILURE, "get time string failed, ret=%d, strerr=%s.", ret,
305 : strerror(AdiagGetErrorCode()));
306 :
307 346 : (void)AdiagLockGet(&tracer->mgr->lock);
308 346 : if (obj != NULL) {
309 220 : ret = TracerScheduleSaveObject(obj, timestamp);
310 220 : if (ret != TRACE_SUCCESS) {
311 0 : (void)AdiagLockRelease(&tracer->mgr->lock);
312 0 : return TRACE_FAILURE;
313 : }
314 : } else {
315 7926 : for (int32_t i = 0; i < MAX_OBJECT_NUM; i++) {
316 7848 : ret = TracerScheduleSaveObject(&tracer->mgr->obj[i], timestamp);
317 7848 : if (ret != TRACE_SUCCESS) {
318 48 : (void)AdiagLockRelease(&tracer->mgr->lock);
319 48 : return TRACE_FAILURE;
320 : }
321 : }
322 : }
323 298 : (void)AdiagLockRelease(&tracer->mgr->lock);
324 298 : return TRACE_SUCCESS;
325 : }
326 :
327 0 : TraStatus TracerScheduleReport(Tracer* tracer, TracerObject* obj)
328 : {
329 : // create thread to save
330 0 : return TracerScheduleSave(tracer, obj);
331 : }
332 :
333 : /**
334 : * @brief add func to signal list
335 : * @param [in] data: data
336 : * @param [in] timeStamp: dir timestamp
337 : * @return TraStatus
338 : */
339 131 : STATIC TraStatus TracerScheduleSignalCallback(void* data, uint64_t timeStamp)
340 : {
341 131 : if (data == NULL) {
342 0 : return TRACE_INVALID_PARAM;
343 : }
344 :
345 131 : Tracer* tracer = (Tracer*)data;
346 131 : return TracerScheduleSafeSave(tracer, timeStamp);
347 : }
348 :
349 982 : STATIC TraStatus TracerScheduleEventInit(Tracer* tracer)
350 : {
351 : // 注册信号量,回调实现安全save
352 982 : TraStatus ret = TraceDumperSetCallback(TracerScheduleSignalCallback, (void*)tracer);
353 982 : ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return ret, "schedule tracer set callback failed, ret=%d.", ret);
354 :
355 : // add inner event
356 982 : tracer->mgr->innerEvent = TraceEventCreate(TRACE_INNER_EVENT_NAME);
357 982 : if (tracer->mgr->innerEvent < 0) {
358 0 : ADIAG_ERR("create trace inner event failed, ret=%lld", tracer->mgr->innerEvent);
359 0 : return TRACE_FAILURE;
360 : }
361 982 : ret = TraceEventBindTracer(tracer->mgr->innerEvent, (TracerHandle)tracer);
362 982 : if (ret != TRACE_SUCCESS) {
363 0 : ADIAG_ERR("bind inner event to tracer failed");
364 0 : TraceEventDestroy(tracer->mgr->innerEvent);
365 0 : tracer->mgr->innerEvent = 0;
366 0 : return TRACE_FAILURE;
367 : }
368 982 : return TRACE_SUCCESS;
369 : }
370 :
371 982 : TraStatus TracerScheduleInit(Tracer* tracer)
372 : {
373 982 : tracer->mgr->ouputType = 0;
374 982 : tracer->mgr->rbType = 0;
375 982 : (void)AdiagLockInit(&tracer->mgr->lock);
376 982 : TraStatus ret = AdiagListInit(&tracer->mgr->deleteList);
377 982 : ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return TRACE_FAILURE, "tracer init delete list failed, ret=%d.", ret);
378 982 : ret = AdiagListInit(&tracer->mgr->exitList);
379 982 : ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return TRACE_FAILURE, "tracer init exit list failed, ret=%d.", ret);
380 :
381 982 : ret = TracerScheduleEventInit(tracer);
382 982 : ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return TRACE_FAILURE, "tracer init event failed, ret=%d.", ret);
383 :
384 982 : return TRACE_SUCCESS;
385 : }
386 :
387 976 : STATIC void TracerScheduleEventExit(Tracer* tracer)
388 : {
389 976 : (void)TraceEventUnbindTracer(tracer->mgr->innerEvent, (TracerHandle)tracer);
390 976 : TraceEventDestroy(tracer->mgr->innerEvent);
391 976 : tracer->mgr->innerEvent = 0;
392 976 : }
393 :
394 : /**
395 : * @brief destroy all object when exit
396 : * @param [in] tracer: pointer of tracer
397 : * @return NA
398 : */
399 976 : STATIC void TracerScheduleObjDestroyAll(Tracer* tracer)
400 : {
401 976 : (void)AdiagLockGet(&tracer->mgr->lock);
402 98576 : for (int32_t i = 0; i < MAX_OBJECT_NUM; i++) {
403 97600 : TracerObject* obj = &tracer->mgr->obj[i];
404 97600 : if (obj->status != (int32_t)OBJ_STATUS_INIT) {
405 23 : obj->status = (int32_t)OBJ_STATUS_INIT;
406 23 : if (obj->exitSave) {
407 0 : (void)TracerSchedulePushExitList(tracer, obj);
408 : }
409 23 : (void)memset_s(obj->name, MAX_OBJECT_NAME_LENGTH, 0, MAX_OBJECT_NAME_LENGTH);
410 23 : TraceRbLogDestroy((RbLog*)obj->data);
411 23 : obj->data = NULL;
412 : }
413 : }
414 976 : TracerSchedulePopExitList(tracer);
415 976 : (void)AdiagLockRelease(&tracer->mgr->lock);
416 976 : }
417 :
418 976 : TraStatus TracerScheduleExit(Tracer* tracer)
419 : {
420 976 : TracerScheduleObjDestroyAll(tracer);
421 976 : TracerScheduleEventExit(tracer);
422 976 : AdiagStatus ret = AdiagListDestroy(&tracer->mgr->deleteList);
423 976 : if (ret != ADIAG_SUCCESS) {
424 0 : ADIAG_ERR("destroy delete list failed, ret=%d.", ret);
425 : }
426 976 : ret = AdiagListDestroy(&tracer->mgr->exitList);
427 976 : if (ret != ADIAG_SUCCESS) {
428 0 : ADIAG_ERR("destroy exit list failed, ret=%d.", ret);
429 : }
430 :
431 976 : (void)AdiagLockDestroy(&tracer->mgr->lock);
432 976 : return ret;
433 : }
|