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