LCOV - code coverage report
Current view: top level - atrace/utrace/trace_client - atrace_client_core.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.4 % 111 87
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 8 8

            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 "atrace_client_core.h"
      12              : #include "atrace_client_communication.h"
      13              : #include "atrace_client_thread.h"
      14              : #include "adiag_print.h"
      15              : #include "trace_attr.h"
      16              : #include "trace_msg.h"
      17              : #include "trace_recorder.h"
      18              : #include "trace_types.h"
      19              : #include "trace_system_api.h"
      20              : 
      21              : #define HOST_AI_DEVID       64
      22              : #define MAX_RETRY_TIME      3
      23              : #define TEN_MILLISECOND     (10 * 1000) // 10 milliseconds
      24              : #define RECV_BUFF_SIZE      (512U * 1024U + (uint32_t)sizeof(TraceEventMsg)) // 512K + head
      25              : 
      26           40 : STATIC void AtraceClientWriteEventLog(char *data, uint32_t len)
      27              : {
      28           40 :     TraceMsgInfo info = { 0 };
      29           40 :     (void)AtraceClientParseEventMsg(data, len, &info);
      30              :     // write to file
      31           40 :     TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, TraceGetPid(), info.eventTime, true };
      32           40 :     TraceFileInfo fileInfo = { 0 };
      33           40 :     fileInfo.tracerName = TRACER_SCHEDULE_NAME;
      34           40 :     fileInfo.objName = info.eventName;
      35           40 :     if (info.saveType == FILE_SAVE_MODE_BIN) {
      36            0 :         fileInfo.suffix = TRACE_FILE_BIN_SUFFIX;
      37              :     } else {
      38           40 :         fileInfo.suffix = TRACE_FILE_TXT_SUFFIX;
      39              :     }
      40           40 :     int32_t fd = -1;
      41           40 :     if (TraceRecorderGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS) {
      42            0 :         ADIAG_ERR("get event fd failed, event name=%s.", info.eventName);
      43            0 :         return;
      44              :     }
      45           40 :     TraStatus ret = TraceRecorderWrite(fd, info.buf, info.bufLen);
      46           40 :     if (ret != TRACE_SUCCESS) {
      47            0 :         ADIAG_ERR("write to file failed, ret = %d, strerr = %s.", ret, strerror(AdiagGetErrorCode()));
      48              :     }
      49           40 :     TraceClose(&fd);
      50              : }
      51              : 
      52          180 : STATIC void AtraceClientRecvAndWrite(int32_t devId, int32_t timeout, void **handle)
      53              : {
      54          180 :     char *data = (char *)AdiagMalloc(RECV_BUFF_SIZE);
      55          180 :     if (data == NULL) {
      56            0 :         ADIAG_ERR("malloc buffer failed, devId=%d.", devId);
      57            0 :         return;
      58              :     }
      59          180 :     uint32_t bufLen = 0;
      60          180 :     int32_t retryTime = 0;
      61          180 :     TraStatus ret = TRACE_FAILURE;
      62          180 :     int32_t recvTimeout = timeout / MAX_RETRY_TIME;
      63        16700 :     while (retryTime < MAX_RETRY_TIME) {
      64        16540 :         if (!AtraceClientIsHandleValid(*handle)) { // handle is invalid
      65            0 :             AtraceClientReleaseHandle(handle);
      66            0 :             if (AtraceThreadGetStatus(devId) == THREAD_STATUS_WAIT_EXIT) {
      67            0 :                 break;
      68              :             }
      69            0 :             ret = AtraceClientCreateLongLink(devId, timeout, handle);
      70            0 :             if (ret == TRACE_SUCCESS) {
      71            0 :                 continue;
      72              :             }
      73            0 :             (void)usleep(TEN_MILLISECOND); // sleep 10ms
      74            0 :             continue;
      75              :         }
      76        16540 :         bufLen = RECV_BUFF_SIZE;
      77        16540 :         ret = AtraceClientRecv(*handle, (char **)&data, &bufLen, recvTimeout);
      78        16540 :         if (AtraceThreadGetStatus(devId) == THREAD_STATUS_WAIT_EXIT) {
      79          480 :             retryTime++;
      80              :         }
      81        16540 :         if ((ret != TRACE_SUCCESS) || (bufLen == 0U)) {
      82        16460 :             (void)usleep(TEN_MILLISECOND); // sleep 10ms
      83        16460 :             continue;
      84              :         }
      85              : 
      86           80 :         if (AtraceClientIsEventMsg(data, bufLen)) {
      87           40 :             ADIAG_DBG("atrace client receive event msg, buffer len = %u bytes.", bufLen);
      88           40 :             retryTime = 0;
      89              :             // write to file
      90           40 :             AtraceClientWriteEventLog(data, bufLen);
      91           40 :         } else if (AtraceClientIsEndMsg(data, bufLen)) {
      92           20 :             ADIAG_RUN_INF("receive end msg, devId=%d.", devId);
      93           20 :             break;
      94              :         } else {
      95           20 :             ADIAG_ERR("message is invalid, devId=%d.", devId);
      96              :         }
      97              :     }
      98          180 :     ADIAG_SAFE_FREE(data);
      99              : }
     100              : 
     101              : /**
     102              :  * @brief       : atrace client thread run function
     103              :  * @param [in]  : pArgs          pointer of thread args
     104              :  * @return      : NA
     105              :  */
     106          200 : STATIC void* AtraceClientRecvThread(void *pArgs)
     107              : {
     108          200 :     if (pArgs == NULL) {
     109            0 :         ADIAG_ERR("args is null.");
     110            0 :         return NULL;
     111              :     }
     112          200 :     if (TraceSetThreadName("TraceClientRecv") != TRACE_SUCCESS) {
     113           20 :         ADIAG_WAR("can not set thread name(TraceClientRecv) but continue.");
     114              :     }
     115          200 :     const int32_t devId = ((TraceThreadArgs *)pArgs)->devId;
     116              : 
     117          200 :     int32_t timeout = TraceGetTimeout();
     118          200 :     void *handle = NULL;
     119          200 :     TraStatus ret = AtraceClientCreateLongLink(devId, timeout, &handle);
     120          200 :     if (ret != TRACE_SUCCESS) {
     121           20 :         ADIAG_ERR("create long link failed, devId=%d.", devId);
     122           20 :         return NULL;
     123              :     }
     124          180 :     const int32_t timeReserve = 1000; // 1s for receive thread waiting device timeout exit
     125          180 :     AtraceClientRecvAndWrite(devId, timeout + timeReserve, &handle);
     126          180 :     AtraceClientReleaseHandle(&handle);
     127          180 :     ADIAG_RUN_INF("atrace receive thread exited, devId=%d.", devId);
     128          180 :     return NULL;
     129              : }
     130              : 
     131          240 : TraStatus AtraceClientStart(int32_t devId)
     132              : {
     133          240 :     if ((devId >= HOST_MAX_DEV_NUM) || (devId < 0)) {
     134           20 :         ADIAG_ERR("atrace client start failed, device id [%d] is invalid.", devId);
     135           20 :         return TRACE_INVALID_PARAM;
     136              :     }
     137          220 :     if (devId == HOST_AI_DEVID) {
     138            0 :         ADIAG_INF("devId[%d] no need to create a thread.", devId);
     139            0 :         return TRACE_SUCCESS;
     140              :     }
     141              : 
     142          220 :     if (AtraceThreadSingleTask(devId)) {
     143            0 :         ADIAG_RUN_INF("thread has been started, devId=%d.", devId);
     144            0 :         return TRACE_SUCCESS;
     145              :     }
     146              : 
     147          220 :     TraStatus ret = AtraceClientSendHello(devId);
     148          220 :     if (ret != TRACE_SUCCESS) {
     149           20 :         ADIAG_WAR("can not send hello, devId=%d.", devId);
     150           20 :         return TRACE_UNSUPPORTED;
     151              :     }
     152              :     // create thread to receive device trace log
     153          200 :     TraceThreadArgs args = { devId };
     154          200 :     ret = AtraceThreadCreate(devId, &args, AtraceClientRecvThread);
     155          200 :     if (ret != TRACE_SUCCESS) {
     156            0 :         ADIAG_ERR("create thread failed, devId=%d, ret=%d.", devId, ret);
     157            0 :         return TRACE_FAILURE;
     158              :     }
     159              : 
     160          200 :     ADIAG_RUN_INF("start to receive device[%d] trace log.", devId);
     161          200 :     return TRACE_SUCCESS;
     162              : }
     163              : 
     164          200 : void AtraceClientStop(int32_t devId)
     165              : {
     166          200 :     if ((devId >= HOST_MAX_DEV_NUM) || (devId < 0)) {
     167           20 :         ADIAG_ERR("stop report failed, device id is invalid, devId=%d.", devId);
     168           20 :         return;
     169              :     }
     170          180 :     if (devId == HOST_AI_DEVID) {
     171            0 :         ADIAG_INF("devId[%d] no need to stop a thread.", devId);
     172            0 :         return;
     173              :     }
     174              : 
     175          180 :     AtraceThreadRelease(devId, AtraceClientSendEnd, true);
     176          180 :     ADIAG_RUN_INF("stop to receive device[%d] trace log.", devId);
     177              : }
     178              : 
     179          901 : TraStatus AtraceClientInit(void)
     180              : {
     181              :     // init thread pool
     182          901 :     TraStatus ret = AtraceThreadPoolInit();
     183          901 :     ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return ret, "init thread pool failed.");
     184              : 
     185          901 :     ADIAG_INF("init atrace client successfully.");
     186          901 :     return TRACE_SUCCESS;
     187              : }
     188              : 
     189              : /**
     190              :  * @brief       : stub stop function used in process-exit destructor.
     191              :  *                Skips sending [end] over HDC because runtime/HDC resources may
     192              :  *                already be torn down (e.g. when Runtime::DeviceRelease is bypassed
     193              :  *                in isExiting_ path). Sending [end] there would re-create an HDC
     194              :  *                session and trigger hdc_ub_connect/register_urma_seg failures.
     195              :  *                Recv threads still exit safely via THREAD_STATUS_WAIT_EXIT set by
     196              :  *                AtraceThreadRelease.
     197              :  */
     198           80 : STATIC int32_t AtraceClientExitNoSend(int32_t devId)
     199              : {
     200              :     (void)devId;
     201           80 :     return TRACE_SUCCESS;
     202              : }
     203              : 
     204          951 : void AtraceClientExit(void)
     205              : {
     206              :     // release all receive thread; do not send [end] in destructor path
     207          951 :     AtraceThreadPoolExit(AtraceClientExitNoSend);
     208          951 : }
        

Generated by: LCOV version 2.0-1