queue.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* $NetBSD: queue.h,v 1.68.2.1 2015/12/27 12:10:18 skrll Exp $ */
  2. /*
  3. * Copyright (c) 1991, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * @(#)queue.h 8.5 (Berkeley) 8/20/94
  31. */
  32. /*
  33. * Tail queue definitions.
  34. */
  35. #define _TAILQ_HEAD(name, type, qual) \
  36. struct name { \
  37. qual type *tqh_first; /* first element */ \
  38. qual type *qual *tqh_last; /* addr of last next element */ \
  39. }
  40. #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
  41. #define TAILQ_HEAD_INITIALIZER(head) \
  42. { TAILQ_END(head), &(head).tqh_first }
  43. #define _TAILQ_ENTRY(type, qual) \
  44. struct { \
  45. qual type *tqe_next; /* next element */ \
  46. qual type *qual *tqe_prev; /* address of previous next element */\
  47. }
  48. #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
  49. /*
  50. * Tail queue access methods.
  51. */
  52. #define TAILQ_FIRST(head) ((head)->tqh_first)
  53. #define TAILQ_END(head) (NULL)
  54. #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
  55. #define TAILQ_LAST(head, headname) \
  56. (*(((struct headname *)(void *)((head)->tqh_last))->tqh_last))
  57. #define TAILQ_PREV(elm, headname, field) \
  58. (*(((struct headname *)(void *)((elm)->field.tqe_prev))->tqh_last))
  59. #define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head))
  60. #define TAILQ_FOREACH(var, head, field) \
  61. for ((var) = ((head)->tqh_first); \
  62. (var) != TAILQ_END(head); \
  63. (var) = ((var)->field.tqe_next))
  64. #define TAILQ_FOREACH_SAFE(var, head, field, next) \
  65. for ((var) = ((head)->tqh_first); \
  66. (var) != TAILQ_END(head) && \
  67. ((next) = TAILQ_NEXT(var, field), 1); (var) = (next))
  68. #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
  69. for ((var) = TAILQ_LAST((head), headname); \
  70. (var) != TAILQ_END(head); \
  71. (var) = TAILQ_PREV((var), headname, field))
  72. #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
  73. for ((var) = TAILQ_LAST((head), headname); \
  74. (var) != TAILQ_END(head) && \
  75. ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev))
  76. /*
  77. * Tail queue functions.
  78. */
  79. #if defined(QUEUEDEBUG)
  80. #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
  81. if ((head)->tqh_first && \
  82. (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
  83. QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \
  84. __FILE__, __LINE__);
  85. #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
  86. if (*(head)->tqh_last != NULL) \
  87. QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \
  88. __FILE__, __LINE__);
  89. #define QUEUEDEBUG_TAILQ_OP(elm, field) \
  90. if ((elm)->field.tqe_next && \
  91. (elm)->field.tqe_next->field.tqe_prev != \
  92. &(elm)->field.tqe_next) \
  93. QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \
  94. __FILE__, __LINE__); \
  95. if (*(elm)->field.tqe_prev != (elm)) \
  96. QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \
  97. __FILE__, __LINE__);
  98. #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
  99. if ((elm)->field.tqe_next == NULL && \
  100. (head)->tqh_last != &(elm)->field.tqe_next) \
  101. QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\
  102. (head), (elm), __FILE__, __LINE__);
  103. #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
  104. (elm)->field.tqe_next = (void *)1L; \
  105. (elm)->field.tqe_prev = (void *)1L;
  106. #else
  107. #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
  108. #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
  109. #define QUEUEDEBUG_TAILQ_OP(elm, field)
  110. #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
  111. #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
  112. #endif
  113. #define TAILQ_INIT(head) do { \
  114. (head)->tqh_first = TAILQ_END(head); \
  115. (head)->tqh_last = &(head)->tqh_first; \
  116. } while (/*CONSTCOND*/0)
  117. #define TAILQ_INSERT_HEAD(head, elm, field) do { \
  118. QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
  119. if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\
  120. (head)->tqh_first->field.tqe_prev = \
  121. &(elm)->field.tqe_next; \
  122. else \
  123. (head)->tqh_last = &(elm)->field.tqe_next; \
  124. (head)->tqh_first = (elm); \
  125. (elm)->field.tqe_prev = &(head)->tqh_first; \
  126. } while (/*CONSTCOND*/0)
  127. #define TAILQ_INSERT_TAIL(head, elm, field) do { \
  128. QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
  129. (elm)->field.tqe_next = TAILQ_END(head); \
  130. (elm)->field.tqe_prev = (head)->tqh_last; \
  131. *(head)->tqh_last = (elm); \
  132. (head)->tqh_last = &(elm)->field.tqe_next; \
  133. } while (/*CONSTCOND*/0)
  134. #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
  135. QUEUEDEBUG_TAILQ_OP((listelm), field) \
  136. if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \
  137. TAILQ_END(head)) \
  138. (elm)->field.tqe_next->field.tqe_prev = \
  139. &(elm)->field.tqe_next; \
  140. else \
  141. (head)->tqh_last = &(elm)->field.tqe_next; \
  142. (listelm)->field.tqe_next = (elm); \
  143. (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
  144. } while (/*CONSTCOND*/0)
  145. #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
  146. QUEUEDEBUG_TAILQ_OP((listelm), field) \
  147. (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
  148. (elm)->field.tqe_next = (listelm); \
  149. *(listelm)->field.tqe_prev = (elm); \
  150. (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
  151. } while (/*CONSTCOND*/0)
  152. #define TAILQ_REMOVE(head, elm, field) do { \
  153. QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
  154. QUEUEDEBUG_TAILQ_OP((elm), field) \
  155. if (((elm)->field.tqe_next) != TAILQ_END(head)) \
  156. (elm)->field.tqe_next->field.tqe_prev = \
  157. (elm)->field.tqe_prev; \
  158. else \
  159. (head)->tqh_last = (elm)->field.tqe_prev; \
  160. *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
  161. QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
  162. } while (/*CONSTCOND*/0)
  163. #define TAILQ_REPLACE(head, elm, elm2, field) do { \
  164. if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \
  165. TAILQ_END(head)) \
  166. (elm2)->field.tqe_next->field.tqe_prev = \
  167. &(elm2)->field.tqe_next; \
  168. else \
  169. (head)->tqh_last = &(elm2)->field.tqe_next; \
  170. (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
  171. *(elm2)->field.tqe_prev = (elm2); \
  172. QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
  173. } while (/*CONSTCOND*/0)
  174. #define TAILQ_CONCAT(head1, head2, field) do { \
  175. if (!TAILQ_EMPTY(head2)) { \
  176. *(head1)->tqh_last = (head2)->tqh_first; \
  177. (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
  178. (head1)->tqh_last = (head2)->tqh_last; \
  179. TAILQ_INIT((head2)); \
  180. } \
  181. } while (/*CONSTCOND*/0)