LCOV - code coverage report
Current view: top level - base_comm/resources/reged_mems - reged_mem_mgr.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.1 % 92 70
Test Date: 2026-07-28 12:11:00 Functions: 81.4 % 43 35

            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              : #ifndef REGED_MEM_MGR_H
      11              : #define REGED_MEM_MGR_H
      12              : 
      13              : #include <algorithm>
      14              : #include <cstdint>
      15              : #include <memory>
      16              : #include <utility>
      17              : #include <vector>
      18              : #include "hcomm_c_adpt.h"
      19              : #include "log.h"
      20              : #include "buffer_key.h"
      21              : #include "buffer.h"
      22              : 
      23              : using RdmaHandle = void *;
      24              : 
      25              : namespace hcomm {
      26              : /**
      27              :  * @note 职责:用于通信设备EndPoint的注册内存信息管理,支持基于RmaBufferMgr类的重叠内存的检测报错等。
      28              :  */
      29              : class RegedMemMgr {
      30              : public:
      31          237 :     RegedMemMgr() = default;
      32          208 :     virtual ~RegedMemMgr() = default;
      33              : 
      34              :     // 注册内存
      35              :     virtual HcclResult RegisterMemory(HcommMem mem, const char *memTag, void **memHandle) = 0;
      36              : 
      37              :     // 注销内存
      38              :     virtual HcclResult UnregisterMemory(void* memHandle) = 0;
      39              :  
      40              :     // 导出指定内存描述,用于交换
      41              :     virtual HcclResult MemoryExport(const EndpointDesc endpointDesc, void *memHandle, void **memDesc, uint32_t *memDescLen) = 0;
      42              :  
      43              :     // 基于内存描述,导入获得内存
      44              :     virtual HcclResult MemoryImport(const void *memDesc, uint32_t descLen, HcommMem *outMem) = 0;
      45              :  
      46              :     // 关闭内存
      47              :     virtual HcclResult MemoryUnimport(const void *memDesc, uint32_t descLen) = 0;
      48              : 
      49              :     virtual HcclResult GetAllMemHandles(void **memHandles, uint32_t *memHandleNum) = 0;
      50              :  
      51              :     // 授权
      52            0 :     virtual HcclResult MemoryGrant(const HcommMemGrantInfo *remoteGrantInfo)
      53              :     {
      54            0 :         return HCCL_SUCCESS;
      55              :     }
      56              : 
      57              :     RdmaHandle rdmaHandle_{nullptr};
      58              : 
      59              : protected:
      60              :     template <typename RmaBuffer>
      61              :     using RegedBufferEntry = std::pair<std::shared_ptr<RmaBuffer>, bool>;
      62              : 
      63           58 :     static HcclResult ValidateMemParams(HcommMem mem, void **memHandle)
      64              :     {
      65           58 :         CHK_PTR_NULL(memHandle);
      66           57 :         CHK_PTR_NULL(mem.addr);
      67           54 :         CHK_PRT_RET(mem.size == 0, HCCL_ERROR("[%s] mem size is zero", __func__), HCCL_E_PARA);
      68           51 :         CHK_PRT_RET(mem.type == COMM_MEM_TYPE_INVALID,
      69              :             HCCL_ERROR("[%s] invalid mem type [%d]", __func__, mem.type), HCCL_E_PARA);
      70           48 :         return HCCL_SUCCESS;
      71              :     }
      72              : 
      73              :     // MemoryExport: 从allBuffers中校验memHandle并获取buffer指针
      74              :     template <typename RmaBuffer>
      75            6 :     static HcclResult ValidateMemExportHandle(void *memHandle,
      76              :         const std::vector<RegedBufferEntry<RmaBuffer>>& allBuffers, RmaBuffer*& outBuffer)
      77              :     {
      78            6 :         auto it = std::find_if(allBuffers.begin(), allBuffers.end(),
      79            2 :             [memHandle](const auto &entry) {
      80            2 :                 return entry.first != nullptr && entry.first.get() == memHandle;
      81              :             });
      82            6 :         if (it == allBuffers.end()) {
      83            4 :             HCCL_ERROR("[RegedMemMgr][MemoryExport] memHandle[%p] is not registered.", memHandle);
      84            4 :             return HCCL_E_NOT_FOUND;
      85              :         }
      86            2 :         outBuffer = it->first.get();
      87            2 :         return HCCL_SUCCESS;
      88              :     }
      89              : 
      90              :     // GetAllMemHandles: 收集所有未标记删除的buffer指针
      91              :     template <typename RmaBuffer>
      92            0 :     static HcclResult GetAllMemHandlesImpl(std::vector<RegedBufferEntry<RmaBuffer>>& allBuffers,
      93              :         std::vector<std::shared_ptr<RmaBuffer>>& activeHandles,
      94              :         void **memHandles, uint32_t *memHandleNum, const char* logTag)
      95              :     {
      96            0 :         CHK_PTR_NULL(memHandles);
      97            0 :         CHK_PTR_NULL(memHandleNum);
      98              : 
      99            0 :         activeHandles.clear();
     100            0 :         for (auto& entry : allBuffers) {
     101            0 :             if (!entry.second) {
     102            0 :                 activeHandles.push_back(entry.first);
     103              :             }
     104              :         }
     105              : 
     106            0 :         *memHandleNum = static_cast<uint32_t>(activeHandles.size());
     107            0 :         *memHandles = activeHandles.empty() ? nullptr : static_cast<void *>(activeHandles.data());
     108            0 :         HCCL_INFO("[%s][GetAllMemHandles] memHandleNum[%u]", logTag, *memHandleNum);
     109            0 :         return HCCL_SUCCESS;
     110              :     }
     111              : 
     112              :     // ---- 底层:tree 操作 ----
     113              : 
     114              :     // 用实际注册后的addr/size做key,对buffer增加引用计数
     115              :     template <typename Mgr, typename BufferPtr>
     116           51 :     static HcclResult AddBuffer(Mgr& mgr, const BufferPtr& buffer)
     117              :     {
     118           51 :         hccl::BufferKey<uintptr_t, u64> actualRegKey(
     119           51 :             reinterpret_cast<uintptr_t>(buffer->GetAddr()), static_cast<uint64_t>(buffer->GetSize()));
     120           51 :         EXCEPTION_CATCH((void)mgr->AddWithoutCheck(actualRegKey, buffer), return HCCL_E_INTERNAL);
     121           51 :         return HCCL_SUCCESS;
     122              :     }
     123              : 
     124              :     // UnregisterMemory: IsAlias为true时,通过硬件句柄定位父buffer
     125              :     template <typename Mgr, typename BufferPtr, typename BufferVec, typename HwHandleFn, typename EqualFn>
     126           15 :     static BufferPtr ResolveAliasParent(Mgr& mgr, const hccl::BufferKey<uintptr_t, u64>& ownKey,
     127              :         BufferPtr buffer, BufferVec& allBuffers, HwHandleFn&& hwHandleGetter, EqualFn&& tokenEqual)
     128              :     {
     129           15 :         auto token = hwHandleGetter(buffer);
     130           15 :         auto findResult = mgr->Find(ownKey);
     131           15 :         if (findResult.first && tokenEqual(hwHandleGetter(findResult.second.get()), token)) {
     132           15 :             return findResult.second.get();
     133              :         }
     134            0 :         for (auto& entry : allBuffers) {
     135            0 :             const auto& ptr = entry.first;
     136            0 :             if (ptr.get() == buffer) {
     137            0 :                 continue;
     138              :             }
     139            0 :             if (tokenEqual(hwHandleGetter(ptr.get()), token) && !ptr->IsAlias()) {
     140            0 :                 return ptr.get();
     141              :             }
     142              :         }
     143            0 :         return nullptr;
     144           15 :     }
     145              : 
     146              :     // ---- 中层:注册/注销 核心逻辑 ----
     147              : 
     148              :     // Find命中则基于父buffer构造别名,未命中则构造新buffer并注册
     149              :     template <typename Mgr, typename FindResult, typename BufferPtr, typename MakeAlias, typename MakeNew>
     150           30 :     static HcclResult RegisterOrAlias(Mgr& mgr, const FindResult& findPair, BufferPtr& buffer,
     151              :         MakeAlias&& makeAlias, MakeNew&& makeNew)
     152              :     {
     153           30 :         if (findPair.first) {
     154           11 :             auto parentBuffer = findPair.second;
     155           11 :             EXCEPTION_CATCH((buffer = makeAlias(parentBuffer)), return HCCL_E_PTR);
     156           11 :             CHK_RET(AddBuffer(mgr, parentBuffer));
     157           11 :         } else {
     158           19 :             EXCEPTION_CATCH((buffer = makeNew()), return HCCL_E_PTR);
     159           19 :             CHK_RET(AddBuffer(mgr, buffer));
     160              :         }
     161           30 :         return HCCL_SUCCESS;
     162              :     }
     163              : 
     164              :     // ---- 上层:RegisterMemory / UnregisterMemory 通用实现 ----
     165              : 
     166              :     // 构造基类Buffer → RegisterOrAlias → 写回memHandle
     167              :     // makeAlias(bufPtr, parent) — 基于父buffer构造别名
     168              :     // makeNew(bufPtr)          — 构造新buffer
     169              :     template <typename Mgr, typename RmaBuffer, typename MakeAlias, typename MakeNew>
     170           37 :     static HcclResult RegisterMemoryImpl(HcommMem mem, const char *memTag, void **memHandle,
     171              :         Mgr& mgr, std::vector<RegedBufferEntry<RmaBuffer>>& allBuffers,
     172              :         const char* logTag, MakeAlias&& makeAlias, MakeNew&& makeNew)
     173              :     {
     174           37 :         CHK_RET(ValidateMemParams(mem, memHandle));
     175              : 
     176           30 :         hccl::BufferKey<uintptr_t, u64> tempKey(reinterpret_cast<uintptr_t>(mem.addr), mem.size);
     177           30 :         auto findPair = mgr->Find(tempKey);
     178              : 
     179           30 :         std::shared_ptr<Hccl::Buffer> localBufferPtr = nullptr;
     180           30 :         EXCEPTION_CATCH((localBufferPtr = std::make_shared<Hccl::Buffer>(reinterpret_cast<uintptr_t>(mem.addr),
     181              :             mem.size, static_cast<HcclMemType>(mem.type), memTag)),
     182              :             return HCCL_E_PTR);
     183              : 
     184           30 :         std::shared_ptr<RmaBuffer> rmaBuffer;
     185           60 :         CHK_RET(RegisterOrAlias(mgr, findPair, rmaBuffer,
     186              :             [&](auto& parent) { return makeAlias(localBufferPtr, parent); },
     187              :             [&]() { return makeNew(localBufferPtr); }));
     188              : 
     189           30 :         HCCL_INFO("[%s][RegisterMemory] success, key {%p, %llu}", logTag, mem.addr, mem.size);
     190           30 :         *memHandle = static_cast<void *>(rmaBuffer.get());
     191           30 :         allBuffers.emplace_back(rmaBuffer, false);
     192           30 :         return HCCL_SUCCESS;
     193           30 :     }
     194              : 
     195              :     // IsAlias → ResolveAliasParent → Del → erase
     196              :     // hwHandleGetter(buffer) — 获取硬件句柄用于ResolveAliasParent
     197              :     // tokenEqual(lhs, rhs)   — 比较两个句柄是否相等
     198              :     template <typename Mgr, typename RmaBuffer, typename HwHandleFn, typename EqualFn>
     199           38 :     static HcclResult UnregisterMemoryImpl(void* memHandle, Mgr& mgr,
     200              :         std::vector<RegedBufferEntry<RmaBuffer>>& allBuffers, HwHandleFn&& hwHandleGetter, EqualFn&& tokenEqual)
     201              :     {
     202           38 :         CHK_PTR_NULL(memHandle);
     203           37 :         RmaBuffer* buffer = static_cast<RmaBuffer*>(memHandle);
     204           37 :         CHK_PTR_NULL(buffer);
     205           37 :         auto bufferInfo = buffer->GetBufferInfo();
     206              : 
     207           37 :         hccl::BufferKey<uintptr_t, u64> ownKey(bufferInfo.first, bufferInfo.second);
     208           37 :         RmaBuffer* refBuffer = buffer;
     209           37 :         if (buffer->IsAlias()) {
     210           13 :             refBuffer = ResolveAliasParent(mgr, ownKey, buffer, allBuffers,
     211              :                 std::forward<HwHandleFn>(hwHandleGetter), std::forward<EqualFn>(tokenEqual));
     212           13 :             if (refBuffer == nullptr) {
     213            0 :                 HCCL_ERROR("[UnregisterMemory] alias parent not found");
     214            0 :                 return HCCL_E_NOT_FOUND;
     215              :             }
     216              :         }
     217              : 
     218           37 :         auto refBufferInfo = refBuffer->GetBufferInfo();
     219           37 :         hccl::BufferKey<uintptr_t, u64> tempKey(refBufferInfo.first, refBufferInfo.second);
     220              :         // Del returns false when ref remains nonzero; local unregister still succeeds after erasing this handle.
     221           37 :         EXCEPTION_CATCH((void)mgr->Del(tempKey), return HCCL_E_NOT_FOUND);
     222              :         // IsInTree判断tree中是否还有该key的引用
     223           30 :         auto it = std::find_if(allBuffers.begin(), allBuffers.end(),
     224           46 :             [buffer](const RegedBufferEntry<RmaBuffer>& entry) { return entry.first.get() == buffer; });
     225           30 :         if (it != allBuffers.end()) {
     226           30 :             if(!mgr->IsInTree(ownKey)) {
     227           22 :                 allBuffers.erase(it);
     228              :             } else {
     229            8 :                 it->second = true;
     230              :             }
     231              :         }
     232           30 :         return HCCL_SUCCESS;
     233              :     }
     234              : 
     235              : };
     236              : }
     237              : #endif // REGED_MEM_MGR_H
        

Generated by: LCOV version 2.0-1