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