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 : #include "trace_session_mgr.h"
11 : #include "adiag_lock.h"
12 : #include "adiag_print.h"
13 : #include "trace_system_api.h"
14 : #include "trace_adx_api.h"
15 : #include "ascend_hal.h"
16 :
17 : #define MAX_DEV_NUM 64
18 :
19 : STATIC SessionNode *g_sessionPidDevIdList = NULL;
20 : STATIC SessionNode *g_sessionPidDevIdDeletedList = NULL;
21 : STATIC AdiagLock g_sessionLock = TRACE_MUTEX_INITIALIZER;
22 :
23 41876 : void TraceServerSessionLock(void)
24 : {
25 41876 : (void)AdiagLockGet(&g_sessionLock);
26 41876 : }
27 :
28 41876 : void TraceServerSessionUnlock(void)
29 : {
30 41876 : (void)AdiagLockRelease(&g_sessionLock);
31 41876 : }
32 :
33 34 : TraStatus TraceServerSessionInit(void)
34 : {
35 34 : return AdiagLockInit(&g_sessionLock);
36 : }
37 :
38 88 : STATIC void TraceServerListExit(SessionNode *list)
39 : {
40 88 : SessionNode *node = NULL;
41 104 : while (list != NULL) {
42 16 : node = list;
43 16 : list = list->next;
44 16 : TraceQueueFree(node->queue);
45 16 : ADIAG_SAFE_FREE(node->queue);
46 16 : TraceAdxDestroyCommHandle(node->handle);
47 16 : ADIAG_SAFE_FREE(node);
48 : }
49 88 : }
50 :
51 44 : void TraceServerSessionExit(void)
52 : {
53 44 : TraceServerSessionLock();
54 44 : TraceServerListExit(g_sessionPidDevIdList);
55 44 : g_sessionPidDevIdList = NULL;
56 44 : TraceServerListExit(g_sessionPidDevIdDeletedList);
57 44 : g_sessionPidDevIdDeletedList = NULL;
58 44 : TraceServerSessionUnlock();
59 44 : AdiagLockDestroy(&g_sessionLock);
60 44 : }
61 :
62 61 : STATIC SessionNode* TraceServerPopDeletedSessionNode(void)
63 : {
64 61 : SessionNode *tmp = g_sessionPidDevIdDeletedList;
65 61 : if (tmp != NULL) {
66 31 : g_sessionPidDevIdDeletedList = NULL;
67 : }
68 61 : return tmp;
69 : }
70 :
71 69 : STATIC void TraceServerPushDeletedSessionNode(SessionNode *node)
72 : {
73 69 : if (node == NULL) {
74 32 : return;
75 : }
76 37 : if (g_sessionPidDevIdDeletedList == NULL) {
77 36 : g_sessionPidDevIdDeletedList = node;
78 36 : return;
79 : }
80 1 : if (node->next != NULL) {
81 : // if node is list, insert to global list tail
82 0 : SessionNode *tmp = g_sessionPidDevIdDeletedList;
83 0 : while (tmp->next != NULL) {
84 0 : tmp = tmp->next;
85 : }
86 0 : tmp->next = node;
87 : } else {
88 : // if node is single, insert to global list head
89 1 : node->next = g_sessionPidDevIdDeletedList;
90 1 : g_sessionPidDevIdDeletedList = node;
91 : }
92 : }
93 :
94 : /**
95 : * @brief handle deleted session list node, if node is timeout, free it.
96 : * @param [in] func: handle function
97 : * @return NA
98 : */
99 61 : void TraceServerHandleDeletedSessionNode(TraceSeverSendDataFunc func)
100 : {
101 : // pop all session nodes which will be deleted
102 61 : TraceServerSessionLock();
103 61 : SessionNode *sessionNode = TraceServerPopDeletedSessionNode();
104 61 : SessionNode *pre = NULL;
105 61 : SessionNode *head = sessionNode;
106 122 : while (sessionNode != NULL) {
107 : // traverse each node
108 61 : sessionNode->timeout -= SESSION_TIME_INTERVAL;
109 61 : g_sessionPidDevIdDeletedList = sessionNode;
110 61 : func(sessionNode, DELETED_SESSION_LIST);
111 61 : g_sessionPidDevIdDeletedList = NULL;
112 61 : if (sessionNode->timeout <= 0) {
113 3 : ADIAG_RUN_INF("session node is timeout, pid = %d.", sessionNode->pid);
114 : // session node is timeout, the timeout value is notified by client (libascend_trace.so)
115 : // delete node from list
116 3 : SessionNode *tmp = sessionNode->next;
117 3 : if (pre == NULL) {
118 3 : head = sessionNode->next;
119 : } else {
120 0 : pre->next = sessionNode->next;
121 : }
122 : // free log node
123 3 : TraceQueueFree(sessionNode->queue);
124 3 : ADIAG_SAFE_FREE(sessionNode->queue);
125 3 : TraceAdxDestroyCommHandle(sessionNode->handle);
126 3 : ADIAG_SAFE_FREE(sessionNode);
127 3 : sessionNode = tmp;
128 : } else {
129 58 : pre = sessionNode;
130 58 : sessionNode = sessionNode->next;
131 : }
132 : }
133 : // push none timeout nodes to the list again
134 61 : TraceServerPushDeletedSessionNode(head);
135 61 : TraceServerSessionUnlock();
136 61 : }
137 :
138 : /**
139 : * @brief handle session list node, if handle is invalid, destroy it.
140 : * @param [in] func: handle function
141 : * @return NA
142 : */
143 74 : void TraceServerHandleSessionNode(TraceSeverSendDataFunc func)
144 : {
145 74 : if (func == NULL) {
146 0 : return;
147 : }
148 :
149 74 : SessionNode *tmp = NULL;
150 74 : TraceServerSessionLock();
151 74 : SessionNode *node = g_sessionPidDevIdList;
152 74 : int32_t status = 0; // invalid value
153 74 : TraStatus ret = TRACE_SUCCESS;
154 : // get the first valid session node
155 76 : while (node != NULL) {
156 : // if handle is invalid, delete node
157 15 : status = 0;
158 15 : ret = TraceAdxGetAttrByCommHandle(node->handle, HDC_SESSION_ATTR_STATUS, &status);
159 15 : if ((ret != TRACE_SUCCESS) || (status == HDC_SESSION_STATUS_CLOSE)) {
160 2 : g_sessionPidDevIdList = node->next;
161 2 : TraceAdxDestroyCommHandle(node->handle);
162 2 : node->handle = NULL;
163 2 : ADIAG_RUN_INF("handle is invalid, release session finished, pid = %d", node->pid);
164 2 : tmp = node;
165 2 : node = node->next;
166 2 : TraceQueueFree(tmp->queue);
167 2 : ADIAG_SAFE_FREE(tmp->queue);
168 2 : ADIAG_SAFE_FREE(tmp);
169 : } else {
170 13 : func(node, SESSION_LIST);
171 13 : break;
172 : }
173 : }
174 :
175 75 : while ((node != NULL) && (node->next != NULL)) {
176 1 : status = 0;
177 1 : ret = TraceAdxGetAttrByCommHandle(node->next->handle, HDC_SESSION_ATTR_STATUS, &status);
178 1 : if ((ret != TRACE_SUCCESS) || (status == HDC_SESSION_STATUS_CLOSE)) {
179 0 : TraceAdxDestroyCommHandle(node->next->handle);
180 0 : node->next->handle = NULL;
181 0 : ADIAG_RUN_INF("handle is invalid, release session finished, pid = %d", node->next->pid);
182 0 : tmp = node->next;
183 0 : node->next = node->next->next;
184 0 : TraceQueueFree(tmp->queue);
185 0 : ADIAG_SAFE_FREE(tmp->queue);
186 0 : ADIAG_SAFE_FREE(tmp);
187 : } else {
188 1 : func(node->next, SESSION_LIST);
189 1 : node = node->next;
190 : }
191 : }
192 74 : TraceServerSessionUnlock();
193 74 : return;
194 : }
195 :
196 83430 : STATIC SessionNode* TraceServerGetSessionNodeByList(int32_t pid, int32_t devId, SessionNode *list)
197 : {
198 83430 : SessionNode *tmp = list;
199 104216 : while (tmp != NULL) {
200 20829 : if ((tmp->pid == pid) && (tmp->devId == devId)) {
201 43 : return tmp;
202 : }
203 20786 : tmp = tmp->next;
204 : }
205 83387 : return NULL;
206 : }
207 :
208 : /**
209 : * @brief get session node from list by pid and device id.
210 : * @param [in] pid: pid
211 : * @param [in] devId: device id
212 : * @return SessionNode
213 : */
214 41716 : SessionNode* TraceServerGetSessionNode(int32_t pid, int32_t devId)
215 : {
216 41716 : if ((devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
217 1 : ADIAG_ERR("invalid input for session node searching: pid = %d, devId = %d", pid, devId);
218 1 : return NULL;
219 : }
220 :
221 41715 : SessionNode *tmp = TraceServerGetSessionNodeByList(pid, devId, g_sessionPidDevIdDeletedList);
222 41715 : if (tmp == NULL) {
223 41715 : tmp = TraceServerGetSessionNodeByList(pid, devId, g_sessionPidDevIdList);
224 : }
225 41715 : return tmp;
226 : }
227 :
228 : /**
229 : * @brief insert session node.
230 : * @param [in] handle: session handle
231 : * @param [in] pid: pid
232 : * @param [in] devId: device id
233 : * @param [in] timeout: timeout
234 : * @return TraStatus
235 : */
236 25 : TraStatus TraceServerInsertSessionNode(const void *handle, int32_t pid, int32_t devId, int32_t timeout)
237 : {
238 25 : if ((TraceAdxIsCommHandleValid(handle) != TRACE_SUCCESS) || (devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
239 1 : ADIAG_ERR("invalid input for session node insert: pid = %d, devId = %d", pid, devId);
240 1 : return TRACE_INVALID_PARAM;
241 : }
242 24 : TraceServerSessionLock();
243 24 : if (TraceServerGetSessionNode(pid, devId) != NULL) {
244 1 : ADIAG_WAR("can not insert session, session has existed.");
245 1 : TraceServerSessionUnlock();
246 1 : return TRACE_FAILURE;
247 : }
248 23 : SessionNode *sessionNode = (SessionNode *)AdiagMalloc(sizeof(SessionNode));
249 23 : if (sessionNode == NULL) {
250 1 : ADIAG_ERR("malloc session node failed, strerr=%s.", strerror(AdiagGetErrorCode()));
251 1 : TraceServerSessionUnlock();
252 1 : return TRACE_FAILURE;
253 : }
254 22 : sessionNode->queue = (TraceQueue *)AdiagMalloc(sizeof(TraceQueue));
255 22 : if (sessionNode->queue == NULL) {
256 1 : ADIAG_ERR("malloc queue failed, strerr=%s.", strerror(AdiagGetErrorCode()));
257 1 : TraceServerSessionUnlock();
258 1 : ADIAG_SAFE_FREE(sessionNode);
259 1 : return TRACE_FAILURE;
260 : }
261 21 : sessionNode->pid = pid;
262 21 : sessionNode->devId = devId;
263 21 : sessionNode->handle = handle;
264 21 : sessionNode->timeout = timeout;
265 21 : TraceQueueInit(sessionNode->queue);
266 21 : sessionNode->next = g_sessionPidDevIdList;
267 21 : g_sessionPidDevIdList = sessionNode;
268 21 : TraceServerSessionUnlock();
269 21 : return TRACE_SUCCESS;
270 : }
271 :
272 : /**
273 : * @brief push session node from session list to deleted session list.
274 : * @param [in] handle: handle
275 : * @param [in] pid: pid
276 : * @param [in] devId: device id
277 : * @return TraStatus
278 : */
279 10 : TraStatus TraceServerDeleteSessionNode(const void *handle, int32_t pid, int32_t devId)
280 : {
281 10 : if ((TraceAdxIsCommHandleValid(handle) != TRACE_SUCCESS) || (devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
282 1 : ADIAG_ERR("invalid input for session node delete: pid = %d, devId = %d", pid, devId);
283 1 : return TRACE_INVALID_PARAM;
284 : }
285 9 : TraceServerSessionLock();
286 9 : if (g_sessionPidDevIdList == NULL) {
287 1 : TraceServerSessionUnlock();
288 1 : return TRACE_INVALID_DATA;
289 : }
290 8 : SessionNode *deletedNode = NULL;
291 8 : SessionNode *tmp = g_sessionPidDevIdList;
292 8 : if ((tmp->pid == pid) && (tmp->devId == devId)) {
293 5 : g_sessionPidDevIdList = tmp->next;
294 5 : tmp->next = NULL;
295 5 : deletedNode = tmp;
296 : } else {
297 3 : while ((tmp->next != NULL) && ((tmp->next->pid != pid) ||
298 3 : (tmp->next->devId != devId))) {
299 0 : tmp = tmp->next;
300 : }
301 3 : if ((tmp->next != NULL) && (tmp->next->pid == pid) &&
302 3 : (tmp->next->devId == devId)) {
303 3 : deletedNode = tmp->next;
304 3 : tmp->next = deletedNode->next;
305 3 : deletedNode->next = NULL;
306 : }
307 : }
308 8 : TraceServerPushDeletedSessionNode(deletedNode);
309 8 : TraceServerSessionUnlock();
310 8 : return TRACE_SUCCESS;
311 : }
312 :
313 40 : bool TraceIsSessionNodeListNull(void)
314 : {
315 40 : return (g_sessionPidDevIdList == NULL);
316 : }
317 :
318 40 : bool TraceIsDeletedSessionNodeListNull(void)
319 : {
320 40 : return (g_sessionPidDevIdDeletedList == NULL);
321 : }
|