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