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