ustream: prevent recursive calls to the read callback
[project/libubox.git] / list.h
1 /*-
2 * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (c) 2010 Isilon Systems, Inc.
4 * Copyright (c) 2010 iX Systems, Inc.
5 * Copyright (c) 2010 Panasas, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice unmodified, this list of conditions, and the following
13 * disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #ifndef _LINUX_LIST_H_
30 #define _LINUX_LIST_H_
31
32 #include <stddef.h>
33 #include <stdbool.h>
34
35 #define prefetch(x)
36
37 #ifndef container_of
38 #define container_of(ptr, type, member) \
39 ({ \
40 const __typeof__(((type *) NULL)->member) *__mptr = (ptr); \
41 (type *) ((char *) __mptr - offsetof(type, member)); \
42 })
43 #endif
44
45 #ifndef container_of_safe
46 #define container_of_safe(ptr, type, member) \
47 ({ \
48 const __typeof__(((type *) NULL)->member) *__mptr = (ptr); \
49 __mptr ? (type *)((char *) __mptr - offsetof(type, member)) : NULL; \
50 })
51 #endif
52
53 struct list_head {
54 struct list_head *next;
55 struct list_head *prev;
56 };
57
58 #define LIST_HEAD_INIT(name) { &(name), &(name) }
59 #undef LIST_HEAD
60 #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
61
62 static inline void
63 INIT_LIST_HEAD(struct list_head *list)
64 {
65 list->next = list->prev = list;
66 }
67
68 static inline bool
69 list_empty(const struct list_head *head)
70 {
71 return (head->next == head);
72 }
73
74 static inline bool
75 list_is_first(const struct list_head *list,
76 const struct list_head *head)
77 {
78 return list->prev == head;
79 }
80
81 static inline bool
82 list_is_last(const struct list_head *list,
83 const struct list_head *head)
84 {
85 return list->next == head;
86 }
87
88 static inline void
89 _list_del(struct list_head *entry)
90 {
91 entry->next->prev = entry->prev;
92 entry->prev->next = entry->next;
93 }
94
95 static inline void
96 list_del(struct list_head *entry)
97 {
98 _list_del(entry);
99 entry->next = entry->prev = NULL;
100 }
101
102 static inline void
103 _list_add(struct list_head *_new, struct list_head *prev,
104 struct list_head *next)
105 {
106
107 next->prev = _new;
108 _new->next = next;
109 _new->prev = prev;
110 prev->next = _new;
111 }
112
113 static inline void
114 list_del_init(struct list_head *entry)
115 {
116 _list_del(entry);
117 INIT_LIST_HEAD(entry);
118 }
119
120 #define list_entry(ptr, type, field) container_of(ptr, type, field)
121 #define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field)
122 #define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)
123 #define list_next_entry(pos, member) list_entry((pos)->member.next, typeof(*(pos)), member)
124 #define list_entry_is_h(p, h, field) (&p->field == (h))
125
126 #define list_for_each(p, head) \
127 for (p = (head)->next; p != (head); p = p->next)
128
129 #define list_for_each_safe(p, n, head) \
130 for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)
131
132 #define list_for_each_entry(p, h, field) \
133 for (p = list_first_entry(h, __typeof__(*p), field); &p->field != (h); \
134 p = list_entry(p->field.next, __typeof__(*p), field))
135
136 #define list_for_each_entry_continue(p, h, field) \
137 for (p = list_next_entry(p, field); \
138 !list_entry_is_h(p, h, field); \
139 p = list_next_entry(p, field))
140
141 #define list_for_each_entry_continue_reverse(p, h, field) \
142 for (p = list_prev_entry(p, field); \
143 !list_entry_is_h(p, h, field); \
144 p = list_prev_entry(p, field))
145
146 #define list_for_each_entry_safe(p, n, h, field) \
147 for (p = list_first_entry(h, __typeof__(*p), field), \
148 n = list_entry(p->field.next, __typeof__(*p), field); &p->field != (h);\
149 p = n, n = list_entry(n->field.next, __typeof__(*n), field))
150
151 #define list_for_each_entry_reverse(p, h, field) \
152 for (p = list_last_entry(h, __typeof__(*p), field); &p->field != (h); \
153 p = list_entry(p->field.prev, __typeof__(*p), field))
154
155 #define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev)
156 #define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev)
157
158 static inline void
159 list_add(struct list_head *_new, struct list_head *head)
160 {
161 _list_add(_new, head, head->next);
162 }
163
164 static inline void
165 list_add_tail(struct list_head *_new, struct list_head *head)
166 {
167 _list_add(_new, head->prev, head);
168 }
169
170 static inline void
171 list_move(struct list_head *list, struct list_head *head)
172 {
173 _list_del(list);
174 list_add(list, head);
175 }
176
177 static inline void
178 list_move_tail(struct list_head *entry, struct list_head *head)
179 {
180 _list_del(entry);
181 list_add_tail(entry, head);
182 }
183
184 static inline void
185 _list_splice(const struct list_head *list, struct list_head *prev,
186 struct list_head *next)
187 {
188 struct list_head *first;
189 struct list_head *last;
190
191 if (list_empty(list))
192 return;
193
194 first = list->next;
195 last = list->prev;
196 first->prev = prev;
197 prev->next = first;
198 last->next = next;
199 next->prev = last;
200 }
201
202 static inline void
203 list_splice(const struct list_head *list, struct list_head *head)
204 {
205 _list_splice(list, head, head->next);
206 }
207
208 static inline void
209 list_splice_tail(struct list_head *list, struct list_head *head)
210 {
211 _list_splice(list, head->prev, head);
212 }
213
214 static inline void
215 list_splice_init(struct list_head *list, struct list_head *head)
216 {
217 _list_splice(list, head, head->next);
218 INIT_LIST_HEAD(list);
219 }
220
221 static inline void
222 list_splice_tail_init(struct list_head *list, struct list_head *head)
223 {
224 _list_splice(list, head->prev, head);
225 INIT_LIST_HEAD(list);
226 }
227
228 #endif /* _LINUX_LIST_H_ */