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

Generated by: LCOV version 2.0-1