LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_instance - ccu_var_event_res_mgr.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 80.5 % 328 264
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 21 21

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 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 "ccu_var_event_res_mgr.h"
      12              : 
      13              : #include <mutex>
      14              : 
      15              : #include "ccu_log.h"
      16              : #include "hccl_common.h"
      17              : #include "ccu_common.h"
      18              : 
      19              : #include "ccu_dev_mgr_imp.h"
      20              : #include "../ccu_device/ccu_res_specs.h"
      21              : 
      22              : #include "rt_external.h"
      23              : 
      24              : namespace hcomm {
      25              : 
      26          194 : CcuVarEventResMgr& CcuVarEventResMgr::GetInstance(const int32_t deviceLogicId)
      27              : {
      28          326 :     static CcuVarEventResMgr resMgrs[MAX_MODULE_DEVICE_NUM + 1];
      29              : 
      30          194 :     int32_t devLogicId = deviceLogicId;
      31          194 :     if (devLogicId < 0 || static_cast<uint32_t>(devLogicId) >= MAX_MODULE_DEVICE_NUM) {
      32            6 :         HCCL_WARNING(
      33              :             "[CcuVarEventResMgr][%s] use the backup device, devLogicId[%d] should be "
      34              :             "less than %u.",
      35              :             __func__, devLogicId, MAX_MODULE_DEVICE_NUM);
      36            6 :         devLogicId = MAX_MODULE_DEVICE_NUM;
      37              :     }
      38              : 
      39          194 :     resMgrs[devLogicId].devLogicId_ = devLogicId;
      40          194 :     return resMgrs[devLogicId];
      41              : }
      42              : 
      43           10 : CcuResult CcuVarEventResMgr::AllocFromPool(std::vector<ResInfo>& pool, uint32_t num, std::vector<ResInfo>& out)
      44              : {
      45           12 :     for (auto it = pool.begin(); it != pool.end(); ++it) {
      46           10 :         if (it->num < num) {
      47            2 :             continue;
      48              :         }
      49              : 
      50            8 :         out.clear();
      51            8 :         out.emplace_back(it->startId, num);
      52              : 
      53            8 :         if (it->num == num) {
      54            0 :             pool.erase(it);
      55              :         } else {
      56            8 :             it->startId += num;
      57            8 :             it->num -= num;
      58              :         }
      59            8 :         return CCU_SUCCESS;
      60              :     }
      61              : 
      62            2 :     return CCU_E_UNAVAIL;
      63              : }
      64              : 
      65            8 : void CcuVarEventResMgr::ReturnToPool(std::vector<ResInfo>& pool, const std::vector<ResInfo>& res)
      66              : {
      67           16 :     for (const auto& info : res) {
      68            8 :         if (info.num == 0) {
      69            0 :             continue;
      70              :         }
      71            8 :         pool.emplace_back(info.startId, info.num);
      72              :     }
      73            8 : }
      74              : 
      75           20 : static std::vector<ResInfo>* SelectPool(CcuResRepository& resRepo, CcuVarEventType type, uint8_t dieId)
      76              : {
      77           20 :     switch (type) {
      78           12 :         case CcuVarEventType::VARIABLE:
      79           12 :             return &resRepo.blockXn[dieId];
      80            8 :         case CcuVarEventType::EVENT:
      81            8 :             return &resRepo.blockCke[dieId];
      82            0 :         default:
      83            0 :             return nullptr;
      84              :     }
      85              : }
      86              : 
      87              : // 由预约资源类型推导runtime资源类型,不支持的类型返回false
      88           15 : static bool GetRtResType(CcuVarEventType type, rtDevResType_t& resType)
      89              : {
      90           15 :     switch (type) {
      91            9 :         case CcuVarEventType::VARIABLE:
      92            9 :             resType = RT_RES_TYPE_CCU_XN;
      93            9 :             return true;
      94            6 :         case CcuVarEventType::EVENT:
      95            6 :             resType = RT_RES_TYPE_CCU_CKE;
      96            6 :             return true;
      97            0 :         default:
      98            0 :             return false;
      99              :     }
     100              : }
     101              : 
     102           38 : static CcuResult MapDevResAddress(uint8_t dieId, rtDevResType_t resType, uint32_t resId, uint64_t& va)
     103              : {
     104           38 :     rtDevResInfo resInfo{};
     105           38 :     resInfo.dieId = dieId;
     106           38 :     resInfo.procType = RT_PROCESS_CP1;
     107           38 :     resInfo.resType = resType;
     108           38 :     resInfo.resId = resId;
     109           38 :     resInfo.flag = 0;
     110              : 
     111           38 :     uint64_t mappedAddr = 0;
     112           38 :     uint32_t mappedLen = 0;
     113           38 :     rtDevResAddrInfo addrInfo{};
     114           38 :     addrInfo.resAddress = &mappedAddr;
     115           38 :     addrInfo.len = &mappedLen;
     116              : 
     117           38 :     rtError_t ret = rtGetDevResAddress(&resInfo, &addrInfo);
     118           38 :     if (ret != RT_ERROR_NONE) {
     119            1 :         HCCL_ERROR(
     120              :             "[CcuVarEventResMgr][%s] rtGetDevResAddress failed[%d], dieId[%u] resType[%d] "
     121              :             "resId[%u].",
     122              :             __func__, ret, dieId, static_cast<int32_t>(resType), resId);
     123            1 :         return CCU_E_RUNTIME;
     124              :     }
     125              : 
     126           37 :     va = mappedAddr;
     127           37 :     return CCU_SUCCESS;
     128              : }
     129              : 
     130              : // 解除MapDevResAddress映射的进程可访问VA,与映射一一对应
     131           37 : static CcuResult UnmapDevResAddress(uint8_t dieId, rtDevResType_t resType, uint32_t resId)
     132              : {
     133           37 :     rtDevResInfo resInfo{};
     134           37 :     resInfo.dieId = dieId;
     135           37 :     resInfo.procType = RT_PROCESS_CP1;
     136           37 :     resInfo.resType = resType;
     137           37 :     resInfo.resId = resId;
     138           37 :     resInfo.flag = 0;
     139              : 
     140           37 :     rtError_t ret = rtReleaseDevResAddress(&resInfo);
     141           37 :     if (ret != RT_ERROR_NONE) {
     142            0 :         HCCL_ERROR(
     143              :             "[CcuVarEventResMgr][%s] rtReleaseDevResAddress failed[%d], dieId[%u] "
     144              :             "resType[%d] resId[%u].",
     145              :             __func__, ret, dieId, static_cast<int32_t>(resType), resId);
     146            0 :         return CCU_E_RUNTIME;
     147              :     }
     148              : 
     149           37 :     return CCU_SUCCESS;
     150              : }
     151              : 
     152              : namespace {
     153              :     // RegisterAddrs 中记录本次已成功映射的资源,供失败回滚逆序解除
     154              :     struct MappedRes {
     155              :         uint8_t dieId;
     156              :         uint32_t resId;
     157              :     };
     158              : } // namespace
     159              : 
     160              : // 逆序解除本次已完成的映射,与 MapDevResAddress 一一对应
     161              : static void
     162            1 : UnmapMappedRes(const std::vector<MappedRes>& mapped, rtDevResType_t resType, uint64_t handle, CcuVarEventType type)
     163              : {
     164            1 :     HCCL_RUN_WARNING(
     165              :         "[CcuVarEventResMgr][%s] rollback, unmap [%zu] mapped res of "
     166              :         "handle[0x%llx] type[%d].",
     167              :         __func__, mapped.size(), handle, static_cast<int32_t>(type));
     168            2 :     for (auto it = mapped.rbegin(); it != mapped.rend(); ++it) {
     169            1 :         (void)UnmapDevResAddress(it->dieId, resType, it->resId);
     170              :     }
     171            1 : }
     172              : 
     173            8 : CcuResult CcuVarEventResMgr::RegisterAddrs(CcuVarEventType type, uint64_t handle, uint32_t num)
     174              : {
     175            8 :     rtDevResType_t resType = RT_RES_TYPE_CCU_XN;
     176            8 :     if (!GetRtResType(type, resType)) {
     177            0 :         HCCL_ERROR(
     178              :             "[CcuVarEventResMgr][%s] failed, unsupported type[%d], handle[0x%llx].", __func__,
     179              :             static_cast<int32_t>(type), handle);
     180            0 :         return CCU_E_PARA;
     181              :     }
     182              : 
     183            8 :     std::vector<uint64_t> vaList{};
     184            8 :     std::vector<MappedRes> mapped{};
     185            8 :     vaList.reserve(num);
     186            8 :     mapped.reserve(num);
     187              : 
     188              :     // 归一本函数内三处失败回滚路径:均为“逆序解除已完成映射”,收敛成一个闭包,
     189              :     // 避免 UnmapMappedRes 调用点重复三份;(void) 消歧义式丢弃返回值,规避静态检查误报
     190            1 :     auto rollback = [&mapped, resType, handle, type]() {
     191            1 :         (void)UnmapMappedRes(mapped, resType, handle, type);
     192            9 :     };
     193              : 
     194           45 :     for (uint32_t index = 0; index < num; index++) {
     195           38 :         uint8_t dieId = 0;
     196           38 :         uint32_t resId = 0;
     197           38 :         CcuResult idRet = (type == CcuVarEventType::VARIABLE) ? GetVariableXnId(handle, index, dieId, resId) :
     198           10 :                                                                 GetEventCkeId(handle, index, dieId, resId);
     199           38 :         if (idRet != CCU_SUCCESS) {
     200            0 :             rollback();
     201            1 :             return idRet;
     202              :         }
     203              : 
     204           38 :         uint64_t va = 0;
     205           38 :         CcuResult mapRet = MapDevResAddress(dieId, resType, resId, va);
     206           38 :         if (mapRet != CCU_SUCCESS) {
     207            1 :             rollback();
     208            1 :             return mapRet;
     209              :         }
     210           37 :         vaList.push_back(va);
     211           37 :         mapped.push_back({dieId, resId});
     212              :     }
     213              : 
     214            7 :     CcuResult saveRet = SaveAddrs(type, handle, vaList);
     215            7 :     if (saveRet != CCU_SUCCESS) {
     216            0 :         rollback();
     217            0 :         return saveRet;
     218              :     }
     219            7 :     return CCU_SUCCESS;
     220            8 : }
     221              : 
     222           14 : CcuResult CcuVarEventResMgr::AllocAndRecord(
     223              :     CcuInsHandle insHandle, CcuResRepository& resRepo, CcuVarEventType type, uint8_t dieId, uint32_t num,
     224              :     uint64_t& newHandle)
     225              : {
     226           14 :     if (dieId >= CCU_MAX_IODIE_NUM) {
     227            2 :         HCCL_ERROR(
     228              :             "[CcuVarEventResMgr][%s] failed, dieId[%u] should be less than %u.", __func__, dieId, CCU_MAX_IODIE_NUM);
     229            2 :         return CCU_E_PARA;
     230              :     }
     231           12 :     if (num == 0) {
     232            2 :         HCCL_ERROR("[CcuVarEventResMgr][%s] failed, num should not be 0.", __func__);
     233            2 :         return CCU_E_PARA;
     234              :     }
     235              : 
     236           10 :     std::vector<ResInfo>* pool = SelectPool(resRepo, type, dieId);
     237           10 :     if (pool == nullptr) {
     238            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] failed, unsupported type[%d].", __func__, static_cast<int32_t>(type));
     239            0 :         return CCU_E_PARA;
     240              :     }
     241              : 
     242           10 :     std::vector<ResInfo> resInfos{};
     243           10 :     CcuResult ret = AllocFromPool(*pool, num, resInfos);
     244           10 :     if (ret != CCU_SUCCESS) {
     245            2 :         HCCL_ERROR(
     246              :             "[CcuVarEventResMgr][%s] failed, no consecutive block of num[%u] in insHandle[0x%llx] "
     247              :             "resource pool, dieId[%u] type[%d].",
     248              :             __func__, num, insHandle, dieId, static_cast<int32_t>(type));
     249            2 :         return ret;
     250              :     }
     251              : 
     252            8 :     CcuVarEventRes res{};
     253            8 :     res.insHandle = insHandle;
     254            8 :     res.devLogicId = devLogicId_;
     255            8 :     res.dieId = dieId;
     256            8 :     res.type = type;
     257            8 :     res.resInfos = std::move(resInfos);
     258            8 :     res.resRepo = &resRepo;
     259              : 
     260            8 :     std::unique_lock<std::shared_timed_mutex> lock(mapMutex_);
     261            8 :     handleSeed_ += 1;
     262            8 :     newHandle = handleSeed_;
     263            8 :     resMap_.emplace(newHandle, std::move(res));
     264            8 :     return CCU_SUCCESS;
     265           10 : }
     266              : 
     267           14 : CcuResult CcuVarEventResMgr::Acquire(
     268              :     CcuInsHandle insHandle, CcuResRepository& resRepo, CcuVarEventType type, uint8_t dieId, uint32_t num,
     269              :     uint64_t& handle)
     270              : {
     271           14 :     uint64_t newHandle = 0;
     272           14 :     CcuResult allocRet = AllocAndRecord(insHandle, resRepo, type, dieId, num, newHandle);
     273           14 :     if (allocRet != CCU_SUCCESS) {
     274            6 :         return allocRet;
     275              :     }
     276              : 
     277              :     // 申请期即完成地址映射;失败与切池动作配对,整笔撤销后不写出参
     278            8 :     CcuResult regRet = RegisterAddrs(type, newHandle, num);
     279            8 :     if (regRet != CCU_SUCCESS) {
     280            1 :         HCCL_RUN_WARNING(
     281              :             "[CcuVarEventResMgr][%s] register addrs failed[%d], release acquired "
     282              :             "handle[0x%llx] insHandle[0x%llx] dieId[%u] type[%d] num[%u].",
     283              :             __func__, static_cast<int32_t>(regRet), newHandle, insHandle, dieId, static_cast<int32_t>(type), num);
     284            1 :         (void)ReleaseByHandle(newHandle);
     285            1 :         return regRet;
     286              :     }
     287              : 
     288            7 :     handle = newHandle;
     289            7 :     HCCL_RUN_INFO(
     290              :         "[CcuVarEventResMgr][%s] success, devLogicId[%d] insHandle[0x%llx] dieId[%u] "
     291              :         "type[%d] num[%u] handle[0x%llx].",
     292              :         __func__, devLogicId_, insHandle, dieId, static_cast<int32_t>(type), num, handle);
     293            7 :     return CCU_SUCCESS;
     294              : }
     295              : 
     296           38 : CcuResult CcuVarEventResMgr::GetVariableXnId(uint64_t handle, uint32_t index, uint8_t& dieId, uint32_t& xnId) const
     297              : {
     298           38 :     std::shared_lock<std::shared_timed_mutex> lock(mapMutex_);
     299           38 :     auto it = resMap_.find(handle);
     300           38 :     if (it == resMap_.end()) {
     301            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] handle[0x%llx] is not existed.", __func__, handle);
     302            0 :         return CCU_E_NOT_FOUND;
     303              :     }
     304              : 
     305           38 :     const auto& res = it->second;
     306           38 :     if (res.type != CcuVarEventType::VARIABLE) {
     307            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] failed, handle[0x%llx] is not a variable(xn) resource.", __func__, handle);
     308            0 :         return CCU_E_PARA;
     309              :     }
     310           38 :     if (res.resInfos.size() != 1) {
     311            0 :         HCCL_ERROR(
     312              :             "[CcuVarEventResMgr][%s] get variable resource id failed, variable resource is fragmented into %zu blocks.",
     313              :             __func__, res.resInfos.size());
     314            0 :         return CCU_E_NOT_SUPPORT;
     315              :     }
     316              : 
     317           38 :     const ResInfo& info = res.resInfos[0];
     318           38 :     if (index >= info.num) {
     319            0 :         HCCL_ERROR(
     320              :             "[CcuVarEventResMgr][%s] get variable resource id failed, index[%u] out of range, block num[%u].", __func__,
     321              :             index, info.num);
     322            0 :         return CCU_E_PARA;
     323              :     }
     324              : 
     325           38 :     dieId = res.dieId;
     326           38 :     xnId = info.startId + index;
     327           38 :     return CCU_SUCCESS;
     328           38 : }
     329              : 
     330           14 : CcuResult CcuVarEventResMgr::GetEventCkeId(uint64_t handle, uint32_t index, uint8_t& dieId, uint32_t& ckeId) const
     331              : {
     332           14 :     std::shared_lock<std::shared_timed_mutex> lock(mapMutex_);
     333           14 :     auto it = resMap_.find(handle);
     334           14 :     if (it == resMap_.end()) {
     335            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] handle[0x%llx] is not existed.", __func__, handle);
     336            0 :         return CCU_E_NOT_FOUND;
     337              :     }
     338              : 
     339           14 :     const auto& res = it->second;
     340           14 :     if (res.type != CcuVarEventType::EVENT) {
     341            0 :         HCCL_ERROR(
     342              :             "[CcuVarEventResMgr][%s] get event resource id failed, handle[0x%llx] is not an event(cke) resource.",
     343              :             __func__, handle);
     344            0 :         return CCU_E_PARA;
     345              :     }
     346           14 :     if (res.resInfos.size() != 1) {
     347            0 :         HCCL_ERROR(
     348              :             "[CcuVarEventResMgr][%s] get event resource id failed, event resource is fragmented into %zu blocks.",
     349              :             __func__, res.resInfos.size());
     350            0 :         return CCU_E_NOT_SUPPORT;
     351              :     }
     352              : 
     353           14 :     const ResInfo& info = res.resInfos[0];
     354           14 :     if (index >= info.num) {
     355            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] failed, index[%u] out of range, block num[%u].", __func__, index, info.num);
     356            0 :         return CCU_E_PARA;
     357              :     }
     358              : 
     359           14 :     dieId = res.dieId;
     360           14 :     ckeId = info.startId + index;
     361           14 :     return CCU_SUCCESS;
     362           14 : }
     363              : 
     364            7 : CcuResult CcuVarEventResMgr::SaveAddrs(CcuVarEventType type, uint64_t handle, const std::vector<uint64_t>& vaList)
     365              : {
     366            7 :     std::unique_lock<std::shared_timed_mutex> lock(mapMutex_);
     367            7 :     auto it = resMap_.find(handle);
     368            7 :     if (it == resMap_.end()) {
     369            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] handle[0x%llx] is not existed.", __func__, handle);
     370            0 :         return CCU_E_NOT_FOUND;
     371              :     }
     372              : 
     373            7 :     auto& res = it->second;
     374            7 :     if (res.type != type) {
     375            0 :         HCCL_ERROR(
     376              :             "[CcuVarEventResMgr][%s] failed, handle[0x%llx] type mismatch, expect[%d] "
     377              :             "actual[%d].",
     378              :             __func__, handle, static_cast<int32_t>(type), static_cast<int32_t>(res.type));
     379            0 :         return CCU_E_PARA;
     380              :     }
     381            7 :     if (res.resInfos.size() != 1) {
     382            0 :         HCCL_ERROR(
     383              :             "[CcuVarEventResMgr][%s] failed, resource is fragmented into %zu blocks.", __func__, res.resInfos.size());
     384            0 :         return CCU_E_NOT_SUPPORT;
     385              :     }
     386            7 :     if (vaList.size() != res.resInfos[0].num) {
     387            0 :         HCCL_ERROR(
     388              :             "[CcuVarEventResMgr][%s] failed, va count[%zu] mismatch resource num[%u].", __func__, vaList.size(),
     389              :             res.resInfos[0].num);
     390            0 :         return CCU_E_PARA;
     391              :     }
     392              : 
     393            7 :     res.vaList = vaList;
     394            7 :     return CCU_SUCCESS;
     395            7 : }
     396              : 
     397           31 : CcuResult CcuVarEventResMgr::GetSavedAddr(CcuVarEventType type, uint64_t handle, uint32_t index, uint64_t& va) const
     398              : {
     399           31 :     std::shared_lock<std::shared_timed_mutex> lock(mapMutex_);
     400           31 :     auto it = resMap_.find(handle);
     401           31 :     if (it == resMap_.end()) {
     402            2 :         HCCL_ERROR("[CcuVarEventResMgr][%s] handle[0x%llx] is not existed.", __func__, handle);
     403            2 :         return CCU_E_NOT_FOUND;
     404              :     }
     405              : 
     406           29 :     const auto& res = it->second;
     407           29 :     if (res.type != type) {
     408            1 :         HCCL_ERROR(
     409              :             "[CcuVarEventResMgr][%s] failed, handle[0x%llx] type mismatch, expect[%d] "
     410              :             "actual[%d].",
     411              :             __func__, handle, static_cast<int32_t>(type), static_cast<int32_t>(res.type));
     412            1 :         return CCU_E_PARA;
     413              :     }
     414           28 :     if (index >= res.vaList.size()) {
     415            2 :         HCCL_ERROR(
     416              :             "[CcuVarEventResMgr][%s] failed, index[%u] out of range, registered num[%zu].", __func__, index,
     417              :             res.vaList.size());
     418            2 :         return CCU_E_PARA;
     419              :     }
     420              : 
     421           26 :     va = res.vaList[index];
     422           26 :     return CCU_SUCCESS;
     423           31 : }
     424              : 
     425            8 : CcuResult CcuVarEventResMgr::UnmapSavedAddrs(const CcuVarEventRes& res)
     426              : {
     427              :     // 仅 unmap Alloc 阶段已成功映射并保存 VA 的资源;错误回滚路径中 vaList 为空,天然跳过。
     428              :     // 不变量:vaList 非空 <=> SaveAddrs 已成功,而 SaveAddrs 强校验 resInfos 为单个连续块且
     429              :     // vaList.size() == resInfos[0].num,故下面用 resInfos[0].startId + index 反推 resId 恒成立
     430            8 :     if (res.vaList.empty() || res.resInfos.empty()) {
     431            1 :         return CCU_SUCCESS;
     432              :     }
     433              :     // 上述不变量当前由 SaveAddrs 保证,此处再作一次防御校验:一旦将来分配策略改为可返回多块,
     434              :     // 用首块 startId 反推 resId 会越出块边界,宁可跳过 unmap 也不能解除错误资源的映射
     435            7 :     if (res.resInfos.size() != 1) {
     436            0 :         HCCL_ERROR(
     437              :             "[CcuVarEventResMgr][%s] unexpected fragmented resInfos size[%zu], skip unmap.", __func__,
     438              :             res.resInfos.size());
     439            0 :         return CCU_E_NOT_SUPPORT;
     440              :     }
     441              : 
     442            7 :     rtDevResType_t resType = RT_RES_TYPE_CCU_XN;
     443            7 :     if (!GetRtResType(res.type, resType)) {
     444            0 :         HCCL_ERROR("[CcuVarEventResMgr][%s] failed, unsupported type[%d].", __func__, static_cast<int32_t>(res.type));
     445            0 :         return CCU_E_PARA;
     446              :     }
     447              : 
     448            7 :     CcuResult firstErr = CCU_SUCCESS;
     449            7 :     const uint32_t startId = res.resInfos[0].startId;
     450           43 :     for (uint32_t index = 0; index < res.vaList.size(); index++) {
     451           36 :         CcuResult ret = UnmapDevResAddress(res.dieId, resType, startId + index);
     452           36 :         if (ret != CCU_SUCCESS && firstErr == CCU_SUCCESS) {
     453            0 :             firstErr = ret;
     454              :         }
     455              :     }
     456            7 :     return firstErr;
     457              : }
     458              : 
     459            1 : CcuResult CcuVarEventResMgr::ReleaseByHandle(uint64_t handle)
     460              : {
     461            1 :     CcuVarEventRes res{};
     462              :     {
     463            1 :         std::unique_lock<std::shared_timed_mutex> lock(mapMutex_);
     464            1 :         auto it = resMap_.find(handle);
     465            1 :         if (it == resMap_.end()) {
     466            0 :             HCCL_ERROR("[CcuVarEventResMgr][%s] handle[0x%llx] is not existed.", __func__, handle);
     467            0 :             return CCU_E_NOT_FOUND;
     468              :         }
     469            1 :         res = std::move(it->second);
     470            1 :         resMap_.erase(it);
     471            1 :     }
     472              : 
     473              :     // 归还资源池前,先解除该 handle 已映射的进程可访问 VA;
     474              :     // unmap 失败不阻断归还,错误码上抛由调用方决定是否处理
     475            1 :     CcuResult unmapRet = UnmapSavedAddrs(res);
     476            1 :     if (unmapRet != CCU_SUCCESS) {
     477            0 :         HCCL_RUN_WARNING(
     478              :             "[CcuVarEventResMgr][%s] unmap failed[%d], continue to return resources, "
     479              :             "handle[0x%llx].",
     480              :             __func__, static_cast<int32_t>(unmapRet), handle);
     481              :     }
     482              : 
     483            1 :     if (res.resRepo == nullptr) {
     484            0 :         return unmapRet;
     485              :     }
     486            1 :     std::vector<ResInfo>* pool = SelectPool(*res.resRepo, res.type, res.dieId);
     487            1 :     if (pool == nullptr) {
     488            0 :         HCCL_ERROR(
     489              :             "[CcuVarEventResMgr][%s] failed to return, handle[0x%llx] type[%d].", __func__, handle,
     490              :             static_cast<int32_t>(res.type));
     491            0 :         return CCU_E_INTERNAL;
     492              :     }
     493            1 :     ReturnToPool(*pool, res.resInfos);
     494            1 :     return unmapRet;
     495            1 : }
     496              : 
     497           76 : CcuResult CcuVarEventResMgr::ReleaseByInstance(CcuInsHandle insHandle)
     498              : {
     499           76 :     std::vector<CcuVarEventRes> toRelease{};
     500              :     {
     501           76 :         std::unique_lock<std::shared_timed_mutex> lock(mapMutex_);
     502           83 :         for (auto it = resMap_.begin(); it != resMap_.end();) {
     503            7 :             if (it->second.insHandle == insHandle) {
     504            7 :                 toRelease.push_back(std::move(it->second));
     505            7 :                 it = resMap_.erase(it);
     506              :             } else {
     507            0 :                 ++it;
     508              :             }
     509              :         }
     510           76 :     }
     511              : 
     512              :     // 通信域正在销毁,单条失败不中断,记录首个错误码后继续清干净其余记录
     513           76 :     CcuResult firstErr = CCU_SUCCESS;
     514           83 :     for (auto& res : toRelease) {
     515              :         // ccu_instance 析构释放资源前,先解除 Alloc 阶段映射的进程可访问 VA
     516            7 :         CcuResult unmapRet = UnmapSavedAddrs(res);
     517            7 :         if (unmapRet != CCU_SUCCESS && firstErr == CCU_SUCCESS) {
     518            0 :             firstErr = unmapRet;
     519              :         }
     520              : 
     521            7 :         if (res.resRepo == nullptr) {
     522            0 :             continue;
     523              :         }
     524            7 :         std::vector<ResInfo>* pool = SelectPool(*res.resRepo, res.type, res.dieId);
     525            7 :         if (pool == nullptr) {
     526            0 :             HCCL_ERROR(
     527              :                 "[CcuVarEventResMgr][%s] failed to return, insHandle[0x%llx] type[%d].", __func__, insHandle,
     528              :                 static_cast<int32_t>(res.type));
     529            0 :             if (firstErr == CCU_SUCCESS) {
     530            0 :                 firstErr = CCU_E_INTERNAL;
     531              :             }
     532            0 :             continue;
     533              :         }
     534            7 :         ReturnToPool(*pool, res.resInfos);
     535              :     }
     536           76 :     return firstErr;
     537           76 : }
     538              : 
     539              : // 从空闲块列表 pool 中扣除区间 [start, start+num)必要时把命中的空闲块拆分成左右两段。
     540            2 : static void RemoveRangeFromPool(std::vector<ResInfo>& pool, uint32_t start, uint32_t num)
     541              : {
     542            2 :     if (num == 0) {
     543            0 :         return;
     544              :     }
     545            2 :     const uint32_t end = start + num;
     546            2 :     std::vector<ResInfo> result{};
     547            2 :     result.reserve(pool.size() + 1);
     548            4 :     for (const auto& block : pool) {
     549            2 :         const uint32_t blockStart = block.startId;
     550            2 :         const uint32_t blockEnd = block.startId + block.num;
     551            2 :         if (end <= blockStart || start >= blockEnd) {
     552            0 :             result.push_back(block);
     553            0 :             continue;
     554              :         }
     555            2 :         if (blockStart < start) {
     556            0 :             result.emplace_back(blockStart, start - blockStart);
     557              :         }
     558            2 :         if (end < blockEnd) {
     559            2 :             result.emplace_back(end, blockEnd - end);
     560              :         }
     561              :     }
     562            2 :     pool.swap(result);
     563            2 : }
     564              : 
     565           55 : CcuResult CcuVarEventResMgr::ExcludeAllocatedFromRepo(CcuInsHandle insHandle) const
     566              : {
     567              :     // shared_lock 用于只读遍历 resMap_;被修改的 *pool 属于该 insHandle 自己的 CcuResPack,
     568              :     // 其并发安全由“同一 instance 单线程串行访问”契约保证,详见头文件线程安全契约说明
     569           55 :     std::shared_lock<std::shared_timed_mutex> lock(mapMutex_);
     570           57 :     for (const auto& kv : resMap_) {
     571            2 :         const CcuVarEventRes& res = kv.second;
     572            2 :         if (res.insHandle != insHandle || res.resRepo == nullptr) {
     573            0 :             continue;
     574              :         }
     575            2 :         std::vector<ResInfo>* pool = SelectPool(*res.resRepo, res.type, res.dieId);
     576            2 :         if (pool == nullptr) {
     577            0 :             HCCL_ERROR(
     578              :                 "[CcuVarEventResMgr][%s] failed, insHandle[0x%llx] type[%d].", __func__, insHandle,
     579              :                 static_cast<int32_t>(res.type));
     580            0 :             continue;
     581              :         }
     582            4 :         for (const auto& info : res.resInfos) {
     583            2 :             RemoveRangeFromPool(*pool, info.startId, info.num);
     584            2 :             HCCL_INFO(
     585              :                 "[CcuVarEventResMgr][%s] exclude acquired res, insHandle[0x%llx] type[%d] "
     586              :                 "dieId[%u] startId[%u] num[%u].",
     587              :                 __func__, insHandle, static_cast<int32_t>(res.type), res.dieId, info.startId, info.num);
     588              :         }
     589              :     }
     590           55 :     return CCU_SUCCESS;
     591           55 : }
     592              : 
     593              : } // namespace hcomm
        

Generated by: LCOV version 2.0-1