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: 54.8 % 115 63
Test Date: 2026-07-28 10:53:44 Functions: 75.0 % 12 9

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

Generated by: LCOV version 2.0-1