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 element)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  ********************************************************************************** */
LIST_AddTail(list_handle_t list,list_element_handle_t element)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  ********************************************************************************** */
LIST_AddHead(list_handle_t list,list_element_handle_t element)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  ********************************************************************************** */
LIST_RemoveHead(list_handle_t list)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  ********************************************************************************** */
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 element)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  ********************************************************************************** */
LIST_GetPrev(list_element_handle_t element)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  ********************************************************************************** */
LIST_RemoveElement(list_element_handle_t element)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  ********************************************************************************** */
LIST_AddPrevElement(list_element_handle_t element,list_element_handle_t newElement)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  ********************************************************************************** */
LIST_GetSize(list_handle_t list)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  ********************************************************************************** */
LIST_GetAvailableSize(list_handle_t list)490 uint32_t LIST_GetAvailableSize(list_handle_t list)
491 {
492     return (list->max - list->size); /*Gets the number of free places in the list*/
493 }
494