LCOV - code coverage report
Current view: top level - atrace/trace_server/ktrace_ts - ktrace_ts.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.8 % 168 161
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              : #include "ktrace_ts.h"
      11              : #include "adiag_lock.h"
      12              : #include "adiag_print.h"
      13              : #include "adiag_utils.h"
      14              : #include "ascend_hal.h"
      15              : #include "trace_msg.h"
      16              : #include "trace_node.h"
      17              : #include "trace_server_mgr.h"
      18              : #include "trace_system_api.h"
      19              : #include "trace_types.h"
      20              : 
      21              : #define MAX_DEV_NUM 64
      22              : #define DRV_RECV_MAX_LEN 524288
      23              : #define TRACE_RECV_TIMEOUT 500
      24              : #define GET_DEV_ID_RETRY_INTERVAL 1000 * 1000
      25              : #define GET_DEV_ID_RETRY_TIMES 10
      26              : 
      27              : typedef struct {
      28              :     TraceThread tid;
      29              :     uint32_t devId;
      30              :     int32_t status;
      31              : } ThreadInfo;
      32              : 
      33              : typedef struct {
      34              :     uint32_t pid;
      35              :     uint32_t logSize;
      36              :     uint8_t endFlag; // 0 start; 1 mid; 2 end
      37              :     uint8_t reserve[23];
      38              : } TraceInfoHead;
      39              : 
      40              : STATIC ThreadInfo** g_ktraceTsThread = NULL;
      41              : STATIC AdiagLock g_ktraceTsLock = TRACE_MUTEX_INITIALIZER;
      42              : STATIC int32_t g_ktraceTsStatus = 0;
      43              : STATIC uint32_t g_devNum = 0;
      44              : 
      45              : /**
      46              :  * @brief           get event time when each event start.
      47              :  * @param [in]      sessionNode:         sessionNode
      48              :  * @param [in]      endFlag:             event flag
      49              :  * @param [out]     time:                event time
      50              :  * @param [in]      len:                 time length
      51              :  * @return          TraStatus
      52              :  */
      53           23 : STATIC TraStatus KtraceGetEventTime(SessionNode* sessionNode, uint8_t endFlag, char* time, uint32_t len)
      54              : {
      55           23 :     if ((strlen(sessionNode->eventTime) == 0) || (endFlag == ADIAG_INFO_FLAG_START)) {
      56           21 :         (void)memset_s(sessionNode->eventTime, TIMESTAMP_MAX_LENGTH, 0, TIMESTAMP_MAX_LENGTH);
      57           21 :         TraStatus ret = TimestampToFileStr(GetRealTime(), sessionNode->eventTime, TIMESTAMP_MAX_LENGTH);
      58           21 :         if (ret != TRACE_SUCCESS) {
      59            1 :             ADIAG_ERR("get timestamp failed, ret = %d.", ret);
      60            1 :             return TRACE_FAILURE;
      61              :         }
      62              :     }
      63           22 :     errno_t err = strncpy_s(time, len, sessionNode->eventTime, TIMESTAMP_MAX_LENGTH);
      64           22 :     if (err != EOK) {
      65            1 :         ADIAG_ERR("strncpy timestamp failed, err = %d, strerr = %s", (int32_t)err, strerror(AdiagGetErrorCode()));
      66            1 :         return TRACE_FAILURE;
      67              :     }
      68           21 :     if (endFlag == ADIAG_INFO_FLAG_END) {
      69           19 :         (void)memset_s(sessionNode->eventTime, TIMESTAMP_MAX_LENGTH, 0, TIMESTAMP_MAX_LENGTH);
      70              :     }
      71           21 :     return TRACE_SUCCESS;
      72              : }
      73              : 
      74          397 : STATIC TraStatus KtracePushDataToNode(TraceInfoHead* head, TraceEventMsg* eventMsg)
      75              : {
      76          397 :     SessionNode* sessionNode = TraceServerGetSessionNode((int32_t)head->pid, (int32_t)eventMsg->devId);
      77          397 :     if (sessionNode == NULL) {
      78          374 :         ADIAG_WAR("no session node is valid, pid = %u.", head->pid);
      79          374 :         return TRACE_FAILURE;
      80              :     }
      81           23 :     TraStatus ret = KtraceGetEventTime(sessionNode, head->endFlag, eventMsg->eventTime, TIMESTAMP_MAX_LENGTH);
      82           23 :     if (ret != TRACE_SUCCESS) {
      83            2 :         ADIAG_ERR("get event time failed, ret = %d, pid = %u.", ret, head->pid);
      84            2 :         return TRACE_FAILURE;
      85              :     }
      86              : 
      87           21 :     ret = TraceTsPushNode(sessionNode, head->endFlag, (void*)eventMsg, eventMsg->bufLen + sizeof(TraceEventMsg));
      88           21 :     if (ret != TRACE_SUCCESS) {
      89            2 :         if (ret == TRACE_QUEUE_FULL) {
      90            2 :             ADIAG_WAR("queue is full.");
      91              :         } else {
      92            0 :             ADIAG_ERR("push node failed, ret = %d, pid = %u.", ret, head->pid);
      93              :         }
      94            2 :         return TRACE_FAILURE;
      95              :     }
      96           19 :     return TRACE_SUCCESS;
      97              : }
      98              : 
      99              : /**
     100              :  * @brief           parse data from ts and construct to event msg.
     101              :  * @param [in]      traceInfo:         data from ts
     102              :  * @param [in]      len:               length of data from ts
     103              :  * @param [in]      devId:             device id
     104              :  * @return          NA
     105              :  */
     106          400 : STATIC void KtraceDataProcess(char* traceInfo, uint32_t len, uint32_t localDevId, uint32_t devId)
     107              : {
     108          400 :     ADIAG_CHK_EXPR_ACTION(
     109              :         (len > DRV_RECV_MAX_LEN) || (len < sizeof(TraceInfoHead)), return, "invalid length[%u] from driver", len);
     110          400 :     TraceInfoHead* head = (TraceInfoHead*)traceInfo;
     111          400 :     ADIAG_CHK_EXPR_ACTION(
     112              :         head->logSize >= len, return, "data len[%u] is over max len[%u] from ts.", head->logSize, len);
     113              : 
     114          399 :     TraceEventMsg* eventMsg = (TraceEventMsg*)AdiagMalloc(sizeof(TraceEventMsg) + head->logSize + 1U);
     115          399 :     if (eventMsg == NULL) {
     116            0 :         ADIAG_ERR("malloc for event msg failed.");
     117            0 :         return;
     118              :     }
     119          399 :     eventMsg->msgType = TRACE_EVENT_MSG;
     120          399 :     eventMsg->eventType = 0;
     121          399 :     eventMsg->devId = localDevId;
     122          399 :     eventMsg->pid = (int32_t)head->pid;
     123          399 :     eventMsg->seqFlag = head->endFlag;
     124          399 :     eventMsg->sequence = 0;
     125          399 :     eventMsg->bufLen = head->logSize;
     126          399 :     errno_t err = memcpy_s(eventMsg->buf, head->logSize + 1U, traceInfo + sizeof(TraceInfoHead), head->logSize);
     127          399 :     if (err != EOK) {
     128            1 :         ADIAG_ERR("memcpy failed, err = %d, strerr = %s.", (int32_t)err, strerror(AdiagGetErrorCode()));
     129            1 :         ADIAG_SAFE_FREE(eventMsg);
     130            1 :         return;
     131              :     }
     132          398 :     int32_t ret = snprintf_s(eventMsg->eventName, EVENT_NAME_MAX_LENGTH, EVENT_NAME_MAX_LENGTH - 1U, "ts_%u", devId);
     133          398 :     if (ret == -1) {
     134            1 :         ADIAG_ERR("snprintf failed, ret = %d, strerr = %s.", ret, strerror(AdiagGetErrorCode()));
     135            1 :         ADIAG_SAFE_FREE(eventMsg);
     136            1 :         return;
     137              :     }
     138          397 :     TraceServerSessionLock();
     139          397 :     ret = KtracePushDataToNode(head, eventMsg);
     140          397 :     TraceServerSessionUnlock();
     141          397 :     if (ret != TRACE_SUCCESS) {
     142          378 :         ADIAG_SAFE_FREE(eventMsg);
     143          378 :         return;
     144              :     }
     145           19 :     ADIAG_INF(
     146              :         "log read by type successfully, pid = %d, data len = %u bytes, end flag = %hhu.", eventMsg->pid,
     147              :         eventMsg->bufLen, eventMsg->seqFlag);
     148           19 :     return;
     149              : }
     150              : 
     151              : /**
     152              :  * @brief           convert device-side devId to host-side devId
     153              :  * @param [in]      localDeviceId:         chip ID
     154              :  * @return          host side devId (physical id)
     155              :  */
     156           26 : STATIC uint32_t KtraceGetPhysicalDeviceID(uint32_t localDeviceId)
     157              : {
     158           26 :     uint32_t phyDeviceId = 0;
     159           26 :     drvError_t ret = DRV_ERROR_NONE;
     160           26 :     uint32_t retryTime = 0;
     161              :     do {
     162           36 :         ret = drvGetDevIDByLocalDevID(localDeviceId, &phyDeviceId);
     163           36 :         if (ret == DRV_ERROR_NONE) {
     164           25 :             break;
     165              :         }
     166           11 :         usleep(GET_DEV_ID_RETRY_INTERVAL);
     167           11 :         retryTime++;
     168           11 :     } while (retryTime < GET_DEV_ID_RETRY_TIMES);
     169           26 :     if (ret != DRV_ERROR_NONE) {
     170            1 :         ADIAG_WAR("get physical device-id by local device-id=%u, result=%d", localDeviceId, ret);
     171            1 :         return localDeviceId;
     172              :     }
     173           25 :     return phyDeviceId;
     174              : }
     175              : 
     176              : /**
     177              :  * @brief           thread to get data from ts.
     178              :  * @param [in]      arg:         thread info
     179              :  * @return          NULL
     180              :  */
     181           26 : STATIC void* KtraceTsThread(void* arg)
     182              : {
     183           26 :     ADIAG_CHK_NULL_PTR(arg, return NULL);
     184           26 :     ThreadInfo* info = (ThreadInfo*)arg;
     185           26 :     uint32_t phyDeviceId = KtraceGetPhysicalDeviceID(info->devId);
     186           26 :     ADIAG_RUN_INF("ktrace ts thread start, local device id = %u, physical device id = %u.", info->devId, phyDeviceId);
     187           26 :     if (TraceSetThreadName("TraceServerRecv") != TRACE_SUCCESS) {
     188            3 :         ADIAG_WAR("can not set thread name(TraceServerRecv) but continue.");
     189              :     }
     190           26 :     char* traceInfo = (char*)AdiagMalloc(DRV_RECV_MAX_LEN);
     191           26 :     if (traceInfo == NULL) {
     192            0 :         ADIAG_ERR("trace info malloc failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     193            0 :         return NULL;
     194              :     }
     195        37876 :     while (info->status != 0) {
     196        37851 :         (void)memset_s(traceInfo, DRV_RECV_MAX_LEN, 0, DRV_RECV_MAX_LEN);
     197        37851 :         uint32_t len = DRV_RECV_MAX_LEN;
     198              :         int32_t ret =
     199        37851 :             log_read_by_type((int32_t)info->devId, traceInfo, &len, TRACE_RECV_TIMEOUT, LOG_CHANNEL_TYPE_TS_PROC);
     200        37851 :         if (ret == (int32_t)LOG_NOT_SUPPORT) {
     201            1 :             ADIAG_RUN_INF("ts channel is not supported.");
     202            1 :             break;
     203              :         }
     204        37850 :         if (ret == (int32_t)LOG_NOT_READY) {
     205        37450 :             continue;
     206              :         }
     207          406 :         if (ret != TRACE_SUCCESS) {
     208            6 :             ADIAG_WAR("can not read trace data from driver, ret = %d, strerr=%s.", ret, strerror(AdiagGetErrorCode()));
     209            6 :             usleep(TRACE_RECV_TIMEOUT * TIME_ONE_THOUSAND_MS);
     210            6 :             continue;
     211              :         }
     212          400 :         KtraceDataProcess(traceInfo, len, info->devId, phyDeviceId);
     213              :     }
     214           26 :     ADIAG_SAFE_FREE(traceInfo);
     215           26 :     return NULL;
     216              : }
     217              : 
     218           29 : STATIC TraStatus KtraceTsRecvThread(uint32_t devIndex, uint32_t devId)
     219              : {
     220           29 :     g_ktraceTsThread[devIndex] = (ThreadInfo*)AdiagMalloc(sizeof(ThreadInfo));
     221           29 :     if (g_ktraceTsThread[devIndex] == NULL) {
     222            0 :         ADIAG_ERR("malloc ktrace ts thread failed, device id = %u.", devId);
     223            0 :         return TRACE_FAILURE;
     224              :     }
     225           29 :     g_ktraceTsThread[devIndex]->status = 1;
     226           29 :     g_ktraceTsThread[devIndex]->devId = devId;
     227              : 
     228              :     TraceUserBlock thread;
     229           29 :     thread.procFunc = KtraceTsThread;
     230           29 :     thread.pulArg = (void*)g_ktraceTsThread[devIndex];
     231           29 :     TraceThreadAttr attr = {0, 0, 0, 0, 0, 0, TRACE_THREAD_STACK_SIZE};
     232           29 :     TraceThread tid = 0;
     233           29 :     if (TraceCreateTaskWithThreadAttr(&tid, &thread, &attr) != TRACE_SUCCESS) {
     234            3 :         ADIAG_ERR("create task failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     235            3 :         return TRACE_FAILURE;
     236              :     }
     237           26 :     g_ktraceTsThread[devIndex]->tid = tid;
     238           26 :     return TRACE_SUCCESS;
     239              : }
     240              : 
     241              : /**
     242              :  * @brief           create thread to data from ts for each device.
     243              :  * @param [in]      devNum:         device number
     244              :  * @param [in]      devIdArray:     device id array
     245              :  * @return          TraStatus
     246              :  */
     247           33 : TraStatus KtraceTsCreateThread(uint32_t devNum, uint32_t* devIdArray)
     248              : {
     249           33 :     if ((devNum > MAX_DEV_NUM) || (devIdArray == NULL)) {
     250            2 :         ADIAG_ERR("ktrace ts receive thread init failed.");
     251            2 :         return TRACE_FAILURE;
     252              :     }
     253              : 
     254           31 :     if (g_ktraceTsStatus != 0) {
     255            1 :         ADIAG_ERR("ktrace ts receive thread has already existed.");
     256            1 :         return TRACE_FAILURE;
     257              :     }
     258              : 
     259           30 :     (void)AdiagLockInit(&g_ktraceTsLock);
     260           30 :     (void)AdiagLockGet(&g_ktraceTsLock);
     261           30 :     g_ktraceTsStatus = 1;
     262           30 :     g_devNum = devNum;
     263           30 :     g_ktraceTsThread = (ThreadInfo**)AdiagMalloc(sizeof(ThreadInfo*) * (size_t)devNum);
     264           30 :     if (g_ktraceTsThread == NULL) {
     265            2 :         ADIAG_ERR("malloc ktrace ts thread failed.");
     266            2 :         (void)AdiagLockRelease(&g_ktraceTsLock);
     267            2 :         KtraceTsDestroyThread();
     268            2 :         return TRACE_FAILURE;
     269              :     }
     270              : 
     271           28 :     TraStatus ret = TRACE_SUCCESS;
     272           54 :     for (uint32_t i = 0; i < devNum; i++) {
     273           29 :         ret = KtraceTsRecvThread(i, devIdArray[i]);
     274           29 :         if (ret != TRACE_SUCCESS) {
     275            3 :             ADIAG_ERR("ktrace create ts receive thread failed, device id = %u.", i);
     276            3 :             (void)AdiagLockRelease(&g_ktraceTsLock);
     277            3 :             KtraceTsDestroyThread();
     278            3 :             return TRACE_FAILURE;
     279              :         }
     280              :     }
     281              : 
     282           25 :     (void)AdiagLockRelease(&g_ktraceTsLock);
     283           25 :     ADIAG_RUN_INF("create ts ktrace thread successfully.");
     284           25 :     return TRACE_SUCCESS;
     285              : }
     286              : 
     287           52 : void KtraceTsDestroyThread(void)
     288              : {
     289           52 :     if (g_ktraceTsStatus == 0) {
     290           22 :         return;
     291              :     }
     292           30 :     (void)AdiagLockGet(&g_ktraceTsLock);
     293           30 :     g_ktraceTsStatus = 0;
     294           30 :     if (g_ktraceTsThread == NULL) {
     295            2 :         (void)AdiagLockRelease(&g_ktraceTsLock);
     296            2 :         (void)AdiagLockDestroy(&g_ktraceTsLock);
     297            2 :         return;
     298              :     }
     299           58 :     for (uint32_t i = 0; i < g_devNum; i++) {
     300           30 :         if (g_ktraceTsThread[i] != NULL) {
     301           29 :             g_ktraceTsThread[i]->status = 0;
     302              :         }
     303              :     }
     304           58 :     for (uint32_t i = 0; i < g_devNum; i++) {
     305           30 :         if ((g_ktraceTsThread[i] != NULL) && (g_ktraceTsThread[i]->tid != 0)) {
     306           26 :             (void)TraceJoinTask(&g_ktraceTsThread[i]->tid);
     307              :         }
     308           30 :         ADIAG_SAFE_FREE(g_ktraceTsThread[i]);
     309              :     }
     310           28 :     ADIAG_SAFE_FREE(g_ktraceTsThread);
     311           28 :     (void)AdiagLockRelease(&g_ktraceTsLock);
     312           28 :     (void)AdiagLockDestroy(&g_ktraceTsLock);
     313           28 :     ADIAG_RUN_INF("destroy ts ktrace thread successfully.");
     314              : }
        

Generated by: LCOV version 2.0-1