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-08-31 10:07:06 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           44 : STATIC void AtraceClientWriteEventLog(char* data, uint32_t len)
      27              : {
      28           44 :     TraceMsgInfo info = {0};
      29           44 :     (void)AtraceClientParseEventMsg(data, len, &info);
      30              :     // write to file
      31           44 :     TraceDirInfo dirInfo = {TRACER_SCHEDULE_NAME, TraceGetPid(), info.eventTime, true};
      32           44 :     TraceFileInfo fileInfo = {0};
      33           44 :     fileInfo.tracerName = TRACER_SCHEDULE_NAME;
      34           44 :     fileInfo.objName = info.eventName;
      35           44 :     if (info.saveType == FILE_SAVE_MODE_BIN) {
      36            0 :         fileInfo.suffix = TRACE_FILE_BIN_SUFFIX;
      37              :     } else {
      38           44 :         fileInfo.suffix = TRACE_FILE_TXT_SUFFIX;
      39              :     }
      40           44 :     int32_t fd = -1;
      41           44 :     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           44 :     TraStatus ret = TraceRecorderWrite(fd, info.buf, info.bufLen);
      46           44 :     if (ret != TRACE_SUCCESS) {
      47            0 :         ADIAG_ERR("write to file failed, ret = %d, strerr = %s.", ret, strerror(AdiagGetErrorCode()));
      48              :     }
      49           44 :     TraceClose(&fd);
      50              : }
      51              : 
      52          198 : STATIC void AtraceClientRecvAndWrite(int32_t devId, int32_t timeout, void** handle)
      53              : {
      54          198 :     char* data = (char*)AdiagMalloc(RECV_BUFF_SIZE);
      55          198 :     if (data == NULL) {
      56            0 :         ADIAG_ERR("malloc buffer failed, devId=%d.", devId);
      57            0 :         return;
      58              :     }
      59          198 :     uint32_t bufLen = 0;
      60          198 :     int32_t retryTime = 0;
      61          198 :     TraStatus ret = TRACE_FAILURE;
      62          198 :     int32_t recvTimeout = timeout / MAX_RETRY_TIME;
      63        18414 :     while (retryTime < MAX_RETRY_TIME) {
      64        18238 :         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        18238 :         bufLen = RECV_BUFF_SIZE;
      77        18238 :         ret = AtraceClientRecv(*handle, (char**)&data, &bufLen, recvTimeout);
      78        18238 :         if (AtraceThreadGetStatus(devId) == THREAD_STATUS_WAIT_EXIT) {
      79          528 :             retryTime++;
      80              :         }
      81        18238 :         if ((ret != TRACE_SUCCESS) || (bufLen == 0U)) {
      82        18150 :             (void)usleep(TEN_MILLISECOND); // sleep 10ms
      83        18150 :             continue;
      84              :         }
      85              : 
      86           88 :         if (AtraceClientIsEventMsg(data, bufLen)) {
      87           44 :             ADIAG_DBG("atrace client receive event msg, buffer len = %u bytes.", bufLen);
      88           44 :             retryTime = 0;
      89              :             // write to file
      90           44 :             AtraceClientWriteEventLog(data, bufLen);
      91           44 :         } else if (AtraceClientIsEndMsg(data, bufLen)) {
      92           22 :             ADIAG_RUN_INF("receive end msg, devId=%d.", devId);
      93           22 :             break;
      94              :         } else {
      95           22 :             ADIAG_ERR("message is invalid, devId=%d.", devId);
      96              :         }
      97              :     }
      98          198 :     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          220 : STATIC void* AtraceClientRecvThread(void* pArgs)
     107              : {
     108          220 :     if (pArgs == NULL) {
     109            0 :         ADIAG_ERR("args is null.");
     110            0 :         return NULL;
     111              :     }
     112          220 :     if (TraceSetThreadName("TraceClientRecv") != TRACE_SUCCESS) {
     113           22 :         ADIAG_WAR("can not set thread name(TraceClientRecv) but continue.");
     114              :     }
     115          220 :     const int32_t devId = ((TraceThreadArgs*)pArgs)->devId;
     116              : 
     117          220 :     int32_t timeout = TraceGetTimeout();
     118          220 :     void* handle = NULL;
     119          220 :     TraStatus ret = AtraceClientCreateLongLink(devId, timeout, &handle);
     120          220 :     if (ret != TRACE_SUCCESS) {
     121           22 :         ADIAG_WAR("create long link failed, devId=%d.", devId);
     122           22 :         return NULL;
     123              :     }
     124          198 :     const int32_t timeReserve = 2000; // 2s for receive thread waiting device timeout exit
     125          198 :     AtraceClientRecvAndWrite(devId, timeout + timeReserve, &handle);
     126          198 :     AtraceClientReleaseHandle(&handle);
     127          198 :     ADIAG_RUN_INF("atrace receive thread exited, devId=%d.", devId);
     128          198 :     return NULL;
     129              : }
     130              : 
     131          264 : TraStatus AtraceClientStart(int32_t devId)
     132              : {
     133          264 :     if ((devId >= HOST_MAX_DEV_NUM) || (devId < 0)) {
     134           22 :         ADIAG_ERR("atrace client start failed, device id [%d] is invalid.", devId);
     135           22 :         return TRACE_INVALID_PARAM;
     136              :     }
     137          242 :     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          242 :     if (AtraceThreadSingleTask(devId)) {
     143            0 :         ADIAG_RUN_INF("thread has been started, devId=%d.", devId);
     144            0 :         return TRACE_SUCCESS;
     145              :     }
     146              : 
     147          242 :     TraStatus ret = AtraceClientSendHello(devId);
     148          242 :     if (ret != TRACE_SUCCESS) {
     149           22 :         ADIAG_WAR("can not send hello, devId=%d.", devId);
     150           22 :         return TRACE_UNSUPPORTED;
     151              :     }
     152              :     // create thread to receive device trace log
     153          220 :     TraceThreadArgs args = {devId};
     154          220 :     ret = AtraceThreadCreate(devId, &args, AtraceClientRecvThread);
     155          220 :     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          220 :     ADIAG_RUN_INF("start to receive device[%d] trace log.", devId);
     161          220 :     return TRACE_SUCCESS;
     162              : }
     163              : 
     164          220 : void AtraceClientStop(int32_t devId)
     165              : {
     166          220 :     if ((devId >= HOST_MAX_DEV_NUM) || (devId < 0)) {
     167           22 :         ADIAG_ERR("stop report failed, device id is invalid, devId=%d.", devId);
     168           22 :         return;
     169              :     }
     170          198 :     if (devId == HOST_AI_DEVID) {
     171            0 :         ADIAG_INF("devId[%d] no need to stop a thread.", devId);
     172            0 :         return;
     173              :     }
     174              : 
     175          198 :     AtraceThreadRelease(devId, AtraceClientSendEnd, true);
     176          198 :     ADIAG_RUN_INF("stop to receive device[%d] trace log.", devId);
     177              : }
     178              : 
     179         1017 : TraStatus AtraceClientInit(void)
     180              : {
     181              :     // init thread pool
     182         1017 :     TraStatus ret = AtraceThreadPoolInit();
     183         1017 :     ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return ret, "init thread pool failed.");
     184              : 
     185         1017 :     ADIAG_INF("init atrace client successfully.");
     186         1017 :     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           88 : STATIC int32_t AtraceClientExitNoSend(int32_t devId)
     199              : {
     200              :     (void)devId;
     201           88 :     return TRACE_SUCCESS;
     202              : }
     203              : 
     204         1073 : void AtraceClientExit(void)
     205              : {
     206              :     // release all receive thread; do not send [end] in destructor path
     207         1073 :     AtraceThreadPoolExit(AtraceClientExitNoSend);
     208         1073 : }
        

Generated by: LCOV version 2.0-1