xref: /freebsd/sys/dev/ocs_fc/ocs_list.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1ef270ab1SKenneth D. Merry /*-
2ef270ab1SKenneth D. Merry  * Copyright (c) 2017 Broadcom. All rights reserved.
3ef270ab1SKenneth D. Merry  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4ef270ab1SKenneth D. Merry  *
5ef270ab1SKenneth D. Merry  * Redistribution and use in source and binary forms, with or without
6ef270ab1SKenneth D. Merry  * modification, are permitted provided that the following conditions are met:
7ef270ab1SKenneth D. Merry  *
8ef270ab1SKenneth D. Merry  * 1. Redistributions of source code must retain the above copyright notice,
9ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer.
10ef270ab1SKenneth D. Merry  *
11ef270ab1SKenneth D. Merry  * 2. Redistributions in binary form must reproduce the above copyright notice,
12ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer in the documentation
13ef270ab1SKenneth D. Merry  *    and/or other materials provided with the distribution.
14ef270ab1SKenneth D. Merry  *
15ef270ab1SKenneth D. Merry  * 3. Neither the name of the copyright holder nor the names of its contributors
16ef270ab1SKenneth D. Merry  *    may be used to endorse or promote products derived from this software
17ef270ab1SKenneth D. Merry  *    without specific prior written permission.
18ef270ab1SKenneth D. Merry  *
19ef270ab1SKenneth D. Merry  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20ef270ab1SKenneth D. Merry  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21ef270ab1SKenneth D. Merry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22ef270ab1SKenneth D. Merry  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23ef270ab1SKenneth D. Merry  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ef270ab1SKenneth D. Merry  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ef270ab1SKenneth D. Merry  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ef270ab1SKenneth D. Merry  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ef270ab1SKenneth D. Merry  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ef270ab1SKenneth D. Merry  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ef270ab1SKenneth D. Merry  * POSSIBILITY OF SUCH DAMAGE.
30ef270ab1SKenneth D. Merry  */
31ef270ab1SKenneth D. Merry 
32ef270ab1SKenneth D. Merry /**
33ef270ab1SKenneth D. Merry  * @file
34ef270ab1SKenneth D. Merry  *
35ef270ab1SKenneth D. Merry  * OCS linked list API
36ef270ab1SKenneth D. Merry  *
37ef270ab1SKenneth D. Merry  */
38ef270ab1SKenneth D. Merry 
39ef270ab1SKenneth D. Merry #if !defined(__OCS_LIST_H__)
40ef270ab1SKenneth D. Merry #define __OCS_LIST_H__
41ef270ab1SKenneth D. Merry 
42ef270ab1SKenneth D. Merry #define OCS_LIST_DEBUG
43ef270ab1SKenneth D. Merry 
44ef270ab1SKenneth D. Merry #if defined(OCS_LIST_DEBUG)
45ef270ab1SKenneth D. Merry 
46ef270ab1SKenneth D. Merry #define ocs_list_magic_decl		uint32_t magic;
47ef270ab1SKenneth D. Merry #define OCS_LIST_LIST_MAGIC		0xcafe0000
48ef270ab1SKenneth D. Merry #define OCS_LIST_LINK_MAGIC		0xcafe0001
49ef270ab1SKenneth D. Merry #define ocs_list_set_list_magic		list->magic = OCS_LIST_LIST_MAGIC
50ef270ab1SKenneth D. Merry #define ocs_list_set_link_magic		list->magic = OCS_LIST_LINK_MAGIC
51ef270ab1SKenneth D. Merry 
52ef270ab1SKenneth D. Merry #define ocs_list_assert(cond, ...) \
53ef270ab1SKenneth D. Merry 	if (!(cond)) { \
54ef270ab1SKenneth D. Merry 		return __VA_ARGS__; \
55ef270ab1SKenneth D. Merry 	}
56ef270ab1SKenneth D. Merry #else
57ef270ab1SKenneth D. Merry #define ocs_list_magic_decl
58ef270ab1SKenneth D. Merry #define ocs_list_assert(cond, ...)
59ef270ab1SKenneth D. Merry #define ocs_list_set_list_magic
60ef270ab1SKenneth D. Merry #define ocs_list_set_link_magic
61ef270ab1SKenneth D. Merry #endif
62ef270ab1SKenneth D. Merry 
63ef270ab1SKenneth D. Merry /**
64ef270ab1SKenneth D. Merry  * @brief list/link structure
65ef270ab1SKenneth D. Merry  *
66ef270ab1SKenneth D. Merry  * used for both the list object, and the link object(s).  offset
67ef270ab1SKenneth D. Merry  * is specified when the list is initialized; this implies that a list
68ef270ab1SKenneth D. Merry  * will always point to objects of the same type.  offset is not used
69ef270ab1SKenneth D. Merry  * when ocs_list_t is used as a link (ocs_list_link_t).
70ef270ab1SKenneth D. Merry  *
71ef270ab1SKenneth D. Merry  */
72ef270ab1SKenneth D. Merry 
73ef270ab1SKenneth D. Merry typedef struct ocs_list_s ocs_list_t;
74ef270ab1SKenneth D. Merry struct ocs_list_s {
75ef270ab1SKenneth D. Merry 	ocs_list_magic_decl			/*<< used if debugging is enabled */
76ef270ab1SKenneth D. Merry 	ocs_list_t *next;			/*<< pointer to head of list (or next if link) */
77ef270ab1SKenneth D. Merry 	ocs_list_t *prev;			/*<< pointer to tail of list (or previous if link) */
78ef270ab1SKenneth D. Merry 	uint32_t offset;			/*<< offset in bytes to the link element of the objects in list */
79ef270ab1SKenneth D. Merry };
80ef270ab1SKenneth D. Merry typedef ocs_list_t ocs_list_link_t;
81ef270ab1SKenneth D. Merry 
82ef270ab1SKenneth D. Merry /* item2link - return pointer to link given pointer to an item */
83ef270ab1SKenneth D. Merry #define item2link(list, item)	((ocs_list_t*) (((uint8_t*)(item)) + (list)->offset))
84ef270ab1SKenneth D. Merry 
85ef270ab1SKenneth D. Merry /* link2item - return pointer to item given pointer to a link */
86ef270ab1SKenneth D. Merry #define link2item(list, link)	((void*) (((uint8_t*)(link)) - (list)->offset))
87ef270ab1SKenneth D. Merry 
88ef270ab1SKenneth D. Merry /**
89ef270ab1SKenneth D. Merry  * @brief Initialize a list
90ef270ab1SKenneth D. Merry  *
91ef270ab1SKenneth D. Merry  * A list object is initialized.  Helper define is used to call _ocs_list_init() with
92ef270ab1SKenneth D. Merry  * offsetof(type, link)
93ef270ab1SKenneth D. Merry  *
94ef270ab1SKenneth D. Merry  * @param list Pointer to list
95ef270ab1SKenneth D. Merry  * @param offset Offset in bytes in item to the link element
96ef270ab1SKenneth D. Merry  *
97ef270ab1SKenneth D. Merry  * @return none
98ef270ab1SKenneth D. Merry  */
99ef270ab1SKenneth D. Merry static inline void
_ocs_list_init(ocs_list_t * list,uint32_t offset)100ef270ab1SKenneth D. Merry _ocs_list_init(ocs_list_t *list, uint32_t offset)
101ef270ab1SKenneth D. Merry {
102ef270ab1SKenneth D. Merry 	ocs_list_assert(list);
103ef270ab1SKenneth D. Merry 	ocs_list_set_list_magic;
104ef270ab1SKenneth D. Merry 
105ef270ab1SKenneth D. Merry 	list->next = list;
106ef270ab1SKenneth D. Merry 	list->prev = list;
107ef270ab1SKenneth D. Merry 	list->offset = offset;
108ef270ab1SKenneth D. Merry }
109ef270ab1SKenneth D. Merry #define ocs_list_init(head, type, link)		_ocs_list_init(head, offsetof(type, link))
110ef270ab1SKenneth D. Merry 
111ef270ab1SKenneth D. Merry /**
112ef270ab1SKenneth D. Merry  * @ingroup os
113ef270ab1SKenneth D. Merry  * @brief Test if a list is empty
114ef270ab1SKenneth D. Merry  *
115ef270ab1SKenneth D. Merry  * @param list Pointer to list head
116ef270ab1SKenneth D. Merry  *
117ef270ab1SKenneth D. Merry  * @return 1 if empty, 0 otherwise
118ef270ab1SKenneth D. Merry  */
119ef270ab1SKenneth D. Merry static inline int32_t
ocs_list_empty(ocs_list_t * list)120ef270ab1SKenneth D. Merry ocs_list_empty(ocs_list_t *list)
121ef270ab1SKenneth D. Merry {
122ef270ab1SKenneth D. Merry 	ocs_list_assert(list, 1);
123ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, 1);
124ef270ab1SKenneth D. Merry 	return list->next == list;
125ef270ab1SKenneth D. Merry }
126ef270ab1SKenneth D. Merry 
127ef270ab1SKenneth D. Merry /**
128ef270ab1SKenneth D. Merry  * @ingroup os
129ef270ab1SKenneth D. Merry  * @brief Test if a list is valid (ready for use)
130ef270ab1SKenneth D. Merry  *
131ef270ab1SKenneth D. Merry  * @param list Pointer to list head
132ef270ab1SKenneth D. Merry  *
133ef270ab1SKenneth D. Merry  * @return true if list is usable, false otherwise
134ef270ab1SKenneth D. Merry  */
135ef270ab1SKenneth D. Merry static inline int
ocs_list_valid(ocs_list_t * list)136ef270ab1SKenneth D. Merry ocs_list_valid(ocs_list_t *list)
137ef270ab1SKenneth D. Merry {
138ef270ab1SKenneth D. Merry 	return (list->magic == OCS_LIST_LIST_MAGIC);
139ef270ab1SKenneth D. Merry }
140ef270ab1SKenneth D. Merry 
141ef270ab1SKenneth D. Merry /**
142ef270ab1SKenneth D. Merry  * @brief Insert link between two other links
143ef270ab1SKenneth D. Merry  *
144ef270ab1SKenneth D. Merry  * Inserts a link in between two other links
145ef270ab1SKenneth D. Merry  *
146ef270ab1SKenneth D. Merry  * @param a Pointer to first link
147ef270ab1SKenneth D. Merry  * @param b Pointer to next link
148ef270ab1SKenneth D. Merry  * @param c Pointer to link to insert between a and b
149ef270ab1SKenneth D. Merry  *
150ef270ab1SKenneth D. Merry  * @return none
151ef270ab1SKenneth D. Merry  */
152ef270ab1SKenneth D. Merry static inline void
_ocs_list_insert_link(ocs_list_t * a,ocs_list_t * b,ocs_list_t * c)153ef270ab1SKenneth D. Merry _ocs_list_insert_link(ocs_list_t *a, ocs_list_t *b, ocs_list_t *c)
154ef270ab1SKenneth D. Merry {
155ef270ab1SKenneth D. Merry 	ocs_list_assert(a);
156ef270ab1SKenneth D. Merry 	ocs_list_assert((a->magic == OCS_LIST_LIST_MAGIC) || (a->magic == OCS_LIST_LINK_MAGIC));
157ef270ab1SKenneth D. Merry 	ocs_list_assert(a->next);
158ef270ab1SKenneth D. Merry 	ocs_list_assert(a->prev);
159ef270ab1SKenneth D. Merry 	ocs_list_assert(b);
160ef270ab1SKenneth D. Merry 	ocs_list_assert((b->magic == OCS_LIST_LIST_MAGIC) || (b->magic == OCS_LIST_LINK_MAGIC));
161ef270ab1SKenneth D. Merry 	ocs_list_assert(b->next);
162ef270ab1SKenneth D. Merry 	ocs_list_assert(b->prev);
163ef270ab1SKenneth D. Merry 	ocs_list_assert(c);
164ef270ab1SKenneth D. Merry 	ocs_list_assert((c->magic == OCS_LIST_LIST_MAGIC) || (c->magic == OCS_LIST_LINK_MAGIC));
165ef270ab1SKenneth D. Merry 	ocs_list_assert(!c->next);
166ef270ab1SKenneth D. Merry 	ocs_list_assert(!c->prev);
167ef270ab1SKenneth D. Merry 
168ef270ab1SKenneth D. Merry 	ocs_list_assert(a->offset == b->offset);
169ef270ab1SKenneth D. Merry 	ocs_list_assert(b->offset == c->offset);
170ef270ab1SKenneth D. Merry 
171ef270ab1SKenneth D. Merry 	c->next = a->next;
172ef270ab1SKenneth D. Merry 	c->prev = b->prev;
173ef270ab1SKenneth D. Merry 	a->next = c;
174ef270ab1SKenneth D. Merry 	b->prev = c;
175ef270ab1SKenneth D. Merry }
176ef270ab1SKenneth D. Merry 
177ef270ab1SKenneth D. Merry #if defined(OCS_LIST_DEBUG)
178ef270ab1SKenneth D. Merry /**
179ef270ab1SKenneth D. Merry  * @brief Initialize a list link for debug purposes
180ef270ab1SKenneth D. Merry  *
181ef270ab1SKenneth D. Merry  * For debugging a linked list link element has a magic number that is initialized,
182*cededdffSGordon Bergling  * and the offset value initialized and used for subsequent assertions.
183ef270ab1SKenneth D. Merry  *
184ef270ab1SKenneth D. Merry  *
185ef270ab1SKenneth D. Merry  * @param list Pointer to list head
186ef270ab1SKenneth D. Merry  * @param link Pointer to link to be initialized
187ef270ab1SKenneth D. Merry  *
188ef270ab1SKenneth D. Merry  * @return none
189ef270ab1SKenneth D. Merry  */
190ef270ab1SKenneth D. Merry static inline void
ocs_list_init_link(ocs_list_t * list,ocs_list_t * link)191ef270ab1SKenneth D. Merry ocs_list_init_link(ocs_list_t *list, ocs_list_t *link)
192ef270ab1SKenneth D. Merry {
193ef270ab1SKenneth D. Merry 	ocs_list_assert(list);
194ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC);
195ef270ab1SKenneth D. Merry 	ocs_list_assert(link);
196ef270ab1SKenneth D. Merry 
197ef270ab1SKenneth D. Merry 	if (link->magic == 0) {
198ef270ab1SKenneth D. Merry 		link->magic = OCS_LIST_LINK_MAGIC;
199ef270ab1SKenneth D. Merry 		link->offset = list->offset;
200ef270ab1SKenneth D. Merry 		link->next = NULL;
201ef270ab1SKenneth D. Merry 		link->prev = NULL;
202ef270ab1SKenneth D. Merry 	}
203ef270ab1SKenneth D. Merry }
204ef270ab1SKenneth D. Merry #else
205ef270ab1SKenneth D. Merry #define ocs_list_init_link(...)
206ef270ab1SKenneth D. Merry #endif
207ef270ab1SKenneth D. Merry 
208ef270ab1SKenneth D. Merry /**
209ef270ab1SKenneth D. Merry  * @ingroup os
210ef270ab1SKenneth D. Merry  * @brief Add an item to the head of the list
211ef270ab1SKenneth D. Merry  *
212ef270ab1SKenneth D. Merry  * @param list Pointer to list head
213ef270ab1SKenneth D. Merry  * @param item Item to add
214ef270ab1SKenneth D. Merry  */
215ef270ab1SKenneth D. Merry static inline void
ocs_list_add_head(ocs_list_t * list,void * item)216ef270ab1SKenneth D. Merry ocs_list_add_head(ocs_list_t *list, void *item)
217ef270ab1SKenneth D. Merry {
218ef270ab1SKenneth D. Merry 	ocs_list_t *link;
219ef270ab1SKenneth D. Merry 
220ef270ab1SKenneth D. Merry 	ocs_list_assert(list);
221ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC);
222ef270ab1SKenneth D. Merry 	ocs_list_assert(item);
223ef270ab1SKenneth D. Merry 
224ef270ab1SKenneth D. Merry 	link = item2link(list, item);
225ef270ab1SKenneth D. Merry 	ocs_list_init_link(list, link);
226ef270ab1SKenneth D. Merry 
227ef270ab1SKenneth D. Merry 	ocs_list_assert(link->magic == OCS_LIST_LINK_MAGIC);
228ef270ab1SKenneth D. Merry 	ocs_list_assert(link->offset == list->offset);
229ef270ab1SKenneth D. Merry 	ocs_list_assert(link->next == NULL);
230ef270ab1SKenneth D. Merry 	ocs_list_assert(link->prev == NULL);
231ef270ab1SKenneth D. Merry 
232ef270ab1SKenneth D. Merry 	_ocs_list_insert_link(list, list->next, item2link(list, item));
233ef270ab1SKenneth D. Merry }
234ef270ab1SKenneth D. Merry 
235ef270ab1SKenneth D. Merry /**
236ef270ab1SKenneth D. Merry  * @ingroup os
237ef270ab1SKenneth D. Merry  * @brief Add an item to the tail of the list
238ef270ab1SKenneth D. Merry  *
239ef270ab1SKenneth D. Merry  * @param list Head of the list
240ef270ab1SKenneth D. Merry  * @param item Item to add
241ef270ab1SKenneth D. Merry  */
242ef270ab1SKenneth D. Merry static inline void
ocs_list_add_tail(ocs_list_t * list,void * item)243ef270ab1SKenneth D. Merry ocs_list_add_tail(ocs_list_t *list, void *item)
244ef270ab1SKenneth D. Merry {
245ef270ab1SKenneth D. Merry 	ocs_list_t *link;
246ef270ab1SKenneth D. Merry 
247ef270ab1SKenneth D. Merry 	ocs_list_assert(list);
248ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC);
249ef270ab1SKenneth D. Merry 	ocs_list_assert(item);
250ef270ab1SKenneth D. Merry 
251ef270ab1SKenneth D. Merry 	link = item2link(list, item);
252ef270ab1SKenneth D. Merry 	ocs_list_init_link(list, link);
253ef270ab1SKenneth D. Merry 
254ef270ab1SKenneth D. Merry 	ocs_list_assert(link->magic == OCS_LIST_LINK_MAGIC);
255ef270ab1SKenneth D. Merry 	ocs_list_assert(link->offset == list->offset);
256ef270ab1SKenneth D. Merry 	ocs_list_assert(link->next == NULL);
257ef270ab1SKenneth D. Merry 	ocs_list_assert(link->prev == NULL);
258ef270ab1SKenneth D. Merry 
259ef270ab1SKenneth D. Merry 	_ocs_list_insert_link(list->prev, list, link);
260ef270ab1SKenneth D. Merry }
261ef270ab1SKenneth D. Merry 
262ef270ab1SKenneth D. Merry /**
263ef270ab1SKenneth D. Merry  * @ingroup os
264ef270ab1SKenneth D. Merry  * @brief Return the first item in the list
265ef270ab1SKenneth D. Merry  *
266ef270ab1SKenneth D. Merry  * @param list Head of the list
267ef270ab1SKenneth D. Merry  *
268ef270ab1SKenneth D. Merry  * @return pointer to the first item, NULL otherwise
269ef270ab1SKenneth D. Merry  */
270ef270ab1SKenneth D. Merry static inline void *
ocs_list_get_head(ocs_list_t * list)271ef270ab1SKenneth D. Merry ocs_list_get_head(ocs_list_t *list)
272ef270ab1SKenneth D. Merry {
273ef270ab1SKenneth D. Merry 	ocs_list_assert(list, NULL);
274ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, NULL);
275ef270ab1SKenneth D. Merry 	return ocs_list_empty(list) ? NULL : link2item(list, list->next);
276ef270ab1SKenneth D. Merry }
277ef270ab1SKenneth D. Merry 
278ef270ab1SKenneth D. Merry /**
279ef270ab1SKenneth D. Merry  * @ingroup os
280ef270ab1SKenneth D. Merry  * @brief Return the first item in the list
281ef270ab1SKenneth D. Merry  *
282ef270ab1SKenneth D. Merry  * @param list head of the list
283ef270ab1SKenneth D. Merry  *
284ef270ab1SKenneth D. Merry  * @return pointer to the last item, NULL otherwise
285ef270ab1SKenneth D. Merry  */
286ef270ab1SKenneth D. Merry static inline void *
ocs_list_get_tail(ocs_list_t * list)287ef270ab1SKenneth D. Merry ocs_list_get_tail(ocs_list_t *list)
288ef270ab1SKenneth D. Merry {
289ef270ab1SKenneth D. Merry 	ocs_list_assert(list, NULL);
290ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, NULL);
291ef270ab1SKenneth D. Merry 	return ocs_list_empty(list) ? NULL : link2item(list, list->prev);
292ef270ab1SKenneth D. Merry }
293ef270ab1SKenneth D. Merry 
294ef270ab1SKenneth D. Merry /**
295ef270ab1SKenneth D. Merry  * @ingroup os
296ef270ab1SKenneth D. Merry  * @brief Return the last item in the list
297ef270ab1SKenneth D. Merry  *
298ef270ab1SKenneth D. Merry  * @param list Pointer to list head
299ef270ab1SKenneth D. Merry  *
300ef270ab1SKenneth D. Merry  * @return pointer to the last item, NULL otherwise
301ef270ab1SKenneth D. Merry  */
ocs_list_tail(ocs_list_t * list)302ef270ab1SKenneth D. Merry static inline void *ocs_list_tail(ocs_list_t *list)
303ef270ab1SKenneth D. Merry {
304ef270ab1SKenneth D. Merry 	ocs_list_assert(list, NULL);
305ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, NULL);
306ef270ab1SKenneth D. Merry 	return ocs_list_empty(list) ? NULL : link2item(list, list->prev);
307ef270ab1SKenneth D. Merry }
308ef270ab1SKenneth D. Merry 
309ef270ab1SKenneth D. Merry /**
310ef270ab1SKenneth D. Merry  * @ingroup os
311ef270ab1SKenneth D. Merry  * @brief Get the next item on the list
312ef270ab1SKenneth D. Merry  *
313ef270ab1SKenneth D. Merry  * @param list head of the list
314ef270ab1SKenneth D. Merry  * @param item current item
315ef270ab1SKenneth D. Merry  *
316ef270ab1SKenneth D. Merry  * @return pointer to the next item, NULL otherwise
317ef270ab1SKenneth D. Merry  */
ocs_list_next(ocs_list_t * list,void * item)318ef270ab1SKenneth D. Merry static inline void *ocs_list_next(ocs_list_t *list, void *item)
319ef270ab1SKenneth D. Merry {
320ef270ab1SKenneth D. Merry 	ocs_list_t *link;
321ef270ab1SKenneth D. Merry 
322ef270ab1SKenneth D. Merry 	if (item == NULL) {
323ef270ab1SKenneth D. Merry 		return NULL;
324ef270ab1SKenneth D. Merry 	}
325ef270ab1SKenneth D. Merry 
326ef270ab1SKenneth D. Merry 	ocs_list_assert(list, NULL);
327ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, NULL);
328ef270ab1SKenneth D. Merry 	ocs_list_assert(item, NULL);
329ef270ab1SKenneth D. Merry 
330ef270ab1SKenneth D. Merry 	link = item2link(list, item);
331ef270ab1SKenneth D. Merry 
332ef270ab1SKenneth D. Merry 	ocs_list_assert(link->magic == OCS_LIST_LINK_MAGIC, NULL);
333ef270ab1SKenneth D. Merry 	ocs_list_assert(link->offset == list->offset, NULL);
334ef270ab1SKenneth D. Merry 	ocs_list_assert(link->next, NULL);
335ef270ab1SKenneth D. Merry 	ocs_list_assert(link->prev, NULL);
336ef270ab1SKenneth D. Merry 
337ef270ab1SKenneth D. Merry 	if ((link->next) == list) {
338ef270ab1SKenneth D. Merry 		return NULL;
339ef270ab1SKenneth D. Merry 	}
340ef270ab1SKenneth D. Merry 
341ef270ab1SKenneth D. Merry 	return link2item(list, link->next);
342ef270ab1SKenneth D. Merry }
343ef270ab1SKenneth D. Merry 
344ef270ab1SKenneth D. Merry /**
345ef270ab1SKenneth D. Merry  * @ingroup os
346ef270ab1SKenneth D. Merry  * @brief Remove and return an item from the head of the list
347ef270ab1SKenneth D. Merry  *
348ef270ab1SKenneth D. Merry  * @param list head of the list
349ef270ab1SKenneth D. Merry  *
350ef270ab1SKenneth D. Merry  * @return pointer to returned item, or NULL if list is empty
351ef270ab1SKenneth D. Merry  */
352ef270ab1SKenneth D. Merry #define ocs_list_remove_head(list)		ocs_list_remove(list, ocs_list_get_head(list))
353ef270ab1SKenneth D. Merry 
354ef270ab1SKenneth D. Merry /**
355ef270ab1SKenneth D. Merry  * @ingroup os
356ef270ab1SKenneth D. Merry  * @brief Remove an item from the list
357ef270ab1SKenneth D. Merry  *
358ef270ab1SKenneth D. Merry  * @param list Head of the list
359ef270ab1SKenneth D. Merry  * @param item Item to remove
360ef270ab1SKenneth D. Merry  *
361ef270ab1SKenneth D. Merry  * @return pointer to item, or NULL if item is not found.
362ef270ab1SKenneth D. Merry  */
ocs_list_remove(ocs_list_t * list,void * item)363ef270ab1SKenneth D. Merry static inline void *ocs_list_remove(ocs_list_t *list, void *item)
364ef270ab1SKenneth D. Merry {
365ef270ab1SKenneth D. Merry 	ocs_list_t *link;
366ef270ab1SKenneth D. Merry 	ocs_list_t *prev;
367ef270ab1SKenneth D. Merry 	ocs_list_t *next;
368ef270ab1SKenneth D. Merry 
369ef270ab1SKenneth D. Merry 	if (item == NULL) {
370ef270ab1SKenneth D. Merry 		return NULL;
371ef270ab1SKenneth D. Merry 	}
372ef270ab1SKenneth D. Merry 	ocs_list_assert(list, NULL);
373ef270ab1SKenneth D. Merry 	ocs_list_assert(list->magic == OCS_LIST_LIST_MAGIC, NULL);
374ef270ab1SKenneth D. Merry 
375ef270ab1SKenneth D. Merry 	link = item2link(list, item);
376ef270ab1SKenneth D. Merry 
377ef270ab1SKenneth D. Merry 	ocs_list_assert(link->magic == OCS_LIST_LINK_MAGIC, NULL);
378ef270ab1SKenneth D. Merry 	ocs_list_assert(link->offset == list->offset, NULL);
379ef270ab1SKenneth D. Merry 	ocs_list_assert(link->next, NULL);
380ef270ab1SKenneth D. Merry 	ocs_list_assert(link->prev, NULL);
381ef270ab1SKenneth D. Merry 
382ef270ab1SKenneth D. Merry 	prev = link->prev;
383ef270ab1SKenneth D. Merry 	next = link->next;
384ef270ab1SKenneth D. Merry 
385ef270ab1SKenneth D. Merry 	prev->next = next;
386ef270ab1SKenneth D. Merry 	next->prev = prev;
387ef270ab1SKenneth D. Merry 
388ef270ab1SKenneth D. Merry 	link->next = link->prev = NULL;
389ef270ab1SKenneth D. Merry 
390ef270ab1SKenneth D. Merry 	return item;
391ef270ab1SKenneth D. Merry }
392ef270ab1SKenneth D. Merry 
393ef270ab1SKenneth D. Merry /**
394ef270ab1SKenneth D. Merry  * @brief Iterate a linked list
395ef270ab1SKenneth D. Merry  *
396ef270ab1SKenneth D. Merry  * Iterate a linked list.
397ef270ab1SKenneth D. Merry  *
398ef270ab1SKenneth D. Merry  * @param list Pointer to list
399ef270ab1SKenneth D. Merry  * @param item Pointer to iterated item
400ef270ab1SKenneth D. Merry  *
401ef270ab1SKenneth D. Merry  * note, item is NULL after full list is traversed.
402ef270ab1SKenneth D. Merry 
403ef270ab1SKenneth D. Merry  * @return none
404ef270ab1SKenneth D. Merry  */
405ef270ab1SKenneth D. Merry 
406ef270ab1SKenneth D. Merry #define ocs_list_foreach(list, item) \
407ef270ab1SKenneth D. Merry 	for (item = ocs_list_get_head((list)); item; item = ocs_list_next((list), item) )
408ef270ab1SKenneth D. Merry 
409ef270ab1SKenneth D. Merry /**
410ef270ab1SKenneth D. Merry  * @brief Iterate a linked list safely
411ef270ab1SKenneth D. Merry  *
412ef270ab1SKenneth D. Merry  * Iterate a linked list safely, meaning that the iterated item
413ef270ab1SKenneth D. Merry  * may be safely removed from the list.
414ef270ab1SKenneth D. Merry  *
415ef270ab1SKenneth D. Merry  * @param list Pointer to list
416ef270ab1SKenneth D. Merry  * @param item Pointer to iterated item
417ef270ab1SKenneth D. Merry  * @param nxt Pointer to saveed iterated item
418ef270ab1SKenneth D. Merry  *
419ef270ab1SKenneth D. Merry  * note, item is NULL after full list is traversed.
420ef270ab1SKenneth D. Merry  *
421ef270ab1SKenneth D. Merry  * @return none
422ef270ab1SKenneth D. Merry  */
423ef270ab1SKenneth D. Merry 
424ef270ab1SKenneth D. Merry #define ocs_list_foreach_safe(list, item, nxt) \
425ef270ab1SKenneth D. Merry 	for (item = ocs_list_get_head(list), nxt = item ? ocs_list_next(list, item) : NULL; item; \
426ef270ab1SKenneth D. Merry 		item = nxt, nxt = ocs_list_next(list, item))
427ef270ab1SKenneth D. Merry 
428ef270ab1SKenneth D. Merry /**
429ef270ab1SKenneth D. Merry  * @brief Test if object is on a list
430ef270ab1SKenneth D. Merry  *
431ef270ab1SKenneth D. Merry  * Returns True if object is on a list
432ef270ab1SKenneth D. Merry  *
433ef270ab1SKenneth D. Merry  * @param link Pointer to list link
434ef270ab1SKenneth D. Merry  *
435ef270ab1SKenneth D. Merry  * @return returns True if object is on a list
436ef270ab1SKenneth D. Merry  */
437ef270ab1SKenneth D. Merry static inline int32_t
ocs_list_on_list(ocs_list_link_t * link)438ef270ab1SKenneth D. Merry ocs_list_on_list(ocs_list_link_t *link)
439ef270ab1SKenneth D. Merry {
440ef270ab1SKenneth D. Merry 	return (link->next != NULL);
441ef270ab1SKenneth D. Merry }
442ef270ab1SKenneth D. Merry 
443ef270ab1SKenneth D. Merry #endif /* __OCS_LIST_H__ */
444