xref: /f-stack/freebsd/contrib/ck/include/ck_queue.h (revision 22ce4aff)
1*22ce4affSfengbojiang /*
2*22ce4affSfengbojiang  * Copyright 2012-2015 Samy Al Bahra.
3*22ce4affSfengbojiang  * All rights reserved.
4*22ce4affSfengbojiang  *
5*22ce4affSfengbojiang  * Redistribution and use in source and binary forms, with or without
6*22ce4affSfengbojiang  * modification, are permitted provided that the following conditions
7*22ce4affSfengbojiang  * are met:
8*22ce4affSfengbojiang  * 1. Redistributions of source code must retain the above copyright
9*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer.
10*22ce4affSfengbojiang  * 2. Redistributions in binary form must reproduce the above copyright
11*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer in the
12*22ce4affSfengbojiang  *    documentation and/or other materials provided with the distribution.
13*22ce4affSfengbojiang  *
14*22ce4affSfengbojiang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*22ce4affSfengbojiang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*22ce4affSfengbojiang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*22ce4affSfengbojiang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*22ce4affSfengbojiang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*22ce4affSfengbojiang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*22ce4affSfengbojiang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*22ce4affSfengbojiang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*22ce4affSfengbojiang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*22ce4affSfengbojiang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*22ce4affSfengbojiang  * SUCH DAMAGE.
25*22ce4affSfengbojiang  */
26*22ce4affSfengbojiang 
27*22ce4affSfengbojiang /*-
28*22ce4affSfengbojiang  * Copyright (c) 1991, 1993
29*22ce4affSfengbojiang  *	The Regents of the University of California.  All rights reserved.
30*22ce4affSfengbojiang  *
31*22ce4affSfengbojiang  * Redistribution and use in source and binary forms, with or without
32*22ce4affSfengbojiang  * modification, are permitted provided that the following conditions
33*22ce4affSfengbojiang  * are met:
34*22ce4affSfengbojiang  * 1. Redistributions of source code must retain the above copyright
35*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer.
36*22ce4affSfengbojiang  * 2. Redistributions in binary form must reproduce the above copyright
37*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer in the
38*22ce4affSfengbojiang  *    documentation and/or other materials provided with the distribution.
39*22ce4affSfengbojiang  * 4. Neither the name of the University nor the names of its contributors
40*22ce4affSfengbojiang  *    may be used to endorse or promote products derived from this software
41*22ce4affSfengbojiang  *    without specific prior written permission.
42*22ce4affSfengbojiang  *
43*22ce4affSfengbojiang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44*22ce4affSfengbojiang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45*22ce4affSfengbojiang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46*22ce4affSfengbojiang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47*22ce4affSfengbojiang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48*22ce4affSfengbojiang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49*22ce4affSfengbojiang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50*22ce4affSfengbojiang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51*22ce4affSfengbojiang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52*22ce4affSfengbojiang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53*22ce4affSfengbojiang  * SUCH DAMAGE.
54*22ce4affSfengbojiang  *
55*22ce4affSfengbojiang  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
56*22ce4affSfengbojiang  * $FreeBSD$
57*22ce4affSfengbojiang  */
58*22ce4affSfengbojiang 
59*22ce4affSfengbojiang #ifndef CK_QUEUE_H
60*22ce4affSfengbojiang #define	CK_QUEUE_H
61*22ce4affSfengbojiang 
62*22ce4affSfengbojiang #include <ck_pr.h>
63*22ce4affSfengbojiang 
64*22ce4affSfengbojiang /*
65*22ce4affSfengbojiang  * This file defines three types of data structures: singly-linked lists,
66*22ce4affSfengbojiang  * singly-linked tail queues and lists.
67*22ce4affSfengbojiang  *
68*22ce4affSfengbojiang  * A singly-linked list is headed by a single forward pointer. The elements
69*22ce4affSfengbojiang  * are singly linked for minimum space and pointer manipulation overhead at
70*22ce4affSfengbojiang  * the expense of O(n) removal for arbitrary elements. New elements can be
71*22ce4affSfengbojiang  * added to the list after an existing element or at the head of the list.
72*22ce4affSfengbojiang  * Elements being removed from the head of the list should use the explicit
73*22ce4affSfengbojiang  * macro for this purpose for optimum efficiency. A singly-linked list may
74*22ce4affSfengbojiang  * only be traversed in the forward direction.  Singly-linked lists are ideal
75*22ce4affSfengbojiang  * for applications with large datasets and few or no removals or for
76*22ce4affSfengbojiang  * implementing a LIFO queue.
77*22ce4affSfengbojiang  *
78*22ce4affSfengbojiang  * A singly-linked tail queue is headed by a pair of pointers, one to the
79*22ce4affSfengbojiang  * head of the list and the other to the tail of the list. The elements are
80*22ce4affSfengbojiang  * singly linked for minimum space and pointer manipulation overhead at the
81*22ce4affSfengbojiang  * expense of O(n) removal for arbitrary elements. New elements can be added
82*22ce4affSfengbojiang  * to the list after an existing element, at the head of the list, or at the
83*22ce4affSfengbojiang  * end of the list. Elements being removed from the head of the tail queue
84*22ce4affSfengbojiang  * should use the explicit macro for this purpose for optimum efficiency.
85*22ce4affSfengbojiang  * A singly-linked tail queue may only be traversed in the forward direction.
86*22ce4affSfengbojiang  * Singly-linked tail queues are ideal for applications with large datasets
87*22ce4affSfengbojiang  * and few or no removals or for implementing a FIFO queue.
88*22ce4affSfengbojiang  *
89*22ce4affSfengbojiang  * A list is headed by a single forward pointer (or an array of forward
90*22ce4affSfengbojiang  * pointers for a hash table header). The elements are doubly linked
91*22ce4affSfengbojiang  * so that an arbitrary element can be removed without a need to
92*22ce4affSfengbojiang  * traverse the list. New elements can be added to the list before
93*22ce4affSfengbojiang  * or after an existing element or at the head of the list. A list
94*22ce4affSfengbojiang  * may only be traversed in the forward direction.
95*22ce4affSfengbojiang  *
96*22ce4affSfengbojiang  * It is safe to use _FOREACH/_FOREACH_SAFE in the presence of concurrent
97*22ce4affSfengbojiang  * modifications to the list. Writers to these lists must, on the other hand,
98*22ce4affSfengbojiang  * implement writer-side synchronization. The _SWAP operations are not atomic.
99*22ce4affSfengbojiang  * This facility is currently unsupported on architectures such as the Alpha
100*22ce4affSfengbojiang  * which require load-depend memory fences.
101*22ce4affSfengbojiang  *
102*22ce4affSfengbojiang  *				CK_SLIST	CK_LIST	CK_STAILQ
103*22ce4affSfengbojiang  * _HEAD			+		+	+
104*22ce4affSfengbojiang  * _HEAD_INITIALIZER		+		+	+
105*22ce4affSfengbojiang  * _ENTRY			+		+	+
106*22ce4affSfengbojiang  * _INIT			+		+	+
107*22ce4affSfengbojiang  * _EMPTY			+		+	+
108*22ce4affSfengbojiang  * _FIRST			+		+	+
109*22ce4affSfengbojiang  * _NEXT			+		+	+
110*22ce4affSfengbojiang  * _FOREACH			+		+	+
111*22ce4affSfengbojiang  * _FOREACH_SAFE		+		+	+
112*22ce4affSfengbojiang  * _INSERT_HEAD			+		+	+
113*22ce4affSfengbojiang  * _INSERT_BEFORE		-		+	-
114*22ce4affSfengbojiang  * _INSERT_AFTER		+		+	+
115*22ce4affSfengbojiang  * _INSERT_TAIL			-		-	+
116*22ce4affSfengbojiang  * _REMOVE_AFTER		+		-	+
117*22ce4affSfengbojiang  * _REMOVE_HEAD			+		-	+
118*22ce4affSfengbojiang  * _REMOVE			+		+	+
119*22ce4affSfengbojiang  * _SWAP			+		+	+
120*22ce4affSfengbojiang  * _MOVE			+		+	+
121*22ce4affSfengbojiang  */
122*22ce4affSfengbojiang 
123*22ce4affSfengbojiang /*
124*22ce4affSfengbojiang  * Singly-linked List declarations.
125*22ce4affSfengbojiang  */
126*22ce4affSfengbojiang #define	CK_SLIST_HEAD(name, type)						\
127*22ce4affSfengbojiang struct name {									\
128*22ce4affSfengbojiang 	struct type *cslh_first;	/* first element */				\
129*22ce4affSfengbojiang }
130*22ce4affSfengbojiang 
131*22ce4affSfengbojiang #define	CK_SLIST_HEAD_INITIALIZER(head)						\
132*22ce4affSfengbojiang 	{ NULL }
133*22ce4affSfengbojiang 
134*22ce4affSfengbojiang #define	CK_SLIST_ENTRY(type)							\
135*22ce4affSfengbojiang struct {									\
136*22ce4affSfengbojiang 	struct type *csle_next;	/* next element */				\
137*22ce4affSfengbojiang }
138*22ce4affSfengbojiang 
139*22ce4affSfengbojiang /*
140*22ce4affSfengbojiang  * Singly-linked List functions.
141*22ce4affSfengbojiang  */
142*22ce4affSfengbojiang #define	CK_SLIST_EMPTY(head)							\
143*22ce4affSfengbojiang 	(ck_pr_load_ptr(&(head)->cslh_first) == NULL)
144*22ce4affSfengbojiang 
145*22ce4affSfengbojiang #define	CK_SLIST_FIRST(head)							\
146*22ce4affSfengbojiang 	(ck_pr_load_ptr(&(head)->cslh_first))
147*22ce4affSfengbojiang 
148*22ce4affSfengbojiang #define	CK_SLIST_NEXT(elm, field)						\
149*22ce4affSfengbojiang 	ck_pr_load_ptr(&((elm)->field.csle_next))
150*22ce4affSfengbojiang 
151*22ce4affSfengbojiang #define	CK_SLIST_FOREACH(var, head, field)					\
152*22ce4affSfengbojiang 	for ((var) = CK_SLIST_FIRST((head));					\
153*22ce4affSfengbojiang 	    (var) && (ck_pr_fence_load(), 1);					\
154*22ce4affSfengbojiang 	    (var) = CK_SLIST_NEXT((var), field))
155*22ce4affSfengbojiang 
156*22ce4affSfengbojiang #define	CK_SLIST_FOREACH_SAFE(var, head, field, tvar)				 \
157*22ce4affSfengbojiang 	for ((var) = CK_SLIST_FIRST(head);					 \
158*22ce4affSfengbojiang 	    (var) && (ck_pr_fence_load(), (tvar) = CK_SLIST_NEXT(var, field), 1);\
159*22ce4affSfengbojiang 	    (var) = (tvar))
160*22ce4affSfengbojiang 
161*22ce4affSfengbojiang #define	CK_SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
162*22ce4affSfengbojiang 	for ((varp) = &(head)->cslh_first;					\
163*22ce4affSfengbojiang 	    ((var) = ck_pr_load_ptr(varp)) != NULL && (ck_pr_fence_load(), 1);	\
164*22ce4affSfengbojiang 	    (varp) = &(var)->field.csle_next)
165*22ce4affSfengbojiang 
166*22ce4affSfengbojiang #define	CK_SLIST_INIT(head) do {						\
167*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cslh_first, NULL);				\
168*22ce4affSfengbojiang 	ck_pr_fence_store();							\
169*22ce4affSfengbojiang } while (0)
170*22ce4affSfengbojiang 
171*22ce4affSfengbojiang #define	CK_SLIST_INSERT_AFTER(a, b, field) do {					\
172*22ce4affSfengbojiang 	(b)->field.csle_next = (a)->field.csle_next;				\
173*22ce4affSfengbojiang 	ck_pr_fence_store();							\
174*22ce4affSfengbojiang 	ck_pr_store_ptr(&(a)->field.csle_next, b);				\
175*22ce4affSfengbojiang } while (0)
176*22ce4affSfengbojiang 
177*22ce4affSfengbojiang #define	CK_SLIST_INSERT_HEAD(head, elm, field) do {				\
178*22ce4affSfengbojiang 	(elm)->field.csle_next = (head)->cslh_first;				\
179*22ce4affSfengbojiang 	ck_pr_fence_store();							\
180*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cslh_first, elm);				\
181*22ce4affSfengbojiang } while (0)
182*22ce4affSfengbojiang 
183*22ce4affSfengbojiang #define	CK_SLIST_INSERT_PREVPTR(prevp, slistelm, elm, field) do {		\
184*22ce4affSfengbojiang 	(elm)->field.csle_next = (slistelm);					\
185*22ce4affSfengbojiang 	ck_pr_fence_store();							\
186*22ce4affSfengbojiang 	ck_pr_store_ptr(prevp, elm);						\
187*22ce4affSfengbojiang } while (0)
188*22ce4affSfengbojiang 
189*22ce4affSfengbojiang #define CK_SLIST_REMOVE_AFTER(elm, field) do {					\
190*22ce4affSfengbojiang 	ck_pr_store_ptr(&(elm)->field.csle_next,				\
191*22ce4affSfengbojiang 	    (elm)->field.csle_next->field.csle_next);				\
192*22ce4affSfengbojiang } while (0)
193*22ce4affSfengbojiang 
194*22ce4affSfengbojiang #define	CK_SLIST_REMOVE(head, elm, type, field) do {				\
195*22ce4affSfengbojiang 	if ((head)->cslh_first == (elm)) {					\
196*22ce4affSfengbojiang 		CK_SLIST_REMOVE_HEAD((head), field);				\
197*22ce4affSfengbojiang 	} else {								\
198*22ce4affSfengbojiang 		struct type *curelm = (head)->cslh_first;			\
199*22ce4affSfengbojiang 		while (curelm->field.csle_next != (elm))			\
200*22ce4affSfengbojiang 			curelm = curelm->field.csle_next;			\
201*22ce4affSfengbojiang 		CK_SLIST_REMOVE_AFTER(curelm, field);				\
202*22ce4affSfengbojiang 	}									\
203*22ce4affSfengbojiang } while (0)
204*22ce4affSfengbojiang 
205*22ce4affSfengbojiang #define	CK_SLIST_REMOVE_HEAD(head, field) do {					\
206*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cslh_first,					\
207*22ce4affSfengbojiang 		(head)->cslh_first->field.csle_next);				\
208*22ce4affSfengbojiang } while (0)
209*22ce4affSfengbojiang 
210*22ce4affSfengbojiang #define CK_SLIST_REMOVE_PREVPTR(prevp, elm, field) do {				\
211*22ce4affSfengbojiang 	ck_pr_store_ptr(prevptr, (elm)->field.csle_next);			\
212*22ce4affSfengbojiang } while (0)
213*22ce4affSfengbojiang 
214*22ce4affSfengbojiang #define CK_SLIST_MOVE(head1, head2, field) do {					\
215*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head1)->cslh_first, (head2)->cslh_first);		\
216*22ce4affSfengbojiang } while (0)
217*22ce4affSfengbojiang 
218*22ce4affSfengbojiang /*
219*22ce4affSfengbojiang  * This operation is not applied atomically.
220*22ce4affSfengbojiang  */
221*22ce4affSfengbojiang #define CK_SLIST_SWAP(a, b, type) do {						\
222*22ce4affSfengbojiang 	struct type *swap_first = (a)->cslh_first;				\
223*22ce4affSfengbojiang 	(a)->cslh_first = (b)->cslh_first;					\
224*22ce4affSfengbojiang 	(b)->cslh_first = swap_first;						\
225*22ce4affSfengbojiang } while (0)
226*22ce4affSfengbojiang 
227*22ce4affSfengbojiang /*
228*22ce4affSfengbojiang  * Singly-linked Tail queue declarations.
229*22ce4affSfengbojiang  */
230*22ce4affSfengbojiang #define	CK_STAILQ_HEAD(name, type)					\
231*22ce4affSfengbojiang struct name {								\
232*22ce4affSfengbojiang 	struct type *cstqh_first;/* first element */			\
233*22ce4affSfengbojiang 	struct type **cstqh_last;/* addr of last next element */		\
234*22ce4affSfengbojiang }
235*22ce4affSfengbojiang 
236*22ce4affSfengbojiang #define	CK_STAILQ_HEAD_INITIALIZER(head)				\
237*22ce4affSfengbojiang 	{ NULL, &(head).cstqh_first }
238*22ce4affSfengbojiang 
239*22ce4affSfengbojiang #define	CK_STAILQ_ENTRY(type)						\
240*22ce4affSfengbojiang struct {								\
241*22ce4affSfengbojiang 	struct type *cstqe_next;	/* next element */			\
242*22ce4affSfengbojiang }
243*22ce4affSfengbojiang 
244*22ce4affSfengbojiang /*
245*22ce4affSfengbojiang  * Singly-linked Tail queue functions.
246*22ce4affSfengbojiang  */
247*22ce4affSfengbojiang #define	CK_STAILQ_CONCAT(head1, head2) do {					\
248*22ce4affSfengbojiang 	if ((head2)->cstqh_first != NULL) {					\
249*22ce4affSfengbojiang 		ck_pr_store_ptr((head1)->cstqh_last, (head2)->cstqh_first);	\
250*22ce4affSfengbojiang 		ck_pr_fence_store();						\
251*22ce4affSfengbojiang 		(head1)->cstqh_last = (head2)->cstqh_last;			\
252*22ce4affSfengbojiang 		CK_STAILQ_INIT((head2));					\
253*22ce4affSfengbojiang 	}									\
254*22ce4affSfengbojiang } while (0)
255*22ce4affSfengbojiang 
256*22ce4affSfengbojiang #define	CK_STAILQ_EMPTY(head)	(ck_pr_load_ptr(&(head)->cstqh_first) == NULL)
257*22ce4affSfengbojiang 
258*22ce4affSfengbojiang #define	CK_STAILQ_FIRST(head)	(ck_pr_load_ptr(&(head)->cstqh_first))
259*22ce4affSfengbojiang 
260*22ce4affSfengbojiang #define	CK_STAILQ_FOREACH(var, head, field)				\
261*22ce4affSfengbojiang 	for((var) = CK_STAILQ_FIRST((head));				\
262*22ce4affSfengbojiang 	   (var) && (ck_pr_fence_load(), 1);				\
263*22ce4affSfengbojiang 	   (var) = CK_STAILQ_NEXT((var), field))
264*22ce4affSfengbojiang 
265*22ce4affSfengbojiang #define	CK_STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
266*22ce4affSfengbojiang 	for ((var) = CK_STAILQ_FIRST((head));				\
267*22ce4affSfengbojiang 	    (var) && (ck_pr_fence_load(), (tvar) =			\
268*22ce4affSfengbojiang 		CK_STAILQ_NEXT((var), field), 1);			\
269*22ce4affSfengbojiang 	    (var) = (tvar))
270*22ce4affSfengbojiang 
271*22ce4affSfengbojiang #define	CK_STAILQ_INIT(head) do {					\
272*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cstqh_first, NULL);			\
273*22ce4affSfengbojiang 	ck_pr_fence_store();						\
274*22ce4affSfengbojiang 	(head)->cstqh_last = &(head)->cstqh_first;			\
275*22ce4affSfengbojiang } while (0)
276*22ce4affSfengbojiang 
277*22ce4affSfengbojiang #define	CK_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {			\
278*22ce4affSfengbojiang 	(elm)->field.cstqe_next = (tqelm)->field.cstqe_next;			\
279*22ce4affSfengbojiang 	ck_pr_fence_store();							\
280*22ce4affSfengbojiang 	ck_pr_store_ptr(&(tqelm)->field.cstqe_next, elm);			\
281*22ce4affSfengbojiang 	if ((elm)->field.cstqe_next == NULL)					\
282*22ce4affSfengbojiang 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
283*22ce4affSfengbojiang } while (0)
284*22ce4affSfengbojiang 
285*22ce4affSfengbojiang #define	CK_STAILQ_INSERT_HEAD(head, elm, field) do {				\
286*22ce4affSfengbojiang 	(elm)->field.cstqe_next = (head)->cstqh_first;				\
287*22ce4affSfengbojiang 	ck_pr_fence_store();							\
288*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cstqh_first, elm);				\
289*22ce4affSfengbojiang 	if ((elm)->field.cstqe_next == NULL)					\
290*22ce4affSfengbojiang 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
291*22ce4affSfengbojiang } while (0)
292*22ce4affSfengbojiang 
293*22ce4affSfengbojiang #define	CK_STAILQ_INSERT_TAIL(head, elm, field) do {				\
294*22ce4affSfengbojiang 	(elm)->field.cstqe_next = NULL;						\
295*22ce4affSfengbojiang 	ck_pr_fence_store();							\
296*22ce4affSfengbojiang 	ck_pr_store_ptr((head)->cstqh_last, (elm));				\
297*22ce4affSfengbojiang 	(head)->cstqh_last = &(elm)->field.cstqe_next;				\
298*22ce4affSfengbojiang } while (0)
299*22ce4affSfengbojiang 
300*22ce4affSfengbojiang #define	CK_STAILQ_NEXT(elm, field)						\
301*22ce4affSfengbojiang 	(ck_pr_load_ptr(&(elm)->field.cstqe_next))
302*22ce4affSfengbojiang 
303*22ce4affSfengbojiang #define	CK_STAILQ_REMOVE(head, elm, type, field) do {				\
304*22ce4affSfengbojiang 	if ((head)->cstqh_first == (elm)) {					\
305*22ce4affSfengbojiang 		CK_STAILQ_REMOVE_HEAD((head), field);				\
306*22ce4affSfengbojiang 	} else {								\
307*22ce4affSfengbojiang 		struct type *curelm = (head)->cstqh_first;			\
308*22ce4affSfengbojiang 		while (curelm->field.cstqe_next != (elm))			\
309*22ce4affSfengbojiang 			curelm = curelm->field.cstqe_next;			\
310*22ce4affSfengbojiang 		CK_STAILQ_REMOVE_AFTER(head, curelm, field);			\
311*22ce4affSfengbojiang 	}									\
312*22ce4affSfengbojiang } while (0)
313*22ce4affSfengbojiang 
314*22ce4affSfengbojiang #define CK_STAILQ_REMOVE_AFTER(head, elm, field) do {				\
315*22ce4affSfengbojiang 	ck_pr_store_ptr(&(elm)->field.cstqe_next,				\
316*22ce4affSfengbojiang 	    (elm)->field.cstqe_next->field.cstqe_next);				\
317*22ce4affSfengbojiang 	if ((elm)->field.cstqe_next == NULL)					\
318*22ce4affSfengbojiang 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
319*22ce4affSfengbojiang } while (0)
320*22ce4affSfengbojiang 
321*22ce4affSfengbojiang #define	CK_STAILQ_REMOVE_HEAD(head, field) do {					\
322*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->cstqh_first,					\
323*22ce4affSfengbojiang 	    (head)->cstqh_first->field.cstqe_next);				\
324*22ce4affSfengbojiang 	if ((head)->cstqh_first == NULL)						\
325*22ce4affSfengbojiang 		(head)->cstqh_last = &(head)->cstqh_first;			\
326*22ce4affSfengbojiang } while (0)
327*22ce4affSfengbojiang 
328*22ce4affSfengbojiang #define CK_STAILQ_MOVE(head1, head2, field) do {				\
329*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head1)->cstqh_first, (head2)->cstqh_first);		\
330*22ce4affSfengbojiang 	(head1)->cstqh_last = (head2)->cstqh_last;				\
331*22ce4affSfengbojiang 	if ((head2)->cstqh_last == &(head2)->cstqh_first)				\
332*22ce4affSfengbojiang 		(head1)->cstqh_last = &(head1)->cstqh_first;			\
333*22ce4affSfengbojiang } while (0)
334*22ce4affSfengbojiang 
335*22ce4affSfengbojiang /*
336*22ce4affSfengbojiang  * This operation is not applied atomically.
337*22ce4affSfengbojiang  */
338*22ce4affSfengbojiang #define CK_STAILQ_SWAP(head1, head2, type) do {				\
339*22ce4affSfengbojiang 	struct type *swap_first = CK_STAILQ_FIRST(head1);		\
340*22ce4affSfengbojiang 	struct type **swap_last = (head1)->cstqh_last;			\
341*22ce4affSfengbojiang 	CK_STAILQ_FIRST(head1) = CK_STAILQ_FIRST(head2);		\
342*22ce4affSfengbojiang 	(head1)->cstqh_last = (head2)->cstqh_last;			\
343*22ce4affSfengbojiang 	CK_STAILQ_FIRST(head2) = swap_first;				\
344*22ce4affSfengbojiang 	(head2)->cstqh_last = swap_last;					\
345*22ce4affSfengbojiang 	if (CK_STAILQ_EMPTY(head1))					\
346*22ce4affSfengbojiang 		(head1)->cstqh_last = &(head1)->cstqh_first;		\
347*22ce4affSfengbojiang 	if (CK_STAILQ_EMPTY(head2))					\
348*22ce4affSfengbojiang 		(head2)->cstqh_last = &(head2)->cstqh_first;		\
349*22ce4affSfengbojiang } while (0)
350*22ce4affSfengbojiang 
351*22ce4affSfengbojiang /*
352*22ce4affSfengbojiang  * List declarations.
353*22ce4affSfengbojiang  */
354*22ce4affSfengbojiang #define	CK_LIST_HEAD(name, type)						\
355*22ce4affSfengbojiang struct name {									\
356*22ce4affSfengbojiang 	struct type *clh_first;	/* first element */				\
357*22ce4affSfengbojiang }
358*22ce4affSfengbojiang 
359*22ce4affSfengbojiang #define	CK_LIST_HEAD_INITIALIZER(head)						\
360*22ce4affSfengbojiang 	{ NULL }
361*22ce4affSfengbojiang 
362*22ce4affSfengbojiang #define	CK_LIST_ENTRY(type)							\
363*22ce4affSfengbojiang struct {									\
364*22ce4affSfengbojiang 	struct type *cle_next;	/* next element */				\
365*22ce4affSfengbojiang 	struct type **cle_prev;	/* address of previous next element */		\
366*22ce4affSfengbojiang }
367*22ce4affSfengbojiang 
368*22ce4affSfengbojiang #define	CK_LIST_FIRST(head)		ck_pr_load_ptr(&(head)->clh_first)
369*22ce4affSfengbojiang #define	CK_LIST_EMPTY(head)		(CK_LIST_FIRST(head) == NULL)
370*22ce4affSfengbojiang #define	CK_LIST_NEXT(elm, field)	ck_pr_load_ptr(&(elm)->field.cle_next)
371*22ce4affSfengbojiang 
372*22ce4affSfengbojiang #define	CK_LIST_FOREACH(var, head, field)					\
373*22ce4affSfengbojiang 	for ((var) = CK_LIST_FIRST((head));					\
374*22ce4affSfengbojiang 	    (var) && (ck_pr_fence_load(), 1);					\
375*22ce4affSfengbojiang 	    (var) = CK_LIST_NEXT((var), field))
376*22ce4affSfengbojiang 
377*22ce4affSfengbojiang #define	CK_LIST_FOREACH_SAFE(var, head, field, tvar)				  \
378*22ce4affSfengbojiang 	for ((var) = CK_LIST_FIRST((head));					  \
379*22ce4affSfengbojiang 	    (var) && (ck_pr_fence_load(), (tvar) = CK_LIST_NEXT((var), field), 1);\
380*22ce4affSfengbojiang 	    (var) = (tvar))
381*22ce4affSfengbojiang 
382*22ce4affSfengbojiang #define	CK_LIST_INIT(head) do {							\
383*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->clh_first, NULL);				\
384*22ce4affSfengbojiang 	ck_pr_fence_store();							\
385*22ce4affSfengbojiang } while (0)
386*22ce4affSfengbojiang 
387*22ce4affSfengbojiang #define	CK_LIST_INSERT_AFTER(listelm, elm, field) do {				\
388*22ce4affSfengbojiang 	(elm)->field.cle_next = (listelm)->field.cle_next;			\
389*22ce4affSfengbojiang 	(elm)->field.cle_prev = &(listelm)->field.cle_next;			\
390*22ce4affSfengbojiang 	ck_pr_fence_store();							\
391*22ce4affSfengbojiang 	if ((listelm)->field.cle_next != NULL)					\
392*22ce4affSfengbojiang 		(listelm)->field.cle_next->field.cle_prev = &(elm)->field.cle_next;\
393*22ce4affSfengbojiang 	ck_pr_store_ptr(&(listelm)->field.cle_next, elm);			\
394*22ce4affSfengbojiang } while (0)
395*22ce4affSfengbojiang 
396*22ce4affSfengbojiang #define	CK_LIST_INSERT_BEFORE(listelm, elm, field) do {				\
397*22ce4affSfengbojiang 	(elm)->field.cle_prev = (listelm)->field.cle_prev;			\
398*22ce4affSfengbojiang 	(elm)->field.cle_next = (listelm);					\
399*22ce4affSfengbojiang 	ck_pr_fence_store();							\
400*22ce4affSfengbojiang 	ck_pr_store_ptr((listelm)->field.cle_prev, (elm));			\
401*22ce4affSfengbojiang 	(listelm)->field.cle_prev = &(elm)->field.cle_next;			\
402*22ce4affSfengbojiang } while (0)
403*22ce4affSfengbojiang 
404*22ce4affSfengbojiang #define	CK_LIST_INSERT_HEAD(head, elm, field) do {				\
405*22ce4affSfengbojiang 	(elm)->field.cle_next = (head)->clh_first;				\
406*22ce4affSfengbojiang 	ck_pr_fence_store();							\
407*22ce4affSfengbojiang 	if ((elm)->field.cle_next != NULL)					\
408*22ce4affSfengbojiang 		(head)->clh_first->field.cle_prev =  &(elm)->field.cle_next;	\
409*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head)->clh_first, elm);				\
410*22ce4affSfengbojiang 	(elm)->field.cle_prev = &(head)->clh_first;				\
411*22ce4affSfengbojiang } while (0)
412*22ce4affSfengbojiang 
413*22ce4affSfengbojiang #define	CK_LIST_REMOVE(elm, field) do {						\
414*22ce4affSfengbojiang 	ck_pr_store_ptr((elm)->field.cle_prev, (elm)->field.cle_next);		\
415*22ce4affSfengbojiang 	if ((elm)->field.cle_next != NULL)					\
416*22ce4affSfengbojiang 		(elm)->field.cle_next->field.cle_prev = (elm)->field.cle_prev;	\
417*22ce4affSfengbojiang } while (0)
418*22ce4affSfengbojiang 
419*22ce4affSfengbojiang #define CK_LIST_MOVE(head1, head2, field) do {				\
420*22ce4affSfengbojiang 	ck_pr_store_ptr(&(head1)->clh_first, (head2)->clh_first);		\
421*22ce4affSfengbojiang 	if ((head1)->clh_first != NULL)					\
422*22ce4affSfengbojiang 		(head1)->clh_first->field.cle_prev = &(head1)->clh_first;	\
423*22ce4affSfengbojiang } while (0)
424*22ce4affSfengbojiang 
425*22ce4affSfengbojiang /*
426*22ce4affSfengbojiang  * This operation is not applied atomically.
427*22ce4affSfengbojiang  */
428*22ce4affSfengbojiang #define CK_LIST_SWAP(head1, head2, type, field) do {			\
429*22ce4affSfengbojiang 	struct type *swap_tmp = (head1)->clh_first;			\
430*22ce4affSfengbojiang 	(head1)->clh_first = (head2)->clh_first;				\
431*22ce4affSfengbojiang 	(head2)->clh_first = swap_tmp;					\
432*22ce4affSfengbojiang 	if ((swap_tmp = (head1)->clh_first) != NULL)			\
433*22ce4affSfengbojiang 		swap_tmp->field.cle_prev = &(head1)->clh_first;		\
434*22ce4affSfengbojiang 	if ((swap_tmp = (head2)->clh_first) != NULL)			\
435*22ce4affSfengbojiang 		swap_tmp->field.cle_prev = &(head2)->clh_first;		\
436*22ce4affSfengbojiang } while (0)
437*22ce4affSfengbojiang 
438*22ce4affSfengbojiang #endif /* CK_QUEUE_H */
439