nutcracker 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. data/README.md +22 -0
  2. data/Rakefile +55 -0
  3. data/bin/nutcracker +2 -0
  4. data/ext/nutcracker/ChangeLog +66 -0
  5. data/ext/nutcracker/LICENSE +177 -0
  6. data/ext/nutcracker/Makefile.am +7 -0
  7. data/ext/nutcracker/Makefile.in +726 -0
  8. data/ext/nutcracker/NOTICE +124 -0
  9. data/ext/nutcracker/README.md +240 -0
  10. data/ext/nutcracker/aclocal.m4 +956 -0
  11. data/ext/nutcracker/conf/nutcracker.leaf.yml +10 -0
  12. data/ext/nutcracker/conf/nutcracker.root.yml +8 -0
  13. data/ext/nutcracker/conf/nutcracker.yml +67 -0
  14. data/ext/nutcracker/config.h.in +316 -0
  15. data/ext/nutcracker/config/config.guess +1561 -0
  16. data/ext/nutcracker/config/config.sub +1686 -0
  17. data/ext/nutcracker/config/depcomp +630 -0
  18. data/ext/nutcracker/config/install-sh +520 -0
  19. data/ext/nutcracker/config/ltmain.sh +8413 -0
  20. data/ext/nutcracker/config/missing +376 -0
  21. data/ext/nutcracker/configure +18862 -0
  22. data/ext/nutcracker/configure.ac +155 -0
  23. data/ext/nutcracker/contrib/Makefile.am +3 -0
  24. data/ext/nutcracker/contrib/Makefile.in +560 -0
  25. data/ext/nutcracker/contrib/yaml-0.1.4.tar.gz +0 -0
  26. data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +19 -0
  27. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +20 -0
  28. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +736 -0
  29. data/ext/nutcracker/contrib/yaml-0.1.4/README +27 -0
  30. data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +956 -0
  31. data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +80 -0
  32. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +1561 -0
  33. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +1686 -0
  34. data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +630 -0
  35. data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +520 -0
  36. data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +8406 -0
  37. data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +376 -0
  38. data/ext/nutcracker/contrib/yaml-0.1.4/configure +13085 -0
  39. data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +75 -0
  40. data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +222 -0
  41. data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +1971 -0
  42. data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +7357 -0
  43. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +368 -0
  44. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +123 -0
  45. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +23 -0
  46. data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +92 -0
  47. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +4 -0
  48. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +484 -0
  49. data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +1392 -0
  50. data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +394 -0
  51. data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +2329 -0
  52. data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +432 -0
  53. data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +1374 -0
  54. data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +465 -0
  55. data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +3570 -0
  56. data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +141 -0
  57. data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +640 -0
  58. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +8 -0
  59. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +675 -0
  60. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +800 -0
  61. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +1130 -0
  62. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +217 -0
  63. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +202 -0
  64. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +311 -0
  65. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +327 -0
  66. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +63 -0
  67. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +63 -0
  68. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +63 -0
  69. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +354 -0
  70. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +29 -0
  71. data/ext/nutcracker/extconf.rb +5 -0
  72. data/ext/nutcracker/m4/libtool.m4 +7376 -0
  73. data/ext/nutcracker/m4/ltoptions.m4 +368 -0
  74. data/ext/nutcracker/m4/ltsugar.m4 +123 -0
  75. data/ext/nutcracker/m4/ltversion.m4 +23 -0
  76. data/ext/nutcracker/m4/lt~obsolete.m4 +92 -0
  77. data/ext/nutcracker/notes/c-styleguide.txt +425 -0
  78. data/ext/nutcracker/notes/debug.txt +96 -0
  79. data/ext/nutcracker/notes/memcache.txt +123 -0
  80. data/ext/nutcracker/notes/recommendation.md +118 -0
  81. data/ext/nutcracker/notes/redis.md +415 -0
  82. data/ext/nutcracker/notes/socket.txt +131 -0
  83. data/ext/nutcracker/scripts/multi_get.sh +26 -0
  84. data/ext/nutcracker/scripts/nutcracker.init +73 -0
  85. data/ext/nutcracker/scripts/nutcracker.spec +52 -0
  86. data/ext/nutcracker/scripts/pipelined_read.sh +23 -0
  87. data/ext/nutcracker/scripts/pipelined_write.sh +29 -0
  88. data/ext/nutcracker/scripts/populate_memcached.sh +24 -0
  89. data/ext/nutcracker/scripts/redis-check.py +23 -0
  90. data/ext/nutcracker/scripts/redis-check.sh +564 -0
  91. data/ext/nutcracker/src/Makefile.am +46 -0
  92. data/ext/nutcracker/src/Makefile.in +726 -0
  93. data/ext/nutcracker/src/hashkit/Makefile.am +22 -0
  94. data/ext/nutcracker/src/hashkit/Makefile.in +501 -0
  95. data/ext/nutcracker/src/hashkit/nc_crc32.c +105 -0
  96. data/ext/nutcracker/src/hashkit/nc_fnv.c +82 -0
  97. data/ext/nutcracker/src/hashkit/nc_hashkit.h +74 -0
  98. data/ext/nutcracker/src/hashkit/nc_hsieh.c +93 -0
  99. data/ext/nutcracker/src/hashkit/nc_jenkins.c +230 -0
  100. data/ext/nutcracker/src/hashkit/nc_ketama.c +240 -0
  101. data/ext/nutcracker/src/hashkit/nc_md5.c +379 -0
  102. data/ext/nutcracker/src/hashkit/nc_modula.c +144 -0
  103. data/ext/nutcracker/src/hashkit/nc_murmur.c +99 -0
  104. data/ext/nutcracker/src/hashkit/nc_one_at_a_time.c +51 -0
  105. data/ext/nutcracker/src/hashkit/nc_random.c +146 -0
  106. data/ext/nutcracker/src/nc.c +573 -0
  107. data/ext/nutcracker/src/nc_array.c +204 -0
  108. data/ext/nutcracker/src/nc_array.h +73 -0
  109. data/ext/nutcracker/src/nc_client.c +189 -0
  110. data/ext/nutcracker/src/nc_client.h +28 -0
  111. data/ext/nutcracker/src/nc_conf.c +1766 -0
  112. data/ext/nutcracker/src/nc_conf.h +134 -0
  113. data/ext/nutcracker/src/nc_connection.c +392 -0
  114. data/ext/nutcracker/src/nc_connection.h +99 -0
  115. data/ext/nutcracker/src/nc_core.c +334 -0
  116. data/ext/nutcracker/src/nc_core.h +131 -0
  117. data/ext/nutcracker/src/nc_event.c +214 -0
  118. data/ext/nutcracker/src/nc_event.h +39 -0
  119. data/ext/nutcracker/src/nc_log.c +254 -0
  120. data/ext/nutcracker/src/nc_log.h +120 -0
  121. data/ext/nutcracker/src/nc_mbuf.c +285 -0
  122. data/ext/nutcracker/src/nc_mbuf.h +67 -0
  123. data/ext/nutcracker/src/nc_message.c +828 -0
  124. data/ext/nutcracker/src/nc_message.h +253 -0
  125. data/ext/nutcracker/src/nc_proxy.c +359 -0
  126. data/ext/nutcracker/src/nc_proxy.h +34 -0
  127. data/ext/nutcracker/src/nc_queue.h +788 -0
  128. data/ext/nutcracker/src/nc_rbtree.c +348 -0
  129. data/ext/nutcracker/src/nc_rbtree.h +47 -0
  130. data/ext/nutcracker/src/nc_request.c +588 -0
  131. data/ext/nutcracker/src/nc_response.c +332 -0
  132. data/ext/nutcracker/src/nc_server.c +841 -0
  133. data/ext/nutcracker/src/nc_server.h +143 -0
  134. data/ext/nutcracker/src/nc_signal.c +131 -0
  135. data/ext/nutcracker/src/nc_signal.h +34 -0
  136. data/ext/nutcracker/src/nc_stats.c +1188 -0
  137. data/ext/nutcracker/src/nc_stats.h +206 -0
  138. data/ext/nutcracker/src/nc_string.c +109 -0
  139. data/ext/nutcracker/src/nc_string.h +112 -0
  140. data/ext/nutcracker/src/nc_util.c +619 -0
  141. data/ext/nutcracker/src/nc_util.h +214 -0
  142. data/ext/nutcracker/src/proto/Makefile.am +14 -0
  143. data/ext/nutcracker/src/proto/Makefile.in +482 -0
  144. data/ext/nutcracker/src/proto/nc_memcache.c +1306 -0
  145. data/ext/nutcracker/src/proto/nc_proto.h +155 -0
  146. data/ext/nutcracker/src/proto/nc_redis.c +2102 -0
  147. data/lib/nutcracker.rb +7 -0
  148. data/lib/nutcracker/version.rb +3 -0
  149. metadata +194 -0
@@ -0,0 +1,34 @@
1
+ /*
2
+ * twemproxy - A fast and lightweight proxy for memcached protocol.
3
+ * Copyright (C) 2011 Twitter, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #ifndef _NC_PROXY_H_
19
+ #define _NC_PROXY_H_
20
+
21
+ #include <nc_core.h>
22
+
23
+ void proxy_ref(struct conn *conn, void *owner);
24
+ void proxy_unref(struct conn *conn);
25
+ void proxy_close(struct context *ctx, struct conn *conn);
26
+
27
+ rstatus_t proxy_each_init(void *elem, void *data);
28
+ rstatus_t proxy_each_deinit(void *elem, void *data);
29
+
30
+ rstatus_t proxy_init(struct context *ctx);
31
+ void proxy_deinit(struct context *ctx);
32
+ rstatus_t proxy_recv(struct context *ctx, struct conn *conn);
33
+
34
+ #endif
@@ -0,0 +1,788 @@
1
+ /*
2
+ * twemproxy - A fast and lightweight proxy for memcached protocol.
3
+ * Copyright (C) 2011 Twitter, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /*
19
+ * Copyright (c) 1991, 1993
20
+ * The Regents of the University of California. All rights reserved.
21
+ *
22
+ * Redistribution and use in source and binary forms, with or without
23
+ * modification, are permitted provided that the following conditions
24
+ * are met:
25
+ * 1. Redistributions of source code must retain the above copyright
26
+ * notice, this list of conditions and the following disclaimer.
27
+ * 2. Redistributions in binary form must reproduce the above copyright
28
+ * notice, this list of conditions and the following disclaimer in the
29
+ * documentation and/or other materials provided with the distribution.
30
+ * 4. Neither the name of the University nor the names of its contributors
31
+ * may be used to endorse or promote products derived from this software
32
+ * without specific prior written permission.
33
+ *
34
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44
+ * SUCH DAMAGE.
45
+ *
46
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
47
+ * $FreeBSD: src/sys/sys/queue.h,v 1.73 2010/02/20 01:05:30 emaste Exp $
48
+ */
49
+
50
+ #ifndef _NC_QUEUE_H_
51
+ #define _NC_QUEUE_H_
52
+
53
+ #include <nc_log.h>
54
+
55
+ #define __offsetof(type, field) ((size_t)(&((type *)NULL)->field))
56
+
57
+ /*
58
+ * This file defines five types of data structures: singly-linked lists,
59
+ * singly-linked tail queues, lists, tail queues, and circular queues.
60
+ *
61
+ * A singly-linked list is headed by a single forward pointer. The elements
62
+ * are singly linked for minimum space and pointer manipulation overhead at
63
+ * the expense of O(n) removal for arbitrary elements. New elements can be
64
+ * added to the list after an existing element or at the head of the list.
65
+ * Elements being removed from the head of the list should use the explicit
66
+ * macro for this purpose for optimum efficiency. A singly-linked list may
67
+ * only be traversed in the forward direction. Singly-linked lists are ideal
68
+ * for applications with large datasets and few or no removals or for
69
+ * implementing a LIFO queue.
70
+ *
71
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
72
+ * head of the list and the other to the tail of the list. The elements are
73
+ * singly linked for minimum space and pointer manipulation overhead at the
74
+ * expense of O(n) removal for arbitrary elements. New elements can be added
75
+ * to the list after an existing element, at the head of the list, or at the
76
+ * end of the list. Elements being removed from the head of the tail queue
77
+ * should use the explicit macro for this purpose for optimum efficiency.
78
+ * A singly-linked tail queue may only be traversed in the forward direction.
79
+ * Singly-linked tail queues are ideal for applications with large datasets
80
+ * and few or no removals or for implementing a FIFO queue.
81
+ *
82
+ * A list is headed by a single forward pointer (or an array of forward
83
+ * pointers for a hash table header). The elements are doubly linked
84
+ * so that an arbitrary element can be removed without a need to
85
+ * traverse the list. New elements can be added to the list before
86
+ * or after an existing element or at the head of the list. A list
87
+ * may only be traversed in the forward direction.
88
+ *
89
+ * A tail queue is headed by a pair of pointers, one to the head of the
90
+ * list and the other to the tail of the list. The elements are doubly
91
+ * linked so that an arbitrary element can be removed without a need to
92
+ * traverse the list. New elements can be added to the list before or
93
+ * after an existing element, at the head of the list, or at the end of
94
+ * the list. A tail queue may be traversed in either direction.
95
+ *
96
+ * A circle queue is headed by a pair of pointers, one to the head of the
97
+ * list and the other to the tail of the list. The elements are doubly
98
+ * linked so that an arbitrary element can be removed without a need to
99
+ * traverse the list. New elements can be added to the list before or after
100
+ * an existing element, at the head of the list, or at the end of the list.
101
+ * A circle queue may be traversed in either direction, but has a more
102
+ * complex end of list detection.
103
+ *
104
+ * For details on the use of these macros, see the queue(3) manual page.
105
+ *
106
+ *
107
+ * SLIST LIST STAILQ TAILQ CIRCLEQ
108
+ * _HEAD + + + + +
109
+ * _HEAD_INITIALIZER + + + + +
110
+ * _ENTRY + + + + +
111
+ * _INIT + + + + +
112
+ * _EMPTY + + + + +
113
+ * _FIRST + + + + +
114
+ * _NEXT + + + + +
115
+ * _PREV - - - + +
116
+ * _LAST - - + + +
117
+ * _FOREACH + + + + +
118
+ * _FOREACH_REVERSE - - - + +
119
+ * _INSERT_HEAD + + + + +
120
+ * _INSERT_BEFORE - + - + +
121
+ * _INSERT_AFTER + + + + +
122
+ * _INSERT_TAIL - - + + +
123
+ * _REMOVE_HEAD + - + - -
124
+ * _REMOVE + + + + +
125
+ *
126
+ */
127
+
128
+ #define QUEUE_MACRO_SCRUB 1
129
+
130
+ #ifdef NC_ASSERT_PANIC
131
+ # define QUEUE_MACRO_TRACE 1
132
+ # define QUEUE_MACRO_ASSERT 1
133
+ #endif
134
+
135
+ #ifdef QUEUE_MACRO_SCRUB
136
+
137
+ #define QMD_SAVELINK(name, link) void **name = (void *)&(link)
138
+
139
+ #define TRASHIT(x) do { \
140
+ (x) = (void *) NULL; \
141
+ } while (0)
142
+
143
+ #else
144
+
145
+ #define QMD_SAVELINK(name, link)
146
+ #define TRASHIT(x)
147
+
148
+ #endif /* QUEUE_MACRO_SCRUB */
149
+
150
+ #ifdef QUEUE_MACRO_TRACE
151
+
152
+ /* Store the last 2 places the queue element or head was altered */
153
+ struct qm_trace {
154
+ char *lastfile;
155
+ int lastline;
156
+ char *prevfile;
157
+ int prevline;
158
+ };
159
+
160
+ #define TRACEBUF struct qm_trace trace;
161
+
162
+ #define QMD_TRACE_HEAD(head) do { \
163
+ (head)->trace.prevline = (head)->trace.lastline; \
164
+ (head)->trace.prevfile = (head)->trace.lastfile; \
165
+ (head)->trace.lastline = __LINE__; \
166
+ (head)->trace.lastfile = __FILE__; \
167
+ } while (0)
168
+
169
+ #define QMD_TRACE_ELEM(elem) do { \
170
+ (elem)->trace.prevline = (elem)->trace.lastline; \
171
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
172
+ (elem)->trace.lastline = __LINE__; \
173
+ (elem)->trace.lastfile = __FILE__; \
174
+ } while (0)
175
+
176
+ #else
177
+
178
+ #define QMD_TRACE_ELEM(elem)
179
+ #define QMD_TRACE_HEAD(head)
180
+ #define TRACEBUF
181
+
182
+ #endif /* QUEUE_MACRO_TRACE */
183
+
184
+ /*
185
+ * Singly-linked List declarations.
186
+ */
187
+ #define SLIST_HEAD(name, type) \
188
+ struct name { \
189
+ struct type *slh_first; /* first element */ \
190
+ }
191
+
192
+ #define SLIST_HEAD_INITIALIZER(head) \
193
+ { NULL }
194
+
195
+ #define SLIST_ENTRY(type) \
196
+ struct { \
197
+ struct type *sle_next; /* next element */ \
198
+ }
199
+
200
+ /*
201
+ * Singly-linked List functions.
202
+ */
203
+ #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
204
+
205
+ #define SLIST_FIRST(head) ((head)->slh_first)
206
+
207
+ #define SLIST_FOREACH(var, head, field) \
208
+ for ((var) = SLIST_FIRST((head)); \
209
+ (var); \
210
+ (var) = SLIST_NEXT((var), field))
211
+
212
+ #define SLIST_FOREACH_SAFE(var, head, field, tvar) \
213
+ for ((var) = SLIST_FIRST((head)); \
214
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
215
+ (var) = (tvar))
216
+
217
+ #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
218
+ for ((varp) = &SLIST_FIRST((head)); \
219
+ ((var) = *(varp)) != NULL; \
220
+ (varp) = &SLIST_NEXT((var), field))
221
+
222
+ #define SLIST_INIT(head) do { \
223
+ SLIST_FIRST((head)) = NULL; \
224
+ } while (0)
225
+
226
+ #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
227
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
228
+ SLIST_NEXT((slistelm), field) = (elm); \
229
+ } while (0)
230
+
231
+ #define SLIST_INSERT_HEAD(head, elm, field) do { \
232
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
233
+ SLIST_FIRST((head)) = (elm); \
234
+ } while (0)
235
+
236
+ #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
237
+
238
+ #define SLIST_REMOVE(head, elm, type, field) do { \
239
+ if (SLIST_FIRST((head)) == (elm)) { \
240
+ SLIST_REMOVE_HEAD((head), field); \
241
+ } else { \
242
+ struct type *curelm = SLIST_FIRST((head)); \
243
+ while (SLIST_NEXT(curelm, field) != (elm)) { \
244
+ curelm = SLIST_NEXT(curelm, field); \
245
+ } \
246
+ SLIST_REMOVE_AFTER(curelm, field); \
247
+ } \
248
+ } while (0)
249
+
250
+ #define SLIST_REMOVE_AFTER(elm, field) do { \
251
+ QMD_SAVELINK(oldnext, SLIST_NEXT(SLIST_NEXT(elm, field), field)); \
252
+ SLIST_NEXT(elm, field) = SLIST_NEXT(SLIST_NEXT(elm, field), field); \
253
+ TRASHIT(*oldnext); \
254
+ } while (0)
255
+
256
+ #define SLIST_REMOVE_HEAD(head, field) do { \
257
+ QMD_SAVELINK(oldnext, SLIST_NEXT(SLIST_FIRST((head)), field)); \
258
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
259
+ TRASHIT(*oldnext); \
260
+ } while (0)
261
+
262
+ /*
263
+ * Singly-linked Tail queue declarations.
264
+ */
265
+ #define STAILQ_HEAD(name, type) \
266
+ struct name { \
267
+ struct type *stqh_first; /* first element */ \
268
+ struct type **stqh_last; /* addr of last next element */ \
269
+ }
270
+
271
+ #define STAILQ_HEAD_INITIALIZER(head) \
272
+ { NULL, &(head).stqh_first }
273
+
274
+ #define STAILQ_ENTRY(type) \
275
+ struct { \
276
+ struct type *stqe_next; /* next element */ \
277
+ }
278
+
279
+ /*
280
+ * Singly-linked Tail queue functions.
281
+ */
282
+ #define STAILQ_CONCAT(head1, head2) do { \
283
+ if (!STAILQ_EMPTY((head2))) { \
284
+ *(head1)->stqh_last = (head2)->stqh_first; \
285
+ (head1)->stqh_last = (head2)->stqh_last; \
286
+ STAILQ_INIT((head2)); \
287
+ } \
288
+ } while (0)
289
+
290
+ #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
291
+
292
+ #define STAILQ_FIRST(head) ((head)->stqh_first)
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
+ #define STAILQ_INIT(head) do { \
305
+ STAILQ_FIRST((head)) = NULL; \
306
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
307
+ } while (0)
308
+
309
+ #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
310
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
311
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
312
+ STAILQ_NEXT((tqelm), field) = (elm); \
313
+ } while (0)
314
+
315
+ #define STAILQ_INSERT_HEAD(head, elm, field) do { \
316
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
317
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
318
+ STAILQ_FIRST((head)) = (elm); \
319
+ } while (0)
320
+
321
+ #define STAILQ_INSERT_TAIL(head, elm, field) do { \
322
+ STAILQ_NEXT((elm), field) = NULL; \
323
+ *(head)->stqh_last = (elm); \
324
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
325
+ } while (0)
326
+
327
+ #define STAILQ_LAST(head, type, field) \
328
+ (STAILQ_EMPTY((head)) ? \
329
+ NULL : \
330
+ ((struct type *)(void *) \
331
+ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
332
+
333
+ #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
334
+
335
+ #define STAILQ_REMOVE(head, elm, type, field) do { \
336
+ if (STAILQ_FIRST((head)) == (elm)) { \
337
+ STAILQ_REMOVE_HEAD((head), field); \
338
+ } \
339
+ else { \
340
+ struct type *curelm = STAILQ_FIRST((head)); \
341
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
342
+ curelm = STAILQ_NEXT(curelm, field); \
343
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
344
+ } \
345
+ } while (0)
346
+
347
+ #define STAILQ_REMOVE_HEAD(head, field) do { \
348
+ QMD_SAVELINK(oldnext, STAILQ_NEXT(STAILQ_FIRST((head)), field)); \
349
+ if ((STAILQ_FIRST((head)) = \
350
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) { \
351
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
352
+ } \
353
+ TRASHIT(*oldnext); \
354
+ } while (0)
355
+
356
+ #define STAILQ_REMOVE_AFTER(head, elm, field) do { \
357
+ QMD_SAVELINK(oldnext, STAILQ_NEXT(STAILQ_NEXT(elm, field), field)); \
358
+ if ((STAILQ_NEXT(elm, field) = \
359
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) { \
360
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
361
+ } \
362
+ TRASHIT(*oldnext); \
363
+ } while (0)
364
+
365
+ #define STAILQ_SWAP(head1, head2, type) do { \
366
+ struct type *swap_first = STAILQ_FIRST(head1); \
367
+ struct type **swap_last = (head1)->stqh_last; \
368
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
369
+ (head1)->stqh_last = (head2)->stqh_last; \
370
+ STAILQ_FIRST(head2) = swap_first; \
371
+ (head2)->stqh_last = swap_last; \
372
+ if (STAILQ_EMPTY(head1)) \
373
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
374
+ if (STAILQ_EMPTY(head2)) \
375
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
376
+ } while (0)
377
+
378
+
379
+ /*
380
+ * List declarations.
381
+ */
382
+ #define LIST_HEAD(name, type) \
383
+ struct name { \
384
+ struct type *lh_first; /* first element */ \
385
+ }
386
+
387
+ #define LIST_HEAD_INITIALIZER(head) \
388
+ { NULL }
389
+
390
+ #define LIST_ENTRY(type) \
391
+ struct { \
392
+ struct type *le_next; /* next element */ \
393
+ struct type **le_prev; /* address of previous next element */ \
394
+ }
395
+
396
+ /*
397
+ * List functions.
398
+ */
399
+
400
+ #ifdef QUEUE_MACRO_ASSERT
401
+
402
+ #define QMD_LIST_CHECK_HEAD(head, field) do { \
403
+ if (LIST_FIRST((head)) != NULL && \
404
+ LIST_FIRST((head))->field.le_prev != &LIST_FIRST((head))) { \
405
+ log_panic("Bad list head %p first->prev != head", (void *)(head)); \
406
+ } \
407
+ } while (0)
408
+
409
+ #define QMD_LIST_CHECK_NEXT(elm, field) do { \
410
+ if (LIST_NEXT((elm), field) != NULL && \
411
+ LIST_NEXT((elm), field)->field.le_prev != &((elm)->field.le_next)) {\
412
+ log_panic("Bad link elm %p next->prev != elm",(void *)(elm)); \
413
+ } \
414
+ } while (0)
415
+
416
+ #define QMD_LIST_CHECK_PREV(elm, field) do { \
417
+ if (*(elm)->field.le_prev != (elm)) { \
418
+ log_panic("Bad link elm %p prev->next != elm",(void *)(elm)); \
419
+ } \
420
+ } while (0)
421
+
422
+ #else
423
+
424
+ #define QMD_LIST_CHECK_HEAD(head, field)
425
+ #define QMD_LIST_CHECK_NEXT(elm, field)
426
+ #define QMD_LIST_CHECK_PREV(elm, field)
427
+
428
+ #endif /* QUEUE_MACRO_ASSERT */
429
+
430
+ #define LIST_EMPTY(head) ((head)->lh_first == NULL)
431
+
432
+ #define LIST_FIRST(head) ((head)->lh_first)
433
+
434
+ #define LIST_FOREACH(var, head, field) \
435
+ for ((var) = LIST_FIRST((head)); \
436
+ (var); \
437
+ (var) = LIST_NEXT((var), field))
438
+
439
+ #define LIST_FOREACH_SAFE(var, head, field, tvar) \
440
+ for ((var) = LIST_FIRST((head)); \
441
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
442
+ (var) = (tvar))
443
+
444
+ #define LIST_INIT(head) do { \
445
+ LIST_FIRST((head)) = NULL; \
446
+ } while (0)
447
+
448
+ #define LIST_INSERT_AFTER(listelm, elm, field) do { \
449
+ QMD_LIST_CHECK_NEXT(listelm, field); \
450
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
451
+ LIST_NEXT((listelm), field)->field.le_prev = \
452
+ &LIST_NEXT((elm), field); \
453
+ LIST_NEXT((listelm), field) = (elm); \
454
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
455
+ } while (0)
456
+
457
+ #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
458
+ QMD_LIST_CHECK_PREV(listelm, field); \
459
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
460
+ LIST_NEXT((elm), field) = (listelm); \
461
+ *(listelm)->field.le_prev = (elm); \
462
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
463
+ } while (0)
464
+
465
+ #define LIST_INSERT_HEAD(head, elm, field) do { \
466
+ QMD_LIST_CHECK_HEAD((head), field); \
467
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
468
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \
469
+ LIST_FIRST((head)) = (elm); \
470
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
471
+ } while (0)
472
+
473
+ #define LIST_NEXT(elm, field) ((elm)->field.le_next)
474
+
475
+ #define LIST_REMOVE(elm, field) do { \
476
+ QMD_SAVELINK(oldnext, (elm)->field.le_next); \
477
+ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
478
+ QMD_LIST_CHECK_NEXT(elm, field); \
479
+ QMD_LIST_CHECK_PREV(elm, field); \
480
+ if (LIST_NEXT((elm), field) != NULL) \
481
+ LIST_NEXT((elm), field)->field.le_prev = \
482
+ (elm)->field.le_prev; \
483
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
484
+ TRASHIT(*oldnext); \
485
+ TRASHIT(*oldprev); \
486
+ } while (0)
487
+
488
+ #define LIST_SWAP(head1, head2, type, field) do { \
489
+ struct type *swap_tmp = LIST_FIRST((head1)); \
490
+ LIST_FIRST((head1)) = LIST_FIRST((head2)); \
491
+ LIST_FIRST((head2)) = swap_tmp; \
492
+ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
493
+ swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
494
+ if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
495
+ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
496
+ } while (0)
497
+
498
+ /*
499
+ * Tail queue declarations.
500
+ */
501
+ #define TAILQ_HEAD(name, type) \
502
+ struct name { \
503
+ struct type *tqh_first; /* first element */ \
504
+ struct type **tqh_last; /* addr of last next element */ \
505
+ TRACEBUF \
506
+ }
507
+
508
+ #define TAILQ_HEAD_INITIALIZER(head) \
509
+ { NULL, &(head).tqh_first }
510
+
511
+ #define TAILQ_ENTRY(type) \
512
+ struct { \
513
+ struct type *tqe_next; /* next element */ \
514
+ struct type **tqe_prev; /* address of previous next element */ \
515
+ TRACEBUF \
516
+ }
517
+
518
+ /*
519
+ * Tail queue functions.
520
+ */
521
+ #ifdef QUEUE_MACRO_ASSERT
522
+
523
+ #define QMD_TAILQ_CHECK_HEAD(head, field) do { \
524
+ if (!TAILQ_EMPTY(head) && \
525
+ TAILQ_FIRST((head))->field.tqe_prev != &TAILQ_FIRST((head))) { \
526
+ log_panic("Bad tailq head %p first->prev != head", (void *)(head)); \
527
+ } \
528
+ } while (0)
529
+
530
+ #define QMD_TAILQ_CHECK_TAIL(head, field) do { \
531
+ if (*(head)->tqh_last != NULL) { \
532
+ log_panic("Bad tailq NEXT(%p->tqh_last) != NULL",(void *)(head)); \
533
+ } \
534
+ } while (0)
535
+
536
+ #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
537
+ if (TAILQ_NEXT((elm), field) != NULL && \
538
+ TAILQ_NEXT((elm), field)->field.tqe_prev != &((elm)->field.tqe_next)) {\
539
+ log_panic("Bad link elm %p next->prev != elm",(void *)(elm)); \
540
+ } \
541
+ } while (0)
542
+
543
+ #define QMD_TAILQ_CHECK_PREV(elm, field) do { \
544
+ if (*(elm)->field.tqe_prev != (elm)) { \
545
+ log_panic("Bad link elm %p prev->next != elm",(void *)(elm)); \
546
+ } \
547
+ } while (0)
548
+
549
+ #else
550
+
551
+ #define QMD_TAILQ_CHECK_HEAD(head, field)
552
+ #define QMD_TAILQ_CHECK_TAIL(head, headname)
553
+ #define QMD_TAILQ_CHECK_NEXT(elm, field)
554
+ #define QMD_TAILQ_CHECK_PREV(elm, field)
555
+
556
+ #endif /* QUEUE_MACRO_ASSERT */
557
+
558
+ #define TAILQ_CONCAT(head1, head2, field) do { \
559
+ if (!TAILQ_EMPTY(head2)) { \
560
+ *(head1)->tqh_last = (head2)->tqh_first; \
561
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
562
+ (head1)->tqh_last = (head2)->tqh_last; \
563
+ TAILQ_INIT((head2)); \
564
+ QMD_TRACE_HEAD(head1); \
565
+ QMD_TRACE_HEAD(head2); \
566
+ } \
567
+ } while (0)
568
+
569
+ #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
570
+
571
+ #define TAILQ_FIRST(head) ((head)->tqh_first)
572
+
573
+ #define TAILQ_FOREACH(var, head, field) \
574
+ for ((var) = TAILQ_FIRST((head)); \
575
+ (var); \
576
+ (var) = TAILQ_NEXT((var), field))
577
+
578
+ #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
579
+ for ((var) = TAILQ_FIRST((head)); \
580
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
581
+ (var) = (tvar))
582
+
583
+ #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
584
+ for ((var) = TAILQ_LAST((head), headname); \
585
+ (var); \
586
+ (var) = TAILQ_PREV((var), headname, field))
587
+
588
+ #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
589
+ for ((var) = TAILQ_LAST((head), headname); \
590
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
591
+ (var) = (tvar))
592
+
593
+ #define TAILQ_INIT(head) do { \
594
+ TAILQ_FIRST((head)) = NULL; \
595
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
596
+ QMD_TRACE_HEAD(head); \
597
+ } while (0)
598
+
599
+ #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
600
+ QMD_TAILQ_CHECK_NEXT(listelm, field); \
601
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL) { \
602
+ TAILQ_NEXT((elm), field)->field.tqe_prev = &TAILQ_NEXT((elm), field);\
603
+ } else { \
604
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
605
+ QMD_TRACE_HEAD(head); \
606
+ } \
607
+ TAILQ_NEXT((listelm), field) = (elm); \
608
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
609
+ QMD_TRACE_ELEM(&(elm)->field); \
610
+ QMD_TRACE_ELEM(&listelm->field); \
611
+ } while (0)
612
+
613
+ #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
614
+ QMD_TAILQ_CHECK_PREV(listelm, field); \
615
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
616
+ TAILQ_NEXT((elm), field) = (listelm); \
617
+ *(listelm)->field.tqe_prev = (elm); \
618
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
619
+ QMD_TRACE_ELEM(&(elm)->field); \
620
+ QMD_TRACE_ELEM(&listelm->field); \
621
+ } while (0)
622
+
623
+ #define TAILQ_INSERT_HEAD(head, elm, field) do { \
624
+ QMD_TAILQ_CHECK_HEAD(head, field); \
625
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
626
+ TAILQ_FIRST((head))->field.tqe_prev = \
627
+ &TAILQ_NEXT((elm), field); \
628
+ else \
629
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
630
+ TAILQ_FIRST((head)) = (elm); \
631
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
632
+ QMD_TRACE_HEAD(head); \
633
+ QMD_TRACE_ELEM(&(elm)->field); \
634
+ } while (0)
635
+
636
+ #define TAILQ_INSERT_TAIL(head, elm, field) do { \
637
+ QMD_TAILQ_CHECK_TAIL(head, field); \
638
+ TAILQ_NEXT((elm), field) = NULL; \
639
+ (elm)->field.tqe_prev = (head)->tqh_last; \
640
+ *(head)->tqh_last = (elm); \
641
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
642
+ QMD_TRACE_HEAD(head); \
643
+ QMD_TRACE_ELEM(&(elm)->field); \
644
+ } while (0)
645
+
646
+ #define TAILQ_LAST(head, headname) \
647
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
648
+
649
+ #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
650
+
651
+ #define TAILQ_PREV(elm, headname, field) \
652
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
653
+
654
+ #define TAILQ_REMOVE(head, elm, field) do { \
655
+ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
656
+ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
657
+ QMD_TAILQ_CHECK_NEXT(elm, field); \
658
+ QMD_TAILQ_CHECK_PREV(elm, field); \
659
+ if ((TAILQ_NEXT((elm), field)) != NULL) { \
660
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
661
+ (elm)->field.tqe_prev; \
662
+ } else { \
663
+ (head)->tqh_last = (elm)->field.tqe_prev; \
664
+ QMD_TRACE_HEAD(head); \
665
+ } \
666
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
667
+ TRASHIT(*oldnext); \
668
+ TRASHIT(*oldprev); \
669
+ QMD_TRACE_ELEM(&(elm)->field); \
670
+ } while (0)
671
+
672
+ #define TAILQ_SWAP(head1, head2, type, field) do { \
673
+ struct type *swap_first = (head1)->tqh_first; \
674
+ struct type **swap_last = (head1)->tqh_last; \
675
+ (head1)->tqh_first = (head2)->tqh_first; \
676
+ (head1)->tqh_last = (head2)->tqh_last; \
677
+ (head2)->tqh_first = swap_first; \
678
+ (head2)->tqh_last = swap_last; \
679
+ if ((swap_first = (head1)->tqh_first) != NULL) \
680
+ swap_first->field.tqe_prev = &(head1)->tqh_first; \
681
+ else \
682
+ (head1)->tqh_last = &(head1)->tqh_first; \
683
+ if ((swap_first = (head2)->tqh_first) != NULL) \
684
+ swap_first->field.tqe_prev = &(head2)->tqh_first; \
685
+ else \
686
+ (head2)->tqh_last = &(head2)->tqh_first; \
687
+ } while (0)
688
+
689
+ /*
690
+ * Circular queue declarations.
691
+ */
692
+ #define CIRCLEQ_HEAD(name, type) \
693
+ struct name { \
694
+ struct type *cqh_first; /* first element */ \
695
+ struct type *cqh_last; /* last element */ \
696
+ }
697
+
698
+ #define CIRCLEQ_HEAD_INITIALIZER(head) \
699
+ { (void *)&(head), (void *)&(head) }
700
+
701
+ #define CIRCLEQ_ENTRY(type) \
702
+ struct { \
703
+ struct type *cqe_next; /* next element */ \
704
+ struct type *cqe_prev; /* previous element */ \
705
+ }
706
+
707
+ /*
708
+ * Circular queue functions.
709
+ */
710
+ #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
711
+
712
+ #define CIRCLEQ_FIRST(head) ((head)->cqh_first)
713
+
714
+ #define CIRCLEQ_FOREACH(var, head, field) \
715
+ for ((var) = CIRCLEQ_FIRST((head)); \
716
+ (var) != (void *)(head) || ((var) = NULL); \
717
+ (var) = CIRCLEQ_NEXT((var), field))
718
+
719
+ #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
720
+ for ((var) = CIRCLEQ_LAST((head)); \
721
+ (var) != (void *)(head) || ((var) = NULL); \
722
+ (var) = CIRCLEQ_PREV((var), field))
723
+
724
+ #define CIRCLEQ_INIT(head) do { \
725
+ CIRCLEQ_FIRST((head)) = (void *)(head); \
726
+ CIRCLEQ_LAST((head)) = (void *)(head); \
727
+ } while (0)
728
+
729
+ #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
730
+ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
731
+ CIRCLEQ_PREV((elm), field) = (listelm); \
732
+ if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
733
+ CIRCLEQ_LAST((head)) = (elm); \
734
+ else \
735
+ CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm); \
736
+ CIRCLEQ_NEXT((listelm), field) = (elm); \
737
+ } while (0)
738
+
739
+ #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
740
+ CIRCLEQ_NEXT((elm), field) = (listelm); \
741
+ CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
742
+ if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
743
+ CIRCLEQ_FIRST((head)) = (elm); \
744
+ else \
745
+ CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm); \
746
+ CIRCLEQ_PREV((listelm), field) = (elm); \
747
+ } while (0)
748
+
749
+ #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
750
+ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
751
+ CIRCLEQ_PREV((elm), field) = (void *)(head); \
752
+ if (CIRCLEQ_LAST((head)) == (void *)(head)) \
753
+ CIRCLEQ_LAST((head)) = (elm); \
754
+ else \
755
+ CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
756
+ CIRCLEQ_FIRST((head)) = (elm); \
757
+ } while (0)
758
+
759
+ #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
760
+ CIRCLEQ_NEXT((elm), field) = (void *)(head); \
761
+ CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
762
+ if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
763
+ CIRCLEQ_FIRST((head)) = (elm); \
764
+ else \
765
+ CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
766
+ CIRCLEQ_LAST((head)) = (elm); \
767
+ } while (0)
768
+
769
+ #define CIRCLEQ_LAST(head) ((head)->cqh_last)
770
+
771
+ #define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
772
+
773
+ #define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
774
+
775
+ #define CIRCLEQ_REMOVE(head, elm, field) do { \
776
+ if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
777
+ CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
778
+ else \
779
+ CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
780
+ CIRCLEQ_PREV((elm), field); \
781
+ if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
782
+ CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
783
+ else \
784
+ CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
785
+ CIRCLEQ_NEXT((elm), field); \
786
+ } while (0)
787
+
788
+ #endif