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 6428 : AdiagStatus AdiagListInit(struct AdiagList* traList)
21 : {
22 6428 : AdiagStatus ret = ADIAG_FAILURE;
23 6428 : if (traList != NULL) {
24 6428 : INIT_LIST_HEAD(&traList->list);
25 6428 : traList->cnt = 0;
26 6428 : ret = AdiagLockInit(&traList->lock);
27 6428 : traList->valid = ((ret == ADIAG_SUCCESS) ? true : false);
28 : }
29 :
30 6428 : 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 4890 : AdiagStatus AdiagListDestroy(struct AdiagList* traList)
39 : {
40 4890 : AdiagStatus ret = ADIAG_SUCCESS;
41 :
42 4890 : if ((traList != NULL) && (traList->valid == true)) {
43 4400 : void* data = AdiagListTakeOut(traList);
44 5637 : while (data != NULL) {
45 1237 : ADIAG_SAFE_FREE(data);
46 1237 : data = AdiagListTakeOut(traList);
47 : }
48 :
49 4400 : ret = AdiagLockDestroy(&traList->lock);
50 : }
51 :
52 4890 : 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 4813 : AdiagStatus AdiagListInsert(struct AdiagList* traList, void* data)
62 : {
63 4813 : ADIAG_CHK_NULL_PTR(traList, return ADIAG_FAILURE);
64 4813 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
65 :
66 4813 : struct AdiagListNode* node = AdiagMalloc(sizeof(struct AdiagListNode));
67 4813 : if (node == NULL) {
68 64 : ADIAG_ERR("malloc list node failed.");
69 64 : return ADIAG_FAILURE;
70 : }
71 :
72 4749 : INIT_LIST_HEAD(&node->list);
73 4749 : node->data = data;
74 :
75 4749 : (void)AdiagLockGet(&traList->lock);
76 4749 : if (traList->cnt < (UINT32_MAX - 1U)) {
77 4749 : ListAddBeforeEntry(&node->list, &traList->list);
78 4749 : traList->cnt++;
79 4749 : (void)AdiagLockRelease(&traList->lock);
80 4749 : 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 9404 : void* AdiagListTakeOut(struct AdiagList* traList)
95 : {
96 9404 : ADIAG_CHK_NULL_PTR(traList, return NULL);
97 :
98 9404 : void* data = NULL;
99 9404 : struct AdiagListNode* node = NULL;
100 9404 : (void)AdiagLockGet(&traList->lock);
101 9404 : if (!ListEmpty(&traList->list)) {
102 3262 : node = LIST_FIRST_ENTRY(&traList->list, struct AdiagListNode, list);
103 3262 : if (node != NULL) {
104 3262 : ListDelEntry(&node->list);
105 3262 : traList->cnt--;
106 3262 : data = node->data;
107 : }
108 : }
109 9404 : (void)AdiagLockRelease(&traList->lock);
110 :
111 9404 : ADIAG_SAFE_FREE(node);
112 9404 : 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 749 : void AdiagListForEachTraverse(struct AdiagList* traList, const AdiagListTraverseFunc func, void* arg)
122 : {
123 749 : if ((traList == NULL) || (func == NULL)) {
124 44 : return;
125 : }
126 :
127 705 : struct AdiagListNode* pos = NULL;
128 705 : (void)AdiagLockGet(&traList->lock);
129 746 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) { (void)func(pos->data, arg); }
130 705 : (void)AdiagLockRelease(&traList->lock);
131 : }
132 :
133 : /**
134 : * @brief apply specified function on every node in list without lock.
135 : * @param [in] traList: list ptr
136 : * @param [in] func: function to be applied
137 : * @param [in] arg: extra argument for function
138 : * @return NA
139 : */
140 0 : void AdiagListForEachNolock(struct AdiagList* traList, const AdiagListCmpFunc func, const void* arg)
141 : {
142 0 : if ((traList == NULL) || (func == NULL)) {
143 0 : return;
144 : }
145 :
146 0 : const struct AdiagListNode* pos = NULL;
147 :
148 0 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) { (void)func(pos->data, arg); }
149 : }
150 :
151 2888756 : STATIC INLINE AdiagStatus AdiagListCmpData(const void* nodeData, const void* data)
152 : {
153 2888756 : if (nodeData == data) {
154 1445732 : return ADIAG_SUCCESS;
155 : }
156 1443024 : return ADIAG_FAILURE;
157 : }
158 :
159 1445754 : void* AdiagListGetNode(struct AdiagList* traList, const void* data)
160 : {
161 1445754 : return AdiagListForEach(traList, AdiagListCmpData, data);
162 : }
163 :
164 : /**
165 : * @brief apply specified function on every node in list.
166 : * return first data that let function return true
167 : * @param [in] traList: list ptr
168 : * @param [in] func: function to be applied
169 : * @param [in] arg: extra argument for function
170 : * @return data which let function return true
171 : */
172 1454760 : void* AdiagListForEach(struct AdiagList* traList, const AdiagListCmpFunc func, const void* arg)
173 : {
174 1454760 : const struct AdiagListNode* pos = NULL;
175 1454760 : void* data = NULL;
176 1454760 : ADIAG_CHK_NULL_PTR(traList, return NULL);
177 1454760 : ADIAG_CHK_NULL_PTR(func, return NULL);
178 :
179 1454760 : (void)AdiagLockGet(&traList->lock);
180 2922574 : LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list)
181 : {
182 2920096 : if (func(pos->data, arg) == ADIAG_SUCCESS) {
183 1452282 : data = pos->data;
184 1452282 : break;
185 : }
186 : }
187 1454760 : (void)AdiagLockRelease(&traList->lock);
188 1454760 : return (void*)data;
189 : }
190 :
191 : /**
192 : * @brief remove the node that has specified data in list, break if found one
193 : * @param [in] traceList: list ptr
194 : * @param [in] data: data to be removed
195 : * @return 0 on success, otherwise -1.
196 : */
197 1424 : AdiagStatus AdiagListRemove(struct AdiagList* traceList, void* data)
198 : {
199 1424 : AdiagStatus ret = ADIAG_FAILURE;
200 1424 : struct AdiagListNode* node = NULL;
201 1424 : struct ListHead* pos = NULL;
202 :
203 1424 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
204 1424 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
205 :
206 1424 : (void)AdiagLockGet(&traceList->lock);
207 1424 : if (!ListEmpty(&traceList->list)) {
208 1891 : LIST_FOR_EACH(pos, &traceList->list)
209 : {
210 1891 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
211 1891 : if ((node != NULL) && (node->data == data)) {
212 1424 : ListDelEntry(pos);
213 1424 : traceList->cnt--;
214 1424 : AdiagFree(node);
215 1424 : node = NULL;
216 1424 : ret = ADIAG_SUCCESS;
217 1424 : break;
218 : }
219 : }
220 : }
221 1424 : (void)AdiagLockRelease(&traceList->lock);
222 :
223 1424 : return ret;
224 : }
225 :
226 : /**
227 : * @brief remove all the node that has specified data in list
228 : * @param [in] traceList: list ptr
229 : * @param [in] data: data to be removed
230 : * @return 0 on success, otherwise -1.
231 : */
232 1262 : AdiagStatus AdiagListRemoveAll(struct AdiagList* traceList, void* data, const AdiagListElemFunc func)
233 : {
234 1262 : AdiagStatus ret = ADIAG_FAILURE;
235 1262 : struct AdiagListNode* node = NULL;
236 1262 : struct ListHead* pos = NULL;
237 1262 : struct ListHead* tmp = NULL;
238 :
239 1262 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
240 1262 : ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
241 :
242 1262 : (void)AdiagLockGet(&traceList->lock);
243 1262 : if (!ListEmpty(&traceList->list)) {
244 66 : LIST_FOR_EACH(pos, &traceList->list)
245 : {
246 44 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
247 44 : if ((node != NULL) && (node->data == data)) {
248 44 : tmp = pos->next;
249 44 : ListDelEntry(pos);
250 44 : traceList->cnt--;
251 44 : if (func != NULL) {
252 0 : func(node->data);
253 : }
254 44 : AdiagFree(node);
255 44 : node = NULL;
256 44 : ret = ADIAG_SUCCESS;
257 44 : pos = tmp->prev;
258 : }
259 : }
260 : }
261 1262 : (void)AdiagLockRelease(&traceList->lock);
262 :
263 1262 : return ret;
264 : }
265 :
266 : /**
267 : * @brief move from oldList to new List
268 : * @param [in] oldList: old list to be move from
269 : * @param [in] newList: new list to be move to
270 : * @return NA
271 : */
272 1 : void AdiagListMove(struct AdiagList* oldList, struct AdiagList* newList)
273 : {
274 1 : void* data = NULL;
275 : do {
276 2 : data = AdiagListTakeOut(oldList);
277 2 : if (data == NULL) {
278 1 : break;
279 : }
280 1 : (void)AdiagListInsert(newList, data);
281 : } while (true);
282 1 : }
283 :
284 : /**
285 : * @brief clear all the node that match cmpFunc and do otherFunc if not match
286 : * @param [in] traceList: list ptr
287 : * @param [in] cmpFunc: compare function to check if remove or not
288 : * @param [in] arg: argument of compare function
289 : * @param [in] otherFunc: function do if no need to remove
290 :
291 : * @return 0 on success, otherwise -1.
292 : */
293 1 : AdiagStatus AdiagListClearAndProcessNoLock(
294 : struct AdiagList* traceList, const AdiagListCmpFunc cmpFunc, const void* arg, const AdiagListElemFunc otherFunc)
295 : {
296 1 : AdiagStatus ret = ADIAG_FAILURE;
297 1 : struct AdiagListNode* node = NULL;
298 1 : struct ListHead* pos = NULL;
299 1 : struct ListHead* tmp = NULL;
300 1 : void* data = NULL;
301 :
302 1 : ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
303 :
304 1 : if (!ListEmpty(&traceList->list)) {
305 2 : LIST_FOR_EACH(pos, &traceList->list)
306 : {
307 1 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
308 1 : if (node == NULL) {
309 0 : continue;
310 : }
311 1 : if (cmpFunc(node->data, arg) == ADIAG_SUCCESS) {
312 1 : tmp = pos->next;
313 1 : ListDelEntry(pos);
314 1 : traceList->cnt--;
315 1 : data = (void*)node->data;
316 1 : pos = tmp->prev;
317 1 : ADIAG_SAFE_FREE(node);
318 1 : ADIAG_SAFE_FREE(data);
319 1 : ret = ADIAG_SUCCESS;
320 0 : } else if (otherFunc != NULL) {
321 0 : otherFunc(node->data);
322 : } else {
323 : ;
324 : }
325 : }
326 : }
327 :
328 1 : return ret;
329 : }
|