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 "dpu_notify_manager.h"
12 : #include "log.h"
13 : namespace hcomm {
14 :
15 : constexpr uint32_t BYTE_SIZE = 8; // 一个字节占8位,用于比较赋值等,避免使用魔法数字
16 :
17 186 : DpuNotifyManager& DpuNotifyManager::GetInstance()
18 : {
19 186 : int numNotify = 8192;
20 186 : static DpuNotifyManager instance{numNotify};
21 186 : return instance;
22 : }
23 :
24 2 : DpuNotifyManager::DpuNotifyManager(int numEntries)
25 : {
26 2 : if (numEntries <= 0) {
27 0 : numEntries = 1;
28 : }
29 2 : byteSize = (numEntries + BYTE_SIZE - 1) / BYTE_SIZE;
30 2 : notifyIdBitMap = std::vector<unsigned char>(byteSize, 0x00);
31 2 : freeBit = std::vector<uint32_t>(byteSize, 0);
32 2 : }
33 :
34 2 : DpuNotifyManager::~DpuNotifyManager() = default;
35 :
36 456 : void DpuNotifyManager::UpdateFreeBit(uint32_t index)
37 : {
38 1040 : for (uint32_t j = 0; j < BYTE_SIZE; ++j) {
39 1039 : if (!(notifyIdBitMap[index] & (1 << j))) { // 检查第j位是否为0
40 455 : freeBit[index] = j;
41 455 : return;
42 : }
43 : }
44 1 : freeBit[index] = BYTE_SIZE; // 都检查完了,已满
45 : }
46 :
47 232 : int DpuNotifyManager::AllocSingleNotifyId()
48 : {
49 240 : for (uint32_t i = 0; i < byteSize; ++i) {
50 240 : if (notifyIdBitMap[i] != 0xFF) { // 当前字节未满
51 232 : notifyIdBitMap[i] |= (1 << freeBit[i]); // 设置为1
52 232 : size_t tmp = freeBit[i]; // 后续update会覆盖,所以先存起来。
53 232 : UpdateFreeBit(i);
54 232 : return i * BYTE_SIZE + tmp;
55 : }
56 : }
57 0 : return -1; // 无可用资源
58 : }
59 :
60 62 : HcclResult DpuNotifyManager::AllocNotifyIds(
61 : uint32_t notifyNum,
62 : std::vector<uint32_t>& notifyIds) // std::unique_ptr<uint64_t[]>& handles)
63 : {
64 62 : if (notifyNum == 0) {
65 0 : HCCL_INFO("[DpuNotifyManager::%s] notifyNum == 0, no need to alloc.", __func__);
66 0 : return HCCL_SUCCESS;
67 : }
68 :
69 62 : if (notifyNum > byteSize * BYTE_SIZE) {
70 1 : HCCL_ERROR(
71 : "[DpuNotifyManager::%s] notifyNum[%u] is too large. Maximum: %u.", __func__, notifyNum,
72 : byteSize * BYTE_SIZE);
73 1 : return HCCL_E_PARA;
74 : }
75 :
76 61 : std::lock_guard<std::mutex> lock(mtxAlloc_);
77 :
78 61 : notifyIds.resize(notifyNum);
79 :
80 293 : for (uint32_t i = 0; i < notifyNum; ++i) {
81 232 : int notifyId = AllocSingleNotifyId();
82 232 : if (notifyId == -1) {
83 : // 空间不足,释放之前的申请,并报错
84 0 : FreeNotifyIds(i, notifyIds);
85 0 : HCCL_ERROR("[DpuNotifyManager::%s] no free notify to alloc.", __func__);
86 0 : return HCCL_E_MEMORY;
87 : }
88 232 : notifyIds[i] = notifyId; // 存起来
89 : }
90 61 : return HCCL_SUCCESS;
91 61 : }
92 :
93 224 : void DpuNotifyManager::FreeSingleNotifyId(uint32_t notifyId)
94 : {
95 : // 校验输入是否溢出
96 224 : if (notifyId >= byteSize * BYTE_SIZE) {
97 0 : HCCL_INFO("[DpuNotifyManager::%s] no need to free.", __func__);
98 0 : return;
99 : }
100 224 : uint32_t byteIndex = notifyId / BYTE_SIZE;
101 224 : uint32_t bitIndex = notifyId % BYTE_SIZE;
102 224 : notifyIdBitMap[byteIndex] &= ~(1 << bitIndex);
103 224 : UpdateFreeBit(byteIndex);
104 224 : return;
105 : }
106 :
107 123 : HcclResult DpuNotifyManager::FreeNotifyIds(uint32_t notifyNum, std::vector<uint32_t>& notifyIds)
108 : {
109 123 : if (notifyNum == 0) { // 没有需要回收的notify
110 59 : HCCL_INFO("[DpuNotifyManager::%s] notifyNum == 0, no need to free.", __func__);
111 59 : return HCCL_SUCCESS;
112 : }
113 :
114 64 : if (notifyNum > notifyIds.size()) {
115 5 : HCCL_ERROR(
116 : "[DpuNotifyManager::%s] notifyNum[%u] > notifyIds length[%zu].", __func__, notifyNum, notifyIds.size());
117 5 : return HCCL_E_PARA;
118 : }
119 :
120 59 : std::lock_guard<std::mutex> lock(mtxFree_);
121 :
122 283 : for (uint32_t i = 0; i < notifyNum; ++i) {
123 224 : FreeSingleNotifyId(notifyIds[i]);
124 : }
125 59 : return HCCL_SUCCESS;
126 59 : }
127 :
128 : } // namespace hcomm
|