LCOV - code coverage report
Current view: top level - aicpu_processer - ae_kernel_lib_fwk.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.9 % 194 155
Test Date: 2026-08-12 11:05:02 Functions: 94.4 % 18 17

            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_fwk.hpp"
      12              : #include "securec.h"
      13              : #include "aicpu_context.h"
      14              : #include "aicpu_event_struct.h"
      15              : 
      16              : namespace {
      17              : // aicpu so root dir, must be absolute path.
      18              : constexpr const char* AICPU_SO_ROOT_PATH = "/usr/lib64/aicpu_kernels/";
      19              : // tf kernels so name
      20              : constexpr const char* TF_SO_NAME = "libtf_kernels.so";
      21              : // tensorflow so name
      22              : constexpr const char* TENSORFLOW_SO_NAME = "libtensorflow.so";
      23              : // tensorflow tar uncompress path
      24              : constexpr const char* TENSORFLOW_SO_UNCOMPRESS_PAHT = "sand_box";
      25              : // aicpu kernels tar uncompress path
      26              : constexpr const char* AICPU_SO_UNCOMPRESS_PATH = "aicpu_kernels_device";
      27              : constexpr const uint32_t MAX_SO_PATH = 4096U;
      28              : const std::string THREAD_MODE_SO_PATH_FIX = "aicpu_kernels";
      29              : } // namespace
      30              : 
      31              : namespace cce {
      32              : AIKernelsLibFWK* AIKernelsLibFWK::instance_ = nullptr;
      33              : std::mutex AIKernelsLibFWK::mtx_;
      34              : 
      35            9 : AIKernelsLibFWK* AIKernelsLibFWK::GetInstance()
      36              : {
      37            9 :     const std::lock_guard<std::mutex> lockGuard(mtx_);
      38            9 :     if (instance_ != nullptr) {
      39            5 :         return instance_;
      40              :     } else {
      41            4 :         instance_ = new (std::nothrow) AIKernelsLibFWK();
      42            4 :         if (instance_ == nullptr) {
      43            0 :             return nullptr;
      44              :         }
      45            4 :         (void)instance_->Init();
      46            4 :         return instance_;
      47              :     }
      48            9 : }
      49              : 
      50            4 : void AIKernelsLibFWK::DestroyInstance()
      51              : {
      52            4 :     const std::lock_guard<std::mutex> lockGuard(mtx_);
      53            4 :     if (instance_ == nullptr) {
      54            0 :         return;
      55              :     }
      56            4 :     delete instance_;
      57            4 :     instance_ = nullptr;
      58            4 : }
      59              : 
      60            4 : aeStatus_t AIKernelsLibFWK::Init() { return tfImpl_.Init(); }
      61              : 
      62            1 : aeStatus_t AIKernelsLibFWK::CloseSo(const char_t* const soName)
      63              : {
      64              :     (void)soName;
      65            1 :     return AE_STATUS_SUCCESS;
      66              : }
      67              : 
      68            4 : int32_t AIKernelsLibFWK::CallKernelApi(const aicpu::KernelType kernelType, const void* const kernelBase)
      69              : {
      70            4 :     const auto fwkKernel = reinterpret_cast<const aicpu::HwtsFwkKernel* const>(kernelBase);
      71            4 :     if (static_cast<bool>(unlikely(fwkKernel == nullptr))) {
      72            1 :         AE_ERR_LOG(AE_MODULE_ID, "Input param fwkKernelBase is NULL.");
      73            1 :         return AE_STATUS_BAD_PARAM;
      74              :     }
      75              : 
      76            3 :     const auto fwkOpKernelPtr = static_cast<const uintptr_t>(fwkKernel->kernel);
      77            3 :     const auto fwkOpKernel = reinterpret_cast<const STR_FWK_OP_KERNEL* const>(fwkOpKernelPtr);
      78            3 :     if (static_cast<bool>(unlikely(fwkOpKernel == nullptr))) {
      79            0 :         AE_ERR_LOG(AE_MODULE_ID, "Input param fwkOpKernel is NULL.");
      80            0 :         return AE_STATUS_BAD_PARAM;
      81              :     }
      82            3 :     AE_INFO_LOG(
      83              :         AE_MODULE_ID, "Current kernelType:%d, FWK op kernel kernel type:%d.", kernelType, fwkOpKernel->fwkKernelType);
      84              : 
      85              :     // Call different Implement method switch by kernel type.
      86            3 :     int32_t ret = AE_STATUS_SUCCESS;
      87            3 :     switch (static_cast<FwkkernelType_t>(fwkOpKernel->fwkKernelType)) {
      88            3 :         case FMK_KERNEL_TYPE_TF:
      89            3 :             ret = tfImpl_.CallKernelApi(PtrToValue(PtrToPtr<const ::aicpu::FWKAdapter::FWKOperateParam, const void>(
      90              :                 &fwkOpKernel->fwkKernelBase.fwk_kernel)));
      91            3 :             break;
      92            0 :         default:
      93            0 :             AE_ERR_LOG(
      94              :                 AE_MODULE_ID, "Input param fwkKernelType in STR_FWK_OP_KERNEL is invalid :%d",
      95              :                 fwkOpKernel->fwkKernelType);
      96            0 :             ret = AE_STATUS_BAD_PARAM;
      97            0 :             break;
      98              :     }
      99            3 :     return ret;
     100              : }
     101              : 
     102            3 : aeStatus_t AIKernelsLibFWK::BatchLoadKernelSo(const aicpu::KernelType kernelType, std::vector<std::string>& soVec)
     103              : {
     104            3 :     AE_INFO_LOG(AE_MODULE_ID, "Begin to batch load kernel so, kerelType:[%d].", kernelType);
     105            3 :     if (soVec.empty()) {
     106            0 :         return AE_STATUS_SUCCESS;
     107              :     }
     108              :     // only one tf so
     109            3 :     return tfImpl_.LoadTfSo();
     110              : }
     111              : 
     112              : // need refresh soFile_
     113           12 : FWKKernelTfImpl::FWKKernelTfImpl()
     114           24 :     : kernelName_("TFOperateAPI"), funcAddr_(nullptr), soHandle_(nullptr), soTensorflowHandle_(nullptr)
     115           12 : {}
     116              : 
     117            4 : aeStatus_t FWKKernelTfImpl::Init()
     118              : {
     119            4 :     std::string baseSoFile(AICPU_SO_ROOT_PATH);
     120            4 :     (void)baseSoFile.append(TF_SO_NAME);
     121            4 :     soFile_ = baseSoFile;
     122              :     aicpu::aicpuContext_t currentAicpuCtx;
     123            4 :     const aicpu::status_t status = aicpu::aicpuGetContext(&currentAicpuCtx);
     124            4 :     if (status == aicpu::AICPU_ERROR_NONE) {
     125            4 :         std::string soPath(AICPU_SO_ROOT_PATH);
     126            8 :         (void)soPath.append(std::to_string(aicpu::GetUniqueVfId()))
     127            4 :             .append("/")
     128            4 :             .append(AICPU_SO_UNCOMPRESS_PATH)
     129            4 :             .append("/");
     130            4 :         soFile_ = soPath + TF_SO_NAME;
     131            4 :         GetThreadModelSoPath(soPath);
     132              :         // check so file
     133            4 :         const aeStatus_t ret = SingleSoManager::CheckSoFile(soPath, soFile_);
     134            4 :         if (ret != AE_STATUS_SUCCESS) {
     135            4 :             soFile_ = baseSoFile;
     136            4 :             AE_RUN_INFO_LOG(
     137              :                 AE_MODULE_ID, "So does not exist in path %s, use default soFile %s.", soPath.c_str(),
     138              :                 baseSoFile.c_str());
     139              :         }
     140            4 :     }
     141            4 :     AE_INFO_LOG(AE_MODULE_ID, "FWKernelTfImpl init success, soFile_=%s.", soFile_.c_str());
     142            4 :     return AE_STATUS_SUCCESS;
     143            4 : }
     144              : 
     145           12 : FWKKernelTfImpl::~FWKKernelTfImpl()
     146              : {
     147           12 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     148           12 :     funcAddr_ = nullptr;
     149           12 :     aeStatus_t ret = SingleSoManager::CloseSo(soHandle_);
     150           12 :     if (ret != AE_STATUS_SUCCESS) {
     151            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "~FWKKernelTfImpl CloseSo failed, ret is[%d]", ret);
     152              :     }
     153           12 :     ret = SingleSoManager::CloseSo(soTensorflowHandle_);
     154           12 :     if (ret != AE_STATUS_SUCCESS) {
     155            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "~FWKKernelTensorflowImpl CloseSo failed, ret is[%d]", ret);
     156              :     }
     157           12 :     soHandle_ = nullptr;
     158           12 :     soTensorflowHandle_ = nullptr;
     159           12 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     160           12 :     AE_RW_LOCK_DESTROY(&rwLock_);
     161           12 : }
     162              : 
     163            8 : void FWKKernelTfImpl::GetTfKernelThreadModeSoPath(std::string& soPath) const
     164              : {
     165            8 :     (void)soPath.append(THREAD_MODE_SO_PATH_FIX)
     166            8 :         .append("/")
     167           16 :         .append(std::to_string(aicpu::GetUniqueVfId()))
     168            8 :         .append("/")
     169            8 :         .append(AICPU_SO_UNCOMPRESS_PATH)
     170            8 :         .append("/");
     171            8 :     return;
     172              : }
     173              : 
     174            0 : void FWKKernelTfImpl::GetTensorflowThreadModeSoPath(std::string soPath)
     175              : {
     176            0 :     (void)soPath.append(THREAD_MODE_SO_PATH_FIX)
     177            0 :         .append("/")
     178            0 :         .append(std::to_string(aicpu::GetUniqueVfId()))
     179            0 :         .append("/")
     180            0 :         .append(AICPU_SO_UNCOMPRESS_PATH)
     181            0 :         .append("/")
     182            0 :         .append(TENSORFLOW_SO_UNCOMPRESS_PAHT)
     183            0 :         .append("/");
     184            0 :     tensorflowSoFile_ = soPath + TENSORFLOW_SO_NAME;
     185            0 :     return;
     186              : }
     187              : 
     188            9 : aeStatus_t FWKKernelTfImpl::GetTfThreadModeSoPath(std::string& soPath)
     189              : {
     190            9 :     const char_t* const innerDirName = getenv("HOME");
     191            9 :     if (innerDirName != nullptr) {
     192            8 :         const std::string str = innerDirName;
     193            8 :         const size_t len = str.length();
     194            8 :         if ((len == 0U) || (len >= static_cast<size_t>(MAX_SO_PATH))) {
     195            0 :             AE_ERR_LOG(AE_MODULE_ID, "Length[%zu] of inner so dir is invalid.", len);
     196            0 :             return AE_STATUS_INNER_ERROR;
     197              :         }
     198            8 :         soPath = str;
     199            8 :         if (soPath[soPath.size() - 1UL] != '/') {
     200            8 :             (void)soPath.append("/");
     201              :         }
     202            8 :         GetTensorflowThreadModeSoPath(soPath);
     203            8 :         GetTfKernelThreadModeSoPath(soPath);
     204            8 :         return AE_STATUS_SUCCESS;
     205            8 :     } else {
     206            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Get HOME env failed, get tf thread mode so path failed.");
     207            1 :         return AE_STATUS_INNER_ERROR;
     208              :     }
     209              : }
     210              : 
     211            7 : void FWKKernelTfImpl::GetThreadModelSoPath(std::string& soPath)
     212              : {
     213              :     uint32_t runMode;
     214            7 :     aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
     215            7 :     if (status != aicpu::AICPU_ERROR_NONE) {
     216            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
     217            2 :         return;
     218              :     }
     219            6 :     if (runMode != aicpu::AicpuRunMode::THREAD_MODE) {
     220            0 :         return;
     221              :     }
     222            6 :     std::string threadSoPath;
     223            6 :     if (GetTfThreadModeSoPath(threadSoPath) != AE_STATUS_SUCCESS) {
     224            1 :         AE_WARN_LOG(AE_MODULE_ID, "GetThreadModeSoPath failed.");
     225            1 :         return;
     226              :     }
     227            5 :     soPath = threadSoPath;
     228            5 :     soFile_ = threadSoPath + TF_SO_NAME;
     229            6 : }
     230              : 
     231            3 : int32_t FWKKernelTfImpl::CallKernelApi(const uint64_t fwkKernelParam)
     232              : {
     233            3 :     void* theFuncAddr = nullptr;
     234            3 :     AE_RW_LOCK_RD_LOCK(&rwLock_);
     235            3 :     if (static_cast<bool>(unlikely(funcAddr_ != nullptr))) {
     236            0 :         theFuncAddr = funcAddr_;
     237              :     }
     238            3 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     239              : 
     240            3 :     if (static_cast<bool>(unlikely(theFuncAddr == nullptr))) {
     241            3 :         AE_RW_LOCK_WR_LOCK(&rwLock_);
     242            3 :         if (static_cast<bool>(unlikely(funcAddr_ == nullptr))) {
     243            3 :             AE_INFO_LOG(
     244              :                 AE_MODULE_ID, "Begin to GetApi, soFile=%s, kernelName=%s.", GetSoFile().c_str(),
     245              :                 GetKernelName().c_str());
     246              : 
     247            3 :             aeStatus_t retGetApi = AE_STATUS_SUCCESS;
     248            3 :             if (static_cast<bool>(unlikely(soHandle_ == nullptr))) {
     249            3 :                 retGetApi = SingleSoManager::GetApi(GetSoFile().data(), GetKernelName().data(), &funcAddr_, &soHandle_);
     250              :             } else {
     251            0 :                 retGetApi = SingleSoManager::GetFunc(soHandle_, GetKernelName().data(), &funcAddr_);
     252              :             }
     253            3 :             AE_INFO_LOG(AE_MODULE_ID, "End to GetApi, retGetApi=%d.", retGetApi);
     254              : 
     255            3 :             if (static_cast<bool>(unlikely((retGetApi == AE_STATUS_SUCCESS) && (funcAddr_ == nullptr)))) {
     256            1 :                 AE_RW_LOCK_UN_LOCK(&rwLock_);
     257            1 :                 AE_ERR_LOG(AE_MODULE_ID, "Get a NULL func addr, but status is success.");
     258            1 :                 return AE_STATUS_INNER_ERROR;
     259            2 :             } else if (static_cast<bool>(unlikely(retGetApi != AE_STATUS_SUCCESS))) {
     260            2 :                 AE_RW_LOCK_UN_LOCK(&rwLock_);
     261            2 :                 AE_ERR_LOG(AE_MODULE_ID, "Get API or Func failed, ret[%d].", static_cast<int32_t>(retGetApi));
     262            2 :                 return retGetApi;
     263              :             } else {
     264            0 :                 AE_INFO_LOG(AE_MODULE_ID, "Get API or Func success.");
     265              :             }
     266              :         }
     267            0 :         theFuncAddr = funcAddr_;
     268            0 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     269              :     }
     270              : 
     271            0 :     const uint32_t tfRet = (reinterpret_cast<FwkTfOpFuncPtr>(theFuncAddr))(fwkKernelParam);
     272              :     // for tensorflow will should check the result.
     273            0 :     return static_cast<int32_t>(TransformKernelErrorCode(tfRet, fwkKernelParam));
     274              : }
     275              : 
     276            3 : aeStatus_t FWKKernelTfImpl::LoadTfSo()
     277              : {
     278            3 :     AE_RW_LOCK_RD_LOCK(&rwLock_);
     279            3 :     if (soHandle_ != nullptr) {
     280            0 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     281            0 :         return AE_STATUS_SUCCESS;
     282              :     }
     283            3 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     284              : 
     285            3 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     286            3 :     if (soHandle_ != nullptr) {
     287            0 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     288            0 :         return AE_STATUS_SUCCESS;
     289              :     }
     290            3 :     aeStatus_t ret = SingleSoManager::OpenSo(tensorflowSoFile_, &soTensorflowHandle_);
     291            3 :     if (ret != AE_STATUS_SUCCESS) {
     292            3 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "load tensorflow so failed, ret is[%d]", ret);
     293              :     }
     294            3 :     ret = SingleSoManager::OpenSo(soFile_, &soHandle_);
     295            3 :     if (ret != AE_STATUS_SUCCESS) {
     296            3 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     297            3 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "LoadTfSo open so failed, soFile[%s], ret[%u].", soFile_.c_str(), ret);
     298            3 :         return ret;
     299              :     }
     300            0 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     301            0 :     return AE_STATUS_SUCCESS;
     302              : }
     303              : 
     304            3 : aeStatus_t FWKKernelTfImpl::TransformKernelErrorCode(const uint32_t errCode, const uint64_t fwkKernelParam)
     305              : {
     306            3 :     if (errCode == 0U) {
     307            1 :         return AE_STATUS_SUCCESS;
     308              :     }
     309              :     // check tf end of sequence
     310            2 :     if (errCode == aicpu::FWKAdapter::FWK_ADPT_NATIVE_END_OF_SEQUENCE) {
     311            1 :         return AE_STATUS_END_OF_SEQUENCE;
     312              :     }
     313            1 :     uint32_t returnCode = errCode;
     314            1 :     if (errCode == aicpu::FWKAdapter::FWK_ADPT_NOT_SUPPORT_OPTYPE) {
     315            0 :         returnCode = AE_STATUS_BAD_PARAM;
     316              :     }
     317            1 :     AE_ERR_LOG(
     318              :         AE_MODULE_ID, "Call tf api return failed:%u, returncode:%u, input param to tf api:0x%lx", errCode, returnCode,
     319              :         fwkKernelParam);
     320              :     // other error code: transform to inner_error
     321            1 :     return static_cast<aeStatus_t>(returnCode);
     322              : }
     323              : 
     324            2 : const std::string& FWKKernelTfImpl::GetSoFile() const { return soFile_; }
     325              : 
     326            6 : const std::string& FWKKernelTfImpl::GetKernelName() const { return kernelName_; }
     327              : } // namespace cce
        

Generated by: LCOV version 2.0-1