1 | /* |
2 | * Copyright 2018-2019 NXP |
3 | * All rights reserved. |
4 | * |
5 | * |
6 | * SPDX-License-Identifier: BSD-3-Clause |
7 | */ |
8 | |
9 | /*! ********************************************************************************* |
10 | ************************************************************************************* |
11 | * Include |
12 | ************************************************************************************* |
13 | ********************************************************************************** */ |
14 | #include "fsl_component_generic_list.h" |
15 | |
16 | #if defined(OSA_USED) |
17 | #include "fsl_os_abstraction.h" |
18 | #if (defined(USE_RTOS) && (USE_RTOS > 0U)) |
19 | #define LIST_ENTER_CRITICAL() \ |
20 | OSA_SR_ALLOC(); \ |
21 | OSA_ENTER_CRITICAL() |
22 | #define LIST_EXIT_CRITICAL() OSA_EXIT_CRITICAL() |
23 | #else |
24 | #define LIST_ENTER_CRITICAL() |
25 | #define LIST_EXIT_CRITICAL() |
26 | #endif |
27 | #else |
28 | #define LIST_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ(); |
29 | #define LIST_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask); |
30 | #endif |
31 | |
32 | static list_status_t LIST_Error_Check(list_handle_t list, list_element_handle_t newElement) |
33 | { |
34 | list_status_t listStatus = kLIST_Ok; |
35 | #if (defined(GENERIC_LIST_DUPLICATED_CHECKING) && (GENERIC_LIST_DUPLICATED_CHECKING > 0U)) |
36 | list_element_handle_t element = list->head; |
37 | #endif |
38 | if ((list->max != 0U) && (list->max == list->size)) |
39 | { |
40 | listStatus = kLIST_Full; /*List is full*/ |
41 | } |
42 | #if (defined(GENERIC_LIST_DUPLICATED_CHECKING) && (GENERIC_LIST_DUPLICATED_CHECKING > 0U)) |
43 | else |
44 | { |
45 | while (element != NULL) /*Scan list*/ |
46 | { |
47 | /* Determine if element is duplicated */ |
48 | if (element == newElement) |
49 | { |
50 | listStatus = kLIST_DuplicateError; |
51 | break; |
52 | } |
53 | element = element->next; |
54 | } |
55 | } |
56 | #endif |
57 | return listStatus; |
58 | } |
59 | |
60 | /*! ********************************************************************************* |
61 | ************************************************************************************* |
62 | * Public functions |
63 | ************************************************************************************* |
64 | ********************************************************************************** */ |
65 | /*! ********************************************************************************* |
66 | * \brief Initialises the list descriptor. |
67 | * |
68 | * \param[in] list - LIST_ handle to init. |
69 | * max - Maximum number of elements in list. 0 for unlimited. |
70 | * |
71 | * \return void. |
72 | * |
73 | * \pre |
74 | * |
75 | * \post |
76 | * |
77 | * \remarks |
78 | * |
79 | ********************************************************************************** */ |
80 | void LIST_Init(list_handle_t list, uint32_t max) |
81 | { |
82 | list->head = NULL; |
83 | list->tail = NULL; |
84 | list->max = (uint16_t)max; |
85 | list->size = 0; |
86 | } |
87 | |
88 | /*! ********************************************************************************* |
89 | * \brief Gets the list that contains the given element. |
90 | * |
91 | * \param[in] element - Handle of the element. |
92 | * |
93 | * \return NULL if element is orphan. |
94 | * Handle of the list the element is inserted into. |
95 | * |
96 | * \pre |
97 | * |
98 | * \post |
99 | * |
100 | * \remarks |
101 | * |
102 | ********************************************************************************** */ |
103 | list_handle_t LIST_GetList(list_element_handle_t element) |
104 | { |
105 | return element->list; |
106 | } |
107 | |
108 | /*! ********************************************************************************* |
109 | * \brief Links element to the tail of the list. |
110 | * |
111 | * \param[in] list - ID of list to insert into. |
112 | * element - element to add |
113 | * |
114 | * \return kLIST_Full if list is full. |
115 | * kLIST_Ok if insertion was successful. |
116 | * |
117 | * \pre |
118 | * |
119 | * \post |
120 | * |
121 | * \remarks |
122 | * |
123 | ********************************************************************************** */ |
124 | list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element) |
125 | { |
126 | LIST_ENTER_CRITICAL(); |
127 | list_status_t listStatus = kLIST_Ok; |
128 | |
129 | listStatus = LIST_Error_Check(list, element); |
130 | if (listStatus == kLIST_Ok) /* Avoiding list status error */ |
131 | { |
132 | if (list->size == 0U) |
133 | { |
134 | list->head = element; |
135 | } |
136 | else |
137 | { |
138 | list->tail->next = element; |
139 | } |
140 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
141 | #else |
142 | element->prev = list->tail; |
143 | #endif |
144 | element->list = list; |
145 | element->next = NULL; |
146 | list->tail = element; |
147 | list->size++; |
148 | } |
149 | |
150 | LIST_EXIT_CRITICAL(); |
151 | return listStatus; |
152 | } |
153 | |
154 | /*! ********************************************************************************* |
155 | * \brief Links element to the head of the list. |
156 | * |
157 | * \param[in] list - ID of list to insert into. |
158 | * element - element to add |
159 | * |
160 | * \return kLIST_Full if list is full. |
161 | * kLIST_Ok if insertion was successful. |
162 | * |
163 | * \pre |
164 | * |
165 | * \post |
166 | * |
167 | * \remarks |
168 | * |
169 | ********************************************************************************** */ |
170 | list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element) |
171 | { |
172 | LIST_ENTER_CRITICAL(); |
173 | list_status_t listStatus = kLIST_Ok; |
174 | |
175 | listStatus = LIST_Error_Check(list, element); |
176 | if (listStatus == kLIST_Ok) /* Avoiding list status error */ |
177 | { |
178 | /* Links element to the head of the list */ |
179 | if (list->size == 0U) |
180 | { |
181 | list->tail = element; |
182 | } |
183 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
184 | #else |
185 | else |
186 | { |
187 | list->head->prev = element; |
188 | } |
189 | element->prev = NULL; |
190 | #endif |
191 | element->list = list; |
192 | element->next = list->head; |
193 | list->head = element; |
194 | list->size++; |
195 | } |
196 | |
197 | LIST_EXIT_CRITICAL(); |
198 | return listStatus; |
199 | } |
200 | |
201 | /*! ********************************************************************************* |
202 | * \brief Unlinks element from the head of the list. |
203 | * |
204 | * \param[in] list - ID of list to remove from. |
205 | * |
206 | * \return NULL if list is empty. |
207 | * ID of removed element(pointer) if removal was successful. |
208 | * |
209 | * \pre |
210 | * |
211 | * \post |
212 | * |
213 | * \remarks |
214 | * |
215 | ********************************************************************************** */ |
216 | list_element_handle_t LIST_RemoveHead(list_handle_t list) |
217 | { |
218 | list_element_handle_t element; |
219 | |
220 | LIST_ENTER_CRITICAL(); |
221 | |
222 | if ((NULL == list) || (list->size == 0U)) |
223 | { |
224 | element = NULL; /*LIST_ is empty*/ |
225 | } |
226 | else |
227 | { |
228 | element = list->head; |
229 | list->size--; |
230 | if (list->size == 0U) |
231 | { |
232 | list->tail = NULL; |
233 | } |
234 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
235 | #else |
236 | else |
237 | { |
238 | element->next->prev = NULL; |
239 | } |
240 | #endif |
241 | element->list = NULL; |
242 | list->head = element->next; /*Is NULL if element is head*/ |
243 | } |
244 | |
245 | LIST_EXIT_CRITICAL(); |
246 | return element; |
247 | } |
248 | |
249 | /*! ********************************************************************************* |
250 | * \brief Gets head element ID. |
251 | * |
252 | * \param[in] list - ID of list. |
253 | * |
254 | * \return NULL if list is empty. |
255 | * ID of head element if list is not empty. |
256 | * |
257 | * \pre |
258 | * |
259 | * \post |
260 | * |
261 | * \remarks |
262 | * |
263 | ********************************************************************************** */ |
264 | list_element_handle_t LIST_GetHead(list_handle_t list) |
265 | { |
266 | return list->head; |
267 | } |
268 | |
269 | /*! ********************************************************************************* |
270 | * \brief Gets next element ID. |
271 | * |
272 | * \param[in] element - ID of the element. |
273 | * |
274 | * \return NULL if element is tail. |
275 | * ID of next element if exists. |
276 | * |
277 | * \pre |
278 | * |
279 | * \post |
280 | * |
281 | * \remarks |
282 | * |
283 | ********************************************************************************** */ |
284 | list_element_handle_t LIST_GetNext(list_element_handle_t element) |
285 | { |
286 | return element->next; |
287 | } |
288 | |
289 | /*! ********************************************************************************* |
290 | * \brief Gets previous element ID. |
291 | * |
292 | * \param[in] element - ID of the element. |
293 | * |
294 | * \return NULL if element is head. |
295 | * ID of previous element if exists. |
296 | * |
297 | * \pre |
298 | * |
299 | * \post |
300 | * |
301 | * \remarks |
302 | * |
303 | ********************************************************************************** */ |
304 | list_element_handle_t LIST_GetPrev(list_element_handle_t element) |
305 | { |
306 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
307 | return NULL; |
308 | #else |
309 | return element->prev; |
310 | #endif |
311 | } |
312 | |
313 | /*! ********************************************************************************* |
314 | * \brief Unlinks an element from its list. |
315 | * |
316 | * \param[in] element - ID of the element to remove. |
317 | * |
318 | * \return kLIST_OrphanElement if element is not part of any list. |
319 | * kLIST_Ok if removal was successful. |
320 | * |
321 | * \pre |
322 | * |
323 | * \post |
324 | * |
325 | * \remarks |
326 | * |
327 | ********************************************************************************** */ |
328 | list_status_t LIST_RemoveElement(list_element_handle_t element) |
329 | { |
330 | list_status_t listStatus = kLIST_Ok; |
331 | LIST_ENTER_CRITICAL(); |
332 | |
333 | if (element->list == NULL) |
334 | { |
335 | listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ |
336 | } |
337 | else |
338 | { |
339 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
340 | list_element_handle_t element_list = element->list->head; |
341 | while (NULL != element_list) |
342 | { |
343 | if (element->list->head == element) |
344 | { |
345 | element->list->head = element_list->next; |
346 | break; |
347 | } |
348 | if (element_list->next == element) |
349 | { |
350 | element_list->next = element->next; |
351 | break; |
352 | } |
353 | element_list = element_list->next; |
354 | } |
355 | #else |
356 | if (element->prev == NULL) /*Element is head or solo*/ |
357 | { |
358 | element->list->head = element->next; /*is null if solo*/ |
359 | } |
360 | if (element->next == NULL) /*Element is tail or solo*/ |
361 | { |
362 | element->list->tail = element->prev; /*is null if solo*/ |
363 | } |
364 | if (element->prev != NULL) /*Element is not head*/ |
365 | { |
366 | element->prev->next = element->next; |
367 | } |
368 | if (element->next != NULL) /*Element is not tail*/ |
369 | { |
370 | element->next->prev = element->prev; |
371 | } |
372 | #endif |
373 | element->list->size--; |
374 | element->list = NULL; |
375 | } |
376 | |
377 | LIST_EXIT_CRITICAL(); |
378 | return listStatus; |
379 | } |
380 | |
381 | /*! ********************************************************************************* |
382 | * \brief Links an element in the previous position relative to a given member |
383 | * of a list. |
384 | * |
385 | * \param[in] element - ID of a member of a list. |
386 | * newElement - new element to insert before the given member. |
387 | * |
388 | * \return kLIST_OrphanElement if element is not part of any list. |
389 | * kLIST_Full if list is full. |
390 | * kLIST_Ok if insertion was successful. |
391 | * |
392 | * \pre |
393 | * |
394 | * \post |
395 | * |
396 | * \remarks |
397 | * |
398 | ********************************************************************************** */ |
399 | list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement) |
400 | { |
401 | list_status_t listStatus = kLIST_Ok; |
402 | LIST_ENTER_CRITICAL(); |
403 | |
404 | if (element->list == NULL) |
405 | { |
406 | listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ |
407 | } |
408 | else |
409 | { |
410 | listStatus = LIST_Error_Check(element->list, newElement); |
411 | if (listStatus == kLIST_Ok) |
412 | { |
413 | #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) |
414 | list_element_handle_t element_list = element->list->head; |
415 | while (NULL != element_list) |
416 | { |
417 | if ((element_list->next == element) || (element_list == element)) |
418 | { |
419 | if (element_list == element) |
420 | { |
421 | element->list->head = newElement; |
422 | } |
423 | else |
424 | { |
425 | element_list->next = newElement; |
426 | } |
427 | newElement->list = element->list; |
428 | newElement->next = element; |
429 | element->list->size++; |
430 | break; |
431 | } |
432 | element_list = element_list->next; |
433 | } |
434 | |
435 | #else |
436 | if (element->prev == NULL) /*Element is list head*/ |
437 | { |
438 | element->list->head = newElement; |
439 | } |
440 | else |
441 | { |
442 | element->prev->next = newElement; |
443 | } |
444 | newElement->list = element->list; |
445 | element->list->size++; |
446 | newElement->next = element; |
447 | newElement->prev = element->prev; |
448 | element->prev = newElement; |
449 | #endif |
450 | } |
451 | } |
452 | |
453 | LIST_EXIT_CRITICAL(); |
454 | return listStatus; |
455 | } |
456 | |
457 | /*! ********************************************************************************* |
458 | * \brief Gets the current size of a list. |
459 | * |
460 | * \param[in] list - ID of the list. |
461 | * |
462 | * \return Current size of the list. |
463 | * |
464 | * \pre |
465 | * |
466 | * \post |
467 | * |
468 | * \remarks |
469 | * |
470 | ********************************************************************************** */ |
471 | uint32_t LIST_GetSize(list_handle_t list) |
472 | { |
473 | return list->size; |
474 | } |
475 | |
476 | /*! ********************************************************************************* |
477 | * \brief Gets the number of free places in the list. |
478 | * |
479 | * \param[in] list - ID of the list. |
480 | * |
481 | * \return Available size of the list. |
482 | * |
483 | * \pre |
484 | * |
485 | * \post |
486 | * |
487 | * \remarks |
488 | * |
489 | ********************************************************************************** */ |
490 | uint32_t LIST_GetAvailableSize(list_handle_t list) |
491 | { |
492 | return ((uint32_t)list->max - (uint32_t)list->size); /*Gets the number of free places in the list*/ |
493 | } |
494 |