LCOV - code coverage report
Current view: top level - atrace/utrace/stacktrace/stacktrace_dumper - scd_threads.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.3 % 115 113
Test Date: 2026-08-31 10:07:06 Functions: 100.0 % 12 12

            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 "scd_threads.h"
      12              : #include "adiag_utils.h"
      13              : #include "scd_thread.h"
      14              : #include "scd_log.h"
      15              : #include "scd_frame.h"
      16              : 
      17           21 : TraStatus ScdThreadsRecord(int32_t fd, const ScdThreads* thds)
      18              : {
      19           21 :     SCD_CHK_PTR_ACTION(thds, return TRACE_INVALID_PARAM);
      20           20 :     char tmpBuf[SCD_FRAME_LENGTH] = {0};
      21           20 :     int32_t threadIdx = 0;
      22           20 :     struct ListHead* pos = NULL;
      23           20 :     struct AdiagListNode* node = NULL;
      24           24 :     LIST_FOR_EACH(pos, &thds->thdList.list)
      25              :     {
      26            5 :         node = LIST_ENTRY(pos, struct AdiagListNode, list);
      27            5 :         threadIdx++;
      28            5 :         ScdThread* threadInfo = (ScdThread*)node->data;
      29            5 :         int32_t err = snprintf_s(
      30              :             tmpBuf, SCD_FRAME_LENGTH, SCD_FRAME_LENGTH - 1U, "Thread %d (%d, %s)\n", threadIdx, threadInfo->tid,
      31            5 :             threadInfo->tname);
      32            5 :         if (err == -1) {
      33            1 :             SCD_DLOG_ERR("snprintf_s thread header failed, tid=%d.", threadInfo->tid);
      34            1 :             return TRACE_FAILURE;
      35              :         }
      36            4 :         (void)ScdUtilWrite(fd, tmpBuf, strlen(tmpBuf));
      37              : 
      38              :         // record frame info
      39            4 :         struct ListHead* posFrame = NULL;
      40            4 :         struct AdiagListNode* nodeFrame = NULL;
      41            4 :         int32_t frameIdx = -1;
      42            6 :         LIST_FOR_EACH(posFrame, &threadInfo->frames.frameList.list)
      43              :         {
      44            2 :             nodeFrame = LIST_ENTRY(posFrame, struct AdiagListNode, list);
      45            2 :             frameIdx++;
      46            2 :             ScdFrame* frame = (ScdFrame*)nodeFrame->data;
      47            2 :             if (strlen(frame->funcName) == 0) {
      48            1 :                 err = snprintf_s(
      49              :                     tmpBuf, SCD_FRAME_LENGTH, SCD_FRAME_LENGTH - 1U, "#%02u 0x%016lx 0x%016lx %s\n", frame->num,
      50            1 :                     frame->pc, frame->base, frame->soName);
      51              :             } else {
      52            1 :                 err = snprintf_s(
      53              :                     tmpBuf, SCD_FRAME_LENGTH, SCD_FRAME_LENGTH - 1U, "#%02u 0x%016lx 0x%016lx %s (%s)\n", frame->num,
      54            1 :                     frame->pc, frame->base, frame->soName, frame->funcName);
      55              :             }
      56            2 :             if (err == -1) {
      57            0 :                 SCD_DLOG_ERR("snprintf_s frame failed, tid=%d, frame index=%d.", threadInfo->tid, frameIdx);
      58            0 :                 return TRACE_FAILURE;
      59              :             }
      60            2 :             (void)ScdUtilWrite(fd, tmpBuf, strlen(tmpBuf));
      61              :         }
      62            4 :         ScdUtilWriteNewLine(fd);
      63              :     }
      64           19 :     return TRACE_SUCCESS;
      65              : }
      66              : 
      67           23 : STATIC TraStatus ScdThreadsTraverseLoadFrames(void* node, void* data)
      68              : {
      69           23 :     ScdThread* thd = (ScdThread*)node;
      70           23 :     ScdMaps* maps = (ScdMaps*)data;
      71           23 :     if (ScdThreadLoadFrames(thd, maps) != TRACE_SUCCESS) {
      72            6 :         SCD_DLOG_WAR("can not load thread frames, pid=%d, tid=%d.", thd->pid, thd->tid);
      73            6 :         return TRACE_FAILURE;
      74              :     }
      75           17 :     return TRACE_SUCCESS;
      76              : }
      77              : 
      78          189 : TraStatus ScdThreadsLoadFrames(ScdThreads* thds, ScdMaps* maps)
      79              : {
      80              :     // 遍历tid
      81          189 :     AdiagListForEachTraverse(&thds->thdList, ScdThreadsTraverseLoadFrames, maps);
      82          189 :     return TRACE_SUCCESS;
      83              : }
      84              : 
      85            6 : STATIC TraStatus ScdThreadsTraverseLoadInfo(void* node, void* data)
      86              : {
      87            6 :     ScdThread* thd = (ScdThread*)node;
      88            6 :     ScdThreads* thds = (ScdThreads*)data;
      89              : 
      90              :     // load thread regs
      91            6 :     if (thd->tid != thds->crashTid) {
      92            4 :         return ScdThreadLoadInfo(thd);
      93              :     } else {
      94            2 :         return ScdThreadLoadInfoForCrash(thd, &thds->ucRegs);
      95              :     }
      96              : }
      97              : 
      98          172 : TraStatus ScdThreadsLoadInfo(ScdThreads* thds)
      99              : {
     100              :     // 遍历tid
     101          172 :     AdiagListForEachTraverse(&thds->thdList, ScdThreadsTraverseLoadInfo, thds);
     102          172 :     return TRACE_SUCCESS;
     103              : }
     104              : 
     105           92 : TraStatus ScdThreadsLoad(ScdThreads* thds)
     106              : {
     107           92 :     SCD_CHK_PTR_ACTION(thds, return TRACE_FAILURE);
     108              : 
     109           92 :     char buf[SCD_UTIL_TMP_BUF_LEN] = {0};
     110           92 :     int32_t ret = snprintf_s(buf, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%d/task", thds->pid);
     111           92 :     if (ret == -1) {
     112            1 :         SCD_DLOG_ERR("snprintf_s task path failed, pid=%d, errno=%d.", thds->pid, errno);
     113            1 :         return TRACE_FAILURE;
     114              :     }
     115              : 
     116           91 :     DIR* dir = opendir(buf);
     117           91 :     if (dir == NULL) {
     118           68 :         SCD_DLOG_ERR("open dir %s failed, errno=%d", buf, errno);
     119           68 :         return TRACE_FAILURE;
     120              :     }
     121              : 
     122           23 :     struct dirent* ent = NULL;
     123           94 :     while ((ent = readdir(dir)) != NULL) {
     124           73 :         if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
     125           47 :             continue;
     126              :         }
     127              : 
     128           27 :         int32_t tid = -1;
     129           27 :         if (AdiagStrToInt(ent->d_name, &tid) != ADIAG_SUCCESS) {
     130            1 :             continue;
     131              :         }
     132              : 
     133           26 :         ScdThread* thd = ScdThreadCreate(thds->pid, tid);
     134           26 :         if (thd == NULL) {
     135            1 :             SCD_DLOG_ERR("create thread failed, pid=%d, tid=%d.", thds->pid, tid);
     136            1 :             (void)closedir(dir);
     137            2 :             return TRACE_FAILURE;
     138              :         }
     139              : 
     140           25 :         ret = AdiagListInsert(&thds->thdList, (void*)thd);
     141           25 :         if (ret != ADIAG_SUCCESS) {
     142            1 :             ScdThreadDestroy(&thd);
     143            1 :             (void)closedir(dir);
     144            1 :             SCD_DLOG_ERR("insert thread failed, pid=%d, tid=%d.", thds->pid, tid);
     145            1 :             return TRACE_FAILURE;
     146              :         }
     147           24 :         SCD_DLOG_INF("load thread successfully, pid=%d, tid=%d.", thds->pid, tid);
     148              :     }
     149           21 :     (void)closedir(dir);
     150           21 :     return TRACE_SUCCESS;
     151              : }
     152              : 
     153            6 : STATIC TraStatus ScdThreadsTraverseSuspend(void* node, void* data)
     154              : {
     155              :     (void)data;
     156            6 :     return ScdThreadSuspend((ScdThread*)node);
     157              : }
     158              : 
     159          172 : void ScdThreadsSuspend(ScdThreads* thds)
     160              : {
     161              :     // 遍历tid
     162          172 :     AdiagListForEachTraverse(&thds->thdList, ScdThreadsTraverseSuspend, NULL);
     163          172 : }
     164              : 
     165            6 : STATIC TraStatus ScdThreadsTraverseResume(void* node, void* data)
     166              : {
     167              :     (void)data;
     168            6 :     ScdThreadResume((ScdThread*)node);
     169            6 :     return TRACE_SUCCESS;
     170              : }
     171              : 
     172          172 : void ScdThreadsResume(ScdThreads* thds)
     173              : {
     174              :     // 遍历tid
     175          172 :     AdiagListForEachTraverse(&thds->thdList, ScdThreadsTraverseResume, NULL);
     176          172 : }
     177              : 
     178          277 : TraStatus ScdThreadsInit(ScdThreads* thds, int32_t pid, int32_t crashTid, ucontext_t* uc)
     179              : {
     180          277 :     SCD_CHK_PTR_ACTION(thds, return TRACE_FAILURE);
     181          277 :     SCD_CHK_PTR_ACTION(uc, return TRACE_FAILURE);
     182          277 :     thds->pid = pid;
     183          277 :     thds->crashTid = crashTid;
     184          277 :     ScdRegsLoadFromUcontext(&thds->ucRegs, uc);
     185          277 :     AdiagStatus ret = AdiagListInit(&thds->thdList);
     186          277 :     if (ret != ADIAG_SUCCESS) {
     187            1 :         SCD_DLOG_ERR("init thread list failed, ret = %d.", ret);
     188            1 :         return TRACE_FAILURE;
     189              :     }
     190          276 :     SCD_DLOG_DBG(
     191              :         "init all threads successfully, pid=%d, crash tid=%d, pc=0x%lx, sp=0x%lx, fp=0x%lx.", pid, crashTid,
     192              :         GET_PCREG(thds->ucRegs.r), GET_SPREG(thds->ucRegs.r), GET_FPREG(thds->ucRegs.r));
     193          276 :     return TRACE_SUCCESS;
     194              : }
     195              : 
     196          278 : void ScdThreadsUninit(ScdThreads* thds)
     197              : {
     198          278 :     if (thds == NULL) {
     199            2 :         return;
     200              :     }
     201          276 :     ScdThread* node = (ScdThread*)AdiagListTakeOut(&thds->thdList);
     202          301 :     while (node != NULL) {
     203           25 :         ScdThreadDestroy(&node);
     204           25 :         node = (ScdThread*)AdiagListTakeOut(&thds->thdList);
     205              :     }
     206              : }
        

Generated by: LCOV version 2.0-1