1 /*
2 * Copyright 2018-2019, 2022 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() uint32_t regPrimask = DisableGlobalIRQ();
25 #define LIST_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask);
26 #endif
27 #else
28 #define LIST_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
29 #define LIST_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask);
30 #endif
31
LIST_Error_Check(list_handle_t list,list_element_handle_t newElement)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 Initializes 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 ********************************************************************************** */
LIST_Init(list_handle_t list,uint32_t max)80 void LIST_Init(list_handle_t list, uint32_t max)
81 {
82 list->head = NULL;
83 list->tail = NULL;
84 list->max = 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 ********************************************************************************** */
LIST_GetList(list_element_handle_t listElement)103 list_handle_t LIST_GetList(list_element_handle_t listElement)
104 {
105 return listElement->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 ********************************************************************************** */
LIST_AddTail(list_handle_t list,list_element_handle_t listElement)124 list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t listElement)
125 {
126 LIST_ENTER_CRITICAL();
127 list_status_t listStatus = kLIST_Ok;
128
129 listStatus = LIST_Error_Check(list, listElement);
130 if (listStatus == kLIST_Ok) /* Avoiding list status error */
131 {
132 if (list->size == 0U)
133 {
134 list->head = listElement;
135 }
136 else
137 {
138 list->tail->next = listElement;
139 }
140 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
141 #else
142 listElement->prev = list->tail;
143 #endif
144 listElement->list = list;
145 listElement->next = NULL;
146 list->tail = listElement;
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 ********************************************************************************** */
LIST_AddHead(list_handle_t list,list_element_handle_t listElement)170 list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t listElement)
171 {
172 LIST_ENTER_CRITICAL();
173 list_status_t listStatus = kLIST_Ok;
174
175 listStatus = LIST_Error_Check(list, listElement);
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 = listElement;
182 }
183 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
184 #else
185 else
186 {
187 list->head->prev = listElement;
188 }
189 listElement->prev = NULL;
190 #endif
191 listElement->list = list;
192 listElement->next = list->head;
193 list->head = listElement;
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 ********************************************************************************** */
LIST_RemoveHead(list_handle_t list)216 list_element_handle_t LIST_RemoveHead(list_handle_t list)
217 {
218 list_element_handle_t listElement;
219
220 LIST_ENTER_CRITICAL();
221
222 if ((NULL == list) || (list->size == 0U))
223 {
224 listElement = NULL; /*LIST_ is empty*/
225 }
226 else
227 {
228 listElement = 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 listElement->next->prev = NULL;
239 }
240 #endif
241 listElement->list = NULL;
242 list->head = listElement->next; /*Is NULL if element is head*/
243 }
244
245 LIST_EXIT_CRITICAL();
246 return listElement;
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 ********************************************************************************** */
LIST_GetHead(list_handle_t list)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 ********************************************************************************** */
LIST_GetNext(list_element_handle_t listElement)284 list_element_handle_t LIST_GetNext(list_element_handle_t listElement)
285 {
286 return listElement->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 ********************************************************************************** */
LIST_GetPrev(list_element_handle_t listElement)304 list_element_handle_t LIST_GetPrev(list_element_handle_t listElement)
305 {
306 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
307 return NULL;
308 #else
309 return listElement->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 ********************************************************************************** */
LIST_RemoveElement(list_element_handle_t listElement)328 list_status_t LIST_RemoveElement(list_element_handle_t listElement)
329 {
330 list_status_t listStatus = kLIST_Ok;
331 LIST_ENTER_CRITICAL();
332
333 if (listElement->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 = listElement->list->head;
341 list_element_handle_t element_Prev = NULL;
342 while (NULL != element_list)
343 {
344 if (listElement->list->head == listElement)
345 {
346 listElement->list->head = element_list->next;
347 break;
348 }
349 if (element_list->next == listElement)
350 {
351 element_Prev = element_list;
352 element_list->next = listElement->next;
353 break;
354 }
355 element_list = element_list->next;
356 }
357 if (listElement->next == NULL)
358 {
359 listElement->list->tail = element_Prev;
360 }
361 #else
362 if (listElement->prev == NULL) /*Element is head or solo*/
363 {
364 listElement->list->head = listElement->next; /*is null if solo*/
365 }
366 if (listElement->next == NULL) /*Element is tail or solo*/
367 {
368 listElement->list->tail = listElement->prev; /*is null if solo*/
369 }
370 if (listElement->prev != NULL) /*Element is not head*/
371 {
372 listElement->prev->next = listElement->next;
373 }
374 if (listElement->next != NULL) /*Element is not tail*/
375 {
376 listElement->next->prev = listElement->prev;
377 }
378 #endif
379 listElement->list->size--;
380 listElement->list = NULL;
381 }
382
383 LIST_EXIT_CRITICAL();
384 return listStatus;
385 }
386
387 /*! *********************************************************************************
388 * \brief Links an element in the previous position relative to a given member
389 * of a list.
390 *
391 * \param[in] element - ID of a member of a list.
392 * newElement - new element to insert before the given member.
393 *
394 * \return kLIST_OrphanElement if element is not part of any list.
395 * kLIST_Full if list is full.
396 * kLIST_Ok if insertion was successful.
397 *
398 * \pre
399 *
400 * \post
401 *
402 * \remarks
403 *
404 ********************************************************************************** */
LIST_AddPrevElement(list_element_handle_t listElement,list_element_handle_t newElement)405 list_status_t LIST_AddPrevElement(list_element_handle_t listElement, list_element_handle_t newElement)
406 {
407 list_status_t listStatus = kLIST_Ok;
408 LIST_ENTER_CRITICAL();
409
410 if (listElement->list == NULL)
411 {
412 listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/
413 }
414 else
415 {
416 listStatus = LIST_Error_Check(listElement->list, newElement);
417 if (listStatus == kLIST_Ok)
418 {
419 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
420 list_element_handle_t element_list = listElement->list->head;
421 while (NULL != element_list)
422 {
423 if ((element_list->next == listElement) || (element_list == listElement))
424 {
425 if (element_list == listElement)
426 {
427 listElement->list->head = newElement;
428 }
429 else
430 {
431 element_list->next = newElement;
432 }
433 newElement->list = listElement->list;
434 newElement->next = listElement;
435 listElement->list->size++;
436 break;
437 }
438 element_list = element_list->next;
439 }
440
441 #else
442 if (listElement->prev == NULL) /*Element is list head*/
443 {
444 listElement->list->head = newElement;
445 }
446 else
447 {
448 listElement->prev->next = newElement;
449 }
450 newElement->list = listElement->list;
451 listElement->list->size++;
452 newElement->next = listElement;
453 newElement->prev = listElement->prev;
454 listElement->prev = newElement;
455 #endif
456 }
457 }
458
459 LIST_EXIT_CRITICAL();
460 return listStatus;
461 }
462
463 /*! *********************************************************************************
464 * \brief Gets the current size of a list.
465 *
466 * \param[in] list - ID of the list.
467 *
468 * \return Current size of the list.
469 *
470 * \pre
471 *
472 * \post
473 *
474 * \remarks
475 *
476 ********************************************************************************** */
LIST_GetSize(list_handle_t list)477 uint32_t LIST_GetSize(list_handle_t list)
478 {
479 return list->size;
480 }
481
482 /*! *********************************************************************************
483 * \brief Gets the number of free places in the list.
484 *
485 * \param[in] list - ID of the list.
486 *
487 * \return Available size of the list.
488 *
489 * \pre
490 *
491 * \post
492 *
493 * \remarks
494 *
495 ********************************************************************************** */
LIST_GetAvailableSize(list_handle_t list)496 uint32_t LIST_GetAvailableSize(list_handle_t list)
497 {
498 return (list->max - list->size); /*Gets the number of free places in the list*/
499 }
500