xref: /freebsd/sys/compat/linuxkpi/common/include/linux/list.h (revision c58ddc25462699c0d13bf703adbed661bb102cac)
18d59ecb2SHans Petter Selasky /*-
28d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Isilon Systems, Inc.
38d59ecb2SHans Petter Selasky  * Copyright (c) 2010 iX Systems, Inc.
48d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Panasas, Inc.
5c7c96d10SHans Petter Selasky  * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
68d59ecb2SHans Petter Selasky  * All rights reserved.
78d59ecb2SHans Petter Selasky  *
88d59ecb2SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
98d59ecb2SHans Petter Selasky  * modification, are permitted provided that the following conditions
108d59ecb2SHans Petter Selasky  * are met:
118d59ecb2SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
128d59ecb2SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
138d59ecb2SHans Petter Selasky  *    disclaimer.
148d59ecb2SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
158d59ecb2SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
168d59ecb2SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
178d59ecb2SHans Petter Selasky  *
188d59ecb2SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
198d59ecb2SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
208d59ecb2SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
218d59ecb2SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
228d59ecb2SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
238d59ecb2SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248d59ecb2SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258d59ecb2SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268d59ecb2SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278d59ecb2SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288d59ecb2SHans Petter Selasky  */
29307f78f3SVladimir Kondratyev #ifndef _LINUXKPI_LINUX_LIST_H_
30307f78f3SVladimir Kondratyev #define _LINUXKPI_LINUX_LIST_H_
318d59ecb2SHans Petter Selasky 
3201fdacdbSHans Petter Selasky #ifndef _STANDALONE
338d59ecb2SHans Petter Selasky /*
3401fdacdbSHans Petter Selasky  * Since LIST_HEAD conflicts with the Linux definition we must include any
358d59ecb2SHans Petter Selasky  * FreeBSD header which requires it here so it is resolved with the correct
368d59ecb2SHans Petter Selasky  * definition prior to the undef.
378d59ecb2SHans Petter Selasky  */
388d59ecb2SHans Petter Selasky #include <linux/types.h>
398d59ecb2SHans Petter Selasky 
408d59ecb2SHans Petter Selasky #include <sys/param.h>
418d59ecb2SHans Petter Selasky #include <sys/kernel.h>
428d59ecb2SHans Petter Selasky #include <sys/queue.h>
438d59ecb2SHans Petter Selasky #include <sys/cpuset.h>
448d59ecb2SHans Petter Selasky #include <sys/jail.h>
458d59ecb2SHans Petter Selasky #include <sys/lock.h>
468d59ecb2SHans Petter Selasky #include <sys/mutex.h>
478d59ecb2SHans Petter Selasky #include <sys/proc.h>
488d59ecb2SHans Petter Selasky #include <sys/vnode.h>
498d59ecb2SHans Petter Selasky #include <sys/conf.h>
508d59ecb2SHans Petter Selasky #include <sys/socket.h>
518d59ecb2SHans Petter Selasky #include <sys/mbuf.h>
528d59ecb2SHans Petter Selasky 
538d59ecb2SHans Petter Selasky #include <net/bpf.h>
54de8a7cc7SBjoern A. Zeeb #include <net/ethernet.h>
558d59ecb2SHans Petter Selasky #include <net/if.h>
568d59ecb2SHans Petter Selasky #include <net/if_var.h>
578d59ecb2SHans Petter Selasky #include <net/if_types.h>
588d59ecb2SHans Petter Selasky #include <net/if_media.h>
598d59ecb2SHans Petter Selasky #include <net/vnet.h>
608d59ecb2SHans Petter Selasky 
618d59ecb2SHans Petter Selasky #include <netinet/in.h>
628d59ecb2SHans Petter Selasky #include <netinet/in_pcb.h>
638d59ecb2SHans Petter Selasky #include <netinet/in_var.h>
641ea44822SSepherosa Ziehau #include <netinet/tcp_lro.h>
658d59ecb2SHans Petter Selasky 
668d59ecb2SHans Petter Selasky #include <netinet6/in6_var.h>
678d59ecb2SHans Petter Selasky #include <netinet6/nd6.h>
688d59ecb2SHans Petter Selasky 
69de8a7cc7SBjoern A. Zeeb #include <net80211/ieee80211.h>
70de8a7cc7SBjoern A. Zeeb #include <net80211/ieee80211_var.h>
71de8a7cc7SBjoern A. Zeeb #include <net80211/ieee80211_node.h>
72de8a7cc7SBjoern A. Zeeb 
738d59ecb2SHans Petter Selasky #include <vm/vm.h>
748d59ecb2SHans Petter Selasky #include <vm/vm_object.h>
7586845417SHans Petter Selasky #include <vm/pmap.h>
7601fdacdbSHans Petter Selasky #endif
778d59ecb2SHans Petter Selasky 
7800d47e02SMark Johnston #ifndef prefetch
798d59ecb2SHans Petter Selasky #define	prefetch(x)
8000d47e02SMark Johnston #endif
8101fdacdbSHans Petter Selasky 
82a11bac73SHans Petter Selasky #define LINUX_LIST_HEAD_INIT(name) { &(name), &(name) }
83a11bac73SHans Petter Selasky 
84a11bac73SHans Petter Selasky #define LINUX_LIST_HEAD(name) \
85a11bac73SHans Petter Selasky 	struct list_head name = LINUX_LIST_HEAD_INIT(name)
86a11bac73SHans Petter Selasky 
878d59ecb2SHans Petter Selasky static inline void
INIT_LIST_HEAD(struct list_head * list)888d59ecb2SHans Petter Selasky INIT_LIST_HEAD(struct list_head *list)
898d59ecb2SHans Petter Selasky {
908d59ecb2SHans Petter Selasky 
918d59ecb2SHans Petter Selasky 	list->next = list->prev = list;
928d59ecb2SHans Petter Selasky }
938d59ecb2SHans Petter Selasky 
948d59ecb2SHans Petter Selasky static inline int
list_empty(const struct list_head * head)958d59ecb2SHans Petter Selasky list_empty(const struct list_head *head)
968d59ecb2SHans Petter Selasky {
978d59ecb2SHans Petter Selasky 
988d59ecb2SHans Petter Selasky 	return (head->next == head);
998d59ecb2SHans Petter Selasky }
1008d59ecb2SHans Petter Selasky 
101a11bac73SHans Petter Selasky static inline int
list_empty_careful(const struct list_head * head)102a11bac73SHans Petter Selasky list_empty_careful(const struct list_head *head)
103a11bac73SHans Petter Selasky {
104a11bac73SHans Petter Selasky 	struct list_head *next = head->next;
105a11bac73SHans Petter Selasky 
106a11bac73SHans Petter Selasky 	return ((next == head) && (next == head->prev));
107a11bac73SHans Petter Selasky }
108a11bac73SHans Petter Selasky 
109a11bac73SHans Petter Selasky static inline void
__list_del(struct list_head * prev,struct list_head * next)110a11bac73SHans Petter Selasky __list_del(struct list_head *prev, struct list_head *next)
111a11bac73SHans Petter Selasky {
112a11bac73SHans Petter Selasky 	next->prev = prev;
113a11bac73SHans Petter Selasky 	WRITE_ONCE(prev->next, next);
114a11bac73SHans Petter Selasky }
115a11bac73SHans Petter Selasky 
1168d59ecb2SHans Petter Selasky static inline void
__list_del_entry(struct list_head * entry)11715052dc8SHans Petter Selasky __list_del_entry(struct list_head *entry)
11815052dc8SHans Petter Selasky {
11915052dc8SHans Petter Selasky 
12015052dc8SHans Petter Selasky 	__list_del(entry->prev, entry->next);
12115052dc8SHans Petter Selasky }
12215052dc8SHans Petter Selasky 
12315052dc8SHans Petter Selasky static inline void
list_del(struct list_head * entry)1248d59ecb2SHans Petter Selasky list_del(struct list_head *entry)
1258d59ecb2SHans Petter Selasky {
1268d59ecb2SHans Petter Selasky 
127a11bac73SHans Petter Selasky 	__list_del(entry->prev, entry->next);
1288d59ecb2SHans Petter Selasky }
1298d59ecb2SHans Petter Selasky 
1308d59ecb2SHans Petter Selasky static inline void
list_replace(struct list_head * old,struct list_head * new)1318d59ecb2SHans Petter Selasky list_replace(struct list_head *old, struct list_head *new)
1328d59ecb2SHans Petter Selasky {
1338d59ecb2SHans Petter Selasky 	new->next = old->next;
1348d59ecb2SHans Petter Selasky 	new->next->prev = new;
1358d59ecb2SHans Petter Selasky 	new->prev = old->prev;
1368d59ecb2SHans Petter Selasky 	new->prev->next = new;
1378d59ecb2SHans Petter Selasky }
1388d59ecb2SHans Petter Selasky 
1398d59ecb2SHans Petter Selasky static inline void
list_replace_init(struct list_head * old,struct list_head * new)140aad02fb4SHans Petter Selasky list_replace_init(struct list_head *old, struct list_head *new)
141aad02fb4SHans Petter Selasky {
142aad02fb4SHans Petter Selasky 	list_replace(old, new);
143aad02fb4SHans Petter Selasky 	INIT_LIST_HEAD(old);
144aad02fb4SHans Petter Selasky }
145aad02fb4SHans Petter Selasky 
146aad02fb4SHans Petter Selasky static inline void
__list_add(struct list_head * new,struct list_head * prev,struct list_head * next)147*c58ddc25SVladimir Kondratyev __list_add(struct list_head *new, struct list_head *prev,
1488d59ecb2SHans Petter Selasky     struct list_head *next)
1498d59ecb2SHans Petter Selasky {
1508d59ecb2SHans Petter Selasky 
1518d59ecb2SHans Petter Selasky 	next->prev = new;
1528d59ecb2SHans Petter Selasky 	new->next = next;
1538d59ecb2SHans Petter Selasky 	new->prev = prev;
1548d59ecb2SHans Petter Selasky 	prev->next = new;
1558d59ecb2SHans Petter Selasky }
1568d59ecb2SHans Petter Selasky 
1578d59ecb2SHans Petter Selasky static inline void
list_del_init(struct list_head * entry)1588d59ecb2SHans Petter Selasky list_del_init(struct list_head *entry)
1598d59ecb2SHans Petter Selasky {
1608d59ecb2SHans Petter Selasky 
1618d59ecb2SHans Petter Selasky 	list_del(entry);
1628d59ecb2SHans Petter Selasky 	INIT_LIST_HEAD(entry);
1638d59ecb2SHans Petter Selasky }
1648d59ecb2SHans Petter Selasky 
1658d59ecb2SHans Petter Selasky #define	list_entry(ptr, type, field)	container_of(ptr, type, field)
1668d59ecb2SHans Petter Selasky 
1678d59ecb2SHans Petter Selasky #define	list_first_entry(ptr, type, member) \
1688d59ecb2SHans Petter Selasky 	list_entry((ptr)->next, type, member)
1698d59ecb2SHans Petter Selasky 
170aad02fb4SHans Petter Selasky #define	list_last_entry(ptr, type, member)	\
171aad02fb4SHans Petter Selasky 	list_entry((ptr)->prev, type, member)
172aad02fb4SHans Petter Selasky 
173aad02fb4SHans Petter Selasky #define	list_first_entry_or_null(ptr, type, member) \
174aad02fb4SHans Petter Selasky 	(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
175aad02fb4SHans Petter Selasky 
1768d59ecb2SHans Petter Selasky #define	list_next_entry(ptr, member)					\
1778d59ecb2SHans Petter Selasky 	list_entry(((ptr)->member.next), typeof(*(ptr)), member)
1788d59ecb2SHans Petter Selasky 
179e44fa94cSHans Petter Selasky #define	list_safe_reset_next(ptr, n, member) \
180e44fa94cSHans Petter Selasky 	(n) = list_next_entry(ptr, member)
181e44fa94cSHans Petter Selasky 
182aad02fb4SHans Petter Selasky #define	list_prev_entry(ptr, member)					\
183aad02fb4SHans Petter Selasky 	list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
184aad02fb4SHans Petter Selasky 
1858d59ecb2SHans Petter Selasky #define	list_for_each(p, head)						\
186c7c96d10SHans Petter Selasky 	for (p = (head)->next; p != (head); p = (p)->next)
1878d59ecb2SHans Petter Selasky 
1888d59ecb2SHans Petter Selasky #define	list_for_each_safe(p, n, head)					\
189c7c96d10SHans Petter Selasky 	for (p = (head)->next, n = (p)->next; p != (head); p = n, n = (p)->next)
1908d59ecb2SHans Petter Selasky 
1918d59ecb2SHans Petter Selasky #define list_for_each_entry(p, h, field)				\
192c7c96d10SHans Petter Selasky 	for (p = list_entry((h)->next, typeof(*p), field); &(p)->field != (h); \
193c7c96d10SHans Petter Selasky 	    p = list_entry((p)->field.next, typeof(*p), field))
1948d59ecb2SHans Petter Selasky 
1958d59ecb2SHans Petter Selasky #define list_for_each_entry_safe(p, n, h, field)			\
1968d59ecb2SHans Petter Selasky 	for (p = list_entry((h)->next, typeof(*p), field),		\
197c7c96d10SHans Petter Selasky 	    n = list_entry((p)->field.next, typeof(*p), field); &(p)->field != (h);\
1988d59ecb2SHans Petter Selasky 	    p = n, n = list_entry(n->field.next, typeof(*n), field))
1998d59ecb2SHans Petter Selasky 
200c7c96d10SHans Petter Selasky #define	list_for_each_entry_from(p, h, field) \
201c7c96d10SHans Petter Selasky 	for ( ; &(p)->field != (h); \
202c7c96d10SHans Petter Selasky 	    p = list_entry((p)->field.next, typeof(*p), field))
203c7c96d10SHans Petter Selasky 
2048d59ecb2SHans Petter Selasky #define	list_for_each_entry_continue(p, h, field)			\
205c7c96d10SHans Petter Selasky 	for (p = list_next_entry((p), field); &(p)->field != (h);	\
2068d59ecb2SHans Petter Selasky 	    p = list_next_entry((p), field))
2078d59ecb2SHans Petter Selasky 
2088d59ecb2SHans Petter Selasky #define	list_for_each_entry_safe_from(pos, n, head, member)			\
209c7c96d10SHans Petter Selasky 	for (n = list_entry((pos)->member.next, typeof(*pos), member);		\
210c7c96d10SHans Petter Selasky 	     &(pos)->member != (head);						\
2118d59ecb2SHans Petter Selasky 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
2128d59ecb2SHans Petter Selasky 
2138d59ecb2SHans Petter Selasky #define	list_for_each_entry_reverse(p, h, field)			\
214c7c96d10SHans Petter Selasky 	for (p = list_entry((h)->prev, typeof(*p), field); &(p)->field != (h); \
215c7c96d10SHans Petter Selasky 	    p = list_entry((p)->field.prev, typeof(*p), field))
2168d59ecb2SHans Petter Selasky 
217a11bac73SHans Petter Selasky #define	list_for_each_entry_safe_reverse(p, n, h, field)		\
218a11bac73SHans Petter Selasky 	for (p = list_entry((h)->prev, typeof(*p), field),		\
219a11bac73SHans Petter Selasky 	    n = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
220a11bac73SHans Petter Selasky 	    p = n, n = list_entry(n->field.prev, typeof(*n), field))
221a11bac73SHans Petter Selasky 
222c7c96d10SHans Petter Selasky #define	list_for_each_entry_continue_reverse(p, h, field) \
223c7c96d10SHans Petter Selasky 	for (p = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
224c7c96d10SHans Petter Selasky 	    p = list_entry((p)->field.prev, typeof(*p), field))
225c7c96d10SHans Petter Selasky 
226c7c96d10SHans Petter Selasky #define	list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev)
2278d59ecb2SHans Petter Selasky 
228b723bcd0SJean-Sébastien Pédron #define	list_for_each_prev_safe(p, n, h) 				\
229b723bcd0SJean-Sébastien Pédron 	for (p = (h)->prev, n = (p)->prev;				\
230b723bcd0SJean-Sébastien Pédron 	     p != (h);							\
231b723bcd0SJean-Sébastien Pédron 	     p = n, n = (p)->prev)
232b723bcd0SJean-Sébastien Pédron 
233845a91ceSHans Petter Selasky #define	list_for_each_entry_from_reverse(p, h, field)	\
234845a91ceSHans Petter Selasky 	for (; &p->field != (h);			\
235845a91ceSHans Petter Selasky 	     p = list_prev_entry(p, field))
236845a91ceSHans Petter Selasky 
2378d59ecb2SHans Petter Selasky static inline void
list_add(struct list_head * new,struct list_head * head)2388d59ecb2SHans Petter Selasky list_add(struct list_head *new, struct list_head *head)
2398d59ecb2SHans Petter Selasky {
2408d59ecb2SHans Petter Selasky 
241*c58ddc25SVladimir Kondratyev 	__list_add(new, head, head->next);
2428d59ecb2SHans Petter Selasky }
2438d59ecb2SHans Petter Selasky 
2448d59ecb2SHans Petter Selasky static inline void
list_add_tail(struct list_head * new,struct list_head * head)2458d59ecb2SHans Petter Selasky list_add_tail(struct list_head *new, struct list_head *head)
2468d59ecb2SHans Petter Selasky {
2478d59ecb2SHans Petter Selasky 
248*c58ddc25SVladimir Kondratyev 	__list_add(new, head->prev, head);
2498d59ecb2SHans Petter Selasky }
2508d59ecb2SHans Petter Selasky 
2518d59ecb2SHans Petter Selasky static inline void
list_move(struct list_head * list,struct list_head * head)2528d59ecb2SHans Petter Selasky list_move(struct list_head *list, struct list_head *head)
2538d59ecb2SHans Petter Selasky {
2548d59ecb2SHans Petter Selasky 
2558d59ecb2SHans Petter Selasky 	list_del(list);
2568d59ecb2SHans Petter Selasky 	list_add(list, head);
2578d59ecb2SHans Petter Selasky }
2588d59ecb2SHans Petter Selasky 
2598d59ecb2SHans Petter Selasky static inline void
list_move_tail(struct list_head * entry,struct list_head * head)2608d59ecb2SHans Petter Selasky list_move_tail(struct list_head *entry, struct list_head *head)
2618d59ecb2SHans Petter Selasky {
2628d59ecb2SHans Petter Selasky 
2638d59ecb2SHans Petter Selasky 	list_del(entry);
2648d59ecb2SHans Petter Selasky 	list_add_tail(entry, head);
2658d59ecb2SHans Petter Selasky }
2668d59ecb2SHans Petter Selasky 
2678d59ecb2SHans Petter Selasky static inline void
list_rotate_to_front(struct list_head * entry,struct list_head * head)268bf7deecfSEmmanuel Vadot list_rotate_to_front(struct list_head *entry, struct list_head *head)
269bf7deecfSEmmanuel Vadot {
270bf7deecfSEmmanuel Vadot 
271bf7deecfSEmmanuel Vadot 	list_move_tail(entry, head);
272bf7deecfSEmmanuel Vadot }
273bf7deecfSEmmanuel Vadot 
274bf7deecfSEmmanuel Vadot static inline void
list_bulk_move_tail(struct list_head * head,struct list_head * first,struct list_head * last)275845a91ceSHans Petter Selasky list_bulk_move_tail(struct list_head *head, struct list_head *first,
276845a91ceSHans Petter Selasky     struct list_head *last)
277845a91ceSHans Petter Selasky {
278845a91ceSHans Petter Selasky 	first->prev->next = last->next;
279845a91ceSHans Petter Selasky 	last->next->prev = first->prev;
280845a91ceSHans Petter Selasky 	head->prev->next = first;
281845a91ceSHans Petter Selasky 	first->prev = head->prev;
282845a91ceSHans Petter Selasky 	last->next = head;
283845a91ceSHans Petter Selasky 	head->prev = last;
284845a91ceSHans Petter Selasky }
285845a91ceSHans Petter Selasky 
286845a91ceSHans Petter Selasky static inline void
linux_list_splice(const struct list_head * list,struct list_head * prev,struct list_head * next)287c7c96d10SHans Petter Selasky linux_list_splice(const struct list_head *list, struct list_head *prev,
2888d59ecb2SHans Petter Selasky     struct list_head *next)
2898d59ecb2SHans Petter Selasky {
2908d59ecb2SHans Petter Selasky 	struct list_head *first;
2918d59ecb2SHans Petter Selasky 	struct list_head *last;
2928d59ecb2SHans Petter Selasky 
2938d59ecb2SHans Petter Selasky 	if (list_empty(list))
2948d59ecb2SHans Petter Selasky 		return;
2958d59ecb2SHans Petter Selasky 	first = list->next;
2968d59ecb2SHans Petter Selasky 	last = list->prev;
2978d59ecb2SHans Petter Selasky 	first->prev = prev;
2988d59ecb2SHans Petter Selasky 	prev->next = first;
2998d59ecb2SHans Petter Selasky 	last->next = next;
3008d59ecb2SHans Petter Selasky 	next->prev = last;
3018d59ecb2SHans Petter Selasky }
3028d59ecb2SHans Petter Selasky 
3038d59ecb2SHans Petter Selasky static inline void
list_splice(const struct list_head * list,struct list_head * head)3048d59ecb2SHans Petter Selasky list_splice(const struct list_head *list, struct list_head *head)
3058d59ecb2SHans Petter Selasky {
3068d59ecb2SHans Petter Selasky 
307c7c96d10SHans Petter Selasky 	linux_list_splice(list, head, head->next);
3088d59ecb2SHans Petter Selasky }
3098d59ecb2SHans Petter Selasky 
3108d59ecb2SHans Petter Selasky static inline void
list_splice_tail(struct list_head * list,struct list_head * head)3118d59ecb2SHans Petter Selasky list_splice_tail(struct list_head *list, struct list_head *head)
3128d59ecb2SHans Petter Selasky {
3138d59ecb2SHans Petter Selasky 
314c7c96d10SHans Petter Selasky 	linux_list_splice(list, head->prev, head);
3158d59ecb2SHans Petter Selasky }
3168d59ecb2SHans Petter Selasky 
3178d59ecb2SHans Petter Selasky static inline void
list_splice_init(struct list_head * list,struct list_head * head)3188d59ecb2SHans Petter Selasky list_splice_init(struct list_head *list, struct list_head *head)
3198d59ecb2SHans Petter Selasky {
3208d59ecb2SHans Petter Selasky 
321c7c96d10SHans Petter Selasky 	linux_list_splice(list, head, head->next);
3228d59ecb2SHans Petter Selasky 	INIT_LIST_HEAD(list);
3238d59ecb2SHans Petter Selasky }
3248d59ecb2SHans Petter Selasky 
3258d59ecb2SHans Petter Selasky static inline void
list_splice_tail_init(struct list_head * list,struct list_head * head)3268d59ecb2SHans Petter Selasky list_splice_tail_init(struct list_head *list, struct list_head *head)
3278d59ecb2SHans Petter Selasky {
3288d59ecb2SHans Petter Selasky 
329c7c96d10SHans Petter Selasky 	linux_list_splice(list, head->prev, head);
3308d59ecb2SHans Petter Selasky 	INIT_LIST_HEAD(list);
3318d59ecb2SHans Petter Selasky }
3328d59ecb2SHans Petter Selasky 
3338d59ecb2SHans Petter Selasky #undef LIST_HEAD
3348d59ecb2SHans Petter Selasky #define LIST_HEAD(name)	struct list_head name = { &(name), &(name) }
3358d59ecb2SHans Petter Selasky 
3368d59ecb2SHans Petter Selasky struct hlist_head {
3378d59ecb2SHans Petter Selasky 	struct hlist_node *first;
3388d59ecb2SHans Petter Selasky };
3398d59ecb2SHans Petter Selasky 
3408d59ecb2SHans Petter Selasky struct hlist_node {
3418d59ecb2SHans Petter Selasky 	struct hlist_node *next, **pprev;
3428d59ecb2SHans Petter Selasky };
3438d59ecb2SHans Petter Selasky #define	HLIST_HEAD_INIT { }
3448d59ecb2SHans Petter Selasky #define	HLIST_HEAD(name) struct hlist_head name = HLIST_HEAD_INIT
3458d59ecb2SHans Petter Selasky #define	INIT_HLIST_HEAD(head) (head)->first = NULL
3468d59ecb2SHans Petter Selasky #define	INIT_HLIST_NODE(node)						\
3478d59ecb2SHans Petter Selasky do {									\
3488d59ecb2SHans Petter Selasky 	(node)->next = NULL;						\
3498d59ecb2SHans Petter Selasky 	(node)->pprev = NULL;						\
3508d59ecb2SHans Petter Selasky } while (0)
3518d59ecb2SHans Petter Selasky 
3528d59ecb2SHans Petter Selasky static inline int
hlist_unhashed(const struct hlist_node * h)3538d59ecb2SHans Petter Selasky hlist_unhashed(const struct hlist_node *h)
3548d59ecb2SHans Petter Selasky {
3558d59ecb2SHans Petter Selasky 
3568d59ecb2SHans Petter Selasky 	return !h->pprev;
3578d59ecb2SHans Petter Selasky }
3588d59ecb2SHans Petter Selasky 
3598d59ecb2SHans Petter Selasky static inline int
hlist_empty(const struct hlist_head * h)3608d59ecb2SHans Petter Selasky hlist_empty(const struct hlist_head *h)
3618d59ecb2SHans Petter Selasky {
3628d59ecb2SHans Petter Selasky 
36340ddfc76SHans Petter Selasky 	return !READ_ONCE(h->first);
3648d59ecb2SHans Petter Selasky }
3658d59ecb2SHans Petter Selasky 
3668d59ecb2SHans Petter Selasky static inline void
hlist_del(struct hlist_node * n)3678d59ecb2SHans Petter Selasky hlist_del(struct hlist_node *n)
3688d59ecb2SHans Petter Selasky {
3698d59ecb2SHans Petter Selasky 
37040ddfc76SHans Petter Selasky 	WRITE_ONCE(*(n->pprev), n->next);
37140ddfc76SHans Petter Selasky 	if (n->next != NULL)
3728d59ecb2SHans Petter Selasky 		n->next->pprev = n->pprev;
3738d59ecb2SHans Petter Selasky }
3748d59ecb2SHans Petter Selasky 
3758d59ecb2SHans Petter Selasky static inline void
hlist_del_init(struct hlist_node * n)3768d59ecb2SHans Petter Selasky hlist_del_init(struct hlist_node *n)
3778d59ecb2SHans Petter Selasky {
3788d59ecb2SHans Petter Selasky 
3798d59ecb2SHans Petter Selasky 	if (hlist_unhashed(n))
3808d59ecb2SHans Petter Selasky 		return;
3818d59ecb2SHans Petter Selasky 	hlist_del(n);
3828d59ecb2SHans Petter Selasky 	INIT_HLIST_NODE(n);
3838d59ecb2SHans Petter Selasky }
3848d59ecb2SHans Petter Selasky 
3858d59ecb2SHans Petter Selasky static inline void
hlist_add_head(struct hlist_node * n,struct hlist_head * h)3868d59ecb2SHans Petter Selasky hlist_add_head(struct hlist_node *n, struct hlist_head *h)
3878d59ecb2SHans Petter Selasky {
3888d59ecb2SHans Petter Selasky 
3898d59ecb2SHans Petter Selasky 	n->next = h->first;
39040ddfc76SHans Petter Selasky 	if (h->first != NULL)
3918d59ecb2SHans Petter Selasky 		h->first->pprev = &n->next;
39240ddfc76SHans Petter Selasky 	WRITE_ONCE(h->first, n);
3938d59ecb2SHans Petter Selasky 	n->pprev = &h->first;
3948d59ecb2SHans Petter Selasky }
3958d59ecb2SHans Petter Selasky 
3968d59ecb2SHans Petter Selasky static inline void
hlist_add_before(struct hlist_node * n,struct hlist_node * next)3978d59ecb2SHans Petter Selasky hlist_add_before(struct hlist_node *n, struct hlist_node *next)
3988d59ecb2SHans Petter Selasky {
3998d59ecb2SHans Petter Selasky 
4008d59ecb2SHans Petter Selasky 	n->pprev = next->pprev;
4018d59ecb2SHans Petter Selasky 	n->next = next;
4028d59ecb2SHans Petter Selasky 	next->pprev = &n->next;
40340ddfc76SHans Petter Selasky 	WRITE_ONCE(*(n->pprev), n);
4048d59ecb2SHans Petter Selasky }
4058d59ecb2SHans Petter Selasky 
4068d59ecb2SHans Petter Selasky static inline void
hlist_add_behind(struct hlist_node * n,struct hlist_node * prev)40740ddfc76SHans Petter Selasky hlist_add_behind(struct hlist_node *n, struct hlist_node *prev)
4088d59ecb2SHans Petter Selasky {
4098d59ecb2SHans Petter Selasky 
41040ddfc76SHans Petter Selasky 	n->next = prev->next;
41140ddfc76SHans Petter Selasky 	WRITE_ONCE(prev->next, n);
41240ddfc76SHans Petter Selasky 	n->pprev = &prev->next;
41340ddfc76SHans Petter Selasky 
41440ddfc76SHans Petter Selasky 	if (n->next != NULL)
41540ddfc76SHans Petter Selasky 		n->next->pprev = &n->next;
4168d59ecb2SHans Petter Selasky }
4178d59ecb2SHans Petter Selasky 
4188d59ecb2SHans Petter Selasky static inline void
hlist_move_list(struct hlist_head * old,struct hlist_head * new)4198d59ecb2SHans Petter Selasky hlist_move_list(struct hlist_head *old, struct hlist_head *new)
4208d59ecb2SHans Petter Selasky {
4218d59ecb2SHans Petter Selasky 
4228d59ecb2SHans Petter Selasky 	new->first = old->first;
4238d59ecb2SHans Petter Selasky 	if (new->first)
4248d59ecb2SHans Petter Selasky 		new->first->pprev = &new->first;
4258d59ecb2SHans Petter Selasky 	old->first = NULL;
4268d59ecb2SHans Petter Selasky }
4278d59ecb2SHans Petter Selasky 
list_is_singular(const struct list_head * head)4288d59ecb2SHans Petter Selasky static inline int list_is_singular(const struct list_head *head)
4298d59ecb2SHans Petter Selasky {
4308d59ecb2SHans Petter Selasky 	return !list_empty(head) && (head->next == head->prev);
4318d59ecb2SHans Petter Selasky }
4328d59ecb2SHans Petter Selasky 
__list_cut_position(struct list_head * list,struct list_head * head,struct list_head * entry)4338d59ecb2SHans Petter Selasky static inline void __list_cut_position(struct list_head *list,
4348d59ecb2SHans Petter Selasky 		struct list_head *head, struct list_head *entry)
4358d59ecb2SHans Petter Selasky {
4368d59ecb2SHans Petter Selasky 	struct list_head *new_first = entry->next;
4378d59ecb2SHans Petter Selasky 	list->next = head->next;
4388d59ecb2SHans Petter Selasky 	list->next->prev = list;
4398d59ecb2SHans Petter Selasky 	list->prev = entry;
4408d59ecb2SHans Petter Selasky 	entry->next = list;
4418d59ecb2SHans Petter Selasky 	head->next = new_first;
4428d59ecb2SHans Petter Selasky 	new_first->prev = head;
4438d59ecb2SHans Petter Selasky }
4448d59ecb2SHans Petter Selasky 
list_cut_position(struct list_head * list,struct list_head * head,struct list_head * entry)4458d59ecb2SHans Petter Selasky static inline void list_cut_position(struct list_head *list,
4468d59ecb2SHans Petter Selasky 		struct list_head *head, struct list_head *entry)
4478d59ecb2SHans Petter Selasky {
4488d59ecb2SHans Petter Selasky 	if (list_empty(head))
4498d59ecb2SHans Petter Selasky 		return;
4508d59ecb2SHans Petter Selasky 	if (list_is_singular(head) &&
4518d59ecb2SHans Petter Selasky 		(head->next != entry && head != entry))
4528d59ecb2SHans Petter Selasky 		return;
4538d59ecb2SHans Petter Selasky 	if (entry == head)
4548d59ecb2SHans Petter Selasky 		INIT_LIST_HEAD(list);
4558d59ecb2SHans Petter Selasky 	else
4568d59ecb2SHans Petter Selasky 		__list_cut_position(list, head, entry);
4578d59ecb2SHans Petter Selasky }
4588d59ecb2SHans Petter Selasky 
list_is_first(const struct list_head * list,const struct list_head * head)4598f0c7343SEmmanuel Vadot static inline int list_is_first(const struct list_head *list,
4608f0c7343SEmmanuel Vadot 				const struct list_head *head)
4618f0c7343SEmmanuel Vadot {
4628f0c7343SEmmanuel Vadot 
4638f0c7343SEmmanuel Vadot 	return (list->prev == head);
4648f0c7343SEmmanuel Vadot }
4658f0c7343SEmmanuel Vadot 
list_is_last(const struct list_head * list,const struct list_head * head)4668d59ecb2SHans Petter Selasky static inline int list_is_last(const struct list_head *list,
4678d59ecb2SHans Petter Selasky 				const struct list_head *head)
4688d59ecb2SHans Petter Selasky {
4698d59ecb2SHans Petter Selasky 	return list->next == head;
4708d59ecb2SHans Petter Selasky }
4718d59ecb2SHans Petter Selasky 
4721b18fb7fSBjoern A. Zeeb static inline size_t
list_count_nodes(const struct list_head * list)4731b18fb7fSBjoern A. Zeeb list_count_nodes(const struct list_head *list)
4741b18fb7fSBjoern A. Zeeb {
4751b18fb7fSBjoern A. Zeeb 	const struct list_head *lh;
4761b18fb7fSBjoern A. Zeeb 	size_t count;
4771b18fb7fSBjoern A. Zeeb 
4781b18fb7fSBjoern A. Zeeb 	count = 0;
4791b18fb7fSBjoern A. Zeeb 	list_for_each(lh, list) {
4801b18fb7fSBjoern A. Zeeb 		count++;
4811b18fb7fSBjoern A. Zeeb 	}
4821b18fb7fSBjoern A. Zeeb 
4831b18fb7fSBjoern A. Zeeb 	return (count);
4841b18fb7fSBjoern A. Zeeb }
4851b18fb7fSBjoern A. Zeeb 
4868d59ecb2SHans Petter Selasky #define	hlist_entry(ptr, type, field)	container_of(ptr, type, field)
4878d59ecb2SHans Petter Selasky 
4888d59ecb2SHans Petter Selasky #define	hlist_for_each(p, head)						\
489c7c96d10SHans Petter Selasky 	for (p = (head)->first; p; p = (p)->next)
4908d59ecb2SHans Petter Selasky 
4918d59ecb2SHans Petter Selasky #define	hlist_for_each_safe(p, n, head)					\
492c7c96d10SHans Petter Selasky 	for (p = (head)->first; p && ({ n = (p)->next; 1; }); p = n)
4938d59ecb2SHans Petter Selasky 
4948d59ecb2SHans Petter Selasky #define	hlist_entry_safe(ptr, type, member) \
4958d59ecb2SHans Petter Selasky 	((ptr) ? hlist_entry(ptr, type, member) : NULL)
4968d59ecb2SHans Petter Selasky 
4978d59ecb2SHans Petter Selasky #define	hlist_for_each_entry(pos, head, member)				\
4988d59ecb2SHans Petter Selasky 	for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
4998d59ecb2SHans Petter Selasky 	     pos;							\
5008d59ecb2SHans Petter Selasky 	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
5018d59ecb2SHans Petter Selasky 
502c7c96d10SHans Petter Selasky #define	hlist_for_each_entry_continue(pos, member)			\
503c7c96d10SHans Petter Selasky 	for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member); \
504c7c96d10SHans Petter Selasky 	     (pos);							\
505c7c96d10SHans Petter Selasky 	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
5068d59ecb2SHans Petter Selasky 
507c7c96d10SHans Petter Selasky #define	hlist_for_each_entry_from(pos, member)				\
508c7c96d10SHans Petter Selasky 	for (; (pos);								\
509c7c96d10SHans Petter Selasky 	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
5108d59ecb2SHans Petter Selasky 
511c7c96d10SHans Petter Selasky #define	hlist_for_each_entry_safe(pos, n, head, member)			\
512c7c96d10SHans Petter Selasky 	for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
513c7c96d10SHans Petter Selasky 	     (pos) && ({ n = (pos)->member.next; 1; });			\
514c7c96d10SHans Petter Selasky 	     pos = hlist_entry_safe(n, typeof(*(pos)), member))
5158d59ecb2SHans Petter Selasky 
516a83b3ec7SJean-Sébastien Pédron #if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300
517a83b3ec7SJean-Sébastien Pédron extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
518a83b3ec7SJean-Sébastien Pédron     const struct list_head *a, const struct list_head *b));
519a83b3ec7SJean-Sébastien Pédron #else
520aad02fb4SHans Petter Selasky extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
521aad02fb4SHans Petter Selasky     struct list_head *a, struct list_head *b));
522a83b3ec7SJean-Sébastien Pédron #endif
523aad02fb4SHans Petter Selasky 
524307f78f3SVladimir Kondratyev #endif /* _LINUXKPI_LINUX_LIST_H_ */
525