source: rtems/cpukit/libnetworking/sys/queue.h @ 36799d4

4.104.114.84.95
Last change on this file since 36799d4 was 36799d4, checked in by Joel Sherrill <joel.sherrill@…>, on 01/03/03 at 18:09:57

2002-11-26 Chris Johns <cjohns@…>

  • Makefile.am: Added sys/linker_set.h
  • kern/Makefile.am: Added kern_mib.c and kern_sysctl.c.
  • kern/uipc_socket.c: OID changed from KERN_SOMAXCONN to KIPC_SOMAXCONN.
  • kern/uipc_socket2.c: OID changed from KERN_MAXSOCKBUF to KIPC_MAXSOCKBUF.
  • net/if_ethersubr.c: FreeBSD 2.2.2 does not have a _net_link node while 5.0 does.
  • net/if_ppp.c: Removed the TEXT_SET define as these macros are now implemented.
  • net/rtsock.c: Enable sysctl support plus fix the bug with the lastest FreeBSD sysctl header file.
  • netinet/icmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_icmp node while 5.0 does.
  • netinet/if_ether.c: FreeBSD 2.2.2 does not have a _net_link_ether node while 5.0 does.
  • netinet/igmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_igmp node while 5.0 does.
  • netinet/in_pcb.c: Fixed the arguments to the sysctl call. Add inp_gencnt and ipi_count. These are used when listing connections.
  • netinet/in_pcb.h: Added counters to aid the listing of connections.
  • netinet/in_var.h: Provide the _net_inet_ip and _net_inet_raw nodes.
  • netinet/ip_fw.c: Disable the firewall sysctl calls.
  • netinet/tcp_subr.c: Merge tcp_pcblist from the lastest FreeBSD source.
  • netinet/tcp_var.h: Add structures needed by net-snmp to list connections.
  • netinet/udp_usrreq.c: Merged udp_pcblist from the lastest FreeBSD source.
  • netinet/udp_var.h: Added the sysctl id UDPCTL_PCBLIST. Used by net-snmp.
  • rtems_glue.c: Call sysctl_register_all when initialising the network stack to register all the sysctl calls. These are in the special sections and required an updated linker script.
  • rtems/rtems_syscall.c: Add the sysctl call.
  • sys/kernel.h: Use the lastest FreeBSD method of handling sysctl structures. This now held in the sys/linker_set.h file.
  • sys/queue.h: This is from the lastest FreeBSD code with the circular code merged back in as it is not used in the lastest FreeBSD kernel.
  • sys/sysctl.h: The lastest sysctl. This was needed to use with the new linker set method. The FreeBSD 2.2.2 version has asm hacks. The lastest version of the FreeBSD does not have these hacks. It uses gcc attribute directives.
  • Property mode set to 100644
File size: 18.8 KB
Line 
1/*
2 * Copyright (c) 1991, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *      @(#)queue.h     8.5 (Berkeley) 8/20/94
34 * $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $
35 */
36
37#ifndef _SYS_QUEUE_H_
38#define _SYS_QUEUE_H_
39
40#include <sys/cdefs.h>
41
42/*
43 * This file defines four types of data structures: singly-linked lists,
44 * singly-linked tail queues, lists and tail queues.
45 *
46 * A singly-linked list is headed by a single forward pointer. The elements
47 * are singly linked for minimum space and pointer manipulation overhead at
48 * the expense of O(n) removal for arbitrary elements. New elements can be
49 * added to the list after an existing element or at the head of the list.
50 * Elements being removed from the head of the list should use the explicit
51 * macro for this purpose for optimum efficiency. A singly-linked list may
52 * only be traversed in the forward direction.  Singly-linked lists are ideal
53 * for applications with large datasets and few or no removals or for
54 * implementing a LIFO queue.
55 *
56 * A singly-linked tail queue is headed by a pair of pointers, one to the
57 * head of the list and the other to the tail of the list. The elements are
58 * singly linked for minimum space and pointer manipulation overhead at the
59 * expense of O(n) removal for arbitrary elements. New elements can be added
60 * to the list after an existing element, at the head of the list, or at the
61 * end of the list. Elements being removed from the head of the tail queue
62 * should use the explicit macro for this purpose for optimum efficiency.
63 * A singly-linked tail queue may only be traversed in the forward direction.
64 * Singly-linked tail queues are ideal for applications with large datasets
65 * and few or no removals or for implementing a FIFO queue.
66 *
67 * A list is headed by a single forward pointer (or an array of forward
68 * pointers for a hash table header). The elements are doubly linked
69 * so that an arbitrary element can be removed without a need to
70 * traverse the list. New elements can be added to the list before
71 * or after an existing element or at the head of the list. A list
72 * may only be traversed in the forward direction.
73 *
74 * A tail queue is headed by a pair of pointers, one to the head of the
75 * list and the other to the tail of the list. The elements are doubly
76 * linked so that an arbitrary element can be removed without a need to
77 * traverse the list. New elements can be added to the list before or
78 * after an existing element, at the head of the list, or at the end of
79 * the list. A tail queue may be traversed in either direction.
80 *
81 * For details on the use of these macros, see the queue(3) manual page.
82 *
83 *
84 *                      SLIST   LIST    STAILQ  TAILQ
85 * _HEAD                +       +       +       +
86 * _HEAD_INITIALIZER    +       +       +       +
87 * _ENTRY               +       +       +       +
88 * _INIT                +       +       +       +
89 * _EMPTY               +       +       +       +
90 * _FIRST               +       +       +       +
91 * _NEXT                +       +       +       +
92 * _PREV                -       -       -       +
93 * _LAST                -       -       +       +
94 * _FOREACH             +       +       +       +
95 * _FOREACH_REVERSE     -       -       -       +
96 * _INSERT_HEAD         +       +       +       +
97 * _INSERT_BEFORE       -       +       -       +
98 * _INSERT_AFTER        +       +       +       +
99 * _INSERT_TAIL         -       -       +       +
100 * _CONCAT              -       -       +       +
101 * _REMOVE_HEAD         +       -       +       -
102 * _REMOVE              +       +       +       +
103 *
104 */
105#define QUEUE_MACRO_DEBUG 0
106#if QUEUE_MACRO_DEBUG
107/* Store the last 2 places the queue element or head was altered */
108struct qm_trace {
109        char * lastfile;
110        int lastline;
111        char * prevfile;
112        int prevline;
113};
114
115#define TRACEBUF        struct qm_trace trace;
116#define TRASHIT(x)      do {(x) = (void *)-1;} while (0)
117
118#define QMD_TRACE_HEAD(head) do {                                       \
119        (head)->trace.prevline = (head)->trace.lastline;                \
120        (head)->trace.prevfile = (head)->trace.lastfile;                \
121        (head)->trace.lastline = __LINE__;                              \
122        (head)->trace.lastfile = __FILE__;                              \
123} while (0)
124
125#define QMD_TRACE_ELEM(elem) do {                                       \
126        (elem)->trace.prevline = (elem)->trace.lastline;                \
127        (elem)->trace.prevfile = (elem)->trace.lastfile;                \
128        (elem)->trace.lastline = __LINE__;                              \
129        (elem)->trace.lastfile = __FILE__;                              \
130} while (0)
131
132#else
133#define QMD_TRACE_ELEM(elem)
134#define QMD_TRACE_HEAD(head)
135#define TRACEBUF
136#define TRASHIT(x)
137#endif  /* QUEUE_MACRO_DEBUG */
138
139/*
140 * Singly-linked List declarations.
141 */
142#define SLIST_HEAD(name, type)                                          \
143struct name {                                                           \
144        struct type *slh_first; /* first element */                     \
145}
146
147#define SLIST_HEAD_INITIALIZER(head)                                    \
148        { NULL }
149 
150#define SLIST_ENTRY(type)                                               \
151struct {                                                                \
152        struct type *sle_next;  /* next element */                      \
153}
154 
155/*
156 * Singly-linked List functions.
157 */
158#define SLIST_EMPTY(head)       ((head)->slh_first == NULL)
159
160#define SLIST_FIRST(head)       ((head)->slh_first)
161
162#define SLIST_FOREACH(var, head, field)                                 \
163        for ((var) = SLIST_FIRST((head));                               \
164            (var);                                                      \
165            (var) = SLIST_NEXT((var), field))
166
167#define SLIST_FOREACH_PREVPTR(var, varp, head, field)                   \
168        for ((varp) = &SLIST_FIRST((head));                             \
169            ((var) = *(varp)) != NULL;                                  \
170            (varp) = &SLIST_NEXT((var), field))
171
172#define SLIST_INIT(head) do {                                           \
173        SLIST_FIRST((head)) = NULL;                                     \
174} while (0)
175
176#define SLIST_INSERT_AFTER(slistelm, elm, field) do {                   \
177        SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);       \
178        SLIST_NEXT((slistelm), field) = (elm);                          \
179} while (0)
180
181#define SLIST_INSERT_HEAD(head, elm, field) do {                        \
182        SLIST_NEXT((elm), field) = SLIST_FIRST((head));                 \
183        SLIST_FIRST((head)) = (elm);                                    \
184} while (0)
185
186#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
187
188#define SLIST_REMOVE(head, elm, type, field) do {                       \
189        if (SLIST_FIRST((head)) == (elm)) {                             \
190                SLIST_REMOVE_HEAD((head), field);                       \
191        }                                                               \
192        else {                                                          \
193                struct type *curelm = SLIST_FIRST((head));              \
194                while (SLIST_NEXT(curelm, field) != (elm))              \
195                        curelm = SLIST_NEXT(curelm, field);             \
196                SLIST_NEXT(curelm, field) =                             \
197                    SLIST_NEXT(SLIST_NEXT(curelm, field), field);       \
198        }                                                               \
199} while (0)
200
201#define SLIST_REMOVE_HEAD(head, field) do {                             \
202        SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);   \
203} while (0)
204
205/*
206 * Singly-linked Tail queue declarations.
207 */
208#define STAILQ_HEAD(name, type)                                         \
209struct name {                                                           \
210        struct type *stqh_first;/* first element */                     \
211        struct type **stqh_last;/* addr of last next element */         \
212}
213
214#define STAILQ_HEAD_INITIALIZER(head)                                   \
215        { NULL, &(head).stqh_first }
216
217#define STAILQ_ENTRY(type)                                              \
218struct {                                                                \
219        struct type *stqe_next; /* next element */                      \
220}
221
222/*
223 * Singly-linked Tail queue functions.
224 */
225#define STAILQ_CONCAT(head1, head2) do {                                \
226        if (!STAILQ_EMPTY((head2))) {                                   \
227                *(head1)->stqh_last = (head2)->stqh_first;              \
228                (head1)->stqh_last = (head2)->stqh_last;                \
229                STAILQ_INIT((head2));                                   \
230        }                                                               \
231} while (0)
232
233#define STAILQ_EMPTY(head)      ((head)->stqh_first == NULL)
234
235#define STAILQ_FIRST(head)      ((head)->stqh_first)
236
237#define STAILQ_FOREACH(var, head, field)                                \
238        for((var) = STAILQ_FIRST((head));                               \
239           (var);                                                       \
240           (var) = STAILQ_NEXT((var), field))
241
242#define STAILQ_INIT(head) do {                                          \
243        STAILQ_FIRST((head)) = NULL;                                    \
244        (head)->stqh_last = &STAILQ_FIRST((head));                      \
245} while (0)
246
247#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {               \
248        if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
249                (head)->stqh_last = &STAILQ_NEXT((elm), field);         \
250        STAILQ_NEXT((tqelm), field) = (elm);                            \
251} while (0)
252
253#define STAILQ_INSERT_HEAD(head, elm, field) do {                       \
254        if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
255                (head)->stqh_last = &STAILQ_NEXT((elm), field);         \
256        STAILQ_FIRST((head)) = (elm);                                   \
257} while (0)
258
259#define STAILQ_INSERT_TAIL(head, elm, field) do {                       \
260        STAILQ_NEXT((elm), field) = NULL;                               \
261        *(head)->stqh_last = (elm);                                     \
262        (head)->stqh_last = &STAILQ_NEXT((elm), field);                 \
263} while (0)
264
265#define STAILQ_LAST(head, type, field)                                  \
266        (STAILQ_EMPTY((head)) ?                                         \
267                NULL :                                                  \
268                ((struct type *)                                        \
269                ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
270
271#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
272
273#define STAILQ_REMOVE(head, elm, type, field) do {                      \
274        if (STAILQ_FIRST((head)) == (elm)) {                            \
275                STAILQ_REMOVE_HEAD((head), field);                      \
276        }                                                               \
277        else {                                                          \
278                struct type *curelm = STAILQ_FIRST((head));             \
279                while (STAILQ_NEXT(curelm, field) != (elm))             \
280                        curelm = STAILQ_NEXT(curelm, field);            \
281                if ((STAILQ_NEXT(curelm, field) =                       \
282                     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
283                        (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
284        }                                                               \
285} while (0)
286
287#define STAILQ_REMOVE_HEAD(head, field) do {                            \
288        if ((STAILQ_FIRST((head)) =                                     \
289             STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)         \
290                (head)->stqh_last = &STAILQ_FIRST((head));              \
291} while (0)
292
293#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {                 \
294        if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
295                (head)->stqh_last = &STAILQ_FIRST((head));              \
296} while (0)
297
298/*
299 * List declarations.
300 */
301#define LIST_HEAD(name, type)                                           \
302struct name {                                                           \
303        struct type *lh_first;  /* first element */                     \
304}
305
306#define LIST_HEAD_INITIALIZER(head)                                     \
307        { NULL }
308
309#define LIST_ENTRY(type)                                                \
310struct {                                                                \
311        struct type *le_next;   /* next element */                      \
312        struct type **le_prev;  /* address of previous next element */  \
313}
314
315/*
316 * List functions.
317 */
318
319#define LIST_EMPTY(head)        ((head)->lh_first == NULL)
320
321#define LIST_FIRST(head)        ((head)->lh_first)
322
323#define LIST_FOREACH(var, head, field)                                  \
324        for ((var) = LIST_FIRST((head));                                \
325            (var);                                                      \
326            (var) = LIST_NEXT((var), field))
327
328#define LIST_INIT(head) do {                                            \
329        LIST_FIRST((head)) = NULL;                                      \
330} while (0)
331
332#define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
333        if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
334                LIST_NEXT((listelm), field)->field.le_prev =            \
335                    &LIST_NEXT((elm), field);                           \
336        LIST_NEXT((listelm), field) = (elm);                            \
337        (elm)->field.le_prev = &LIST_NEXT((listelm), field);            \
338} while (0)
339
340#define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
341        (elm)->field.le_prev = (listelm)->field.le_prev;                \
342        LIST_NEXT((elm), field) = (listelm);                            \
343        *(listelm)->field.le_prev = (elm);                              \
344        (listelm)->field.le_prev = &LIST_NEXT((elm), field);            \
345} while (0)
346
347#define LIST_INSERT_HEAD(head, elm, field) do {                         \
348        if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)     \
349                LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
350        LIST_FIRST((head)) = (elm);                                     \
351        (elm)->field.le_prev = &LIST_FIRST((head));                     \
352} while (0)
353
354#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
355
356#define LIST_REMOVE(elm, field) do {                                    \
357        if (LIST_NEXT((elm), field) != NULL)                            \
358                LIST_NEXT((elm), field)->field.le_prev =                \
359                    (elm)->field.le_prev;                               \
360        *(elm)->field.le_prev = LIST_NEXT((elm), field);                \
361} while (0)
362
363/*
364 * Tail queue declarations.
365 */
366#define TAILQ_HEAD(name, type)                                          \
367struct name {                                                           \
368        struct type *tqh_first; /* first element */                     \
369        struct type **tqh_last; /* addr of last next element */         \
370        TRACEBUF                                                        \
371}
372
373#define TAILQ_HEAD_INITIALIZER(head)                                    \
374        { NULL, &(head).tqh_first }
375
376#define TAILQ_ENTRY(type)                                               \
377struct {                                                                \
378        struct type *tqe_next;  /* next element */                      \
379        struct type **tqe_prev; /* address of previous next element */  \
380        TRACEBUF                                                        \
381}
382
383/*
384 * Tail queue functions.
385 */
386#define TAILQ_CONCAT(head1, head2, field) do {                          \
387        if (!TAILQ_EMPTY(head2)) {                                      \
388                *(head1)->tqh_last = (head2)->tqh_first;                \
389                (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
390                (head1)->tqh_last = (head2)->tqh_last;                  \
391                TAILQ_INIT((head2));                                    \
392                QMD_TRACE_HEAD(head);                                   \
393                QMD_TRACE_HEAD(head2);                                  \
394        }                                                               \
395} while (0)
396
397#define TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
398
399#define TAILQ_FIRST(head)       ((head)->tqh_first)
400
401#define TAILQ_FOREACH(var, head, field)                                 \
402        for ((var) = TAILQ_FIRST((head));                               \
403            (var);                                                      \
404            (var) = TAILQ_NEXT((var), field))
405
406#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
407        for ((var) = TAILQ_LAST((head), headname);                      \
408            (var);                                                      \
409            (var) = TAILQ_PREV((var), headname, field))
410
411#define TAILQ_INIT(head) do {                                           \
412        TAILQ_FIRST((head)) = NULL;                                     \
413        (head)->tqh_last = &TAILQ_FIRST((head));                        \
414        QMD_TRACE_HEAD(head);                                           \
415} while (0)
416
417#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
418        if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
419                TAILQ_NEXT((elm), field)->field.tqe_prev =              \
420                    &TAILQ_NEXT((elm), field);                          \
421        else {                                                          \
422                (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
423                QMD_TRACE_HEAD(head);                                   \
424        }                                                               \
425        TAILQ_NEXT((listelm), field) = (elm);                           \
426        (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);          \
427        QMD_TRACE_ELEM(&(elm)->field);                                  \
428        QMD_TRACE_ELEM(&listelm->field);                                \
429} while (0)
430
431#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
432        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
433        TAILQ_NEXT((elm), field) = (listelm);                           \
434        *(listelm)->field.tqe_prev = (elm);                             \
435        (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);          \
436        QMD_TRACE_ELEM(&(elm)->field);                                  \
437        QMD_TRACE_ELEM(&listelm->field);                                \
438} while (0)
439
440#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
441        if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   \
442                TAILQ_FIRST((head))->field.tqe_prev =                   \
443                    &TAILQ_NEXT((elm), field);                          \
444        else                                                            \
445                (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
446        TAILQ_FIRST((head)) = (elm);                                    \
447        (elm)->field.tqe_prev = &TAILQ_FIRST((head));                   \
448        QMD_TRACE_HEAD(head);                                           \
449        QMD_TRACE_ELEM(&(elm)->field);                                  \
450} while (0)
451
452#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
453        TAILQ_NEXT((elm), field) = NULL;                                \
454        (elm)->field.tqe_prev = (head)->tqh_last;                       \
455        *(head)->tqh_last = (elm);                                      \
456        (head)->tqh_last = &TAILQ_NEXT((elm), field);                   \
457        QMD_TRACE_HEAD(head);                                           \
458        QMD_TRACE_ELEM(&(elm)->field);                                  \
459} while (0)
460
461#define TAILQ_LAST(head, headname)                                      \
462        (*(((struct headname *)((head)->tqh_last))->tqh_last))
463
464#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
465
466#define TAILQ_PREV(elm, headname, field)                                \
467        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
468
469#define TAILQ_REMOVE(head, elm, field) do {                             \
470        if ((TAILQ_NEXT((elm), field)) != NULL)                         \
471                TAILQ_NEXT((elm), field)->field.tqe_prev =              \
472                    (elm)->field.tqe_prev;                              \
473        else {                                                          \
474                (head)->tqh_last = (elm)->field.tqe_prev;               \
475                QMD_TRACE_HEAD(head);                                   \
476        }                                                               \
477        *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);              \
478        TRASHIT((elm)->field.tqe_next);                                 \
479        TRASHIT((elm)->field.tqe_prev);                                 \
480        QMD_TRACE_ELEM(&(elm)->field);                                  \
481} while (0)
482
483
484/*
485 * Circular queue definitions.
486 */
487#define CIRCLEQ_HEAD(name, type)                                        \
488struct name {                                                           \
489        struct type *cqh_first;         /* first element */             \
490        struct type *cqh_last;          /* last element */              \
491}
492
493#define CIRCLEQ_ENTRY(type)                                             \
494struct {                                                                \
495        struct type *cqe_next;          /* next element */              \
496        struct type *cqe_prev;          /* previous element */          \
497}
498
499/*
500 * Circular queue functions.
501 */
502#define CIRCLEQ_INIT(head) {                                            \
503        (head)->cqh_first = (void *)(head);                             \
504        (head)->cqh_last = (void *)(head);                              \
505}
506
507#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {               \
508        (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
509        (elm)->field.cqe_prev = (listelm);                              \
510        if ((listelm)->field.cqe_next == (void *)(head))                \
511                (head)->cqh_last = (elm);                               \
512        else                                                            \
513                (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
514        (listelm)->field.cqe_next = (elm);                              \
515}
516
517#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {              \
518        (elm)->field.cqe_next = (listelm);                              \
519        (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
520        if ((listelm)->field.cqe_prev == (void *)(head))                \
521                (head)->cqh_first = (elm);                              \
522        else                                                            \
523                (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
524        (listelm)->field.cqe_prev = (elm);                              \
525}
526
527#define CIRCLEQ_INSERT_HEAD(head, elm, field) {                         \
528        (elm)->field.cqe_next = (head)->cqh_first;                      \
529        (elm)->field.cqe_prev = (void *)(head);                         \
530        if ((head)->cqh_last == (void *)(head))                         \
531                (head)->cqh_last = (elm);                               \
532        else                                                            \
533                (head)->cqh_first->field.cqe_prev = (elm);              \
534        (head)->cqh_first = (elm);                                      \
535}
536
537#define CIRCLEQ_INSERT_TAIL(head, elm, field) {                         \
538        (elm)->field.cqe_next = (void *)(head);                         \
539        (elm)->field.cqe_prev = (head)->cqh_last;                       \
540        if ((head)->cqh_first == (void *)(head))                        \
541                (head)->cqh_first = (elm);                              \
542        else                                                            \
543                (head)->cqh_last->field.cqe_next = (elm);               \
544        (head)->cqh_last = (elm);                                       \
545}
546
547#define CIRCLEQ_REMOVE(head, elm, field) {                              \
548        if ((elm)->field.cqe_next == (void *)(head))                    \
549                (head)->cqh_last = (elm)->field.cqe_prev;               \
550        else                                                            \
551                (elm)->field.cqe_next->field.cqe_prev =                 \
552                    (elm)->field.cqe_prev;                              \
553        if ((elm)->field.cqe_prev == (void *)(head))                    \
554                (head)->cqh_first = (elm)->field.cqe_next;              \
555        else                                                            \
556                (elm)->field.cqe_prev->field.cqe_next =                 \
557                    (elm)->field.cqe_next;                              \
558}
559
560#ifdef KERNEL
561
562/*
563 * XXX insque() and remque() are an old way of handling certain queues.
564 * They bogusly assumes that all queue heads look alike.
565 */
566
567struct quehead {
568        struct quehead *qh_link;
569        struct quehead *qh_rlink;
570};
571
572#ifdef  __GNUC__
573
574static __inline void
575insque(void *a, void *b)
576{
577        struct quehead *element = (struct quehead *)a,
578                 *head = (struct quehead *)b;
579
580        element->qh_link = head->qh_link;
581        element->qh_rlink = head;
582        head->qh_link = element;
583        element->qh_link->qh_rlink = element;
584}
585
586static __inline void
587remque(void *a)
588{
589        struct quehead *element = (struct quehead *)a;
590
591        element->qh_link->qh_rlink = element->qh_rlink;
592        element->qh_rlink->qh_link = element->qh_link;
593        element->qh_rlink = 0;
594}
595
596#else /* !__GNUC__ */
597
598void    insque(void *a, void *b);
599void    remque(void *a);
600
601#endif /* __GNUC__ */
602
603#endif /* _KERNEL */
604
605#endif /* !_SYS_QUEUE_H_ */
Note: See TracBrowser for help on using the repository browser.