1*0Sstevel@tonic-gate /*- 2*0Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Copyright (c) 1996, 1997 5*0Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*0Sstevel@tonic-gate * 7*0Sstevel@tonic-gate * @(#)shqueue.h 8.12 (Sleepycat) 9/10/97 8*0Sstevel@tonic-gate * %W% (Sun) %G% 9*0Sstevel@tonic-gate */ 10*0Sstevel@tonic-gate /* 11*0Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc. 12*0Sstevel@tonic-gate * All rights reserved. 13*0Sstevel@tonic-gate */ 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate #ifndef _SYS_SHQUEUE_H_ 18*0Sstevel@tonic-gate #define _SYS_SHQUEUE_H_ 19*0Sstevel@tonic-gate 20*0Sstevel@tonic-gate /* 21*0Sstevel@tonic-gate * This file defines three types of data structures: lists, tail queues, and 22*0Sstevel@tonic-gate * circular queues, similarly to the include file <sys/queue.h>. 23*0Sstevel@tonic-gate * 24*0Sstevel@tonic-gate * The difference is that this set of macros can be used for structures that 25*0Sstevel@tonic-gate * reside in shared memory that may be mapped at different addresses in each 26*0Sstevel@tonic-gate * process. In most cases, the macros for shared structures exactly mirror 27*0Sstevel@tonic-gate * the normal macros, although the macro calls require an additional type 28*0Sstevel@tonic-gate * parameter, only used by the HEAD and ENTRY macros of the standard macros. 29*0Sstevel@tonic-gate * 30*0Sstevel@tonic-gate * For details on the use of these macros, see the queue(3) manual page. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * Shared list definitions. 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate #define SH_LIST_HEAD(name) \ 37*0Sstevel@tonic-gate struct name { \ 38*0Sstevel@tonic-gate ssize_t slh_first; /* first element */ \ 39*0Sstevel@tonic-gate } 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #define SH_LIST_ENTRY \ 42*0Sstevel@tonic-gate struct { \ 43*0Sstevel@tonic-gate ssize_t sle_next; /* relative offset next element */ \ 44*0Sstevel@tonic-gate ssize_t sle_prev; /* relative offset of prev element */ \ 45*0Sstevel@tonic-gate } 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * Shared list functions. Since we use relative offsets for pointers, 49*0Sstevel@tonic-gate * 0 is a valid offset. Therefore, we use -1 to indicate end of list. 50*0Sstevel@tonic-gate * The macros ending in "P" return pointers without checking for end 51*0Sstevel@tonic-gate * of list, the others check for end of list and evaluate to either a 52*0Sstevel@tonic-gate * pointer or NULL. 53*0Sstevel@tonic-gate */ 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate #define SH_LIST_FIRSTP(head, type) \ 56*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)) 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #define SH_LIST_FIRST(head, type) \ 59*0Sstevel@tonic-gate ((head)->slh_first == -1 ? NULL : \ 60*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))) 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate #define SH_LIST_NEXTP(elm, field, type) \ 63*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)) 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate #define SH_LIST_NEXT(elm, field, type) \ 66*0Sstevel@tonic-gate ((elm)->field.sle_next == -1 ? NULL : \ 67*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))) 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate #define SH_LIST_PREV(elm, field) \ 70*0Sstevel@tonic-gate ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev)) 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #define SH_PTR_TO_OFF(src, dest) \ 73*0Sstevel@tonic-gate ((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src)))) 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate #define SH_LIST_END(head) NULL 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate /* 78*0Sstevel@tonic-gate * Take the element's next pointer and calculate what the corresponding 79*0Sstevel@tonic-gate * Prev pointer should be -- basically it is the negation plus the offset 80*0Sstevel@tonic-gate * of the next field in the structure. 81*0Sstevel@tonic-gate */ 82*0Sstevel@tonic-gate #define SH_LIST_NEXT_TO_PREV(elm, field) \ 83*0Sstevel@tonic-gate (-(elm)->field.sle_next + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next)) 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate #define SH_LIST_INIT(head) (head)->slh_first = -1 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate #define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do { \ 88*0Sstevel@tonic-gate if ((listelm)->field.sle_next != -1) { \ 89*0Sstevel@tonic-gate (elm)->field.sle_next = SH_PTR_TO_OFF(elm, \ 90*0Sstevel@tonic-gate SH_LIST_NEXTP(listelm, field, type)); \ 91*0Sstevel@tonic-gate SH_LIST_NEXTP(listelm, field, type)->field.sle_prev = \ 92*0Sstevel@tonic-gate SH_LIST_NEXT_TO_PREV(elm, field); \ 93*0Sstevel@tonic-gate } else \ 94*0Sstevel@tonic-gate (elm)->field.sle_next = -1; \ 95*0Sstevel@tonic-gate (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm); \ 96*0Sstevel@tonic-gate (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field); \ 97*0Sstevel@tonic-gate } while (0) 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate #define SH_LIST_INSERT_HEAD(head, elm, field, type) do { \ 100*0Sstevel@tonic-gate if ((head)->slh_first != -1) { \ 101*0Sstevel@tonic-gate (elm)->field.sle_next = \ 102*0Sstevel@tonic-gate (head)->slh_first - SH_PTR_TO_OFF(head, elm); \ 103*0Sstevel@tonic-gate SH_LIST_FIRSTP(head, type)->field.sle_prev = \ 104*0Sstevel@tonic-gate SH_LIST_NEXT_TO_PREV(elm, field); \ 105*0Sstevel@tonic-gate } else \ 106*0Sstevel@tonic-gate (elm)->field.sle_next = -1; \ 107*0Sstevel@tonic-gate (head)->slh_first = SH_PTR_TO_OFF(head, elm); \ 108*0Sstevel@tonic-gate (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \ 109*0Sstevel@tonic-gate } while (0) 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate #define SH_LIST_REMOVE(elm, field, type) do { \ 112*0Sstevel@tonic-gate if ((elm)->field.sle_next != -1) { \ 113*0Sstevel@tonic-gate SH_LIST_NEXTP(elm, field, type)->field.sle_prev = \ 114*0Sstevel@tonic-gate (elm)->field.sle_prev - (elm)->field.sle_next; \ 115*0Sstevel@tonic-gate *SH_LIST_PREV(elm, field) += (elm)->field.sle_next; \ 116*0Sstevel@tonic-gate } else \ 117*0Sstevel@tonic-gate *SH_LIST_PREV(elm, field) = -1; \ 118*0Sstevel@tonic-gate } while (0) 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * Shared tail queue definitions. 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate #define SH_TAILQ_HEAD(name) \ 124*0Sstevel@tonic-gate struct name { \ 125*0Sstevel@tonic-gate ssize_t stqh_first; /* relative offset of first element */ \ 126*0Sstevel@tonic-gate ssize_t stqh_last; /* relative offset of last's next */ \ 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate #define SH_TAILQ_ENTRY \ 130*0Sstevel@tonic-gate struct { \ 131*0Sstevel@tonic-gate ssize_t stqe_next; /* relative offset of next element */ \ 132*0Sstevel@tonic-gate ssize_t stqe_prev; /* relative offset of prev's next */ \ 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate /* 136*0Sstevel@tonic-gate * Shared tail queue functions. 137*0Sstevel@tonic-gate */ 138*0Sstevel@tonic-gate #define SH_TAILQ_FIRSTP(head, type) \ 139*0Sstevel@tonic-gate ((struct type *)((u_int8_t *)(head) + (head)->stqh_first)) 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate #define SH_TAILQ_FIRST(head, type) \ 142*0Sstevel@tonic-gate ((head)->stqh_first == -1 ? NULL : SH_TAILQ_FIRSTP(head, type)) 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate #define SH_TAILQ_NEXTP(elm, field, type) \ 145*0Sstevel@tonic-gate ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next)) 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate #define SH_TAILQ_NEXT(elm, field, type) \ 148*0Sstevel@tonic-gate ((elm)->field.stqe_next == -1 ? NULL : SH_TAILQ_NEXTP(elm, field, type)) 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate #define SH_TAILQ_PREVP(elm, field) \ 151*0Sstevel@tonic-gate ((ssize_t *)((u_int8_t *)(elm) + (elm)->field.stqe_prev)) 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate #define SH_TAILQ_LAST(head) \ 154*0Sstevel@tonic-gate ((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last)) 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate #define SH_TAILQ_NEXT_TO_PREV(elm, field) \ 157*0Sstevel@tonic-gate (-(elm)->field.stqe_next + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next)) 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate #define SH_TAILQ_END(head) NULL 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate #define SH_TAILQ_INIT(head) { \ 162*0Sstevel@tonic-gate (head)->stqh_first = -1; \ 163*0Sstevel@tonic-gate (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first); \ 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate #define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do { \ 167*0Sstevel@tonic-gate if ((head)->stqh_first != -1) { \ 168*0Sstevel@tonic-gate (elm)->field.stqe_next = \ 169*0Sstevel@tonic-gate (head)->stqh_first - SH_PTR_TO_OFF(head, elm); \ 170*0Sstevel@tonic-gate SH_TAILQ_FIRSTP(head, type)->field.stqe_prev = \ 171*0Sstevel@tonic-gate SH_TAILQ_NEXT_TO_PREV(elm, field); \ 172*0Sstevel@tonic-gate } else { \ 173*0Sstevel@tonic-gate (elm)->field.stqe_next = -1; \ 174*0Sstevel@tonic-gate (head)->stqh_last = \ 175*0Sstevel@tonic-gate SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \ 176*0Sstevel@tonic-gate } \ 177*0Sstevel@tonic-gate (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ 178*0Sstevel@tonic-gate (elm)->field.stqe_prev = \ 179*0Sstevel@tonic-gate SH_PTR_TO_OFF(elm, &(head)->stqh_first); \ 180*0Sstevel@tonic-gate } while (0) 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate #define SH_TAILQ_INSERT_TAIL(head, elm, field) do { \ 183*0Sstevel@tonic-gate (elm)->field.stqe_next = -1; \ 184*0Sstevel@tonic-gate (elm)->field.stqe_prev = \ 185*0Sstevel@tonic-gate -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last; \ 186*0Sstevel@tonic-gate if ((head)->stqh_last == \ 187*0Sstevel@tonic-gate SH_PTR_TO_OFF((head), &(head)->stqh_first)) \ 188*0Sstevel@tonic-gate (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ 189*0Sstevel@tonic-gate else \ 190*0Sstevel@tonic-gate *SH_TAILQ_LAST(head) = -(head)->stqh_last + \ 191*0Sstevel@tonic-gate SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) + \ 192*0Sstevel@tonic-gate SH_PTR_TO_OFF(head, elm); \ 193*0Sstevel@tonic-gate (head)->stqh_last = \ 194*0Sstevel@tonic-gate SH_PTR_TO_OFF(head, &((elm)->field.stqe_next)); \ 195*0Sstevel@tonic-gate } while (0) 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate #define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do { \ 198*0Sstevel@tonic-gate if ((listelm)->field.stqe_next != -1) { \ 199*0Sstevel@tonic-gate (elm)->field.stqe_next = (listelm)->field.stqe_next - \ 200*0Sstevel@tonic-gate SH_PTR_TO_OFF(listelm, elm); \ 201*0Sstevel@tonic-gate SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \ 202*0Sstevel@tonic-gate SH_TAILQ_NEXT_TO_PREV(elm, field); \ 203*0Sstevel@tonic-gate } else { \ 204*0Sstevel@tonic-gate (elm)->field.stqe_next = -1; \ 205*0Sstevel@tonic-gate (head)->stqh_last = \ 206*0Sstevel@tonic-gate SH_PTR_TO_OFF(head, &elm->field.stqe_next); \ 207*0Sstevel@tonic-gate } \ 208*0Sstevel@tonic-gate (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm); \ 209*0Sstevel@tonic-gate (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \ 210*0Sstevel@tonic-gate } while (0) 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate #define SH_TAILQ_REMOVE(head, elm, field, type) do { \ 213*0Sstevel@tonic-gate if ((elm)->field.stqe_next != -1) { \ 214*0Sstevel@tonic-gate SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev = \ 215*0Sstevel@tonic-gate (elm)->field.stqe_prev + \ 216*0Sstevel@tonic-gate SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm, \ 217*0Sstevel@tonic-gate field, type), elm); \ 218*0Sstevel@tonic-gate *SH_TAILQ_PREVP(elm, field) += elm->field.stqe_next; \ 219*0Sstevel@tonic-gate } else { \ 220*0Sstevel@tonic-gate (head)->stqh_last = (elm)->field.stqe_prev + \ 221*0Sstevel@tonic-gate SH_PTR_TO_OFF(head, elm); \ 222*0Sstevel@tonic-gate *SH_TAILQ_PREVP(elm, field) = -1; \ 223*0Sstevel@tonic-gate } \ 224*0Sstevel@tonic-gate } while (0) 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* 227*0Sstevel@tonic-gate * Shared circular queue definitions. 228*0Sstevel@tonic-gate */ 229*0Sstevel@tonic-gate #define SH_CIRCLEQ_HEAD(name) \ 230*0Sstevel@tonic-gate struct name { \ 231*0Sstevel@tonic-gate ssize_t scqh_first; /* first element */ \ 232*0Sstevel@tonic-gate ssize_t scqh_last; /* last element */ \ 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate #define SH_CIRCLEQ_ENTRY \ 236*0Sstevel@tonic-gate struct { \ 237*0Sstevel@tonic-gate ssize_t scqe_next; /* next element */ \ 238*0Sstevel@tonic-gate ssize_t scqe_prev; /* previous element */ \ 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* 242*0Sstevel@tonic-gate * Shared circular queue functions. 243*0Sstevel@tonic-gate */ 244*0Sstevel@tonic-gate #define SH_CIRCLEQ_FIRSTP(head, type) \ 245*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_first)) 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate #define SH_CIRCLEQ_FIRST(head, type) \ 248*0Sstevel@tonic-gate ((head)->scqh_first == -1 ? \ 249*0Sstevel@tonic-gate (void *)head : SH_CIRCLEQ_FIRSTP(head, type)) 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate #define SH_CIRCLEQ_LASTP(head, type) \ 252*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_last)) 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate #define SH_CIRCLEQ_LAST(head, type) \ 255*0Sstevel@tonic-gate ((head)->scqh_last == -1 ? (void *)head : SH_CIRCLEQ_LASTP(head, type)) 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate #define SH_CIRCLEQ_NEXTP(elm, field, type) \ 258*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_next)) 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate #define SH_CIRCLEQ_NEXT(head, elm, field, type) \ 261*0Sstevel@tonic-gate ((elm)->field.scqe_next == SH_PTR_TO_OFF(elm, head) ? \ 262*0Sstevel@tonic-gate (void *)head : SH_CIRCLEQ_NEXTP(elm, field, type)) 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate #define SH_CIRCLEQ_PREVP(elm, field, type) \ 265*0Sstevel@tonic-gate ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_prev)) 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate #define SH_CIRCLEQ_PREV(head, elm, field, type) \ 268*0Sstevel@tonic-gate ((elm)->field.scqe_prev == SH_PTR_TO_OFF(elm, head) ? \ 269*0Sstevel@tonic-gate (void *)head : SH_CIRCLEQ_PREVP(elm, field, type)) 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate #define SH_CIRCLEQ_END(head) ((void *)(head)) 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate #define SH_CIRCLEQ_INIT(head) { \ 274*0Sstevel@tonic-gate (head)->scqh_first = 0; \ 275*0Sstevel@tonic-gate (head)->scqh_last = 0; \ 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate #define SH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field, type) do { \ 279*0Sstevel@tonic-gate (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, listelm); \ 280*0Sstevel@tonic-gate (elm)->field.scqe_next = (listelm)->field.scqe_next + \ 281*0Sstevel@tonic-gate (elm)->field.scqe_prev; \ 282*0Sstevel@tonic-gate if (SH_CIRCLEQ_NEXTP(listelm, field, type) == (void *)head) \ 283*0Sstevel@tonic-gate (head)->scqh_last = SH_PTR_TO_OFF(head, elm); \ 284*0Sstevel@tonic-gate else \ 285*0Sstevel@tonic-gate SH_CIRCLEQ_NEXTP(listelm, \ 286*0Sstevel@tonic-gate field, type)->field.scqe_prev = \ 287*0Sstevel@tonic-gate SH_PTR_TO_OFF(SH_CIRCLEQ_NEXTP(listelm, \ 288*0Sstevel@tonic-gate field, type), elm); \ 289*0Sstevel@tonic-gate (listelm)->field.scqe_next = -(elm)->field.scqe_prev; \ 290*0Sstevel@tonic-gate } while (0) 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate #define SH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field, type) do { \ 293*0Sstevel@tonic-gate (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, listelm); \ 294*0Sstevel@tonic-gate (elm)->field.scqe_prev = (elm)->field.scqe_next - \ 295*0Sstevel@tonic-gate SH_CIRCLEQ_PREVP(listelm, field, type)->field.scqe_next;\ 296*0Sstevel@tonic-gate if (SH_CIRCLEQ_PREVP(listelm, field, type) == (void *)(head)) \ 297*0Sstevel@tonic-gate (head)->scqh_first = SH_PTR_TO_OFF(head, elm); \ 298*0Sstevel@tonic-gate else \ 299*0Sstevel@tonic-gate SH_CIRCLEQ_PREVP(listelm, \ 300*0Sstevel@tonic-gate field, type)->field.scqe_next = \ 301*0Sstevel@tonic-gate SH_PTR_TO_OFF(SH_CIRCLEQ_PREVP(listelm, \ 302*0Sstevel@tonic-gate field, type), elm); \ 303*0Sstevel@tonic-gate (listelm)->field.scqe_prev = -(elm)->field.scqe_next; \ 304*0Sstevel@tonic-gate } while (0) 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate #define SH_CIRCLEQ_INSERT_HEAD(head, elm, field, type) do { \ 307*0Sstevel@tonic-gate (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, head); \ 308*0Sstevel@tonic-gate (elm)->field.scqe_next = (head)->scqh_first + \ 309*0Sstevel@tonic-gate (elm)->field.scqe_prev; \ 310*0Sstevel@tonic-gate if ((head)->scqh_last == 0) \ 311*0Sstevel@tonic-gate (head)->scqh_last = -(elm)->field.scqe_prev; \ 312*0Sstevel@tonic-gate else \ 313*0Sstevel@tonic-gate SH_CIRCLEQ_FIRSTP(head, type)->field.scqe_prev = \ 314*0Sstevel@tonic-gate SH_PTR_TO_OFF(SH_CIRCLEQ_FIRSTP(head, type), elm); \ 315*0Sstevel@tonic-gate (head)->scqh_first = -(elm)->field.scqe_prev; \ 316*0Sstevel@tonic-gate } while (0) 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate #define SH_CIRCLEQ_INSERT_TAIL(head, elm, field, type) do { \ 319*0Sstevel@tonic-gate (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, head); \ 320*0Sstevel@tonic-gate (elm)->field.scqe_prev = (head)->scqh_last + \ 321*0Sstevel@tonic-gate (elm)->field.scqe_next; \ 322*0Sstevel@tonic-gate if ((head)->scqh_first == 0) \ 323*0Sstevel@tonic-gate (head)->scqh_first = -(elm)->field.scqe_next; \ 324*0Sstevel@tonic-gate else \ 325*0Sstevel@tonic-gate SH_CIRCLEQ_LASTP(head, type)->field.scqe_next = \ 326*0Sstevel@tonic-gate SH_PTR_TO_OFF(SH_CIRCLEQ_LASTP(head, type), elm); \ 327*0Sstevel@tonic-gate (head)->scqh_last = -(elm)->field.scqe_next; \ 328*0Sstevel@tonic-gate } while (0) 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate #define SH_CIRCLEQ_REMOVE(head, elm, field, type) do { \ 331*0Sstevel@tonic-gate if (SH_CIRCLEQ_NEXTP(elm, field, type) == (void *)(head)) \ 332*0Sstevel@tonic-gate (head)->scqh_last += (elm)->field.scqe_prev; \ 333*0Sstevel@tonic-gate else \ 334*0Sstevel@tonic-gate SH_CIRCLEQ_NEXTP(elm, field, type)->field.scqe_prev += \ 335*0Sstevel@tonic-gate (elm)->field.scqe_prev; \ 336*0Sstevel@tonic-gate if (SH_CIRCLEQ_PREVP(elm, field, type) == (void *)(head)) \ 337*0Sstevel@tonic-gate (head)->scqh_first += (elm)->field.scqe_next; \ 338*0Sstevel@tonic-gate else \ 339*0Sstevel@tonic-gate SH_CIRCLEQ_PREVP(elm, field, type)->field.scqe_next += \ 340*0Sstevel@tonic-gate (elm)->field.scqe_next; \ 341*0Sstevel@tonic-gate } while (0) 342*0Sstevel@tonic-gate #endif /* !_SYS_SHQUEUE_H_ */ 343