1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2016 Intel Corporation. All rights reserved.
4 *
5 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6 * Keyon Jie <yang.jie@linux.intel.com>
7 */
8
9 #ifndef __SOF_LIST_H__
10 #define __SOF_LIST_H__
11
12 /* Really simple list manipulation */
13
14 struct list_item;
15
16 struct list_item {
17 struct list_item *next;
18 struct list_item *prev;
19 };
20
21 /* initialise list before any use - list will point to itself */
list_init(struct list_item * list)22 static inline void list_init(struct list_item *list)
23 {
24 list->next = list;
25 list->prev = list;
26 }
27
28 /* add new item to the start or head of the list */
list_item_prepend(struct list_item * item,struct list_item * list)29 static inline void list_item_prepend(struct list_item *item,
30 struct list_item *list)
31 {
32 struct list_item *next = list->next;
33
34 next->prev = item;
35 item->next = next;
36 item->prev = list;
37 list->next = item;
38 }
39
40 /* add new item to the end or tail of the list */
list_item_append(struct list_item * item,struct list_item * list)41 static inline void list_item_append(struct list_item *item,
42 struct list_item *list)
43 {
44 struct list_item *tail = list->prev;
45
46 tail->next = item;
47 item->next = list;
48 item->prev = tail;
49 list->prev = item;
50 }
51
52 /* delete item from the list leaves deleted list item
53 *in undefined state list_is_empty will return true
54 */
list_item_del(struct list_item * item)55 static inline void list_item_del(struct list_item *item)
56 {
57 item->next->prev = item->prev;
58 item->prev->next = item->next;
59 list_init(item);
60 }
61
62 /* is list item the last item in list ? */
list_item_is_last(struct list_item * item,struct list_item * list)63 static inline int list_item_is_last(struct list_item *item,
64 struct list_item *list)
65 {
66 return item->next == list;
67 }
68
69 /* is list empty ? */
70 #define list_is_empty(item) \
71 ((item)->next == item)
72
73 #define __list_object(item, type, offset) \
74 ((type *)((char *)(item) - (offset)))
75
76 /* get the container object of the list item */
77 #define list_item(item, type, member) \
78 __list_object(item, type, offsetof(type, member))
79
80 /* get the container object of the first item in the list */
81 #define list_first_item(list, type, member) \
82 __list_object((list)->next, type, offsetof(type, member))
83
84 /* get the next container object in the list */
85 #define list_next_item(object, member) \
86 list_item((object)->member.next, typeof(*(object)), member)
87
88 /* list iterator */
89 #define list_for_item(item, list) \
90 for (item = (list)->next; item != (list); item = item->next)
91
92 /* list iterator */
93 #define list_for_item_prev(item, list) \
94 for (item = (list)->prev; item != (list); item = item->prev)
95
96 /* list iterator - safe to delete items */
97 #define list_for_item_safe(item, tmp, list) \
98 for (item = (list)->next, tmp = item->next;\
99 item != (list); \
100 item = tmp, tmp = item->next)
101
102 /**
103 * Re-links the list when head address changed (list moved).
104 * @param new_list New address of the head.
105 * @param old_list Old address of the head.
106 */
list_relink(struct list_item * new_list,struct list_item * old_list)107 static inline void list_relink(struct list_item *new_list,
108 struct list_item *old_list)
109 {
110 struct list_item *li;
111
112 if (new_list->next == old_list) {
113 list_init(new_list);
114 } else {
115 list_for_item(li, new_list)
116 if (li->next == old_list)
117 li->next = new_list; /* for stops here */
118 list_for_item_prev(li, new_list)
119 if (li->prev == old_list)
120 li->prev = new_list; /* for stops here */
121 }
122 }
123
124 #endif /* __SOF_LIST_H__ */
125