]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sys/arb.h
THIS BRANCH IS OBSOLETE, PLEASE READ:
[FreeBSD/FreeBSD.git] / sys / sys / arb.h
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
5  * Copyright 2018-2019 Netflix, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #ifndef _SYS_ARB_H_
32 #define _SYS_ARB_H_
33
34 #include <sys/cdefs.h>
35
36 /* Array-based red-black trees. */
37
38 #define ARB_NULLIDX     -1
39 #define ARB_NULLCOL     -1
40
41 #define ARB_BLACK       0
42 #define ARB_RED         1
43
44 #define ARB_NEGINF      -1
45 #define ARB_INF         1
46
47 #define ARB_HEAD(name, type, idxbits)                                   \
48 struct name {                                                           \
49         int##idxbits##_t        arb_curnodes;                           \
50         int##idxbits##_t        arb_maxnodes;                           \
51         int##idxbits##_t        arb_root_idx;                           \
52         int##idxbits##_t        arb_free_idx;                           \
53         int##idxbits##_t        arb_min_idx;                            \
54         int##idxbits##_t        arb_max_idx;                            \
55         struct type             arb_nodes[];                            \
56 }
57 #define ARB8_HEAD(name, type)   ARB_HEAD(name, type, 8)
58 #define ARB16_HEAD(name, type)  ARB_HEAD(name, type, 16)
59 #define ARB32_HEAD(name, type)  ARB_HEAD(name, type, 32)
60
61 #define ARB_ALLOCSIZE(head, maxn, x)                                    \
62         (sizeof(*head) + (maxn) * sizeof(*x))
63
64 #define ARB_INITIALIZER(name, maxn)                                     \
65         ((struct name){ 0, maxn, ARB_NULLIDX, ARB_NULLIDX,              \
66             ARB_NULLIDX, ARB_NULLIDX })
67
68 #define ARB_INIT(x, field, head, maxn)                                  \
69         (head)->arb_curnodes = 0;                                       \
70         (head)->arb_maxnodes = (maxn);                                  \
71         (head)->arb_root_idx = (head)->arb_free_idx =                   \
72             (head)->arb_min_idx = (head)->arb_max_idx = ARB_NULLIDX;    \
73         /* The ARB_RETURNFREE() puts all entries on the free list. */   \
74         ARB_ARRFOREACH_REVWCOND(x, field, head,                         \
75             ARB_RETURNFREE(head, x, field))
76
77 #define ARB_ENTRY(idxbits)                                              \
78 struct {                                                                \
79         int##idxbits##_t        arbe_parent_idx;                        \
80         int##idxbits##_t        arbe_left_idx;                          \
81         int##idxbits##_t        arbe_right_idx;                         \
82         int8_t                  arbe_color;                             \
83 }
84 #define ARB8_ENTRY()            ARB_ENTRY(8)
85 #define ARB16_ENTRY()           ARB_ENTRY(16)
86 #define ARB32_ENTRY()           ARB_ENTRY(32)
87
88 #define ARB_ENTRYINIT(elm, field) do {                                  \
89         (elm)->field.arbe_parent_idx =                                  \
90             (elm)->field.arbe_left_idx =                                \
91             (elm)->field.arbe_right_idx = ARB_NULLIDX;                  \
92             (elm)->field.arbe_color = ARB_NULLCOL;                      \
93 } while (/*CONSTCOND*/ 0)
94
95 #define ARB_ELMTYPE(head)               __typeof(&(head)->arb_nodes[0])
96 #define ARB_NODES(head)                 (head)->arb_nodes
97 #define ARB_MAXNODES(head)              (head)->arb_maxnodes
98 #define ARB_CURNODES(head)              (head)->arb_curnodes
99 #define ARB_EMPTY(head)                 ((head)->arb_curnodes == 0)
100 #define ARB_FULL(head)                  ((head)->arb_curnodes >= (head)->arb_maxnodes)
101 #define ARB_CNODE(head, idx) \
102     ((((intptr_t)(idx) <= ARB_NULLIDX) || ((idx) >= ARB_MAXNODES(head))) ? \
103     NULL : ((const ARB_ELMTYPE(head))(ARB_NODES(head) + (idx))))
104 #define ARB_NODE(head, idx) \
105     (__DECONST(ARB_ELMTYPE(head), ARB_CNODE(head, idx)))
106 #define ARB_ROOT(head)                  ARB_NODE(head, ARB_ROOTIDX(head))
107 #define ARB_LEFT(head, elm, field)      ARB_NODE(head, ARB_LEFTIDX(elm, field))
108 #define ARB_RIGHT(head, elm, field)     ARB_NODE(head, ARB_RIGHTIDX(elm, field))
109 #define ARB_PARENT(head, elm, field)    ARB_NODE(head, ARB_PARENTIDX(elm, field))
110 #define ARB_FREEIDX(head)               (head)->arb_free_idx
111 #define ARB_ROOTIDX(head)               (head)->arb_root_idx
112 #define ARB_MINIDX(head)                (head)->arb_min_idx
113 #define ARB_MAXIDX(head)                (head)->arb_max_idx
114 #define ARB_SELFIDX(head, elm)                                          \
115     ((elm) ? ((intptr_t)((((const uint8_t *)(elm)) -                    \
116     ((const uint8_t *)ARB_NODES(head))) / sizeof(*(elm)))) :            \
117     (intptr_t)ARB_NULLIDX)
118 #define ARB_LEFTIDX(elm, field)         (elm)->field.arbe_left_idx
119 #define ARB_RIGHTIDX(elm, field)        (elm)->field.arbe_right_idx
120 #define ARB_PARENTIDX(elm, field)       (elm)->field.arbe_parent_idx
121 #define ARB_COLOR(elm, field)           (elm)->field.arbe_color
122 #define ARB_PREVFREE(head, elm, field) \
123     ARB_NODE(head, ARB_PREVFREEIDX(elm, field))
124 #define ARB_PREVFREEIDX(elm, field)     ARB_LEFTIDX(elm, field)
125 #define ARB_NEXTFREE(head, elm, field) \
126     ARB_NODE(head, ARB_NEXTFREEIDX(elm, field))
127 #define ARB_NEXTFREEIDX(elm, field)     ARB_RIGHTIDX(elm, field)
128 #define ARB_ISFREE(elm, field)          (ARB_COLOR(elm, field) == ARB_NULLCOL)
129
130 #define ARB_SET(head, elm, parent, field) do {                          \
131         ARB_PARENTIDX(elm, field) =                                     \
132             parent ? ARB_SELFIDX(head, parent) : ARB_NULLIDX;           \
133         ARB_LEFTIDX(elm, field) = ARB_RIGHTIDX(elm, field) = ARB_NULLIDX; \
134         ARB_COLOR(elm, field) = ARB_RED;                                        \
135 } while (/*CONSTCOND*/ 0)
136
137 #define ARB_SET_BLACKRED(black, red, field) do {                        \
138         ARB_COLOR(black, field) = ARB_BLACK;                            \
139         ARB_COLOR(red, field) = ARB_RED;                                        \
140 } while (/*CONSTCOND*/ 0)
141
142 #ifndef ARB_AUGMENT
143 #define ARB_AUGMENT(x)  do {} while (0)
144 #endif
145
146 #define ARB_ROTATE_LEFT(head, elm, tmp, field) do {                     \
147         __typeof(ARB_RIGHTIDX(elm, field)) _tmpidx;                     \
148         (tmp) = ARB_RIGHT(head, elm, field);                            \
149         _tmpidx = ARB_RIGHTIDX(elm, field);                             \
150         ARB_RIGHTIDX(elm, field) = ARB_LEFTIDX(tmp, field);             \
151         if (ARB_RIGHTIDX(elm, field) != ARB_NULLIDX) {                  \
152                 ARB_PARENTIDX(ARB_LEFT(head, tmp, field), field) =      \
153                     ARB_SELFIDX(head, elm);                             \
154         }                                                               \
155         ARB_AUGMENT(elm);                                               \
156         ARB_PARENTIDX(tmp, field) = ARB_PARENTIDX(elm, field);          \
157         if (ARB_PARENTIDX(tmp, field) != ARB_NULLIDX) {                 \
158                 if (ARB_SELFIDX(head, elm) ==                           \
159                     ARB_LEFTIDX(ARB_PARENT(head, elm, field), field))   \
160                         ARB_LEFTIDX(ARB_PARENT(head, elm, field),       \
161                             field) = _tmpidx;                           \
162                 else                                                    \
163                         ARB_RIGHTIDX(ARB_PARENT(head, elm, field),      \
164                             field) = _tmpidx;                           \
165         } else                                                          \
166                 ARB_ROOTIDX(head) = _tmpidx;                            \
167         ARB_LEFTIDX(tmp, field) = ARB_SELFIDX(head, elm);               \
168         ARB_PARENTIDX(elm, field) = _tmpidx;                            \
169         ARB_AUGMENT(tmp);                                               \
170         if (ARB_PARENTIDX(tmp, field) != ARB_NULLIDX)                   \
171                 ARB_AUGMENT(ARB_PARENT(head, tmp, field));              \
172 } while (/*CONSTCOND*/ 0)
173
174 #define ARB_ROTATE_RIGHT(head, elm, tmp, field) do {                    \
175         __typeof(ARB_LEFTIDX(elm, field)) _tmpidx;                      \
176         (tmp) = ARB_LEFT(head, elm, field);                             \
177         _tmpidx = ARB_LEFTIDX(elm, field);                              \
178         ARB_LEFTIDX(elm, field) = ARB_RIGHTIDX(tmp, field);             \
179         if (ARB_LEFTIDX(elm, field) != ARB_NULLIDX) {                   \
180                 ARB_PARENTIDX(ARB_RIGHT(head, tmp, field), field) =     \
181                     ARB_SELFIDX(head, elm);                             \
182         }                                                               \
183         ARB_AUGMENT(elm);                                               \
184         ARB_PARENTIDX(tmp, field) = ARB_PARENTIDX(elm, field);          \
185         if (ARB_PARENTIDX(tmp, field) != ARB_NULLIDX) {                 \
186                 if (ARB_SELFIDX(head, elm) ==                           \
187                     ARB_LEFTIDX(ARB_PARENT(head, elm, field), field))   \
188                         ARB_LEFTIDX(ARB_PARENT(head, elm, field),       \
189                             field) = _tmpidx;                           \
190                 else                                                    \
191                         ARB_RIGHTIDX(ARB_PARENT(head, elm, field),      \
192                             field) = _tmpidx;                           \
193         } else                                                          \
194                 ARB_ROOTIDX(head) = _tmpidx;                            \
195         ARB_RIGHTIDX(tmp, field) = ARB_SELFIDX(head, elm);              \
196         ARB_PARENTIDX(elm, field) = _tmpidx;                            \
197         ARB_AUGMENT(tmp);                                               \
198         if (ARB_PARENTIDX(tmp, field) != ARB_NULLIDX)                   \
199                 ARB_AUGMENT(ARB_PARENT(head, tmp, field));              \
200 } while (/*CONSTCOND*/ 0)
201
202 #define ARB_RETURNFREE(head, elm, field)                                \
203 ({                                                                      \
204         ARB_COLOR(elm, field) = ARB_NULLCOL;                            \
205         ARB_NEXTFREEIDX(elm, field) = ARB_FREEIDX(head);                \
206         ARB_FREEIDX(head) = ARB_SELFIDX(head, elm);                     \
207         elm;                                                            \
208 })
209
210 #define ARB_GETFREEAT(head, field, fidx)                                \
211 ({                                                                      \
212         __typeof(ARB_NODE(head, 0)) _elm, _prevelm;                     \
213         int _idx = fidx;                                                        \
214         if (ARB_FREEIDX(head) == ARB_NULLIDX && !ARB_FULL(head)) {      \
215                 /* Populate the free list. */                           \
216                 ARB_ARRFOREACH_REVERSE(_elm, field, head) {             \
217                         if (ARB_ISFREE(_elm, field))                    \
218                                 ARB_RETURNFREE(head, _elm, field);      \
219                 }                                                       \
220         }                                                               \
221         _elm = _prevelm = ARB_NODE(head, ARB_FREEIDX(head));            \
222         for (; _idx > 0 && _elm != NULL; _idx--, _prevelm = _elm)       \
223                 _elm = ARB_NODE(head, ARB_NEXTFREEIDX(_elm, field));    \
224         if (_elm) {                                                     \
225                 if (fidx == 0)                                          \
226                         ARB_FREEIDX(head) =                             \
227                             ARB_NEXTFREEIDX(_elm, field);               \
228                 else                                                    \
229                         ARB_NEXTFREEIDX(_prevelm, field) =              \
230                             ARB_NEXTFREEIDX(_elm, field);               \
231         }                                                               \
232         _elm;                                                           \
233 })
234 #define ARB_GETFREE(head, field) ARB_GETFREEAT(head, field, 0)
235
236 /* Generates prototypes and inline functions */
237 #define ARB_PROTOTYPE(name, type, field, cmp)                           \
238         ARB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
239 #define ARB_PROTOTYPE_STATIC(name, type, field, cmp)                    \
240         ARB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
241 #define ARB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)            \
242         ARB_PROTOTYPE_INSERT_COLOR(name, type, attr);                   \
243         ARB_PROTOTYPE_REMOVE_COLOR(name, type, attr);                   \
244         ARB_PROTOTYPE_INSERT(name, type, attr);                         \
245         ARB_PROTOTYPE_REMOVE(name, type, attr);                         \
246         ARB_PROTOTYPE_CFIND(name, type, attr);                          \
247         ARB_PROTOTYPE_FIND(name, type, attr);                           \
248         ARB_PROTOTYPE_NFIND(name, type, attr);                          \
249         ARB_PROTOTYPE_CNEXT(name, type, attr);                          \
250         ARB_PROTOTYPE_NEXT(name, type, attr);                           \
251         ARB_PROTOTYPE_CPREV(name, type, attr);                          \
252         ARB_PROTOTYPE_PREV(name, type, attr);                           \
253         ARB_PROTOTYPE_CMINMAX(name, type, attr);                        \
254         ARB_PROTOTYPE_MINMAX(name, type, attr);                         \
255         ARB_PROTOTYPE_REINSERT(name, type, attr);
256 #define ARB_PROTOTYPE_INSERT_COLOR(name, type, attr)                    \
257         attr void name##_ARB_INSERT_COLOR(struct name *, struct type *)
258 #define ARB_PROTOTYPE_REMOVE_COLOR(name, type, attr)                    \
259         attr void name##_ARB_REMOVE_COLOR(struct name *, struct type *, struct type *)
260 #define ARB_PROTOTYPE_REMOVE(name, type, attr)                          \
261         attr struct type *name##_ARB_REMOVE(struct name *, struct type *)
262 #define ARB_PROTOTYPE_INSERT(name, type, attr)                          \
263         attr struct type *name##_ARB_INSERT(struct name *, struct type *)
264 #define ARB_PROTOTYPE_CFIND(name, type, attr)                           \
265         attr const struct type *name##_ARB_CFIND(const struct name *,   \
266             const struct type *)
267 #define ARB_PROTOTYPE_FIND(name, type, attr)                            \
268         attr struct type *name##_ARB_FIND(const struct name *,          \
269             const struct type *)
270 #define ARB_PROTOTYPE_NFIND(name, type, attr)                           \
271         attr struct type *name##_ARB_NFIND(struct name *, struct type *)
272 #define ARB_PROTOTYPE_CNFIND(name, type, attr)                          \
273         attr const struct type *name##_ARB_CNFIND(const struct name *,  \
274             const struct type *)
275 #define ARB_PROTOTYPE_CNEXT(name, type, attr)                           \
276         attr const struct type *name##_ARB_CNEXT(const struct name *head,\
277             const struct type *)
278 #define ARB_PROTOTYPE_NEXT(name, type, attr)                            \
279         attr struct type *name##_ARB_NEXT(const struct name *,          \
280             const struct type *)
281 #define ARB_PROTOTYPE_CPREV(name, type, attr)                           \
282         attr const struct type *name##_ARB_CPREV(const struct name *,   \
283             const struct type *)
284 #define ARB_PROTOTYPE_PREV(name, type, attr)                            \
285         attr struct type *name##_ARB_PREV(const struct name *,          \
286             const struct type *)
287 #define ARB_PROTOTYPE_CMINMAX(name, type, attr)                         \
288         attr const struct type *name##_ARB_CMINMAX(const struct name *, int)
289 #define ARB_PROTOTYPE_MINMAX(name, type, attr)                          \
290         attr struct type *name##_ARB_MINMAX(const struct name *, int)
291 #define ARB_PROTOTYPE_REINSERT(name, type, attr)                        \
292         attr struct type *name##_ARB_REINSERT(struct name *, struct type *)
293
294 #define ARB_GENERATE(name, type, field, cmp)                            \
295         ARB_GENERATE_INTERNAL(name, type, field, cmp,)
296 #define ARB_GENERATE_STATIC(name, type, field, cmp)                     \
297         ARB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
298 #define ARB_GENERATE_INTERNAL(name, type, field, cmp, attr)             \
299         ARB_GENERATE_INSERT_COLOR(name, type, field, attr)              \
300         ARB_GENERATE_REMOVE_COLOR(name, type, field, attr)              \
301         ARB_GENERATE_INSERT(name, type, field, cmp, attr)               \
302         ARB_GENERATE_REMOVE(name, type, field, attr)                    \
303         ARB_GENERATE_CFIND(name, type, field, cmp, attr)                \
304         ARB_GENERATE_FIND(name, type, field, cmp, attr)                 \
305         ARB_GENERATE_CNEXT(name, type, field, attr)                     \
306         ARB_GENERATE_NEXT(name, type, field, attr)                      \
307         ARB_GENERATE_CPREV(name, type, field, attr)                     \
308         ARB_GENERATE_PREV(name, type, field, attr)                      \
309         ARB_GENERATE_CMINMAX(name, type, field, attr)                   \
310         ARB_GENERATE_MINMAX(name, type, field, attr)                    \
311         ARB_GENERATE_REINSERT(name, type, field, cmp, attr)
312
313 #define ARB_GENERATE_INSERT_COLOR(name, type, field, attr)              \
314 attr void                                                               \
315 name##_ARB_INSERT_COLOR(struct name *head, struct type *elm)            \
316 {                                                                       \
317         struct type *parent, *gparent, *tmp;                            \
318         while ((parent = ARB_PARENT(head, elm, field)) != NULL &&       \
319             ARB_COLOR(parent, field) == ARB_RED) {                      \
320                 gparent = ARB_PARENT(head, parent, field);              \
321                 if (parent == ARB_LEFT(head, gparent, field)) {         \
322                         tmp = ARB_RIGHT(head, gparent, field);          \
323                         if (tmp && ARB_COLOR(tmp, field) == ARB_RED) {  \
324                                 ARB_COLOR(tmp, field) = ARB_BLACK;      \
325                                 ARB_SET_BLACKRED(parent, gparent, field); \
326                                 elm = gparent;                          \
327                                 continue;                               \
328                         }                                               \
329                         if (ARB_RIGHT(head, parent, field) == elm) {    \
330                                 ARB_ROTATE_LEFT(head, parent, tmp, field); \
331                                 tmp = parent;                           \
332                                 parent = elm;                           \
333                                 elm = tmp;                              \
334                         }                                               \
335                         ARB_SET_BLACKRED(parent, gparent, field);       \
336                         ARB_ROTATE_RIGHT(head, gparent, tmp, field);    \
337                 } else {                                                \
338                         tmp = ARB_LEFT(head, gparent, field);           \
339                         if (tmp && ARB_COLOR(tmp, field) == ARB_RED) {  \
340                                 ARB_COLOR(tmp, field) = ARB_BLACK;      \
341                                 ARB_SET_BLACKRED(parent, gparent, field); \
342                                 elm = gparent;                          \
343                                 continue;                               \
344                         }                                               \
345                         if (ARB_LEFT(head, parent, field) == elm) {     \
346                                 ARB_ROTATE_RIGHT(head, parent, tmp, field); \
347                                 tmp = parent;                           \
348                                 parent = elm;                           \
349                                 elm = tmp;                              \
350                         }                                               \
351                         ARB_SET_BLACKRED(parent, gparent, field);       \
352                         ARB_ROTATE_LEFT(head, gparent, tmp, field);     \
353                 }                                                       \
354         }                                                               \
355         ARB_COLOR(ARB_ROOT(head), field) = ARB_BLACK;                   \
356 }
357
358 #define ARB_GENERATE_REMOVE_COLOR(name, type, field, attr)              \
359 attr void                                                               \
360 name##_ARB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
361 {                                                                       \
362         struct type *tmp;                                               \
363         while ((elm == NULL || ARB_COLOR(elm, field) == ARB_BLACK) &&   \
364             elm != ARB_ROOT(head)) {                                    \
365                 if (ARB_LEFT(head, parent, field) == elm) {             \
366                         tmp = ARB_RIGHT(head, parent, field);           \
367                         if (ARB_COLOR(tmp, field) == ARB_RED) {         \
368                                 ARB_SET_BLACKRED(tmp, parent, field);   \
369                                 ARB_ROTATE_LEFT(head, parent, tmp, field); \
370                                 tmp = ARB_RIGHT(head, parent, field);   \
371                         }                                               \
372                         if ((ARB_LEFT(head, tmp, field) == NULL ||      \
373                             ARB_COLOR(ARB_LEFT(head, tmp, field), field) == ARB_BLACK) && \
374                             (ARB_RIGHT(head, tmp, field) == NULL ||     \
375                             ARB_COLOR(ARB_RIGHT(head, tmp, field), field) == ARB_BLACK)) { \
376                                 ARB_COLOR(tmp, field) = ARB_RED;                \
377                                 elm = parent;                           \
378                                 parent = ARB_PARENT(head, elm, field);  \
379                         } else {                                        \
380                                 if (ARB_RIGHT(head, tmp, field) == NULL || \
381                                     ARB_COLOR(ARB_RIGHT(head, tmp, field), field) == ARB_BLACK) { \
382                                         struct type *oleft;             \
383                                         if ((oleft = ARB_LEFT(head, tmp, field)) \
384                                             != NULL)                    \
385                                                 ARB_COLOR(oleft, field) = ARB_BLACK; \
386                                         ARB_COLOR(tmp, field) = ARB_RED;        \
387                                         ARB_ROTATE_RIGHT(head, tmp, oleft, field); \
388                                         tmp = ARB_RIGHT(head, parent, field); \
389                                 }                                       \
390                                 ARB_COLOR(tmp, field) = ARB_COLOR(parent, field); \
391                                 ARB_COLOR(parent, field) = ARB_BLACK;   \
392                                 if (ARB_RIGHT(head, tmp, field))        \
393                                         ARB_COLOR(ARB_RIGHT(head, tmp, field), field) = ARB_BLACK; \
394                                 ARB_ROTATE_LEFT(head, parent, tmp, field); \
395                                 elm = ARB_ROOT(head);                   \
396                                 break;                                  \
397                         }                                               \
398                 } else {                                                \
399                         tmp = ARB_LEFT(head, parent, field);            \
400                         if (ARB_COLOR(tmp, field) == ARB_RED) {         \
401                                 ARB_SET_BLACKRED(tmp, parent, field);   \
402                                 ARB_ROTATE_RIGHT(head, parent, tmp, field); \
403                                 tmp = ARB_LEFT(head, parent, field);    \
404                         }                                               \
405                         if ((ARB_LEFT(head, tmp, field) == NULL ||      \
406                             ARB_COLOR(ARB_LEFT(head, tmp, field), field) == ARB_BLACK) && \
407                             (ARB_RIGHT(head, tmp, field) == NULL ||     \
408                             ARB_COLOR(ARB_RIGHT(head, tmp, field), field) == ARB_BLACK)) { \
409                                 ARB_COLOR(tmp, field) = ARB_RED;                \
410                                 elm = parent;                           \
411                                 parent = ARB_PARENT(head, elm, field);  \
412                         } else {                                        \
413                                 if (ARB_LEFT(head, tmp, field) == NULL || \
414                                     ARB_COLOR(ARB_LEFT(head, tmp, field), field) == ARB_BLACK) { \
415                                         struct type *oright;            \
416                                         if ((oright = ARB_RIGHT(head, tmp, field)) \
417                                             != NULL)                    \
418                                                 ARB_COLOR(oright, field) = ARB_BLACK; \
419                                         ARB_COLOR(tmp, field) = ARB_RED;        \
420                                         ARB_ROTATE_LEFT(head, tmp, oright, field); \
421                                         tmp = ARB_LEFT(head, parent, field); \
422                                 }                                       \
423                                 ARB_COLOR(tmp, field) = ARB_COLOR(parent, field); \
424                                 ARB_COLOR(parent, field) = ARB_BLACK;   \
425                                 if (ARB_LEFT(head, tmp, field))         \
426                                         ARB_COLOR(ARB_LEFT(head, tmp, field), field) = ARB_BLACK; \
427                                 ARB_ROTATE_RIGHT(head, parent, tmp, field); \
428                                 elm = ARB_ROOT(head);                   \
429                                 break;                                  \
430                         }                                               \
431                 }                                                       \
432         }                                                               \
433         if (elm)                                                        \
434                 ARB_COLOR(elm, field) = ARB_BLACK;                      \
435 }
436
437 #define ARB_GENERATE_REMOVE(name, type, field, attr)                    \
438 attr struct type *                                                      \
439 name##_ARB_REMOVE(struct name *head, struct type *elm)                  \
440 {                                                                       \
441         struct type *child, *parent, *old = elm;                        \
442         int color;                                                      \
443         if (ARB_LEFT(head, elm, field) == NULL)                         \
444                 child = ARB_RIGHT(head, elm, field);                    \
445         else if (ARB_RIGHT(head, elm, field) == NULL)                   \
446                 child = ARB_LEFT(head, elm, field);                     \
447         else {                                                          \
448                 struct type *left;                                      \
449                 elm = ARB_RIGHT(head, elm, field);                      \
450                 while ((left = ARB_LEFT(head, elm, field)) != NULL)     \
451                         elm = left;                                     \
452                 child = ARB_RIGHT(head, elm, field);                    \
453                 parent = ARB_PARENT(head, elm, field);                  \
454                 color = ARB_COLOR(elm, field);                          \
455                 if (child)                                              \
456                         ARB_PARENTIDX(child, field) =                   \
457                             ARB_SELFIDX(head, parent);                  \
458                 if (parent) {                                           \
459                         if (ARB_LEFT(head, parent, field) == elm)       \
460                                 ARB_LEFTIDX(parent, field) =            \
461                                     ARB_SELFIDX(head, child);           \
462                         else                                            \
463                                 ARB_RIGHTIDX(parent, field) =           \
464                                     ARB_SELFIDX(head, child);           \
465                         ARB_AUGMENT(parent);                            \
466                 } else                                                  \
467                         ARB_ROOTIDX(head) = ARB_SELFIDX(head, child);   \
468                 if (ARB_PARENT(head, elm, field) == old)                \
469                         parent = elm;                                   \
470                 (elm)->field = (old)->field;                            \
471                 if (ARB_PARENT(head, old, field)) {                     \
472                         if (ARB_LEFT(head, ARB_PARENT(head, old, field), \
473                             field) == old)                              \
474                                 ARB_LEFTIDX(ARB_PARENT(head, old, field), \
475                                     field) = ARB_SELFIDX(head, elm);    \
476                         else                                            \
477                                 ARB_RIGHTIDX(ARB_PARENT(head, old, field),\
478                                     field) = ARB_SELFIDX(head, elm);    \
479                         ARB_AUGMENT(ARB_PARENT(head, old, field));      \
480                 } else                                                  \
481                         ARB_ROOTIDX(head) = ARB_SELFIDX(head, elm);     \
482                 ARB_PARENTIDX(ARB_LEFT(head, old, field), field) =      \
483                     ARB_SELFIDX(head, elm);                             \
484                 if (ARB_RIGHT(head, old, field))                        \
485                         ARB_PARENTIDX(ARB_RIGHT(head, old, field),      \
486                             field) = ARB_SELFIDX(head, elm);            \
487                 if (parent) {                                           \
488                         left = parent;                                  \
489                         do {                                            \
490                                 ARB_AUGMENT(left);                      \
491                         } while ((left = ARB_PARENT(head, left, field)) \
492                             != NULL);                                   \
493                 }                                                       \
494                 goto color;                                             \
495         }                                                               \
496         parent = ARB_PARENT(head, elm, field);                          \
497         color = ARB_COLOR(elm, field);                                  \
498         if (child)                                                      \
499                 ARB_PARENTIDX(child, field) = ARB_SELFIDX(head, parent);\
500         if (parent) {                                                   \
501                 if (ARB_LEFT(head, parent, field) == elm)               \
502                         ARB_LEFTIDX(parent, field) =                    \
503                             ARB_SELFIDX(head, child);                   \
504                 else                                                    \
505                         ARB_RIGHTIDX(parent, field) =                   \
506                             ARB_SELFIDX(head, child);                   \
507                 ARB_AUGMENT(parent);                                    \
508         } else                                                          \
509                 ARB_ROOTIDX(head) = ARB_SELFIDX(head, child);           \
510 color:                                                                  \
511         if (color == ARB_BLACK)                                         \
512                 name##_ARB_REMOVE_COLOR(head, parent, child);           \
513         ARB_CURNODES(head) -= 1;                                        \
514         if (ARB_MINIDX(head) == ARB_SELFIDX(head, old))                 \
515                 ARB_MINIDX(head) = ARB_PARENTIDX(old, field);           \
516         if (ARB_MAXIDX(head) == ARB_SELFIDX(head, old))                 \
517                 ARB_MAXIDX(head) = ARB_PARENTIDX(old, field);           \
518         ARB_RETURNFREE(head, old, field);                               \
519         return (old);                                                   \
520 }                                                                       \
521
522 #define ARB_GENERATE_INSERT(name, type, field, cmp, attr)               \
523 /* Inserts a node into the RB tree */                                   \
524 attr struct type *                                                      \
525 name##_ARB_INSERT(struct name *head, struct type *elm)                  \
526 {                                                                       \
527         struct type *tmp;                                               \
528         struct type *parent = NULL;                                     \
529         int comp = 0;                                                   \
530         tmp = ARB_ROOT(head);                                           \
531         while (tmp) {                                                   \
532                 parent = tmp;                                           \
533                 comp = (cmp)(elm, parent);                              \
534                 if (comp < 0)                                           \
535                         tmp = ARB_LEFT(head, tmp, field);               \
536                 else if (comp > 0)                                      \
537                         tmp = ARB_RIGHT(head, tmp, field);              \
538                 else                                                    \
539                         return (tmp);                                   \
540         }                                                               \
541         ARB_SET(head, elm, parent, field);                              \
542         if (parent != NULL) {                                           \
543                 if (comp < 0)                                           \
544                         ARB_LEFTIDX(parent, field) =                    \
545                             ARB_SELFIDX(head, elm);                     \
546                 else                                                    \
547                         ARB_RIGHTIDX(parent, field) =                   \
548                             ARB_SELFIDX(head, elm);                     \
549                 ARB_AUGMENT(parent);                                    \
550         } else                                                          \
551                 ARB_ROOTIDX(head) = ARB_SELFIDX(head, elm);             \
552         name##_ARB_INSERT_COLOR(head, elm);                             \
553         ARB_CURNODES(head) += 1;                                        \
554         if (ARB_MINIDX(head) == ARB_NULLIDX ||                          \
555             (ARB_PARENTIDX(elm, field) == ARB_MINIDX(head) &&           \
556             ARB_LEFTIDX(parent, field) == ARB_SELFIDX(head, elm)))      \
557                 ARB_MINIDX(head) = ARB_SELFIDX(head, elm);              \
558         if (ARB_MAXIDX(head) == ARB_NULLIDX ||                          \
559             (ARB_PARENTIDX(elm, field) == ARB_MAXIDX(head) &&           \
560             ARB_RIGHTIDX(parent, field) == ARB_SELFIDX(head, elm)))     \
561                 ARB_MAXIDX(head) = ARB_SELFIDX(head, elm);      \
562         return (NULL);                                                  \
563 }
564
565 #define ARB_GENERATE_CFIND(name, type, field, cmp, attr)                \
566 /* Finds the node with the same key as elm */                           \
567 attr const struct type *                                                \
568 name##_ARB_CFIND(const struct name *head, const struct type *elm)       \
569 {                                                                       \
570         const struct type *tmp = ARB_ROOT(head);                        \
571         int comp;                                                       \
572         while (tmp) {                                                   \
573                 comp = cmp(elm, tmp);                                   \
574                 if (comp < 0)                                           \
575                         tmp = ARB_LEFT(head, tmp, field);               \
576                 else if (comp > 0)                                      \
577                         tmp = ARB_RIGHT(head, tmp, field);              \
578                 else                                                    \
579                         return (tmp);                                   \
580         }                                                               \
581         return (NULL);                                                  \
582 }
583
584 #define ARB_GENERATE_FIND(name, type, field, cmp, attr)                 \
585 attr struct type *                                                      \
586 name##_ARB_FIND(const struct name *head, const struct type *elm)        \
587 { return (__DECONST(struct type *, name##_ARB_CFIND(head, elm))); }
588
589 #define ARB_GENERATE_CNFIND(name, type, field, cmp, attr)               \
590 /* Finds the first node greater than or equal to the search key */      \
591 attr const struct type *                                                \
592 name##_ARB_CNFIND(const struct name *head, const struct type *elm)      \
593 {                                                                       \
594         const struct type *tmp = ARB_ROOT(head);                        \
595         const struct type *res = NULL;                                  \
596         int comp;                                                       \
597         while (tmp) {                                                   \
598                 comp = cmp(elm, tmp);                                   \
599                 if (comp < 0) {                                         \
600                         res = tmp;                                      \
601                         tmp = ARB_LEFT(head, tmp, field);               \
602                 }                                                       \
603                 else if (comp > 0)                                      \
604                         tmp = ARB_RIGHT(head, tmp, field);              \
605                 else                                                    \
606                         return (tmp);                                   \
607         }                                                               \
608         return (res);                                                   \
609 }
610
611 #define ARB_GENERATE_NFIND(name, type, field, cmp, attr)                \
612 attr struct type *                                                      \
613 name##_ARB_NFIND(const struct name *head, const struct type *elm)       \
614 { return (__DECONST(struct type *, name##_ARB_CNFIND(head, elm))); }
615
616 #define ARB_GENERATE_CNEXT(name, type, field, attr)                     \
617 /* ARGSUSED */                                                          \
618 attr const struct type *                                                \
619 name##_ARB_CNEXT(const struct name *head, const struct type *elm)       \
620 {                                                                       \
621         if (ARB_RIGHT(head, elm, field)) {                              \
622                 elm = ARB_RIGHT(head, elm, field);                      \
623                 while (ARB_LEFT(head, elm, field))                      \
624                         elm = ARB_LEFT(head, elm, field);               \
625         } else {                                                        \
626                 if (ARB_PARENT(head, elm, field) &&                     \
627                     (elm == ARB_LEFT(head, ARB_PARENT(head, elm, field),\
628                     field)))                                            \
629                         elm = ARB_PARENT(head, elm, field);             \
630                 else {                                                  \
631                         while (ARB_PARENT(head, elm, field) &&          \
632                             (elm == ARB_RIGHT(head, ARB_PARENT(head,    \
633                             elm, field), field)))                       \
634                                 elm = ARB_PARENT(head, elm, field);     \
635                         elm = ARB_PARENT(head, elm, field);             \
636                 }                                                       \
637         }                                                               \
638         return (elm);                                                   \
639 }
640
641 #define ARB_GENERATE_NEXT(name, type, field, attr)                      \
642 attr struct type *                                                      \
643 name##_ARB_NEXT(const struct name *head, const struct type *elm)        \
644 { return (__DECONST(struct type *, name##_ARB_CNEXT(head, elm))); }
645
646 #define ARB_GENERATE_CPREV(name, type, field, attr)                     \
647 /* ARGSUSED */                                                          \
648 attr const struct type *                                                \
649 name##_ARB_CPREV(const struct name *head, const struct type *elm)       \
650 {                                                                       \
651         if (ARB_LEFT(head, elm, field)) {                               \
652                 elm = ARB_LEFT(head, elm, field);                       \
653                 while (ARB_RIGHT(head, elm, field))                     \
654                         elm = ARB_RIGHT(head, elm, field);              \
655         } else {                                                        \
656                 if (ARB_PARENT(head, elm, field) &&                     \
657                     (elm == ARB_RIGHT(head, ARB_PARENT(head, elm,       \
658                     field), field)))                                    \
659                         elm = ARB_PARENT(head, elm, field);             \
660                 else {                                                  \
661                         while (ARB_PARENT(head, elm, field) &&          \
662                             (elm == ARB_LEFT(head, ARB_PARENT(head, elm,\
663                             field), field)))                            \
664                                 elm = ARB_PARENT(head, elm, field);     \
665                         elm = ARB_PARENT(head, elm, field);             \
666                 }                                                       \
667         }                                                               \
668         return (elm);                                                   \
669 }
670
671 #define ARB_GENERATE_PREV(name, type, field, attr)                      \
672 attr struct type *                                                      \
673 name##_ARB_PREV(const struct name *head, const struct type *elm)        \
674 { return (__DECONST(struct type *, name##_ARB_CPREV(head, elm))); }
675
676 #define ARB_GENERATE_CMINMAX(name, type, field, attr)                   \
677 attr const struct type *                                                \
678 name##_ARB_CMINMAX(const struct name *head, int val)                    \
679 {                                                                       \
680         const struct type *tmp = ARB_EMPTY(head) ? NULL : ARB_ROOT(head);\
681         const struct type *parent = NULL;                               \
682         while (tmp) {                                                   \
683                 parent = tmp;                                           \
684                 if (val < 0)                                            \
685                         tmp = ARB_LEFT(head, tmp, field);               \
686                 else                                                    \
687                         tmp = ARB_RIGHT(head, tmp, field);              \
688         }                                                               \
689         return (__DECONST(struct type *, parent));                      \
690 }
691
692 #define ARB_GENERATE_MINMAX(name, type, field, attr)                    \
693 attr struct type *                                                      \
694 name##_ARB_MINMAX(const struct name *head, int val)                     \
695 { return (__DECONST(struct type *, name##_ARB_CMINMAX(head, val))); }
696
697 #define ARB_GENERATE_REINSERT(name, type, field, cmp, attr)             \
698 attr struct type *                                                      \
699 name##_ARB_REINSERT(struct name *head, struct type *elm)                \
700 {                                                                       \
701         struct type *cmpelm;                                            \
702         if (((cmpelm = ARB_PREV(name, head, elm)) != NULL &&            \
703             (cmp)(cmpelm, elm) >= 0) ||                                 \
704             ((cmpelm = ARB_NEXT(name, head, elm)) != NULL &&            \
705             (cmp)(elm, cmpelm) >= 0)) {                                 \
706                 /* XXXLAS: Remove/insert is heavy handed. */            \
707                 ARB_REMOVE(name, head, elm);                            \
708                 /* Remove puts elm on the free list. */                 \
709                 elm = ARB_GETFREE(head, field);                         \
710                 return (ARB_INSERT(name, head, elm));                   \
711         }                                                               \
712         return (NULL);                                                  \
713 }                                                                       \
714
715 #define ARB_INSERT(name, x, y)  name##_ARB_INSERT(x, y)
716 #define ARB_REMOVE(name, x, y)  name##_ARB_REMOVE(x, y)
717 #define ARB_CFIND(name, x, y)   name##_ARB_CFIND(x, y)
718 #define ARB_FIND(name, x, y)    name##_ARB_FIND(x, y)
719 #define ARB_CNFIND(name, x, y)  name##_ARB_CNFIND(x, y)
720 #define ARB_NFIND(name, x, y)   name##_ARB_NFIND(x, y)
721 #define ARB_CNEXT(name, x, y)   name##_ARB_CNEXT(x, y)
722 #define ARB_NEXT(name, x, y)    name##_ARB_NEXT(x, y)
723 #define ARB_CPREV(name, x, y)   name##_ARB_CPREV(x, y)
724 #define ARB_PREV(name, x, y)    name##_ARB_PREV(x, y)
725 #define ARB_CMIN(name, x)       (ARB_MINIDX(x) == ARB_NULLIDX ? \
726         name##_ARB_CMINMAX(x, ARB_NEGINF) : ARB_CNODE(x, ARB_MINIDX(x)))
727 #define ARB_MIN(name, x)        (ARB_MINIDX(x) == ARB_NULLIDX ? \
728         name##_ARB_MINMAX(x, ARB_NEGINF) : ARB_NODE(x, ARB_MINIDX(x)))
729 #define ARB_CMAX(name, x)       (ARB_MAXIDX(x) == ARB_NULLIDX ? \
730         name##_ARB_CMINMAX(x, ARB_INF) : ARB_CNODE(x, ARB_MAXIDX(x)))
731 #define ARB_MAX(name, x)        (ARB_MAXIDX(x) == ARB_NULLIDX ? \
732         name##_ARB_MINMAX(x, ARB_INF) : ARB_NODE(x, ARB_MAXIDX(x)))
733 #define ARB_REINSERT(name, x, y) name##_ARB_REINSERT(x, y)
734
735 #define ARB_FOREACH(x, name, head)                                      \
736         for ((x) = ARB_MIN(name, head);                                 \
737              (x) != NULL;                                               \
738              (x) = name##_ARB_NEXT(head, x))
739
740 #define ARB_FOREACH_FROM(x, name, y)                                    \
741         for ((x) = (y);                                                 \
742             ((x) != NULL) && ((y) = name##_ARB_NEXT(x), (x) != NULL);   \
743              (x) = (y))
744
745 #define ARB_FOREACH_SAFE(x, name, head, y)                              \
746         for ((x) = ARB_MIN(name, head);                                 \
747             ((x) != NULL) && ((y) = name##_ARB_NEXT(x), (x) != NULL);   \
748              (x) = (y))
749
750 #define ARB_FOREACH_REVERSE(x, name, head)                              \
751         for ((x) = ARB_MAX(name, head);                                 \
752              (x) != NULL;                                               \
753              (x) = name##_ARB_PREV(x))
754
755 #define ARB_FOREACH_REVERSE_FROM(x, name, y)                            \
756         for ((x) = (y);                                                 \
757             ((x) != NULL) && ((y) = name##_ARB_PREV(x), (x) != NULL);   \
758              (x) = (y))
759
760 #define ARB_FOREACH_REVERSE_SAFE(x, name, head, y)                      \
761         for ((x) = ARB_MAX(name, head);                                 \
762             ((x) != NULL) && ((y) = name##_ARB_PREV(x), (x) != NULL);   \
763              (x) = (y))
764
765 #define ARB_ARRFOREACH(x, field, head)                                  \
766         for ((x) = ARB_NODES(head);                                     \
767             ARB_SELFIDX(head, x) < ARB_MAXNODES(head);                  \
768             (x)++)
769
770 #define ARB_ARRFOREACH_REVWCOND(x, field, head, extracond)              \
771         for ((x) = ARB_NODES(head) + (ARB_MAXNODES(head) - 1);          \
772             (x) >= ARB_NODES(head) && (extracond);                      \
773             (x)--)
774
775 #define ARB_ARRFOREACH_REVERSE(x, field, head) \
776         ARB_ARRFOREACH_REVWCOND(x, field, head, 1)
777
778 #define ARB_RESET_TREE(head, name, maxn)                                \
779         *(head) = ARB_INITIALIZER(name, maxn)
780
781 #endif  /* _SYS_ARB_H_ */