The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sys/arb.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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_ */

Cache object: d236bde6907397d9d100f2c9cc636a66


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.