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
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.
12 * @file mali_osk_list.h
13 * Implementation of the OS abstraction layer for the kernel device driver
16 #ifndef __MALI_OSK_LIST_H__
17 #define __MALI_OSK_LIST_H__
20 #include "mali_kernel_common.h"
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
)
28 next
->prev
= new_entry
;
29 new_entry
->next
= next
;
30 new_entry
->prev
= prev
;
31 prev
->next
= new_entry
;
34 MALI_STATIC_INLINE
void __mali_osk_list_del(_mali_osk_list_t
*prev
, _mali_osk_list_t
*next
)
40 /** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists
43 /** Reference implementations of Doubly-linked Circular Lists are provided.
44 * There is often no need to re-implement these.
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. */
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)
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
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 }
62 /** @brief Initialize a list element.
64 * All list elements must be initialized before use.
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.
69 * @param list the list element to initialize
71 MALI_STATIC_INLINE
void _mali_osk_list_init( _mali_osk_list_t
*list
)
77 /** @brief Insert a single list element after an entry in a list
79 * As an example, if this is inserted to the head of a list, then this becomes
80 * the first element of the list.
82 * Do not use to move list elements from one list to another, as it will break
83 * the originating list.
86 * @param newlist the list element to insert
87 * @param list the list in which to insert. The new element will be the next
90 MALI_STATIC_INLINE
void _mali_osk_list_add( _mali_osk_list_t
*new_entry
, _mali_osk_list_t
*list
)
92 __mali_osk_list_add(new_entry
, list
, list
->next
);
95 /** @brief Insert a single list element before an entry in a list
97 * As an example, if this is inserted to the head of a list, then this becomes
98 * the last element of the list.
100 * Do not use to move list elements from one list to another, as it will break
101 * the originating list.
103 * @param newlist the list element to insert
104 * @param list the list in which to insert. The new element will be the previous
107 MALI_STATIC_INLINE
void _mali_osk_list_addtail( _mali_osk_list_t
*new_entry
, _mali_osk_list_t
*list
)
109 __mali_osk_list_add(new_entry
, list
->prev
, list
);
112 /** @brief Remove a single element from a list
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.
118 * @param list the list element to remove.
120 MALI_STATIC_INLINE
void _mali_osk_list_del( _mali_osk_list_t
*list
)
122 __mali_osk_list_del(list
->prev
, list
->next
);
125 /** @brief Remove a single element from a list, and re-initialize it
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.
130 * @param list the list element to remove and initialize.
132 MALI_STATIC_INLINE
void _mali_osk_list_delinit( _mali_osk_list_t
*list
)
134 __mali_osk_list_del(list
->prev
, list
->next
);
135 _mali_osk_list_init(list
);
138 /** @brief Determine whether a list is empty.
140 * An empty list is one that contains a single element that points to itself.
142 * @param list the list to check.
143 * @return non-zero if the list is empty, and zero otherwise.
145 MALI_STATIC_INLINE mali_bool
_mali_osk_list_empty( _mali_osk_list_t
*list
)
147 return list
->next
== list
;
150 /** @brief Move a list element from one list to another.
152 * The list element must be initialized.
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.
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.
161 MALI_STATIC_INLINE
void _mali_osk_list_move( _mali_osk_list_t
*move_entry
, _mali_osk_list_t
*list
)
163 __mali_osk_list_del(move_entry
->prev
, move_entry
->next
);
164 _mali_osk_list_add(move_entry
, list
);
167 /** @brief Move an entire list
169 * The list element must be initialized.
171 * Allows you to move a list from one list head to another list head
173 * @param old_list The existing list head
174 * @param new_list The new list head (must be an empty list)
176 MALI_STATIC_INLINE
void _mali_osk_list_move_list( _mali_osk_list_t
*old_list
, _mali_osk_list_t
*new_list
)
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
;
189 /** @brief Find the containing structure of a list
191 * When traversing a list, this is used to recover the containing structure,
192 * given that is contains a _mali_osk_list_t member.
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.
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.
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.
208 #define _MALI_OSK_LIST_ENTRY(ptr, type, member) \
209 _MALI_OSK_CONTAINER_OF(ptr, type, member)
211 /** @brief Enumerate a list safely
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.
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
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.
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
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.
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); \
242 tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member))
244 /** @brief Enumerate a list in reverse order safely
246 * This macro is identical to @ref _MALI_OSK_LIST_FOREACHENTRY, except that
247 * entries are enumerated in reverse order.
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
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.
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); \
265 tmp = _MALI_OSK_LIST_ENTRY(tmp->member.prev, type, member))
267 /** @} */ /* end group _mali_osk_list */
273 #endif /* __MALI_OSK_LIST_H__ */