1 #ifndef __LIST_H
2 #define __LIST_H
3 
4 #include "types.h" // container_of
5 
6 
7 /****************************************************************
8  * hlist - Double linked lists with a single pointer list head
9  ****************************************************************/
10 
11 struct hlist_node {
12     struct hlist_node *next, **pprev;
13 };
14 
15 struct hlist_head {
16     struct hlist_node *first;
17 };
18 
19 static inline int
hlist_empty(const struct hlist_head * h)20 hlist_empty(const struct hlist_head *h)
21 {
22     return !h->first;
23 }
24 
25 static inline void
hlist_del(struct hlist_node * n)26 hlist_del(struct hlist_node *n)
27 {
28     struct hlist_node *next = n->next;
29     struct hlist_node **pprev = n->pprev;
30     *pprev = next;
31     if (next)
32         next->pprev = pprev;
33 }
34 
35 static inline void
hlist_add(struct hlist_node * n,struct hlist_node ** pprev)36 hlist_add(struct hlist_node *n, struct hlist_node **pprev)
37 {
38     struct hlist_node *next = *pprev;
39     n->pprev = pprev;
40     n->next = next;
41     if (next)
42         next->pprev = &n->next;
43     *pprev = n;
44 }
45 
46 static inline void
hlist_add_head(struct hlist_node * n,struct hlist_head * h)47 hlist_add_head(struct hlist_node *n, struct hlist_head *h)
48 {
49     hlist_add(n, &h->first);
50 }
51 
52 static inline void
hlist_add_before(struct hlist_node * n,struct hlist_node * next)53 hlist_add_before(struct hlist_node *n, struct hlist_node *next)
54 {
55     hlist_add(n, next->pprev);
56 }
57 
58 static inline void
hlist_add_after(struct hlist_node * n,struct hlist_node * prev)59 hlist_add_after(struct hlist_node *n, struct hlist_node *prev)
60 {
61     hlist_add(n, &prev->next);
62 }
63 
64 static inline void
hlist_replace(struct hlist_node * old,struct hlist_node * new)65 hlist_replace(struct hlist_node *old, struct hlist_node *new)
66 {
67     new->next = old->next;
68     if (new->next)
69         new->next->pprev = &new->next;
70     new->pprev = old->pprev;
71     *new->pprev = new;
72 }
73 
74 #define hlist_for_each_entry(pos, head, member)                         \
75     for (pos = container_of((head)->first, typeof(*pos), member)        \
76          ; pos != container_of(NULL, typeof(*pos), member)              \
77          ; pos = container_of(pos->member.next, typeof(*pos), member))
78 
79 #define hlist_for_each_entry_safe(pos, n, head, member)                 \
80     for (pos = container_of((head)->first, typeof(*pos), member)        \
81          ; pos != container_of(NULL, typeof(*pos), member)              \
82              && ({ n = pos->member.next; 1; })                          \
83          ; pos = container_of(n, typeof(*pos), member))
84 
85 #define hlist_for_each_entry_pprev(pos, pprev, head, member)            \
86     for (pprev = &(head)->first                                         \
87          ; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \
88          ; pprev = &(*pprev)->next)
89 
90 
91 #endif // list.h
92