LCOV - code coverage report
Current view: top level - atrace/utrace/tracer - tracer_mgr_operate.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.4 % 247 211
Test Date: 2026-07-28 10:53:44 Functions: 89.5 % 19 17

            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              : }
        

Generated by: LCOV version 2.0-1