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
|