LCOV - code coverage report
Current view: top level - aicpu_processer - ae_kernel_lib_aicpu_kfc.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.4 % 109 104
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 11 11

            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_kfc.h"
      12              : #include <sstream>
      13              : #include <string>
      14              : #include <memory>
      15              : #include <dlfcn.h>
      16              : #include "securec.h"
      17              : #include "aicpu_event_struct.h"
      18              : #ifdef AICPU_PROFILING
      19              : #include "aicpu_prof/profiling_adp.h"
      20              : #endif
      21              : namespace cce {
      22              :     AIKernelsLibAiCpuKFC *AIKernelsLibAiCpuKFC::instance_ = nullptr;
      23              : 
      24              :     // SINGLETON object get interface
      25            9 :     AIKernelsLibAiCpuKFC *AIKernelsLibAiCpuKFC::GetInstance()
      26              :     {
      27              :         static std::once_flag flag;
      28            9 :         std::call_once(flag, []() {
      29            1 :             instance_ = new(std::nothrow) AIKernelsLibAiCpuKFC();
      30            1 :             if ((instance_ != nullptr) && (instance_->Init() != AE_STATUS_SUCCESS)) {
      31            0 :                 AE_RUN_WARN_LOG(AE_MODULE_ID,  "AIKernelsLibAiCpuKFC init failed.");
      32            0 :                 delete instance_;
      33            0 :                 instance_ = nullptr;
      34              :             }
      35            1 :             AE_RUN_INFO_LOG(AE_MODULE_ID,  "AIKernelsLibAiCpuKFC init finish.");
      36            1 :         });
      37            9 :         return instance_;
      38              :     }
      39              : 
      40            1 :     aeStatus_t AIKernelsLibAiCpuKFC::Init()
      41              :     {
      42            1 :         apiCacher_.clear();
      43            1 :         return AIKernelsLibBase::Init();
      44              :     }
      45              : 
      46              :     // SINGLETON object destroy interface
      47            5 :     void AIKernelsLibAiCpuKFC::DestroyInstance()
      48              :     {
      49            5 :         if (instance_ == nullptr) {
      50            4 :             return;
      51              :         }
      52            1 :         delete instance_;
      53            1 :         instance_ = nullptr;
      54              :     }
      55              : 
      56           12 :     aeStatus_t AIKernelsLibAiCpuKFC::GetKernelName(char_t *&kernelName, const aicpu::HwtsCceKernel *cceKernelBase) const
      57              :     {
      58           12 :         kernelName = PtrToPtr<void, char_t>(ValueToPtr(cceKernelBase->kernelName));
      59           12 :         if (static_cast<bool>(unlikely(kernelName == nullptr))) {
      60            1 :             AE_ERR_LOG(AE_MODULE_ID, "Input param kernelName is null.");
      61            1 :             return AE_STATUS_BAD_PARAM;
      62              :         }
      63           11 :         uint32_t len = strnlen(kernelName, AE_MAX_KERNEL_NAME + 1);
      64           11 :         if (static_cast<bool>(unlikely(len > AE_MAX_KERNEL_NAME))) {
      65            1 :             AE_ERR_LOG(AE_MODULE_ID, "KernelName length is not supported, len=%d.", len);
      66            1 :             kernelName = nullptr;
      67            1 :             return AE_STATUS_INNER_ERROR;
      68              :         }
      69           10 :         return AE_STATUS_SUCCESS;
      70              :     }
      71              : 
      72            8 :     int32_t AIKernelsLibAiCpuKFC::GetApiGlobal(AicpuKFCOpFuncPtr &opFuncPtr, const char_t *kernelName) const
      73              :     {
      74            8 :         opFuncPtr = PtrToFunctionPtr<void, AicpuKFCOpFuncPtr>(dlsym(RTLD_DEFAULT, kernelName));
      75            8 :         if (static_cast<bool>(unlikely(opFuncPtr == nullptr))) {
      76            7 :             AE_ERR_LOG(AE_MODULE_ID, "Get KFC api by global failed, func is nullptr, kernelName[%s], dlerror[%s]",
      77              :                 kernelName, dlerror());
      78            7 :             return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
      79              :         }
      80            1 :         return AE_STATUS_SUCCESS;
      81              :     }
      82              : 
      83            7 :     int32_t AIKernelsLibAiCpuKFC::GetApiWhenSonameNotEmpty(const aicpu::KernelType kernelType, const uint32_t soNameLen,
      84              :         const char_t *kernelSoName, const char_t *kernelName, void* &funcAddr)
      85              :     {
      86            7 :         if (static_cast<bool>(unlikely(soNameLen > AE_MAX_SO_NAME))) {
      87            2 :             AE_RUN_WARN_LOG(AE_MODULE_ID, "kernelSoName length is not supported, len=%d.", soNameLen);
      88            2 :             return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
      89              :         }
      90              : 
      91            5 :         const auto ret = soMngr_.GetApi(kernelType, kernelSoName, kernelName, &funcAddr);
      92            5 :         if (static_cast<bool>(unlikely(ret != AE_STATUS_SUCCESS))) {
      93            3 :             AE_RUN_WARN_LOG(AE_MODULE_ID, "Get %s api from %s unsuccessfully.", kernelName, kernelSoName);
      94            3 :             return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
      95              :         }
      96              : 
      97            2 :         if (static_cast<bool>(unlikely(funcAddr == nullptr))) {
      98            1 :             AE_RUN_WARN_LOG(AE_MODULE_ID, "Get %s api from %s success, but func is nullptr",
      99              :                             kernelName, kernelSoName);
     100            1 :             return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
     101              :         }
     102              : 
     103            1 :         return AE_STATUS_SUCCESS;
     104              :     }
     105              : 
     106            9 :     int32_t AIKernelsLibAiCpuKFC::GetApiBySoname(const aicpu::KernelType kernelType, const char_t *kernelSoName,
     107              :                                                  AicpuKFCOpFuncPtr &opFuncPtr, const char_t *kernelName)
     108              :     {
     109            9 :         const uint32_t soNameLen = strnlen(kernelSoName, AE_MAX_SO_NAME + 1);
     110            9 :         if (soNameLen == 0) {
     111            2 :             if (GetApiGlobal(opFuncPtr, kernelName) != AE_STATUS_SUCCESS) {
     112            1 :                 AE_ERR_LOG(AE_MODULE_ID, "Get KFC api by global failed, kernelSoName[%s], soNameLen[%u], kernelName[%s].",
     113              :                            kernelSoName, soNameLen, kernelName);
     114            1 :                 return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
     115              :             }
     116              :         } else {
     117            7 :             void *funcAddr = nullptr;
     118            7 :             if (GetApiWhenSonameNotEmpty(kernelType, soNameLen, kernelSoName, kernelName, funcAddr) == AE_STATUS_SUCCESS) {
     119            1 :                 opFuncPtr = PtrToFunctionPtr<void, AicpuKFCOpFuncPtr>(funcAddr);
     120              :             } else {
     121            6 :                 if (GetApiGlobal(opFuncPtr, kernelName) != AE_STATUS_SUCCESS) {
     122            6 :                     AE_ERR_LOG(AE_MODULE_ID,
     123              :                                "Get KFC api by soname and global both failed, kernelSoName[%s], soNameLen[%u], kernelName[%s].",
     124              :                                kernelSoName, soNameLen, kernelName);
     125            6 :                     return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
     126              :                 }
     127              :             }
     128              :         }
     129              : 
     130            2 :         return AE_STATUS_SUCCESS;
     131              :     }
     132              : 
     133              : 
     134              :     // Implement call a aicpu op kernel interface
     135           12 :     int32_t AIKernelsLibAiCpuKFC::CallKernelApi(const aicpu::KernelType kernelType, const void * const kernelBase)
     136              :     {
     137              :         (void)kernelType;
     138           12 :         const aicpu::HwtsCceKernel *cceKernelBase = static_cast<const aicpu::HwtsCceKernel *>(kernelBase);
     139           12 :         if (static_cast<bool>(unlikely(cceKernelBase == nullptr))) {
     140            1 :             AE_ERR_LOG(AE_MODULE_ID, "Input param KFC kernelBase is nullptr.");
     141            1 :             return static_cast<int32_t>(AE_STATUS_BAD_PARAM);
     142              :         }
     143              : 
     144           11 :         char_t *kernelName = nullptr;
     145           11 :         aeStatus_t ret = GetKernelName(kernelName, cceKernelBase);
     146           11 :         if (static_cast<bool>(unlikely((ret != AE_STATUS_SUCCESS)))) {
     147            1 :             AE_ERR_LOG(AE_MODULE_ID, "get KFC kernelName failed, ret=%u.", ret);
     148            1 :             return static_cast<int32_t>(ret);
     149              :         }
     150           10 :         AicpuKFCOpFuncPtr opFuncPtr = nullptr;
     151           10 :         AE_RW_LOCK_RD_LOCK(&rwLock_);
     152           20 :         auto apiIter = apiCacher_.find(kernelName);
     153           10 :         if (apiIter != apiCacher_.end()) {
     154            1 :             opFuncPtr = apiIter->second;
     155              :         } else {
     156            9 :             AE_RW_LOCK_UN_LOCK(&rwLock_);
     157            9 :             AE_RW_LOCK_WR_LOCK(&rwLock_);
     158           18 :             apiIter = apiCacher_.find(kernelName);
     159            9 :             if (apiIter != apiCacher_.end()) {
     160            0 :                 opFuncPtr = apiIter->second;
     161              :             } else {
     162            9 :                 char_t *kernelSoName = PtrToPtr<void, char_t>(ValueToPtr(cceKernelBase->kernelSo));
     163            9 :                 if (GetApiBySoname(kernelType, kernelSoName, opFuncPtr, kernelName) != AE_STATUS_SUCCESS) {
     164            7 :                     AE_RW_LOCK_UN_LOCK(&rwLock_);
     165            7 :                     AE_ERR_LOG(AE_MODULE_ID, "Get KFC kernel api failed, kernelSoName[%s], kernelName[%s].",
     166              :                                kernelSoName, kernelName);
     167            7 :                     return static_cast<int32_t>(AE_STATUS_INNER_ERROR);
     168              :                 }
     169            6 :                 apiCacher_[kernelName] = opFuncPtr;
     170              :             }
     171              :         }
     172              : 
     173            3 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     174            3 :         AE_INFO_LOG(AE_MODULE_ID, "Get KFC kernelname[%s] func success", kernelName);
     175            3 :         const uint32_t result = RunAicpuFunc(kernelBase, opFuncPtr);
     176            3 :         return static_cast<int32_t>(TransformKernelErrorCode(result, kernelName));
     177              :     }
     178              : 
     179            4 :     uint32_t AIKernelsLibAiCpuKFC::RunAicpuFunc(const void* const kernelBase,
     180              :                                                 AicpuKFCOpFuncPtr &opFuncPtr) const
     181              :     {
     182            4 :         const auto cceKernelBase = static_cast<const aicpu::HwtsCceKernel *>(kernelBase);
     183            4 :         void * const param = ValueToPtr(static_cast<const uintptr_t>(cceKernelBase->paramBase));
     184            4 :         uint32_t result = 0U;
     185            4 :         if (&aicpu::SetBlockIdxAndBlockNum != nullptr) {
     186            0 :             (void)aicpu::SetBlockIdxAndBlockNum(cceKernelBase->blockId, cceKernelBase->blockNum);
     187              :         }
     188              : #ifdef AICPU_PROFILING
     189              :         uint64_t runStartTick;
     190              :         uint64_t runStartTime;
     191              :         const std::shared_ptr<aicpu::ProfMessage> profHandle = aicpu::GetProfHandle();
     192              :         if (static_cast<bool>(unlikely(profHandle != nullptr))) {
     193              :             aicpu::GetMicrosAndSysTick(runStartTime, runStartTick);
     194              :         }
     195              : #endif
     196            4 :         result = opFuncPtr(param);
     197              : #ifdef AICPU_PROFILING
     198              :         if (static_cast<bool>(unlikely(profHandle != nullptr))) {
     199              :             uint64_t runEndTick;
     200              :             uint64_t runEndTime;
     201              :             aicpu::GetMicrosAndSysTick(runEndTime, runEndTick);
     202              :             (void)profHandle->SetRunStartTime(runStartTime)
     203              :                 ->SetRunStartTick(runStartTick)
     204              :                 ->SetRunEndTime(runEndTime)
     205              :                 ->SetRunEndTick(runEndTick);
     206              :         }
     207              : #endif
     208            4 :         return result;
     209              :     }
     210              : 
     211            6 :     int32_t AIKernelsLibAiCpuKFC::TransformKernelErrorCode(const uint32_t errCode,
     212              :                                                            const char_t * const kernelName) const
     213              :     {
     214            6 :         if (likely(errCode == 0U)) {
     215            2 :             return AE_STATUS_SUCCESS;
     216              :         }
     217              : 
     218            4 :         if (errCode == static_cast<uint32_t>(AicpuOpErrorCode::AICPU_TASK_ABORT)) {
     219            1 :             AE_INFO_LOG(AE_MODULE_ID, "Get kfc task abort flag");
     220            1 :             return AE_STATUS_TASK_ABORT;
     221              :         }
     222              : 
     223            3 :         if ((errCode >= static_cast<uint32_t>(AicpuOpErrorCode::AICPU_KFC_PASSTHROUGH_START)) &&
     224              :            (errCode <= static_cast<uint32_t>(AicpuOpErrorCode::AICPU_KFC_PASSTHROUGH_END))) {
     225            1 :             AE_INFO_LOG(AE_MODULE_ID, "KFC %s run passthrough ret[%u]", kernelName, errCode);
     226            1 :             return static_cast<int32_t>(errCode);
     227              :         }
     228              : 
     229            2 :         AE_ERR_LOG(AE_MODULE_ID, "KFC %s run failed ret[%u]", kernelName, errCode);
     230            2 :         return AE_STATUS_TASK_FAIL;
     231              :     }
     232              : }
        

Generated by: LCOV version 2.0-1