Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* |
2 | * This confidential and proprietary software may be used only as | |
3 | * authorised by a licensing agreement from ARM Limited | |
4 | * (C) COPYRIGHT 2008-2013 ARM Limited | |
5 | * ALL RIGHTS RESERVED | |
6 | * The entire notice above must be reproduced on all authorised | |
7 | * copies and copies may only be made to the extent permitted | |
8 | * by a licensing agreement from ARM Limited. | |
9 | */ | |
10 | ||
11 | /** | |
12 | * @file mali_osk_list.h | |
13 | * Implementation of the OS abstraction layer for the kernel device driver | |
14 | */ | |
15 | ||
16 | #ifndef __MALI_OSK_LIST_H__ | |
17 | #define __MALI_OSK_LIST_H__ | |
18 | ||
19 | #include "mali_osk.h" | |
20 | #include "mali_kernel_common.h" | |
21 | ||
22 | #ifdef __cplusplus | |
23 | extern "C" { | |
24 | #endif | |
25 | ||
26 | MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next) | |
27 | { | |
28 | next->prev = new_entry; | |
29 | new_entry->next = next; | |
30 | new_entry->prev = prev; | |
31 | prev->next = new_entry; | |
32 | } | |
33 | ||
34 | MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next) | |
35 | { | |
36 | next->prev = prev; | |
37 | prev->next = next; | |
38 | } | |
39 | ||
40 | /** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists | |
41 | * @{ */ | |
42 | ||
43 | /** Reference implementations of Doubly-linked Circular Lists are provided. | |
44 | * There is often no need to re-implement these. | |
45 | * | |
46 | * @note The implementation may differ subtly from any lists the OS provides. | |
47 | * For this reason, these lists should not be mixed with OS-specific lists | |
48 | * inside the OSK/UKK implementation. */ | |
49 | ||
50 | /** @brief Initialize a list to be a head of an empty list | |
51 | * @param exp the list to initialize. */ | |
52 | #define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp) | |
53 | ||
54 | /** @brief Define a list variable, which is uninitialized. | |
55 | * @param exp the name of the variable that the list will be defined as. */ | |
56 | #define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp | |
57 | ||
58 | /** @brief Define a list variable, which is initialized. | |
59 | * @param exp the name of the variable that the list will be defined as. */ | |
60 | #define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp } | |
61 | ||
62 | /** @brief Initialize a list element. | |
63 | * | |
64 | * All list elements must be initialized before use. | |
65 | * | |
66 | * Do not use on any list element that is present in a list without using | |
67 | * _mali_osk_list_del first, otherwise this will break the list. | |
68 | * | |
69 | * @param list the list element to initialize | |
70 | */ | |
71 | MALI_STATIC_INLINE void _mali_osk_list_init( _mali_osk_list_t *list ) | |
72 | { | |
73 | list->next = list; | |
74 | list->prev = list; | |
75 | } | |
76 | ||
77 | /** @brief Insert a single list element after an entry in a list | |
78 | * | |
79 | * As an example, if this is inserted to the head of a list, then this becomes | |
80 | * the first element of the list. | |
81 | * | |
82 | * Do not use to move list elements from one list to another, as it will break | |
83 | * the originating list. | |
84 | * | |
85 | * | |
86 | * @param newlist the list element to insert | |
87 | * @param list the list in which to insert. The new element will be the next | |
88 | * entry in this list | |
89 | */ | |
90 | MALI_STATIC_INLINE void _mali_osk_list_add( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) | |
91 | { | |
92 | __mali_osk_list_add(new_entry, list, list->next); | |
93 | } | |
94 | ||
95 | /** @brief Insert a single list element before an entry in a list | |
96 | * | |
97 | * As an example, if this is inserted to the head of a list, then this becomes | |
98 | * the last element of the list. | |
99 | * | |
100 | * Do not use to move list elements from one list to another, as it will break | |
101 | * the originating list. | |
102 | * | |
103 | * @param newlist the list element to insert | |
104 | * @param list the list in which to insert. The new element will be the previous | |
105 | * entry in this list | |
106 | */ | |
107 | MALI_STATIC_INLINE void _mali_osk_list_addtail( _mali_osk_list_t *new_entry, _mali_osk_list_t *list ) | |
108 | { | |
109 | __mali_osk_list_add(new_entry, list->prev, list); | |
110 | } | |
111 | ||
112 | /** @brief Remove a single element from a list | |
113 | * | |
114 | * The element will no longer be present in the list. The removed list element | |
115 | * will be uninitialized, and so should not be traversed. It must be | |
116 | * initialized before further use. | |
117 | * | |
118 | * @param list the list element to remove. | |
119 | */ | |
120 | MALI_STATIC_INLINE void _mali_osk_list_del( _mali_osk_list_t *list ) | |
121 | { | |
122 | __mali_osk_list_del(list->prev, list->next); | |
123 | } | |
124 | ||
125 | /** @brief Remove a single element from a list, and re-initialize it | |
126 | * | |
127 | * The element will no longer be present in the list. The removed list element | |
128 | * will initialized, and so can be used as normal. | |
129 | * | |
130 | * @param list the list element to remove and initialize. | |
131 | */ | |
132 | MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) | |
133 | { | |
134 | __mali_osk_list_del(list->prev, list->next); | |
135 | _mali_osk_list_init(list); | |
136 | } | |
137 | ||
138 | /** @brief Determine whether a list is empty. | |
139 | * | |
140 | * An empty list is one that contains a single element that points to itself. | |
141 | * | |
142 | * @param list the list to check. | |
143 | * @return non-zero if the list is empty, and zero otherwise. | |
144 | */ | |
145 | MALI_STATIC_INLINE mali_bool _mali_osk_list_empty( _mali_osk_list_t *list ) | |
146 | { | |
147 | return list->next == list; | |
148 | } | |
149 | ||
150 | /** @brief Move a list element from one list to another. | |
151 | * | |
152 | * The list element must be initialized. | |
153 | * | |
154 | * As an example, moving a list item to the head of a new list causes this item | |
155 | * to be the first element in the new list. | |
156 | * | |
157 | * @param move the list element to move | |
158 | * @param list the new list into which the element will be inserted, as the next | |
159 | * element in the list. | |
160 | */ | |
161 | MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali_osk_list_t *list ) | |
162 | { | |
163 | __mali_osk_list_del(move_entry->prev, move_entry->next); | |
164 | _mali_osk_list_add(move_entry, list); | |
165 | } | |
166 | ||
167 | /** @brief Move an entire list | |
168 | * | |
169 | * The list element must be initialized. | |
170 | * | |
171 | * Allows you to move a list from one list head to another list head | |
172 | * | |
173 | * @param old_list The existing list head | |
174 | * @param new_list The new list head (must be an empty list) | |
175 | */ | |
176 | MALI_STATIC_INLINE void _mali_osk_list_move_list( _mali_osk_list_t *old_list, _mali_osk_list_t *new_list ) | |
177 | { | |
178 | MALI_DEBUG_ASSERT(_mali_osk_list_empty(new_list)); | |
179 | if (!_mali_osk_list_empty(old_list)) { | |
180 | new_list->next = old_list->next; | |
181 | new_list->prev = old_list->prev; | |
182 | new_list->next->prev = new_list; | |
183 | new_list->prev->next = new_list; | |
184 | old_list->next = old_list; | |
185 | old_list->prev = old_list; | |
186 | } | |
187 | } | |
188 | ||
189 | /** @brief Find the containing structure of a list | |
190 | * | |
191 | * When traversing a list, this is used to recover the containing structure, | |
192 | * given that is contains a _mali_osk_list_t member. | |
193 | * | |
194 | * Each list must be of structures of one type, and must link the same members | |
195 | * together, otherwise it will not be possible to correctly recover the | |
196 | * sturctures that the lists link. | |
197 | * | |
198 | * @note no type or memory checking occurs to ensure that a structure does in | |
199 | * fact exist for the list entry, and that it is being recovered with respect | |
200 | * to the correct list member. | |
201 | * | |
202 | * @param ptr the pointer to the _mali_osk_list_t member in this structure | |
203 | * @param type the type of the structure that contains the member | |
204 | * @param member the member of the structure that ptr points to. | |
205 | * @return a pointer to a \a type object which contains the _mali_osk_list_t | |
206 | * \a member, as pointed to by the _mali_osk_list_t \a *ptr. | |
207 | */ | |
208 | #define _MALI_OSK_LIST_ENTRY(ptr, type, member) \ | |
209 | _MALI_OSK_CONTAINER_OF(ptr, type, member) | |
210 | ||
211 | /** @brief Enumerate a list safely | |
212 | * | |
213 | * With this macro, lists can be enumerated in a 'safe' manner. That is, | |
214 | * entries can be deleted from the list without causing an error during | |
215 | * enumeration. To achieve this, a 'temporary' pointer is required, which must | |
216 | * be provided to the macro. | |
217 | * | |
218 | * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be | |
219 | * followed by a statement or compound-statement which will be executed for | |
220 | * each list entry. | |
221 | * | |
222 | * Upon loop completion, providing that an early out was not taken in the | |
223 | * loop body, then it is guaranteed that ptr->member == list, even if the loop | |
224 | * body never executed. | |
225 | * | |
226 | * @param ptr a pointer to an object of type 'type', which points to the | |
227 | * structure that contains the currently enumerated list entry. | |
228 | * @param tmp a pointer to an object of type 'type', which must not be used | |
229 | * inside the list-execution statement. | |
230 | * @param list a pointer to a _mali_osk_list_t, from which enumeration will | |
231 | * begin | |
232 | * @param type the type of the structure that contains the _mali_osk_list_t | |
233 | * member that is part of the list to be enumerated. | |
234 | * @param member the _mali_osk_list_t member of the structure that is part of | |
235 | * the list to be enumerated. | |
236 | */ | |
237 | #define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member) \ | |
238 | for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member), \ | |
239 | tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member); \ | |
240 | &ptr->member != (list); \ | |
241 | ptr = tmp, \ | |
242 | tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member)) | |
243 | ||
244 | /** @brief Enumerate a list in reverse order safely | |
245 | * | |
246 | * This macro is identical to @ref _MALI_OSK_LIST_FOREACHENTRY, except that | |
247 | * entries are enumerated in reverse order. | |
248 | * | |
249 | * @param ptr a pointer to an object of type 'type', which points to the | |
250 | * structure that contains the currently enumerated list entry. | |
251 | * @param tmp a pointer to an object of type 'type', which must not be used | |
252 | * inside the list-execution statement. | |
253 | * @param list a pointer to a _mali_osk_list_t, from which enumeration will | |
254 | * begin | |
255 | * @param type the type of the structure that contains the _mali_osk_list_t | |
256 | * member that is part of the list to be enumerated. | |
257 | * @param member the _mali_osk_list_t member of the structure that is part of | |
258 | * the list to be enumerated. | |
259 | */ | |
260 | #define _MALI_OSK_LIST_FOREACHENTRY_REVERSE(ptr, tmp, list, type, member) \ | |
261 | for (ptr = _MALI_OSK_LIST_ENTRY((list)->prev, type, member), \ | |
262 | tmp = _MALI_OSK_LIST_ENTRY(ptr->member.prev, type, member); \ | |
263 | &ptr->member != (list); \ | |
264 | ptr = tmp, \ | |
265 | tmp = _MALI_OSK_LIST_ENTRY(tmp->member.prev, type, member)) | |
266 | ||
267 | /** @} */ /* end group _mali_osk_list */ | |
268 | ||
269 | #ifdef __cplusplus | |
270 | } | |
271 | #endif | |
272 | ||
273 | #endif /* __MALI_OSK_LIST_H__ */ |