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