xref: /freebsd/sys/contrib/ck/include/ck_queue.h (revision 6f48a4acbeb86ebbef90290ad73ea6be83507aa9)
11fb62fb0SOlivier Houchard /*
21fb62fb0SOlivier Houchard  * Copyright 2012-2015 Samy Al Bahra.
31fb62fb0SOlivier Houchard  * All rights reserved.
41fb62fb0SOlivier Houchard  *
51fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
61fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
71fb62fb0SOlivier Houchard  * are met:
81fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
91fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
101fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
111fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
121fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
131fb62fb0SOlivier Houchard  *
141fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241fb62fb0SOlivier Houchard  * SUCH DAMAGE.
251fb62fb0SOlivier Houchard  */
261fb62fb0SOlivier Houchard 
271fb62fb0SOlivier Houchard /*-
281fb62fb0SOlivier Houchard  * Copyright (c) 1991, 1993
291fb62fb0SOlivier Houchard  *	The Regents of the University of California.  All rights reserved.
301fb62fb0SOlivier Houchard  *
311fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
321fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
331fb62fb0SOlivier Houchard  * are met:
341fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
351fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
361fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
371fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
381fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
391fb62fb0SOlivier Houchard  * 4. Neither the name of the University nor the names of its contributors
401fb62fb0SOlivier Houchard  *    may be used to endorse or promote products derived from this software
411fb62fb0SOlivier Houchard  *    without specific prior written permission.
421fb62fb0SOlivier Houchard  *
431fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
441fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
451fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
461fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
471fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
481fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
491fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
501fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
511fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
521fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
531fb62fb0SOlivier Houchard  * SUCH DAMAGE.
541fb62fb0SOlivier Houchard  *
551fb62fb0SOlivier Houchard  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
5674e9b5f2SOlivier Houchard  * $FreeBSD: release/9.0.0/sys/sys/queue.h 221843 2011-05-13 15:49:23Z mdf $
571fb62fb0SOlivier Houchard  */
581fb62fb0SOlivier Houchard 
591fb62fb0SOlivier Houchard #ifndef CK_QUEUE_H
601fb62fb0SOlivier Houchard #define	CK_QUEUE_H
611fb62fb0SOlivier Houchard 
621fb62fb0SOlivier Houchard #include <ck_pr.h>
631fb62fb0SOlivier Houchard 
641fb62fb0SOlivier Houchard /*
651fb62fb0SOlivier Houchard  * This file defines three types of data structures: singly-linked lists,
661fb62fb0SOlivier Houchard  * singly-linked tail queues and lists.
671fb62fb0SOlivier Houchard  *
681fb62fb0SOlivier Houchard  * A singly-linked list is headed by a single forward pointer. The elements
691fb62fb0SOlivier Houchard  * are singly linked for minimum space and pointer manipulation overhead at
701fb62fb0SOlivier Houchard  * the expense of O(n) removal for arbitrary elements. New elements can be
711fb62fb0SOlivier Houchard  * added to the list after an existing element or at the head of the list.
721fb62fb0SOlivier Houchard  * Elements being removed from the head of the list should use the explicit
731fb62fb0SOlivier Houchard  * macro for this purpose for optimum efficiency. A singly-linked list may
741fb62fb0SOlivier Houchard  * only be traversed in the forward direction.  Singly-linked lists are ideal
751fb62fb0SOlivier Houchard  * for applications with large datasets and few or no removals or for
761fb62fb0SOlivier Houchard  * implementing a LIFO queue.
771fb62fb0SOlivier Houchard  *
781fb62fb0SOlivier Houchard  * A singly-linked tail queue is headed by a pair of pointers, one to the
791fb62fb0SOlivier Houchard  * head of the list and the other to the tail of the list. The elements are
801fb62fb0SOlivier Houchard  * singly linked for minimum space and pointer manipulation overhead at the
811fb62fb0SOlivier Houchard  * expense of O(n) removal for arbitrary elements. New elements can be added
821fb62fb0SOlivier Houchard  * to the list after an existing element, at the head of the list, or at the
831fb62fb0SOlivier Houchard  * end of the list. Elements being removed from the head of the tail queue
841fb62fb0SOlivier Houchard  * should use the explicit macro for this purpose for optimum efficiency.
851fb62fb0SOlivier Houchard  * A singly-linked tail queue may only be traversed in the forward direction.
861fb62fb0SOlivier Houchard  * Singly-linked tail queues are ideal for applications with large datasets
871fb62fb0SOlivier Houchard  * and few or no removals or for implementing a FIFO queue.
881fb62fb0SOlivier Houchard  *
891fb62fb0SOlivier Houchard  * A list is headed by a single forward pointer (or an array of forward
901fb62fb0SOlivier Houchard  * pointers for a hash table header). The elements are doubly linked
911fb62fb0SOlivier Houchard  * so that an arbitrary element can be removed without a need to
921fb62fb0SOlivier Houchard  * traverse the list. New elements can be added to the list before
931fb62fb0SOlivier Houchard  * or after an existing element or at the head of the list. A list
941fb62fb0SOlivier Houchard  * may only be traversed in the forward direction.
951fb62fb0SOlivier Houchard  *
961fb62fb0SOlivier Houchard  * It is safe to use _FOREACH/_FOREACH_SAFE in the presence of concurrent
971fb62fb0SOlivier Houchard  * modifications to the list. Writers to these lists must, on the other hand,
981fb62fb0SOlivier Houchard  * implement writer-side synchronization. The _SWAP operations are not atomic.
991fb62fb0SOlivier Houchard  * This facility is currently unsupported on architectures such as the Alpha
1001fb62fb0SOlivier Houchard  * which require load-depend memory fences.
1011fb62fb0SOlivier Houchard  *
1021fb62fb0SOlivier Houchard  *				CK_SLIST	CK_LIST	CK_STAILQ
1031fb62fb0SOlivier Houchard  * _HEAD			+		+	+
1041fb62fb0SOlivier Houchard  * _HEAD_INITIALIZER		+		+	+
1051fb62fb0SOlivier Houchard  * _ENTRY			+		+	+
1061fb62fb0SOlivier Houchard  * _INIT			+		+	+
1071fb62fb0SOlivier Houchard  * _EMPTY			+		+	+
1081fb62fb0SOlivier Houchard  * _FIRST			+		+	+
1091fb62fb0SOlivier Houchard  * _NEXT			+		+	+
1101fb62fb0SOlivier Houchard  * _FOREACH			+		+	+
1111fb62fb0SOlivier Houchard  * _FOREACH_SAFE		+		+	+
1121fb62fb0SOlivier Houchard  * _INSERT_HEAD			+		+	+
1131fb62fb0SOlivier Houchard  * _INSERT_BEFORE		-		+	-
1141fb62fb0SOlivier Houchard  * _INSERT_AFTER		+		+	+
1151fb62fb0SOlivier Houchard  * _INSERT_TAIL			-		-	+
1161fb62fb0SOlivier Houchard  * _REMOVE_AFTER		+		-	+
1171fb62fb0SOlivier Houchard  * _REMOVE_HEAD			+		-	+
1181fb62fb0SOlivier Houchard  * _REMOVE			+		+	+
1191fb62fb0SOlivier Houchard  * _SWAP			+		+	+
1201fb62fb0SOlivier Houchard  * _MOVE			+		+	+
1211fb62fb0SOlivier Houchard  */
1221fb62fb0SOlivier Houchard 
1231fb62fb0SOlivier Houchard /*
1241fb62fb0SOlivier Houchard  * Singly-linked List declarations.
1251fb62fb0SOlivier Houchard  */
1261fb62fb0SOlivier Houchard #define	CK_SLIST_HEAD(name, type)						\
1271fb62fb0SOlivier Houchard struct name {									\
128d1f3fb2cSOlivier Houchard 	struct type *cslh_first;	/* first element */				\
1291fb62fb0SOlivier Houchard }
1301fb62fb0SOlivier Houchard 
1311fb62fb0SOlivier Houchard #define	CK_SLIST_HEAD_INITIALIZER(head)						\
1321fb62fb0SOlivier Houchard 	{ NULL }
1331fb62fb0SOlivier Houchard 
1341fb62fb0SOlivier Houchard #define	CK_SLIST_ENTRY(type)							\
1351fb62fb0SOlivier Houchard struct {									\
136d1f3fb2cSOlivier Houchard 	struct type *csle_next;	/* next element */				\
1371fb62fb0SOlivier Houchard }
1381fb62fb0SOlivier Houchard 
1391fb62fb0SOlivier Houchard /*
1401fb62fb0SOlivier Houchard  * Singly-linked List functions.
1411fb62fb0SOlivier Houchard  */
1421fb62fb0SOlivier Houchard #define	CK_SLIST_EMPTY(head)							\
143d1f3fb2cSOlivier Houchard 	(ck_pr_load_ptr(&(head)->cslh_first) == NULL)
1441fb62fb0SOlivier Houchard 
1451fb62fb0SOlivier Houchard #define	CK_SLIST_FIRST(head)							\
146d1f3fb2cSOlivier Houchard 	(ck_pr_load_ptr(&(head)->cslh_first))
1471fb62fb0SOlivier Houchard 
1481fb62fb0SOlivier Houchard #define	CK_SLIST_NEXT(elm, field)						\
149d1f3fb2cSOlivier Houchard 	ck_pr_load_ptr(&((elm)->field.csle_next))
1501fb62fb0SOlivier Houchard 
1511fb62fb0SOlivier Houchard #define	CK_SLIST_FOREACH(var, head, field)					\
1521fb62fb0SOlivier Houchard 	for ((var) = CK_SLIST_FIRST((head));					\
15374e9b5f2SOlivier Houchard 	    (var);								\
1541fb62fb0SOlivier Houchard 	    (var) = CK_SLIST_NEXT((var), field))
1551fb62fb0SOlivier Houchard 
156*6f48a4acSMark Johnston #define	CK_SLIST_FOREACH_FROM(var, head, field)					\
157*6f48a4acSMark Johnston 	for ((var) = ((var) != NULL ? (var) : CK_SLIST_FIRST((head)));		\
158*6f48a4acSMark Johnston 	    (var);								\
159*6f48a4acSMark Johnston 	    (var) = CK_SLIST_NEXT((var), field))
160*6f48a4acSMark Johnston 
1611fb62fb0SOlivier Houchard #define	CK_SLIST_FOREACH_SAFE(var, head, field, tvar)				\
1621fb62fb0SOlivier Houchard 	for ((var) = CK_SLIST_FIRST(head);					\
16374e9b5f2SOlivier Houchard 	    (var) && ((tvar) = CK_SLIST_NEXT(var, field), 1);			\
1641fb62fb0SOlivier Houchard 	    (var) = (tvar))
1651fb62fb0SOlivier Houchard 
1661fb62fb0SOlivier Houchard #define	CK_SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
167d1f3fb2cSOlivier Houchard 	for ((varp) = &(head)->cslh_first;					\
16874e9b5f2SOlivier Houchard 	    ((var) = ck_pr_load_ptr(varp)) != NULL;				\
169d1f3fb2cSOlivier Houchard 	    (varp) = &(var)->field.csle_next)
1701fb62fb0SOlivier Houchard 
1711fb62fb0SOlivier Houchard #define	CK_SLIST_INIT(head) do {						\
172d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cslh_first, NULL);				\
1731fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
1741fb62fb0SOlivier Houchard } while (0)
1751fb62fb0SOlivier Houchard 
1761fb62fb0SOlivier Houchard #define	CK_SLIST_INSERT_AFTER(a, b, field) do {					\
177d1f3fb2cSOlivier Houchard 	(b)->field.csle_next = (a)->field.csle_next;				\
1781fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
179d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(a)->field.csle_next, b);				\
1801fb62fb0SOlivier Houchard } while (0)
1811fb62fb0SOlivier Houchard 
1821fb62fb0SOlivier Houchard #define	CK_SLIST_INSERT_HEAD(head, elm, field) do {				\
183d1f3fb2cSOlivier Houchard 	(elm)->field.csle_next = (head)->cslh_first;				\
1841fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
185d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cslh_first, elm);				\
1861fb62fb0SOlivier Houchard } while (0)
1871fb62fb0SOlivier Houchard 
188725de581SAndriy Gapon #define	CK_SLIST_INSERT_PREVPTR(prevp, slistelm, elm, field) do {		\
189725de581SAndriy Gapon 	(elm)->field.csle_next = (slistelm);					\
190725de581SAndriy Gapon 	ck_pr_fence_store();							\
191725de581SAndriy Gapon 	ck_pr_store_ptr(prevp, elm);						\
192725de581SAndriy Gapon } while (0)
193725de581SAndriy Gapon 
1941fb62fb0SOlivier Houchard #define CK_SLIST_REMOVE_AFTER(elm, field) do {					\
195d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(elm)->field.csle_next,				\
196d1f3fb2cSOlivier Houchard 	    (elm)->field.csle_next->field.csle_next);				\
1971fb62fb0SOlivier Houchard } while (0)
1981fb62fb0SOlivier Houchard 
1991fb62fb0SOlivier Houchard #define	CK_SLIST_REMOVE(head, elm, type, field) do {				\
200d1f3fb2cSOlivier Houchard 	if ((head)->cslh_first == (elm)) {					\
2011fb62fb0SOlivier Houchard 		CK_SLIST_REMOVE_HEAD((head), field);				\
2021fb62fb0SOlivier Houchard 	} else {								\
203d1f3fb2cSOlivier Houchard 		struct type *curelm = (head)->cslh_first;			\
204d1f3fb2cSOlivier Houchard 		while (curelm->field.csle_next != (elm))			\
205d1f3fb2cSOlivier Houchard 			curelm = curelm->field.csle_next;			\
2061fb62fb0SOlivier Houchard 		CK_SLIST_REMOVE_AFTER(curelm, field);				\
2071fb62fb0SOlivier Houchard 	}									\
2081fb62fb0SOlivier Houchard } while (0)
2091fb62fb0SOlivier Houchard 
2101fb62fb0SOlivier Houchard #define	CK_SLIST_REMOVE_HEAD(head, field) do {					\
211d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cslh_first,					\
212d1f3fb2cSOlivier Houchard 		(head)->cslh_first->field.csle_next);				\
2131fb62fb0SOlivier Houchard } while (0)
2141fb62fb0SOlivier Houchard 
215725de581SAndriy Gapon #define CK_SLIST_REMOVE_PREVPTR(prevp, elm, field) do {				\
216725de581SAndriy Gapon 	ck_pr_store_ptr(prevptr, (elm)->field.csle_next);			\
217725de581SAndriy Gapon } while (0)
218725de581SAndriy Gapon 
2191fb62fb0SOlivier Houchard #define CK_SLIST_MOVE(head1, head2, field) do {					\
220d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head1)->cslh_first, (head2)->cslh_first);		\
2211fb62fb0SOlivier Houchard } while (0)
2221fb62fb0SOlivier Houchard 
2231fb62fb0SOlivier Houchard /*
2241fb62fb0SOlivier Houchard  * This operation is not applied atomically.
2251fb62fb0SOlivier Houchard  */
2261fb62fb0SOlivier Houchard #define CK_SLIST_SWAP(a, b, type) do {						\
227d1f3fb2cSOlivier Houchard 	struct type *swap_first = (a)->cslh_first;				\
228d1f3fb2cSOlivier Houchard 	(a)->cslh_first = (b)->cslh_first;					\
229d1f3fb2cSOlivier Houchard 	(b)->cslh_first = swap_first;						\
2301fb62fb0SOlivier Houchard } while (0)
2311fb62fb0SOlivier Houchard 
2321fb62fb0SOlivier Houchard /*
2331fb62fb0SOlivier Houchard  * Singly-linked Tail queue declarations.
2341fb62fb0SOlivier Houchard  */
2351fb62fb0SOlivier Houchard #define	CK_STAILQ_HEAD(name, type)					\
2361fb62fb0SOlivier Houchard struct name {								\
237d1f3fb2cSOlivier Houchard 	struct type *cstqh_first;/* first element */			\
238d1f3fb2cSOlivier Houchard 	struct type **cstqh_last;/* addr of last next element */		\
2391fb62fb0SOlivier Houchard }
2401fb62fb0SOlivier Houchard 
2411fb62fb0SOlivier Houchard #define	CK_STAILQ_HEAD_INITIALIZER(head)				\
242d1f3fb2cSOlivier Houchard 	{ NULL, &(head).cstqh_first }
2431fb62fb0SOlivier Houchard 
2441fb62fb0SOlivier Houchard #define	CK_STAILQ_ENTRY(type)						\
2451fb62fb0SOlivier Houchard struct {								\
246d1f3fb2cSOlivier Houchard 	struct type *cstqe_next;	/* next element */			\
2471fb62fb0SOlivier Houchard }
2481fb62fb0SOlivier Houchard 
2491fb62fb0SOlivier Houchard /*
2501fb62fb0SOlivier Houchard  * Singly-linked Tail queue functions.
2511fb62fb0SOlivier Houchard  */
2521fb62fb0SOlivier Houchard #define	CK_STAILQ_CONCAT(head1, head2) do {					\
253d1f3fb2cSOlivier Houchard 	if ((head2)->cstqh_first != NULL) {					\
254d1f3fb2cSOlivier Houchard 		ck_pr_store_ptr((head1)->cstqh_last, (head2)->cstqh_first);	\
2551fb62fb0SOlivier Houchard 		ck_pr_fence_store();						\
256d1f3fb2cSOlivier Houchard 		(head1)->cstqh_last = (head2)->cstqh_last;			\
2571fb62fb0SOlivier Houchard 		CK_STAILQ_INIT((head2));					\
2581fb62fb0SOlivier Houchard 	}									\
2591fb62fb0SOlivier Houchard } while (0)
2601fb62fb0SOlivier Houchard 
261d1f3fb2cSOlivier Houchard #define	CK_STAILQ_EMPTY(head)	(ck_pr_load_ptr(&(head)->cstqh_first) == NULL)
2621fb62fb0SOlivier Houchard 
263d1f3fb2cSOlivier Houchard #define	CK_STAILQ_FIRST(head)	(ck_pr_load_ptr(&(head)->cstqh_first))
2641fb62fb0SOlivier Houchard 
2651fb62fb0SOlivier Houchard #define	CK_STAILQ_FOREACH(var, head, field)				\
2661fb62fb0SOlivier Houchard 	for((var) = CK_STAILQ_FIRST((head));				\
26774e9b5f2SOlivier Houchard 	   (var);							\
2681fb62fb0SOlivier Houchard 	   (var) = CK_STAILQ_NEXT((var), field))
2691fb62fb0SOlivier Houchard 
270*6f48a4acSMark Johnston #define	CK_STAILQ_FOREACH_FROM(var, head, field)			\
271*6f48a4acSMark Johnston 	for ((var) = ((var) != NULL ? (var) : CK_STAILQ_FIRST((head)));	\
272*6f48a4acSMark Johnston 	    (var);							\
273*6f48a4acSMark Johnston 	    (var) = CK_STAILQ_NEXT((var), field))
274*6f48a4acSMark Johnston 
2751fb62fb0SOlivier Houchard #define	CK_STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
2761fb62fb0SOlivier Houchard 	for ((var) = CK_STAILQ_FIRST((head));				\
27774e9b5f2SOlivier Houchard 	    (var) && ((tvar) =						\
2781fb62fb0SOlivier Houchard 		CK_STAILQ_NEXT((var), field), 1);			\
2791fb62fb0SOlivier Houchard 	    (var) = (tvar))
2801fb62fb0SOlivier Houchard 
2811fb62fb0SOlivier Houchard #define	CK_STAILQ_INIT(head) do {					\
282d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cstqh_first, NULL);			\
2831fb62fb0SOlivier Houchard 	ck_pr_fence_store();						\
284d1f3fb2cSOlivier Houchard 	(head)->cstqh_last = &(head)->cstqh_first;			\
2851fb62fb0SOlivier Houchard } while (0)
2861fb62fb0SOlivier Houchard 
2871fb62fb0SOlivier Houchard #define	CK_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {			\
288d1f3fb2cSOlivier Houchard 	(elm)->field.cstqe_next = (tqelm)->field.cstqe_next;			\
2891fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
290d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(tqelm)->field.cstqe_next, elm);			\
291d1f3fb2cSOlivier Houchard 	if ((elm)->field.cstqe_next == NULL)					\
292d1f3fb2cSOlivier Houchard 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
2931fb62fb0SOlivier Houchard } while (0)
2941fb62fb0SOlivier Houchard 
2951fb62fb0SOlivier Houchard #define	CK_STAILQ_INSERT_HEAD(head, elm, field) do {				\
296d1f3fb2cSOlivier Houchard 	(elm)->field.cstqe_next = (head)->cstqh_first;				\
2971fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
298d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cstqh_first, elm);				\
299d1f3fb2cSOlivier Houchard 	if ((elm)->field.cstqe_next == NULL)					\
300d1f3fb2cSOlivier Houchard 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
3011fb62fb0SOlivier Houchard } while (0)
3021fb62fb0SOlivier Houchard 
3031fb62fb0SOlivier Houchard #define	CK_STAILQ_INSERT_TAIL(head, elm, field) do {				\
304d1f3fb2cSOlivier Houchard 	(elm)->field.cstqe_next = NULL;						\
3051fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
306d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr((head)->cstqh_last, (elm));				\
307d1f3fb2cSOlivier Houchard 	(head)->cstqh_last = &(elm)->field.cstqe_next;				\
3081fb62fb0SOlivier Houchard } while (0)
3091fb62fb0SOlivier Houchard 
3101fb62fb0SOlivier Houchard #define	CK_STAILQ_NEXT(elm, field)						\
311d1f3fb2cSOlivier Houchard 	(ck_pr_load_ptr(&(elm)->field.cstqe_next))
3121fb62fb0SOlivier Houchard 
3131fb62fb0SOlivier Houchard #define	CK_STAILQ_REMOVE(head, elm, type, field) do {				\
314d1f3fb2cSOlivier Houchard 	if ((head)->cstqh_first == (elm)) {					\
3151fb62fb0SOlivier Houchard 		CK_STAILQ_REMOVE_HEAD((head), field);				\
3161fb62fb0SOlivier Houchard 	} else {								\
317d1f3fb2cSOlivier Houchard 		struct type *curelm = (head)->cstqh_first;			\
318d1f3fb2cSOlivier Houchard 		while (curelm->field.cstqe_next != (elm))			\
319d1f3fb2cSOlivier Houchard 			curelm = curelm->field.cstqe_next;			\
3201fb62fb0SOlivier Houchard 		CK_STAILQ_REMOVE_AFTER(head, curelm, field);			\
3211fb62fb0SOlivier Houchard 	}									\
3221fb62fb0SOlivier Houchard } while (0)
3231fb62fb0SOlivier Houchard 
3241fb62fb0SOlivier Houchard #define CK_STAILQ_REMOVE_AFTER(head, elm, field) do {				\
325d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(elm)->field.cstqe_next,				\
326d1f3fb2cSOlivier Houchard 	    (elm)->field.cstqe_next->field.cstqe_next);				\
327d1f3fb2cSOlivier Houchard 	if ((elm)->field.cstqe_next == NULL)					\
328d1f3fb2cSOlivier Houchard 		(head)->cstqh_last = &(elm)->field.cstqe_next;			\
3291fb62fb0SOlivier Houchard } while (0)
3301fb62fb0SOlivier Houchard 
3311fb62fb0SOlivier Houchard #define	CK_STAILQ_REMOVE_HEAD(head, field) do {					\
332d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->cstqh_first,					\
333d1f3fb2cSOlivier Houchard 	    (head)->cstqh_first->field.cstqe_next);				\
334d1f3fb2cSOlivier Houchard 	if ((head)->cstqh_first == NULL)						\
335d1f3fb2cSOlivier Houchard 		(head)->cstqh_last = &(head)->cstqh_first;			\
3361fb62fb0SOlivier Houchard } while (0)
3371fb62fb0SOlivier Houchard 
3381fb62fb0SOlivier Houchard #define CK_STAILQ_MOVE(head1, head2, field) do {				\
339d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head1)->cstqh_first, (head2)->cstqh_first);		\
340d1f3fb2cSOlivier Houchard 	(head1)->cstqh_last = (head2)->cstqh_last;				\
341d1f3fb2cSOlivier Houchard 	if ((head2)->cstqh_last == &(head2)->cstqh_first)				\
342d1f3fb2cSOlivier Houchard 		(head1)->cstqh_last = &(head1)->cstqh_first;			\
3431fb62fb0SOlivier Houchard } while (0)
3441fb62fb0SOlivier Houchard 
3451fb62fb0SOlivier Houchard /*
3461fb62fb0SOlivier Houchard  * This operation is not applied atomically.
3471fb62fb0SOlivier Houchard  */
3481fb62fb0SOlivier Houchard #define CK_STAILQ_SWAP(head1, head2, type) do {				\
3491fb62fb0SOlivier Houchard 	struct type *swap_first = CK_STAILQ_FIRST(head1);		\
350d1f3fb2cSOlivier Houchard 	struct type **swap_last = (head1)->cstqh_last;			\
3511fb62fb0SOlivier Houchard 	CK_STAILQ_FIRST(head1) = CK_STAILQ_FIRST(head2);		\
352d1f3fb2cSOlivier Houchard 	(head1)->cstqh_last = (head2)->cstqh_last;			\
3531fb62fb0SOlivier Houchard 	CK_STAILQ_FIRST(head2) = swap_first;				\
354d1f3fb2cSOlivier Houchard 	(head2)->cstqh_last = swap_last;					\
3551fb62fb0SOlivier Houchard 	if (CK_STAILQ_EMPTY(head1))					\
356d1f3fb2cSOlivier Houchard 		(head1)->cstqh_last = &(head1)->cstqh_first;		\
3571fb62fb0SOlivier Houchard 	if (CK_STAILQ_EMPTY(head2))					\
358d1f3fb2cSOlivier Houchard 		(head2)->cstqh_last = &(head2)->cstqh_first;		\
3591fb62fb0SOlivier Houchard } while (0)
3601fb62fb0SOlivier Houchard 
3611fb62fb0SOlivier Houchard /*
3621fb62fb0SOlivier Houchard  * List declarations.
3631fb62fb0SOlivier Houchard  */
3641fb62fb0SOlivier Houchard #define	CK_LIST_HEAD(name, type)						\
3651fb62fb0SOlivier Houchard struct name {									\
366d1f3fb2cSOlivier Houchard 	struct type *clh_first;	/* first element */				\
3671fb62fb0SOlivier Houchard }
3681fb62fb0SOlivier Houchard 
3691fb62fb0SOlivier Houchard #define	CK_LIST_HEAD_INITIALIZER(head)						\
3701fb62fb0SOlivier Houchard 	{ NULL }
3711fb62fb0SOlivier Houchard 
3721fb62fb0SOlivier Houchard #define	CK_LIST_ENTRY(type)							\
3731fb62fb0SOlivier Houchard struct {									\
374d1f3fb2cSOlivier Houchard 	struct type *cle_next;	/* next element */				\
375d1f3fb2cSOlivier Houchard 	struct type **cle_prev;	/* address of previous next element */		\
3761fb62fb0SOlivier Houchard }
3771fb62fb0SOlivier Houchard 
378d1f3fb2cSOlivier Houchard #define	CK_LIST_FIRST(head)		ck_pr_load_ptr(&(head)->clh_first)
3791fb62fb0SOlivier Houchard #define	CK_LIST_EMPTY(head)		(CK_LIST_FIRST(head) == NULL)
380d1f3fb2cSOlivier Houchard #define	CK_LIST_NEXT(elm, field)	ck_pr_load_ptr(&(elm)->field.cle_next)
3811fb62fb0SOlivier Houchard 
3821fb62fb0SOlivier Houchard #define	CK_LIST_FOREACH(var, head, field)					\
3831fb62fb0SOlivier Houchard 	for ((var) = CK_LIST_FIRST((head));					\
38474e9b5f2SOlivier Houchard 	    (var);								\
3851fb62fb0SOlivier Houchard 	    (var) = CK_LIST_NEXT((var), field))
3861fb62fb0SOlivier Houchard 
387*6f48a4acSMark Johnston #define	CK_LIST_FOREACH_FROM(var, head, field)					\
388*6f48a4acSMark Johnston 	for ((var) = ((var) != NULL ? (var) : CK_LIST_FIRST((head)));		\
389*6f48a4acSMark Johnston 	    (var);								\
390*6f48a4acSMark Johnston 	    (var) = CK_LIST_NEXT((var), field))
391*6f48a4acSMark Johnston 
3921fb62fb0SOlivier Houchard #define	CK_LIST_FOREACH_SAFE(var, head, field, tvar)				  \
3931fb62fb0SOlivier Houchard 	for ((var) = CK_LIST_FIRST((head));					  \
39474e9b5f2SOlivier Houchard 	    (var) && ((tvar) = CK_LIST_NEXT((var), field), 1);			  \
3951fb62fb0SOlivier Houchard 	    (var) = (tvar))
3961fb62fb0SOlivier Houchard 
3971fb62fb0SOlivier Houchard #define	CK_LIST_INIT(head) do {							\
398d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->clh_first, NULL);				\
3991fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
4001fb62fb0SOlivier Houchard } while (0)
4011fb62fb0SOlivier Houchard 
4021fb62fb0SOlivier Houchard #define	CK_LIST_INSERT_AFTER(listelm, elm, field) do {				\
403d1f3fb2cSOlivier Houchard 	(elm)->field.cle_next = (listelm)->field.cle_next;			\
404d1f3fb2cSOlivier Houchard 	(elm)->field.cle_prev = &(listelm)->field.cle_next;			\
4051fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
406d1f3fb2cSOlivier Houchard 	if ((listelm)->field.cle_next != NULL)					\
407d1f3fb2cSOlivier Houchard 		(listelm)->field.cle_next->field.cle_prev = &(elm)->field.cle_next;\
408d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(listelm)->field.cle_next, elm);			\
4091fb62fb0SOlivier Houchard } while (0)
4101fb62fb0SOlivier Houchard 
4111fb62fb0SOlivier Houchard #define	CK_LIST_INSERT_BEFORE(listelm, elm, field) do {				\
412d1f3fb2cSOlivier Houchard 	(elm)->field.cle_prev = (listelm)->field.cle_prev;			\
413d1f3fb2cSOlivier Houchard 	(elm)->field.cle_next = (listelm);					\
4141fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
415d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr((listelm)->field.cle_prev, (elm));			\
416d1f3fb2cSOlivier Houchard 	(listelm)->field.cle_prev = &(elm)->field.cle_next;			\
4171fb62fb0SOlivier Houchard } while (0)
4181fb62fb0SOlivier Houchard 
4191fb62fb0SOlivier Houchard #define	CK_LIST_INSERT_HEAD(head, elm, field) do {				\
420d1f3fb2cSOlivier Houchard 	(elm)->field.cle_next = (head)->clh_first;				\
4211fb62fb0SOlivier Houchard 	ck_pr_fence_store();							\
422d1f3fb2cSOlivier Houchard 	if ((elm)->field.cle_next != NULL)					\
423d1f3fb2cSOlivier Houchard 		(head)->clh_first->field.cle_prev =  &(elm)->field.cle_next;	\
424d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head)->clh_first, elm);				\
425d1f3fb2cSOlivier Houchard 	(elm)->field.cle_prev = &(head)->clh_first;				\
4261fb62fb0SOlivier Houchard } while (0)
4271fb62fb0SOlivier Houchard 
4281fb62fb0SOlivier Houchard #define	CK_LIST_REMOVE(elm, field) do {						\
429d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr((elm)->field.cle_prev, (elm)->field.cle_next);		\
430d1f3fb2cSOlivier Houchard 	if ((elm)->field.cle_next != NULL)					\
431d1f3fb2cSOlivier Houchard 		(elm)->field.cle_next->field.cle_prev = (elm)->field.cle_prev;	\
4321fb62fb0SOlivier Houchard } while (0)
4331fb62fb0SOlivier Houchard 
4341fb62fb0SOlivier Houchard #define CK_LIST_MOVE(head1, head2, field) do {				\
435d1f3fb2cSOlivier Houchard 	ck_pr_store_ptr(&(head1)->clh_first, (head2)->clh_first);		\
436d1f3fb2cSOlivier Houchard 	if ((head1)->clh_first != NULL)					\
437d1f3fb2cSOlivier Houchard 		(head1)->clh_first->field.cle_prev = &(head1)->clh_first;	\
4381fb62fb0SOlivier Houchard } while (0)
4391fb62fb0SOlivier Houchard 
4401fb62fb0SOlivier Houchard /*
4411fb62fb0SOlivier Houchard  * This operation is not applied atomically.
4421fb62fb0SOlivier Houchard  */
4431fb62fb0SOlivier Houchard #define CK_LIST_SWAP(head1, head2, type, field) do {			\
444d1f3fb2cSOlivier Houchard 	struct type *swap_tmp = (head1)->clh_first;			\
445d1f3fb2cSOlivier Houchard 	(head1)->clh_first = (head2)->clh_first;				\
446d1f3fb2cSOlivier Houchard 	(head2)->clh_first = swap_tmp;					\
447d1f3fb2cSOlivier Houchard 	if ((swap_tmp = (head1)->clh_first) != NULL)			\
448d1f3fb2cSOlivier Houchard 		swap_tmp->field.cle_prev = &(head1)->clh_first;		\
449d1f3fb2cSOlivier Houchard 	if ((swap_tmp = (head2)->clh_first) != NULL)			\
450d1f3fb2cSOlivier Houchard 		swap_tmp->field.cle_prev = &(head2)->clh_first;		\
4511fb62fb0SOlivier Houchard } while (0)
4521fb62fb0SOlivier Houchard 
4531fb62fb0SOlivier Houchard #endif /* CK_QUEUE_H */
454