2 * Copyright 2012-2015 Samy Al Bahra.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Copyright (c) 1991, 1993
29 * The Regents of the University of California. All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)queue.h 8.5 (Berkeley) 8/20/94
65 * This file defines three types of data structures: singly-linked lists,
66 * singly-linked tail queues and lists.
68 * A singly-linked list is headed by a single forward pointer. The elements
69 * are singly linked for minimum space and pointer manipulation overhead at
70 * the expense of O(n) removal for arbitrary elements. New elements can be
71 * added to the list after an existing element or at the head of the list.
72 * Elements being removed from the head of the list should use the explicit
73 * macro for this purpose for optimum efficiency. A singly-linked list may
74 * only be traversed in the forward direction. Singly-linked lists are ideal
75 * for applications with large datasets and few or no removals or for
76 * implementing a LIFO queue.
78 * A singly-linked tail queue is headed by a pair of pointers, one to the
79 * head of the list and the other to the tail of the list. The elements are
80 * singly linked for minimum space and pointer manipulation overhead at the
81 * expense of O(n) removal for arbitrary elements. New elements can be added
82 * to the list after an existing element, at the head of the list, or at the
83 * end of the list. Elements being removed from the head of the tail queue
84 * should use the explicit macro for this purpose for optimum efficiency.
85 * A singly-linked tail queue may only be traversed in the forward direction.
86 * Singly-linked tail queues are ideal for applications with large datasets
87 * and few or no removals or for implementing a FIFO queue.
89 * A list is headed by a single forward pointer (or an array of forward
90 * pointers for a hash table header). The elements are doubly linked
91 * so that an arbitrary element can be removed without a need to
92 * traverse the list. New elements can be added to the list before
93 * or after an existing element or at the head of the list. A list
94 * may only be traversed in the forward direction.
96 * It is safe to use _FOREACH/_FOREACH_SAFE in the presence of concurrent
97 * modifications to the list. Writers to these lists must, on the other hand,
98 * implement writer-side synchronization. The _SWAP operations are not atomic.
99 * This facility is currently unsupported on architectures such as the Alpha
100 * which require load-depend memory fences.
102 * CK_SLIST CK_LIST CK_STAILQ
104 * _HEAD_INITIALIZER + + +
111 * _FOREACH_SAFE + + +
113 * _INSERT_BEFORE - + -
114 * _INSERT_AFTER + + +
116 * _REMOVE_AFTER + - +
124 * Singly-linked List declarations.
126 #define CK_SLIST_HEAD(name, type) \
128 struct type *cslh_first; /* first element */ \
131 #define CK_SLIST_HEAD_INITIALIZER(head) \
134 #define CK_SLIST_ENTRY(type) \
136 struct type *csle_next; /* next element */ \
140 * Singly-linked List functions.
142 #define CK_SLIST_EMPTY(head) \
143 (ck_pr_load_ptr(&(head)->cslh_first) == NULL)
145 #define CK_SLIST_FIRST(head) \
146 (ck_pr_load_ptr(&(head)->cslh_first))
148 #define CK_SLIST_NEXT(elm, field) \
149 ck_pr_load_ptr(&((elm)->field.csle_next))
151 #define CK_SLIST_FOREACH(var, head, field) \
152 for ((var) = CK_SLIST_FIRST((head)); \
153 (var) && (ck_pr_fence_load(), 1); \
154 (var) = CK_SLIST_NEXT((var), field))
156 #define CK_SLIST_FOREACH_SAFE(var, head, field, tvar) \
157 for ((var) = CK_SLIST_FIRST(head); \
158 (var) && (ck_pr_fence_load(), (tvar) = CK_SLIST_NEXT(var, field), 1);\
161 #define CK_SLIST_FOREACH_PREVPTR(var, varp, head, field) \
162 for ((varp) = &(head)->cslh_first; \
163 ((var) = ck_pr_load_ptr(varp)) != NULL && (ck_pr_fence_load(), 1); \
164 (varp) = &(var)->field.csle_next)
166 #define CK_SLIST_INIT(head) do { \
167 ck_pr_store_ptr(&(head)->cslh_first, NULL); \
168 ck_pr_fence_store(); \
171 #define CK_SLIST_INSERT_AFTER(a, b, field) do { \
172 (b)->field.csle_next = (a)->field.csle_next; \
173 ck_pr_fence_store(); \
174 ck_pr_store_ptr(&(a)->field.csle_next, b); \
177 #define CK_SLIST_INSERT_HEAD(head, elm, field) do { \
178 (elm)->field.csle_next = (head)->cslh_first; \
179 ck_pr_fence_store(); \
180 ck_pr_store_ptr(&(head)->cslh_first, elm); \
183 #define CK_SLIST_INSERT_PREVPTR(prevp, slistelm, elm, field) do { \
184 (elm)->field.csle_next = (slistelm); \
185 ck_pr_fence_store(); \
186 ck_pr_store_ptr(prevp, elm); \
189 #define CK_SLIST_REMOVE_AFTER(elm, field) do { \
190 ck_pr_store_ptr(&(elm)->field.csle_next, \
191 (elm)->field.csle_next->field.csle_next); \
194 #define CK_SLIST_REMOVE(head, elm, type, field) do { \
195 if ((head)->cslh_first == (elm)) { \
196 CK_SLIST_REMOVE_HEAD((head), field); \
198 struct type *curelm = (head)->cslh_first; \
199 while (curelm->field.csle_next != (elm)) \
200 curelm = curelm->field.csle_next; \
201 CK_SLIST_REMOVE_AFTER(curelm, field); \
205 #define CK_SLIST_REMOVE_HEAD(head, field) do { \
206 ck_pr_store_ptr(&(head)->cslh_first, \
207 (head)->cslh_first->field.csle_next); \
210 #define CK_SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
211 ck_pr_store_ptr(prevptr, (elm)->field.csle_next); \
214 #define CK_SLIST_MOVE(head1, head2, field) do { \
215 ck_pr_store_ptr(&(head1)->cslh_first, (head2)->cslh_first); \
219 * This operation is not applied atomically.
221 #define CK_SLIST_SWAP(a, b, type) do { \
222 struct type *swap_first = (a)->cslh_first; \
223 (a)->cslh_first = (b)->cslh_first; \
224 (b)->cslh_first = swap_first; \
228 * Singly-linked Tail queue declarations.
230 #define CK_STAILQ_HEAD(name, type) \
232 struct type *cstqh_first;/* first element */ \
233 struct type **cstqh_last;/* addr of last next element */ \
236 #define CK_STAILQ_HEAD_INITIALIZER(head) \
237 { NULL, &(head).cstqh_first }
239 #define CK_STAILQ_ENTRY(type) \
241 struct type *cstqe_next; /* next element */ \
245 * Singly-linked Tail queue functions.
247 #define CK_STAILQ_CONCAT(head1, head2) do { \
248 if ((head2)->cstqh_first != NULL) { \
249 ck_pr_store_ptr((head1)->cstqh_last, (head2)->cstqh_first); \
250 ck_pr_fence_store(); \
251 (head1)->cstqh_last = (head2)->cstqh_last; \
252 CK_STAILQ_INIT((head2)); \
256 #define CK_STAILQ_EMPTY(head) (ck_pr_load_ptr(&(head)->cstqh_first) == NULL)
258 #define CK_STAILQ_FIRST(head) (ck_pr_load_ptr(&(head)->cstqh_first))
260 #define CK_STAILQ_FOREACH(var, head, field) \
261 for((var) = CK_STAILQ_FIRST((head)); \
262 (var) && (ck_pr_fence_load(), 1); \
263 (var) = CK_STAILQ_NEXT((var), field))
265 #define CK_STAILQ_FOREACH_SAFE(var, head, field, tvar) \
266 for ((var) = CK_STAILQ_FIRST((head)); \
267 (var) && (ck_pr_fence_load(), (tvar) = \
268 CK_STAILQ_NEXT((var), field), 1); \
271 #define CK_STAILQ_INIT(head) do { \
272 ck_pr_store_ptr(&(head)->cstqh_first, NULL); \
273 ck_pr_fence_store(); \
274 (head)->cstqh_last = &(head)->cstqh_first; \
277 #define CK_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
278 (elm)->field.cstqe_next = (tqelm)->field.cstqe_next; \
279 ck_pr_fence_store(); \
280 ck_pr_store_ptr(&(tqelm)->field.cstqe_next, elm); \
281 if ((elm)->field.cstqe_next == NULL) \
282 (head)->cstqh_last = &(elm)->field.cstqe_next; \
285 #define CK_STAILQ_INSERT_HEAD(head, elm, field) do { \
286 (elm)->field.cstqe_next = (head)->cstqh_first; \
287 ck_pr_fence_store(); \
288 ck_pr_store_ptr(&(head)->cstqh_first, elm); \
289 if ((elm)->field.cstqe_next == NULL) \
290 (head)->cstqh_last = &(elm)->field.cstqe_next; \
293 #define CK_STAILQ_INSERT_TAIL(head, elm, field) do { \
294 (elm)->field.cstqe_next = NULL; \
295 ck_pr_fence_store(); \
296 ck_pr_store_ptr((head)->cstqh_last, (elm)); \
297 (head)->cstqh_last = &(elm)->field.cstqe_next; \
300 #define CK_STAILQ_NEXT(elm, field) \
301 (ck_pr_load_ptr(&(elm)->field.cstqe_next))
303 #define CK_STAILQ_REMOVE(head, elm, type, field) do { \
304 if ((head)->cstqh_first == (elm)) { \
305 CK_STAILQ_REMOVE_HEAD((head), field); \
307 struct type *curelm = (head)->cstqh_first; \
308 while (curelm->field.cstqe_next != (elm)) \
309 curelm = curelm->field.cstqe_next; \
310 CK_STAILQ_REMOVE_AFTER(head, curelm, field); \
314 #define CK_STAILQ_REMOVE_AFTER(head, elm, field) do { \
315 ck_pr_store_ptr(&(elm)->field.cstqe_next, \
316 (elm)->field.cstqe_next->field.cstqe_next); \
317 if ((elm)->field.cstqe_next == NULL) \
318 (head)->cstqh_last = &(elm)->field.cstqe_next; \
321 #define CK_STAILQ_REMOVE_HEAD(head, field) do { \
322 ck_pr_store_ptr(&(head)->cstqh_first, \
323 (head)->cstqh_first->field.cstqe_next); \
324 if ((head)->cstqh_first == NULL) \
325 (head)->cstqh_last = &(head)->cstqh_first; \
328 #define CK_STAILQ_MOVE(head1, head2, field) do { \
329 ck_pr_store_ptr(&(head1)->cstqh_first, (head2)->cstqh_first); \
330 (head1)->cstqh_last = (head2)->cstqh_last; \
331 if ((head2)->cstqh_last == &(head2)->cstqh_first) \
332 (head1)->cstqh_last = &(head1)->cstqh_first; \
336 * This operation is not applied atomically.
338 #define CK_STAILQ_SWAP(head1, head2, type) do { \
339 struct type *swap_first = CK_STAILQ_FIRST(head1); \
340 struct type **swap_last = (head1)->cstqh_last; \
341 CK_STAILQ_FIRST(head1) = CK_STAILQ_FIRST(head2); \
342 (head1)->cstqh_last = (head2)->cstqh_last; \
343 CK_STAILQ_FIRST(head2) = swap_first; \
344 (head2)->cstqh_last = swap_last; \
345 if (CK_STAILQ_EMPTY(head1)) \
346 (head1)->cstqh_last = &(head1)->cstqh_first; \
347 if (CK_STAILQ_EMPTY(head2)) \
348 (head2)->cstqh_last = &(head2)->cstqh_first; \
354 #define CK_LIST_HEAD(name, type) \
356 struct type *clh_first; /* first element */ \
359 #define CK_LIST_HEAD_INITIALIZER(head) \
362 #define CK_LIST_ENTRY(type) \
364 struct type *cle_next; /* next element */ \
365 struct type **cle_prev; /* address of previous next element */ \
368 #define CK_LIST_FIRST(head) ck_pr_load_ptr(&(head)->clh_first)
369 #define CK_LIST_EMPTY(head) (CK_LIST_FIRST(head) == NULL)
370 #define CK_LIST_NEXT(elm, field) ck_pr_load_ptr(&(elm)->field.cle_next)
372 #define CK_LIST_FOREACH(var, head, field) \
373 for ((var) = CK_LIST_FIRST((head)); \
374 (var) && (ck_pr_fence_load(), 1); \
375 (var) = CK_LIST_NEXT((var), field))
377 #define CK_LIST_FOREACH_SAFE(var, head, field, tvar) \
378 for ((var) = CK_LIST_FIRST((head)); \
379 (var) && (ck_pr_fence_load(), (tvar) = CK_LIST_NEXT((var), field), 1);\
382 #define CK_LIST_INIT(head) do { \
383 ck_pr_store_ptr(&(head)->clh_first, NULL); \
384 ck_pr_fence_store(); \
387 #define CK_LIST_INSERT_AFTER(listelm, elm, field) do { \
388 (elm)->field.cle_next = (listelm)->field.cle_next; \
389 (elm)->field.cle_prev = &(listelm)->field.cle_next; \
390 ck_pr_fence_store(); \
391 if ((listelm)->field.cle_next != NULL) \
392 (listelm)->field.cle_next->field.cle_prev = &(elm)->field.cle_next;\
393 ck_pr_store_ptr(&(listelm)->field.cle_next, elm); \
396 #define CK_LIST_INSERT_BEFORE(listelm, elm, field) do { \
397 (elm)->field.cle_prev = (listelm)->field.cle_prev; \
398 (elm)->field.cle_next = (listelm); \
399 ck_pr_fence_store(); \
400 ck_pr_store_ptr((listelm)->field.cle_prev, (elm)); \
401 (listelm)->field.cle_prev = &(elm)->field.cle_next; \
404 #define CK_LIST_INSERT_HEAD(head, elm, field) do { \
405 (elm)->field.cle_next = (head)->clh_first; \
406 ck_pr_fence_store(); \
407 if ((elm)->field.cle_next != NULL) \
408 (head)->clh_first->field.cle_prev = &(elm)->field.cle_next; \
409 ck_pr_store_ptr(&(head)->clh_first, elm); \
410 (elm)->field.cle_prev = &(head)->clh_first; \
413 #define CK_LIST_REMOVE(elm, field) do { \
414 ck_pr_store_ptr((elm)->field.cle_prev, (elm)->field.cle_next); \
415 if ((elm)->field.cle_next != NULL) \
416 (elm)->field.cle_next->field.cle_prev = (elm)->field.cle_prev; \
419 #define CK_LIST_MOVE(head1, head2, field) do { \
420 ck_pr_store_ptr(&(head1)->clh_first, (head2)->clh_first); \
421 if ((head1)->clh_first != NULL) \
422 (head1)->clh_first->field.cle_prev = &(head1)->clh_first; \
426 * This operation is not applied atomically.
428 #define CK_LIST_SWAP(head1, head2, type, field) do { \
429 struct type *swap_tmp = (head1)->clh_first; \
430 (head1)->clh_first = (head2)->clh_first; \
431 (head2)->clh_first = swap_tmp; \
432 if ((swap_tmp = (head1)->clh_first) != NULL) \
433 swap_tmp->field.cle_prev = &(head1)->clh_first; \
434 if ((swap_tmp = (head2)->clh_first) != NULL) \
435 swap_tmp->field.cle_prev = &(head2)->clh_first; \
438 #endif /* CK_QUEUE_H */