Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
9259 libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/sys/queue.h
+++ new/usr/src/uts/common/sys/queue.h
1 -/* $NetBSD: queue.h,v 1.42 2005/07/13 15:08:24 wiz Exp $ */
2 -
3 1 /*
4 2 * Copyright (c) 1991, 1993
5 3 * The Regents of the University of California. All rights reserved.
6 4 *
7 5 * Redistribution and use in source and binary forms, with or without
8 6 * modification, are permitted provided that the following conditions
9 7 * are met:
10 8 * 1. Redistributions of source code must retain the above copyright
11 9 * notice, this list of conditions and the following disclaimer.
12 10 * 2. Redistributions in binary form must reproduce the above copyright
13 11 * notice, this list of conditions and the following disclaimer in the
14 12 * documentation and/or other materials provided with the distribution.
15 13 * 3. Neither the name of the University nor the names of its contributors
16 14 * may be used to endorse or promote products derived from this software
17 15 * without specific prior written permission.
18 16 *
19 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 27 * SUCH DAMAGE.
30 28 *
31 29 * @(#)queue.h 8.5 (Berkeley) 8/20/94
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
32 30 */
33 31 /*
34 32 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
35 33 * Use is subject to license terms.
36 34 */
37 35
38 36 #ifndef _SYS_QUEUE_H
39 37 #define _SYS_QUEUE_H
40 38
41 39 #include <sys/note.h>
40 +#include <sys/stddef.h>
42 41
43 42 #ifdef __cplusplus
44 43 extern "C" {
45 44 #endif
46 45
47 46 /*
48 47 * This file defines five types of data structures: singly-linked lists,
49 48 * lists, simple queues, tail queues, and circular queues.
50 49 *
51 50 * A singly-linked list is headed by a single forward pointer. The
52 51 * elements are singly linked for minimum space and pointer manipulation
53 52 * overhead at the expense of O(n) removal for arbitrary elements. New
54 53 * elements can be added to the list after an existing element or at the
55 54 * head of the list. Elements being removed from the head of the list
56 55 * should use the explicit macro for this purpose for optimum
57 56 * efficiency. A singly-linked list may only be traversed in the forward
58 57 * direction. Singly-linked lists are ideal for applications with large
59 58 * datasets and few or no removals or for implementing a LIFO queue.
60 59 *
61 60 * A list is headed by a single forward pointer (or an array of forward
62 61 * pointers for a hash table header). The elements are doubly linked
63 62 * so that an arbitrary element can be removed without a need to
64 63 * traverse the list. New elements can be added to the list before
65 64 * or after an existing element or at the head of the list. A list
66 65 * may only be traversed in the forward direction.
67 66 *
68 67 * A simple queue is headed by a pair of pointers, one the head of the
69 68 * list and the other to the tail of the list. The elements are singly
70 69 * linked to save space, so elements can only be removed from the
71 70 * head of the list. New elements can be added to the list after
72 71 * an existing element, at the head of the list, or at the end of the
73 72 * list. A simple queue may only be traversed in the forward direction.
74 73 *
75 74 * A tail queue is headed by a pair of pointers, one to the head of the
76 75 * list and the other to the tail of the list. The elements are doubly
77 76 * linked so that an arbitrary element can be removed without a need to
78 77 * traverse the list. New elements can be added to the list before or
79 78 * after an existing element, at the head of the list, or at the end of
80 79 * the list. A tail queue may be traversed in either direction.
81 80 *
82 81 * A circle queue is headed by a pair of pointers, one to the head of the
83 82 * list and the other to the tail of the list. The elements are doubly
84 83 * linked so that an arbitrary element can be removed without a need to
85 84 * traverse the list. New elements can be added to the list before or after
86 85 * an existing element, at the head of the list, or at the end of the list.
87 86 * A circle queue may be traversed in either direction, but has a more
88 87 * complex end of list detection.
89 88 *
90 89 * For details on the use of these macros, see the queue(3) manual page.
91 90 */
92 91
93 92 /*
94 93 * List definitions.
95 94 */
96 95 #define LIST_HEAD(name, type) \
97 96 struct name { \
98 97 struct type *lh_first; /* first element */ \
99 98 }
100 99
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
101 100 #define LIST_HEAD_INITIALIZER(head) \
102 101 { NULL }
103 102
104 103 #define LIST_ENTRY(type) \
105 104 struct { \
106 105 struct type *le_next; /* next element */ \
107 106 struct type **le_prev; /* address of previous next element */ \
108 107 }
109 108
110 109 /*
110 + * List access methods.
111 + */
112 +#define LIST_EMPTY(head) ((head)->lh_first == NULL)
113 +#define LIST_FIRST(head) ((head)->lh_first)
114 +#define LIST_NEXT(elm, field) ((elm)->field.le_next)
115 +#define LIST_PREV(elm, head, type, field) \
116 + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
117 + container_of((elm)->field.le_prev, type, field.le_next))
118 +
119 +#define LIST_FOREACH(var, head, field) \
120 + for ((var) = LIST_FIRST((head)); \
121 + (var); \
122 + (var) = LIST_NEXT((var), field))
123 +
124 +#define LIST_FOREACH_SAFE(var, head, field, tvar) \
125 + for ((var) = LIST_FIRST((head)); \
126 + (var) && ((tvar) = LIST_NEXT((var), field), 1); \
127 + (var) = (tvar))
128 +
129 +/*
111 130 * List functions.
112 131 */
113 132 #if defined(_KERNEL) && defined(QUEUEDEBUG)
114 133 #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
115 134 if ((head)->lh_first && \
116 135 (head)->lh_first->field.le_prev != &(head)->lh_first) \
117 136 panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
118 137 #define QUEUEDEBUG_LIST_OP(elm, field) \
119 138 if ((elm)->field.le_next && \
120 139 (elm)->field.le_next->field.le_prev != \
121 140 &(elm)->field.le_next) \
122 141 panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
123 142 if (*(elm)->field.le_prev != (elm)) \
124 143 panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
125 144 #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
126 145 (elm)->field.le_next = (void *)1L; \
127 146 (elm)->field.le_prev = (void *)1L;
128 147 #else
129 148 #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
130 149 #define QUEUEDEBUG_LIST_OP(elm, field)
131 150 #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
132 151 #endif
133 152
134 153 #define LIST_INIT(head) do { \
135 154 (head)->lh_first = NULL; \
136 155 _NOTE(CONSTCOND) \
137 156 } while (0)
138 157
139 158 #define LIST_INSERT_AFTER(listelm, elm, field) do { \
140 159 QUEUEDEBUG_LIST_OP((listelm), field) \
141 160 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
142 161 (listelm)->field.le_next->field.le_prev = \
143 162 &(elm)->field.le_next; \
144 163 (listelm)->field.le_next = (elm); \
145 164 (elm)->field.le_prev = &(listelm)->field.le_next; \
146 165 _NOTE(CONSTCOND) \
147 166 } while (0)
148 167
149 168 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
150 169 QUEUEDEBUG_LIST_OP((listelm), field) \
151 170 (elm)->field.le_prev = (listelm)->field.le_prev; \
152 171 (elm)->field.le_next = (listelm); \
153 172 *(listelm)->field.le_prev = (elm); \
154 173 (listelm)->field.le_prev = &(elm)->field.le_next; \
155 174 _NOTE(CONSTCOND) \
156 175 } while (0)
157 176
158 177 #define LIST_INSERT_HEAD(head, elm, field) do { \
159 178 QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
160 179 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
161 180 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
162 181 (head)->lh_first = (elm); \
163 182 (elm)->field.le_prev = &(head)->lh_first; \
164 183 _NOTE(CONSTCOND) \
165 184 } while (0)
166 185
|
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
167 186 #define LIST_REMOVE(elm, field) do { \
168 187 QUEUEDEBUG_LIST_OP((elm), field) \
169 188 if ((elm)->field.le_next != NULL) \
170 189 (elm)->field.le_next->field.le_prev = \
171 190 (elm)->field.le_prev; \
172 191 *(elm)->field.le_prev = (elm)->field.le_next; \
173 192 QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
174 193 _NOTE(CONSTCOND) \
175 194 } while (0)
176 195
177 -#define LIST_FOREACH(var, head, field) \
178 - for ((var) = ((head)->lh_first); \
179 - (var); \
180 - (var) = ((var)->field.le_next))
181 196
182 197 /*
183 - * List access methods.
184 - */
185 -#define LIST_EMPTY(head) ((head)->lh_first == NULL)
186 -#define LIST_FIRST(head) ((head)->lh_first)
187 -#define LIST_NEXT(elm, field) ((elm)->field.le_next)
188 -
189 -
190 -/*
191 198 * Singly-linked List definitions.
192 199 */
193 200 #define SLIST_HEAD(name, type) \
194 201 struct name { \
195 202 struct type *slh_first; /* first element */ \
196 203 }
197 204
198 205 #define SLIST_HEAD_INITIALIZER(head) \
199 206 { NULL }
200 207
201 208 #define SLIST_ENTRY(type) \
202 209 struct { \
203 210 struct type *sle_next; /* next element */ \
204 211 }
205 212
206 213 /*
214 + * Singly-linked List access methods.
215 + */
216 +#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
217 +#define SLIST_FIRST(head) ((head)->slh_first)
218 +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
219 +
220 +#define SLIST_FOREACH(var, head, field) \
221 + for ((var) = SLIST_FIRST((head)); \
222 + (var); \
223 + (var) = SLIST_NEXT((var), field))
224 +
225 +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
226 + for ((var) = SLIST_FIRST((head)); \
227 + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
228 + (var) = (tvar))
229 +
230 +/*
207 231 * Singly-linked List functions.
208 232 */
209 233 #define SLIST_INIT(head) do { \
210 234 (head)->slh_first = NULL; \
211 235 _NOTE(CONSTCOND) \
212 236 } while (0)
213 237
214 238 #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
215 239 (elm)->field.sle_next = (slistelm)->field.sle_next; \
216 240 (slistelm)->field.sle_next = (elm); \
217 241 _NOTE(CONSTCOND) \
218 242 } while (0)
219 243
220 244 #define SLIST_INSERT_HEAD(head, elm, field) do { \
221 245 (elm)->field.sle_next = (head)->slh_first; \
222 246 (head)->slh_first = (elm); \
223 247 _NOTE(CONSTCOND) \
224 248 } while (0)
225 249
226 250 #define SLIST_REMOVE_HEAD(head, field) do { \
227 251 (head)->slh_first = (head)->slh_first->field.sle_next; \
228 252 _NOTE(CONSTCOND) \
229 253 } while (0)
230 254
231 255 #define SLIST_REMOVE(head, elm, type, field) do { \
232 256 if ((head)->slh_first == (elm)) { \
233 257 SLIST_REMOVE_HEAD((head), field); \
234 258 } \
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
235 259 else { \
236 260 struct type *curelm = (head)->slh_first; \
237 261 while (curelm->field.sle_next != (elm)) \
238 262 curelm = curelm->field.sle_next; \
239 263 curelm->field.sle_next = \
240 264 curelm->field.sle_next->field.sle_next; \
241 265 } \
242 266 _NOTE(CONSTCOND) \
243 267 } while (0)
244 268
245 -#define SLIST_FOREACH(var, head, field) \
246 - for ((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
247 269
248 270 /*
249 - * Singly-linked List access methods.
250 - */
251 -#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
252 -#define SLIST_FIRST(head) ((head)->slh_first)
253 -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
254 -
255 -
256 -/*
257 271 * Singly-linked Tail queue declarations.
258 272 */
259 273 #define STAILQ_HEAD(name, type) \
260 274 struct name { \
261 275 struct type *stqh_first; /* first element */ \
262 276 struct type **stqh_last; /* addr of last next element */ \
263 277 }
264 278
265 279 #define STAILQ_HEAD_INITIALIZER(head) \
266 280 { NULL, &(head).stqh_first }
267 281
268 282 #define STAILQ_ENTRY(type) \
269 283 struct { \
270 284 struct type *stqe_next; /* next element */ \
271 285 }
272 286
273 287 /*
288 + * Singly-linked Tail queue access methods.
289 + */
290 +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
291 +#define STAILQ_FIRST(head) ((head)->stqh_first)
292 +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
293 +
294 +#define STAILQ_FOREACH(var, head, field) \
295 + for ((var) = STAILQ_FIRST(head); \
296 + (var); \
297 + (var) = STAILQ_NEXT((var), field))
298 +
299 +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
300 + for ((var) = STAILQ_FIRST(head); \
301 + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
302 + (var) = (tvar))
303 +
304 +/*
274 305 * Singly-linked Tail queue functions.
275 306 */
276 307 #define STAILQ_INIT(head) do { \
277 308 (head)->stqh_first = NULL; \
278 309 (head)->stqh_last = &(head)->stqh_first; \
279 310 _NOTE(CONSTCOND) \
280 311 } while (0)
281 312
313 +#define STAILQ_CONCAT(head1, head2) do { \
314 + if (!STAILQ_EMPTY((head2))) { \
315 + *(head1)->stqh_last = (head2)->stqh_first; \
316 + (head1)->stqh_last = (head2)->stqh_last; \
317 + STAILQ_INIT((head2)); \
318 + } \
319 + _NOTE(CONSTCOND) \
320 +} while (0)
321 +
282 322 #define STAILQ_INSERT_HEAD(head, elm, field) do { \
283 323 if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
284 324 (head)->stqh_last = &(elm)->field.stqe_next; \
285 325 (head)->stqh_first = (elm); \
286 326 _NOTE(CONSTCOND) \
287 327 } while (0)
288 328
289 329 #define STAILQ_INSERT_TAIL(head, elm, field) do { \
290 330 (elm)->field.stqe_next = NULL; \
291 331 *(head)->stqh_last = (elm); \
292 332 (head)->stqh_last = &(elm)->field.stqe_next; \
293 333 _NOTE(CONSTCOND) \
294 334 } while (0)
295 335
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
296 336 #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
297 337 if (((elm)->field.stqe_next = (listelm)->field.stqe_next) \
298 338 == NULL) \
299 339 (head)->stqh_last = &(elm)->field.stqe_next; \
300 340 (listelm)->field.stqe_next = (elm); \
301 341 _NOTE(CONSTCOND) \
302 342 } while (0)
303 343
304 344 #define STAILQ_REMOVE_HEAD(head, field) do { \
305 345 if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) \
306 - == NULL) \
346 + == NULL) \
307 347 (head)->stqh_last = &(head)->stqh_first; \
308 348 _NOTE(CONSTCOND) \
309 349 } while (0)
310 350
351 +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
352 + if ((STAILQ_NEXT(elm, field) = \
353 + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
354 + (head)->stqh_last = &STAILQ_NEXT((elm), field); \
355 + _NOTE(CONSTCOND) \
356 +} while (0)
357 +
311 358 #define STAILQ_REMOVE(head, elm, type, field) do { \
312 - if ((head)->stqh_first == (elm)) { \
359 + if (STAILQ_FIRST((head)) == (elm)) { \
313 360 STAILQ_REMOVE_HEAD((head), field); \
314 361 } else { \
315 - struct type *curelm = (head)->stqh_first; \
316 - while (curelm->field.stqe_next != (elm)) \
317 - curelm = curelm->field.stqe_next; \
318 - if ((curelm->field.stqe_next = \
319 - curelm->field.stqe_next->field.stqe_next) == NULL) \
320 - (head)->stqh_last = &(curelm)->field.stqe_next; \
362 + struct type *curelm = STAILQ_FIRST(head); \
363 + while (STAILQ_NEXT(curelm, field) != (elm)) \
364 + curelm = STAILQ_NEXT(curelm, field); \
365 + STAILQ_REMOVE_AFTER(head, curelm, field); \
321 366 } \
322 367 _NOTE(CONSTCOND) \
323 368 } while (0)
324 369
325 -#define STAILQ_FOREACH(var, head, field) \
326 - for ((var) = ((head)->stqh_first); \
327 - (var); \
328 - (var) = ((var)->field.stqe_next))
370 +#define STAILQ_LAST(head, type, field) \
371 + (STAILQ_EMPTY((head)) ? NULL : \
372 + container_of((head)->stqh_last, struct type, field.stqe_next))
329 373
330 374 /*
331 - * Singly-linked Tail queue access methods.
332 - */
333 -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
334 -#define STAILQ_FIRST(head) ((head)->stqh_first)
335 -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
336 -
337 -
338 -/*
339 375 * Simple queue definitions.
340 376 */
341 377 #define SIMPLEQ_HEAD(name, type) \
342 378 struct name { \
343 379 struct type *sqh_first; /* first element */ \
344 380 struct type **sqh_last; /* addr of last next element */ \
345 381 }
346 382
347 383 #define SIMPLEQ_HEAD_INITIALIZER(head) \
348 384 { NULL, &(head).sqh_first }
349 385
350 386 #define SIMPLEQ_ENTRY(type) \
351 387 struct { \
352 388 struct type *sqe_next; /* next element */ \
353 389 }
354 390
355 391 /*
392 + * Simple queue access methods.
393 + */
394 +#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
395 +#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
396 +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
397 +
398 +#define SIMPLEQ_FOREACH(var, head, field) \
399 + for ((var) = SIMPLEQ_FIRST((head)); \
400 + (var); \
401 + (var) = SIMPLEQ_NEXT((var), field))
402 +
403 +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
404 + for ((var) = SIMPLEQ_FIRST((head)); \
405 + (var) && ((tvar) = SIMPLEQ_NEXT((var), field), 1); \
406 + (var) = (tvar))
407 +
408 +/*
356 409 * Simple queue functions.
357 410 */
358 411 #define SIMPLEQ_INIT(head) do { \
359 412 (head)->sqh_first = NULL; \
360 413 (head)->sqh_last = &(head)->sqh_first; \
361 414 _NOTE(CONSTCOND) \
362 415 } while (0)
363 416
364 417 #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
365 418 if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
366 419 (head)->sqh_last = &(elm)->field.sqe_next; \
367 420 (head)->sqh_first = (elm); \
368 421 _NOTE(CONSTCOND) \
369 422 } while (0)
370 423
371 424 #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
372 425 (elm)->field.sqe_next = NULL; \
373 426 *(head)->sqh_last = (elm); \
374 427 (head)->sqh_last = &(elm)->field.sqe_next; \
375 428 _NOTE(CONSTCOND) \
376 429 } while (0)
377 430
378 431 #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
379 432 if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
380 433 (head)->sqh_last = &(elm)->field.sqe_next; \
381 434 (listelm)->field.sqe_next = (elm); \
382 435 _NOTE(CONSTCOND) \
383 436 } while (0)
384 437
385 438 #define SIMPLEQ_REMOVE_HEAD(head, field) do { \
386 439 if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
387 440 (head)->sqh_last = &(head)->sqh_first; \
388 441 _NOTE(CONSTCOND) \
389 442 } while (0)
390 443
391 444 #define SIMPLEQ_REMOVE(head, elm, type, field) do { \
392 445 if ((head)->sqh_first == (elm)) { \
393 446 SIMPLEQ_REMOVE_HEAD((head), field); \
394 447 } else { \
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
395 448 struct type *curelm = (head)->sqh_first; \
396 449 while (curelm->field.sqe_next != (elm)) \
397 450 curelm = curelm->field.sqe_next; \
398 451 if ((curelm->field.sqe_next = \
399 452 curelm->field.sqe_next->field.sqe_next) == NULL) \
400 453 (head)->sqh_last = &(curelm)->field.sqe_next; \
401 454 } \
402 455 _NOTE(CONSTCOND) \
403 456 } while (0)
404 457
405 -#define SIMPLEQ_FOREACH(var, head, field) \
406 - for ((var) = ((head)->sqh_first); \
407 - (var); \
408 - (var) = ((var)->field.sqe_next))
409 458
410 459 /*
411 - * Simple queue access methods.
412 - */
413 -#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
414 -#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
415 -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
416 -
417 -
418 -/*
419 460 * Tail queue definitions.
420 461 */
421 462 #define _TAILQ_HEAD(name, type) \
422 463 struct name { \
423 464 type *tqh_first; /* first element */ \
424 465 type **tqh_last; /* addr of last next element */ \
425 466 }
426 467 #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type)
427 468
428 469 #define TAILQ_HEAD_INITIALIZER(head) \
429 470 { NULL, &(head).tqh_first }
430 471
431 472 #define _TAILQ_ENTRY(type) \
432 473 struct { \
433 474 type *tqe_next; /* next element */ \
434 475 type **tqe_prev; /* address of previous next element */\
435 476 }
436 477 #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type)
437 478
438 479 /*
480 + * Tail queue access methods.
481 + */
482 +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
483 +#define TAILQ_FIRST(head) ((head)->tqh_first)
484 +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
485 +#define TAILQ_LAST(head, headname) \
486 + (*(((struct headname *)((head)->tqh_last))->tqh_last))
487 +#define TAILQ_PREV(elm, headname, field) \
488 + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
489 +
490 +
491 +#define TAILQ_FOREACH(var, head, field) \
492 + for ((var) = TAILQ_FIRST((head)); \
493 + (var); \
494 + (var) = TAILQ_NEXT((var), field))
495 +
496 +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
497 + for ((var) = TAILQ_FIRST((head)); \
498 + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
499 + (var) = (tvar))
500 +
501 +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
502 + for ((var) = TAILQ_LAST((head), headname); \
503 + (var); \
504 + (var) = TAILQ_PREV((var), headname, field))
505 +
506 +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
507 + for ((var) = TAILQ_LAST((head), headname); \
508 + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
509 + (var) = (tvar))
510 +
511 +/*
439 512 * Tail queue functions.
440 513 */
441 514 #if defined(_KERNEL) && defined(QUEUEDEBUG)
442 515 #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
443 516 if ((head)->tqh_first && \
444 517 (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
445 518 panic("TAILQ_INSERT_HEAD %p %s:%d", (void *)(head), \
446 519 __FILE__, __LINE__);
447 520 #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
448 521 if (*(head)->tqh_last != NULL) \
449 522 panic("TAILQ_INSERT_TAIL %p %s:%d", (void *)(head), \
450 523 __FILE__, __LINE__);
451 524 #define QUEUEDEBUG_TAILQ_OP(elm, field) \
452 525 if ((elm)->field.tqe_next && \
453 526 (elm)->field.tqe_next->field.tqe_prev != \
454 527 &(elm)->field.tqe_next) \
455 528 panic("TAILQ_* forw %p %s:%d", (void *)(elm), \
456 529 __FILE__, __LINE__);\
457 530 if (*(elm)->field.tqe_prev != (elm)) \
458 531 panic("TAILQ_* back %p %s:%d", (void *)(elm), \
459 532 __FILE__, __LINE__);
460 533 #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
461 534 if ((elm)->field.tqe_next == NULL && \
462 535 (head)->tqh_last != &(elm)->field.tqe_next) \
463 536 panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \
464 537 (void *)(head), (void *)(elm), __FILE__, __LINE__);
465 538 #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
466 539 (elm)->field.tqe_next = (void *)1L; \
467 540 (elm)->field.tqe_prev = (void *)1L;
468 541 #else
469 542 #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
470 543 #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
471 544 #define QUEUEDEBUG_TAILQ_OP(elm, field)
472 545 #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
473 546 #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
474 547 #endif
475 548
476 549 #define TAILQ_INIT(head) do { \
477 550 (head)->tqh_first = NULL; \
478 551 (head)->tqh_last = &(head)->tqh_first; \
479 552 _NOTE(CONSTCOND) \
480 553 } while (0)
481 554
482 555 #define TAILQ_INSERT_HEAD(head, elm, field) do { \
483 556 QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
484 557 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
485 558 (head)->tqh_first->field.tqe_prev = \
486 559 &(elm)->field.tqe_next; \
487 560 else \
488 561 (head)->tqh_last = &(elm)->field.tqe_next; \
489 562 (head)->tqh_first = (elm); \
490 563 (elm)->field.tqe_prev = &(head)->tqh_first; \
491 564 _NOTE(CONSTCOND) \
492 565 } while (0)
493 566
494 567 #define TAILQ_INSERT_TAIL(head, elm, field) do { \
495 568 QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
496 569 (elm)->field.tqe_next = NULL; \
497 570 (elm)->field.tqe_prev = (head)->tqh_last; \
498 571 *(head)->tqh_last = (elm); \
499 572 (head)->tqh_last = &(elm)->field.tqe_next; \
500 573 _NOTE(CONSTCOND) \
501 574 } while (0)
502 575
503 576 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
504 577 QUEUEDEBUG_TAILQ_OP((listelm), field) \
505 578 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
506 579 (elm)->field.tqe_next->field.tqe_prev = \
507 580 &(elm)->field.tqe_next; \
508 581 else \
509 582 (head)->tqh_last = &(elm)->field.tqe_next; \
510 583 (listelm)->field.tqe_next = (elm); \
511 584 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
512 585 _NOTE(CONSTCOND) \
513 586 } while (0)
514 587
515 588 #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
516 589 QUEUEDEBUG_TAILQ_OP((listelm), field) \
517 590 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
518 591 (elm)->field.tqe_next = (listelm); \
519 592 *(listelm)->field.tqe_prev = (elm); \
520 593 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
521 594 _NOTE(CONSTCOND) \
522 595 } while (0)
523 596
524 597 #define TAILQ_REMOVE(head, elm, field) do { \
525 598 QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
526 599 QUEUEDEBUG_TAILQ_OP((elm), field) \
|
↓ open down ↓ |
78 lines elided |
↑ open up ↑ |
527 600 if (((elm)->field.tqe_next) != NULL) \
528 601 (elm)->field.tqe_next->field.tqe_prev = \
529 602 (elm)->field.tqe_prev; \
530 603 else \
531 604 (head)->tqh_last = (elm)->field.tqe_prev; \
532 605 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
533 606 QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
534 607 _NOTE(CONSTCOND) \
535 608 } while (0)
536 609
537 -#define TAILQ_FOREACH(var, head, field) \
538 - for ((var) = ((head)->tqh_first); \
539 - (var); \
540 - (var) = ((var)->field.tqe_next))
541 610
542 -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
543 - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
544 - (var); \
545 - (var) = \
546 - (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
547 -
548 611 /*
549 - * Tail queue access methods.
550 - */
551 -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
552 -#define TAILQ_FIRST(head) ((head)->tqh_first)
553 -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
554 -
555 -#define TAILQ_LAST(head, headname) \
556 - (*(((struct headname *)((head)->tqh_last))->tqh_last))
557 -#define TAILQ_PREV(elm, headname, field) \
558 - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
559 -
560 -
561 -/*
562 612 * Circular queue definitions.
563 613 */
564 614 #define CIRCLEQ_HEAD(name, type) \
565 615 struct name { \
566 616 struct type *cqh_first; /* first element */ \
567 617 struct type *cqh_last; /* last element */ \
568 618 }
569 619
570 620 #define CIRCLEQ_HEAD_INITIALIZER(head) \
571 621 { (void *)&head, (void *)&head }
572 622
573 623 #define CIRCLEQ_ENTRY(type) \
574 624 struct { \
575 625 struct type *cqe_next; /* next element */ \
576 626 struct type *cqe_prev; /* previous element */ \
577 627 }
578 628
579 629 /*
630 + * Circular queue access methods.
631 + */
632 +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
633 +#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
634 +#define CIRCLEQ_LAST(head) ((head)->cqh_last)
635 +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
636 +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
637 +
638 +#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
639 + (((elm)->field.cqe_next == (void *)(head)) \
640 + ? ((head)->cqh_first) \
641 + : (elm->field.cqe_next))
642 +#define CIRCLEQ_LOOP_PREV(head, elm, field) \
643 + (((elm)->field.cqe_prev == (void *)(head)) \
644 + ? ((head)->cqh_last) \
645 + : (elm->field.cqe_prev))
646 +
647 +#define CIRCLEQ_FOREACH(var, head, field) \
648 + for ((var) = CIRCLEQ_FIRST((head)); \
649 + (var) != (void *)(head); \
650 + (var) = CIRCLEQ_NEXT((var), field))
651 +
652 +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
653 + for ((var) = CIRCLEQ_LAST((head)); \
654 + (var) != (void *)(head); \
655 + (var) = CIRCLEQ_PREV((var), field))
656 +
657 +/*
580 658 * Circular queue functions.
581 659 */
582 660 #define CIRCLEQ_INIT(head) do { \
583 661 (head)->cqh_first = (void *)(head); \
584 662 (head)->cqh_last = (void *)(head); \
585 663 _NOTE(CONSTCOND) \
586 664 } while (0)
587 665
588 666 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
589 667 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
590 668 (elm)->field.cqe_prev = (listelm); \
591 669 if ((listelm)->field.cqe_next == (void *)(head)) \
592 670 (head)->cqh_last = (elm); \
593 671 else \
594 672 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
595 673 (listelm)->field.cqe_next = (elm); \
596 674 _NOTE(CONSTCOND) \
597 675 } while (0)
598 676
599 677 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
600 678 (elm)->field.cqe_next = (listelm); \
601 679 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
602 680 if ((listelm)->field.cqe_prev == (void *)(head)) \
603 681 (head)->cqh_first = (elm); \
604 682 else \
605 683 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
606 684 (listelm)->field.cqe_prev = (elm); \
607 685 _NOTE(CONSTCOND) \
608 686 } while (0)
609 687
610 688 #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
611 689 (elm)->field.cqe_next = (head)->cqh_first; \
612 690 (elm)->field.cqe_prev = (void *)(head); \
613 691 if ((head)->cqh_last == (void *)(head)) \
614 692 (head)->cqh_last = (elm); \
615 693 else \
616 694 (head)->cqh_first->field.cqe_prev = (elm); \
617 695 (head)->cqh_first = (elm); \
618 696 _NOTE(CONSTCOND) \
619 697 } while (0)
620 698
621 699 #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
622 700 (elm)->field.cqe_next = (void *)(head); \
623 701 (elm)->field.cqe_prev = (head)->cqh_last; \
624 702 if ((head)->cqh_first == (void *)(head)) \
625 703 (head)->cqh_first = (elm); \
626 704 else \
627 705 (head)->cqh_last->field.cqe_next = (elm); \
628 706 (head)->cqh_last = (elm); \
629 707 _NOTE(CONSTCOND) \
630 708 } while (0)
631 709
632 710 #define CIRCLEQ_REMOVE(head, elm, field) do { \
633 711 if ((elm)->field.cqe_next == (void *)(head)) \
634 712 (head)->cqh_last = (elm)->field.cqe_prev; \
635 713 else \
|
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
636 714 (elm)->field.cqe_next->field.cqe_prev = \
637 715 (elm)->field.cqe_prev; \
638 716 if ((elm)->field.cqe_prev == (void *)(head)) \
639 717 (head)->cqh_first = (elm)->field.cqe_next; \
640 718 else \
641 719 (elm)->field.cqe_prev->field.cqe_next = \
642 720 (elm)->field.cqe_next; \
643 721 _NOTE(CONSTCOND) \
644 722 } while (0)
645 723
646 -#define CIRCLEQ_FOREACH(var, head, field) \
647 - for ((var) = ((head)->cqh_first); \
648 - (var) != (void *)(head); \
649 - (var) = ((var)->field.cqe_next))
650 724
651 -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
652 - for ((var) = ((head)->cqh_last); \
653 - (var) != (void *)(head); \
654 - (var) = ((var)->field.cqe_prev))
655 -
656 -/*
657 - * Circular queue access methods.
658 - */
659 -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
660 -#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
661 -#define CIRCLEQ_LAST(head) ((head)->cqh_last)
662 -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
663 -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
664 -
665 -#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
666 - (((elm)->field.cqe_next == (void *)(head)) \
667 - ? ((head)->cqh_first) \
668 - : (elm->field.cqe_next))
669 -#define CIRCLEQ_LOOP_PREV(head, elm, field) \
670 - (((elm)->field.cqe_prev == (void *)(head)) \
671 - ? ((head)->cqh_last) \
672 - : (elm->field.cqe_prev))
673 -
674 725 #ifdef __cplusplus
675 726 }
676 727 #endif
677 728
678 729 #endif /* !_SYS_QUEUE_H */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX