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