LCOV - code coverage report
Current view: top level - atrace/utrace/event - trace_event.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.2 % 209 178
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 17 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 "trace_event.h"
      12              : #include "adiag_print.h"
      13              : #include "adiag_utils.h"
      14              : #include "tracer_core.h"
      15              : 
      16              : #define TRACE_EVENT_THREAD_WAIT_INTERVAL  1000U  // 1000ms
      17              : typedef struct {
      18              :     mmMutex_t mutex;
      19              :     mmCond cond;
      20              :     mmThread tid;
      21              :     int32_t status;
      22              : } ThreadCondInfo;
      23              : 
      24              : typedef struct TraceEventsMgr {
      25              :     struct AdiagList eventList;
      26              :     struct AdiagList saveList;
      27              :     ThreadCondInfo eventProcessThread;
      28              : } TraceEventsMgr;
      29              : 
      30              : STATIC TraceEventsMgr *g_eventsMgr = NULL;
      31              : 
      32         1290 : STATIC bool CheckEventNameValid(const char *name)
      33              : {
      34         1290 :     if (name == NULL) {
      35           40 :         ADIAG_ERR("invalid name NULL");
      36           40 :         return false;
      37              :     }
      38         1250 :     if ((strlen(name) + 1U) > MAX_EVENT_NAME_LENGTH) {
      39           40 :         ADIAG_ERR("size of event name exceeds the upper limit of %u", MAX_EVENT_NAME_LENGTH);
      40           40 :         return false;
      41              :     }
      42         1210 :     return true;
      43              : }
      44              : 
      45      1314514 : STATIC bool CheckEventHandleValid(TraEventHandle eventHandle)
      46              : {
      47      1314514 :     if (eventHandle <= 0) {
      48          260 :         ADIAG_ERR("invalid event handle %lld", eventHandle);
      49          260 :         return false;
      50              :     }
      51      1314254 :     void *data = AdiagListGetNode(&g_eventsMgr->eventList, (TraceEventNode *)eventHandle);
      52      1314254 :     if (data == NULL) {
      53           20 :         ADIAG_ERR("invalid event handle %lld", eventHandle);
      54           20 :         return false;
      55              :     }
      56      1314234 :     return true;
      57              : }
      58              : 
      59          120 : STATIC bool CheckEventAttrValid(const TraceEventAttr *attr)
      60              : {
      61          120 :     if (attr == NULL) {
      62            0 :         ADIAG_ERR("invalid event attr NULL");
      63            0 :         return false;
      64              :     }
      65              :     // limitedNum is of type uint16_t with range [0, 65535], no need to check
      66          120 :     ADIAG_INF("limitedNum %u.", attr->limitedNum);
      67          120 :     return true;
      68              : }
      69              : 
      70      1311036 : STATIC INLINE bool TraceEventReportNumLimited(TraceEventNode *node)
      71              : {
      72      1311036 :     if (node->attr.limitedNum == 0) {
      73          196 :         return false;
      74              :     }
      75      1310840 :     if (node->reportNum < node->attr.limitedNum) {
      76      1310820 :         return false;
      77              :     }
      78           20 :     return true;
      79              : }
      80              : 
      81          560 : STATIC TraStatus TraceEventCompareName(const void *nodeName, const void *name)
      82              : {
      83          560 :     if (nodeName == NULL || name == NULL) {
      84            0 :         return TRACE_FAILURE;
      85              :     }
      86          560 :     if (strcmp((const char *)nodeName, (const char *)name) == 0) {
      87           60 :         return TRACE_SUCCESS;
      88              :     }
      89          500 :     return TRACE_FAILURE;
      90              : }
      91              : 
      92          316 : STATIC TraStatus TraceEventSave(void *arg)
      93              : {
      94          316 :     if (arg == NULL) {
      95            0 :         return TRACE_SUCCESS;
      96              :     }
      97          316 :     TraceEventNode *node = (TraceEventNode *)arg;
      98          316 :     TracerObject *obj = NULL;
      99          316 :     TraStatus ret = TRACE_SUCCESS;
     100          316 :     if (node->relatedTracer != 0) {
     101              :         // process inner event
     102          116 :         if (TracerSaveTracer((Tracer *)node->relatedTracer) != TRACE_SUCCESS) {
     103           44 :             ADIAG_ERR("save trace for event %s failed", node->eventName);
     104           44 :             ret = TRACE_FAILURE;
     105              :         } else {
     106           72 :             ADIAG_DBG("save trace for event %s", node->eventName);
     107              :         }
     108              :     }
     109          516 :     for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
     110          200 :         obj = (TracerObject *)node->relatedTraceObj[i];
     111          200 :         if (TracerSaveObj(obj) != TRACE_SUCCESS) {
     112            0 :             ADIAG_ERR("save trace for event %s handle %s failed", node->eventName, obj->name);
     113            0 :             ret = TRACE_FAILURE;
     114              :         } else {
     115          200 :             ADIAG_DBG("save trace %s for event %s", obj->name, node->eventName);
     116              :         }
     117              :     }
     118          316 :     return ret;
     119              : }
     120              : 
     121              : /**
     122              :  * @brief       init trace event
     123              :  * @return      TraStatus
     124              :  */
     125          930 : TraStatus TraceEventInit(void)
     126              : {
     127          930 :     g_eventsMgr = (TraceEventsMgr *)AdiagMalloc(sizeof(TraceEventsMgr));
     128          930 :     if (g_eventsMgr == NULL) {
     129           20 :         ADIAG_ERR("malloc g_eventsMgr failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     130           20 :         return TRACE_FAILURE;
     131              :     }
     132          910 :     TraStatus ret = AdiagListInit(&g_eventsMgr->eventList);
     133          910 :     if (ret != TRACE_SUCCESS) {
     134           20 :         ADIAG_ERR("init event list failed, ret=%d.", ret);
     135           20 :         AdiagFree(g_eventsMgr);
     136           20 :         g_eventsMgr = NULL;
     137           20 :         return TRACE_FAILURE;
     138              :     }
     139          890 :     ret = AdiagListInit(&g_eventsMgr->saveList);
     140          890 :     if (ret != TRACE_SUCCESS) {
     141           20 :         ADIAG_ERR("init save list failed, ret=%d.", ret);
     142           20 :         (void)AdiagListDestroy(&g_eventsMgr->eventList);
     143           20 :         AdiagFree(g_eventsMgr);
     144           20 :         g_eventsMgr = NULL;
     145           20 :         return TRACE_FAILURE;
     146              :     }
     147          870 :     ADIAG_INF("init trace event successfully");
     148          870 :     return TRACE_SUCCESS;
     149              : }
     150              : 
     151              : /**
     152              :  * @brief       exit trace event
     153              :  * @return      NA
     154              :  */
     155          920 : void TraceEventExit(void)
     156              : {
     157          920 :     if (g_eventsMgr != NULL) {
     158          864 :         (void)AdiagListDestroy(&g_eventsMgr->saveList);
     159          864 :         (void)AdiagListDestroy(&g_eventsMgr->eventList);
     160          864 :         AdiagFree(g_eventsMgr);
     161          864 :         g_eventsMgr = NULL;
     162              :     }
     163          920 :     return;
     164              : }
     165              : 
     166              : /**
     167              :  * @brief       create trace event, add trace event node to eventList
     168              :  * @param [in]  eventName:    name of trace event
     169              :  * @return      eventHandle if create success, TRACE_INVALID_HANDLE otherwise
     170              :  */
     171         1230 : TraEventHandle TraceEventCreate(const char *eventName)
     172              : {
     173         1230 :     if (!CheckEventNameValid(eventName)) {
     174           40 :         ADIAG_ERR("atrace create event failed");
     175           40 :         return TRACE_INVALID_HANDLE;
     176              :     }
     177         1190 :     if (g_eventsMgr == NULL) {
     178            0 :         ADIAG_ERR("g_eventsMgr has not been init successfully.");
     179            0 :         return TRACE_INVALID_HANDLE;
     180              :     }
     181         1190 :     void *data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
     182         1190 :     if (data != NULL) {
     183           40 :         ADIAG_ERR("duplicated trace event name %s", eventName);
     184           40 :         return TRACE_INVALID_HANDLE;
     185              :     }
     186         1150 :     TraceEventNode *node = (TraceEventNode *)AdiagMalloc(sizeof(TraceEventNode));
     187         1150 :     if (node == NULL) {
     188            0 :         ADIAG_ERR("malloc node failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     189            0 :         return TRACE_INVALID_HANDLE;
     190              :     }
     191         1150 :     errno_t err = strcpy_s(node->eventName, sizeof(node->eventName), eventName);
     192         1150 :     if (err != EOK) {
     193            0 :         ADIAG_ERR("strcpy_s event_name [%s] failed, ret : %d", eventName, err);
     194            0 :         AdiagFree(node);
     195            0 :         return TRACE_INVALID_HANDLE;
     196              :     }
     197         1150 :     node->processFunc = TraceEventSave;
     198         1150 :     AdiagStatus ret = AdiagListInsert(&g_eventsMgr->eventList, node);
     199         1150 :     if (ret != ADIAG_SUCCESS) {
     200            0 :         ADIAG_ERR("insert node to event list failed, ret=%d.", ret);
     201            0 :         AdiagFree(node);
     202            0 :         return TRACE_INVALID_HANDLE;
     203              :     }
     204         1150 :     ADIAG_DBG("insert event %s to event list", node->eventName);
     205         1150 :     return (TraEventHandle)node;
     206              : }
     207              : 
     208              : /**
     209              :  * @brief       get event handle by eventName
     210              :  * @param [in]  eventName:    name of trace event
     211              :  * @return      eventHandle if found, TRACE_INVALID_HANDLE otherwise
     212              :  */
     213           60 : TraEventHandle TraceEventGetHandle(const char *eventName)
     214              : {
     215           60 :     if (!CheckEventNameValid(eventName)) {
     216           40 :         ADIAG_ERR("atrace get event handle failed");
     217           40 :         return TRACE_INVALID_HANDLE;
     218              :     }
     219           20 :     void *data = AdiagListForEach(&g_eventsMgr->eventList, TraceEventCompareName, eventName);
     220           20 :     if (data == NULL) {
     221            0 :         return TRACE_INVALID_HANDLE;
     222              :     }
     223           20 :     return (TraEventHandle)data;
     224              : }
     225              : 
     226              : /**
     227              :  * @brief       destroy event handle, process all event in saveList before destroy
     228              :  * @param [in]  eventHandle:    event handle, handle of event node
     229              :  * @return      NA
     230              :  */
     231         1164 : void TraceEventDestroy(TraEventHandle eventHandle)
     232              : {
     233         1164 :     if (!CheckEventHandleValid(eventHandle)) {
     234           60 :         ADIAG_ERR("atrace destroy event failed");
     235           60 :         return;
     236              :     }
     237         1104 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     238         1104 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return, "invalid param eventHandle %lld", eventHandle);
     239         1264 :     for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
     240          160 :         (void)TraceUnbindEvent(node->relatedTraceObj[i], eventHandle);
     241              :     }
     242         1104 :     (void)AdiagListRemoveAll(&g_eventsMgr->saveList, node, TraceEventSave);
     243         1104 :     AdiagStatus ret = AdiagListRemove(&g_eventsMgr->eventList, node);
     244         1104 :     if (ret != ADIAG_SUCCESS) {
     245            0 :         ADIAG_ERR("remove event from event list failed.");
     246              :     } else {
     247         1104 :         ADIAG_DBG("delete event %s from event list", node->eventName);
     248              :     }
     249         1104 :     ADIAG_SAFE_FREE(node);
     250              : }
     251              : 
     252              : /**
     253              :  * @brief       bind tracer to trace event
     254              :  * @param [in]  eventHandle:    event handle, handle of event node
     255              :  * @param [in]  tracer:         tracer handle
     256              :  * @return      TraStatus
     257              :  */
     258          890 : TraStatus TraceEventBindTracer(TraEventHandle eventHandle, TracerHandle tracer)
     259              : {
     260          890 :     if (!CheckEventHandleValid(eventHandle)) {
     261           20 :         ADIAG_ERR("atrace event bind tracer failed");
     262           20 :         return TRACE_INVALID_PARAM;
     263              :     }
     264          870 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     265          870 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
     266              : 
     267          870 :     if (node->relatedTracer != 0) {
     268            0 :         ADIAG_ERR("event %s has been bound to tracer", node->eventName);
     269            0 :         return TRACE_FAILURE;
     270              :     }
     271          870 :     node->relatedTracer = tracer;
     272          870 :     return TRACE_SUCCESS;
     273              : }
     274              : 
     275              : /**
     276              :  * @brief       unbind tracer with trace event
     277              :  * @param [in]  eventHandle:    event handle, handle of event node
     278              :  * @param [in]  tracer:         tracer handle
     279              :  * @return      TraStatus
     280              :  */
     281          884 : TraStatus TraceEventUnbindTracer(TraEventHandle eventHandle, TracerHandle tracer)
     282              : {
     283          884 :     if (!CheckEventHandleValid(eventHandle)) {
     284           20 :         ADIAG_ERR("atrace event bind tracer failed");
     285           20 :         return TRACE_INVALID_PARAM;
     286              :     }
     287          864 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     288          864 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
     289          864 :     if (node->relatedTracer != tracer) {
     290            0 :         ADIAG_ERR("event %s has not been bound to tracer", node->eventName);
     291            0 :         return TRACE_FAILURE;
     292              :     }
     293          864 :     node->relatedTracer = 0;
     294          864 :     return TRACE_SUCCESS;
     295              : }
     296              : 
     297              : /**
     298              :  * @brief       bind trace object to trace event and bind trace event to trace object
     299              :  * @param [in]  eventHandle:    event handle, handle of event node
     300              :  * @param [in]  handle:         trace object handle
     301              :  * @return      TraStatus
     302              :  */
     303          280 : TraStatus TraceEventBindTrace(TraEventHandle eventHandle, TraHandle handle)
     304              : {
     305          280 :     if (!CheckEventHandleValid(eventHandle)) {
     306           80 :         ADIAG_ERR("atrace event bind trace failed");
     307           80 :         return TRACE_INVALID_PARAM;
     308              :     }
     309          200 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     310          200 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
     311          200 :     if (node->relatedTraceObjNum >= MAX_RELATED_TRACER_NUM) {
     312            0 :         ADIAG_ERR("trace bound to event exceeds the upper limit %u", MAX_RELATED_TRACER_NUM);
     313            0 :         return TRACE_FAILURE;
     314              :     }
     315          200 :     TraStatus ret = TraceBindEvent(handle, eventHandle);
     316          200 :     if (ret != TRACE_SUCCESS) {
     317            0 :         return ret;
     318              :     }
     319          200 :     node->relatedTraceObj[node->relatedTraceObjNum] = handle;
     320          200 :     node->relatedTraceObjNum++;
     321          200 :     return TRACE_SUCCESS;
     322              : }
     323              : 
     324              : /**
     325              :  * @brief       unbind trace event with trace object
     326              :  * @param [in]  eventHandle:    event handle, handle of event node
     327              :  * @param [in]  handle:         trace object handle
     328              :  * @return      TraStatus
     329              :  */
     330           60 : TraStatus TraceEventUnbindTrace(TraEventHandle eventHandle, TraHandle handle)
     331              : {
     332           60 :     if (!CheckEventHandleValid(eventHandle)) {
     333           20 :         ADIAG_ERR("atrace event unbind trace failed");
     334           20 :         return TRACE_INVALID_PARAM;
     335              :     }
     336           40 :     ADIAG_CHK_EXPR_ACTION(handle < 0, return TRACE_INVALID_PARAM, "invalid param handle %lld", eventHandle);
     337           40 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     338           40 :     uint8_t j = 0;
     339           80 :     for (uint8_t i = 0; i < node->relatedTraceObjNum; i++) {
     340           40 :         if (node->relatedTraceObj[i] != handle) {
     341            0 :             node->relatedTraceObj[j] = node->relatedTraceObj[i];
     342            0 :             j++;
     343              :         }
     344              :     }
     345           40 :     node->relatedTraceObjNum = j;
     346           40 :     return TRACE_SUCCESS;
     347              : }
     348              : 
     349              : /**
     350              :  * @brief       set event trace attr
     351              :  * @param [in]  eventHandle:    event handle, handle of event node
     352              :  * @param [in]  attr:           event attr
     353              :  * @return      TraStatus
     354              :  */
     355          180 : TraStatus TraceEventSetAttr(TraEventHandle eventHandle, const TraceEventAttr *attr)
     356              : {
     357          180 :     if (!CheckEventHandleValid(eventHandle) || !CheckEventAttrValid(attr)) {
     358           60 :         ADIAG_ERR("atrace event report failed");
     359           60 :         return TRACE_INVALID_PARAM;
     360              :     }
     361          120 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     362          120 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
     363          120 :     errno_t ret = memcpy_s(&node->attr, sizeof(TraceEventAttr), attr, sizeof(TraceEventAttr));
     364          120 :     if (ret != EOK) {
     365            0 :         ADIAG_ERR("memcpy attr failed, ret : %d", ret);
     366            0 :         return TRACE_FAILURE;
     367              :     }
     368          120 :     ADIAG_INF("set trace event attr limitedNum: %hu", node->attr.limitedNum);
     369          120 :     return TRACE_SUCCESS;
     370              : }
     371              : 
     372              : /**
     373              :  * @brief       report trace event and process event
     374              :  * @param [in]  eventHandle:    event handle, handle of event node
     375              :  * @return      TraStatus
     376              :  */
     377      1311056 : TraStatus TraceEventReport(TraEventHandle eventHandle)
     378              : {
     379      1311056 :     if (!CheckEventHandleValid(eventHandle)) {
     380           20 :         ADIAG_ERR("atrace event report failed");
     381           20 :         return TRACE_INVALID_HANDLE;
     382              :     }
     383      1311036 :     TraceEventNode *node = (TraceEventNode *)eventHandle;
     384      1311036 :     ADIAG_CHK_EXPR_ACTION(node == NULL, return TRACE_INVALID_PARAM, "invalid param eventHandle %lld", eventHandle);
     385      1311036 :     if (node->relatedTraceObjNum == 0 && node->relatedTracer == 0) {
     386            0 :         ADIAG_WAR("trace event [%s] has not been bound to tracer, ignored", node->eventName);
     387            0 :         return TRACE_SUCCESS;
     388              :     }
     389      1311036 :     if (TraceEventReportNumLimited(node)) {
     390           20 :         ADIAG_WAR("the number of trace event[%s] reports has reached the upper limit %hu, ignored",
     391              :             node->eventName, node->attr.limitedNum);
     392           20 :         return TRACE_SUCCESS;
     393              :     }
     394      1311016 :     if (node->attr.limitedNum != 0) {
     395      1310820 :         node->reportNum++;  // ensure reportNum will be no more than limitedNum
     396              :     }
     397      1311016 :     TraStatus ret = TraceEventSave(node);
     398      1311016 :     ADIAG_DBG("AtraceEventReport [%s], ret=%d.", node->eventName, ret);
     399      1311016 :     return ret;
     400              : }
        

Generated by: LCOV version 2.0-1