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