Line data Source code
1 :
2 :
3 : /**
4 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
5 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6 : * CANN Open Software License Agreement Version 2.0 (the "License").
7 : * Please refer to the License for details. You may not use this file except in compliance with the License.
8 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10 : * See LICENSE in the root of the software repository for the full text of the License.
11 : */
12 :
13 : #include "hwts_kernel_queue.h"
14 :
15 : #include "ascend_hal.h"
16 : #include "aicpusd_monitor.h"
17 : #include "aicpusd_drv_manager.h"
18 : #include "hwts_kernel_common.h"
19 :
20 : namespace AicpuSchedule {
21 : namespace {
22 : const std::string CREATE_QUEUE = "CreateQueue";
23 : const std::string DESTROY_QUEUE = "DestroyQueue";
24 : constexpr uint64_t TO_US = 1000000UL;
25 : constexpr GroupShareAttr GROUP_WITH_ALL_ATTR = {1U, 1U, 1U, 1U, 0U}; // admin + read + write + alloc
26 : } // namespace
27 :
28 2 : int32_t CreateQueueTsKernel::DoQueueSubscrible(const QueueAttr &queAttr, uint32_t *queueId) const
29 : {
30 2 : const uint32_t deviceId = AicpuDrvManager::GetInstance().GetDeviceId();
31 2 : auto drvRet = halQueueInit(deviceId);
32 2 : if ((drvRet != DRV_ERROR_NONE) && (drvRet != DRV_ERROR_REPEATED_INIT)) {
33 1 : aicpusd_err("halQueueInit error, deviceId[%u], drvRet[%d]", deviceId, drvRet);
34 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
35 : }
36 :
37 1 : drvRet = halQueueCreate(deviceId, &queAttr, queueId);
38 1 : if (drvRet != DRV_ERROR_NONE) {
39 0 : aicpusd_err("Create buff queue[%s] error, depth[%u], ret[%d]", queAttr.name, queAttr.depth, drvRet);
40 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
41 : }
42 :
43 1 : const int32_t ret = SubscribeEvent(deviceId, *queueId);
44 1 : if (ret != AICPU_SCHEDULE_OK) {
45 0 : (void)halQueueDestroy(deviceId, *queueId);
46 0 : return ret;
47 : }
48 :
49 1 : return AICPU_SCHEDULE_OK;
50 : }
51 :
52 3 : int32_t CreateQueueTsKernel::Compute(const aicpu::HwtsTsKernel &tsKernelInfo)
53 : {
54 3 : const aicpu::HwtsCceKernel &kernel = tsKernelInfo.kernelBase.cceKernel;
55 : // create queue op param : queueId(uint64_t) + queueName(128 char) + queueDepth(uint32_t)
56 3 : constexpr size_t len = sizeof(aicpu::AicpuParamHead) + sizeof(uint64_t) +
57 : static_cast<size_t>(QUEUE_MAX_STR_LEN) + sizeof(uint32_t);
58 3 : size_t offset = sizeof(aicpu::AicpuParamHead);
59 3 : const auto baseAddr = PtrToPtr<void, char_t>(ValueToPtr(kernel.paramBase));
60 3 : const aicpu::AicpuParamHead * const paramHead = PtrToPtr<char_t, aicpu::AicpuParamHead>(baseAddr);
61 3 : if (paramHead == nullptr) {
62 0 : aicpusd_err("ParamHead for create queue is nullptr");
63 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
64 : }
65 :
66 3 : if (static_cast<size_t>(paramHead->length) != len) {
67 0 : aicpusd_err("Create queue param length[%u] should be [%zu]", paramHead->length, len);
68 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
69 : }
70 :
71 3 : const int32_t ret = CreateGrp();
72 3 : if (ret != AICPU_SCHEDULE_OK) {
73 1 : aicpusd_err("CreateGrp abnormal, ret = %d.", ret);
74 1 : return ret;
75 : }
76 :
77 2 : const uint64_t queueIdAddr = *PtrToPtr<const char_t, const uint64_t>(PtrAdd<const char_t>(baseAddr, len, offset));
78 2 : const auto queueId = PtrToPtr<void, uint32_t>(ValueToPtr(queueIdAddr));
79 :
80 2 : offset += sizeof(uint64_t);
81 2 : const auto queueName = PtrAdd<const char_t>(baseAddr, static_cast<size_t>(paramHead->length), offset);
82 :
83 2 : QueueAttr queAttr = {};
84 2 : const auto memcpyRet = memcpy_s(queAttr.name, static_cast<size_t>(QUEUE_MAX_STR_LEN),
85 : queueName, static_cast<size_t>(QUEUE_MAX_STR_LEN));
86 2 : if (memcpyRet != EOK) {
87 0 : aicpusd_err("Memcpy_s failed, ret=%d.", memcpyRet);
88 0 : return AICPU_SCHEDULE_ERROR_INNER_ERROR;
89 : }
90 :
91 2 : offset += static_cast<size_t>(QUEUE_MAX_STR_LEN);
92 2 : const uint32_t queueDepth = *PtrToPtr<const char_t, const uint32_t>(PtrAdd<const char_t>(baseAddr, len, offset));
93 2 : queAttr.depth = queueDepth;
94 2 : queAttr.workMode = QUEUE_MODE_PULL;
95 :
96 2 : return DoQueueSubscrible(queAttr, queueId);
97 : }
98 :
99 2 : int32_t CreateQueueTsKernel::CreateGrp() const
100 : {
101 2 : const pid_t curPid = drvDeviceGetBareTgid();
102 2 : std::map<std::string, GroupShareAttr> buffGrpInfo;
103 2 : const auto ret = AicpuDrvManager::GetInstance().QueryProcBuffInfo(static_cast<uint32_t>(curPid), buffGrpInfo);
104 2 : if (ret != AICPU_SCHEDULE_OK) {
105 0 : aicpusd_err("Fail to get group info of master aicpusd[%d]", curPid);
106 0 : return ret;
107 : }
108 : // 0 group need to create group
109 2 : if (buffGrpInfo.size() == 0UL) {
110 2 : aicpusd_info("There is no group for master aicpusd[%d]. Create new group", curPid);
111 2 : struct timeval tv = {};
112 2 : (void)gettimeofday(&tv, nullptr);
113 2 : const uint64_t groupNameAddition =
114 2 : (static_cast<uint64_t>(tv.tv_sec) * TO_US) + (static_cast<uint64_t>(tv.tv_usec));
115 2 : const std::string groupName = "Aicpusd" + std::to_string(groupNameAddition);
116 2 : GroupCfg groupConf = {};
117 2 : groupConf.privMbufFlag = static_cast<uint32_t>(BUFF_ENABLE_PRIVATE_MBUF);
118 : // 1.create group
119 2 : auto drvRet = halGrpCreate(groupName.c_str(), &groupConf);
120 2 : if (drvRet != DRV_ERROR_NONE) {
121 0 : aicpusd_err("Create group failed in aicpusd[%d], result[%d]", curPid, drvRet);
122 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
123 : }
124 :
125 : // 2.add current process to new group
126 2 : drvRet = halGrpAddProc(groupName.c_str(), curPid, GROUP_WITH_ALL_ATTR);
127 2 : if (drvRet != DRV_ERROR_NONE) {
128 0 : aicpusd_err("Add group[%s] for master aicpusd[%d] failed, ret[%d]",
129 : groupName.c_str(), curPid, drvRet);
130 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
131 : }
132 :
133 2 : drvRet = halGrpAttach(groupName.c_str(), 0);
134 2 : if (drvRet != DRV_ERROR_NONE) {
135 0 : aicpusd_err("Attach group[%s] for master aicpusd[%d] failed, ret[%d]",
136 : groupName.c_str(), curPid, drvRet);
137 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
138 : }
139 :
140 : // 3.initial process
141 2 : BuffCfg buffCfg = {};
142 2 : drvRet = halBuffInit(&buffCfg);
143 2 : if (drvRet != DRV_ERROR_NONE) {
144 0 : aicpusd_err("Buffer initial failed for master aicpusd[%d], ret[%d]", curPid, drvRet);
145 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
146 : }
147 2 : aicpusd_info("Create new group[%s] for master aicpusd[%d] success", groupName.c_str(), curPid);
148 2 : }
149 2 : return AICPU_SCHEDULE_OK;
150 2 : }
151 :
152 5 : int32_t CreateQueueTsKernel::SubscribeEvent(const uint32_t deviceId, const uint32_t queueId) const
153 : {
154 5 : int32_t ret = halQueueSubscribe(deviceId, queueId, 0U, QUEUE_TYPE_SINGLE);
155 5 : if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_QUEUE_RE_SUBSCRIBED)) {
156 1 : aicpusd_err("Subscribe queue[%u] failed, ret[%d].", queueId, ret);
157 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
158 : }
159 :
160 4 : if ((ret == DRV_ERROR_QUEUE_RE_SUBSCRIBED) && (Resubscribe(deviceId, queueId) != AICPU_SCHEDULE_OK)) {
161 1 : aicpusd_err("Resubscribe queue[%u] failed.", queueId);
162 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
163 : }
164 :
165 3 : ret = halQueueSubF2NFEvent(deviceId, queueId, 0U);
166 3 : if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_QUEUE_RE_SUBSCRIBED)) {
167 1 : aicpusd_err("Subscribe queue[%u] F2NF event failed, ret[%d].", queueId, ret);
168 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
169 : }
170 :
171 2 : if ((ret == DRV_ERROR_QUEUE_RE_SUBSCRIBED) && (ResubscribeF2NF(deviceId, queueId) != AICPU_SCHEDULE_OK)) {
172 1 : aicpusd_err("Resubscribe queue[%u] F2NF event failed.", queueId);
173 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
174 : }
175 1 : return AICPU_SCHEDULE_OK;
176 : }
177 :
178 4 : int32_t CreateQueueTsKernel::Resubscribe(const uint32_t deviceId, const uint32_t queueId) const
179 : {
180 4 : int32_t queueStatus = halQueueUnsubscribe(deviceId, queueId);
181 4 : if ((queueStatus != DRV_ERROR_NONE) && (queueStatus != DRV_ERROR_NOT_EXIST)) {
182 2 : aicpusd_err("Unsubscribe queue[%u] failed, ret[%d].", queueId, queueStatus);
183 2 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
184 : }
185 :
186 2 : queueStatus = halQueueSubscribe(deviceId, queueId, 0U, QUEUE_TYPE_SINGLE);
187 2 : if (queueStatus != DRV_ERROR_NONE) {
188 1 : aicpusd_err("Subscribe queue[%u] failed, ret[%d].", queueId, queueStatus);
189 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
190 : }
191 1 : return AICPU_SCHEDULE_OK;
192 : }
193 :
194 4 : int32_t CreateQueueTsKernel::ResubscribeF2NF(const uint32_t deviceId, const uint32_t queueId) const
195 : {
196 4 : int32_t queueStatus = halQueueUnsubF2NFEvent(deviceId, queueId);
197 4 : if ((queueStatus != DRV_ERROR_NONE) && (queueStatus != DRV_ERROR_NOT_EXIST)) {
198 1 : aicpusd_err("Unsub F2NF event for queue[%u] failed, ret[%d].", queueId, queueStatus);
199 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
200 : }
201 :
202 3 : queueStatus = halQueueSubF2NFEvent(deviceId, queueId, 0U);
203 3 : if (queueStatus != DRV_ERROR_NONE) {
204 2 : aicpusd_err("Sub F2NF event for queue[%u] failed, ret=%d.", queueId, queueStatus);
205 2 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
206 : }
207 1 : return AICPU_SCHEDULE_OK;
208 : }
209 :
210 3 : int32_t DestroyQueueTsKernel::Compute(const aicpu::HwtsTsKernel &tsKernelInfo)
211 : {
212 3 : const aicpu::HwtsCceKernel &kernel = tsKernelInfo.kernelBase.cceKernel;
213 : // destroy queue op param : queueId(uint32_t)
214 3 : constexpr uint64_t len = sizeof(aicpu::AicpuParamHead) + sizeof(uint32_t);
215 3 : constexpr uint64_t offset = sizeof(aicpu::AicpuParamHead);
216 3 : const auto baseAddr = PtrToPtr<void, char_t>(ValueToPtr(kernel.paramBase));
217 3 : const aicpu::AicpuParamHead * const paramHead = PtrToPtr<char_t, aicpu::AicpuParamHead>(baseAddr);
218 3 : if (paramHead == nullptr) {
219 1 : aicpusd_err("ParamHead for DumpDataKernel is nullptr");
220 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
221 : }
222 :
223 2 : if (paramHead->length != len) {
224 1 : aicpusd_err("Destroy queue param length[%u] should be [%lu]", paramHead->length, len);
225 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
226 : }
227 :
228 1 : const uint32_t queueId = *PtrToPtr<const char_t, const uint32_t>(PtrAdd<const char_t>(baseAddr, len, offset));
229 1 : const uint32_t deviceId = AicpuDrvManager::GetInstance().GetDeviceId();
230 :
231 1 : int32_t eventRet = AICPU_SCHEDULE_OK;
232 1 : int32_t ret = halQueueUnsubscribe(deviceId, queueId);
233 1 : if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_NOT_EXIST)) {
234 0 : aicpusd_err("Unsubscribe queue[%u] failed, ret[%d].", queueId, ret);
235 0 : eventRet = AICPU_SCHEDULE_ERROR_DRV_ERR;
236 : }
237 :
238 1 : ret = halQueueUnsubF2NFEvent(deviceId, queueId);
239 1 : if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_NOT_EXIST)) {
240 0 : aicpusd_err("Unsubscribe queue[%u] F2NF event failed, ret[%d].", queueId, ret);
241 0 : eventRet = AICPU_SCHEDULE_ERROR_DRV_ERR;
242 : }
243 :
244 1 : ret = halQueueDestroy(deviceId, queueId);
245 1 : if (ret != DRV_ERROR_NONE) {
246 0 : aicpusd_err("Destroy queue[%u] error, ret[%d]", queueId, ret);
247 0 : eventRet = AICPU_SCHEDULE_ERROR_DRV_ERR;
248 : }
249 :
250 1 : return eventRet;
251 : }
252 :
253 : REGISTER_HWTS_KERNEL(CREATE_QUEUE, CreateQueueTsKernel);
254 : REGISTER_HWTS_KERNEL(DESTROY_QUEUE, DestroyQueueTsKernel);
255 : } // namespace AicpuSchedule
|