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 "adiag_list.h"
12 : #include "adiag_print.h"
13 : #include "adiag_utils.h"
14 :
15 : /**
16 : * @brief init circular double linked lists
17 : * @param [in] traList: list holder ptr
18 : * @return AdiagStatus
19 : */
20 5617 : AdiagStatus AdiagListInit(struct AdiagList *traList)
21 : {
22 5617 : AdiagStatus ret = ADIAG_FAILURE;
23 5617 : if (traList != NULL) {
24 5617 : INIT_LIST_HEAD(&traList->list);
25 5617 : traList->cnt = 0;
26 5617 : ret = AdiagLockInit(&traList->lock);
27 5617 : traList->valid = ((ret == ADIAG_SUCCESS) ? true : false);
28 : }
29 :
30 5617 : return ret;
31 : }
32 :
33 : /**
34 : * @brief destroy circular doubly linked lists
35 : * @param [in] traList: list ptr to be destroyed
36 : * @return AdiagStatus
37 : */
38 4350 : AdiagStatus AdiagListDestroy(struct AdiagList *traList)
39 : {
40 4350 : AdiagStatus ret = ADIAG_SUCCESS;
41 :
42 4350 : if ((traList != NULL) && (traList->valid == true)) {
43 3898 : void *data = AdiagListTakeOut(traList);
44 5034 : while (data != NULL) {
45 1136 : ADIAG_SAFE_FREE(data);
46 1136 : data = AdiagListTakeOut(traList);
47 : }
48 :
49 3898 : ret = AdiagLockDestroy(&traList->lock);
50 : }
51 :
52 4350 : return ret;
53 : }
54 :
55 : /**
56 : * @brief insert new node into list
57 : * @param [in] traList: list ptr
58 : * @param [in] data: data to be inserted into list
59 : * @return AdiagStatus
60 : */
61 4292 : AdiagStatus AdiagListInsert(struct AdiagList *traList, void *data)
62 : {
63 4292 : ADIAG_CHK_NULL_PTR(traList, return ADIAG_FAILURE);
64 4292 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
65 :
66 4292 : struct AdiagListNode *node = AdiagMalloc(sizeof(struct AdiagListNode));
67 4292 : if (node == NULL) {
68 56 : ADIAG_ERR("malloc list node failed.");
69 56 : return ADIAG_FAILURE;
70 : }
71 :
72 4236 : INIT_LIST_HEAD(&node->list);
73 4236 : node->data = data;
74 :
75 4236 : (void)AdiagLockGet(&traList->lock);
76 4236 : if (traList->cnt < (UINT32_MAX - 1U)) {
77 4236 : ListAddBeforeEntry(&node->list, &traList->list);
78 4236 : traList->cnt++;
79 4236 : (void)AdiagLockRelease(&traList->lock);
80 4236 : return ADIAG_SUCCESS;
81 : } else {
82 0 : AdiagFree(node);
83 0 : node = NULL;
84 0 : (void)AdiagLockRelease(&traList->lock);
85 0 : return ADIAG_FAILURE;
86 : }
87 : }
88 :
89 : /**
90 : * @brief take out oldest node in list and return node data
91 : * @param [in] traList: list ptr
92 : * @return data ptr which has been taken out
93 : */
94 8278 : void *AdiagListTakeOut(struct AdiagList *traList)
95 : {
96 8278 : ADIAG_CHK_NULL_PTR(traList, return NULL);
97 :
98 8278 : void *data = NULL;
99 8278 : struct AdiagListNode *node = NULL;
100 8278 : (void)AdiagLockGet(&traList->lock);
101 8278 : if (!ListEmpty(&traList->list)) {
102 2906 : node = LIST_FIRST_ENTRY(&traList->list, struct AdiagListNode, list);
103 2906 : if (node != NULL) {
104 2906 : ListDelEntry(&node->list);
105 2906 : traList->cnt--;
106 2906 : data = node->data;
107 : }
108 : }
109 8278 : (void)AdiagLockRelease(&traList->lock);
110 :
111 8278 : ADIAG_SAFE_FREE(node);
112 8278 : return (void *)data;
113 : }
114 : /**
115 : * @brief apply specified function on every node.
116 : * @param [in] traList: list ptr
117 : * @param [in] func: function to be applied
118 : * @param [in] arg: extra argument for function
119 : * @return NA
120 : */
121 595 : void AdiagListForEachTraverse(struct AdiagList *traList, const AdiagListTraverseFunc func, void *arg)
122 : {
123 595 : if ((traList == NULL) || (func == NULL)) {
124 40 : return;
125 : }
126 :
127 555 : struct AdiagListNode *pos = NULL;
128 555 : (void)AdiagLockGet(&traList->lock);
129 570 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
130 15 : (void)func(pos->data, arg);
131 : }
132 555 : (void)AdiagLockRelease(&traList->lock);
133 : }
134 :
135 : /**
136 : * @brief apply specified function on every node in list without lock.
137 : * @param [in] traList: list ptr
138 : * @param [in] func: function to be applied
139 : * @param [in] arg: extra argument for function
140 : * @return NA
141 : */
142 0 : void AdiagListForEachNolock(struct AdiagList *traList, const AdiagListCmpFunc func, const void *arg)
143 : {
144 0 : if ((traList == NULL) || (func == NULL)) {
145 0 : return;
146 : }
147 :
148 0 : const struct AdiagListNode *pos = NULL;
149 :
150 0 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
151 0 : (void)func(pos->data, arg);
152 : }
153 : }
154 :
155 2626074 : STATIC INLINE AdiagStatus AdiagListCmpData(const void *nodeData, const void *data)
156 : {
157 2626074 : if (nodeData == data) {
158 1314234 : return ADIAG_SUCCESS;
159 : }
160 1311840 : return ADIAG_FAILURE;
161 : }
162 :
163 1314254 : void *AdiagListGetNode(struct AdiagList *traList, const void *data)
164 : {
165 1314254 : return AdiagListForEach(traList, AdiagListCmpData, data);
166 : }
167 :
168 : /**
169 : * @brief apply specified function on every node in list.
170 : * return first data that let function return true
171 : * @param [in] traList: list ptr
172 : * @param [in] func: function to be applied
173 : * @param [in] arg: extra argument for function
174 : * @return data which let function return true
175 : */
176 1321898 : void *AdiagListForEach(struct AdiagList *traList, const AdiagListCmpFunc func, const void *arg)
177 : {
178 1321898 : const struct AdiagListNode *pos = NULL;
179 1321898 : void *data = NULL;
180 1321898 : ADIAG_CHK_NULL_PTR(traList, return NULL);
181 1321898 : ADIAG_CHK_NULL_PTR(func, return NULL);
182 :
183 1321898 : (void)AdiagLockGet(&traList->lock);
184 2658686 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
185 2656510 : if (func(pos->data, arg) == ADIAG_SUCCESS) {
186 1319722 : data = pos->data;
187 1319722 : break;
188 : }
189 : }
190 1321898 : (void)AdiagLockRelease(&traList->lock);
191 1321898 : return (void *)data;
192 : }
193 :
194 : /**
195 : * @brief remove the node that has specified data in list, break if found one
196 : * @param [in] traceList: list ptr
197 : * @param [in] data: data to be removed
198 : * @return 0 on success, otherwise -1.
199 : */
200 1272 : AdiagStatus AdiagListRemove(struct AdiagList *traceList, void *data)
201 : {
202 1272 : AdiagStatus ret = ADIAG_FAILURE;
203 1272 : struct AdiagListNode *node = NULL;
204 1272 : struct ListHead *pos = NULL;
205 :
206 1272 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
207 1272 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
208 :
209 1272 : (void)AdiagLockGet(&traceList->lock);
210 1272 : if (!ListEmpty(&traceList->list)) {
211 1697 : LIST_FOR_EACH(pos, &traceList->list) {
212 1697 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
213 1697 : if ((node != NULL) && (node->data == data)) {
214 1272 : ListDelEntry(pos);
215 1272 : traceList->cnt--;
216 1272 : AdiagFree(node);
217 1272 : node = NULL;
218 1272 : ret = ADIAG_SUCCESS;
219 1272 : break;
220 : }
221 : }
222 : }
223 1272 : (void)AdiagLockRelease(&traceList->lock);
224 :
225 1272 : return ret;
226 : }
227 :
228 : /**
229 : * @brief remove all the node that has specified data in list
230 : * @param [in] traceList: list ptr
231 : * @param [in] data: data to be removed
232 : * @return 0 on success, otherwise -1.
233 : */
234 1124 : AdiagStatus AdiagListRemoveAll(struct AdiagList *traceList, void *data, const AdiagListElemFunc func)
235 : {
236 1124 : AdiagStatus ret = ADIAG_FAILURE;
237 1124 : struct AdiagListNode *node = NULL;
238 1124 : struct ListHead *pos = NULL;
239 1124 : struct ListHead *tmp = NULL;
240 :
241 1124 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
242 1124 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
243 :
244 1124 : (void)AdiagLockGet(&traceList->lock);
245 1124 : if (!ListEmpty(&traceList->list)) {
246 60 : LIST_FOR_EACH(pos, &traceList->list) {
247 40 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
248 40 : if ((node != NULL) && (node->data == data)) {
249 40 : tmp = pos->next;
250 40 : ListDelEntry(pos);
251 40 : traceList->cnt--;
252 40 : if (func != NULL) {
253 0 : func(node->data);
254 : }
255 40 : AdiagFree(node);
256 40 : node = NULL;
257 40 : ret = ADIAG_SUCCESS;
258 40 : pos = tmp->prev;
259 : }
260 : }
261 : }
262 1124 : (void)AdiagLockRelease(&traceList->lock);
263 :
264 1124 : return ret;
265 : }
266 :
267 : /**
268 : * @brief move from oldList to new List
269 : * @param [in] oldList: old list to be move from
270 : * @param [in] newList: new list to be move to
271 : * @return NA
272 : */
273 0 : void AdiagListMove(struct AdiagList *oldList, struct AdiagList *newList)
274 : {
275 0 : void *data = NULL;
276 : do {
277 0 : data = AdiagListTakeOut(oldList);
278 0 : if (data == NULL) {
279 0 : break;
280 : }
281 0 : (void)AdiagListInsert(newList, data);
282 : } while (true);
283 0 : }
284 :
285 : /**
286 : * @brief clear all the node that match cmpFunc and do otherFunc if not match
287 : * @param [in] traceList: list ptr
288 : * @param [in] cmpFunc: compare function to check if remove or not
289 : * @param [in] arg: argument of compare function
290 : * @param [in] otherFunc: function do if no need to remove
291 :
292 : * @return 0 on success, otherwise -1.
293 : */
294 0 : AdiagStatus AdiagListClearAndProcessNoLock(struct AdiagList *traceList, const AdiagListCmpFunc cmpFunc, const void *arg,
295 : const AdiagListElemFunc otherFunc)
296 : {
297 0 : AdiagStatus ret = ADIAG_FAILURE;
298 0 : struct AdiagListNode *node = NULL;
299 0 : struct ListHead *pos = NULL;
300 0 : struct ListHead *tmp = NULL;
301 0 : void *data = NULL;
302 :
303 0 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
304 :
305 0 : if (!ListEmpty(&traceList->list)) {
306 0 : LIST_FOR_EACH(pos, &traceList->list) {
307 0 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
308 0 : if (node == NULL) {
309 0 : continue;
310 : }
311 0 : if (cmpFunc(node->data, arg) == ADIAG_SUCCESS) {
312 0 : tmp = pos->next;
313 0 : ListDelEntry(pos);
314 0 : traceList->cnt--;
315 0 : data = (void *)node->data;
316 0 : pos = tmp->prev;
317 0 : ADIAG_SAFE_FREE(node);
318 0 : ADIAG_SAFE_FREE(data);
319 0 : ret = ADIAG_SUCCESS;
320 0 : } else if (otherFunc != NULL) {
321 0 : otherFunc(node->data);
322 : } else {
323 : ;
324 : }
325 : }
326 : }
327 :
328 0 : return ret;
329 : }
|