LCOV - code coverage report
Current view: top level - aicpu_sharder - aicpu_async_event.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.7 % 189 177
Test Date: 2026-08-12 11:05:02 Functions: 95.0 % 20 19

            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 "aicpu_async_event.h"
      12              : #include <map>
      13              : #include <mutex>
      14              : #include "aicpu_sharder_log.h"
      15              : #include "aicpu_context.h"
      16              : #include "driver/ascend_hal.h"
      17              : #include "driver/ascend_hal_define.h"
      18              : 
      19              : namespace aicpu {
      20              : namespace {
      21              : struct AsyncEventInfo {
      22              :     uint32_t eventId;
      23              :     uint32_t subEventId;
      24              : 
      25              :     bool operator==(const AsyncEventInfo& info) const
      26              :     {
      27              :         return (eventId == info.eventId) && (subEventId == info.subEventId);
      28              :     }
      29              :     friend bool operator<(const AsyncEventInfo& info1, const AsyncEventInfo& info2);
      30              : };
      31              : 
      32           51 : inline bool operator<(const AsyncEventInfo& info1, const AsyncEventInfo& info2)
      33              : {
      34           85 :     return (info1.eventId < info2.eventId) ||
      35           85 :            ((info1.eventId == info2.eventId) && (info1.subEventId < info2.subEventId));
      36              : }
      37              : 
      38              : struct AsyncTaskInfo {
      39              :     uint64_t startTick;
      40              :     std::string opName;
      41              :     uint8_t waitType;
      42              :     uint32_t waitId;
      43              :     uint64_t taskId;
      44              :     uint32_t streamId;
      45              :     int32_t currentTimes;
      46              :     int32_t maxTimes;
      47              :     EventProcessCallBack taskCb;
      48              : };
      49              : 
      50              : std::mutex g_mapMutex;
      51              : std::map<AsyncEventInfo, AsyncTaskInfo> g_asyncTaskMap;
      52              : 
      53              : struct OpInfo {
      54              :     uint64_t taskId;
      55              :     uint32_t streamId;
      56              :     uint32_t threadIndex;
      57              : 
      58              :     bool operator==(const OpInfo& info) const
      59              :     {
      60              :         return (taskId == info.taskId) && (streamId == info.streamId) && (threadIndex == info.threadIndex);
      61              :     }
      62              :     friend bool operator<(const OpInfo& info1, const OpInfo& info2);
      63              : };
      64              : 
      65           30 : inline bool operator<(const OpInfo& info1, const OpInfo& info2)
      66              : {
      67           30 :     if (info1.taskId != info2.taskId) {
      68            7 :         return info1.taskId < info2.taskId;
      69              :     }
      70              : 
      71           23 :     if (info1.streamId != info2.streamId) {
      72            5 :         return info1.streamId < info2.streamId;
      73              :     }
      74              : 
      75           18 :     if (info1.threadIndex != info2.threadIndex) {
      76            6 :         return info1.threadIndex < info2.threadIndex;
      77              :     }
      78           12 :     return false;
      79              : }
      80              : std::mutex g_opMapMutex;
      81              : std::map<AsyncEventInfo, std::map<OpInfo, EventProcessCallBack>> g_opAsyncTaskMap;
      82              : 
      83            8 : bool GenTaskInfoFromCtx(AsyncTaskInfo& taskInfo)
      84              : {
      85            8 :     (void)aicpu::GetTaskAndStreamId(taskInfo.taskId, taskInfo.streamId);
      86            8 :     std::string waitIdValue;
      87            8 :     auto status = aicpu::GetThreadLocalCtx(aicpu::CONTEXT_KEY_WAIT_ID, waitIdValue);
      88            8 :     if (status != aicpu::AICPU_ERROR_NONE) {
      89            0 :         AICPUE_LOGE(
      90              :             "GetThreadLocalCtx failed, ret=%d, key=%s.", static_cast<int32_t>(status),
      91              :             aicpu::CONTEXT_KEY_WAIT_ID.c_str());
      92            0 :         return false;
      93              :     }
      94            8 :     int32_t waitId = 0;
      95              :     try {
      96            8 :         waitId = std::stoi(waitIdValue);
      97            1 :     } catch (...) {
      98            1 :         AICPUE_LOGE("Transfer string:%s to waitId failed", waitIdValue.c_str());
      99            1 :         return false;
     100            1 :     }
     101            7 :     taskInfo.waitId = static_cast<uint32_t>(waitId);
     102            7 :     std::string waitTypeValue;
     103            7 :     status = aicpu::GetThreadLocalCtx(aicpu::CONTEXT_KEY_WAIT_TYPE, waitTypeValue);
     104            7 :     if (status != aicpu::AICPU_ERROR_NONE) {
     105            0 :         AICPUE_LOGE(
     106              :             "GetThreadLocalCtx failed, ret=%d, key=%s.", static_cast<int32_t>(status),
     107              :             aicpu::CONTEXT_KEY_WAIT_TYPE.c_str());
     108            0 :         return false;
     109              :     }
     110            7 :     int32_t waitType = 0;
     111              :     try {
     112            7 :         waitType = std::stoi(waitTypeValue);
     113            1 :     } catch (...) {
     114            1 :         AICPUE_LOGE("Transfer string:%s to waitId failed", waitTypeValue.c_str());
     115            1 :         return false;
     116            1 :     }
     117            6 :     taskInfo.waitType = static_cast<uint8_t>(waitType);
     118            6 :     if (&aicpu::aicpuGetProfContext != nullptr) {
     119            6 :         const aicpu::aicpuProfContext_t& aicpuProfCtx = aicpu::aicpuGetProfContext();
     120            6 :         taskInfo.startTick = aicpuProfCtx.tickBeforeRun;
     121              :     }
     122            6 :     status = aicpu::GetOpname(aicpu::GetAicpuThreadIndex(), taskInfo.opName);
     123            6 :     if (status != aicpu::AICPU_ERROR_NONE) {
     124            0 :         AICPUE_LOGE("GetOpname failed, ret=%d.", static_cast<int32_t>(status));
     125            0 :         return false;
     126              :     }
     127            6 :     return true;
     128            8 : }
     129              : } // namespace
     130              : 
     131            3 : AsyncEventManager::AsyncEventManager() : notifyFunc_(nullptr) {}
     132              : 
     133            3 : AsyncEventManager::~AsyncEventManager() {}
     134              : 
     135           88 : AsyncEventManager& AsyncEventManager::GetInstance()
     136              : {
     137           88 :     static AsyncEventManager asyncEventMgr;
     138           88 :     return asyncEventMgr;
     139              : }
     140              : 
     141           39 : void AsyncEventManager::Register(const NotifyFunc& notify) { notifyFunc_ = notify; }
     142              : 
     143            7 : void AsyncEventManager::NotifyWait(void* const notifyParam, const uint32_t paramLen)
     144              : {
     145            7 :     if (notifyFunc_ != nullptr) {
     146            7 :         notifyFunc_(notifyParam, paramLen);
     147              :     }
     148            7 :     return;
     149              : }
     150              : 
     151            8 : bool AsyncEventManager::RegEventCb(
     152              :     const uint32_t eventId, const uint32_t subEventId, const EventProcessCallBack& cb, const int32_t times)
     153              : {
     154            8 :     if (cb == nullptr) {
     155            0 :         AICPUE_LOGE("AsyncEventManager RegEventCb failed, cb is nullptr.");
     156            0 :         return false;
     157              :     }
     158            8 :     AsyncTaskInfo taskInfo;
     159            8 :     taskInfo.taskCb = cb;
     160            8 :     taskInfo.currentTimes = 0;
     161            8 :     taskInfo.maxTimes = times;
     162            8 :     if (!GenTaskInfoFromCtx(taskInfo)) {
     163            2 :         AICPUE_LOGE("AsyncEventManager GenTaskInfoFromCtx failed.");
     164            2 :         return false;
     165              :     }
     166              :     AsyncEventInfo info;
     167            6 :     info.eventId = eventId;
     168            6 :     info.subEventId = subEventId;
     169              :     {
     170            6 :         const std::unique_lock<std::mutex> lk(g_mapMutex);
     171            6 :         const auto iter = g_asyncTaskMap.find(info);
     172            6 :         if (iter != g_asyncTaskMap.end()) {
     173            1 :             AICPUE_LOGE("AsyncEventManager RegEventCb failed.");
     174            1 :             return false;
     175              :         }
     176            5 :         g_asyncTaskMap[info] = taskInfo;
     177            6 :     }
     178              : 
     179            5 :     AICPUE_LOGI(
     180              :         "AsyncEventManager RegEventCb success, event_id[%u], subeventId[%u], taskId[%lu],"
     181              :         " streamId[%u], waitType[%u], waitId[%u], opName[%s], startTick[%lu].",
     182              :         eventId, subEventId, taskInfo.taskId, taskInfo.streamId, static_cast<uint32_t>(taskInfo.waitType),
     183              :         taskInfo.waitId, taskInfo.opName.c_str(), taskInfo.startTick);
     184            5 :     return true;
     185            8 : }
     186              : 
     187            2 : void AsyncEventManager::UnregEventCb(const uint32_t eventId, const uint32_t subEventId)
     188              : {
     189            2 :     const std::unique_lock<std::mutex> lk(g_mapMutex);
     190              :     AsyncEventInfo info;
     191            2 :     info.eventId = eventId;
     192            2 :     info.subEventId = subEventId;
     193            2 :     const auto iter = g_asyncTaskMap.find(info);
     194            2 :     if (iter == g_asyncTaskMap.end()) {
     195            2 :         AICPUE_LOGW("AsyncEventManager pass call UnregEventCb with eventId[%u], subEventId[%u]", eventId, subEventId);
     196            6 :         for (auto& kv : g_asyncTaskMap) {
     197            4 :             AICPUE_LOGI("UnregEventCb show: eventId[%u], subEventId[%u]", kv.first.eventId, kv.first.eventId);
     198              :         }
     199            2 :         return;
     200              :     }
     201            0 :     (void)g_asyncTaskMap.erase(iter);
     202            0 :     AICPUE_LOGI("AsyncEventManager UnregEventCb success, eventId[%u], subEventId[%u]", eventId, subEventId);
     203            2 : }
     204              : 
     205           13 : void AsyncEventManager::ProcessEvent(const uint32_t eventId, const uint32_t subEventId, void* const param)
     206              : {
     207           13 :     AICPUE_LOGI("AsyncEventManager proc eventId = %d, subEventId = %d", eventId, subEventId);
     208              :     AsyncEventInfo info;
     209           13 :     info.eventId = eventId;
     210           13 :     info.subEventId = subEventId;
     211           13 :     EventProcessCallBack taskCb = nullptr;
     212              :     {
     213           13 :         const std::unique_lock<std::mutex> lk(g_mapMutex);
     214           13 :         const auto iter = g_asyncTaskMap.find(info);
     215           13 :         if (iter == g_asyncTaskMap.end()) {
     216           10 :             AICPUE_LOGW("AsyncEventManager no async task to deal with.");
     217           10 :             return;
     218              :         }
     219            3 :         taskCb = iter->second.taskCb;
     220            3 :         iter->second.currentTimes++;
     221            3 :         if ((iter->second.currentTimes >= iter->second.maxTimes) && (iter->second.maxTimes >= 0)) {
     222            3 :             (void)g_asyncTaskMap.erase(iter);
     223              :         }
     224           13 :     }
     225            3 :     if (taskCb != nullptr) {
     226            3 :         taskCb(param);
     227              :     }
     228            3 :     AICPUE_LOGI("AsyncEventManager proc end!");
     229            3 :     return;
     230           13 : }
     231              : 
     232            7 : bool AsyncEventManager::RegOpEventCb(
     233              :     const uint32_t eventId, const uint32_t subEventId, const EventProcessCallBack& cb) const
     234              : {
     235            7 :     if (cb == nullptr) {
     236            1 :         AICPUE_LOGE(
     237              :             "AsyncEventManager RegOpEventCb on eventId[%u], subeventId[%u] failed, cb is nullptr.", eventId,
     238              :             subEventId);
     239            1 :         return false;
     240              :     }
     241            6 :     AsyncEventInfo info = {};
     242            6 :     info.eventId = eventId;
     243            6 :     info.subEventId = subEventId;
     244            6 :     OpInfo opInfo = {};
     245            6 :     (void)aicpu::GetTaskAndStreamId(opInfo.taskId, opInfo.streamId);
     246            6 :     opInfo.threadIndex = aicpu::GetAicpuThreadIndex();
     247              :     {
     248            6 :         const std::unique_lock<std::mutex> lk(g_opMapMutex);
     249            6 :         auto& opMap = g_opAsyncTaskMap[info];
     250            6 :         const auto iter = opMap.find(opInfo);
     251            6 :         if (iter != opMap.end()) {
     252            1 :             AICPUE_LOGE(
     253              :                 "AsyncEventManager RegOpEventCb failed for streamId[%u], taskId[%lu], threadIndex[%u]"
     254              :                 " has been registered on eventId[%u], subeventId[%u].",
     255              :                 opInfo.streamId, opInfo.taskId, opInfo.threadIndex, eventId, subEventId);
     256            1 :             return false;
     257              :         }
     258            5 :         opMap[opInfo] = cb;
     259            6 :     }
     260              : 
     261            5 :     AICPUE_LOGI(
     262              :         "AsyncEventManager RegOpEventCb success, event_id[%u], subeventId[%u], taskId[%lu], streamId[%u],"
     263              :         " threadIndex[%u].",
     264              :         eventId, subEventId, opInfo.taskId, opInfo.streamId, opInfo.threadIndex);
     265            5 :     return true;
     266              : }
     267              : 
     268            7 : void AsyncEventManager::UnregOpEventCb(const uint32_t eventId, const uint32_t subEventId) const
     269              : {
     270            7 :     const std::unique_lock<std::mutex> lk(g_opMapMutex);
     271            7 :     AsyncEventInfo info = {};
     272            7 :     info.eventId = eventId;
     273            7 :     info.subEventId = subEventId;
     274            7 :     auto iter = g_opAsyncTaskMap.find(info);
     275            7 :     if (iter == g_opAsyncTaskMap.end()) {
     276            1 :         AICPUE_LOGW("AsyncEventManager pass call UnregOpEventCb with eventId[%u], subEventId[%u]", eventId, subEventId);
     277            1 :         return;
     278              :     }
     279              : 
     280            6 :     OpInfo opInfo = {};
     281            6 :     (void)aicpu::GetTaskAndStreamId(opInfo.taskId, opInfo.streamId);
     282            6 :     opInfo.threadIndex = aicpu::GetAicpuThreadIndex();
     283            6 :     auto& opMap = iter->second;
     284            6 :     const auto opIter = opMap.find(opInfo);
     285            6 :     if (opIter == opMap.end()) {
     286            1 :         AICPUE_LOGW(
     287              :             "AsyncEventManager pass call UnregOpEventCb with streamId[%u], taskId[%lu], threadIndex[%u].",
     288              :             opInfo.streamId, opInfo.taskId, opInfo.threadIndex);
     289            1 :         return;
     290              :     }
     291            5 :     (void)opMap.erase(opIter);
     292            5 :     if (opMap.empty()) {
     293            2 :         (void)g_opAsyncTaskMap.erase(iter);
     294              :     }
     295            5 :     AICPUE_LOGI(
     296              :         "AsyncEventManager UnregEventCb success, eventId[%u], subEventId[%u], streamId[%u], taskId[%lu],"
     297              :         " threadIndex[%u].",
     298              :         eventId, subEventId, opInfo.streamId, opInfo.taskId, opInfo.threadIndex);
     299            7 : }
     300              : 
     301            5 : void AsyncEventManager::ProcessOpEvent(const uint32_t eventId, const uint32_t subEventId, void* const param) const
     302              : {
     303            5 :     AICPUE_LOGI("AsyncEventManager ProcessOpEvent eventId = %u, subEventId = %u", eventId, subEventId);
     304            5 :     AsyncEventInfo info = {};
     305            5 :     info.eventId = eventId;
     306            5 :     info.subEventId = subEventId;
     307              :     {
     308            5 :         const std::unique_lock<std::mutex> lk(g_opMapMutex);
     309            5 :         const auto iter = g_opAsyncTaskMap.find(info);
     310            5 :         if (iter == g_opAsyncTaskMap.end()) {
     311            4 :             AICPUE_LOGW("AsyncEventManager no async task to deal with.");
     312            4 :             return;
     313              :         }
     314            1 :         const auto& opMap = iter->second;
     315            3 :         for (auto& kv : opMap) {
     316            2 :             const auto& opInfo = kv.first;
     317            2 :             EventProcessCallBack taskCb = kv.second;
     318            2 :             AICPUE_LOGI(
     319              :                 "AsyncEventManager ProcessOpEvent for streamId[%u], taskId[%lu], threadIndex[%u]", opInfo.streamId,
     320              :                 opInfo.taskId, opInfo.threadIndex);
     321            2 :             taskCb(param);
     322            2 :         }
     323            5 :     }
     324            1 :     AICPUE_LOGI("AsyncEventManager ProcessOpEvent eventId = %u, subEventId = %u end!", eventId, subEventId);
     325            1 :     return;
     326              : }
     327              : } // namespace aicpu
     328              : 
     329            2 : void AicpuNotifyWait(void* notifyParam, const uint32_t paramLen)
     330              : {
     331            2 :     aicpu::AsyncEventManager::GetInstance().NotifyWait(notifyParam, paramLen);
     332            2 :     return;
     333              : }
     334              : 
     335            1 : bool AicpuRegEventCb(const uint32_t eventId, const uint32_t subEventId, const aicpu::EventProcessCallBack& cb)
     336              : {
     337            1 :     return aicpu::AsyncEventManager::GetInstance().RegEventCb(eventId, subEventId, cb);
     338              : }
     339              : 
     340            0 : bool AicpuRegEventCbWithTimes(
     341              :     const uint32_t eventId, const uint32_t subEventId, const aicpu::EventProcessCallBack& cb, const int32_t times)
     342              : {
     343            0 :     return aicpu::AsyncEventManager::GetInstance().RegEventCb(eventId, subEventId, cb, times);
     344              : }
     345              : 
     346            1 : void AicpuUnregEventCb(const uint32_t eventId, const uint32_t subEventId)
     347              : {
     348            1 :     aicpu::AsyncEventManager::GetInstance().UnregEventCb(eventId, subEventId);
     349            1 : }
     350              : 
     351            3 : bool AicpuRegOpEventCb(const uint32_t eventId, const uint32_t subEventId, const aicpu::EventProcessCallBack& cb)
     352              : {
     353            3 :     return aicpu::AsyncEventManager::GetInstance().RegOpEventCb(eventId, subEventId, cb);
     354              : }
     355              : 
     356            3 : void AicpuUnregOpEventCb(const uint32_t eventId, const uint32_t subEventId)
     357              : {
     358            3 :     aicpu::AsyncEventManager::GetInstance().UnregOpEventCb(eventId, subEventId);
     359            3 : }
        

Generated by: LCOV version 2.0-1