LCOV - code coverage report
Current view: top level - atrace/utrace/trace_client - atrace_client_thread.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.2 % 117 109
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 16 16

            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_thread.h"
      12              : #include "adiag_print.h"
      13              : #include "trace_system_api.h"
      14              : #include "adiag_lock.h"
      15              : #include "adiag_utils.h"
      16              : 
      17              : typedef struct {
      18              :     TraceThread tid;
      19              :     int32_t pid;
      20              :     int8_t threadStatus;
      21              :     TraceThreadArgs args;
      22              :     TraceUserBlock block;
      23              : } ThreadInfo;
      24              : 
      25              : STATIC ThreadInfo **g_traceThread = NULL;
      26              : STATIC pthread_mutex_t g_traceThreadMutex = TRACE_MUTEX_INITIALIZER;
      27              : 
      28              : /**
      29              :  * @brief       : init thread mutex
      30              :  * @return      : NA
      31              :  */
      32          901 : STATIC INLINE void AtraceThreadMutexInit(void)
      33              : {
      34          901 :     (void)AdiagLockInit(&g_traceThreadMutex);
      35          901 : }
      36              : 
      37              : /**
      38              :  * @brief       : Destroy thread mutex
      39              :  * @return      : NA
      40              :  */
      41          951 : STATIC INLINE void AtraceThreadMutexDestroy(void)
      42              : {
      43          951 :     (void)AdiagLockDestroy(&g_traceThreadMutex);
      44          951 : }
      45              : 
      46              : /**
      47              :  * @brief       : lock thread mutex
      48              :  * @return      : NA
      49              :  */
      50      1966188 : STATIC INLINE void AtraceThreadLock(void)
      51              : {
      52      1966188 :     (void)AdiagLockGet(&g_traceThreadMutex);
      53      1966188 : }
      54              : 
      55              : /**
      56              :  * @brief       : unlock thread mutex
      57              :  * @return      : NA
      58              :  */
      59      1966188 : STATIC INLINE void AtraceThreadUnLock(void)
      60              : {
      61      1966188 :     (void)AdiagLockRelease(&g_traceThreadMutex);
      62      1966188 : }
      63              : 
      64          400 : STATIC void AtraceThreadSetStatus(int32_t devId, int8_t value)
      65              : {
      66          400 :     AtraceThreadLock();
      67          400 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL)) {
      68          400 :         g_traceThread[devId]->threadStatus = value;
      69              :     }
      70          400 :     AtraceThreadUnLock();
      71          400 : }
      72              : 
      73        16740 : int8_t AtraceThreadGetStatus(int32_t devId)
      74              : {
      75        16740 :     int8_t status = THREAD_STATUS_INIT;
      76        16740 :     AtraceThreadLock();
      77        16740 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL)) {
      78        16740 :         status = g_traceThread[devId]->threadStatus;
      79              :     }
      80        16740 :     AtraceThreadUnLock();
      81        16740 :     return status;
      82              : }
      83              : 
      84              : /**
      85              :  * @brief       : get tid of thread, make sure thread exist before callback
      86              :  * @param [in]  : devId         device id
      87              :  * @return      : tid
      88              :  */
      89          200 : STATIC TraceThread AtraceThreadGetTid(int32_t devId)
      90              : {
      91          200 :     ADIAG_CHK_EXPR_ACTION((devId < 0) || (devId >= HOST_MAX_DEV_NUM), return (TraceThread)0,
      92              :         "can not get tid, invalid devId=%d.", devId);
      93          200 :     TraceThread tid = 0;
      94          200 :     AtraceThreadLock();
      95          200 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL)) {
      96          200 :         tid = g_traceThread[devId]->tid;
      97              :     }
      98          200 :     AtraceThreadUnLock();
      99          200 :     return tid;
     100              : }
     101              : 
     102              : 
     103              : /**
     104              :  * @brief       : check thread existence or non-existence
     105              :  * @param [in]  : devId         device id
     106              :  * @return      : true existence; false non-existence
     107              :  */
     108      1948248 : STATIC bool AtraceThreadCheckExist(int32_t devId)
     109              : {
     110      1948248 :     ADIAG_CHK_EXPR_ACTION((devId < 0) || (devId >= HOST_MAX_DEV_NUM), return false,
     111              :         "can not check thread, invalid devId=%d.", devId);
     112      1948248 :     AtraceThreadLock();
     113      1948248 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL) && (g_traceThread[devId]->tid != 0)) {
     114          220 :         AtraceThreadUnLock();
     115          220 :         return true;
     116              :     }
     117      1948028 :     AtraceThreadUnLock();
     118      1948028 :     return false;
     119              : }
     120              : 
     121              : /**
     122              :  * @brief       : free threadInfo pointer, which malloc when create thread
     123              :  * @param [in]  : devId         device id
     124              :  * @return      : NA
     125              :  */
     126          200 : void AtraceThreadFree(int32_t devId)
     127              : {
     128          200 :     ADIAG_CHK_EXPR_ACTION((devId < 0) || (devId >= HOST_MAX_DEV_NUM), return,
     129              :         "can not free atrace receive thread, invalid devId=%d.", devId);
     130          200 :     AtraceThreadLock();
     131          200 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL)) {
     132          200 :         AdiagFree(g_traceThread[devId]);
     133          200 :         g_traceThread[devId] = NULL;
     134              :     }
     135          200 :     AtraceThreadUnLock();
     136              : }
     137              : 
     138              : /**
     139              :  * @brief       : check current pid is same to previous pid(when create thread)
     140              :  * @param [in]  : devId         device id
     141              :  * @return      : true  same; false  different
     142              :  */
     143          200 : STATIC bool AtraceThreadCheckPid(int32_t devId)
     144              : {
     145          200 :     ADIAG_CHK_EXPR_ACTION((devId < 0) || (devId >= HOST_MAX_DEV_NUM), return false,
     146              :         "can not get tid, invalid devId=%d.", devId);
     147          200 :     bool ret = true;
     148          200 :     AtraceThreadLock();
     149          200 :     if ((g_traceThread != NULL) && (g_traceThread[devId] != NULL)) {
     150          200 :         ret = (g_traceThread[devId]->pid == TraceGetPid()) ? true : false;
     151              :     }
     152          200 :     AtraceThreadUnLock();
     153          200 :     return ret;
     154              : }
     155              : /**
     156              :  * @brief       : join thread to release thread resource, then free ThreadInfo
     157              :  * @param [in]  : devId         device id
     158              :  */
     159          200 : STATIC void AtraceThreadJoinTask(int32_t devId)
     160              : {
     161          200 :     TraceThread tid = AtraceThreadGetTid(devId);
     162          200 :     if ((tid > (TraceThread)0) && (AtraceThreadCheckPid(devId))) {
     163          200 :         int32_t ret = TraceJoinTask(&tid);
     164          200 :         if (ret != 0) {
     165            0 :             ADIAG_WAR("can not join atrace receive thread, devId=%d, strerr=%s.", devId, strerror(AdiagGetErrorCode()));
     166              :         }
     167              :     }
     168          200 :     AtraceThreadFree(devId);
     169          200 : }
     170              : 
     171              : /**
     172              :  * @brief       : make sure single thread for one device
     173              :  * @param [in]  : devId         device id
     174              :  * @return      : true   single thread; false   no thread
     175              :  */
     176          220 : bool AtraceThreadSingleTask(int32_t devId)
     177              : {
     178          220 :     if (AtraceThreadCheckExist(devId) == false) {
     179          220 :         return false;
     180              :     }
     181            0 :     if (AtraceThreadGetStatus(devId) == THREAD_STATUS_WAIT_EXIT) {
     182            0 :         AtraceThreadJoinTask(devId);
     183            0 :         return false;
     184              :     }
     185            0 :     return true;
     186              : }
     187              : 
     188              : /**
     189              :  * @brief       : create thread for receive device log
     190              :  * @param [in]  : devId         device id
     191              :  * @param [in]  : pArgs         pointer of thread args
     192              :  * @param [in]  : func          thread run function
     193              :  * @return      : !=0 failure; ==0 success
     194              :  */
     195          200 : TraStatus AtraceThreadCreate(int32_t devId, TraceThreadArgs *pArgs, ThreadRunFunc func)
     196              : {
     197          200 :     ADIAG_CHK_EXPR_ACTION(g_traceThread == NULL, return TRACE_FAILURE,
     198              :         "create thread failed, thread pool is not initialized.");
     199          200 :     ADIAG_CHK_EXPR_ACTION((devId < 0) || (devId >= HOST_MAX_DEV_NUM), return TRACE_FAILURE,
     200              :         "create thread failed, invalid devId=%d.", devId);
     201          200 :     ADIAG_CHK_EXPR_ACTION(pArgs == NULL, return TRACE_FAILURE,
     202              :         "create thread failed, thread args is null.");
     203          200 :     ADIAG_CHK_EXPR_ACTION(AtraceThreadCheckExist(devId), return TRACE_FAILURE,
     204              :         "log receive thread has bean started, devId=%d.", devId);
     205              : 
     206          200 :     ThreadInfo *pThread = (ThreadInfo *)AdiagMalloc(sizeof(ThreadInfo));
     207          200 :     ADIAG_CHK_EXPR_ACTION(pThread == NULL, return TRACE_FAILURE, "malloc failed, can not create atrace receive thread");
     208              : 
     209          200 :     AtraceThreadLock();
     210          200 :     g_traceThread[devId] = pThread;
     211          200 :     int32_t ret = memcpy_s(&g_traceThread[devId]->args, sizeof(TraceThreadArgs), pArgs, sizeof(TraceThreadArgs));
     212          200 :     if (ret != EOK) {
     213            0 :         ADIAG_ERR("copy data failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     214              :     }
     215              : 
     216          200 :     g_traceThread[devId]->pid = TraceGetPid();
     217          200 :     g_traceThread[devId]->block.procFunc = func;
     218          200 :     g_traceThread[devId]->block.pulArg = (void *)(&g_traceThread[devId]->args);
     219          200 :     TraceThreadAttr threadAttr = { 0, 0, 0, 0, 0, 0, 128 * 1024 }; // joinable
     220          200 :     ret = TraceCreateTaskWithThreadAttr(&g_traceThread[devId]->tid, &g_traceThread[devId]->block, &threadAttr);
     221          200 :     AtraceThreadUnLock();
     222          200 :     if (ret != TRACE_SUCCESS) {
     223            0 :         AtraceThreadFree(devId);
     224            0 :         return TRACE_FAILURE;
     225              :     }
     226          200 :     AtraceThreadSetStatus(devId, THREAD_STATUS_RUN);
     227          200 :     return TRACE_SUCCESS;
     228              : }
     229              : 
     230              : /**
     231              :  * @brief       : release single thread
     232              :  * @param [in]  : devId         device id
     233              :  * @param [in]  : func          thread stop function
     234              :  * @param [in]  : sync          whether to wait thread exit
     235              :  * @return      : NA
     236              :  */
     237       974004 : void AtraceThreadRelease(int32_t devId, ThreadStopFunc func, bool sync)
     238              : {
     239       974004 :     if (AtraceThreadCheckExist(devId) == true) {
     240          200 :         if ((func != NULL) && (AtraceThreadGetStatus(devId) != THREAD_STATUS_WAIT_EXIT)) {
     241          200 :             func(devId);
     242          200 :             AtraceThreadSetStatus(devId, THREAD_STATUS_WAIT_EXIT);
     243              :         }
     244          200 :         if (sync == true) {
     245          180 :             AtraceThreadJoinTask(devId);
     246              :         }
     247              :     }
     248       974004 : }
     249              : 
     250              : /**
     251              :  * @brief       : init thread pool
     252              :  * @return      : NA
     253              :  */
     254          901 : TraStatus AtraceThreadPoolInit(void)
     255              : {
     256          901 :     g_traceThread = (ThreadInfo **)AdiagMalloc((size_t)HOST_MAX_DEV_NUM * sizeof(ThreadInfo *));
     257          901 :     ADIAG_CHK_EXPR_ACTION(g_traceThread == NULL, return TRACE_FAILURE, "malloc thread pool failed.");
     258          901 :     AtraceThreadMutexInit();
     259          901 :     return TRACE_SUCCESS;
     260              : }
     261              : 
     262              : /**
     263              :  * @brief       : exit thread pool
     264              :  * @param [in]  : func          thread stop function
     265              :  * @return      : NA
     266              :  */
     267          951 : void AtraceThreadPoolExit(ThreadStopFunc func)
     268              : {
     269              :     int32_t i;
     270       974775 :     for (i = 0; i < HOST_MAX_DEV_NUM; i++) {
     271       973824 :         AtraceThreadRelease(i, func, false);
     272              :     }
     273              :     // wait all thread exit after stop them, to improve running efficiency
     274       974775 :     for (i = 0; i < HOST_MAX_DEV_NUM; i++) {
     275       973824 :         if (AtraceThreadCheckExist(i) == true) {
     276           20 :             AtraceThreadJoinTask(i);
     277              :         }
     278              :     }
     279          951 :     AdiagFree(g_traceThread);
     280          951 :     g_traceThread = NULL;
     281          951 :     AtraceThreadMutexDestroy();
     282          951 : }
        

Generated by: LCOV version 2.0-1