LCOV - code coverage report
Current view: top level - aicpu_processer - ae_kernel_lib_aicpu.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.8 % 144 102
Test Date: 2026-08-12 11:05:02 Functions: 100.0 % 10 10

            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 "ae_kernel_lib_aicpu.hpp"
      12              : #include <sstream>
      13              : #include <string>
      14              : #include <memory>
      15              : #include "securec.h"
      16              : #include "aicpu_event_struct.h"
      17              : #ifdef AICPU_PROFILING
      18              : #include "aicpu_prof/profiling_adp.h"
      19              : #endif
      20              : 
      21              : namespace cce {
      22              : namespace {
      23              : // aicpu device side blockdim entry function name
      24              : constexpr char const* kRunFuncName = "RunCpuKernelWithBlock";
      25              : // 动态白名单
      26              : constexpr size_t MAX_WHITE_LIST_SIZE = 100UL;
      27              : // The interface to call a aicpu kernel api
      28              : using AicpuOpFuncPtr = uint32_t (*)(void*);
      29              : // The interface to call a aicpu kernel api with blockdim
      30              : using AicpuOpFuncPtrWithBlockDim = uint32_t (*)(void*, void*);
      31              : 
      32              : struct BlkDimInfo {
      33              :     uint32_t blockNum; // blockdim number
      34              :     uint32_t blockId;  // block id
      35              : };
      36              : } // namespace
      37              : 
      38              : AIKernelsLibAiCpu* AIKernelsLibAiCpu::instance_ = nullptr;
      39              : std::mutex AIKernelsLibAiCpu::mtx_;
      40              : 
      41              : // SINGLETON object get interface
      42          135 : AIKernelsLibAiCpu* AIKernelsLibAiCpu::GetInstance()
      43              : {
      44          135 :     const std::lock_guard<std::mutex> lockGuard(mtx_);
      45          136 :     if (instance_ != nullptr) {
      46          129 :         return instance_;
      47              :     } else {
      48            7 :         instance_ = new (std::nothrow) AIKernelsLibAiCpu();
      49            7 :         if (instance_ == nullptr) {
      50            0 :             return nullptr;
      51              :         }
      52            7 :         if (instance_->Init() != AE_STATUS_SUCCESS) {
      53            2 :             AE_RUN_WARN_LOG(AE_MODULE_ID, "AIKernelsLibAiCpu init failed.");
      54            2 :             delete instance_;
      55            2 :             instance_ = nullptr;
      56            2 :             return nullptr;
      57              :         }
      58            5 :         return instance_;
      59              :     }
      60          136 : }
      61              : 
      62              : // SINGLETON object destroy interface
      63            9 : void AIKernelsLibAiCpu::DestroyInstance()
      64              : {
      65            9 :     const std::lock_guard<std::mutex> lockGuard(mtx_);
      66            9 :     if (instance_ == nullptr) {
      67            5 :         return;
      68              :     }
      69            4 :     delete instance_;
      70            4 :     instance_ = nullptr;
      71            9 : }
      72              : 
      73          121 : aeStatus_t AIKernelsLibAiCpu::GetKernelNameAndKernelSoName(
      74              :     char_t* kernelName, char_t* kernelSoName, const char_t* paramKernelSo,
      75              :     const aicpu::HwtsCceKernel* cceKernelBase) const
      76              : {
      77          121 :     const auto paramKernelName = PtrToPtr<const void, const char_t>(ValueToPtr(cceKernelBase->kernelName));
      78              :     // A nullptr kernel op name is not supported.
      79          120 :     if (paramKernelName == nullptr) {
      80            0 :         AE_ERR_LOG(AE_MODULE_ID, "Input param kernelName is null.");
      81            0 :         return AE_STATUS_BAD_PARAM;
      82              :     }
      83          120 :     errno_t retCpy = strncpy_s(&kernelName[0], AE_MAX_KERNEL_NAME + 1U, paramKernelName, AE_MAX_KERNEL_NAME);
      84          120 :     if (retCpy != EOK) {
      85            0 :         AE_ERR_LOG(AE_MODULE_ID, "copy paramKernelName failed, retCpy=%d.", retCpy);
      86            0 :         return AE_STATUS_INNER_ERROR;
      87              :     }
      88              : 
      89          120 :     retCpy = strncpy_s(&kernelSoName[0], AE_MAX_SO_NAME + 1U, paramKernelSo, AE_MAX_SO_NAME);
      90          120 :     if (retCpy != EOK) {
      91            0 :         AE_ERR_LOG(AE_MODULE_ID, "copy paramKernelSo failed, retCpy=%d.", retCpy);
      92            0 :         return AE_STATUS_INNER_ERROR;
      93              :     }
      94          120 :     return AE_STATUS_SUCCESS;
      95              : }
      96              : 
      97              : // Implement call a aicpu op kernel interface
      98          121 : int32_t AIKernelsLibAiCpu::CallKernelApi(const aicpu::KernelType kernelType, const void* const kernelBase)
      99              : {
     100          121 :     const aicpu::HwtsCceKernel* cceKernelBase = static_cast<const aicpu::HwtsCceKernel*>(kernelBase);
     101          121 :     if (cceKernelBase == nullptr) {
     102            0 :         AE_ERR_LOG(AE_MODULE_ID, "Input param kernelBase is nullptr.");
     103            0 :         return AE_STATUS_BAD_PARAM;
     104              :     }
     105              : 
     106          121 :     char_t* paramKernelSo = PtrToPtr<void, char_t>(ValueToPtr(cceKernelBase->kernelSo));
     107              :     // Finding a cce op kernel from the whole process space is not supported.
     108              :     // Only get aicpu op kernel a specific so lib.so, kernelSo should not be NULL.
     109          121 :     if (paramKernelSo == nullptr) {
     110            0 :         AE_ERR_LOG(AE_MODULE_ID, "Input param kernelSo is NULL.");
     111            0 :         return AE_STATUS_BAD_PARAM;
     112              :     }
     113          121 :     char_t kernelName[AE_MAX_KERNEL_NAME + 1U] = {};
     114          121 :     char_t kernelSoName[AE_MAX_SO_NAME + 1U] = {};
     115          121 :     aeStatus_t ret = AE_STATUS_SUCCESS;
     116          121 :     ret = GetKernelNameAndKernelSoName(kernelName, kernelSoName, paramKernelSo, cceKernelBase);
     117          120 :     if (ret != AE_STATUS_SUCCESS) {
     118            0 :         AE_ERR_LOG(AE_MODULE_ID, "get kernelName and kernelSoName failed, ret=%u.", ret);
     119            0 :         return ret;
     120              :     }
     121          120 :     void* funcAddr = nullptr;
     122          120 :     ret = soMngr_.GetApi(kernelType, &kernelSoName[0], &kernelName[0], &funcAddr);
     123          121 :     if (ret != AE_STATUS_SUCCESS) {
     124            0 :         AE_ERR_LOG(AE_MODULE_ID, "Get %s api from %s failed.", &kernelName[0], &kernelSoName[0]);
     125            0 :         return ret;
     126              :     }
     127          121 :     if (funcAddr == nullptr) {
     128            0 :         AE_ERR_LOG(AE_MODULE_ID, "Get %s api from %s success, but func is nullptr", &kernelName[0], &kernelSoName[0]);
     129            0 :         return AE_STATUS_INNER_ERROR;
     130              :     }
     131              : 
     132          121 :     (void)aicpu::SetOpname(kernelName);
     133              : 
     134          121 :     const uint32_t result = RunAicpuFunc(kernelBase, funcAddr, &kernelName[0]);
     135          119 :     return static_cast<int32_t>(TransformKernelErrorCode(result, &kernelName[0], &kernelSoName[0]));
     136              : }
     137              : 
     138          120 : uint32_t AIKernelsLibAiCpu::RunAicpuFunc(
     139              :     const void* const kernelBase, void* const funcAddr, const char_t* const funcName) const
     140              : {
     141          120 :     uint32_t result = 0U;
     142          120 :     const auto cceKernelBase = static_cast<const aicpu::HwtsCceKernel*>(kernelBase);
     143          120 :     void* const param = ValueToPtr(cceKernelBase->paramBase);
     144              : #ifdef AICPU_PROFILING
     145              :     uint64_t runStartTime;
     146              :     uint64_t runStartTick;
     147              :     aicpu::GetMicrosAndSysTick(runStartTime, runStartTick);
     148              : #endif
     149          119 :     (void)aicpu::SetBlockIdxAndBlockNum(cceKernelBase->blockId, cceKernelBase->blockNum);
     150          119 :     if (strcmp(funcName, kRunFuncName) == 0) {
     151            0 :         AE_INFO_LOG(AE_MODULE_ID, "opFuncPtr is RunCpuKernelWithBlockDim.");
     152            0 :         struct BlkDimInfo blkInfo = {};
     153            0 :         blkInfo.blockId = cceKernelBase->blockId;
     154            0 :         blkInfo.blockNum = cceKernelBase->blockNum;
     155            0 :         const auto opFuncPtr = PtrToFunctionPtr<void, AicpuOpFuncPtrWithBlockDim>(funcAddr);
     156            0 :         result = opFuncPtr(param, &blkInfo);
     157              :     } else {
     158          119 :         const auto opFuncPtr = PtrToFunctionPtr<void, AicpuOpFuncPtr>(funcAddr);
     159          119 :         result = opFuncPtr(param);
     160              :     }
     161              : 
     162              : #ifdef AICPU_PROFILING
     163              :     uint64_t runEndTime;
     164              :     uint64_t runEndTick;
     165              :     aicpu::GetMicrosAndSysTick(runEndTime, runEndTick);
     166              : 
     167              :     const std::shared_ptr<aicpu::ProfMessage> profHandle = aicpu::GetProfHandle();
     168              :     if (profHandle != nullptr) {
     169              :         std::string opName = "null";
     170              :         (void)aicpu::GetOpname(aicpu::GetAicpuThreadIndex(), opName);
     171              :         (void)profHandle->SetRunStartTime(runStartTime)
     172              :             ->SetRunStartTick(runStartTick)
     173              :             ->SetRunEndTime(runEndTime)
     174              :             ->SetRunEndTick(runEndTick);
     175              :     }
     176              : #endif
     177          119 :     return result;
     178              : }
     179              : 
     180            6 : aeStatus_t AIKernelsLibAiCpu::BatchLoadKernelSo(const aicpu::KernelType kernelType, std::vector<std::string>& soVec)
     181              : {
     182            6 :     if (soVec.empty()) {
     183            1 :         AE_ERR_LOG(AE_MODULE_ID, "so vec is empty.");
     184            1 :         return AE_STATUS_SUCCESS;
     185              :     }
     186           12 :     for (auto& soName : soVec) {
     187            7 :         const aeStatus_t ret = soMngr_.LoadSo(kernelType, soName);
     188            7 :         if (ret != AE_STATUS_SUCCESS) {
     189            5 :             AE_RUN_WARN_LOG(AE_MODULE_ID, "Load so %s failed.", soName.c_str());
     190            5 :             continue;
     191              :         }
     192              :     }
     193            5 :     return AE_STATUS_SUCCESS;
     194              : }
     195              : 
     196            2 : aeStatus_t AIKernelsLibAiCpu::CloseSo(const char_t* const soName)
     197              : {
     198            2 :     if (soName == nullptr) {
     199            1 :         AE_ERR_LOG(AE_MODULE_ID, "soName is null.");
     200            1 :         return AE_STATUS_BAD_PARAM;
     201              :     }
     202            1 :     const std::string kernelSoName(soName);
     203            1 :     return soMngr_.CloseSo(kernelSoName);
     204            1 : }
     205              : 
     206          119 : aeStatus_t AIKernelsLibAiCpu::TransformKernelErrorCode(
     207              :     const uint32_t errCode, const char_t* const kernelName, const char_t* const soName) const
     208              : {
     209          119 :     if (likely(errCode == 0U)) {
     210          109 :         return AE_STATUS_SUCCESS;
     211              :     }
     212              : 
     213           10 :     if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_END_OF_SEQUENCE_FLAG)) {
     214            0 :         AE_INFO_LOG(AE_MODULE_ID, "Get aicpu end of sequence flag.");
     215            0 :         return AE_STATUS_END_OF_SEQUENCE;
     216              :     }
     217           10 :     if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_TASK_WATI_FLAG)) {
     218            0 :         AE_INFO_LOG(AE_MODULE_ID, "Get aicpu task wait flag.");
     219            0 :         return AE_STATUS_TASK_WAIT;
     220              :     }
     221              : 
     222           10 :     if (!aicpu::IsCustAicpuSd()) {
     223           10 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_SILENT_FAULT)) {
     224            0 :             AE_INFO_LOG(AE_MODULE_ID, "Get aicpu silent fault flag");
     225            0 :             return AE_STATUS_SILENT_FAULT;
     226              :         }
     227           10 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_DETECT_FAULT)) {
     228            0 :             AE_INFO_LOG(AE_MODULE_ID, "Get aicpu detect fault flag");
     229            0 :             return AE_STATUS_DETECT_FAULT;
     230              :         }
     231              : 
     232           10 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_DETECT_FAULT_NORAS)) {
     233            0 :             AE_INFO_LOG(AE_MODULE_ID, "Get aicpu detect fault no Ras flag");
     234            0 :             return AE_STATUS_DETECT_FAULT_NORAS;
     235              :         }
     236              : 
     237           10 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_DETECT_LOW_BIT_FAULT)) {
     238            0 :             AE_INFO_LOG(AE_MODULE_ID, "Get aicpu detect low-bit fault flag");
     239            0 :             return AE_STATUS_DETECT_LOW_BIT_FAULT;
     240              :         }
     241              : 
     242           10 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_DETECT_LOW_BIT_FAULT_NORAS)) {
     243            0 :             AE_INFO_LOG(AE_MODULE_ID, "Get aicpu detect low-bit fault no Ras flag");
     244            0 :             return AE_STATUS_DETECT_LOW_BIT_FAULT_NORAS;
     245              :         }
     246              :     }
     247              : 
     248           10 :     AE_ERR_LOG(AE_MODULE_ID, "call aicpu api %s in %s failed, ret:%u.", kernelName, soName, errCode);
     249              :     // other error code: transform to inner_error
     250           10 :     return static_cast<aeStatus_t>(errCode);
     251              : }
     252              : 
     253            2 : void AIKernelsLibAiCpu::DeleteSoInWhiteList(const std::string& soName)
     254              : {
     255            2 :     const std::lock_guard<std::mutex> lk(soWhiteListMtx_);
     256            2 :     if (soWhiteList_.empty()) {
     257            1 :         AE_INFO_LOG(AE_MODULE_ID, "so white list is empty");
     258            1 :         return;
     259              :     }
     260            1 :     auto iter = soWhiteList_.find(soName);
     261            1 :     if (iter != soWhiteList_.end()) {
     262            0 :         soWhiteList_.erase(iter);
     263            0 :         AE_INFO_LOG(AE_MODULE_ID, "erase so:%s in white list", soName.c_str());
     264              :     } else {
     265            1 :         AE_INFO_LOG(AE_MODULE_ID, "so:%s not in white list", soName.c_str());
     266              :     }
     267            2 : }
     268              : 
     269            2 : aeStatus_t AIKernelsLibAiCpu::AddSoInWhiteList(const std::string& soName)
     270              : {
     271            2 :     const std::lock_guard<std::mutex> lk(soWhiteListMtx_);
     272            2 :     if (soWhiteList_.size() >= MAX_WHITE_LIST_SIZE) {
     273            0 :         AE_ERR_LOG(AE_MODULE_ID, "white list is full");
     274            0 :         return AE_STATUS_INNER_ERROR;
     275              :     }
     276            2 :     auto iter = soWhiteList_.find(soName);
     277            2 :     if (iter == soWhiteList_.end()) {
     278            2 :         soWhiteList_[soName] = soName;
     279            2 :         AE_INFO_LOG(AE_MODULE_ID, "add so:%s in white list, list size:%zu", soName.c_str(), soWhiteList_.size());
     280              :     } else {
     281            0 :         AE_INFO_LOG(AE_MODULE_ID, "so:%s already in white list, size:%zu", soName.c_str(), soWhiteList_.size());
     282              :     }
     283            2 :     return AE_STATUS_SUCCESS;
     284            2 : }
     285              : } // namespace cce
        

Generated by: LCOV version 2.0-1