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-08-31 10:07:06 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          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              : }
        

Generated by: LCOV version 2.0-1