LCOV - code coverage report
Current view: top level - aicpu_processer - ae_so_manager.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.4 % 385 348
Test Date: 2026-08-12 11:05:02 Functions: 100.0 % 23 23

            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_so_manager.hpp"
      12              : #include <memory>
      13              : #include <mutex>
      14              : #include <cstdlib>
      15              : #include <string>
      16              : #include <climits>
      17              : #include <securec.h>
      18              : #include <dlfcn.h>
      19              : #include <fstream>
      20              : #include <sstream>
      21              : #include <vector>
      22              : #include "ae_def.hpp"
      23              : #include "ae_kernel_lib_aicpu.hpp"
      24              : 
      25              : namespace cce {
      26              : namespace {
      27              : // aicpu so root dir, must be absolute path
      28              : const std::string AICPU_SO_ROOT_DIR = "/usr/lib64/aicpu_kernels/";
      29              : // aicpu so root dir, old path only for hccl
      30              : const std::string AICPU_SO_ROOT_DIR_OLD_PATH = "/usr/lib64/";
      31              : // cust so path for cust_aicpu_sd: CustAiCpuUser
      32              : constexpr const char_t* CUST_USER_SO_PATH = "/home/CustAiCpuUser";
      33              : // prefix of cust so dir name
      34              : constexpr const char_t* CUSTOM_SO_DIR_NAME_PREFIX = "cust_aicpu_";
      35              : // aicpu kernels tar uncompress path
      36              : constexpr const char_t* AICPU_SO_UNCOMPRESS_DIR = "aicpu_kernels_device";
      37              : // libretr_kernels.so
      38              : constexpr const char_t* RETR_KERNELS_SO_NAME = "libretr_kernels.so";
      39              : // libhccl_operator_call.so
      40              : constexpr const char_t* HCCL_KERNELS_SO_NAME = "libhccl_operator_call.so";
      41              : // libbuiltin_kernels.so
      42              : constexpr const char_t* BUILTIN_KERNELS_SO_NAME = "libbuiltin_kernels.so";
      43              : // pattern for custom so name
      44              : constexpr const char_t* PATTERN_FOR_SO_NAME("abcdefghijklmnopqrstuvwxyz"
      45              :                                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_.");
      46              : // env variable name: inner aicpu kernel so path
      47              : constexpr const char_t* AICPU_INNER_SO_PATH_ENV_VAR_NAME = "ASCEND_AICPU_KERNEL_PATH";
      48              : // env variable name: custom aicpu kernel so path
      49              : // If modify the env name, please modify the same env name in aicpusd_cust_so_manager.cpp
      50              : constexpr const char_t* AICPU_CUSTOM_SO_PATH_ENV_VAR = "ASCEND_CUST_AICPU_KERNEL_CACHE_PATH";
      51              : // physical machine VFID == 0 物理机场景
      52              : constexpr uint32_t DEFAULT_VFID = 0U;
      53              : // min number of vDeviceId
      54              : constexpr const uint32_t VDEVICE_MIN_CPU_NUM = 32U;
      55              : // max number of vDeviceId
      56              : constexpr const uint32_t VDEVICE_MAX_CPU_NUM = 64U;
      57              : constexpr const uint32_t DIV_NUM = 2U;
      58              : // version.info TurstList info
      59              : const std::string TRUST_SO_LIST_PREFIX = "Trustlist=";
      60              : 
      61              : constexpr const char_t* THREAD_MODE_SO_PATH_FIX = "aicpu_kernels";
      62              : } // namespace
      63              : 
      64           29 : SingleSoManager::~SingleSoManager()
      65              : {
      66              :     // Step1.  clear the critical section apiCacher_
      67           29 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
      68           29 :     apiCacher_.clear();
      69           29 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
      70              : 
      71              :     // Step2.  destroy the Read Write lock
      72           29 :     AE_RW_LOCK_DESTROY(&rwLock_);
      73              : 
      74              :     // Step3. close so
      75           29 :     (void)CloseSo(soHandle_);
      76           29 :     soHandle_ = nullptr;
      77           29 : }
      78              : 
      79           28 : aeStatus_t SingleSoManager::Init(const std::string& guardDirName, const std::string& soFile)
      80              : {
      81           28 :     soName_.clear();
      82           28 :     apiCacher_.clear();
      83              : 
      84           28 :     aeStatus_t ret = CheckSoFile(guardDirName, soFile);
      85           28 :     if (ret != AE_STATUS_SUCCESS) {
      86           24 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "CheckSoFile failed, soFile[%s], ret[%u].", soFile.c_str(), ret);
      87           24 :         return ret;
      88              :     }
      89              : 
      90            4 :     void* handle = nullptr;
      91            4 :     ret = OpenSo(soFile, &handle);
      92            4 :     if ((ret == AE_STATUS_SUCCESS) && (handle != nullptr)) {
      93            4 :         soHandle_ = handle;
      94            4 :         soName_ = soFile;
      95              :     }
      96            4 :     return ret;
      97              : }
      98              : 
      99           34 : aeStatus_t SingleSoManager::CheckSoFile(const std::string& guardDirName, const std::string& soFile)
     100              : {
     101           34 :     if (guardDirName.empty()) {
     102            1 :         AE_INFO_LOG(AE_MODULE_ID, "guardDirName is empty, no need check");
     103            1 :         return AE_STATUS_SUCCESS;
     104              :     }
     105              : 
     106           33 :     if (soFile.length() >= static_cast<std::string::size_type>(PATH_MAX)) {
     107            1 :         AE_ERR_LOG(AE_MODULE_ID, "soFile file length[%zu] must less than PATH_MAX[%u]", soFile.length(), PATH_MAX);
     108            1 :         return AE_STATUS_OPEN_SO_FAILED;
     109              :     }
     110              : 
     111           32 :     std::unique_ptr<char_t[]> path(new (std::nothrow) char_t[PATH_MAX]);
     112           32 :     if (path == nullptr) {
     113            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Alloc memory for path failed.");
     114            0 :         return AE_STATUS_OPEN_SO_FAILED;
     115              :     }
     116              : 
     117           32 :     const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
     118           32 :     if (eRet != EOK) {
     119            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Mem set error, ret=%d", eRet);
     120            1 :         return AE_STATUS_OPEN_SO_FAILED;
     121              :     }
     122              : 
     123           31 :     if (realpath(soFile.data(), path.get()) == nullptr) {
     124           27 :         AE_WARN_LOG(AE_MODULE_ID, "Format to realpath failed:%s, path:%s", soFile.data(), path.get());
     125           27 :         return AE_STATUS_OPEN_SO_FAILED;
     126              :     }
     127              : 
     128            4 :     std::string tmpGuardDirName(guardDirName);
     129            4 :     if (tmpGuardDirName[tmpGuardDirName.size() - 1UL] != '/') {
     130            1 :         (void)tmpGuardDirName.append("/");
     131              :     }
     132              : 
     133            4 :     const std::string pathStr(path.get());
     134            4 :     const std::string realSoPath = GetRealCustSoPath();
     135            5 :     if ((strncmp(path.get(), tmpGuardDirName.c_str(), tmpGuardDirName.length()) != 0) &&
     136            1 :         (pathStr.find(realSoPath) == std::string::npos)) {
     137            1 :         AE_ERR_LOG(
     138              :             AE_MODULE_ID, "Invalid so file with dir:%s so:%s, should be %s or %s", path.get(), soFile.c_str(),
     139              :             tmpGuardDirName.data(), realSoPath.c_str());
     140            1 :         return AE_STATUS_OPEN_SO_FAILED;
     141              :     }
     142            3 :     return AE_STATUS_SUCCESS;
     143           32 : }
     144              : 
     145            4 : std::string SingleSoManager::GetRealCustSoPath()
     146              : {
     147              :     aicpu::aicpuContext_t currentAicpuCtx;
     148            4 :     (void)aicpu::aicpuGetContext(&currentAicpuCtx);
     149              : 
     150            4 :     const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
     151              : 
     152            4 :     std::string soPath = CUST_USER_SO_PATH;
     153            4 :     GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
     154            4 :     (void)soPath.append("lib/");
     155            4 :     return soPath;
     156            0 : }
     157              : 
     158            7 : void SingleSoManager::GetCustSoPathByUniqueVfId(std::string& soPath, const uint32_t uniqueVfId)
     159              : {
     160            7 :     if (uniqueVfId == DEFAULT_VFID) {
     161            7 :         (void)soPath.append("/");
     162            0 :     } else if (uniqueVfId >= VDEVICE_MIN_CPU_NUM && uniqueVfId < VDEVICE_MAX_CPU_NUM) {
     163            0 :         const uint32_t custNum = (uniqueVfId - VDEVICE_MIN_CPU_NUM) / DIV_NUM + 1U;
     164            0 :         (void)soPath.append(std::to_string(custNum)).append("/");
     165            0 :     } else {
     166            0 :         (void)soPath.append(std::to_string(uniqueVfId)).append("/");
     167              :     }
     168            7 : }
     169              : 
     170           13 : aeStatus_t SingleSoManager::OpenSo(const std::string& soFile, void** const retHandle)
     171              : {
     172              :     // Use API in glibc to open the so lib, load this so to process.
     173           13 :     std::unique_ptr<char_t[]> path(new (std::nothrow) char_t[PATH_MAX]);
     174           13 :     if (path == nullptr) {
     175            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Alloc memory for path failed.");
     176            0 :         return AE_STATUS_OPEN_SO_FAILED;
     177              :     }
     178              : 
     179           13 :     const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
     180           13 :     if (eRet != EOK) {
     181            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Mem set error, ret=%d", eRet);
     182            1 :         return AE_STATUS_OPEN_SO_FAILED;
     183              :     }
     184              : 
     185           12 :     if (realpath(soFile.data(), path.get()) == nullptr) {
     186            8 :         AE_WARN_LOG(AE_MODULE_ID, "Format to realpath failed:[%s], path:[%s]", soFile.data(), path.get());
     187            8 :         return AE_STATUS_OPEN_SO_FAILED;
     188              :     }
     189              : 
     190            4 :     AE_INFO_LOG(AE_MODULE_ID, "Open so %s begin.", path.get());
     191            4 :     void* const handle = dlopen(
     192            4 :         path.get(), static_cast<int32_t>((static_cast<uint32_t>(RTLD_LAZY)) | (static_cast<uint32_t>(RTLD_GLOBAL))));
     193            4 :     if (handle == nullptr) {
     194            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Open so %s failed with error:%s", path.get(), dlerror());
     195            0 :         return AE_STATUS_OPEN_SO_FAILED;
     196              :     }
     197              : 
     198            4 :     *retHandle = handle;
     199            4 :     AE_INFO_LOG(AE_MODULE_ID, "Open so %s success.", soFile.c_str());
     200            4 :     return AE_STATUS_SUCCESS;
     201           13 : }
     202              : 
     203            2 : aeStatus_t SingleSoManager::GetFunc(void* const soHandle, const char_t* const funcName, void** const retFuncAddr)
     204              : {
     205            2 :     void* const theFuncAddr = dlsym(soHandle, funcName);
     206            2 :     if (static_cast<bool>(unlikely((theFuncAddr == nullptr)))) {
     207            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get funcAddr %s from handle is NULL: %s", funcName, dlerror());
     208            1 :         return AE_STATUS_GET_KERNEL_NAME_FAILED;
     209              :     }
     210            1 :     *retFuncAddr = theFuncAddr;
     211            1 :     return AE_STATUS_SUCCESS;
     212              : }
     213              : 
     214          127 : aeStatus_t SingleSoManager::GetApi(
     215              :     const char_t* const soNamePtr, const char_t* const funcName, void** const funcAddrPtr)
     216              : {
     217          127 :     if (static_cast<bool>(unlikely((soHandle_ == nullptr)))) {
     218            3 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "soHandle_ is null, should be Init first.");
     219            3 :         return AE_STATUS_INNER_ERROR;
     220              :     }
     221              : 
     222          124 :     AE_RW_LOCK_RD_LOCK(&rwLock_);
     223          248 :     auto apiIter = apiCacher_.find(funcName);
     224          124 :     if (apiIter != apiCacher_.end()) {
     225          116 :         *funcAddrPtr = apiIter->second;
     226          116 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     227          117 :         return AE_STATUS_SUCCESS;
     228              :     }
     229            7 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     230              : 
     231            7 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     232           14 :     apiIter = apiCacher_.find(funcName);
     233            7 :     if (apiIter != apiCacher_.end()) {
     234            0 :         *funcAddrPtr = apiIter->second;
     235            0 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     236            0 :         return AE_STATUS_SUCCESS;
     237              :     }
     238              : 
     239              :     // get func
     240            7 :     void* theFuncAddr = nullptr;
     241            7 :     const aeStatus_t ret = GetFunc(soHandle_, funcName, &theFuncAddr);
     242            7 :     if (ret != AE_STATUS_SUCCESS) {
     243            1 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     244            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Get func %s from so %s failed, ret[%u].", funcName, soNamePtr, ret);
     245            1 :         return ret;
     246              :     }
     247              :     // cache func
     248           12 :     apiCacher_[funcName] = theFuncAddr;
     249            6 :     *funcAddrPtr = theFuncAddr;
     250            6 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     251            6 :     AE_RUN_INFO_LOG(AE_MODULE_ID, "Get api %s from so %s success.", funcName, soNamePtr);
     252            6 :     return AE_STATUS_SUCCESS;
     253              : }
     254              : 
     255            3 : aeStatus_t SingleSoManager::GetApi(
     256              :     const char_t* const soFile, const char_t* const funcName, void** const funcAddrPtr, void** const retHandle)
     257              : {
     258            3 :     void* handle = nullptr;
     259            3 :     const aeStatus_t retOpenSo = OpenSo(soFile, &handle);
     260            3 :     if ((retOpenSo == AE_STATUS_SUCCESS) && (handle != nullptr)) {
     261            1 :         void* theFuncAddr = nullptr;
     262            1 :         const aeStatus_t retGetFunc = GetFunc(handle, funcName, &theFuncAddr);
     263            1 :         if ((retGetFunc == AE_STATUS_SUCCESS) && (theFuncAddr != nullptr)) {
     264            1 :             *funcAddrPtr = theFuncAddr;
     265              :         }
     266              : 
     267            1 :         *retHandle = handle;
     268            1 :         return retGetFunc;
     269              :     }
     270              : 
     271            2 :     AE_ERR_LOG(AE_MODULE_ID, "Open so failed when get api, soFile[%s], ret[%u].", soFile, retOpenSo);
     272            2 :     return retOpenSo;
     273              : }
     274              : 
     275           55 : aeStatus_t SingleSoManager::CloseSo(void* const retHandle)
     276              : {
     277           55 :     if (retHandle != nullptr) {
     278            8 :         const int32_t ret = dlclose(retHandle);
     279            8 :         if (ret != 0) {
     280            1 :             AE_ERR_LOG(AE_MODULE_ID, "Close so failed with error:%s", dlerror());
     281            1 :             return AE_STATUS_INNER_ERROR;
     282              :         } else {
     283            7 :             AE_DEBUG_LOG(AE_MODULE_ID, "Close success:");
     284            7 :             return AE_STATUS_SUCCESS;
     285              :         }
     286              :     }
     287           47 :     return AE_STATUS_SUCCESS;
     288              : }
     289              : 
     290           81 : MultiSoManager::~MultiSoManager()
     291              : {
     292              :     // Step1.  clear the critical section apiCacher_
     293           81 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     294           84 :     for (auto iter = soCacher_.begin(); iter != soCacher_.end(); ++iter) {
     295            3 :         const SingleSoManager* const soMngr = iter->second;
     296            3 :         if (soMngr != nullptr) {
     297            3 :             delete soMngr; // Release each SingleSoManager * stored in cache
     298              :         }
     299              :     }
     300           81 :     soCacher_.clear();
     301           81 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     302              :     // Step2.  destroy the Read Write lock
     303           81 :     AE_RW_LOCK_DESTROY(&rwLock_);
     304           81 : };
     305              : 
     306            8 : aeStatus_t MultiSoManager::Init()
     307              : {
     308            8 :     soCacher_.clear();
     309            8 :     const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode_);
     310            8 :     if (status != aicpu::AICPU_ERROR_NONE) {
     311            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Get aicpu runmode failed.");
     312            1 :         return AE_STATUS_INNER_ERROR;
     313              :     }
     314              :     // get aicpu so path
     315            7 :     const char_t* const innerDirName = getenv(AICPU_INNER_SO_PATH_ENV_VAR_NAME);
     316            7 :     if (innerDirName != nullptr) {
     317            1 :         const std::string str = innerDirName;
     318            1 :         const size_t len = str.length();
     319            1 :         if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
     320            0 :             AE_ERR_LOG(AE_MODULE_ID, "Length of inner so dir %zu is invalid.", len);
     321            0 :             return AE_STATUS_INNER_ERROR;
     322              :         }
     323            1 :         innerKernelPath_ = str;
     324            1 :         if (innerKernelPath_[innerKernelPath_.size() - 1UL] != '/') {
     325            0 :             (void)innerKernelPath_.append("/");
     326              :         }
     327            1 :     }
     328              :     // get cust aicpu so path
     329            7 :     const char_t* const custDirName = getenv(AICPU_CUSTOM_SO_PATH_ENV_VAR);
     330            7 :     if (custDirName != nullptr) {
     331            1 :         const std::string str = custDirName;
     332            1 :         const size_t len = str.length();
     333            1 :         if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
     334            0 :             AE_ERR_LOG(AE_MODULE_ID, "Length of cust so dir %zu is invalid.", len);
     335            0 :             return AE_STATUS_INNER_ERROR;
     336              :         }
     337            1 :         custKernelPath_ = str;
     338            1 :         if (custKernelPath_[custKernelPath_.size() - 1UL] != '/') {
     339            0 :             (void)custKernelPath_.append("/");
     340              :         }
     341            1 :     }
     342            7 :     return AE_STATUS_SUCCESS;
     343              : }
     344              : 
     345          124 : aeStatus_t MultiSoManager::GetApi(
     346              :     const aicpu::KernelType kernelType, const char_t* const soName, const char_t* const funcName,
     347              :     void** const funcAddrPtr)
     348              : {
     349          124 :     SingleSoManager* soMgr = nullptr;
     350          124 :     const aeStatus_t ret = LoadSo(kernelType, soName, soMgr);
     351          124 :     if ((ret != AE_STATUS_SUCCESS) || (soMgr == nullptr)) {
     352            3 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Load so %s failed.", soName);
     353            3 :         return AE_STATUS_OPEN_SO_FAILED;
     354              :     }
     355          122 :     return soMgr->GetApi(soName, funcName, funcAddrPtr);
     356              : }
     357              : 
     358           12 : aeStatus_t MultiSoManager::GetSoPath(
     359              :     const aicpu::KernelType kernelType, const std::string& soName, std::string& soPath) const
     360              : {
     361           12 :     if (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM || kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC) {
     362            0 :         return GetCustSoPath(soPath);
     363              :     }
     364           12 :     return GetInnerSoPath(soName, soPath);
     365              : }
     366              : 
     367           11 : aeStatus_t MultiSoManager::GetThreadModeSoPath(std::string& soPath) const
     368              : {
     369           11 :     const char_t* const innerDirName = getenv("HOME");
     370           11 :     if (innerDirName != nullptr) {
     371           10 :         const std::string str = innerDirName;
     372           10 :         const size_t len = str.length();
     373           10 :         if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
     374            0 :             AE_ERR_LOG(AE_MODULE_ID, "Length[%zu] of inner so dir is invalid.", len);
     375            0 :             return AE_STATUS_INNER_ERROR;
     376              :         }
     377           10 :         soPath = str;
     378           10 :         if (soPath[soPath.size() - 1UL] != '/') {
     379           10 :             (void)soPath.append("/");
     380              :         }
     381           10 :         (void)soPath.append(THREAD_MODE_SO_PATH_FIX)
     382           10 :             .append("/")
     383           20 :             .append(std::to_string(aicpu::GetUniqueVfId()))
     384           10 :             .append("/")
     385           10 :             .append(AICPU_SO_UNCOMPRESS_DIR)
     386           10 :             .append("/");
     387           10 :         return AE_STATUS_SUCCESS;
     388           10 :     } else {
     389            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Get HOME env failed, get thread mode so path failed.");
     390            1 :         return AE_STATUS_INNER_ERROR;
     391              :     }
     392              : }
     393           21 : aeStatus_t MultiSoManager::GetInnerSoPath(const std::string& soName, std::string& soPath) const
     394              : {
     395              :     uint32_t runMode;
     396           21 :     aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
     397           21 :     if (status != aicpu::AICPU_ERROR_NONE) {
     398            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
     399            1 :         return AE_STATUS_INNER_ERROR;
     400              :     }
     401              : 
     402              :     // aicpu kernel path for lhisi from env: ASCEND_AICPU_KERNEL_PATH
     403           20 :     if ((runMode == aicpu::AicpuRunMode::THREAD_MODE) && (!innerKernelPath_.empty())) {
     404            1 :         soPath = innerKernelPath_;
     405            1 :         return AE_STATUS_SUCCESS;
     406              :     }
     407              : 
     408              :     // libretr_kernels.so in /usr/lib64/aicpu_kernel/
     409           19 :     if (soName == RETR_KERNELS_SO_NAME) {
     410            1 :         soPath = AICPU_SO_ROOT_DIR;
     411            1 :         return AE_STATUS_SUCCESS;
     412              :     }
     413              : 
     414              :     // libhccl_operator_call.so in /usr/lib64/
     415           18 :     if ((soName == HCCL_KERNELS_SO_NAME) || (soName == BUILTIN_KERNELS_SO_NAME)) {
     416            1 :         soPath = AICPU_SO_ROOT_DIR_OLD_PATH;
     417            1 :         return AE_STATUS_SUCCESS;
     418              :     }
     419              : 
     420           17 :     if (runMode == aicpu::AicpuRunMode::THREAD_MODE) {
     421            7 :         if (GetThreadModeSoPath(soPath) == AE_STATUS_SUCCESS) {
     422            7 :             return AE_STATUS_SUCCESS;
     423              :         }
     424            0 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "thread mode home path invalid use default path [%s].", soPath.c_str());
     425              :     }
     426              :     // get aicpu context
     427              :     aicpu::aicpuContext_t currentAicpuCtx;
     428           10 :     status = aicpu::aicpuGetContext(&currentAicpuCtx);
     429           10 :     if (status != aicpu::AICPU_ERROR_NONE) {
     430            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
     431            1 :         return AE_STATUS_INNER_ERROR;
     432              :     }
     433              :     // libtf_kernels.so and libaicpu_kernels.so and libcpu_kernels.so and libpt_kernels.so path from context
     434            9 :     soPath = AICPU_SO_ROOT_DIR;
     435            9 :     (void)soPath.append(std::to_string(aicpu::GetUniqueVfId())).append("/").append(AICPU_SO_UNCOMPRESS_DIR).append("/");
     436              : 
     437            9 :     return AE_STATUS_SUCCESS;
     438              : }
     439              : 
     440            9 : aeStatus_t MultiSoManager::BuildCustSoPath(std::string& soPath, const uint32_t uniqueVfId) const
     441              : {
     442              :     uint32_t runMode;
     443            9 :     const aicpu::status_t statusMode = aicpu::GetAicpuRunMode(runMode);
     444            9 :     if (statusMode != aicpu::AICPU_ERROR_NONE) {
     445            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
     446            1 :         return AE_STATUS_INNER_ERROR;
     447              :     }
     448              :     // dc
     449            8 :     if (runMode == aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
     450            1 :         soPath = CUST_USER_SO_PATH;
     451            1 :         SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
     452            7 :     } else if (runMode == aicpu::AicpuRunMode::PROCESS_SOCKET_MODE) {
     453            3 :         const char_t* const custDirName = getenv("HOME");
     454            3 :         if (custDirName == nullptr) {
     455            1 :             AE_ERR_LOG(AE_MODULE_ID, "Get current dir name by HOME in socket_mode failed.");
     456            1 :             return AE_STATUS_INNER_ERROR;
     457              :         }
     458            2 :         soPath = custDirName;
     459            2 :         AE_RUN_INFO_LOG(AE_MODULE_ID, "Get soPath[%s] in socket_mode", soPath.c_str());
     460            2 :         SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
     461              :     } else {
     462            4 :         const char_t* const curDirName = getenv("HOME");
     463            4 :         if (curDirName == nullptr) {
     464            2 :             AE_ERR_LOG(AE_MODULE_ID, "Get current home directory failed.");
     465            3 :             return AE_STATUS_INNER_ERROR;
     466              :         }
     467            2 :         const std::string dirName = curDirName;
     468            2 :         const size_t len = dirName.length();
     469            2 :         if ((len == 0LU) || (len >= static_cast<size_t>(PATH_MAX))) {
     470            1 :             AE_ERR_LOG(AE_MODULE_ID, "Length of current dir name %zu is invalid.", len);
     471            1 :             return AE_STATUS_INNER_ERROR;
     472              :         }
     473            1 :         soPath = dirName;
     474            1 :         if (soPath[soPath.size() - 1LU] != '/') {
     475            1 :             (void)soPath.append("/");
     476              :         }
     477            2 :     }
     478            4 :     return AE_STATUS_SUCCESS;
     479              : }
     480              : 
     481            8 : aeStatus_t MultiSoManager::GetCustSoPath(std::string& soPath) const
     482              : {
     483              :     // get aicpu context
     484              :     aicpu::aicpuContext_t currentAicpuCtx;
     485            8 :     const aicpu::status_t status = aicpu::aicpuGetContext(&currentAicpuCtx);
     486            8 :     if (status != aicpu::AICPU_ERROR_NONE) {
     487            1 :         AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
     488            1 :         return AE_STATUS_INNER_ERROR;
     489              :     }
     490            7 :     const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
     491              :     // minirc or ctrlcpu, cust so load in current user root path; else, so load in cust aicpu_sd thread
     492              :     // lhisi, so load path from env ASCEND_CUST_AICPU_KERNEL_PATH
     493            7 :     if (!custKernelPath_.empty()) {
     494            0 :         soPath = custKernelPath_;
     495              :     } else {
     496            7 :         const auto ret = BuildCustSoPath(soPath, uniqueVfId);
     497            7 :         if (ret != AE_STATUS_SUCCESS) {
     498            4 :             AE_ERR_LOG(AE_MODULE_ID, "BuildCustSoPath failed.");
     499            4 :             return ret;
     500              :         }
     501              :     }
     502            3 :     (void)soPath.append(CUSTOM_SO_DIR_NAME_PREFIX)
     503            3 :         .append(std::to_string(currentAicpuCtx.deviceId))
     504            3 :         .append("_")
     505            6 :         .append(std::to_string(uniqueVfId))
     506            3 :         .append("_")
     507            6 :         .append(std::to_string(static_cast<int32_t>(currentAicpuCtx.hostPid)))
     508            3 :         .append("/");
     509            3 :     return AE_STATUS_SUCCESS;
     510              : }
     511              : 
     512            8 : aeStatus_t MultiSoManager::LoadSo(const aicpu::KernelType kernelType, const std::string& soName)
     513              : {
     514            8 :     SingleSoManager* soMgr = nullptr;
     515           16 :     return LoadSo(kernelType, soName, soMgr);
     516              : }
     517              : 
     518          132 : aeStatus_t MultiSoManager::LoadSo(
     519              :     const aicpu::KernelType kernelType, const std::string& soName, SingleSoManager*& soMgr)
     520              : {
     521          132 :     if (soName.empty()) {
     522            1 :         AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
     523            1 :         return AE_STATUS_BAD_PARAM;
     524              :     }
     525              : 
     526          131 :     if (!aicpu::IsCustAicpuSd()) {
     527          131 :         if ((runMode_ != aicpu::AicpuRunMode::THREAD_MODE) &&
     528          124 :             ((kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM) || (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC))) {
     529            1 :             AE_ERR_LOG(AE_MODULE_ID, "runmode is not THREAD_MODE AND kernelType is [%u]", kernelType);
     530            1 :             return AE_STATUS_BAD_PARAM;
     531              :         }
     532              :     }
     533              : 
     534          130 :     AE_RW_LOCK_RD_LOCK(&rwLock_);
     535          131 :     auto soIter = soCacher_.find(soName);
     536          131 :     if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
     537          118 :         soMgr = soIter->second;
     538          118 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     539          118 :         return AE_STATUS_SUCCESS;
     540              :     }
     541           13 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     542              : 
     543           13 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     544           13 :     soIter = soCacher_.find(soName);
     545           13 :     if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
     546            0 :         soMgr = soIter->second;
     547            0 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     548            0 :         return AE_STATUS_SUCCESS;
     549              :     }
     550           13 :     const auto ret = CreateSingleSoMgr(kernelType, soName, soMgr);
     551           13 :     if (ret != AE_STATUS_SUCCESS) {
     552            8 :         AE_RW_LOCK_UN_LOCK(&rwLock_);
     553            8 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "CreateSingleSoMgr failed, soName[%s], ret[%u].", soName.c_str(), ret);
     554            8 :         return ret;
     555              :     }
     556            5 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     557            5 :     return AE_STATUS_SUCCESS;
     558              : }
     559              : 
     560           13 : aeStatus_t MultiSoManager::CreateSingleSoMgr(
     561              :     const aicpu::KernelType kernelType, const std::string& soName, SingleSoManager*& soMgr)
     562              : {
     563              :     // check so name
     564           13 :     if (soName.find_first_not_of(PATTERN_FOR_SO_NAME) != std::string::npos) {
     565            0 :         AE_ERR_LOG(AE_MODULE_ID, "So name %s is not invalid. Please check!", soName.c_str());
     566            0 :         return AE_STATUS_BAD_PARAM;
     567              :     }
     568              :     // get so real path
     569           13 :     std::string realSoPath;
     570           13 :     auto ret = GetSoPath(kernelType, soName, realSoPath);
     571           13 :     if (ret != AE_STATUS_SUCCESS) {
     572            1 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "GetSoPath failed, soName[%s], ret[%u].", soName.c_str(), ret);
     573            1 :         return ret;
     574              :     }
     575           12 :     std::string soFile(realSoPath);
     576           12 :     (void)soFile.append(soName);
     577           12 :     AE_INFO_LOG(AE_MODULE_ID, "soname[%s]", soFile.c_str());
     578              :     // This thread get the lock and create the new single so Manager
     579           12 :     SingleSoManager* const newSSoMngr = new (std::nothrow) SingleSoManager();
     580           12 :     AE_MEMORY_LOG(
     581              :         AE_MODULE_ID, "MallocMemory, func=new, size=%zu, purpose=SingleSoManager object", sizeof(SingleSoManager));
     582           12 :     if (newSSoMngr == nullptr) {
     583            0 :         AE_ERR_LOG(AE_MODULE_ID, "Create newSSoMngr ptr failed");
     584            0 :         return AE_STATUS_INNER_ERROR;
     585              :     }
     586           12 :     ret = newSSoMngr->Init(realSoPath, soFile);
     587           12 :     if (ret != AE_STATUS_SUCCESS) {
     588            7 :         AE_RUN_INFO_LOG(
     589              :             AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.", soFile.c_str());
     590            7 :         if (realSoPath != AICPU_SO_ROOT_DIR) {
     591              :             // try to load so from /usr/lib64/aicpu_kernel/
     592            7 :             std::string oriPath = realSoPath;
     593            7 :             realSoPath = AICPU_SO_ROOT_DIR;
     594            7 :             soFile = realSoPath + soName;
     595            7 :             ret = newSSoMngr->Init(realSoPath, soFile);
     596            7 :             if (ret != AE_STATUS_SUCCESS) {
     597            7 :                 ret = GetSoInHostPidPath(soName, oriPath, newSSoMngr, soFile);
     598              :             }
     599            7 :         }
     600              :     }
     601              : 
     602              :     // check init result
     603           12 :     if (ret != AE_STATUS_SUCCESS) {
     604            7 :         delete newSSoMngr;
     605            7 :         AE_RUN_WARN_LOG(AE_MODULE_ID, "Single so manager init failed, soFile is %s.", soFile.c_str());
     606            7 :         return ret;
     607              :     }
     608              :     // Cache it so that we can get it from cache next time.
     609            5 :     soCacher_[soName] = newSSoMngr;
     610            5 :     soMgr = newSSoMngr;
     611            5 :     AE_INFO_LOG(AE_MODULE_ID, "Loaded so successfully, soFile=%s.", soFile.c_str());
     612            5 :     return AE_STATUS_SUCCESS;
     613           13 : }
     614              : 
     615            1 : aeStatus_t MultiSoManager::CloseSo(const std::string& soName)
     616              : {
     617            1 :     if (soName.empty()) {
     618            0 :         AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
     619            0 :         return AE_STATUS_BAD_PARAM;
     620              :     }
     621              : 
     622            1 :     AE_RW_LOCK_WR_LOCK(&rwLock_);
     623            1 :     const auto iter = soCacher_.find(soName);
     624            1 :     if (iter != soCacher_.end()) {
     625            1 :         const SingleSoManager* const sSoMngr = iter->second;
     626            1 :         if (sSoMngr != nullptr) {
     627            1 :             delete sSoMngr;
     628              :         }
     629            1 :         (void)soCacher_.erase(iter);
     630              :     }
     631            1 :     AE_RW_LOCK_UN_LOCK(&rwLock_);
     632              : 
     633            1 :     return AE_STATUS_SUCCESS;
     634              : }
     635              : 
     636            7 : aeStatus_t MultiSoManager::GetSoInHostPidPath(
     637              :     const std::string& soName, std::string& oriPath, SingleSoManager* const newSSoMngr, std::string& soFile) const
     638              : {
     639              :     aicpu::aicpuContext_t currentAicpuCtx;
     640            7 :     const aicpu::status_t status = aicpu::aicpuGetContext(&currentAicpuCtx);
     641            7 :     if (status != aicpu::AICPU_ERROR_NONE) {
     642            0 :         AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
     643            0 :         return AE_STATUS_INNER_ERROR;
     644              :     }
     645            7 :     oriPath.append(std::to_string(currentAicpuCtx.hostPid))
     646            7 :         .append("_")
     647           14 :         .append(std::to_string(currentAicpuCtx.deviceId))
     648            7 :         .append("/");
     649            7 :     soFile = oriPath + soName;
     650            7 :     AE_RUN_INFO_LOG(AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.", soFile.c_str());
     651            7 :     return newSSoMngr->Init(oriPath, soFile);
     652              : }
     653              : } // namespace cce
        

Generated by: LCOV version 2.0-1