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

Generated by: LCOV version 2.0-1