LCOV - code coverage report
Current view: top level - aicpu_cust_schedule/core/dfx - aicpusd_monitor.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.8 % 136 118
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 14 14

            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 "aicpusd_monitor.h"
      11              : 
      12              : #include <mutex>
      13              : #include <cstdlib>
      14              : #include <string>
      15              : #include <unistd.h>
      16              : #include <cstring>
      17              : #include <cerrno>
      18              : #include "securec.h"
      19              : #include "aicpusd_common.h"
      20              : #include "profiling_adp.h"
      21              : #include "aicpusd_drv_manager.h"
      22              : #include "tsd.h"
      23              : #include "aicpu_context.h"
      24              : #include "aicpu_pulse.h"
      25              : #include "aicpusd_info.h"
      26              : #include "status.h"
      27              : #include "feature_ctrl.h"
      28              : 
      29              : namespace {
      30              :     // aicpu task timeout
      31              :     const uint64_t AICPU_TASK_TIMEOUT = 28LU;
      32              :     const uint64_t AICPU_TASK_TIMEOUT_LONG = 60UL;
      33              : }
      34              : 
      35              : namespace AicpuSchedule {
      36              :     /**
      37              :      * @ingroup AicpuMonitor
      38              :      * @brief it is used to construct a object of AicpuMonitor.
      39              :      *        using default value to construct
      40              :      */
      41           11 :     AicpuMonitor::AicpuMonitor()
      42           11 :         : deviceId_(0U),
      43           11 :           taskTimeoutFlag_(false),
      44           11 :           taskInfo_(nullptr),
      45           11 :           done_(false),
      46           11 :           taskTimeout_(UINT64_MAX),
      47           11 :           taskTimeoutTick_(UINT64_MAX),
      48           11 :           taskTimer_(nullptr),
      49           11 :           running_(false),
      50           11 :           aicpuCoreNum_(0U),
      51           11 :           online_(false)
      52           11 :     {}
      53              : 
      54              : /**
      55              :      * @ingroup AicpuMonitor
      56              :      * @brief it is used to destructor a object of AicpuMonitor.
      57              :      *        it is neccessary to set flag false to make sure thread to be stopped
      58              :      */
      59           11 :     AicpuMonitor::~AicpuMonitor()
      60              :     {
      61           11 :         if (!done_) {
      62            9 :             Stop();
      63              :         }
      64           11 :     }
      65              : 
      66           49 :     AicpuMonitor &AicpuMonitor::GetInstance()
      67              :     {
      68           49 :         static AicpuMonitor instance;
      69           49 :         return instance;
      70              :     }
      71              : 
      72            5 :     int32_t AicpuMonitor::InitAicpuMonitor(const uint32_t deviceId, const bool online)
      73              :     {
      74            5 :         aicpusd_info("Begin to init aicpu monitor");
      75            5 :         online_ = online;
      76            5 :         if (!online_) {
      77            1 :             aicpusd_info("End to init aicpu monitor, offline mode");
      78            1 :             return AICPU_SCHEDULE_OK;
      79              :         }
      80            4 :         deviceId_ = deviceId;
      81            4 :         aicpuCoreNum_ = AicpuSchedule::AicpuDrvManager::GetInstance().GetAicpuNum();
      82            4 :         if (aicpuCoreNum_ != 0U) {
      83            4 :             taskInfo_.reset(new (std::nothrow) TaskInfoForMonitor[aicpuCoreNum_]);
      84            4 :             if (taskInfo_ == nullptr) {
      85            0 :                 aicpusd_err("malloc task info memory for monitor failed");
      86            0 :                 return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
      87              :             }
      88            8 :             for (size_t i = 0UL; i < aicpuCoreNum_; i++) {
      89            4 :                 taskInfo_[i] = {UINT64_MAX, UINT64_MAX, UINT32_MAX, false};
      90              :             }
      91              :         }
      92              : 
      93            4 :         const int32_t ret = SetTaskTimeoutFlag();
      94            4 :         if (ret != AICPU_SCHEDULE_OK) {
      95            1 :             aicpusd_err("set task timeout flag failed, ret[%d]", ret);
      96            1 :             return ret;
      97              :         }
      98              : 
      99            3 :         if (taskTimeoutFlag_ && (aicpuCoreNum_ != 0U)) {
     100            6 :             taskTimer_.reset(new (std::nothrow) TaskTimer[aicpuCoreNum_]);
     101            3 :             if (taskTimer_ == nullptr) {
     102            0 :                 aicpusd_err("malloc memory for task timer failed");
     103            0 :                 return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     104              :             }
     105              :         }
     106              : 
     107            3 :         aicpusd_run_info("Init aicpu monitor success, taskTimeout=%lus, tickFreq=%lu",
     108              :                          taskTimeout_, aicpu::GetSystemTickFreq());
     109            3 :         return AICPU_SCHEDULE_OK;
     110              :     }
     111              : 
     112            2 :     void AicpuMonitor::SendKillMsgToTsd() const
     113              :     {
     114            2 :         aicpusd_run_info("dev[%u] send msg to tsdaemon, tsdaemon will kill aicpu-custom-sd process[%u]",
     115              :                          deviceId_, static_cast<uint32_t>(getpid()));
     116            6 :         const int32_t ret = TsdDestroy(deviceId_, TSD_CUSTOM_COMPUTE,
     117            2 :                                        static_cast<uint32_t>(AicpuDrvManager::GetInstance().GetHostPid()),
     118            2 :                                        AicpuDrvManager::GetInstance().GetVfId());
     119            2 :         if (ret != static_cast<int32_t>(tsd::TSD_OK)) {
     120            1 :             aicpusd_err("dev[%u] send abnormal msg to tsdaemon failed, ret[%d]", deviceId_, ret);
     121              :         }
     122            2 :     }
     123              : 
     124           10 :     void AicpuMonitor::SetTaskInfo(const uint64_t taskIndex, const TaskInfoForMonitor &taskInfo)
     125              :     {
     126           10 :         if ((taskIndex < aicpuCoreNum_) && online_) {
     127            2 :             taskInfo_[taskIndex] = taskInfo;
     128              :         }
     129           10 :     }
     130              : 
     131            8 :     int32_t AicpuMonitor::SetTaskTimeoutFlag()
     132              :     {
     133            8 :         taskTimeout_ = FeatureCtrl::IsDoubleDieProduct() ?
     134              :                        AICPU_TASK_TIMEOUT_LONG : AICPU_TASK_TIMEOUT;
     135            8 :         taskTimeoutTick_ = taskTimeout_ * aicpu::GetSystemTickFreq();
     136            8 :         taskTimeoutFlag_ = true;
     137            8 :         return AICPU_SCHEDULE_OK;
     138              :     }
     139              : 
     140            9 :     void AicpuMonitor::SetTaskStartTime(const uint64_t taskIndex)
     141              :     {
     142            9 :         if ((taskTimeoutFlag_) && (online_)) {
     143            1 :             taskTimer_[taskIndex].SetStartTick(aicpu::GetSystemTick());
     144            1 :             taskTimer_[taskIndex].SetRunFlag(true);
     145              :         }
     146            9 :     }
     147              : 
     148            9 :     void AicpuMonitor::SetTaskEndTime(const uint64_t taskIndex)
     149              :     {
     150            9 :         if ((taskTimeoutFlag_) && (online_)) {
     151            1 :             taskTimer_[taskIndex].SetRunFlag(false);
     152            1 :             taskInfo_[taskIndex].isHwts = false;
     153              :         }
     154            9 :     }
     155              : 
     156            2 :     void AicpuMonitor::Work(AicpuMonitor *const monitor)
     157              :     {
     158            2 :         std::once_flag flag;
     159            3 :         while ((monitor != nullptr) && (!(monitor->done_))) {
     160            3 :             if (monitor->online_) {
     161              :                 // check and handle task timeout, for aicpu task of ts stream and aicpu stream
     162            0 :                 monitor->HandleTaskTimeout();
     163              :             }
     164              :             // call pulseNotifyFuncMap
     165            3 :             AicpuPulseNotify();
     166            3 :             std::call_once(flag, [&]() {
     167            2 :                 monitor->running_ = true;
     168            2 :                 if (sem_post(&monitor->sem_) != 0) {
     169            0 :                     aicpusd_err("sem post failed, %s", strerror(errno));
     170            0 :                     return;
     171              :                 }
     172              :             });
     173            3 :             (void)sleep(1U);
     174              :         }
     175            0 :     }
     176              : 
     177            4 :     int32_t AicpuMonitor::Run()
     178              :     {
     179            4 :         if (done_) {
     180            1 :             aicpusd_err("Fail to run monitor for it has been stopped");
     181            1 :             return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     182              :         }
     183            3 :         int32_t semRet = sem_init(&sem_, 0, 0U);
     184            3 :         if (semRet == -1) {
     185            1 :             aicpusd_err("sem init failed, %s.", strerror(errno));
     186            1 :             return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     187              :         }
     188              :         try {
     189            2 :             std::thread th(&AicpuMonitor::Work, this);
     190            2 :             th.detach();
     191            2 :         } catch(std::exception &e) {
     192            0 :             (void)sem_destroy(&sem_);
     193            0 :             aicpusd_err("create aicpu monitor thread object failed, %s", e.what());
     194            0 :             return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     195            0 :         }
     196              : 
     197            2 :         semRet = sem_wait(&sem_);
     198            2 :         if (semRet == -1) {
     199            0 :             (void)sem_destroy(&sem_);
     200            0 :             aicpusd_err("sem wait failed, %s.", strerror(errno));
     201            0 :             return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     202              :         }
     203            2 :         (void)sem_destroy(&sem_);
     204            2 :         if (!running_) {
     205            0 :             aicpusd_err("create aicpu monitor thread failed");
     206            0 :             return AICPU_SCHEDULE_ERROR_COMMON_ERROR;
     207              :         }
     208            2 :         aicpusd_info("aicpu monitor thread running");
     209              : 
     210            2 :         return AICPU_SCHEDULE_OK;
     211              :     }
     212              : 
     213           28 :     void AicpuMonitor::Stop()
     214              :     {
     215           28 :         const std::unique_lock<std::mutex> stopLock(mutex_);
     216           28 :         done_ = true;
     217           28 :     }
     218              : 
     219            2 :     void AicpuMonitor::HandleTaskTimeout()
     220              :     {
     221            2 :         if (!taskTimeoutFlag_) {
     222            1 :             return;
     223              :         }
     224              : 
     225            1 :         const uint64_t nowTick = aicpu::GetSystemTick();
     226            1 :         for (size_t coreIndex = 0UL; coreIndex < aicpuCoreNum_; ++coreIndex) {
     227            1 :             TaskTimer taskTimer;
     228            1 :             taskTimer.SetRunFlag(taskTimer_[coreIndex].GetRunFlag());
     229            1 :             taskTimer.SetStartTick(taskTimer_[coreIndex].GetStartTick());
     230            2 :             if (taskTimer.GetRunFlag() && (nowTick > taskTimer.GetStartTick()) &&
     231            1 :                 ((nowTick - taskTimer.GetStartTick()) >= taskTimeoutTick_)) {
     232              :                 // handle task timeout
     233            1 :                 std::string opname;
     234            1 :                 (void)aicpu::GetOpname(static_cast<uint32_t>(coreIndex), opname);
     235            1 :                 std::ostringstream oss;
     236            1 :                 oss << "Send timeout to tsdaemon, tsdaemon will kill aicpu-custom-sd process, thread index["
     237            1 :                     << coreIndex << "], op name[" << opname << "]";
     238            1 :                 if (taskInfo_[coreIndex].isHwts) {
     239            0 :                     oss << ", " << taskInfo_[coreIndex].DebugString();
     240              :                 }
     241            1 :                 aicpusd_err("%s.", oss.str().c_str());
     242            1 :                 SendKillMsgToTsd();
     243            1 :                 break;
     244            1 :             }
     245              :         }
     246              :     }
     247              : }  // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1