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 <sys/prctl.h>
12 : #include "securec.h"
13 : #include "user_log.h"
14 : #include "ra_hdc_async.h"
15 : #include "ra_rs_comm.h"
16 : #include "ra_rs_err.h"
17 : #include "ra_adp.h"
18 : #include "ra_adp_pool.h"
19 : #include "ra_adp_async.h"
20 :
21 : struct RaHdcAsyncInfo gHdcAsync[RA_MAX_PHY_ID_NUM] = {0};
22 : struct RaHdcInitPara gHdcAsyncInitPara = {0};
23 : struct RsPthreadInfo gRaAsyncThreadInfo = {0};
24 :
25 119 : int RaHwAsyncInit(unsigned int chipId, pid_t pid)
26 : {
27 : int ret;
28 :
29 119 : ret = pthread_mutex_init(&gHdcAsyncInitPara.mutex, NULL);
30 119 : CHK_PRT_RETURN(ret != 0, hccp_err("g_hdc_async_init_para mutex_init failed ret %d", ret), -ESYSFUNC);
31 :
32 119 : gHdcAsyncInitPara.chipId = chipId;
33 119 : gHdcAsyncInitPara.hostTgid = pid;
34 :
35 119 : ret = pthread_mutex_init(&gHdcAsync[chipId].sendMutex, NULL);
36 119 : if (ret != 0) {
37 0 : hccp_err("send_mutex mutex_init failed ret %d", ret);
38 0 : pthread_mutex_destroy(&gHdcAsyncInitPara.mutex);
39 0 : return -ESYSFUNC;
40 : }
41 119 : RaHdcInitOpSec(&gHdcAsync[chipId].opSec, BUCKET_DEPTH, true);
42 119 : return 0;
43 : }
44 :
45 1 : STATIC int RaHdcHandleSendPkt(unsigned int chipId, void *recvBuf, unsigned int recvLen)
46 : {
47 1 : unsigned int closeSession = 0;
48 1 : void *sendBuf = NULL;
49 1 : int sendLen = 0;
50 : int ret;
51 :
52 1 : RsSetCtx(chipId);
53 :
54 1 : ret = RaHandle(&gHdcAsync[chipId].opSec, recvBuf, recvLen, (char **)&sendBuf, &sendLen, &closeSession);
55 1 : if (ret != 0) {
56 0 : hccp_err("ra_handle failed, ret:%d", ret);
57 0 : goto out;
58 : }
59 :
60 1 : ret = RaHdcAsyncSendPkt(&gHdcAsync[chipId], chipId, sendBuf, sendLen);
61 1 : if (ret != 0) {
62 1 : hccp_err("send_pkt failed, ret:%d", ret);
63 1 : goto err;
64 : }
65 :
66 0 : err:
67 1 : free(sendBuf);
68 1 : sendBuf = NULL;
69 1 : out:
70 1 : return ret;
71 : }
72 :
73 1 : STATIC void RaAsyncHandlePkt(unsigned int chipId, void *recvBuf, unsigned int recvLen)
74 : {
75 1 : struct MsgHead *recvMsgHead = (struct MsgHead *)recvBuf;
76 1 : bool closeSession = false;
77 :
78 : // should handle RA_RS_HDC_SESSION_CLOSE on recv thread
79 1 : if (recvLen < sizeof(struct MsgHead) || recvMsgHead->opcode == RA_RS_HDC_SESSION_CLOSE) {
80 1 : closeSession = true;
81 : }
82 1 : if (closeSession) {
83 1 : (void)RaHdcHandleSendPkt(chipId, recvBuf, recvLen);
84 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsyncInitPara.mutex);
85 1 : gHdcAsyncInitPara.connectStatus = HDC_UNCONNECTED;
86 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsyncInitPara.mutex);
87 1 : return;
88 : }
89 :
90 : // handle other opcode: generate task and process the msg with work thread
91 0 : RaHdcPoolAddTask(gHdcAsync[chipId].pool, RaHdcHandleSendPkt, chipId, recvBuf, recvLen);
92 : }
93 :
94 1 : STATIC void *RaAsyncPthread(void *arg)
95 : {
96 : (void)arg;
97 1 : unsigned int chipId = gHdcAsyncInitPara.chipId;
98 1 : unsigned int recvLen = 0;
99 1 : void *recvBuf = NULL;
100 : int ret;
101 :
102 1 : ret = pthread_detach(pthread_self());
103 1 : CHK_PRT_RETURN(ret != 0, hccp_err("pthread detach failed ret %d", ret), NULL);
104 :
105 1 : (void)prctl(PR_SET_NAME, (uintptr_t) "hccp_ra_async", 0, 0, 0);
106 :
107 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsyncInitPara.mutex);
108 1 : gHdcAsyncInitPara.threadStatus = THREAD_RUNNING;
109 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsyncInitPara.mutex);
110 :
111 1 : RsGetCurTime(&gRaAsyncThreadInfo.lastCheckTime);
112 1 : ret = strncpy_s((char *)gRaAsyncThreadInfo.pthreadName, sizeof(gRaAsyncThreadInfo.pthreadName), "ra_async_thread",
113 : strlen("ra_async_thread"));
114 1 : CHK_PRT_RETURN(ret != 0, hccp_err("strncpy_s pthread name failed, ret[%d]", ret), NULL);
115 :
116 1 : hccp_run_info("pthread[%s] is alive!", gRaAsyncThreadInfo.pthreadName);
117 : while (1) {
118 1 : if (gHdcAsyncInitPara.threadStatus == THREAD_DESTROYING) {
119 0 : break;
120 : }
121 :
122 1 : if (gHdcAsyncInitPara.connectStatus != HDC_CONNECTED) {
123 0 : usleep(THREAD_SLEEP_TIME);
124 0 : continue;
125 : }
126 1 : RsHeartbeatAlivePrint(&gRaAsyncThreadInfo);
127 : // recv msg from hdc, alloc recv_buf in ra_async_pthread, free in work_pthread
128 1 : ret = RaHdcAsyncRecvPkt(&gHdcAsync[chipId], chipId, &recvBuf, &recvLen);
129 1 : if (ret != 0) {
130 1 : hccp_err("ra_hdc_async_recv_pkt failed, ret:%d chipId:%u", ret, chipId);
131 1 : break;
132 : }
133 :
134 0 : RaAsyncHandlePkt(chipId, recvBuf, recvLen);
135 : }
136 :
137 1 : hccp_info("thread [%d] is out, cleaning resources", getpid());
138 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsyncInitPara.mutex);
139 1 : gHdcAsyncInitPara.threadStatus = THREAD_HALT;
140 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsyncInitPara.mutex);
141 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsync[chipId].sendMutex);
142 1 : RaHdcCloseSession(&gHdcAsync[chipId].hdcSession);
143 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsync[chipId].sendMutex);
144 1 : return NULL;
145 : }
146 :
147 1 : STATIC void RaHwAsyncHdcInit(void *arg)
148 : {
149 : (void)arg;
150 1 : unsigned int chipId = gHdcAsyncInitPara.chipId;
151 : pthread_t tidp;
152 : int ret;
153 :
154 1 : ret = pthread_detach(pthread_self());
155 1 : if (ret != 0) {
156 0 : hccp_err("pthread detach failed chip_id(%u), ret %d", chipId, ret);
157 0 : return;
158 : }
159 :
160 1 : (void)prctl(PR_SET_NAME, (uintptr_t) "hccp_hw_async", 0, 0, 0);
161 :
162 1 : hccp_info("chip_id(%u)", chipId);
163 1 : gHdcAsyncInitPara.hdcFlag = 1;
164 :
165 1 : ret = pthread_create(&tidp, NULL, (void *)RaAsyncPthread, NULL);
166 1 : if (ret != 0) {
167 0 : hccp_err("Create pthread failed, chipId(%u), ret(%d) ", chipId, ret);
168 0 : return;
169 : }
170 :
171 : while (1) {
172 1 : if (gHdcAsyncInitPara.connectStatus != HDC_UNCONNECTED) {
173 0 : usleep(HDC_ACCEPT_SLEEP_TIME);
174 0 : continue;
175 : }
176 1 : ret = RaHdcSessionAccept(chipId, &gHdcAsync[chipId].hdcSession, (int)gHdcAsyncInitPara.hostTgid);
177 1 : if (ret != 0) {
178 0 : gHdcAsyncInitPara.hdcFlag = 0;
179 0 : return;
180 : }
181 : // should continue to accept: host_tgid != g_hdc_async_init_para.host_tgid
182 1 : if (ret == 0 && gHdcAsync[chipId].hdcSession == NULL) {
183 0 : continue;
184 : }
185 :
186 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsyncInitPara.mutex);
187 1 : gHdcAsyncInitPara.connectStatus = HDC_CONNECTED;
188 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsyncInitPara.mutex);
189 1 : return;
190 : }
191 : }
192 :
193 122 : void RaHwAsyncDeinit(void)
194 : {
195 122 : pthread_mutex_destroy(&gHdcAsync[gHdcAsyncInitPara.chipId].sendMutex);
196 122 : pthread_mutex_destroy(&gHdcAsyncInitPara.mutex);
197 122 : }
198 :
199 1 : int RaRsAsyncHdcSessionConnect(char *inBuf, char *outBuf, int *outLen, int *opResult, int rcvBufLen)
200 : {
201 : (void)outBuf;
202 : (void)outLen;
203 1 : union OpAsyncHdcConnectData *asyncData = NULL;
204 1 : int timeout = RA_THREAD_TRY_TIME;
205 1 : unsigned int phyId = 0;
206 : pthread_t tidp;
207 : int ret;
208 :
209 : HCCP_CHECK_PARAM_LEN_RET_HOST(sizeof(union OpAsyncHdcConnectData), sizeof(struct MsgHead), rcvBufLen, opResult);
210 1 : asyncData = (union OpAsyncHdcConnectData *)(inBuf + sizeof(struct MsgHead));
211 : HCCP_CHECK_PARAM_LEN_RET_HOST(asyncData->txData.queueSize, 0, MAX_POOL_QUEUE_SIZE, opResult);
212 : HCCP_CHECK_PARAM_LEN_RET_HOST(asyncData->txData.threadNum, 0, MAX_POOL_THREAD_NUM, opResult);
213 :
214 1 : phyId = gHdcAsyncInitPara.chipId;
215 1 : gHdcAsync[phyId].pool = RaHdcPoolCreate(asyncData->txData.queueSize, asyncData->txData.threadNum);
216 1 : if (gHdcAsync[phyId].pool == NULL) {
217 0 : hccp_err("ra_hdc_pool_create failed, queueSize:%u threadNum:%u phyId:%u", asyncData->txData.queueSize,
218 : asyncData->txData.threadNum, asyncData->txData.phyId);
219 0 : *opResult = -ESYSFUNC;
220 0 : return 0;
221 : }
222 :
223 1 : ret = pthread_create(&tidp, NULL, (void *)RaHwAsyncHdcInit, NULL);
224 1 : if (ret != 0) {
225 0 : hccp_err("Create pthread failed, ret(%d)", ret);
226 0 : *opResult = -ESYSFUNC;
227 0 : RaHdcPoolDestroy(gHdcAsync[phyId].pool);
228 0 : gHdcAsync[phyId].pool = NULL;
229 0 : return 0;
230 : }
231 :
232 : // will block until time out: RA_THREAD_TRY_TIME * RA_THREAD_SLEEP_TIME us
233 2 : while (gHdcAsyncInitPara.hdcFlag != 1 && timeout > 0) {
234 1 : usleep(RA_THREAD_SLEEP_TIME);
235 1 : timeout--;
236 : }
237 :
238 1 : if (gHdcAsyncInitPara.hdcFlag == 0 || timeout <= 0) {
239 0 : hccp_err("HDC server thread create timeout, flag %d, timeout %d", gHdcAsyncInitPara.hdcFlag, timeout);
240 0 : *opResult = -ESRCH;
241 0 : RaHdcPoolDestroy(gHdcAsync[phyId].pool);
242 0 : gHdcAsync[phyId].pool = NULL;
243 0 : return 0;
244 : }
245 :
246 1 : *opResult = 0;
247 1 : return 0;
248 : }
249 :
250 1 : int RaRsAsyncHdcSessionClose(char *inBuf, char *outBuf, int *outLen, int *opResult, int rcvBufLen)
251 : {
252 : (void)inBuf;
253 : (void)outBuf;
254 : (void)outLen;
255 1 : int tryAgain = HDC_TRY_TIME;
256 1 : unsigned int phyId = 0;
257 :
258 : HCCP_CHECK_PARAM_LEN_RET_HOST(sizeof(union OpAsyncHdcCloseData), sizeof(struct MsgHead), rcvBufLen, opResult);
259 :
260 1 : RA_PTHREAD_MUTEX_LOCK(&gHdcAsyncInitPara.mutex);
261 1 : gHdcAsyncInitPara.threadStatus = THREAD_DESTROYING;
262 1 : RA_PTHREAD_MUTEX_UNLOCK(&gHdcAsyncInitPara.mutex);
263 :
264 201 : while ((gHdcAsyncInitPara.threadStatus != THREAD_HALT) && tryAgain != 0) {
265 200 : usleep(HDC_USLEEP_TIME);
266 200 : tryAgain--;
267 : }
268 :
269 1 : if (tryAgain <= 0) {
270 1 : hccp_warn("hdc async message thread quit timeout");
271 : }
272 :
273 1 : phyId = gHdcAsyncInitPara.chipId;
274 1 : RaHdcPoolDestroy(gHdcAsync[phyId].pool);
275 1 : gHdcAsync[phyId].pool = NULL;
276 1 : *opResult = 0;
277 1 : return 0;
278 : }
|